mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
build javac ast index only when compilation invoked from IDE (re-fix of workaround)
This commit is contained in:
+1
-6
@@ -32,7 +32,6 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
|
||||
import org.jetbrains.jps.model.java.compiler.JavaCompilers;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -95,10 +94,6 @@ public class BackwardReferenceIndexWriter {
|
||||
myIndex.close();
|
||||
}
|
||||
|
||||
int enumerateFile(JavaFileObject file) {
|
||||
return enumeratePath(file.getName());
|
||||
}
|
||||
|
||||
synchronized LightRef.JavaLightClassRef asClassUsage(Symbol name) {
|
||||
return new LightRef.JavaLightClassRef(myIndex.getByteSeqEum().enumerate(bytes(name)));
|
||||
}
|
||||
@@ -199,7 +194,7 @@ public class BackwardReferenceIndexWriter {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized int enumeratePath(String file) {
|
||||
synchronized int enumeratePath(String file) {
|
||||
try {
|
||||
return myIndex.getFilePathEnumerator().enumerate(file);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.sun.tools.javac.code.Type;
|
||||
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.List;
|
||||
import java.util.Set;
|
||||
@@ -59,8 +58,8 @@ public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, List<JavacRefSymbol> defs) {
|
||||
final int fileId = myWriter.enumerateFile(file);
|
||||
public void registerFile(String filePath, Set<JavacRefSymbol> refs, List<JavacRefSymbol> defs) {
|
||||
final int fileId = myWriter.enumeratePath(filePath);
|
||||
int funExprId = 0;
|
||||
|
||||
final List<LightRef> definitions = new ArrayList<LightRef>(defs.size());
|
||||
|
||||
@@ -16,10 +16,8 @@
|
||||
package org.jetbrains.jps.builders.impl.java;
|
||||
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.backwardRefs.BackwardReferenceIndexWriter;
|
||||
import org.jetbrains.jps.builders.java.CannotCreateJavaCompilerException;
|
||||
import org.jetbrains.jps.builders.java.JavaCompilingTool;
|
||||
import org.jetbrains.jps.javac.JavacMain;
|
||||
@@ -86,8 +84,6 @@ public class JavacCompilerTool extends JavaCompilingTool {
|
||||
|
||||
@Override
|
||||
public void prepareCompilationTask(@NotNull JavaCompiler.CompilationTask task, @NotNull Collection<String> options) {
|
||||
if (BackwardReferenceIndexWriter.isEnabled()) {
|
||||
JavacReferencesCollector.installOn((JavacTask)task);
|
||||
}
|
||||
JavacReferencesCollector.installOn(task);
|
||||
}
|
||||
}
|
||||
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast;
|
||||
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
import com.sun.source.util.TaskListener;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
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.JavacFileReferencesRegistrar;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacRefSymbol;
|
||||
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
final class JavacReferenceCollectorListener implements TaskListener {
|
||||
private final JavacFileReferencesRegistrar[] myFullASTListeners;
|
||||
private final JavacFileReferencesRegistrar[] myOnlyImportsListeners;
|
||||
private final JavacTreeRefScanner myAstScanner;
|
||||
|
||||
private Name myAsterisk;
|
||||
|
||||
private int myRemainDeclarations;
|
||||
private JCTree.JCCompilationUnit myCurrentCompilationUnit;
|
||||
private Set<JavacRefSymbol> myCollectedReferences;
|
||||
private List<JavacRefSymbol> myCollectedDefinitions;
|
||||
|
||||
public JavacReferenceCollectorListener(JavacFileReferencesRegistrar[] fullASTListenerArray, JavacFileReferencesRegistrar[] importsListenerArray) {
|
||||
myFullASTListeners = fullASTListenerArray;
|
||||
myOnlyImportsListeners = importsListenerArray;
|
||||
myAstScanner = JavacTreeRefScanner.createASTScanner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started(TaskEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished(TaskEvent e) {
|
||||
try {
|
||||
if (e.getKind() == TaskEvent.Kind.ANALYZE) {
|
||||
// javac creates an event on each processed top level declared class not file
|
||||
if (myCurrentCompilationUnit != e.getCompilationUnit()) {
|
||||
myCurrentCompilationUnit = (JCTree.JCCompilationUnit)e.getCompilationUnit();
|
||||
myCollectedDefinitions = new ArrayList<JavacRefSymbol>();
|
||||
myCollectedReferences = new THashSet<JavacRefSymbol>();
|
||||
myRemainDeclarations = myCurrentCompilationUnit.getTypeDecls().size() - 1;
|
||||
scanImports(myCurrentCompilationUnit, myCollectedReferences);
|
||||
for(JavacFileReferencesRegistrar r: myOnlyImportsListeners) {
|
||||
r.registerFile(e.getSourceFile().getName(), myCollectedReferences, myCollectedDefinitions);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myRemainDeclarations--;
|
||||
}
|
||||
|
||||
JavacTreeScannerSink sink = new JavacTreeScannerSink() {
|
||||
@Override
|
||||
public void sinkReference(JavacRefSymbol ref) {
|
||||
myCollectedReferences.add(ref);
|
||||
}
|
||||
|
||||
@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 (myRemainDeclarations == 0) {
|
||||
if (myFullASTListeners.length != 0) {
|
||||
for (JCTree.JCAnnotation annotation : myCurrentCompilationUnit.getPackageAnnotations()) {
|
||||
myAstScanner.scan(annotation, sink);
|
||||
}
|
||||
}
|
||||
|
||||
for(JavacFileReferencesRegistrar r: myFullASTListeners) {
|
||||
r.registerFile(e.getSourceFile().getName(), myCollectedReferences, myCollectedDefinitions);
|
||||
}
|
||||
|
||||
myCurrentCompilationUnit = null;
|
||||
myCollectedDefinitions = null;
|
||||
myCollectedReferences = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ClientCodeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Name getAsteriskFromCurrentNameTable(Name tableRepresentative) {
|
||||
if (myAsterisk == null) {
|
||||
myAsterisk = tableRepresentative.table.fromChars(new char[]{'*'}, 0, 1);
|
||||
}
|
||||
return myAsterisk;
|
||||
}
|
||||
|
||||
private void scanImports(JCTree.JCCompilationUnit compilationUnit, Set<JavacRefSymbol> symbols) {
|
||||
for (JCTree.JCImport anImport : compilationUnit.getImports()) {
|
||||
final JCTree.JCFieldAccess id = (JCTree.JCFieldAccess)anImport.getQualifiedIdentifier();
|
||||
final Symbol sym = id.sym;
|
||||
if (sym == null) {
|
||||
final JCTree.JCExpression qExpr = id.getExpression();
|
||||
if (qExpr instanceof JCTree.JCFieldAccess) {
|
||||
final JCTree.JCFieldAccess classImport = (JCTree.JCFieldAccess)qExpr;
|
||||
final Symbol ownerSym = classImport.sym;
|
||||
final Name name = id.getIdentifier();
|
||||
if (name != getAsteriskFromCurrentNameTable(name)) {
|
||||
// member import
|
||||
for (Symbol memberSymbol : ownerSym.members().getElements()) {
|
||||
if (memberSymbol.getSimpleName() == name) {
|
||||
symbols.add(new JavacRefSymbol(memberSymbol, Tree.Kind.IMPORT));
|
||||
}
|
||||
}
|
||||
}
|
||||
collectClassImports(ownerSym, symbols);
|
||||
}
|
||||
} else {
|
||||
// class import
|
||||
collectClassImports(sym, symbols);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectClassImports(Symbol baseImport, Set<JavacRefSymbol> collector) {
|
||||
for (Symbol symbol = baseImport;
|
||||
symbol != null && symbol.getKind() != ElementKind.PACKAGE;
|
||||
symbol = symbol.owner) {
|
||||
collector.add(new JavacRefSymbol(symbol, Tree.Kind.IMPORT));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,29 +17,22 @@ package org.jetbrains.jps.javac.ast;
|
||||
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
import com.sun.source.util.TaskListener;
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
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.JavacFileReferencesRegistrar;
|
||||
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;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Code here should not depend on any javac private API located in tools.jar if no JavacFileReferencesRegistrar will be run.
|
||||
* A workaround to allow run standalone jps with improperly configured classloader without NoClassDefFoundError (e.g: IDEA-162877)
|
||||
*/
|
||||
public class JavacReferencesCollector {
|
||||
public static void installOn(JavacTask task) {
|
||||
public static void installOn(JavaCompiler.CompilationTask task) {
|
||||
List<JavacFileReferencesRegistrar> fullASTListeners = new SmartList<JavacFileReferencesRegistrar>();
|
||||
List<JavacFileReferencesRegistrar> onlyImportsListeners = new SmartList<JavacFileReferencesRegistrar>();
|
||||
for (JavacFileReferencesRegistrar listener : JpsServiceManager.getInstance().getExtensions(JavacFileReferencesRegistrar.class)) {
|
||||
@@ -55,149 +48,22 @@ public class JavacReferencesCollector {
|
||||
return;
|
||||
}
|
||||
|
||||
JavacTask javacTask = (JavacTask)task;
|
||||
Method addTaskMethod = ReflectionUtil.getMethod(JavacTask.class, "addTaskListener", TaskListener.class); // jdk >= 8
|
||||
if (addTaskMethod == null) {
|
||||
addTaskMethod = ReflectionUtil.getMethod(JavacTask.class, "setTaskListener", TaskListener.class); // jdk 6-7
|
||||
}
|
||||
assert addTaskMethod != null;
|
||||
|
||||
try {
|
||||
addTaskMethod.invoke(task, new MyTaskListener(fullASTListenerArray, onlyImportsListenerArray));
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class MyTaskListener implements TaskListener {
|
||||
private final JavacFileReferencesRegistrar[] myFullASTListeners;
|
||||
private final JavacFileReferencesRegistrar[] myOnlyImportsListeners;
|
||||
private final JavacTreeRefScanner myAstScanner;
|
||||
|
||||
private Name myAsterisk;
|
||||
|
||||
private int myRemainDeclarations;
|
||||
private JCTree.JCCompilationUnit myCurrentCompilationUnit;
|
||||
private Set<JavacRefSymbol> myCollectedReferences;
|
||||
private List<JavacRefSymbol> myCollectedDefinitions;
|
||||
|
||||
public MyTaskListener(JavacFileReferencesRegistrar[] fullASTListenerArray, JavacFileReferencesRegistrar[] importsListenerArray) {
|
||||
myFullASTListeners = fullASTListenerArray;
|
||||
myOnlyImportsListeners = importsListenerArray;
|
||||
myAstScanner = JavacTreeRefScanner.createASTScanner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started(TaskEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished(TaskEvent e) {
|
||||
final JavacReferenceCollectorListener taskListener = new JavacReferenceCollectorListener(fullASTListenerArray, onlyImportsListenerArray);
|
||||
if (addTaskMethod != null) {
|
||||
try {
|
||||
if (e.getKind() == TaskEvent.Kind.ANALYZE) {
|
||||
// javac creates an event on each processed top level declared class not file
|
||||
if (myCurrentCompilationUnit != e.getCompilationUnit()) {
|
||||
myCurrentCompilationUnit = (JCTree.JCCompilationUnit)e.getCompilationUnit();
|
||||
myCollectedDefinitions = new ArrayList<JavacRefSymbol>();
|
||||
myCollectedReferences = new THashSet<JavacRefSymbol>();
|
||||
myRemainDeclarations = myCurrentCompilationUnit.getTypeDecls().size() - 1;
|
||||
scanImports(myCurrentCompilationUnit, myCollectedReferences);
|
||||
for(JavacFileReferencesRegistrar r: myOnlyImportsListeners) {
|
||||
r.registerFile(e.getSourceFile(), myCollectedReferences, myCollectedDefinitions);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myRemainDeclarations--;
|
||||
}
|
||||
|
||||
JavacTreeScannerSink sink = new JavacTreeScannerSink() {
|
||||
@Override
|
||||
public void sinkReference(JavacRefSymbol ref) {
|
||||
myCollectedReferences.add(ref);
|
||||
}
|
||||
|
||||
@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 (myRemainDeclarations == 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;
|
||||
}
|
||||
|
||||
}
|
||||
addTaskMethod.invoke(task, taskListener);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ClientCodeException(ex);
|
||||
catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Name getAsteriskFromCurrentNameTable(Name tableRepresentative) {
|
||||
if (myAsterisk == null) {
|
||||
myAsterisk = tableRepresentative.table.fromChars(new char[]{'*'}, 0, 1);
|
||||
catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return myAsterisk;
|
||||
}
|
||||
|
||||
private void scanImports(JCTree.JCCompilationUnit compilationUnit, Set<JavacRefSymbol> symbols) {
|
||||
for (JCTree.JCImport anImport : compilationUnit.getImports()) {
|
||||
final JCTree.JCFieldAccess id = (JCTree.JCFieldAccess)anImport.getQualifiedIdentifier();
|
||||
final Symbol sym = id.sym;
|
||||
if (sym == null) {
|
||||
final JCTree.JCExpression qExpr = id.getExpression();
|
||||
if (qExpr instanceof JCTree.JCFieldAccess) {
|
||||
final JCTree.JCFieldAccess classImport = (JCTree.JCFieldAccess)qExpr;
|
||||
final Symbol ownerSym = classImport.sym;
|
||||
final Name name = id.getIdentifier();
|
||||
if (name != getAsteriskFromCurrentNameTable(name)) {
|
||||
// member import
|
||||
for (Symbol memberSymbol : ownerSym.members().getElements()) {
|
||||
if (memberSymbol.getSimpleName() == name) {
|
||||
symbols.add(new JavacRefSymbol(memberSymbol, Tree.Kind.IMPORT));
|
||||
}
|
||||
}
|
||||
}
|
||||
collectClassImports(ownerSym, symbols);
|
||||
}
|
||||
} else {
|
||||
// class import
|
||||
collectClassImports(sym, symbols);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectClassImports(Symbol baseImport, Set<JavacRefSymbol> collector) {
|
||||
for (Symbol symbol = baseImport;
|
||||
symbol != null && symbol.getKind() != ElementKind.PACKAGE;
|
||||
symbol = symbol.owner) {
|
||||
collector.add(new JavacRefSymbol(symbol, Tree.Kind.IMPORT));
|
||||
} else {
|
||||
// jdk 6-7
|
||||
javacTask.setTaskListener(taskListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast.api;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -25,5 +24,5 @@ public interface JavacFileReferencesRegistrar {
|
||||
|
||||
boolean onlyImports();
|
||||
|
||||
void registerFile(JavaFileObject file, Set<JavacRefSymbol> refs, List<JavacRefSymbol> defs);
|
||||
void registerFile(String filePath, Set<JavacRefSymbol> refs, List<JavacRefSymbol> defs);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user