import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
-import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
+import org.jetbrains.jps.javac.ast.api.JavacDefSymbol;
/**
* Used via reflection in {@link JavacTreeRefScanner#createASTScanner()}
public class Javac8RefScanner extends JavacTreeRefScanner {
@Override
public Tree visitLambdaExpression(LambdaExpressionTree node, JavacTreeScannerSink sink) {
- final Type type = ((JCTree.JCLambda)node).type;
+ JCTree.JCLambda lambda = (JCTree.JCLambda)node;
+ final Type type = lambda.type;
final Symbol.TypeSymbol symbol = type.asElement();
- sink.sinkReference(new JavacRefSymbol(symbol, Tree.Kind.LAMBDA_EXPRESSION));
- //for (Symbol member : symbol.members().getElements()) {
- // sink.mySymbols.add(new JavacRefSymbol(member, Tree.Kind.LAMBDA_EXPRESSION));
- //}
+ sink.sinkDeclaration(new JavacDefSymbol(symbol, Tree.Kind.LAMBDA_EXPRESSION, lambda.pos));
return super.visitLambdaExpression(node, sink);
}
@Override
public Tree visitMemberReference(MemberReferenceTree node, JavacTreeScannerSink sink) {
- final Symbol methodSymbol = ((JCTree.JCMemberReference)node).sym;
- sink.sinkReference(new JavacRefSymbol(methodSymbol, Tree.Kind.MEMBER_REFERENCE));
+ JCTree.JCMemberReference memberRef = (JCTree.JCMemberReference)node;
+ final Symbol methodSymbol = memberRef.sym;
+ sink.sinkDeclaration(new JavacDefSymbol(methodSymbol, Tree.Kind.MEMBER_REFERENCE, memberRef.pos));
return super.visitMemberReference(node, sink);
}
}
Lambda in Lambda
Lambda.<init>(0) in Lambda
Lambda.main(1) in Lambda
+fun_expr(java.lang.Runnable at 80) in Lambda
java.lang.Object.<init>(0) in Lambda
-java.lang.Runnable in Lambda
java.lang.String in Lambda
java.lang.Thread in Lambda
\ No newline at end of file
*/
package org.jetbrains.jps.backwardRefs;
+import com.intellij.util.Function;
import com.intellij.util.SystemProperties;
+import com.intellij.util.containers.ContainerUtil;
import com.sun.tools.javac.code.Symbol;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntProcedure;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Set;
+import java.util.List;
public class BackwardReferenceIndexWriter {
public static final String PROP_KEY = "ref.index.builder";
myIndex.close();
}
- synchronized void writeReferences(JavaFileObject file, Set<JavacRefSymbol> refs) {
- final LightUsage[] usages = new LightUsage[refs.size()];
- int idx = 0;
+ synchronized List<LightUsage> asLightUsages(Collection<JavacRefSymbol> symbols) {
final ByteArrayEnumerator byteSeqEum = myIndex.getByteSeqEum();
- for (JavacRefSymbol ref : refs) {
- usages[idx++] = LightUsage.fromSymbol(ref.getSymbol(), byteSeqEum);
- }
+ return ContainerUtil.mapNotNull(symbols, new Function<JavacRefSymbol, LightUsage>() {
+ @Override
+ public LightUsage fun(JavacRefSymbol symbol) {
+ return LightUsage.fromSymbol(symbol, byteSeqEum);
+ }
+ });
+ }
+ synchronized void writeReferences(JavaFileObject file, Collection<LightUsage> usages) {
final int fileId = enumerateFile(file);
if (myRebuild) {
for (LightUsage usage : usages) {
}
}
- private void updateReferenceIndicesIncrementally(int fileId, LightUsage[] usages) {
+ private void updateReferenceIndicesIncrementally(int fileId, Collection<LightUsage> usages) {
final Collection<LightUsage> rawOldUsages = myIndex.getReferenceMap().get(fileId);
Collection<LightUsage> oldUsages = rawOldUsages == null ? null : new ArrayList<LightUsage>(rawOldUsages);
for (LightUsage usage : usages) {
*/
package org.jetbrains.jps.backwardRefs;
+import com.sun.source.tree.Tree;
import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Type;
+import org.jetbrains.jps.javac.ast.api.JavacDefSymbol;
import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar;
import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
import javax.tools.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.Set;
public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar {
+ private static final Symbol[] EMPTY_SYMBOL_ARRAY = new Symbol[0];
+
private BackwardReferenceIndexWriter myWriter;
@Override
}
@Override
- public void registerReferences(JavaFileObject file, Set<JavacRefSymbol> refs) {
- myWriter.writeReferences(file, refs);
- }
+ public void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, Collection<JavacDefSymbol> defs) {
- @Override
- public void registerClassDeclaration(Symbol className, Symbol[] supers) {
- myWriter.writeHierarchy(className, supers);
+ List<JavacRefSymbol> fileIndexData = null;
+
+ for (JavacDefSymbol def : defs) {
+ Tree.Kind kind = def.getPlaceKind();
+ if (kind == Tree.Kind.CLASS) {
+ Symbol.ClassSymbol sym = (Symbol.ClassSymbol)def.getSymbol();
+ Type superclass = sym.getSuperclass();
+ List<Type> interfaces = sym.getInterfaces();
+
+ final Symbol[] supers;
+ if (superclass != Type.noType) {
+ supers = new Symbol[interfaces.size() + 1];
+ supers[interfaces.size()] = superclass.asElement();
+ } else {
+ supers = interfaces.isEmpty() ? EMPTY_SYMBOL_ARRAY : new Symbol[interfaces.size()];
+ }
+
+ int i = 0;
+ for (Type anInterface : interfaces) {
+ supers[i++] = anInterface.asElement();
+ }
+ myWriter.writeHierarchy(sym, supers);
+ }
+ else if (kind == LightUsage.MEMBER_REFERENCE || kind == LightUsage.LAMBDA_EXPRESSION) {
+ if (fileIndexData == null) {
+ fileIndexData = new ArrayList<JavacRefSymbol>();
+ }
+ fileIndexData.add(def);
+ }
+ }
+
+ final List<LightUsage> usages;
+ if (fileIndexData != null) {
+ fileIndexData.addAll(refs);
+ usages = myWriter.asLightUsages(fileIndexData);
+ }
+ else {
+ usages = myWriter.asLightUsages(refs);
+ }
+ myWriter.writeReferences(file, usages);
}
}
import com.intellij.util.io.DataInputOutputUtil;
import com.intellij.util.io.KeyDescriptor;
+import com.sun.source.tree.Tree;
+import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.java.dependencyView.RW;
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
+import org.jetbrains.jps.javac.ast.api.JavacDefSymbol;
+import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
import javax.lang.model.element.ElementKind;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
+import static com.sun.tools.javac.code.Flags.PRIVATE;
+
public abstract class LightUsage implements RW.Savable {
private final static byte CLASS_MARKER = 0x0;
private final static byte METHOD_MARKER = 0x1;
private final static byte FIELD_MARKER = 0x2;
+ private final static byte FUN_EXPR_MARKER = 0x3;
+
+ static final Tree.Kind LAMBDA_EXPRESSION;
+ static final Tree.Kind MEMBER_REFERENCE;
+
+ static {
+ Tree.Kind lambdaExpression = null;
+ Tree.Kind memberReference = null;
+ try {
+ lambdaExpression = Tree.Kind.valueOf("LAMBDA_EXPRESSION");
+ memberReference = Tree.Kind.valueOf("MEMBER_REFERENCE");
+ }
+ catch (IllegalArgumentException ignored) {
+ }
+ LAMBDA_EXPRESSION = lambdaExpression;
+ MEMBER_REFERENCE = memberReference;
+ }
public final int myOwner;
}
}
+ public static class LightFunExprUsage extends LightUsage {
+ private final int myOffset;
+
+ public LightFunExprUsage(int owner, int offset) {
+ super(owner);
+ myOffset = offset;
+ }
+
+ public int getOffset() {
+ return myOffset;
+ }
+
+ @NotNull
+ @Override
+ public LightClassUsage override(int ownerOverrider) {
+ return new LightClassUsage(ownerOverrider);
+ }
+
+ @Override
+ public void save(DataOutput out) {
+ try {
+ out.writeByte(FUN_EXPR_MARKER);
+ DataInputOutputUtil.writeINT(out, getOwner());
+ DataInputOutputUtil.writeINT(out, getOffset());
+ }
+ catch (IOException e) {
+ throw new BuildDataCorruptedException(e);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ LightFunExprUsage usage = (LightFunExprUsage)o;
+
+ if (myOwner != usage.myOwner) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return myOwner;
+ }
+ }
+
static KeyDescriptor<LightUsage> createDescriptor() {
return new KeyDescriptor<LightUsage>() {
@Override
return new LightMethodUsage(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
case FIELD_MARKER:
return new LightFieldUsage(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
+ case FUN_EXPR_MARKER:
+ return new LightFunExprUsage(DataInputOutputUtil.readINT(in), DataInputOutputUtil.readINT(in));
}
throw new AssertionError();
}
return symbol.flatName().toUtf();
}
- static LightUsage fromSymbol(Symbol symbol, ByteArrayEnumerator byteArrayEnumerator) {
- final ElementKind kind = symbol.getKind();
+ @Nullable
+ static LightUsage fromSymbol(JavacRefSymbol refSymbol, ByteArrayEnumerator byteArrayEnumerator) {
+ Symbol symbol = refSymbol.getSymbol();
+ final Tree.Kind kind = refSymbol.getPlaceKind();
if (symbol instanceof Symbol.ClassSymbol) {
- return new LightClassUsage(id(symbol, byteArrayEnumerator));
- }
- else if (symbol instanceof Symbol.VarSymbol) {
- return new LightFieldUsage(id(symbol.owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator));
- }
- else if (symbol instanceof Symbol.MethodSymbol) {
- int paramCount = ((Symbol.MethodSymbol)symbol).type.getParameterTypes().size();
- return new LightMethodUsage(id(symbol.owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator), paramCount);
+ if (kind == LAMBDA_EXPRESSION || kind == MEMBER_REFERENCE) {
+ return new LightFunExprUsage(id(symbol, byteArrayEnumerator), ((JavacDefSymbol)refSymbol).getOffset());
+ } else if (!isPrivate(symbol) && !symbol.isAnonymous()) {
+ return new LightClassUsage(id(symbol, byteArrayEnumerator));
+ }
}
else {
- throw new AssertionError("unexpected symbol: " + symbol + " class: " + symbol.getClass() + " kind: " + kind);
+ Symbol owner = symbol.owner;
+ if (isPrivate(symbol)) {
+ return null;
+ }
+ if (symbol instanceof Symbol.VarSymbol) {
+ return new LightFieldUsage(id(owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator));
+ }
+ else if (symbol instanceof Symbol.MethodSymbol) {
+ int paramCount = ((Symbol.MethodSymbol)symbol).type.getParameterTypes().size();
+ return new LightMethodUsage(id(owner, byteArrayEnumerator), id(symbol, byteArrayEnumerator), paramCount);
+ }
+ else {
+ throw new AssertionError("unexpected symbol: " + symbol + " class: " + symbol.getClass() + " kind: " + kind);
+ }
}
+ return null;
+ }
+
+ // JDK-6 has no Symbol.isPrivate() method
+ private static boolean isPrivate(Symbol symbol) {
+ return (symbol.flags() & Flags.AccessFlags) == PRIVATE;
}
private static int id(Symbol symbol, ByteArrayEnumerator byteArrayEnumerator) {
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.Name;
import gnu.trove.THashSet;
+import org.jetbrains.jps.javac.ast.api.JavacDefSymbol;
import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar;
import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
import org.jetbrains.jps.service.JpsServiceManager;
import javax.tools.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
public class JavacReferencesCollector {
public static void installOn(JavacTask task) {
final Set<JavacRefSymbol> symbols = new THashSet<JavacRefSymbol>();
scanImports(myCurrentCompilationUnit, symbols);
for (JavacFileReferencesRegistrar listener : myOnlyImportsListeners) {
- listener.registerReferences(sourceFile, symbols);
+ listener.registerFile(sourceFile, symbols, Collections.<JavacDefSymbol>emptySet());
}
if (myFullASTListeners.length != 0) {
+ final Collection<JavacDefSymbol> defs = new ArrayList<JavacDefSymbol>();
myAstScanner.scan(myCurrentCompilationUnit, new JavacTreeScannerSink() {
@Override
public void sinkReference(JavacRefSymbol ref) {
}
@Override
- public void sinkClassDeclaration(Symbol className, Symbol[] supers) {
- for (JavacFileReferencesRegistrar listener : myFullASTListeners) {
- listener.registerClassDeclaration(className, supers);
- }
+ public void sinkDeclaration(JavacDefSymbol def) {
+ defs.add(def);
}
});
for (JavacFileReferencesRegistrar listener : myFullASTListeners) {
- listener.registerReferences(sourceFile, symbols);
+ listener.registerFile(sourceFile, symbols, defs);
}
}
}
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
+import org.jetbrains.jps.javac.ast.api.JavacDefSymbol;
import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
import javax.lang.model.element.ElementKind;
import javax.lang.model.type.TypeKind;
-import java.util.List;
class JavacTreeRefScanner extends TreeScanner<Tree, JavacTreeScannerSink> {
- private static final Symbol[] EMPTY_SYMBOL_ARRAY = new Symbol[0];
-
@Override
public Tree visitCompilationUnit(CompilationUnitTree node, JavacTreeScannerSink sink) {
scan(node.getPackageAnnotations(), sink);
@Override
public Tree visitClass(ClassTree node, JavacTreeScannerSink sink) {
- Symbol.ClassSymbol sym = ((JCTree.JCClassDecl)node).sym;
+ JCTree.JCClassDecl classDecl = (JCTree.JCClassDecl)node;
+ Symbol.ClassSymbol sym = classDecl.sym;
sink.sinkReference(new JavacRefSymbol(sym, Tree.Kind.CLASS));
-
- Type superclass = sym.getSuperclass();
- List<Type> interfaces = sym.getInterfaces();
-
- final Symbol[] supers;
- if (superclass != Type.noType) {
- supers = new Symbol[interfaces.size() + 1];
- supers[interfaces.size()] = superclass.asElement();
- } else {
- supers = interfaces.isEmpty() ? EMPTY_SYMBOL_ARRAY : new Symbol[interfaces.size()];
- }
-
- int i = 0;
- for (Type anInterface : interfaces) {
- supers[i++] = anInterface.asElement();
- }
- sink.sinkClassDeclaration(sym, supers);
-
+ sink.sinkDeclaration(new JavacDefSymbol(sym, Tree.Kind.CLASS, classDecl.pos));
return super.visitClass(node, sink);
}
*/
package org.jetbrains.jps.javac.ast;
-import com.sun.tools.javac.code.Symbol;
+import org.jetbrains.jps.javac.ast.api.JavacDefSymbol;
import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
interface JavacTreeScannerSink {
void sinkReference(JavacRefSymbol ref);
- void sinkClassDeclaration(Symbol className, Symbol[] supers);
+ void sinkDeclaration(JavacDefSymbol def);
}
*/
package org.jetbrains.jps.javac.ast.api;
-import com.sun.tools.javac.code.Symbol;
-
import javax.tools.*;
+import java.util.Collection;
import java.util.Set;
public interface JavacFileReferencesRegistrar {
boolean onlyImports();
- void registerReferences(JavaFileObject file, Set<JavacRefSymbol> refs);
-
- void registerClassDeclaration(Symbol className, Symbol[] supers);
+ void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, Collection<JavacDefSymbol> defs);
}
Backward References:
Anonymous in Anonymous
-Anonymous$1 in Anonymous
Anonymous$1.<init>(0) in Anonymous
Anonymous$1.run(0) in Anonymous
Anonymous.<init>(0) in Anonymous
--- /dev/null
+class PrivateMembers {
+
+ private int privateField = 0;
+
+ private void privateMethod() {
+
+ }
+
+ private static class PrivateInnerClass {
+
+ }
+}
\ No newline at end of file
fun testAnonymous() {
assertIndexOnRebuild("Anonymous.java")
}
+
+ fun testPrivateMembers() {
+ assertIndexOnRebuild("PrivateMembers.java")
+ }
}
byteArrayEnumerator) + "(" + this.parameterCount + ")"
is LightUsage.LightFieldUsage -> this.owner.asName(byteArrayEnumerator) + "." + this.name.asName(byteArrayEnumerator)
is LightUsage.LightClassUsage -> this.owner.asName(byteArrayEnumerator)
+ is LightUsage.LightFunExprUsage -> "fun_expr(" + this.owner.asName(byteArrayEnumerator) + " at " + this.offset + ")";
else -> throw UnsupportedOperationException()
}
}
\ No newline at end of file