// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cache

// This file defines routines to convert diagnostics from go list, go
// get, go/packages, parsing, type checking, and analysis into
// golang.Diagnostic form, and suggesting quick fixes.

import (
	"context"
	"fmt"
	"go/parser"
	"go/scanner"
	"go/token"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/gopls/internal/cache/metadata"
	"golang.org/x/tools/gopls/internal/cache/parsego"
	"golang.org/x/tools/gopls/internal/file"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/protocol/command"
	"golang.org/x/tools/gopls/internal/settings"
	"golang.org/x/tools/gopls/internal/util/bug"
	"golang.org/x/tools/internal/typesinternal"
)

// goPackagesErrorDiagnostics translates the given go/packages Error into a
// diagnostic, using the provided metadata and filesource.
//
// The slice of diagnostics may be empty.
func goPackagesErrorDiagnostics(ctx context.Context, e packages.Error, mp *metadata.Package, fs file.Source) ([]*Diagnostic, error) {
	if diag, err := parseGoListImportCycleError(ctx, e, mp, fs); err != nil {
		return nil, err
	} else if diag != nil {
		return []*Diagnostic{diag}, nil
	}

	// Parse error location and attempt to convert to protocol form.
	loc, err := func() (protocol.Location, error) {
		filename, line, col8 := parseGoListError(e, mp.LoadDir)
		uri := protocol.URIFromPath(filename)

		fh, err := fs.ReadFile(ctx, uri)
		if err != nil {
			return protocol.Location{}, err
		}
		content, err := fh.Content()
		if err != nil {
			return protocol.Location{}, err
		}
		mapper := protocol.NewMapper(uri, content)
		posn, err := mapper.LineCol8Position(line, col8)
		if err != nil {
			return protocol.Location{}, err
		}
		return protocol.Location{
			URI: uri,
			Range: protocol.Range{
				Start: posn,
				End:   posn,
			},
		}, nil
	}()

	// TODO(rfindley): in some cases the go command outputs invalid spans, for
	// example (from TestGoListErrors):
	//
	//   package a
	//   import
	//
	// In this case, the go command will complain about a.go:2:8, which is after
	// the trailing newline but still considered to be on the second line, most
	// likely because *token.File lacks information about newline termination.
	//
	// We could do better here by handling that case.
	if err != nil {
		// Unable to parse a valid position.
		// Apply the error to all files to be safe.
		var diags []*Diagnostic
		for _, uri := range mp.CompiledGoFiles {
			diags = append(diags, &Diagnostic{
				URI:      uri,
				Severity: protocol.SeverityError,
				Source:   ListError,
				Message:  e.Msg,
			})
		}
		return diags, nil
	}
	return []*Diagnostic{{
		URI:      loc.URI,
		Range:    loc.Range,
		Severity: protocol.SeverityError,
		Source:   ListError,
		Message:  e.Msg,
	}}, nil
}

func parseErrorDiagnostics(pkg *syntaxPackage, errList scanner.ErrorList) ([]*Diagnostic, error) {
	// The first parser error is likely the root cause of the problem.
	if errList.Len() <= 0 {
		return nil, fmt.Errorf("no errors in %v", errList)
	}
	e := errList[0]
	pgf, err := pkg.File(protocol.URIFromPath(e.Pos.Filename))
	if err != nil {
		return nil, err
	}
	rng, err := pgf.Mapper.OffsetRange(e.Pos.Offset, e.Pos.Offset)
	if err != nil {
		return nil, err
	}
	return []*Diagnostic{{
		URI:      pgf.URI,
		Range:    rng,
		Severity: protocol.SeverityError,
		Source:   ParseError,
		Message:  e.Msg,
	}}, nil
}

var importErrorRe = regexp.MustCompile(`could not import ([^\s]+)`)
var unsupportedFeatureRe = regexp.MustCompile(`.*require.* go(\d+\.\d+) or later`)

func goGetQuickFixes(haveModule bool, uri protocol.DocumentURI, pkg string) []SuggestedFix {
	// Go get only supports module mode for now.
	if !haveModule {
		return nil
	}
	title := fmt.Sprintf("go get package %v", pkg)
	cmd := command.NewGoGetPackageCommand(title, command.GoGetPackageArgs{
		URI:        uri,
		AddRequire: true,
		Pkg:        pkg,
	})
	return []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)}
}

