diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java index a447538a0eff..b92aa29f6c6b 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java @@ -269,6 +269,10 @@ final class JavacReferenceCollectorListener implements TaskListener { return myTypeUtility; } + JavacNameTable getNameTable() { + return myNameTableCache; + } + private int decrementRemainDeclarationsAndGet(Tree declarationToProcess) { return declarationToProcess == null ? myRemainDeclarations : --myRemainDeclarations; } diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacTreeRefScanner.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacTreeRefScanner.java index 6587fbe64b04..8ded9c088a4e 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacTreeRefScanner.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacTreeRefScanner.java @@ -19,9 +19,11 @@ import com.intellij.util.containers.Stack; import com.sun.source.tree.*; import com.sun.source.util.TreeScanner; import org.jetbrains.jps.javac.ast.api.JavacDef; +import org.jetbrains.jps.javac.ast.api.JavacNameTable; import org.jetbrains.jps.javac.ast.api.JavacRef; import javax.lang.model.element.*; +import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -75,11 +77,7 @@ class JavacTreeRefScanner extends TreeScanner typeArguments = ((DeclaredType)retType).getTypeArguments(); + if (typeArguments.size() == 1 && isIterator((TypeElement)((DeclaredType)retType).asElement(), refCollector)) { + dimension = -1; + retType = typeArguments.get(0); + } + } + final JavacRef.JavacElementRefBase returnType = refCollector.asJavacRef(retType); + if (returnType != null) { + refCollector.sinkDeclaration(new JavacDef.JavacMemberDef(ref, returnType, dimension, isStatic(element))); + } + } + @Override public Tree visitMethodInvocation(MethodInvocationTree node, JavacReferenceCollectorListener.ReferenceCollector collector) { if (node.getMethodSelect() instanceof IdentifierTree) { @@ -208,6 +225,23 @@ class JavacTreeRefScanner extends TreeScanner myParsedNameCache; private final Elements myElements; private Name myAsterisk; + private TypeElement myStreamElement; + private TypeElement myIteratorElement; + private TypeElement myIterableElement; public JavacNameTable(Elements elements) { myParsedNameCache = new SLRUCache(1000, 1000) { @@ -56,4 +60,28 @@ public class JavacNameTable { } return myAsterisk; } + + @Nullable("if the type is not loaded to javac name table") + public TypeElement getStreamElement() { + if (myStreamElement == null) { + myStreamElement = myElements.getTypeElement("java.util.stream.Stream"); + } + return myStreamElement; + } + + @Nullable("if the type is not loaded to javac name table") + public TypeElement getIteratorElement() { + if (myIteratorElement == null) { + myIteratorElement = myElements.getTypeElement("java.util.Iterator"); + } + return myIteratorElement; + } + + @Nullable("if the type is not loaded to javac name table") + public TypeElement getIterableElement() { + if (myIterableElement == null) { + myIterableElement = myElements.getTypeElement("java.lang.Iterable"); + } + return myIterableElement; + } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/BackwardReferenceIndexUtil.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/BackwardReferenceIndexUtil.java index a8593634f934..d0c83802e223 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/BackwardReferenceIndexUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/BackwardReferenceIndexUtil.java @@ -76,7 +76,7 @@ public class BackwardReferenceIndexUtil { final LightRef ref = writer.enumerateNames(def.getDefinedElement(), name -> anonymousClassEnumerator.getLightRefIfAnonymous(name)); final LightRef.JavaLightClassRef returnType = writer.asClassUsage(((JavacDef.JavacMemberDef)def).getReturnType()); if (ref != null && returnType != null) { - final SignatureData data = new SignatureData(returnType.getName(), ((JavacDef.JavacMemberDef)def).isStatic()); + final SignatureData data = new SignatureData(returnType.getName(), ((JavacDef.JavacMemberDef)def).getIteratorKind(), ((JavacDef.JavacMemberDef)def).isStatic()); signatureData.computeIfAbsent(data, element -> new SmartList<>()).add(ref); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/SignatureData.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/SignatureData.java index 3374eec3b259..6f26035437a0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/SignatureData.java +++ b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/SignatureData.java @@ -16,11 +16,18 @@ package org.jetbrains.jps.backwardRefs; public class SignatureData { + public static final byte ZERO_DIM = 0; + public static final byte ARRAY_ONE_DIM = 1; + // represents java's Iterator, Iterable and BaseStream + public static final byte ITERATOR_ONE_DIM = 2; + private final int myRawReturnType; + private final byte myArrayDimension; private final boolean myStatic; - public SignatureData(int rawReturnType, boolean isStatic) { + public SignatureData(int rawReturnType, byte arrayDimension, boolean isStatic) { myRawReturnType = rawReturnType; + myArrayDimension = arrayDimension; myStatic = isStatic; } @@ -28,6 +35,10 @@ public class SignatureData { return myRawReturnType; } + public byte getIteratorKind() { + return myArrayDimension; + } + public boolean isStatic() { return myStatic; } @@ -38,12 +49,18 @@ public class SignatureData { if (o == null || getClass() != o.getClass()) return false; SignatureData data = (SignatureData)o; - return myRawReturnType == data.myRawReturnType && myStatic == data.myStatic; + + if (myRawReturnType != data.myRawReturnType) return false; + if (myArrayDimension != data.myArrayDimension) return false; + if (myStatic != data.myStatic) return false; + + return true; } @Override public int hashCode() { int result = myRawReturnType; + result = 31 * result + myArrayDimension; result = 31 * result + (myStatic ? 1 : 0); return result; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/index/CompilerIndices.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/index/CompilerIndices.java index 8eb0f7f69463..9245cf817052 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/index/CompilerIndices.java +++ b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/index/CompilerIndices.java @@ -37,7 +37,7 @@ import java.util.List; public class CompilerIndices { //TODO manage version separately - public final static int VERSION = 4; + public final static int VERSION = 5; public final static ID BACK_USAGES = ID.create("back.refs"); public final static ID> BACK_HIERARCHY = ID.create("back.hierarchy"); @@ -217,12 +217,13 @@ public class CompilerIndices { @Override public void save(@NotNull DataOutput out, SignatureData value) throws IOException { DataInputOutputUtil.writeINT(out, value.getRawReturnType()); + out.writeByte(value.getIteratorKind()); out.writeBoolean(value.isStatic()); } @Override public SignatureData read(@NotNull DataInput in) throws IOException { - return new SignatureData(DataInputOutputUtil.readINT(in), in.readBoolean()); + return new SignatureData(DataInputOutputUtil.readINT(in), in.readByte(), in.readBoolean()); } }; } diff --git a/jps/jps-builders/testData/referencesIndex/signatureDataIndex/Foo.java b/jps/jps-builders/testData/referencesIndex/signatureDataIndex/Foo.java index ddfd2651a8f8..16ea7496dcd5 100644 --- a/jps/jps-builders/testData/referencesIndex/signatureDataIndex/Foo.java +++ b/jps/jps-builders/testData/referencesIndex/signatureDataIndex/Foo.java @@ -14,4 +14,15 @@ public class Foo { return null; } + public String[] m4() { + return null; + } + + public String f1; + + public static List f2; + + public List f3; + + public String[] f4; } \ No newline at end of file diff --git a/jps/jps-builders/testData/referencesIndex/signatureDataIndex/initialIndex.txt b/jps/jps-builders/testData/referencesIndex/signatureDataIndex/initialIndex.txt index e9c4c301eeeb..b7d25e8851c0 100644 --- a/jps/jps-builders/testData/referencesIndex/signatureDataIndex/initialIndex.txt +++ b/jps/jps-builders/testData/referencesIndex/signatureDataIndex/initialIndex.txt @@ -4,17 +4,23 @@ java.lang.Object -> Foo Backward References: Foo in Foo occurrences = 1 Foo.(0) in Foo occurrences = 1 +Foo.f1 in Foo occurrences = 1 +Foo.f2 in Foo occurrences = 1 +Foo.f3 in Foo occurrences = 1 +Foo.f4 in Foo occurrences = 1 Foo.m1(0) in Foo occurrences = 1 Foo.m2(0) in Foo occurrences = 1 Foo.m3(0) in Foo occurrences = 1 +Foo.m4(0) in Foo occurrences = 1 java.lang.Object.(0) in Foo occurrences = 1 -java.lang.String in Foo occurrences = 2 -java.util.List in Foo occurrences = 3 +java.lang.String in Foo occurrences = 6 +java.util.List in Foo occurrences = 5 Class Definitions: Foo in Foo Members Signatures: -java.lang.String <- Foo.m1(0) -java.util.List <- Foo.m3(0) -static java.util.List <- Foo.m2(0) \ No newline at end of file +java.lang.String <- Foo.f1 Foo.m1(0) +java.lang.String[] <- Foo.f4 Foo.m4(0) +java.util.List <- Foo.f3 Foo.m3(0) +static java.lang.String iterator <- Foo.f2 Foo.m2(0) \ No newline at end of file diff --git a/jps/jps-builders/testSrc/org/jetbrains/references/ReferenceIndexTestBase.kt b/jps/jps-builders/testSrc/org/jetbrains/references/ReferenceIndexTestBase.kt index ed107ae6dbb4..e648b3051838 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/references/ReferenceIndexTestBase.kt +++ b/jps/jps-builders/testSrc/org/jetbrains/references/ReferenceIndexTestBase.kt @@ -185,7 +185,16 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() { } private fun SignatureData.asText(nameEnumerator: NameEnumerator): String { - return (if (this.isStatic) "static " else "") + this.rawReturnType.asName(nameEnumerator) + return (if (this.isStatic) "static " else "") + this.rawReturnType.asName(nameEnumerator) + decodeVectorKind(this.iteratorKind) + } + + private fun decodeVectorKind(kind: Byte): String { + when (kind) { + 0.toByte() -> return "" + 1.toByte() -> return "[]" + (-1).toByte() -> return " iterator" + } + throw IllegalArgumentException() } private fun Int.asFileName(fileNameEnumerator: PersistentStringEnumerator) = FileUtil.getNameWithoutExtension(File(fileNameEnumerator.valueOf(this)).canonicalFile)