do not add private members references to index + add functional expressions to index

This commit is contained in:
Dmitry Batkovich
2016-09-27 10:19:58 +03:00
parent d42d499dcc
commit a867b6100e
13 changed files with 205 additions and 72 deletions
@@ -6,7 +6,7 @@ import com.sun.source.tree.Tree;
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()}
@@ -15,19 +15,18 @@ import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
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);
}
}
@@ -5,7 +5,7 @@ Backward References:
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
@@ -15,7 +15,9 @@
*/
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;
@@ -33,7 +35,7 @@ import java.io.File;
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";
@@ -83,14 +85,17 @@ public class BackwardReferenceIndexWriter {
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) {
@@ -103,7 +108,7 @@ public class BackwardReferenceIndexWriter {
}
}
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) {
@@ -15,14 +15,22 @@
*/
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
@@ -37,12 +45,47 @@ public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar
}
@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);
}
}
@@ -17,20 +17,44 @@ package org.jetbrains.jps.backwardRefs;
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;
@@ -195,6 +219,54 @@ public abstract class LightUsage implements RW.Savable {
}
}
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
@@ -222,6 +294,8 @@ public abstract class LightUsage implements RW.Savable {
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();
}
@@ -232,21 +306,39 @@ public abstract class LightUsage implements RW.Savable {
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) {
@@ -26,6 +26,7 @@ import com.sun.tools.javac.tree.JCTree;
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;
@@ -34,8 +35,7 @@ import javax.lang.model.element.ElementKind;
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) {
@@ -109,9 +109,10 @@ public class JavacReferencesCollector {
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) {
@@ -119,14 +120,12 @@ public class JavacReferencesCollector {
}
@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);
}
}
}
@@ -20,15 +20,13 @@ import com.sun.source.util.TreeScanner;
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);
@@ -86,26 +84,10 @@ class JavacTreeRefScanner extends TreeScanner<Tree, JavacTreeScannerSink> {
@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);
}
@@ -15,12 +15,12 @@
*/
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);
}
@@ -15,9 +15,8 @@
*/
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 {
@@ -26,7 +25,5 @@ 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);
}
@@ -4,7 +4,6 @@ java.lang.Runnable -> Anonymous$1
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
@@ -0,0 +1,12 @@
class PrivateMembers {
private int privateField = 0;
private void privateMethod() {
}
private static class PrivateInnerClass {
}
}
@@ -70,5 +70,9 @@ class ReferenceIndexTest : ReferenceIndexTestBase() {
fun testAnonymous() {
assertIndexOnRebuild("Anonymous.java")
}
fun testPrivateMembers() {
assertIndexOnRebuild("PrivateMembers.java")
}
}
@@ -129,6 +129,7 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
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()
}
}