1// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package cache
6
7import (
8	"bytes"
9	"context"
10	"fmt"
11	"go/ast"
12	"go/types"
13	"path"
14	"path/filepath"
15	"sort"
16	"strings"
17	"sync"
18
19	"golang.org/x/mod/module"
20	"golang.org/x/tools/go/ast/astutil"
21	"golang.org/x/tools/go/packages"
22	"golang.org/x/tools/internal/event"
23	"golang.org/x/tools/internal/lsp/debug/tag"
24	"golang.org/x/tools/internal/lsp/protocol"
25	"golang.org/x/tools/internal/lsp/source"
26	"golang.org/x/tools/internal/memoize"
27	"golang.org/x/tools/internal/packagesinternal"
28	"golang.org/x/tools/internal/span"
29	"golang.org/x/tools/internal/typesinternal"
30	errors "golang.org/x/xerrors"
31)
32
33type packageHandleKey string
34
35type packageHandle struct {
36	handle *memoize.Handle
37
38	goFiles, compiledGoFiles []*parseGoHandle
39
40	// mode is the mode the files were parsed in.
41	mode source.ParseMode
42
43	// m is the metadata associated with the package.
44	m *knownMetadata
45
46	// key is the hashed key for the package.
47	key packageHandleKey
48}
49
50func (ph *packageHandle) packageKey() packageKey {
51	return packageKey{
52		id:   ph.m.id,
53		mode: ph.mode,
54	}
55}
56
57func (ph *packageHandle) imports(ctx context.Context, s source.Snapshot) (result []string) {
58	for _, pgh := range ph.goFiles {
59		f, err := s.ParseGo(ctx, pgh.file, source.ParseHeader)
60		if err != nil {
61			continue
62		}
63		seen := map[string]struct{}{}
64		for _, impSpec := range f.File.Imports {
65			imp := strings.Trim(impSpec.Path.Value, `"`)
66			if _, ok := seen[imp]; !ok {
67				seen[imp] = struct{}{}
68				result = append(result, imp)
69			}
70		}
71	}
72
73	sort.Strings(result)
74	return result
75}
76
77// packageData contains the data produced by type-checking a package.
78type packageData struct {
79	pkg *pkg
80	err error
81}
82
83// buildPackageHandle returns a packageHandle for a given package and mode.
84func (s *snapshot) buildPackageHandle(ctx context.Context, id packageID, mode source.ParseMode) (*packageHandle, error) {
85	if ph := s.getPackage(id, mode); ph != nil {
86		return ph, nil
87	}
88
89	// Build the packageHandle for this ID and its dependencies.
90	ph, deps, err := s.buildKey(ctx, id, mode)
91	if err != nil {
92		return nil, err
93	}
94
95	// Do not close over the packageHandle or the snapshot in the Bind function.
96	// This creates a cycle, which causes the finalizers to never run on the handles.
97	// The possible cycles are:
98	//
99	//     packageHandle.h.function -> packageHandle
100	//     packageHandle.h.function -> snapshot -> packageHandle
101	//
102
103	m := ph.m
104	key := ph.key
105
106	h := s.generation.Bind(key, func(ctx context.Context, arg memoize.Arg) interface{} {
107		snapshot := arg.(*snapshot)
108
109		// Begin loading the direct dependencies, in parallel.
110		var wg sync.WaitGroup
111		for _, dep := range deps {
112			wg.Add(1)
113			go func(dep *packageHandle) {
114				dep.check(ctx, snapshot)
115				wg.Done()
116			}(dep)
117		}
118
119		data := &packageData{}
120		data.pkg, data.err = typeCheck(ctx, snapshot, m.metadata, mode, deps)
121		// Make sure that the workers above have finished before we return,
122		// especially in case of cancellation.
123		wg.Wait()
124
125		return data
126	}, nil)
127	ph.handle = h
128
129	// Cache the handle in the snapshot. If a package handle has already
130	// been cached, addPackage will return the cached value. This is fine,
131	// since the original package handle above will have no references and be
132	// garbage collected.
133	ph = s.addPackageHandle(ph)
134
135	return ph, nil
136}
137
138// buildKey computes the key for a given packageHandle.
139func (s *snapshot) buildKey(ctx context.Context, id packageID, mode source.ParseMode) (*packageHandle, map[packagePath]*packageHandle, error) {
140	m := s.getMetadata(id)
141	if m == nil {
142		return nil, nil, errors.Errorf("no metadata for %s", id)
143	}
144	goFiles, err := s.parseGoHandles(ctx, m.goFiles, mode)
145	if err != nil {
146		return nil, nil, err
147	}
148	compiledGoFiles, err := s.parseGoHandles(ctx, m.compiledGoFiles, mode)
149	if err != nil {
150		return nil, nil, err
151	}
152	ph := &packageHandle{
153		m:               m,
154		goFiles:         goFiles,
155		compiledGoFiles: compiledGoFiles,
156		mode:            mode,
157	}
158	// Make sure all of the depList are sorted.
159	depList := append([]packageID{}, m.deps...)
160	sort.Slice(depList, func(i, j int) bool {
161		return depList[i] < depList[j]
162	})
163
164	deps := make(map[packagePath]*packageHandle)
165
166	// Begin computing the key by getting the depKeys for all dependencies.
167	var depKeys []packageHandleKey
168	for _, depID := range depList {
169		depHandle, err := s.buildPackageHandle(ctx, depID, s.workspaceParseMode(depID))
170		// Don't use invalid metadata for dependencies if the top-level
171		// metadata is valid. We only load top-level packages, so if the
172		// top-level is valid, all of its dependencies should be as well.
173		if err != nil || m.valid && !depHandle.m.valid {
174			event.Error(ctx, fmt.Sprintf("%s: no dep handle for %s", id, depID), err, tag.Snapshot.Of(s.id))
175			if ctx.Err() != nil {
176				return nil, nil, ctx.Err()
177			}
178			// One bad dependency should not prevent us from checking the entire package.
179			// Add a special key to mark a bad dependency.
180			depKeys = append(depKeys, packageHandleKey(fmt.Sprintf("%s import not found", id)))
181			continue
182		}
183		deps[depHandle.m.pkgPath] = depHandle
184		depKeys = append(depKeys, depHandle.key)
185	}
186	experimentalKey := s.View().Options().ExperimentalPackageCacheKey
187	ph.key = checkPackageKey(ph.m.id, compiledGoFiles, m.config, depKeys, mode, experimentalKey)
188	return ph, deps, nil
189}
190
191func (s *snapshot) workspaceParseMode(id packageID) source.ParseMode {
192	s.mu.Lock()
193	defer s.mu.Unlock()
194	_, ws := s.workspacePackages[id]
195	if !ws {
196		return source.ParseExported
197	}
198	if s.view.Options().MemoryMode == source.ModeNormal {
199		return source.ParseFull
200	}
201
202	// Degraded mode. Check for open files.
203	m, ok := s.metadata[id]
204	if !ok {
205		return source.ParseExported
206	}
207	for _, cgf := range m.compiledGoFiles {
208		if s.isOpenLocked(cgf) {
209			return source.ParseFull
210		}
211	}
212	return source.ParseExported
213}
214
215func checkPackageKey(id packageID, pghs []*parseGoHandle, cfg *packages.Config, deps []packageHandleKey, mode source.ParseMode, experimentalKey bool) packageHandleKey {
216	b := bytes.NewBuffer(nil)
217	b.WriteString(string(id))
218	if !experimentalKey {
219		// cfg was used to produce the other hashed inputs (package ID, parsed Go
220		// files, and deps). It should not otherwise affect the inputs to the type
221		// checker, so this experiment omits it. This should increase cache hits on
222		// the daemon as cfg contains the environment and working directory.
223		b.WriteString(hashConfig(cfg))
224	}
225	b.WriteByte(byte(mode))
226	for _, dep := range deps {
227		b.WriteString(string(dep))
228	}
229	for _, cgf := range pghs {
230		b.WriteString(cgf.file.FileIdentity().String())
231	}
232	return packageHandleKey(hashContents(b.Bytes()))
233}
234
235// hashEnv returns a hash of the snapshot's configuration.
236func hashEnv(s *snapshot) string {
237	s.view.optionsMu.Lock()
238	env := s.view.options.EnvSlice()
239	s.view.optionsMu.Unlock()
240
241	b := &bytes.Buffer{}
242	for _, e := range env {
243		b.WriteString(e)
244	}
245	return hashContents(b.Bytes())
246}
247
248// hashConfig returns the hash for the *packages.Config.
249func hashConfig(config *packages.Config) string {
250	b := bytes.NewBuffer(nil)
251
252	// Dir, Mode, Env, BuildFlags are the parts of the config that can change.
253	b.WriteString(config.Dir)
254	b.WriteString(string(rune(config.Mode)))
255
256	for _, e := range config.Env {
257		b.WriteString(e)
258	}
259	for _, f := range config.BuildFlags {
260		b.WriteString(f)
261	}
262	return hashContents(b.Bytes())
263}
264
265func (ph *packageHandle) Check(ctx context.Context, s source.Snapshot) (source.Package, error) {
266	return ph.check(ctx, s.(*snapshot))
267}
268
269func (ph *packageHandle) check(ctx context.Context, s *snapshot) (*pkg, error) {
270	v, err := ph.handle.Get(ctx, s.generation, s)
271	if err != nil {
272		return nil, err
273	}
274	data := v.(*packageData)
275	return data.pkg, data.err
276}
277
278func (ph *packageHandle) CompiledGoFiles() []span.URI {
279	return ph.m.compiledGoFiles
280}
281
282func (ph *packageHandle) ID() string {
283	return string(ph.m.id)
284}
285
286func (ph *packageHandle) cached(g *memoize.Generation) (*pkg, error) {
287	v := ph.handle.Cached(g)
288	if v == nil {
289		return nil, errors.Errorf("no cached type information for %s", ph.m.pkgPath)
290	}
291	data := v.(*packageData)
292	return data.pkg, data.err
293}
294
295func (s *snapshot) parseGoHandles(ctx context.Context, files []span.URI, mode source.ParseMode) ([]*parseGoHandle, error) {
296	pghs := make([]*parseGoHandle, 0, len(files))
297	for _, uri := range files {
298		fh, err := s.GetFile(ctx, uri)
299		if err != nil {
300			return nil, err
301		}
302		pghs = append(pghs, s.parseGoHandle(ctx, fh, mode))
303	}
304	return pghs, nil
305}
306
307func typeCheck(ctx context.Context, snapshot *snapshot, m *metadata, mode source.ParseMode, deps map[packagePath]*packageHandle) (*pkg, error) {
308	var filter *unexportedFilter
309	if mode == source.ParseExported {
310		filter = &unexportedFilter{uses: map[string]bool{}}
311	}
312	pkg, err := doTypeCheck(ctx, snapshot, m, mode, deps, filter)
313	if err != nil {
314		return nil, err
315	}
316
317	if mode == source.ParseExported {
318		// The AST filtering is a little buggy and may remove things it
319		// shouldn't. If we only got undeclared name errors, try one more
320		// time keeping those names.
321		missing, unexpected := filter.ProcessErrors(pkg.typeErrors)
322		if len(unexpected) == 0 && len(missing) != 0 {
323			event.Log(ctx, fmt.Sprintf("discovered missing identifiers: %v", missing), tag.Package.Of(string(m.id)))
324			pkg, err = doTypeCheck(ctx, snapshot, m, mode, deps, filter)
325			if err != nil {
326				return nil, err
327			}
328			missing, unexpected = filter.ProcessErrors(pkg.typeErrors)
329		}
330		if len(unexpected) != 0 || len(missing) != 0 {
331			event.Log(ctx, fmt.Sprintf("falling back to safe trimming due to type errors: %v or still-missing identifiers: %v", unexpected, missing), tag.Package.Of(string(m.id)))
332			pkg, err = doTypeCheck(ctx, snapshot, m, mode, deps, nil)
333			if err != nil {
334				return nil, err
335			}
336		}
337	}
338
339	// If this is a replaced module in the workspace, the version is
340	// meaningless, and we don't want clients to access it.
341	if m.module != nil {
342		version := m.module.Version
343		if source.IsWorkspaceModuleVersion(version) {
344			version = ""
345		}
346		pkg.version = &module.Version{
347			Path:    m.module.Path,
348			Version: version,
349		}
350	}
351
352	// We don't care about a package's errors unless we have parsed it in full.
353	if mode != source.ParseFull {
354		return pkg, nil
355	}
356
357	for _, e := range m.errors {
358		diags, err := goPackagesErrorDiagnostics(snapshot, pkg, e)
359		if err != nil {
360			event.Error(ctx, "unable to compute positions for list errors", err, tag.Package.Of(pkg.ID()))
361			continue
362		}
363		pkg.diagnostics = append(pkg.diagnostics, diags...)
364	}
365
366	// Our heuristic for whether to show type checking errors is:
367	//  + If any file was 'fixed', don't show type checking errors as we
368	//    can't guarantee that they reference accurate locations in the source.
369	//  + If there is a parse error _in the current file_, suppress type
370	//    errors in that file.
371	//  + Otherwise, show type errors even in the presence of parse errors in
372	//    other package files. go/types attempts to suppress follow-on errors
373	//    due to bad syntax, so on balance type checking errors still provide
374	//    a decent signal/noise ratio as long as the file in question parses.
375
376	// Track URIs with parse errors so that we can suppress type errors for these
377	// files.
378	unparseable := map[span.URI]bool{}
379	for _, e := range pkg.parseErrors {
380		diags, err := parseErrorDiagnostics(snapshot, pkg, e)
381		if err != nil {
382			event.Error(ctx, "unable to compute positions for parse errors", err, tag.Package.Of(pkg.ID()))
383			continue
384		}
385		for _, diag := range diags {
386			unparseable[diag.URI] = true
387			pkg.diagnostics = append(pkg.diagnostics, diag)
388		}
389	}
390
391	if pkg.hasFixedFiles {
392		return pkg, nil
393	}
394
395	unexpanded := pkg.typeErrors
396	pkg.typeErrors = nil
397	for _, e := range expandErrors(unexpanded, snapshot.View().Options().RelatedInformationSupported) {
398		diags, err := typeErrorDiagnostics(snapshot, pkg, e)
399		if err != nil {
400			event.Error(ctx, "unable to compute positions for type errors", err, tag.Package.Of(pkg.ID()))
401			continue
402		}
403		pkg.typeErrors = append(pkg.typeErrors, e.primary)
404		for _, diag := range diags {
405			// If the file didn't parse cleanly, it is highly likely that type
406			// checking errors will be confusing or redundant. But otherwise, type
407			// checking usually provides a good enough signal to include.
408			if !unparseable[diag.URI] {
409				pkg.diagnostics = append(pkg.diagnostics, diag)
410			}
411		}
412	}
413
414	depsErrors, err := snapshot.depsErrors(ctx, pkg)
415	if err != nil {
416		return nil, err
417	}
418	pkg.diagnostics = append(pkg.diagnostics, depsErrors...)
419
420	return pkg, nil
421}
422
423func doTypeCheck(ctx context.Context, snapshot *snapshot, m *metadata, mode source.ParseMode, deps map[packagePath]*packageHandle, astFilter *unexportedFilter) (*pkg, error) {
424	ctx, done := event.Start(ctx, "cache.typeCheck", tag.Package.Of(string(m.id)))
425	defer done()
426
427	pkg := &pkg{
428		m:       m,
429		mode:    mode,
430		imports: make(map[packagePath]*pkg),
431		types:   types.NewPackage(string(m.pkgPath), string(m.name)),
432		typesInfo: &types.Info{
433			Types:      make(map[ast.Expr]types.TypeAndValue),
434			Defs:       make(map[*ast.Ident]types.Object),
435			Uses:       make(map[*ast.Ident]types.Object),
436			Implicits:  make(map[ast.Node]types.Object),
437			Selections: make(map[*ast.SelectorExpr]*types.Selection),
438			Scopes:     make(map[ast.Node]*types.Scope),
439		},
440		typesSizes: m.typesSizes,
441	}
442
443	for _, gf := range pkg.m.goFiles {
444		// In the presence of line directives, we may need to report errors in
445		// non-compiled Go files, so we need to register them on the package.
446		// However, we only need to really parse them in ParseFull mode, when
447		// the user might actually be looking at the file.
448		fh, err := snapshot.GetFile(ctx, gf)
449		if err != nil {
450			return nil, err
451		}
452		goMode := source.ParseFull
453		if mode != source.ParseFull {
454			goMode = source.ParseHeader
455		}
456		pgf, err := snapshot.ParseGo(ctx, fh, goMode)
457		if err != nil {
458			return nil, err
459		}
460		pkg.goFiles = append(pkg.goFiles, pgf)
461	}
462
463	if err := parseCompiledGoFiles(ctx, snapshot, mode, pkg, astFilter); err != nil {
464		return nil, err
465	}
466
467	// Use the default type information for the unsafe package.
468	if m.pkgPath == "unsafe" {
469		// Don't type check Unsafe: it's unnecessary, and doing so exposes a data
470		// race to Unsafe.completed.
471		pkg.types = types.Unsafe
472		return pkg, nil
473	}
474
475	if len(m.compiledGoFiles) == 0 {
476		// No files most likely means go/packages failed. Try to attach error
477		// messages to the file as much as possible.
478		var found bool
479		for _, e := range m.errors {
480			srcDiags, err := goPackagesErrorDiagnostics(snapshot, pkg, e)
481			if err != nil {
482				continue
483			}
484			found = true
485			pkg.diagnostics = append(pkg.diagnostics, srcDiags...)
486		}
487		if found {
488			return pkg, nil
489		}
490		return nil, errors.Errorf("no parsed files for package %s, expected: %v, errors: %v", pkg.m.pkgPath, pkg.compiledGoFiles, m.errors)
491	}
492
493	cfg := &types.Config{
494		Error: func(e error) {
495			pkg.typeErrors = append(pkg.typeErrors, e.(types.Error))
496		},
497		Importer: importerFunc(func(pkgPath string) (*types.Package, error) {
498			// If the context was cancelled, we should abort.
499			if ctx.Err() != nil {
500				return nil, ctx.Err()
501			}
502			dep := resolveImportPath(pkgPath, pkg, deps)
503			if dep == nil {
504				return nil, snapshot.missingPkgError(pkgPath)
505			}
506			if !source.IsValidImport(string(m.pkgPath), string(dep.m.pkgPath)) {
507				return nil, errors.Errorf("invalid use of internal package %s", pkgPath)
508			}
509			depPkg, err := dep.check(ctx, snapshot)
510			if err != nil {
511				return nil, err
512			}
513			pkg.imports[depPkg.m.pkgPath] = depPkg
514			return depPkg.types, nil
515		}),
516	}
517
518	if mode != source.ParseFull {
519		cfg.DisableUnusedImportCheck = true
520		cfg.IgnoreFuncBodies = true
521	}
522
523	// We want to type check cgo code if go/types supports it.
524	// We passed typecheckCgo to go/packages when we Loaded.
525	typesinternal.SetUsesCgo(cfg)
526
527	check := types.NewChecker(cfg, snapshot.FileSet(), pkg.types, pkg.typesInfo)
528
529	var files []*ast.File
530	for _, cgf := range pkg.compiledGoFiles {
531		files = append(files, cgf.File)
532	}
533	// Type checking errors are handled via the config, so ignore them here.
534	_ = check.Files(files)
535	// If the context was cancelled, we may have returned a ton of transient
536	// errors to the type checker. Swallow them.
537	if ctx.Err() != nil {
538		return nil, ctx.Err()
539	}
540	return pkg, nil
541}
542
543func parseCompiledGoFiles(ctx context.Context, snapshot *snapshot, mode source.ParseMode, pkg *pkg, astFilter *unexportedFilter) error {
544	for _, cgf := range pkg.m.compiledGoFiles {
545		fh, err := snapshot.GetFile(ctx, cgf)
546		if err != nil {
547			return err
548		}
549
550		var pgf *source.ParsedGoFile
551		var fixed bool
552		// Only parse Full through the cache -- we need to own Exported ASTs
553		// to prune them.
554		if mode == source.ParseFull {
555			pgh := snapshot.parseGoHandle(ctx, fh, mode)
556			pgf, fixed, err = snapshot.parseGo(ctx, pgh)
557		} else {
558			d := parseGo(ctx, snapshot.FileSet(), fh, mode)
559			pgf, fixed, err = d.parsed, d.fixed, d.err
560		}
561		if err != nil {
562			return err
563		}
564		pkg.compiledGoFiles = append(pkg.compiledGoFiles, pgf)
565		if pgf.ParseErr != nil {
566			pkg.parseErrors = append(pkg.parseErrors, pgf.ParseErr)
567		}
568		// If we have fixed parse errors in any of the files, we should hide type
569		// errors, as they may be completely nonsensical.
570		pkg.hasFixedFiles = pkg.hasFixedFiles || fixed
571	}
572	if mode != source.ParseExported {
573		return nil
574	}
575	if astFilter != nil {
576		var files []*ast.File
577		for _, cgf := range pkg.compiledGoFiles {
578			files = append(files, cgf.File)
579		}
580		astFilter.Filter(files)
581	} else {
582		for _, cgf := range pkg.compiledGoFiles {
583			trimAST(cgf.File)
584		}
585	}
586	return nil
587}
588
589func (s *snapshot) depsErrors(ctx context.Context, pkg *pkg) ([]*source.Diagnostic, error) {
590	// Select packages that can't be found, and were imported in non-workspace packages.
591	// Workspace packages already show their own errors.
592	var relevantErrors []*packagesinternal.PackageError
593	for _, depsError := range pkg.m.depsErrors {
594		// Up to Go 1.15, the missing package was included in the stack, which
595		// was presumably a bug. We want the next one up.
596		directImporterIdx := len(depsError.ImportStack) - 1
597		if s.view.goversion < 15 {
598			directImporterIdx = len(depsError.ImportStack) - 2
599		}
600		if directImporterIdx < 0 {
601			continue
602		}
603
604		directImporter := depsError.ImportStack[directImporterIdx]
605		if s.isWorkspacePackage(packageID(directImporter)) {
606			continue
607		}
608		relevantErrors = append(relevantErrors, depsError)
609	}
610
611	// Don't build the import index for nothing.
612	if len(relevantErrors) == 0 {
613		return nil, nil
614	}
615
616	// Build an index of all imports in the package.
617	type fileImport struct {
618		cgf *source.ParsedGoFile
619		imp *ast.ImportSpec
620	}
621	allImports := map[string][]fileImport{}
622	for _, cgf := range pkg.compiledGoFiles {
623		for _, group := range astutil.Imports(s.FileSet(), cgf.File) {
624			for _, imp := range group {
625				if imp.Path == nil {
626					continue
627				}
628				path := strings.Trim(imp.Path.Value, `"`)
629				allImports[path] = append(allImports[path], fileImport{cgf, imp})
630			}
631		}
632	}
633
634	// Apply a diagnostic to any import involved in the error, stopping once
635	// we reach the workspace.
636	var errors []*source.Diagnostic
637	for _, depErr := range relevantErrors {
638		for i := len(depErr.ImportStack) - 1; i >= 0; i-- {
639			item := depErr.ImportStack[i]
640			if s.isWorkspacePackage(packageID(item)) {
641				break
642			}
643
644			for _, imp := range allImports[item] {
645				rng, err := source.NewMappedRange(s.FileSet(), imp.cgf.Mapper, imp.imp.Pos(), imp.imp.End()).Range()
646				if err != nil {
647					return nil, err
648				}
649				fixes, err := goGetQuickFixes(s, imp.cgf.URI, item)
650				if err != nil {
651					return nil, err
652				}
653				errors = append(errors, &source.Diagnostic{
654					URI:            imp.cgf.URI,
655					Range:          rng,
656					Severity:       protocol.SeverityError,
657					Source:         source.TypeError,
658					Message:        fmt.Sprintf("error while importing %v: %v", item, depErr.Err),
659					SuggestedFixes: fixes,
660				})
661			}
662		}
663	}
664
665	if len(pkg.compiledGoFiles) == 0 {
666		return errors, nil
667	}
668	mod := s.GoModForFile(pkg.compiledGoFiles[0].URI)
669	if mod == "" {
670		return errors, nil
671	}
672	fh, err := s.GetFile(ctx, mod)
673	if err != nil {
674		return nil, err
675	}
676	pm, err := s.ParseMod(ctx, fh)
677	if err != nil {
678		return nil, err
679	}
680
681	// Add a diagnostic to the module that contained the lowest-level import of
682	// the missing package.
683	for _, depErr := range relevantErrors {
684		for i := len(depErr.ImportStack) - 1; i >= 0; i-- {
685			item := depErr.ImportStack[i]
686			m := s.getMetadata(packageID(item))
687			if m == nil || m.module == nil {
688				continue
689			}
690			modVer := module.Version{Path: m.module.Path, Version: m.module.Version}
691			reference := findModuleReference(pm.File, modVer)
692			if reference == nil {
693				continue
694			}
695			rng, err := rangeFromPositions(pm.Mapper, reference.Start, reference.End)
696			if err != nil {
697				return nil, err
698			}
699			fixes, err := goGetQuickFixes(s, pm.URI, item)
700			if err != nil {
701				return nil, err
702			}
703			errors = append(errors, &source.Diagnostic{
704				URI:            pm.URI,
705				Range:          rng,
706				Severity:       protocol.SeverityError,
707				Source:         source.TypeError,
708				Message:        fmt.Sprintf("error while importing %v: %v", item, depErr.Err),
709				SuggestedFixes: fixes,
710			})
711			break
712		}
713	}
714	return errors, nil
715}
716
717// missingPkgError returns an error message for a missing package that varies
718// based on the user's workspace mode.
719func (s *snapshot) missingPkgError(pkgPath string) error {
720	if s.workspaceMode()&moduleMode != 0 {
721		return fmt.Errorf("no required module provides package %q", pkgPath)
722	}
723	gorootSrcPkg := filepath.FromSlash(filepath.Join(s.view.goroot, "src", pkgPath))
724
725	var b strings.Builder
726	b.WriteString(fmt.Sprintf("cannot find package %q in any of \n\t%s (from $GOROOT)", pkgPath, gorootSrcPkg))
727
728	for _, gopath := range strings.Split(s.view.gopath, ":") {
729		gopathSrcPkg := filepath.FromSlash(filepath.Join(gopath, "src", pkgPath))
730		b.WriteString(fmt.Sprintf("\n\t%s (from $GOPATH)", gopathSrcPkg))
731	}
732	return errors.New(b.String())
733}
734
735type extendedError struct {
736	primary     types.Error
737	secondaries []types.Error
738}
739
740func (e extendedError) Error() string {
741	return e.primary.Error()
742}
743
744// expandErrors duplicates "secondary" errors by mapping them to their main
745// error. Some errors returned by the type checker are followed by secondary
746// errors which give more information about the error. These are errors in
747// their own right, and they are marked by starting with \t. For instance, when
748// there is a multiply-defined function, the secondary error points back to the
749// definition first noticed.
750//
751// This function associates the secondary error with its primary error, which can
752// then be used as RelatedInformation when the error becomes a diagnostic.
753//
754// If supportsRelatedInformation is false, the secondary is instead embedded as
755// additional context in the primary error.
756func expandErrors(errs []types.Error, supportsRelatedInformation bool) []extendedError {
757	var result []extendedError
758	for i := 0; i < len(errs); {
759		original := extendedError{
760			primary: errs[i],
761		}
762		for i++; i < len(errs); i++ {
763			spl := errs[i]
764			if len(spl.Msg) == 0 || spl.Msg[0] != '\t' {
765				break
766			}
767			spl.Msg = spl.Msg[1:]
768			original.secondaries = append(original.secondaries, spl)
769		}
770
771		// Clone the error to all its related locations -- VS Code, at least,
772		// doesn't do it for us.
773		result = append(result, original)
774		for i, mainSecondary := range original.secondaries {
775			// Create the new primary error, with a tweaked message, in the
776			// secondary's location. We need to start from the secondary to
777			// capture its unexported location fields.
778			relocatedSecondary := mainSecondary
779			if supportsRelatedInformation {
780				relocatedSecondary.Msg = fmt.Sprintf("%v (see details)", original.primary.Msg)
781			} else {
782				relocatedSecondary.Msg = fmt.Sprintf("%v (this error: %v)", original.primary.Msg, mainSecondary.Msg)
783			}
784			relocatedSecondary.Soft = original.primary.Soft
785
786			// Copy over the secondary errors, noting the location of the
787			// current error we're cloning.
788			clonedError := extendedError{primary: relocatedSecondary, secondaries: []types.Error{original.primary}}
789			for j, secondary := range original.secondaries {
790				if i == j {
791					secondary.Msg += " (this error)"
792				}
793				clonedError.secondaries = append(clonedError.secondaries, secondary)
794			}
795			result = append(result, clonedError)
796		}
797
798	}
799	return result
800}
801
802// resolveImportPath resolves an import path in pkg to a package from deps.
803// It should produce the same results as resolveImportPath:
804// https://cs.opensource.google/go/go/+/master:src/cmd/go/internal/load/pkg.go;drc=641918ee09cb44d282a30ee8b66f99a0b63eaef9;l=990.
805func resolveImportPath(importPath string, pkg *pkg, deps map[packagePath]*packageHandle) *packageHandle {
806	if dep := deps[packagePath(importPath)]; dep != nil {
807		return dep
808	}
809	// We may be in GOPATH mode, in which case we need to check vendor dirs.
810	searchDir := path.Dir(pkg.PkgPath())
811	for {
812		vdir := packagePath(path.Join(searchDir, "vendor", importPath))
813		if vdep := deps[vdir]; vdep != nil {
814			return vdep
815		}
816
817		// Search until Dir doesn't take us anywhere new, e.g. "." or "/".
818		next := path.Dir(searchDir)
819		if searchDir == next {
820			break
821		}
822		searchDir = next
823	}
824
825	// Vendor didn't work. Let's try minimal module compatibility mode.
826	// In MMC, the packagePath is the canonical (.../vN/...) path, which
827	// is hard to calculate. But the go command has already resolved the ID
828	// to the non-versioned path, and we can take advantage of that.
829	for _, dep := range deps {
830		if dep.ID() == importPath {
831			return dep
832		}
833	}
834	return nil
835}
836
837// An importFunc is an implementation of the single-method
838// types.Importer interface based on a function value.
839type importerFunc func(path string) (*types.Package, error)
840
841func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
842