gopls/internal/lsp/source: avoid unnecessary transitive rdeps

Most callers of ReverseDependencies need only the direct importers.
The new 'transitive bool' flag lets them express that and do less
work.

Change-Id: Ib0a6b1efc892424dde0e4d2c30ad67c91212fc56
Reviewed-on: https://go-review.googlesource.com/c/tools/+/458855
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
diff --git a/gopls/internal/lsp/cache/snapshot.go b/gopls/internal/lsp/cache/snapshot.go
index ea57d57..bda3690 100644
--- a/gopls/internal/lsp/cache/snapshot.go
+++ b/gopls/internal/lsp/cache/snapshot.go
@@ -819,19 +819,32 @@
 	return metas, nil
 }
 
-func (s *snapshot) ReverseDependencies(ctx context.Context, id PackageID) (map[PackageID]*source.Metadata, error) {
+func (s *snapshot) ReverseDependencies(ctx context.Context, id PackageID, transitive bool) (map[PackageID]*source.Metadata, error) {
 	if err := s.awaitLoaded(ctx); err != nil {
 		return nil, err
 	}
 	s.mu.Lock()
 	meta := s.meta
 	s.mu.Unlock()
-	rdeps := meta.reverseTransitiveClosure(id)
 
-	// Remove the original package ID from the map.
-	// TODO(adonovan): we should make ReverseDependencies and
-	// reverseTransitiveClosure consistent wrt reflexiveness.
-	delete(rdeps, id)
+	var rdeps map[PackageID]*source.Metadata
+	if transitive {
+		rdeps = meta.reverseReflexiveTransitiveClosure(id)
+
+		// Remove the original package ID from the map.
+		// (Callers all want irreflexivity but it's easier
+		// to compute reflexively then subtract.)
+		delete(rdeps, id)
+
+	} else {
+		// direct reverse dependencies
+		rdeps = make(map[PackageID]*source.Metadata)
+		for _, rdepID := range meta.importedBy[id] {
+			if rdep := meta.metadata[rdepID]; rdep != nil {
+				rdeps[rdepID] = rdep
+			}
+		}
+	}
 
 	return rdeps, nil
 }