func editGoDirectiveQuickFix(haveModule bool, uri protocol.DocumentURI, version string) []SuggestedFix {
	// Go mod edit only supports module mode.
	if !haveModule {
		return nil
	}
	title := fmt.Sprintf("go mod edit -go=%s", version)
	cmd := command.NewEditGoDirectiveCommand(title, command.EditGoDirectiveArgs{
		URI:     uri,
		Version: version,
	})
	return []SuggestedFix{SuggestedFixFromCommand(cmd, protocol.QuickFix)}
}

// encodeDiagnostics gob-encodes the given diagnostics.
func encodeDiagnostics(srcDiags []*Diagnostic) []byte {
	var gobDiags []gobDiagnostic
	for _, srcDiag := range srcDiags {
		var gobFixes []gobSuggestedFix
		for _, srcFix := range srcDiag.SuggestedFixes {
			gobFix := gobSuggestedFix{
				Message:    srcFix.Title,
				ActionKind: srcFix.ActionKind,
			}
			for uri, srcEdits := range srcFix.Edits {
				for _, srcEdit := range srcEdits {
					gobFix.TextEdits = append(gobFix.TextEdits, gobTextEdit{
						Location: protocol.Location{
							URI:   uri,
							Range: srcEdit.Range,
						},
						NewText: []byte(srcEdit.NewText),
					})
				}
			}
			if srcCmd := srcFix.Command; srcCmd != nil {
				gobFix.Command = &gobCommand{
					Title:     srcCmd.Title,
					Command:   srcCmd.Command,
					Arguments: srcCmd.Arguments,
				}
			}
			gobFixes = append(gobFixes, gobFix)
		}
		var gobRelated []gobRelatedInformation
		for _, srcRel := range srcDiag.Related {
			gobRel := gobRelatedInformation(srcRel)
			gobRelated = append(gobRelated, gobRel)
		}
		gobDiag := gobDiagnostic{
			Location: protocol.Location{
				URI:   srcDiag.URI,
				Range: srcDiag.Range,
			},
			Severity:       srcDiag.Severity,
			Code:           srcDiag.Code,
			CodeHref:       srcDiag.CodeHref,
			Source:         string(srcDiag.Source),
			Message:        srcDiag.Message,
			SuggestedFixes: gobFixes,
			Related:        gobRelated,
			Tags:           srcDiag.Tags,
		}
		gobDiags = append(gobDiags, gobDiag)
	}
	return diagnosticsCodec.Encode(gobDiags)
}

// decodeDiagnostics decodes the given gob-encoded diagnostics.
func decodeDiagnostics(data []byte) []*Diagnostic {
	var gobDiags []gobDiagnostic
	diagnosticsCodec.Decode(data, &gobDiags)
	var srcDiags []*Diagnostic
	for _, gobDiag := range gobDiags {
		var srcFixes []SuggestedFix
		for _, gobFix := range gobDiag.SuggestedFixes {
			srcFix := SuggestedFix{
				Title:      gobFix.Message,
				ActionKind: gobFix.ActionKind,
			}
			for _, gobEdit := range gobFix.TextEdits {
				if srcFix.Edits == nil {
					srcFix.Edits = make(map[protocol.DocumentURI][]protocol.TextEdit)
				}
				srcEdit := protocol.TextEdit{
					Range:   gobEdit.Location.Range,
					NewText: string(gobEdit.NewText),
				}
				uri := gobEdit.Location.URI
				srcFix.Edits[uri] = append(srcFix.Edits[uri], srcEdit)
			}
			if gobCmd := gobFix.Command; gobCmd != nil {
				srcFix.Command = &protocol.Command{
					Title:     gobCmd.Title,
					Command:   gobCmd.Command,
					Arguments: gobCmd.Arguments,
				}
			}
			srcFixes = append(srcFixes, srcFix)
		}
		var srcRelated []protocol.DiagnosticRelatedInformation
		for _, gobRel := range gobDiag.Related {
			srcRel := protocol.DiagnosticRelatedInformation(gobRel)
			srcRelated = append(srcRelated, srcRel)
		}
		srcDiag := &Diagnostic{
			URI:            gobDiag.Location.URI,
			Range:          gobDiag.Location.Range,
			Severity:       gobDiag.Severity,
			Code:           gobDiag.Code,
			CodeHref:       gobDiag.CodeHref,
			Source:         DiagnosticSource(gobDiag.Source),
			Message:        gobDiag.Message,
			Tags:           gobDiag.Tags,
			Related:        srcRelated,
			SuggestedFixes: srcFixes,
		}
		srcDiags = append(srcDiags, srcDiag)
	}
	return srcDiags
}

