Remove duplicate isEnclosedIn logic from DaggerElements and ValidationReport.

This CL removes logic that was duplicated between the two classes. It also simplifies DaggerElements version to check the `enclosed.getEnclosingElement()` rather than comparing the `enclosed` with every recursively inclosed element of `encloser`, which should be a lot more efficient.

I've also rewritten closestEnclosingTypeElement to avoid using the ElementVisitor, which will likely be more difficult to use once we convert to XProcessing.

RELNOTES=N/A
PiperOrigin-RevId: 390419676
diff --git a/java/dagger/internal/codegen/langmodel/DaggerElements.java b/java/dagger/internal/codegen/langmodel/DaggerElements.java
index 413e3b5..0ca2a0c 100644
--- a/java/dagger/internal/codegen/langmodel/DaggerElements.java
+++ b/java/dagger/internal/codegen/langmodel/DaggerElements.java
@@ -30,7 +30,6 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
-import com.google.common.graph.Traverser;
 import com.squareup.javapoet.ClassName;
 import dagger.Reusable;
 import dagger.internal.codegen.base.ClearableCache;
@@ -49,7 +48,6 @@
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ElementVisitor;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.Name;
 import javax.lang.model.element.PackageElement;
@@ -70,7 +68,6 @@
 import javax.lang.model.type.WildcardType;
 import javax.lang.model.util.AbstractTypeVisitor8;
 import javax.lang.model.util.Elements;
-import javax.lang.model.util.SimpleElementVisitor8;
 import javax.lang.model.util.Types;
 
 /** Extension of {@link Elements} that adds Dagger-specific methods. */
@@ -91,16 +88,19 @@
   }
 
   /**
-   * Returns {@code true} if {@code encloser} is equal to {@code enclosed} or recursively encloses
-   * it.
+   * Returns {@code true} if {@code encloser} is equal to or recursively encloses {@code enclosed}.
    */
