Repository: kythe/kythe
Pull request #4756 (2020-11-13 18:06:24)

fix(java_indexer): emit references to .class literals


Patch:
diff --git a/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java b/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java
index a2cba04c8..3e4383cd4 100644
--- a/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java
+++ b/kythe/java/com/google/devtools/kythe/analyzers/java/JavaEntrySets.java
@@ -137,6 +137,11 @@ public class JavaEntrySets extends KytheEntrySets {
               .build();
     }
 
+    if (v == null && sym.owner != null && sym.owner.asType().isPrimitive()) {
+      // Handle primitive .class reference
+      v = newBuiltinAndEmit(sym.asType().toString()).getVName();
+    }
+
     if (v == null) {
       getStatisticsCollector().incrementCounter("unextracted-input-file");
       String msg =
diff --git a/kythe/java/com/google/devtools/kythe/analyzers/java/KytheTreeScanner.java b/kythe/java/com/google/devtools/kythe/analyzers/java/KytheTreeScanner.java
index 506cdc823..35eca6b55 100644
--- a/kythe/java/com/google/devtools/kythe/analyzers/java/KytheTreeScanner.java
+++ b/kythe/java/com/google/devtools/kythe/analyzers/java/KytheTreeScanner.java
@@ -834,7 +834,7 @@ public class KytheTreeScanner extends JCTreeScanner<JavaNode, TreeContext> {
 
     if (sym == null) {
       scan(field.getExpression(), ctx);
-      if (!field.name.toString().equals("*")) {
+      if (!field.name.contentEquals("*")) {
         String msg = "Could not determine selected Symbol for " + field;
         if (config.getVerboseLogging()) {
           logger.atWarning().log(msg);
@@ -849,7 +849,10 @@ public class KytheTreeScanner extends JCTreeScanner<JavaNode, TreeContext> {
     } else {
       scan(field.getExpression(), ctx);
       return emitNameUsage(
-          ctx, sym, field.name, imprt != null ? EdgeKind.REF_IMPORTS : EdgeKind.REF);
+          ctx,
+          sym,
+          field.name.contentEquals("class") ? Keyword.CLASS : field.name,
+          imprt != null ? EdgeKind.REF_IMPORTS : EdgeKind.REF);
     }
   }
 
@@ -860,7 +863,7 @@ public class KytheTreeScanner extends JCTreeScanner<JavaNode, TreeContext> {
     return emitNameUsage(
         ctx,
         reference.sym,
-        reference.getMode() == ReferenceMode.NEW ? Keyword.of("new") : reference.name);
+        reference.getMode() == ReferenceMode.NEW ? Keyword.NEW : reference.name);
   }
 
   @Override
@@ -1572,6 +1575,7 @@ public class KytheTreeScanner extends JCTreeScanner<JavaNode, TreeContext> {
     } catch (UnsupportedOperationException
         | IllegalArgumentException
         | NullPointerException unused) {
+      // Do nothing; perform fallback below
     }
     // Fallback to URI-based path resolution when asPath is unsupported.
     URI uri = filePositions.getSourceFile().toUri();
diff --git a/kythe/java/com/google/devtools/kythe/analyzers/java/SourceText.java b/kythe/java/com/google/devtools/kythe/analyzers/java/SourceText.java
index c15914fae..5ab3afa88 100644
--- a/kythe/java/com/google/devtools/kythe/analyzers/java/SourceText.java
+++ b/kythe/java/com/google/devtools/kythe/analyzers/java/SourceText.java
@@ -61,7 +61,9 @@ public final class SourceText {
       if (token.kind == TokenKind.IDENTIFIER) {
         positions.addIdentifier(token.name(), scanner.spanForToken(token));
       } else if (token.kind == TokenKind.NEW) {
-        positions.addIdentifier(Keyword.of("new"), scanner.spanForToken(token));
+        positions.addIdentifier(Keyword.NEW, scanner.spanForToken(token));
+      } else if (token.kind == TokenKind.CLASS) {
+        positions.addIdentifier(Keyword.CLASS, scanner.spanForToken(token));
       } else if (token.kind == TokenKind.LT) {
         starts.addFirst(token);
       } else if (token.kind == TokenKind.GT) {
@@ -108,13 +110,11 @@ public final class SourceText {
   }
 
   /** Names for keywords that must act as anchors. */
-  public static final class Keyword implements Name {
-    private final String keyword;
+  public static enum Keyword implements Name {
+    NEW("new"),
+    CLASS("class");
 
-    /** Factory method that can do something smarter if/when we need it to. */
-    public static Keyword of(String keyword) {
-      return new Keyword(keyword);
-    }
+    private final String keyword;
 
     private Keyword(String keyword) {
       this.keyword = keyword;
@@ -144,20 +144,6 @@ public final class SourceText {
     public String toString() {
       return keyword;
     }
-
-    @Override
-    public boolean equals(Object obj) {
-      if (obj instanceof Keyword) {
-        return ((Keyword) obj).contentEquals(keyword);
-      } else {
-        return false;
-      }
-    }
-
-    @Override
-    public int hashCode() {
-      return 1 + keyword.hashCode();
-    }
   }
 
   /** Utility class to provide ANCHOR positions in Java sources. */


Test patch:
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/SpecialMembers.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/SpecialMembers.java
index 654272842..3da51bf1e 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/SpecialMembers.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/SpecialMembers.java
@@ -23,10 +23,20 @@ public final class SpecialMembers {
     //- GetClass.node/kind function
     Class<?> arrayClass = args.getClass();
 
-    // TODO(schroederc): @class ref Class
+    //- @class ref CRef
+    //- CRef.subkind field
+    //- !{ @class ref IntRef }
     System.err.println(SpecialMembers.class);
 
-    // TODO(schroederc): @class ref Class
+    //- @class ref IntRef
+    //- IntRef.subkind field
+    //- !{ @class ref CRef
+    //-    @class ref LongRef }
     System.err.println(int.class);
+
+    //- @class ref LongRef
+    //- LongRef.subkind field
+    //- !{ @class ref IntRef }
+    System.err.println(long.class);
   }
 }