// toSourceDiagnostic converts a gobDiagnostic to "source" form.
func toSourceDiagnostic(srcAnalyzer *settings.Analyzer, gobDiag *gobDiagnostic) *Diagnostic {
	var related []protocol.DiagnosticRelatedInformation
	for _, gobRelated := range gobDiag.Related {
		related = append(related, protocol.DiagnosticRelatedInformation(gobRelated))
	}

	diag := &Diagnostic{
		URI:      gobDiag.Location.URI,
		Range:    gobDiag.Location.Range,
		Severity: srcAnalyzer.Severity(),
		Code:     gobDiag.Code,
		CodeHref: gobDiag.CodeHref,
		Source:   DiagnosticSource(gobDiag.Source),
		Message:  gobDiag.Message,
		Related:  related,
		Tags:     srcAnalyzer.Tags(),
	}

	// We cross the set of fixes (whether edit- or command-based)
	// with the set of kinds, as a single fix may represent more
	// than one kind of action (e.g. refactor, quickfix, fixall),
	// each corresponding to a distinct client UI element
	// or operation.
	kinds := srcAnalyzer.ActionKinds()
	if len(kinds) == 0 {
		kinds = []protocol.CodeActionKind{protocol.QuickFix}
	}

	var fixes []SuggestedFix
	for _, fix := range gobDiag.SuggestedFixes {
		if len(fix.TextEdits) > 0 {
			// Accumulate edit-based fixes supplied by the diagnostic itself.
			edits := make(map[protocol.DocumentURI][]protocol.TextEdit)
			for _, e := range fix.TextEdits {
				uri := e.Location.URI
				edits[uri] = append(edits[uri], protocol.TextEdit{
					Range:   e.Location.Range,
					NewText: string(e.NewText),
				})
			}
			for _, kind := range kinds {
				fixes = append(fixes, SuggestedFix{
					Title:      fix.Message,
					Edits:      edits,
					ActionKind: kind,
				})
			}

		} else {
			// Accumulate command-based fixes, whose edits
			// are not provided by the analyzer but are computed on demand
			// by logic "adjacent to" the analyzer.
			//
			// The analysis.Diagnostic.Category is used as the fix name.
			cmd := command.NewApplyFixCommand(fix.Message, command.ApplyFixArgs{
				Fix:      diag.Code,
				Location: gobDiag.Location,
			})
			for _, kind := range kinds {
				fixes = append(fixes, SuggestedFixFromCommand(cmd, kind))
			}

			// Ensure that the analyzer specifies a category for all its no-edit fixes.
			// This is asserted by analysistest.RunWithSuggestedFixes, but there
			// may be gaps in test coverage.
			if diag.Code == "" || diag.Code == "default" {
				bug.Reportf("missing Diagnostic.Code: %#v", *diag)
			}
		}
	}
	diag.SuggestedFixes = fixes

	// If the fixes only delete code, assume that the diagnostic is reporting dead code.
	if onlyDeletions(diag.SuggestedFixes) {
		diag.Tags = append(diag.Tags, protocol.Unnecessary)
	}
	return diag
}

// onlyDeletions returns true if fixes is non-empty and all of the suggested
// fixes are deletions.
func onlyDeletions(fixes []SuggestedFix) bool {
	for _, fix := range fixes {
		if fix.Command != nil {
			return false
		}
		for _, edits := range fix.Edits {
			for _, edit := range edits {
				if edit.NewText != "" {
					return false
				}
				if protocol.ComparePosition(edit.Range.Start, edit.Range.End) == 0 {
					return false
				}
			}
		}
	}
	return len(fixes) > 0
}

func typesCodeHref(linkTarget string, code typesinternal.ErrorCode) string {
	return BuildLink(linkTarget, "golang.org/x/tools/internal/typesinternal", code.String())
}

