javac ast indices: when java file contains >1 top declaration classes only one was...
authorDmitry Batkovich <dmitry.batkovich@jetbrains.com>
Sat, 15 Oct 2016 16:34:40 +0000 (19:34 +0300)
committerDmitry Batkovich <dmitry.batkovich@jetbrains.com>
Sat, 15 Oct 2016 16:34:40 +0000 (19:34 +0300)
jps/jps-builders/src/org/jetbrains/jps/javac/ast/JavacReferencesCollector.java
jps/jps-builders/testData/referencesIndex/compilationUnitContains2Decls/Foo.java [new file with mode: 0644]
jps/jps-builders/testData/referencesIndex/compilationUnitContains2Decls/initialIndex.txt [new file with mode: 0644]
jps/jps-builders/testData/referencesIndex/nestedClasses/Foo.java [new file with mode: 0644]
jps/jps-builders/testData/referencesIndex/nestedClasses/initialIndex.txt [new file with mode: 0644]
jps/jps-builders/testData/referencesIndex/packageInfo/initialIndex.txt
jps/jps-builders/testSrc/org/jetbrains/references/ReferenceIndexTest.kt
jps/jps-builders/testSrc/org/jetbrains/references/ReferenceIndexTestBase.kt

index 0eb4519f85305e8bfd0c7d6b4b0b18bfee6321d3..6a597ba4fc443ca0dc984e5619bff2b93e77c3ca 100644 (file)
@@ -31,6 +31,7 @@ import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
 import org.jetbrains.jps.service.JpsServiceManager;
 
 import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
 import javax.tools.*;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -71,14 +72,17 @@ public class JavacReferencesCollector {
   }
 
   private static final class MyTaskListener implements TaskListener {
-    private JCTree.JCCompilationUnit myCurrentCompilationUnit;
     private final JavacFileReferencesRegistrar[] myFullASTListeners;
     private final JavacFileReferencesRegistrar[] myOnlyImportsListeners;
     private final JavacTreeRefScanner myAstScanner;
 
-    private int myCurrentSize;
     private Name myAsteriks;
 
+    private int myRemainDecls;
+    private JCTree.JCCompilationUnit myCurrentCompilationUnit;
+    private Set<JavacRefSymbol> myCollectedReferences;
+    private Set<JavacRefSymbol> myCollectedDefinitions;
+
     public MyTaskListener(JavacFileReferencesRegistrar[] fullASTListenerArray, JavacFileReferencesRegistrar[] importsListenerArray) {
       myFullASTListeners = fullASTListenerArray;
       myOnlyImportsListeners = importsListenerArray;
@@ -94,40 +98,58 @@ public class JavacReferencesCollector {
     public void finished(TaskEvent e) {
       try {
         if (e.getKind() == TaskEvent.Kind.ANALYZE) {
-          // javac creates event on each processed class not file
+          // javac creates an event on each processed top level declared class not file
           if (myCurrentCompilationUnit != e.getCompilationUnit()) {
             myCurrentCompilationUnit = (JCTree.JCCompilationUnit)e.getCompilationUnit();
-            myCurrentSize = myCurrentCompilationUnit.getTypeDecls().size() - 1;
+            myCollectedDefinitions = new THashSet<JavacRefSymbol>();
+            myCollectedReferences = new THashSet<JavacRefSymbol>();
+            myRemainDecls = myCurrentCompilationUnit.getTypeDecls().size() - 1;
+            scanImports(myCurrentCompilationUnit, myCollectedReferences);
+            for(JavacFileReferencesRegistrar r: myOnlyImportsListeners) {
+              r.registerFile(e.getSourceFile(), myCollectedReferences, myCollectedDefinitions);
+            }
           }
           else {
-            myCurrentSize--;
+            myRemainDecls--;
           }
 
-          if (myCurrentSize == 0) {
-            final JavaFileObject sourceFile = e.getSourceFile();
-            final Set<JavacRefSymbol> symbols = new THashSet<JavacRefSymbol>();
-            scanImports(myCurrentCompilationUnit, symbols);
-            for (JavacFileReferencesRegistrar listener : myOnlyImportsListeners) {
-              listener.registerFile(sourceFile, symbols, Collections.<JavacRefSymbol>emptySet());
+          JavacTreeScannerSink sink = new JavacTreeScannerSink() {
+            @Override
+            public void sinkReference(JavacRefSymbol ref) {
+              myCollectedReferences.add(ref);
             }
-            if (myFullASTListeners.length != 0) {
-              final Collection<JavacRefSymbol> defs = new ArrayList<JavacRefSymbol>();
-              myAstScanner.scan(myCurrentCompilationUnit, new JavacTreeScannerSink() {
-                @Override
-                public void sinkReference(JavacRefSymbol ref) {
-                  symbols.add(ref);
-                }
 
-                @Override
-                public void sinkDeclaration(JavacRefSymbol def) {
-                  defs.add(def);
-                }
-              });
-              for (JavacFileReferencesRegistrar listener : myFullASTListeners) {
-                listener.registerFile(sourceFile, symbols, defs);
+            @Override
+            public void sinkDeclaration(JavacRefSymbol def) {
+              myCollectedDefinitions.add(def);
+            }
+          };
+
+          if (myFullASTListeners.length != 0) {
+            TypeElement analyzedElement = e.getTypeElement();
+            for (JCTree tree : myCurrentCompilationUnit.getTypeDecls()) {
+              if (tree.type != null && tree.type.tsym == analyzedElement) {
+                myAstScanner.scan(tree, sink);
               }
             }
           }
+
+          if (myRemainDecls == 0) {
+            if (myFullASTListeners.length != 0) {
+              for (JCTree.JCAnnotation annotation : myCurrentCompilationUnit.getPackageAnnotations()) {
+                myAstScanner.scan(annotation, sink);
+              }
+            }
+
+            for(JavacFileReferencesRegistrar r: myFullASTListeners) {
+              r.registerFile(e.getSourceFile(), myCollectedReferences, myCollectedDefinitions);
+            }
+
+            myCurrentCompilationUnit = null;
+            myCollectedDefinitions = null;
+            myCollectedReferences = null;
+          }
+
         }
       }
       catch (Exception ex) {
diff --git a/jps/jps-builders/testData/referencesIndex/compilationUnitContains2Decls/Foo.java b/jps/jps-builders/testData/referencesIndex/compilationUnitContains2Decls/Foo.java
new file mode 100644 (file)
index 0000000..00f0c15
--- /dev/null
@@ -0,0 +1,17 @@
+import java.util.Collections;
+
+class Foo {
+
+  void m() {
+    Collections.emptySet();
+  }
+
+}
+
+class Boo {
+
+  void m() {
+    Collections.emptyList();
+  }
+
+}
\ No newline at end of file
diff --git a/jps/jps-builders/testData/referencesIndex/compilationUnitContains2Decls/initialIndex.txt b/jps/jps-builders/testData/referencesIndex/compilationUnitContains2Decls/initialIndex.txt
new file mode 100644 (file)
index 0000000..fb3e1bb
--- /dev/null
@@ -0,0 +1,18 @@
+Backward Hierarchy:
+java.lang.Object -> Boo Foo
+
+Backward References:
+Boo in Foo
+Boo.<init>(0) in Foo
+Boo.m(0) in Foo
+Foo in Foo
+Foo.<init>(0) in Foo
+Foo.m(0) in Foo
+java.lang.Object.<init>(0) in Foo
+java.util.Collections in Foo
+java.util.Collections.emptyList(0) in Foo
+java.util.Collections.emptySet(0) in Foo
+
+Class Definitions:
+Boo in Foo
+Foo in Foo
\ No newline at end of file
diff --git a/jps/jps-builders/testData/referencesIndex/nestedClasses/Foo.java b/jps/jps-builders/testData/referencesIndex/nestedClasses/Foo.java
new file mode 100644 (file)
index 0000000..a3f4f4b
--- /dev/null
@@ -0,0 +1,33 @@
+import java.util.Collections;
+
+class Foo {
+
+  void m() {
+    Collections.emptyList();
+  }
+
+  static class Bar {
+
+    void m() {
+      Collections.emptyMap();
+    }
+
+  }
+
+}
+
+class Boo {
+
+  static class Baz {
+
+    void m() {
+      Collections.singleton(null);
+    }
+
+  }
+
+  void m() {
+    Collections.emptySet();
+  }
+
+}
\ No newline at end of file
diff --git a/jps/jps-builders/testData/referencesIndex/nestedClasses/initialIndex.txt b/jps/jps-builders/testData/referencesIndex/nestedClasses/initialIndex.txt
new file mode 100644 (file)
index 0000000..38d8143
--- /dev/null
@@ -0,0 +1,28 @@
+Backward Hierarchy:
+java.lang.Object -> Boo Boo$Baz Foo Foo$Bar
+
+Backward References:
+Boo in Foo
+Boo$Baz in Foo
+Boo$Baz.<init>(0) in Foo
+Boo$Baz.m(0) in Foo
+Boo.<init>(0) in Foo
+Boo.m(0) in Foo
+Foo in Foo
+Foo$Bar in Foo
+Foo$Bar.<init>(0) in Foo
+Foo$Bar.m(0) in Foo
+Foo.<init>(0) in Foo
+Foo.m(0) in Foo
+java.lang.Object.<init>(0) in Foo
+java.util.Collections in Foo
+java.util.Collections.emptyList(0) in Foo
+java.util.Collections.emptyMap(0) in Foo
+java.util.Collections.emptySet(0) in Foo
+java.util.Collections.singleton(1) in Foo
+
+Class Definitions:
+Boo in Foo
+Boo$Baz in Foo
+Foo in Foo
+Foo$Bar in Foo
\ No newline at end of file
index 722cfdb71be75ed7c3319bc336d73a1b686b948f..e59599fbf68fcb634254f5bb1ab34806590e2d41 100644 (file)
@@ -3,6 +3,7 @@ java.lang.Object -> myPackage.A
 
 Backward References:
 java.lang.Deprecated in package-info
+java.lang.Object.<init>(0) in package-info
 myPackage.A in package-info
 myPackage.A.<init>(0) in package-info
 
index c11f6b0551d27e9124d26f32d722814e66107e32..f571f8752b81024098f8d208ced15bd49ff6d60d 100644 (file)
@@ -89,5 +89,13 @@ class ReferenceIndexTest : ReferenceIndexTestBase() {
     buildAllModules()
     assertIndexEquals("fileDeletedIndex.txt")
   }
+
+  fun testCompilationUnitContains2Decls() {
+    assertIndexOnRebuild("Foo.java")
+  }
+
+  fun testNestedClasses() {
+    assertIndexOnRebuild("Foo.java")
+  }
 }
 
index eb90ba4a97713d53700dd2935d754e3cda4c2d65..3d96dd828fc289cdd9bab53018b97133a2c3cade 100644 (file)
@@ -17,10 +17,10 @@ package org.jetbrains.references
 
 import com.intellij.openapi.util.io.FileUtil
 import com.intellij.openapi.vfs.CharsetToolkit
-import com.intellij.testFramework.UsefulTestCase
+import com.intellij.openapi.vfs.VfsUtil
 import com.intellij.util.PathUtil
+import com.intellij.util.io.PersistentStringEnumerator
 import com.sun.tools.javac.util.Convert
-import junit.framework.TestCase
 import org.jetbrains.jps.backwardRefs.BackwardReferenceIndexWriter
 import org.jetbrains.jps.backwardRefs.ByteArrayEnumerator
 import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex
@@ -68,9 +68,7 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
 
 
   protected fun assertIndexEquals(expectedIndexDumpFile: String) {
-    val expectedIndex = FileUtil.loadFile(File(testDataRootPath + "/" + getTestName(true) + "/" + expectedIndexDumpFile), CharsetToolkit.UTF8_CHARSET)
-    val actualIndex = indexAsText()
-    TestCase.assertTrue(String.CASE_INSENSITIVE_ORDER.compare(expectedIndex, actualIndex) == 0)
+    assertSameLinesWithFile(testDataRootPath + "/" + getTestName(true) + "/" + expectedIndexDumpFile, indexAsText())
   }
 
   protected fun indexAsText(): String {
@@ -91,7 +89,6 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
         val inheritorsText = mutableListOf<String>()
         inheritors.forEach { id ->
           inheritorsText.add(id.asText(nameEnumerator))
-          true
         }
         inheritorsText.sort()
         hierarchyText.add(superClassName + " -> " + inheritorsText.joinToString(separator = " "))
@@ -105,9 +102,7 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
       index.backwardReferenceMap.forEachEntry { usage, files ->
         val referents = mutableListOf<String>()
         files.forEach { id ->
-          val file = File(fileEnumerator.valueOf(id))
-          val fileName = FileUtil.getNameWithoutExtension(file)
-          referents.add(fileName)
+          referents.add(id.asFileName(fileEnumerator))
         }
         referents.sort()
         referencesText.add(usage.asText(nameEnumerator) + " in " + referents.joinToString(separator = " "))
@@ -121,9 +116,7 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
       index.backwardClassDefinitionMap.forEachEntry { usage, files ->
         val definitionFiles = mutableListOf<String>()
         files.forEach { id ->
-          val file = File(fileEnumerator.valueOf(id))
-          val fileName = FileUtil.getNameWithoutExtension(file)
-          definitionFiles.add(fileName)
+          definitionFiles.add(id.asFileName(fileEnumerator))
         }
         definitionFiles.sort()
         classDefs.add(usage.asText(nameEnumerator) + " in " + definitionFiles.joinToString(separator = " "))
@@ -140,8 +133,7 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
 
   private fun getTestDataPath() = testDataRootPath + "/" + getTestName(true) + "/"
 
-  private fun Int.asName(byteArrayEnumerator: ByteArrayEnumerator): String = Convert.utf2string(
-      byteArrayEnumerator.valueOf(this))
+  private fun Int.asName(byteArrayEnumerator: ByteArrayEnumerator): String = Convert.utf2string(byteArrayEnumerator.valueOf(this))
 
   private fun CompilerBackwardReferenceIndex.LightDefinition.asText(byteArrayEnumerator: ByteArrayEnumerator) = this.usage.asText(byteArrayEnumerator)
 
@@ -154,4 +146,6 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
         is LightUsage.LightFunExprUsage -> "fun_expr(" + this.name.asName(byteArrayEnumerator) + ")"
         else -> throw UnsupportedOperationException()
       }
+
+  private fun Int.asFileName(fileNameEnumerator: PersistentStringEnumerator) = FileUtil.getNameWithoutExtension(File(fileNameEnumerator.valueOf(this)).canonicalFile)
 }
\ No newline at end of file