Repository: kythe/kythe (language: rust)

Issue:
use `ref/id` for Java constructors
Java constructor definitions and invocations should use a `ref/id` edge when pointing to the class, as their C++ counterparts do.


Discussion / hints:

Fix patch:
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 cef9b4b35a..f271455035 100644
--- a/kythe/java/com/google/devtools/kythe/analyzers/java/KytheTreeScanner.java
+++ b/kythe/java/com/google/devtools/kythe/analyzers/java/KytheTreeScanner.java
@@ -291,7 +291,12 @@ public JavaNode visitIdent(JCIdent ident, TreeContext owner) {
     if (ident.sym == null) {
       return emitDiagnostic(ctx, "missing identifier symbol", null, null);
     }
-    JavaNode node = emitSymUsage(ctx, ident.sym);
+    EdgeKind edgeKind = EdgeKind.REF;
+    if (ident.sym instanceof ClassSymbol && ident == owner.getNewClassIdentifier()) {
+      // Use ref/id edges for the primary identifier to disambiguate from the constructor.
+      edgeKind = EdgeKind.REF_ID;
+    }
+    JavaNode node = emitSymUsage(ctx, ident.sym, edgeKind);
     if (node != null && ident.sym instanceof VarSymbol) {
       // Emit typed edges for "this"/"super" on reference since there is no definition location.
       // TODO(schroederc): possibly add implicit definition on class declaration
@@ -773,7 +778,10 @@ public JavaNode visitTypeApply(JCTypeApply tApply, TreeContext owner) {
     EntrySet typeNode =
         entrySets.newTApplyAndEmit(typeCtorNode.getVName(), argVNames, MarkedSources.GENERIC_TAPP);
     // TODO(salguarnieri) Think about removing this since it isn't something that we have a use for.
-    emitAnchor(ctx, EdgeKind.REF, typeNode.getVName());
+    emitAnchor(
+        ctx,
+        (owner.getTree() instanceof JCNewClass) ? EdgeKind.REF_ID : EdgeKind.REF,
+        typeNode.getVName());
 
     return new JavaNode(typeNode, childWildcards.build());
   }
@@ -1225,21 +1233,25 @@ private void visitAnnotations(
     }
   }
 
-  // Emits a node for the given sym, an anchor encompassing the TreeContext, and a REF edge
-  private JavaNode emitSymUsage(TreeContext ctx, Symbol sym) {
+  // Emits a node for the given sym, an anchor encompassing the TreeContext, and the given edge.
+  private JavaNode emitSymUsage(TreeContext ctx, Symbol sym, EdgeKind edgeKind) {
     JavaNode node = getRefNode(ctx, sym);
     if (node == null) {
       // TODO(schroederc): details
       return emitDiagnostic(ctx, "failed to resolve symbol reference", null, null);
     }
-
     // TODO(schroederc): emit reference to JVM node if `sym.outermostClass()` is not defined in a
     //                   .java source file
-    emitAnchor(ctx, EdgeKind.REF, node.getVName());
+    emitAnchor(ctx, edgeKind, node.getVName());
     statistics.incrementCounter("symbol-usages-emitted");
     return node;
   }
 
+  // Emits a node for the given sym, an anchor encompassing the TreeContext, and a REF edge.
+  private JavaNode emitSymUsage(TreeContext ctx, Symbol sym) {
+    return emitSymUsage(ctx, sym, EdgeKind.REF);
+  }
+
   // Emits a node for the given sym, an anchor encompassing the name, and a REF edge
   private JavaNode emitNameUsage(TreeContext ctx, Symbol sym, Name name) {
     return emitNameUsage(ctx, sym, name, EdgeKind.REF);
diff --git a/kythe/java/com/google/devtools/kythe/analyzers/java/TreeContext.java b/kythe/java/com/google/devtools/kythe/analyzers/java/TreeContext.java
index 9e5159a7a7..ca568348d6 100644
--- a/kythe/java/com/google/devtools/kythe/analyzers/java/TreeContext.java
+++ b/kythe/java/com/google/devtools/kythe/analyzers/java/TreeContext.java
@@ -23,7 +23,10 @@
 import com.sun.tools.javac.tree.JCTree.JCBlock;
 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
 import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCNewClass;
+import com.sun.tools.javac.tree.JCTree.JCTypeApply;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 import java.util.ArrayList;
 import java.util.List;
@@ -105,6 +108,27 @@ public JCClassDecl getClassParentDecl() {
     return (JCClassDecl) parent.getTree();
   }
 
+  public JCIdent getNewClassIdentifier() {
+    TreeContext parent = this;
+    while (parent != null && !(parent.getTree() instanceof JCNewClass)) {
+      parent = parent.up();
+    }
+    if (parent == null) {
+      return null;
+    }
+    JCTree ident = ((JCNewClass) parent.getTree()).getIdentifier();
+    if (ident instanceof JCIdent) {
+      return (JCIdent) ident;
+    }
+    if (ident instanceof JCTypeApply) {
+      JCTree type = ((JCTypeApply) ident).getType();
+      if (type instanceof JCIdent) {
+        return (JCIdent) type;
+      }
+    }
+    return null;
+  }
+
   public TreeContext getScope() {
     TreeContext parent = up();
     while (parent != null


Test patch:
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Callgraph.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Callgraph.java
index 0cafafec6b..24c7d664c9 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Callgraph.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Callgraph.java
@@ -65,6 +65,7 @@ public class Callgraph {
   //- CtorRef ref ECtor
   //- CtorCall childof ECtor
   //- CtorCall childof SCtor
+  //- @Callgraph ref/id Class
   final Object instance = new Callgraph();
 
   //- @Callgraph defines/binding ECtor
@@ -82,11 +83,13 @@ public Callgraph(String s) {}
   //- F typed _FType
   static void f(int n) {
     //- @"Callgraph" ref ECtor
+    //- @"Callgraph" ref/id Class
     //- ECtorCall.loc/start @^"new Callgraph()"
     //- ECtorCall.loc/end @$"new Callgraph()"
     Object cg = new Callgraph();
     //
     //- @"Callgraph" ref SCtor
+    //- @"Callgraph" ref/id Class
     //- SCtorCall.loc/start @^"new Callgraph(null)"
     //- SCtorCall.loc/end @$"new Callgraph(null)"
     cg = new Callgraph(null);
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/DiamondOperations.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/DiamondOperations.java
index ecf1738c7c..8513337f75 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/DiamondOperations.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/DiamondOperations.java
@@ -6,7 +6,7 @@ private static void testAnonymousInnerDiamond() {
     //- GenericStringType.node/kind tapp
     //- GenericStringType param.0 GenericType
     Generic<String> iter =
-        //- @"Generic<>" ref DiamondType
+        //- @"Generic<>" ref/id DiamondType
         //- DiamondType.node/kind tapp
         //- DiamondType param.0 GenericType
         new Generic<>() {
@@ -22,7 +22,7 @@ private static void testTrivialDiamondOperator() {
     //- @"Generic<Integer>" ref GenericIntType
     //- GenericIntType.node/kind tapp
     //- GenericIntType param.0 GenericType
-    //- @"Generic<>" ref DiamondIntType
+    //- @"Generic<>" ref/id DiamondIntType
     //- DiamondIntType.node/kind tapp
     //- DiamondIntType param.0 GenericType
     Generic<Integer> n = new Generic<>();
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericMethodRef.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericMethodRef.java
index 10c8d62dfd..34002dacc7 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericMethodRef.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericMethodRef.java
@@ -39,13 +39,13 @@ private static void caller() {
   //- @T defines/binding AbsT
   private static <T> void constructor() {
     //- @Optional ref OptionalConstructor
-    //- @Optional ref OClass
+    //- @Optional ref/id OClass
     //- @GenericMethodRef ref GClass
     //- @"new Optional<GenericMethodRef>()" ref/call OptionalConstructor
     Object o = new Optional<GenericMethodRef>();
 
     //- @Optional ref OptionalConstructor
-    //- @Optional ref OClass
+    //- @Optional ref/id OClass
     //- @"new Optional<T>()" ref/call OptionalConstructor
     //- @T ref AbsT
     Object o2 = new Optional<T>();
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Generics.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Generics.java
index fddff06ce2..49b594af04 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Generics.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Generics.java
@@ -36,7 +36,7 @@ public static void f() {
     //- GType param.0 Class
     //- GType param.1 _Str
     Generics<String> gs =
-        //- @"Generics<String>" ref GType
+        //- @"Generics<String>" ref/id GType
         new Generics<String>();
 
     //- @"Generics" ref Class
@@ -44,7 +44,7 @@ public static void f() {
     //- NGVar typed NGType
     //- NGType.node/kind record
     Generics nonGeneric =
-        //- @"Generics" ref Class
+        //- @"Generics" ref/id Class
         new Generics();
 
     //- @"Optional<Generics<String>>" ref OType
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericsAbs.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericsAbs.java
index b7d4220840..39c9f3cd8e 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericsAbs.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/GenericsAbs.java
@@ -40,7 +40,7 @@ public static void f() {
     //- GType param.0 GAbs
     //- GType param.1 _Str
     GenericsAbs<String> gs =
-        //- @"GenericsAbs<String>" ref GType
+        //- @"GenericsAbs<String>" ref/id GType
         new GenericsAbs<String>();
 
     //- @"GenericsAbs" ref Class
@@ -48,7 +48,7 @@ public static void f() {
     //- NGVar typed NGType
     //- NGType.node/kind record
     GenericsAbs nonGeneric =
-        //- @"GenericsAbs" ref Class
+        //- @"GenericsAbs" ref/id Class
         new GenericsAbs();
 
     //- @"Optional<GenericsAbs<String>>" ref OType
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MemberReferences.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MemberReferences.java
index a11b6d53cc..2c093718fa 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MemberReferences.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/MemberReferences.java
@@ -73,14 +73,14 @@ public BiFunction<Referent, Referent, Referent> getBiFunction() {
   }
 
   public Supplier<Referent> getIdThunk() {
-    //- @Referent ref ReferentClass
+    //- @Referent ref/id ReferentClass
     //- @func ref IdentityMethod
     //- !{ @new.node/kind anchor }
     return new Referent()::func;
   }
 
   public Function<Referent, Referent> getIdPartialApplication() {
-    //- @Referent ref ReferentClass
+    //- @Referent ref/id ReferentClass
     //- @func ref AlternativeMethod
     //- !{ @new.node/kind anchor }
     return new Referent()::func;
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Methods.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Methods.java
index dd31cfc194..c01432e2e6 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Methods.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Methods.java
@@ -30,7 +30,7 @@ public Methods() {}
   //- CreateType param.1 Class
   //- CreateType param.2 VoidBuiltin
   public static Methods create() {
-    //- @Methods ref Class
+    //- @Methods ref/id Class
     //- @"Methods" ref Ctor
     return new Methods();
   }
@@ -100,7 +100,7 @@ public static void main(String[] args) {
 
   //- @IOException ref IOE
   public static void throwsException() throws IOException {
-    //- @IOException ref IOE
+    //- @IOException ref/id IOE
     throw new IOException();
   }
 
diff --git a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Scopes.java b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Scopes.java
index f0e31a3384..70263d4ba6 100644
--- a/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Scopes.java
+++ b/kythe/javatests/com/google/devtools/kythe/analyzers/java/testdata/pkg/Scopes.java
@@ -33,6 +33,7 @@ class LocalClass {
     }
 
     //- @LocalClass childof Method
+    //- @LocalClass ref/id LocalClass
     return new LocalClass();
   }
 }