// BuildLink constructs a URL with the given target, path, and anchor.
func BuildLink(target, path, anchor string) protocol.URI {
	link := fmt.Sprintf("https://%s/%s", target, path)
	if anchor == "" {
		return link
	}
	return link + "#" + anchor
}

func parseGoListError(e packages.Error, dir string) (filename string, line, col8 int) {
	input := e.Pos
	if input == "" {
		// No position. Attempt to parse one out of a
		// go list error of the form "file:line:col:
		// message" by stripping off the message.
		input = strings.TrimSpace(e.Msg)
		if i := strings.Index(input, ": "); i >= 0 {
			input = input[:i]
		}
	}

	filename, line, col8 = splitFileLineCol(input)
	if !filepath.IsAbs(filename) {
		filename = filepath.Join(dir, filename)
	}
	return filename, line, col8
}

// splitFileLineCol splits s into "filename:line:col",
// where line and col consist of decimal digits.
func splitFileLineCol(s string) (file string, line, col8 int) {
	// Beware that the filename may contain colon on Windows.

	// stripColonDigits removes a ":%d" suffix, if any.
	stripColonDigits := func(s string) (rest string, num int) {
		if i := strings.LastIndex(s, ":"); i >= 0 {
			if v, err := strconv.ParseInt(s[i+1:], 10, 32); err == nil {
				return s[:i], int(v)
			}
		}
		return s, -1
	}

	// strip col ":%d"
	s, n1 := stripColonDigits(s)
	if n1 < 0 {
		return s, 1, 1 // "filename"
	}

	// strip line ":%d"
	s, n2 := stripColonDigits(s)
	if n2 < 0 {
		return s, n1, 1 // "filename:line"
	}

	return s, n2, n1 // "filename:line:col"
}

// parseGoListImportCycleError attempts to parse the given go/packages error as
// an import cycle, returning a diagnostic if successful.
//
// If the error is not detected as an import cycle error, it returns nil, nil.
func parseGoListImportCycleError(ctx context.Context, e packages.Error, mp *metadata.Package, fs file.Source) (*Diagnostic, error) {
	re := regexp.MustCompile(`(.*): import stack: \[(.+)\]`)
	matches := re.FindStringSubmatch(strings.TrimSpace(e.Msg))
	if len(matches) < 3 {
		return nil, nil
	}
	msg := matches[1]
	importList := strings.Split(matches[2], " ")
	// Since the error is relative to the current package. The import that is causing
	// the import cycle error is the second one in the list.
	if len(importList) < 2 {
		return nil, nil
	}
	// Imports have quotation marks around them.
	circImp := strconv.Quote(importList[1])
	for _, uri := range mp.CompiledGoFiles {
		pgf, err := parseGoURI(ctx, fs, uri, parsego.Header)
		if err != nil {
			return nil, err
		}
		// Search file imports for the import that is causing the import cycle.
		for _, imp := range pgf.File.Imports {
			if imp.Path.Value == circImp {
				rng, err := pgf.NodeRange(imp)
				if err != nil {
					return nil, nil
				}

				return &Diagnostic{
					URI:      pgf.URI,
					Range:    rng,
					Severity: protocol.SeverityError,
					Source:   ListError,
					Message:  msg,
				}, nil
			}
		}
	}
	return nil, nil
}

// parseGoURI is a helper to parse the Go file at the given URI from the file
// source fs. The resulting syntax and token.File belong to an ephemeral,
// encapsulated FileSet, so this file stands only on its own: it's not suitable
// to use in a list of file of a package, for example.
//
// It returns an error if the file could not be read.
//
// TODO(rfindley): eliminate this helper.
func parseGoURI(ctx context.Context, fs file.Source, uri protocol.DocumentURI, mode parser.Mode) (*parsego.File, error) {
	fh, err := fs.ReadFile(ctx, uri)
	if err != nil {
		return nil, err
	}
	return parseGoImpl(ctx, token.NewFileSet(), fh, mode, false)
}

// parseModURI is a helper to parse the Mod file at the given URI from the file
// source fs.
//
// It returns an error if the file could not be read.
func parseModURI(ctx context.Context, fs file.Source, uri protocol.DocumentURI) (*ParsedModule, error) {
	fh, err := fs.ReadFile(ctx, uri)
	if err != nil {
		return nil, err
	}
	return parseModImpl(ctx, fh)
}