-  public static boolean elementEncloses(TypeElement encloser, Element enclosed) {
-    return Iterables.contains(GET_ENCLOSED_ELEMENTS.breadthFirst(encloser), enclosed);
+  public static boolean transitivelyEncloses(Element encloser, Element enclosed) {
+    Element current = enclosed;
+    while (current != null) {
+      if (current.equals(encloser)) {
+        return true;
+      }
+      current = current.getEnclosingElement();
+    }
+    return false;
   }
 
-  private static final Traverser<Element> GET_ENCLOSED_ELEMENTS =
-      Traverser.forTree(Element::getEnclosedElements);
-
   public ImmutableSet<ExecutableElement> getLocalAndInheritedMethods(TypeElement type) {
     return getLocalAndInheritedMethodsCache.computeIfAbsent(
         type, k -> MoreElements.getLocalAndInheritedMethods(type, types, elements));
@@ -129,22 +129,16 @@
 
   /** Returns the argument or the closest enclosing element that is a {@link TypeElement}. */
   public static TypeElement closestEnclosingTypeElement(Element element) {
-    return element.accept(CLOSEST_ENCLOSING_TYPE_ELEMENT, null);
+    Element current = element;
+    while (current != null) {
+      if (MoreElements.isType(current)) {
+        return MoreElements.asType(current);
+      }
+      current = current.getEnclosingElement();
+    }
+    throw new IllegalStateException("There is no enclosing TypeElement for: " + element);
   }
 
-  private static final ElementVisitor<TypeElement, Void> CLOSEST_ENCLOSING_TYPE_ELEMENT =
-      new SimpleElementVisitor8<TypeElement, Void>() {
-        @Override
-        protected TypeElement defaultAction(Element element, Void p) {
-          return element.getEnclosingElement().accept(this, null);
-        }
-
-        @Override
-        public TypeElement visitType(TypeElement type, Void p) {
-          return type;
-        }
-      };
-
   /**
    * Compares elements according to their declaration order among siblings. Only valid to compare
    * elements enclosed by the same parent.
diff --git a/java/dagger/internal/codegen/validation/CompositeBindingGraphPlugin.java b/java/dagger/internal/codegen/validation/CompositeBindingGraphPlugin.java
index dfd93f5..63bf32b 100644
--- a/java/dagger/internal/codegen/validation/CompositeBindingGraphPlugin.java
+++ b/java/dagger/internal/codegen/validation/CompositeBindingGraphPlugin.java
@@ -22,7 +22,7 @@
 import static com.google.common.collect.Lists.asList;
 import static dagger.internal.codegen.base.ElementFormatter.elementToString;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.langmodel.DaggerElements.elementEncloses;
+import static dagger.internal.codegen.langmodel.DaggerElements.transitivelyEncloses;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.errorprone.annotations.FormatMethod;
@@ -216,7 +216,7 @@
         String message) {
       // TODO(erichang): This repeats some of the logic in DiagnosticReporterImpl. Remove when
       // merged.
-      if (elementEncloses(
+      if (transitivelyEncloses(
           graph.rootComponentNode().componentPath().currentComponent().java(),
           childFactoryMethodEdge.factoryMethod().java())) {
         // Let this pass through since it is not an error reported on the root component
diff --git a/java/dagger/internal/codegen/validation/DiagnosticReporterFactory.java b/java/dagger/internal/codegen/validation/DiagnosticReporterFactory.java
index 17c7048..a613d18 100644
--- a/java/dagger/internal/codegen/validation/DiagnosticReporterFactory.java
+++ b/java/dagger/internal/codegen/validation/DiagnosticReporterFactory.java
@@ -18,7 +18,7 @@
 
 import static com.google.common.collect.Lists.asList;
 import static dagger.internal.codegen.base.ElementFormatter.elementToString;
-import static dagger.internal.codegen.langmodel.DaggerElements.elementEncloses;
+import static dagger.internal.codegen.langmodel.DaggerElements.transitivelyEncloses;
 import static javax.tools.Diagnostic.Kind.ERROR;
 
 import com.google.common.collect.ImmutableSet;
@@ -173,9 +173,7 @@
       StringBuilder fullMessage = new StringBuilder();
       appendBracketPrefix(fullMessage, plugin);
 
-      // TODO(ronshapiro): should we create a HashSet out of elementEncloses() so we don't
-      // need to do an O(n) contains() each time?
-      if (elementToReport != null && !elementEncloses(rootComponent, elementToReport)) {
+      if (elementToReport != null && !transitivelyEncloses(rootComponent, elementToReport)) {
         appendBracketPrefix(fullMessage, elementToString(elementToReport));
         elementToReport = rootComponent;
       }
diff --git a/java/dagger/internal/codegen/validation/ValidationReport.java b/java/dagger/internal/codegen/validation/ValidationReport.java
index 7f37375..5401dfa 100644
--- a/java/dagger/internal/codegen/validation/ValidationReport.java
+++ b/java/dagger/internal/codegen/validation/ValidationReport.java
@@ -18,6 +18,7 @@
 
 import static dagger.internal.codegen.base.ElementFormatter.elementToString;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.langmodel.DaggerElements.transitivelyEncloses;
 import static javax.tools.Diagnostic.Kind.ERROR;
 import static javax.tools.Diagnostic.Kind.NOTE;
 import static javax.tools.Diagnostic.Kind.WARNING;
@@ -103,7 +104,7 @@
     }
     hasPrintedErrors = true;
     for (Item item : items) {
-      if (isEnclosedIn(subject, item.element())) {
+      if (transitivelyEncloses(subject, item.element())) {
         if (item.annotation().isPresent()) {
           if (item.annotationValue().isPresent()) {
             messager.printMessage(
@@ -129,17 +130,6 @@
     }
   }
 
-  private static boolean isEnclosedIn(Element parent, Element child) {
-    Element current = child;
-    while (current != null) {
-      if (current.equals(parent)) {
-        return true;
-      }
-      current = current.getEnclosingElement();
-    }
-    return false;
-  }
-
   /** Metadata about a {@link ValidationReport} item. */
   @AutoValue
   public abstract static class Item {