MetadataForFile returns a new slice containing metadata for each package containing the Go file identified by uri, ordered by the number of CompiledGoFiles (i.e. "narrowest" to "widest" package), and secondarily by IsIntermediateTestVariant (false < true). The result may include tests and intermedia
(ctx context.Context, uri protocol.DocumentURI, removeIntermediateTestVariants bool)
| 674 | // intermediate test variants will be excluded. |
| 675 | // It returns an error if the context was cancelled. |
| 676 | func (s *Snapshot) MetadataForFile(ctx context.Context, uri protocol.DocumentURI, removeIntermediateTestVariants bool) ([]*metadata.Package, error) { |
| 677 | if s.view.typ == AdHocView { |
| 678 | // As described in golang/go#57209, in ad-hoc workspaces (where we load ./ |
| 679 | // rather than ./...), preempting the directory load with file loads can |
| 680 | // lead to an inconsistent outcome, where certain files are loaded with |
| 681 | // command-line-arguments packages and others are loaded only in the ad-hoc |
| 682 | // package. Therefore, ensure that the workspace is loaded before doing any |
| 683 | // file loads. |
| 684 | if err := s.awaitLoaded(ctx); err != nil { |
| 685 | return nil, err |
| 686 | } |
| 687 | } |
| 688 | |
| 689 | s.mu.Lock() |
| 690 | |
| 691 | // Start with the set of package associations derived from the last load. |
| 692 | pkgs := s.meta.ForFile[uri] |
| 693 | |
| 694 | shouldLoad := false // whether any packages containing uri are marked 'shouldLoad' |
| 695 | for _, pkg := range pkgs { |
| 696 | if p, _ := s.shouldLoad.Get(pkg.ID); len(p) > 0 { |
| 697 | shouldLoad = true |
| 698 | } |
| 699 | } |
| 700 | |
| 701 | // Check if uri is known to be unloadable. |
| 702 | unloadable := s.unloadableFiles.Contains(uri) |
| 703 | |
| 704 | s.mu.Unlock() |
| 705 | |
| 706 | // Reload if loading is likely to improve the package associations for uri: |
| 707 | // - uri is not contained in any valid packages |
| 708 | // - ...or one of the packages containing uri is marked 'shouldLoad' |
| 709 | // - ...but uri is not unloadable |
| 710 | if (shouldLoad || len(pkgs) == 0) && !unloadable { |
| 711 | scope := fileLoadScope(uri) |
| 712 | err := s.load(ctx, NoNetwork, scope) |
| 713 | |
| 714 | // Return the context error here as the current operation is no longer |
| 715 | // valid. |
| 716 | if err != nil { |
| 717 | // Guard against failed loads due to context cancellation. We don't want |
| 718 | // to mark loads as completed if they failed due to context cancellation. |
| 719 | if ctx.Err() != nil { |
| 720 | return nil, ctx.Err() |
| 721 | } |
| 722 | |
| 723 | // Don't return an error here, as we may still return stale IDs. |
| 724 | // Furthermore, the result of MetadataForFile should be consistent upon |
| 725 | // subsequent calls, even if the file is marked as unloadable. |
| 726 | if !errors.Is(err, errNoPackages) { |
| 727 | event.Error(ctx, "MetadataForFile", err) |
| 728 | } |
| 729 | } |
| 730 | |
| 731 | // We must clear scopes after loading. |
| 732 | // |
| 733 | // TODO(rfindley): unlike reloadWorkspace, this is simply marking loaded |
no test coverage detected