diff --git a/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental/.idea/misc.xml index fea2212201e1..b554ebac5063 100644 --- a/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental/.idea/misc.xml @@ -42,7 +42,7 @@ - + diff --git a/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental1/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental1/.idea/misc.xml index fea2212201e1..b554ebac5063 100644 --- a/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental1/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/annotations/conservativeNonIncremental1/.idea/misc.xml @@ -42,7 +42,7 @@ - + diff --git a/java/java-tests/testData/compileServer/incremental/common/addClass/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/common/addClass/.idea/misc.xml index 9a249d2930c5..f0bcb39b3655 100644 --- a/java/java-tests/testData/compileServer/incremental/common/addClass/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/common/addClass/.idea/misc.xml @@ -6,7 +6,7 @@ http://www.w3.org/1999/xhtml - + diff --git a/java/java-tests/testData/compileServer/incremental/common/addDuplicateClass/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/common/addDuplicateClass/.idea/misc.xml index 9a249d2930c5..f0bcb39b3655 100644 --- a/java/java-tests/testData/compileServer/incremental/common/addDuplicateClass/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/common/addDuplicateClass/.idea/misc.xml @@ -6,7 +6,7 @@ http://www.w3.org/1999/xhtml - + diff --git a/java/java-tests/testData/compileServer/incremental/common/deleteClass3/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/common/deleteClass3/.idea/misc.xml index 6798096f372b..1b27cbdbd621 100644 --- a/java/java-tests/testData/compileServer/incremental/common/deleteClass3/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/common/deleteClass3/.idea/misc.xml @@ -3,7 +3,7 @@ - + diff --git a/java/java-tests/testData/compileServer/incremental/common/moveClassToAnotherRoot/.idea/misc.xml b/java/java-tests/testData/compileServer/incremental/common/moveClassToAnotherRoot/.idea/misc.xml index 9a249d2930c5..f0bcb39b3655 100644 --- a/java/java-tests/testData/compileServer/incremental/common/moveClassToAnotherRoot/.idea/misc.xml +++ b/java/java-tests/testData/compileServer/incremental/common/moveClassToAnotherRoot/.idea/misc.xml @@ -6,7 +6,7 @@ http://www.w3.org/1999/xhtml - + diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain.log b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain.log index 278d40b50f5b..d3b2f00c761e 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain.log +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain.log @@ -5,16 +5,14 @@ Compiling files: src/Server.java End of files Cleaning output files: -out/production/ConstantChain/Client.class out/production/ConstantChain/ServerClient.class End of files Compiling files: -src/Client.java src/ServerClient.java End of files Cleaning output files: -out/production/ConstantChain/Server.class +out/production/ConstantChain/Client.class End of files Compiling files: -src/Server.java -End of files +src/Client.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain1.log b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain1.log index 106fea4239c9..7ec495552877 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain1.log +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain1.log @@ -5,14 +5,16 @@ Compiling files: src/A.java End of files Cleaning output files: -out/production/ConstantChain1/A.class out/production/ConstantChain1/B.class out/production/ConstantChain1/C.class +End of files +Compiling files: +src/B.java +src/C.java +End of files +Cleaning output files: out/production/ConstantChain1/Client.class End of files Compiling files: -src/A.java -src/B.java -src/C.java src/Client.java -End of files +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain2.log b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain2.log index 7e6d45189a03..b5e323b8d9cb 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain2.log +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChain2.log @@ -7,12 +7,14 @@ src/Client.java src/Const1.java End of files Cleaning output files: -out/production/ConstantChain2/Client.class -out/production/ConstantChain2/Const1.class out/production/ConstantChain2/Const2.class End of files Compiling files: -src/Client.java -src/Const1.java src/Const2.java End of files +Cleaning output files: +out/production/ConstantChain2/Client.class +End of files +Compiling files: +src/Client.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChainMultiModule.log b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChainMultiModule.log index 39556d871b98..3abc1cc08640 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChainMultiModule.log +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/constantChainMultiModule.log @@ -5,26 +5,14 @@ Compiling files: moduleA/src/a/A.java End of files Cleaning output files: -out/production/moduleA/a/A.class -out/production/moduleA/a/AA.class -End of files -Compiling files: -moduleA/src/a/A.java -moduleA/src/a/AA.java -End of files -Cleaning output files: out/production/moduleB/b/B.class -out/production/moduleB/b/BB.class End of files Compiling files: moduleB/src/b/B.java -moduleB/src/b/BB.java End of files Cleaning output files: out/production/moduleC/c/C.class -out/production/moduleC/c/CC.class End of files Compiling files: moduleC/src/c/C.java -moduleC/src/c/CC.java -End of files +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/innerConstantChange.log b/java/java-tests/testData/compileServer/incremental/fieldProperties/innerConstantChange.log index ce8e480ec937..b85f082fb0b6 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/innerConstantChange.log +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/innerConstantChange.log @@ -7,10 +7,7 @@ src/Server.java End of files Cleaning output files: out/production/InnerConstantChange/Client.class -out/production/InnerConstantChange/Server$Inner.class -out/production/InnerConstantChange/Server.class End of files Compiling files: src/Client.java -src/Server.java -End of files +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/mutualConstants.log b/java/java-tests/testData/compileServer/incremental/fieldProperties/mutualConstants.log index e4b795d0740d..63a59264c927 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/mutualConstants.log +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/mutualConstants.log @@ -6,11 +6,19 @@ src/constants/B.java End of files Cleaning output files: out/production/MutualConstants/constants/A.class -out/production/MutualConstants/constants/B.class -out/production/MutualConstants/constants/PrintConst.class End of files Compiling files: src/constants/A.java -src/constants/B.java -src/constants/PrintConst.java End of files +Cleaning output files: +out/production/MutualConstants/constants/B.class +End of files +Compiling files: +src/constants/B.java +End of files +Cleaning output files: +out/production/MutualConstants/constants/PrintConst.class +End of files +Compiling files: +src/constants/PrintConst.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/fieldProperties/stringConstantLessAccessible.log b/java/java-tests/testData/compileServer/incremental/fieldProperties/stringConstantLessAccessible.log index 9fc937afadac..d4158da16236 100644 --- a/java/java-tests/testData/compileServer/incremental/fieldProperties/stringConstantLessAccessible.log +++ b/java/java-tests/testData/compileServer/incremental/fieldProperties/stringConstantLessAccessible.log @@ -6,9 +6,7 @@ src/Server.java End of files Cleaning output files: out/production/StringConstantLessAccessible/Client.class -out/production/StringConstantLessAccessible/Server.class End of files Compiling files: src/Client.java -src/Server.java -End of files +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependent.log b/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependent.log index 15998eaa34d8..b1234fb23593 100644 --- a/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependent.log +++ b/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependent.log @@ -6,9 +6,7 @@ src/Server.java End of files Cleaning output files: out/production/RecompileDependent/Client.class -out/production/RecompileDependent/Server.class End of files Compiling files: src/Client.java -src/Server.java -End of files +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependentTests.log b/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependentTests.log index f546b0a9b1e3..98632f5d0391 100644 --- a/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependentTests.log +++ b/java/java-tests/testData/compileServer/incremental/markDirty/recompileDependentTests.log @@ -6,15 +6,13 @@ src/Server.java End of files Cleaning output files: out/production/RecompileDependentTests/Client.class -out/production/RecompileDependentTests/Server.class End of files Compiling files: src/Client.java -src/Server.java End of files Cleaning output files: out/test/RecompileDependentTests/TestClient.class End of files Compiling files: testSrc/TestClient.java -End of files +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/packageInfo/packageInfoRecompileOnConstantChange.log b/java/java-tests/testData/compileServer/incremental/packageInfo/packageInfoRecompileOnConstantChange.log index ccef33cf3461..5450a3ff0471 100644 --- a/java/java-tests/testData/compileServer/incremental/packageInfo/packageInfoRecompileOnConstantChange.log +++ b/java/java-tests/testData/compileServer/incremental/packageInfo/packageInfoRecompileOnConstantChange.log @@ -5,12 +5,8 @@ Compiling files: src/bug/Namespace.java End of files Cleaning output files: -out/production/PackageInfoRecompileOnConstantChange/bug/Ann.class -out/production/PackageInfoRecompileOnConstantChange/bug/Namespace.class out/production/PackageInfoRecompileOnConstantChange/bug/package-info.class End of files Compiling files: -src/bug/Ann.java -src/bug/Namespace.java src/bug/package-info.java -End of files +End of files \ No newline at end of file diff --git a/jps/javac-ref-scanner-8/src/org/jetbrains/jps/javac/ast/Javac8RefScanner.java b/jps/javac-ref-scanner-8/src/org/jetbrains/jps/javac/ast/Javac8RefScanner.java index ad6faeb052d5..2c239c9b1585 100644 --- a/jps/javac-ref-scanner-8/src/org/jetbrains/jps/javac/ast/Javac8RefScanner.java +++ b/jps/javac-ref-scanner-8/src/org/jetbrains/jps/javac/ast/Javac8RefScanner.java @@ -16,6 +16,7 @@ import javax.lang.model.util.Types; */ @SuppressWarnings("unused") public class Javac8RefScanner extends JavacTreeRefScanner { + @Override public Tree visitLambdaExpression(LambdaExpressionTree node, JavacReferenceCollectorListener.ReferenceCollector refCollector) { final TypeMirror type = refCollector.getType(node); @@ -23,7 +24,7 @@ public class Javac8RefScanner extends JavacTreeRefScanner { if (types != null && type != null) { final Element element = types.asElement(type); if (element != null) { - final JavacRef.JavacElementRefBase ref = refCollector.asJavacRef(element); + final JavacRef.JavacElementRefBase ref = refCollector.asJavacRef(getCurrentEnclosingTypeElement(), element); if (ref != null) { refCollector.sinkDeclaration(new JavacDef.JavacFunExprDef(ref)); } @@ -36,14 +37,14 @@ public class Javac8RefScanner extends JavacTreeRefScanner { public Tree visitMemberReference(MemberReferenceTree node, JavacReferenceCollectorListener.ReferenceCollector refCollector) { final Element element = refCollector.getReferencedElement(node); if (element != null) { - final JavacRef.JavacElementRefBase ref = refCollector.asJavacRef(element); + final JavacRef.JavacElementRefBase ref = refCollector.asJavacRef(getCurrentEnclosingTypeElement(), element); if (ref != null) { refCollector.sinkReference(ref); } } final TypeMirror type = refCollector.getType(node); if (type != null) { - final JavacRef.JavacElementRefBase ref = refCollector.asJavacRef(refCollector.getTypeUtility().asElement(type)); + final JavacRef.JavacElementRefBase ref = refCollector.asJavacRef(getCurrentEnclosingTypeElement(), refCollector.getTypeUtility().asElement(type)); if (ref != null) { refCollector.sinkDeclaration(new JavacDef.JavacFunExprDef(ref)); } diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java index 7e61620fee33..5e026c84a64c 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/JavacMain.java @@ -223,6 +223,7 @@ public class JavacMain { } else { diagnosticConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, buildCompilerErrorMessage(e))); + throw e; } } else { diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/AbstractRefCollectorCompilerToolExtension.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/AbstractRefCollectorCompilerToolExtension.java index 279a683c9f78..589f17ab84ff 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/AbstractRefCollectorCompilerToolExtension.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/AbstractRefCollectorCompilerToolExtension.java @@ -22,7 +22,7 @@ import org.jetbrains.jps.javac.DiagnosticOutputConsumer; import org.jetbrains.jps.javac.JavaCompilerToolExtension; import org.jetbrains.jps.javac.ast.api.JavacFileData; -import javax.tools.*; +import javax.tools.JavaCompiler; import java.util.Collection; public abstract class AbstractRefCollectorCompilerToolExtension extends JavaCompilerToolExtension { @@ -32,7 +32,7 @@ public abstract class AbstractRefCollectorCompilerToolExtension extends JavaComp @NotNull Collection options, @NotNull final DiagnosticOutputConsumer diagnosticConsumer) { if (compilingTool.isCompilerTreeAPISupported() && isEnabled()) { - JavacReferenceCollector.installOn(task, divideImportsRefs(), new Consumer() { + JavacReferenceCollector.installOn(task, new Consumer() { @Override public void consume(JavacFileData data) { diagnosticConsumer.registerJavacFileData(data); @@ -42,6 +42,4 @@ public abstract class AbstractRefCollectorCompilerToolExtension extends JavaComp } protected abstract boolean isEnabled(); - - protected abstract boolean divideImportsRefs(); } diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/ExternalRefCollectorCompilerToolExtension.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/ExternalRefCollectorCompilerToolExtension.java index 57233d33ac04..51a9df6149bf 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/ExternalRefCollectorCompilerToolExtension.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/ExternalRefCollectorCompilerToolExtension.java @@ -17,15 +17,10 @@ package org.jetbrains.jps.javac.ast; public class ExternalRefCollectorCompilerToolExtension extends AbstractRefCollectorCompilerToolExtension { public static final String ENABLED_PARAM = "external.java.process.ref.collector.enabled"; - public static final String DIVIDE_IMPORTS_PARAM = "external.java.process.divide.imports"; @Override protected boolean isEnabled() { return "true".equals(System.getProperty(ENABLED_PARAM)); } - @Override - protected boolean divideImportsRefs() { - return "true".equals(System.getProperty(DIVIDE_IMPORTS_PARAM)); - } } diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollector.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollector.java index e13f8bb03963..19c87e17329a 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollector.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollector.java @@ -18,7 +18,7 @@ package org.jetbrains.jps.javac.ast; import com.intellij.util.Consumer; import org.jetbrains.jps.javac.ast.api.JavacFileData; -import javax.tools.*; +import javax.tools.JavaCompiler; /** * Code here should not depend on any javac private API located in tools.jar if no JavacFileReferencesRegistrar-s will be run. @@ -26,8 +26,7 @@ import javax.tools.*; */ public class JavacReferenceCollector { public static void installOn(JavaCompiler.CompilationTask task, - boolean divideImportRefs, Consumer fileDataConsumer) { - JavacReferenceCollectorListener.installOn(task, divideImportRefs, fileDataConsumer); + JavacReferenceCollectorListener.installOn(task, fileDataConsumer); } } 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 71f169b839d6..4d5934e2ceea 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 @@ -9,10 +9,7 @@ import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.javac.ast.api.*; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.Name; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.*; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; @@ -21,15 +18,9 @@ import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; final class JavacReferenceCollectorListener implements TaskListener { - private final static TObjectIntHashMap EMPTY_T_OBJ_INT_MAP = new TObjectIntHashMap(0); - - private final boolean myDivideImportRefs; private final Consumer myDataConsumer; private final JavacTask myJavacTask; private final JavacTreeRefScanner myAstScanner; @@ -43,9 +34,7 @@ final class JavacReferenceCollectorListener implements TaskListener { private final Map myIncompletelyProcessedFiles = new HashMap(10); - static void installOn(JavaCompiler.CompilationTask task, - boolean divideImportRefs, - Consumer dataConsumer) { + static void installOn(JavaCompiler.CompilationTask task, Consumer dataConsumer) { JavacTask javacTask = (JavacTask)task; Method addTaskMethod; // jdk >= 8 try { @@ -54,10 +43,9 @@ final class JavacReferenceCollectorListener implements TaskListener { catch (NoSuchMethodException e) { addTaskMethod = null; } - final JavacReferenceCollectorListener taskListener = new JavacReferenceCollectorListener(divideImportRefs, - dataConsumer, - javacTask, - addTaskMethod != null); + final JavacReferenceCollectorListener taskListener = new JavacReferenceCollectorListener( + dataConsumer, javacTask, addTaskMethod != null + ); if (addTaskMethod != null) { try { addTaskMethod.setAccessible(true); @@ -75,11 +63,9 @@ final class JavacReferenceCollectorListener implements TaskListener { } } - private JavacReferenceCollectorListener(boolean divideImportRefs, - Consumer dataConsumer, + private JavacReferenceCollectorListener(Consumer dataConsumer, JavacTask javacTask, boolean atLeastJdk8) { - myDivideImportRefs = divideImportRefs; myDataConsumer = dataConsumer; myJavacTask = javacTask; myAtLeastJdk8 = atLeastJdk8; @@ -133,9 +119,6 @@ final class JavacReferenceCollectorListener implements TaskListener { if (collectImportsData) { scanImports(unit, incompletelyProcessedFile.myFileData.getRefs(), incompletelyProcessedFile); - if (myDivideImportRefs) { - scanImports(unit, incompletelyProcessedFile.myFileData.getImportRefs(), incompletelyProcessedFile); - } } myAstScanner.scan(declarationToProcess, incompletelyProcessedFile); @@ -176,7 +159,7 @@ final class JavacReferenceCollectorListener implements TaskListener { // member import for (Element memberElement : myElementUtility.getAllMembers((TypeElement)ownerElement)) { if (memberElement.getSimpleName() == name) { - incrementOrAdd(elements, JavacRef.JavacElementRefBase.fromElement(memberElement, null, myNameTableCache, importProps)); + incrementOrAdd(elements, JavacRef.JavacElementRefBase.fromElement(null, memberElement, null, myNameTableCache, importProps)); } } } @@ -193,7 +176,7 @@ final class JavacReferenceCollectorListener implements TaskListener { for (Element element = baseImport; element != null && element.getKind() != ElementKind.PACKAGE; element = element.getEnclosingElement()) { - incrementOrAdd(collector, JavacRef.JavacElementRefBase.fromElement(element, null, myNameTableCache, importProps)); + incrementOrAdd(collector, JavacRef.JavacElementRefBase.fromElement(null, element, null, myNameTableCache, importProps)); } } @@ -201,18 +184,34 @@ final class JavacReferenceCollectorListener implements TaskListener { private final JavacFileData myFileData; private final JavacTreeHelper myTreeHelper; private int myRemainDeclarations; - + private final JavacRef.JavacClass myPackageInfo; + private ReferenceCollector(int remainDeclarations, String filePath, CompilationUnitTree unitTree) { myRemainDeclarations = remainDeclarations; - myFileData = new JavacFileData(filePath, - createReferenceHolder(), - myDivideImportRefs ? createReferenceHolder() : EMPTY_T_OBJ_INT_MAP, - new ArrayList(), - createDefinitionHolder(), - new THashSet()); + myFileData = new JavacFileData( + filePath, createReferenceHolder(), new ArrayList(), createDefinitionHolder(), new THashSet() + ); myTreeHelper = new JavacTreeHelper(unitTree, myTreeUtility); + + if (isPackageInfo(filePath)) { + final ExpressionTree packageName = unitTree.getPackageName(); + final String pack = packageName != null ? packageName.toString() : ""; + myPackageInfo = new JavacRef.JavacClassImpl(false, Collections.emptySet(), pack.isEmpty()? "package-info" : pack + ".package-info"); + sinkDeclaration(new JavacDef.JavacClassDef(myPackageInfo, JavacRef.EMPTY_ARRAY)); + } + else { + myPackageInfo = null; + } + } + + private boolean isPackageInfo(String filePath) { + if (filePath != null && filePath.endsWith("package-info.java")) { + final int idx = filePath.length() - "package-info.java".length() - 1; + return idx >= 0 && (filePath.charAt(idx) == '/' || filePath.charAt(idx) == File.separatorChar); + } + return false; } void sinkReference(@Nullable JavacRef.JavacElementRefBase ref) { @@ -234,21 +233,25 @@ final class JavacReferenceCollectorListener implements TaskListener { } @Nullable - JavacRef.JavacElementRefBase asJavacRef(Element element) { - return asJavacRef(element, null); + JavacRef.JavacElementRefBase asJavacRef(final Element containingClass, Element element) { + return asJavacRef(containingClass, element, null); } @Nullable - JavacRef.JavacElementRefBase asJavacRef(Element element, Element qualifier) { - return JavacRef.JavacElementRefBase.fromElement(element, qualifier, myNameTableCache); + JavacRef.JavacElementRefBase asJavacRef(final Element containingClass, Element element, Element qualifier) { + return JavacRef.JavacElementRefBase.fromElement(getContainingClassName(containingClass), element, qualifier, myNameTableCache); } @Nullable - JavacRef.JavacElementRefBase asJavacRef(TypeMirror typeMirror) { + JavacRef.JavacElementRefBase asJavacRef(final Element containingClass, TypeMirror typeMirror) { final Element element = getTypeUtility().asElement(typeMirror); - return element == null ? null : JavacRef.JavacElementRefBase.fromElement(element, null, myNameTableCache); + return element == null ? null : JavacRef.JavacElementRefBase.fromElement(getContainingClassName(containingClass), element, null, myNameTableCache); } + private String getContainingClassName(Element containingClass) { + return containingClass != null? myNameTableCache.parseBinaryName(containingClass) : myPackageInfo != null? myPackageInfo.getName() : null; + } + Element getReferencedElement(Tree tree) { return myTreeHelper.getReferencedElement(tree); } 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 73c8ea83b347..7816ffc9e8ad 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 @@ -41,7 +41,7 @@ class JavacTreeRefScanner extends TreeScanner typeElements = extractImplicitToStringCalls(lOp, rOp, collector); if (typeElements != null) { for (TypeElement element : typeElements) { - JavacRef.JavacElementRefBase ref = collector.asJavacRef(element); + JavacRef.JavacElementRefBase ref = collector.asJavacRef(getCurrentEnclosingTypeElement(), element); if (ref != null) { collector.sinkImplicitToString(ref); } @@ -151,7 +151,7 @@ class JavacTreeRefScanner extends TreeScanner modifiers = element.getModifiers(); if (!modifiers.contains(Modifier.STATIC) && !modifiers.contains(Modifier.PRIVATE)) { - TypeElement currentClass = myCurrentEnclosingElement.peek(); + final TypeElement currentClass = getCurrentEnclosingTypeElement(); TypeElement actualQualifier = findQualifier(element, currentClass); //means java.lang.Object's method called from an interface if (actualQualifier == null) { - actualQualifier = myCurrentEnclosingElement.peek(); + actualQualifier = currentClass; } - collector.sinkReference(collector.asJavacRef(element, actualQualifier)); + collector.sinkReference(collector.asJavacRef(currentClass, element, actualQualifier)); scan(node.getTypeArguments(), collector); scan(node.getArguments(), collector); return null; @@ -180,6 +180,10 @@ class JavacTreeRefScanner extends TreeScanner myCurrentEnclosingElement = new Stack(1); private final Stack myCurrentEnclosingElementOffset = new Stack(1); private final Stack myCurrentAnonymousTree = new Stack(1); @@ -199,7 +203,7 @@ class JavacTreeRefScanner extends TreeScanner myRefs; - private final TObjectIntHashMap myImportRefs; private final List myCasts; private final List myDefs; private final Set myImplicitRefs; public JavacFileData(@NotNull String path, @NotNull TObjectIntHashMap refs, - @NotNull TObjectIntHashMap importRefs, @NotNull List casts, @NotNull List defs, @NotNull Set implicitRefs) { myFilePath = path; myRefs = refs; - myImportRefs = importRefs; myCasts = casts; myDefs = defs; myImplicitRefs = implicitRefs; @@ -61,11 +58,6 @@ public class JavacFileData { return myRefs; } - @NotNull - public TObjectIntHashMap getImportRefs() { - return myImportRefs; - } - @NotNull public List getCasts() { return myCasts; @@ -83,7 +75,6 @@ public class JavacFileData { try { stream.writeUTF(getFilePath()); saveRefs(stream, getRefs()); - saveRefs(stream, getImportRefs()); saveCasts(stream, getCasts()); saveDefs(stream, getDefs()); saveImplicitToString(stream, getImplicitToStringRefs()); @@ -99,12 +90,12 @@ public class JavacFileData { @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") final DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes)); try { - return new JavacFileData(in.readUTF(), - readRefs(in), - readRefs(in), - readCasts(in), - readDefs(in), - readImplicitToString(in)); + final String path = in.readUTF(); + final TObjectIntHashMap refs = readRefs(in); + final List casts = readCasts(in); + final List defs = readDefs(in); + final Set implicitRefs = readImplicitToString(in); + return new JavacFileData(path, refs, casts, defs, implicitRefs); } catch (IOException e) { throw new RuntimeException(e); @@ -213,10 +204,13 @@ public class JavacFileData { } else if (ref instanceof JavacRef.JavacField) { out.writeByte(FIELD_MARKER); + out.writeUTF(((JavacRef.JavacField)ref).getContainingClass()); out.writeUTF(ref.getOwnerName()); + out.writeUTF(((JavacRef.JavacField)ref).getDescriptor()); } else if (ref instanceof JavacRef.JavacMethod) { out.writeByte(METHOD_MARKER); + out.writeUTF(((JavacRef.JavacMethod)ref).getContainingClass()); out.writeUTF(ref.getOwnerName()); out.write(((JavacRef.JavacMethod)ref).getParamCount()); } @@ -231,11 +225,27 @@ public class JavacFileData { final byte marker = in.readByte(); switch (marker) { case CLASS_MARKER: - return new JavacRef.JavacClassImpl(in.readBoolean(), readModifiers(in), in.readUTF()); + final boolean isAnonymous = in.readBoolean(); + final Set classModifiers = readModifiers(in); + final String className = in.readUTF(); + return new JavacRef.JavacClassImpl(isAnonymous, classModifiers, className); + case METHOD_MARKER: - return new JavacRef.JavacMethodImpl(in.readUTF(), in.readByte(), readModifiers(in), in.readUTF()); + final String methodContainingClass = in.readUTF(); + final String methodOwnerName = in.readUTF(); + final byte methodParamCount = in.readByte(); + final Set methodModifiers = readModifiers(in); + final String methodName = in.readUTF(); + return new JavacRef.JavacMethodImpl(methodContainingClass, methodOwnerName, methodParamCount, methodModifiers, methodName); + case FIELD_MARKER: - return new JavacRef.JavacFieldImpl(in.readUTF(), readModifiers(in), in.readUTF()); + final String fieldContainingClass = in.readUTF(); + final String fieldOwnerName = in.readUTF(); + final String fieldDescriptor = in.readUTF(); + final Set fieldModifiers = readModifiers(in); + final String fieldName = in.readUTF(); + return new JavacRef.JavacFieldImpl(fieldContainingClass, fieldOwnerName, fieldModifiers, fieldName, fieldDescriptor); + default: throw new IllegalStateException("unknown marker " + marker); } diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/api/JavacRef.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/api/JavacRef.java index f0c010ec8a22..745b45618b69 100644 --- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/api/JavacRef.java +++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/api/JavacRef.java @@ -19,8 +19,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.lang.model.element.*; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.*; +import javax.lang.model.util.SimpleTypeVisitor6; import java.util.Set; public interface JavacRef { @@ -61,13 +61,17 @@ public interface JavacRef { interface JavacClass extends JavacRef { boolean isAnonymous(); + boolean isPackageInfo(); } interface JavacMethod extends JavacRef { byte getParamCount(); + String getContainingClass(); } interface JavacField extends JavacRef { + String getDescriptor(); + String getContainingClass(); } abstract class JavacRefBase implements JavacRef { @@ -115,18 +119,31 @@ public interface JavacRef { public boolean isAnonymous() { return myAnonymous; } + + @Override + public boolean isPackageInfo() { + final String name = getName(); + return name.endsWith(".package-info") || "package-info".equals(name); + } } class JavacMethodImpl extends JavacRefBase implements JavacMethod { + private final String myContainingClassName; private final String myOwnerName; private final byte myParamCount; - public JavacMethodImpl(String ownerName, byte paramCount, Set modifiers, String name) { + public JavacMethodImpl(String containingClassName, String ownerName, byte paramCount, Set modifiers, String name) { super(name, modifiers); + myContainingClassName = containingClassName; myOwnerName = ownerName; myParamCount = paramCount; } + @Override + public String getContainingClass() { + return myContainingClassName; + } + @Override public byte getParamCount() { return myParamCount; @@ -140,11 +157,21 @@ public interface JavacRef { } class JavacFieldImpl extends JavacRefBase implements JavacField { - private final String myOwnerName; - public JavacFieldImpl(String ownerName, Set modifiers, String name) { + private final String myContainingClassName; + private final String myOwnerName; + private final String myDescriptor; + + public JavacFieldImpl(String containingClassName, String ownerName, Set modifiers, String name, String descriptor) { super(name, modifiers); + myContainingClassName = containingClassName; myOwnerName = ownerName; + myDescriptor = descriptor; + } + + @Override + public String getContainingClass() { + return myContainingClassName; } @NotNull @@ -152,6 +179,11 @@ public interface JavacRef { public String getOwnerName() { return myOwnerName; } + + @Override + public String getDescriptor() { + return myDescriptor; + } } abstract class JavacElementRefBase implements JavacRef { @@ -191,12 +223,12 @@ public interface JavacRef { } @Nullable - public static JavacElementRefBase fromElement(Element element, Element qualifier, JavacNameTable nameTableCache) { - return fromElement(element, qualifier, nameTableCache, null); + public static JavacElementRefBase fromElement(final String containingClass, Element element, Element qualifier, JavacNameTable nameTableCache) { + return fromElement(containingClass, element, qualifier, nameTableCache, null); } @Nullable - public static JavacElementRefBase fromElement(Element element, Element qualifier, JavacNameTable nameTableCache, @Nullable ImportProperties importProps) { + public static JavacElementRefBase fromElement(final String containigClass, Element element, Element qualifier, JavacNameTable nameTableCache, @Nullable ImportProperties importProps) { if (qualifier != null) { TypeMirror type = qualifier.asType(); if (!isValidType(type)) { @@ -208,11 +240,11 @@ public interface JavacRef { } else if (element instanceof VariableElement) { if (qualifier == null && !checkEnclosingElement(element)) return null; - return new JavacElementFieldImpl(element, qualifier, nameTableCache, importProps); + return new JavacElementFieldImpl(containigClass, element, qualifier, nameTableCache, importProps); } else if (element instanceof ExecutableElement) { if (qualifier == null && !checkEnclosingElement(element)) return null; - return new JavacElementMethodImpl(element, qualifier, nameTableCache, importProps); + return new JavacElementMethodImpl(containigClass, element, qualifier, nameTableCache, importProps); } else if (element == null || element.getKind() == ElementKind.OTHER || element.getKind() == ElementKind.TYPE_PARAMETER) { // javac reserved symbol kind (e.g: com.sun.tools.javac.comp.Resolve.ResolveError) @@ -270,11 +302,24 @@ public interface JavacRef { public boolean isAnonymous() { return myNameTableCache.parseName(myOriginalElement.getSimpleName()).isEmpty(); } + + @Override + public boolean isPackageInfo() { + return false; + } } class JavacElementMethodImpl extends JavacElementRefBase implements JavacMethod { - public JavacElementMethodImpl(@NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache, final ImportProperties importProps) { + private final String myContainingClass; + + public JavacElementMethodImpl(String containingClass, @NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache, final ImportProperties importProps) { super(element, qualifier, nameTableCache, importProps); + myContainingClass = containingClass; + } + + @Override + public String getContainingClass() { + return myContainingClass; } @Override @@ -284,8 +329,51 @@ public interface JavacRef { } class JavacElementFieldImpl extends JavacElementRefBase implements JavacField { - public JavacElementFieldImpl(@NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache, final ImportProperties importProps) { + private final String myContainingClass; + + public JavacElementFieldImpl(String containingClass, @NotNull Element element, @Nullable Element qualifier, JavacNameTable nameTableCache, final ImportProperties importProps) { super(element, qualifier, nameTableCache, importProps); + myContainingClass = containingClass; + } + + @Override + public String getContainingClass() { + return myContainingClass; + } + + @Override + public String getDescriptor() { + return calcDescriptor(myOriginalElement.asType()); + } + + private String calcDescriptor(TypeMirror type) { + return new SimpleTypeVisitor6(null) { + @Override + public String visitPrimitive(PrimitiveType t, Void aVoid) { + switch(t.getKind()) { + case BYTE: return "B"; + case CHAR: return "C"; + case DOUBLE: return "D"; + case FLOAT: return "F"; + case INT: return "I"; + case LONG:return "J"; + case SHORT: return "S"; + case BOOLEAN: return "Z"; + } + return null; + } + + @Override + public String visitArray(ArrayType t, Void aVoid) { + return "[" + visit(t.getComponentType()); + } + + @Override + public String visitDeclared(DeclaredType t, Void aVoid) { + return "L" + myNameTableCache.parseBinaryName(t.asElement()).replace('.', '/') + ";"; + } + + }.visit(type); } } } diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar index 70083620e39a..20bc7ac92604 100644 --- a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar +++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar @@ -14,4 +14,4 @@ # limitations under the License. # org.jetbrains.jps.backwardRefs.JavaBackwardReferenceRegistrar -org.jetbrains.jps.incremental.java.ImportReferencesRegistrar +org.jetbrains.jps.incremental.java.JpsReferenceDependenciesRegistrar diff --git a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/JavaBackwardReferenceRegistrar.java b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/JavaBackwardReferenceRegistrar.java index 2617855dd331..86a0bd6d2081 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/JavaBackwardReferenceRegistrar.java +++ b/jps/jps-builders/src/org/jetbrains/jps/backwardRefs/JavaBackwardReferenceRegistrar.java @@ -23,12 +23,8 @@ public class JavaBackwardReferenceRegistrar implements JavacFileReferencesRegist return JavaBackwardReferenceIndexWriter.isEnabled() && JavaBackwardReferenceIndexWriter.getInstance() != null; } + @SuppressWarnings("unchecked") @Override - public boolean onlyImports() { - return false; - } - - @Override public void registerFile(CompileContext context, String filePath, TObjectIntHashMap refs, Collection defs, diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java index 50506329345d..24f9aef08931 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java @@ -27,10 +27,36 @@ import java.util.concurrent.Future; */ public class Callbacks { + public interface ConstantRef { + String getOwner(); + String getName(); + String getDescriptor(); + } + public interface Backend { void associate(String classFileName, String sourceFileName, ClassReader cr); void associate(String classFileName, Collection sources, ClassReader cr); void registerImports(String className, Collection classImports, Collection staticImports); + void registerConstantReferences(String className, Collection cRefs); + } + + public static ConstantRef createConstantReference(String ownerClass, String fieldName, String descriptor) { + return new ConstantRef() { + @Override + public String getOwner() { + return ownerClass; + } + + @Override + public String getName() { + return fieldName; + } + + @Override + public String getDescriptor() { + return descriptor; + } + }; } public static class ConstantAffection { diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java index d6b7d8e78633..b74902fad51d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java @@ -28,6 +28,7 @@ public class ClassRepr extends ClassFileRepr { private final int myOuterClassName; private final boolean myIsLocal; private final boolean myIsAnonymous; + private boolean myHasInlinedConstants; public Set getMethods() { return myMethods; @@ -49,6 +50,14 @@ public class ClassRepr extends ClassFileRepr { return myIsAnonymous; } + public boolean hasInlinedConstants() { + return myHasInlinedConstants; + } + + public void setHasInlinedConstants(boolean hasConstants) { + myHasInlinedConstants = hasConstants; + } + public TypeRepr.ClassType getSuperClass() { return mySuperClass; } @@ -106,10 +115,13 @@ public class ClassRepr extends ClassFileRepr { if (!mySuperClass.equals(pastClass.mySuperClass)) { base |= Difference.SUPERCLASS; } - if (!getUsages().equals(pastClass.getUsages())) { base |= Difference.USAGES; } + if (hasInlinedConstants() != pastClass.hasInlinedConstants()) { + base |= Difference.CONSTANT_REFERENCES; + } + final int d = base; return new Diff(diff) { @@ -244,6 +256,7 @@ public class ClassRepr extends ClassFileRepr { int flags = DataInputOutputUtil.readINT(in); myIsLocal = (flags & LOCAL_MASK) != 0; myIsAnonymous = (flags & ANONYMOUS_MASK) != 0; + myHasInlinedConstants = (flags & HAS_INLINED_CONSTANTS_MASK) != 0; } catch (IOException e) { throw new BuildDataCorruptedException(e); @@ -252,6 +265,7 @@ public class ClassRepr extends ClassFileRepr { private static final int LOCAL_MASK = 1; private static final int ANONYMOUS_MASK = 2; + private static final int HAS_INLINED_CONSTANTS_MASK = 4; @Override public void save(final DataOutput out) { @@ -264,7 +278,9 @@ public class ClassRepr extends ClassFileRepr { RW.save(myAnnotationTargets, UsageRepr.AnnotationUsage.elementTypeExternalizer, out); RW.writeUTF(out, myRetentionPolicy == null ? "" : myRetentionPolicy.toString()); DataInputOutputUtil.writeINT(out, myOuterClassName); - DataInputOutputUtil.writeINT(out, (myIsLocal ? LOCAL_MASK:0) | (myIsAnonymous ? ANONYMOUS_MASK : 0)); + DataInputOutputUtil.writeINT( + out, (myIsLocal ? LOCAL_MASK:0) | (myIsAnonymous ? ANONYMOUS_MASK : 0) | (myHasInlinedConstants ? HAS_INLINED_CONSTANTS_MASK : 0) + ); } catch (IOException e) { throw new BuildDataCorruptedException(e); @@ -380,6 +396,8 @@ public class ClassRepr extends ClassFileRepr { stream.println(myIsLocal); stream.print(" Anonymous class: "); stream.println(myIsAnonymous); + stream.print(" Has inlined constants: "); + stream.println(myHasInlinedConstants); stream.println(" Fields:"); final FieldRepr[] fs = myFields.toArray(new FieldRepr[0]); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java index 8763a6f36f1b..5a7e474f47e4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java @@ -29,6 +29,7 @@ public abstract class Difference { public static final int SUPERCLASS = 16; public static final int USAGES = 32; public static final int ANNOTATIONS = 64; + public static final int CONSTANT_REFERENCES = 128; public interface Specifier { Collection added(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java index 3258e47baf37..8589b408f505 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.io.PrintStream; import java.lang.annotation.RetentionPolicy; import java.util.*; -import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.function.Supplier; @@ -33,6 +32,8 @@ import java.util.function.Supplier; */ public class Mappings { private final static Logger LOG = Logger.getInstance(Mappings.class); + public static final String PROCESS_CONSTANTS_NON_INCREMENTAL_PROPERTY = "compiler.process.constants.non.incremental"; + private final boolean myProcessConstantsIncrementally = !Boolean.valueOf(System.getProperty(PROCESS_CONSTANTS_NON_INCREMENTAL_PROPERTY, "false")); private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab"; private final static String CLASS_TO_CLASS = "classToClass.tab"; @@ -1012,7 +1013,7 @@ public class Mappings { } private class Differential { - private static final int DESPERATE_MASK = Opcodes.ACC_FINAL; + private static final int INLINABLE_FIELD_MODIFIERS_MASK = Opcodes.ACC_FINAL; final Mappings myDelta; final Collection myFilesToCompile; @@ -1021,8 +1022,6 @@ public class Mappings { final Collection myAffectedFiles; @Nullable final DependentFilesFilter myFilter; - @Nullable final Callbacks.ConstantAffectionResolver myConstantSearch; - final DelayedWorks myDelayedWorks; final Util myFuture; final Util myPresent; @@ -1032,90 +1031,6 @@ public class Mappings { private final Iterable myAnnotationChangeTracker = JpsServiceManager.getInstance().getExtensions(AnnotationsChangeTracker.class); - private class DelayedWorks { - class Triple { - final int owner; - final FieldRepr field; - @Nullable - final Future affection; - - private Triple(final int owner, final FieldRepr field, @Nullable final Future affection) { - this.owner = owner; - this.field = field; - this.affection = affection; - } - - Callbacks.ConstantAffection getAffection() { - try { - return affection != null ? affection.get() : Callbacks.ConstantAffection.EMPTY; - } - catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - final Collection myQueue = new LinkedList<>(); - - void addConstantWork(final int ownerClass, final FieldRepr changedField, final boolean isRemoved, boolean accessChanged) { - final Future future; - if (myConstantSearch == null) { - future = null; - } - else { - final String className = myContext.getValue(ownerClass); - final String fieldName = myContext.getValue(changedField.name); - future = myConstantSearch.request(className.replace('/', '.'), fieldName, changedField.access, isRemoved, accessChanged); - } - myQueue.add(new Triple(ownerClass, changedField, future)); - } - - boolean doWork(@NotNull final Collection affectedFiles) { - if (!myQueue.isEmpty()) { - debug("Starting delayed works."); - - for (final Triple t : myQueue) { - final Callbacks.ConstantAffection affection = t.getAffection(); - - debug("Class: ", t.owner); - debug("Field: ", t.field.name); - - if (!affection.isKnown()) { - if (myConstantSearch != null) { - debug("No external dependency information available."); - } - else { - debug("Constant search service not available."); - } - debug("Trying to soften non-incremental decision."); - if (!incrementalDecision(t.owner, t.field, affectedFiles, myFilesToCompile, myFilter)) { - debug("No luck."); - debug("End of delayed work, returning false."); - return false; - } - } - else { - debug("External dependency information retrieved."); - final Collection files = affection.getAffectedFiles(); - if (myFilter == null) { - affectedFiles.addAll(files); - } - else { - for (File file : files) { - if (myFilter.accept(file)) { - affectedFiles.add(file); - } - } - } - } - } - - debug("End of delayed work, returning true."); - } - return true; - } - } - private class FileClasses { final File myFileName; final Set myFileClasses = new THashSet<>(); @@ -1157,31 +1072,20 @@ public class Mappings { this.myCompiledWithErrors = null; this.myAffectedFiles = null; this.myFilter = null; - this.myConstantSearch = null; - - myDelayedWorks = null; - myFuture = null; myPresent = null; - myEasyMode = true; - delta.myIsRebuild = true; } private Differential(final Mappings delta, final Collection removed, final Collection filesToCompile) { delta.myRemovedFiles = removed; - this.myDelta = delta; this.myFilesToCompile = filesToCompile; this.myCompiledFiles = null; this.myCompiledWithErrors = null; this.myAffectedFiles = null; this.myFilter = null; - this.myConstantSearch = null; - - myDelayedWorks = null; - myFuture = new Util(delta); myPresent = new Util(); myEasyMode = true; @@ -1193,8 +1097,7 @@ public class Mappings { final Collection compiledWithErrors, final Collection compiledFiles, final Collection affectedFiles, - @NotNull final DependentFilesFilter filter, - @Nullable final Callbacks.ConstantAffectionResolver constantSearch) { + @NotNull final DependentFilesFilter filter) { delta.myRemovedFiles = removed; this.myDelta = delta; @@ -1203,9 +1106,6 @@ public class Mappings { this.myCompiledWithErrors = compiledWithErrors; this.myAffectedFiles = affectedFiles; this.myFilter = filter; - this.myConstantSearch = constantSearch; - - myDelayedWorks = new DelayedWorks(); myFuture = new Util(delta); myPresent = new Util(); @@ -1755,17 +1655,11 @@ public class Mappings { for (final FieldRepr f : removed) { debug("Field: ", f.name); - if (!f.isPrivate() && (f.access & DESPERATE_MASK) == DESPERATE_MASK && f.hasValue()) { + if (!myProcessConstantsIncrementally && !f.isPrivate() && (f.access & INLINABLE_FIELD_MODIFIERS_MASK) == INLINABLE_FIELD_MODIFIERS_MASK && f.hasValue()) { debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested"); - if (myConstantSearch != null) { - assert myDelayedWorks != null; - myDelayedWorks.addConstantWork(it.name, f, true, false); - } - else { - if (!incrementalDecision(it.name, f, myAffectedFiles, myFilesToCompile, myFilter)) { - debug("End of Differentiate, returning false"); - return false; - } + if (!incrementalDecision(it.name, f, myAffectedFiles, myFilesToCompile, myFilter)) { + debug("End of Differentiate, returning false"); + return false; } } @@ -1788,6 +1682,7 @@ public class Mappings { } debug("Processing changed fields:"); assert myFuture != null; + assert myPresent != null; for (final Pair f : changed) { final Difference d = f.second; @@ -1795,8 +1690,10 @@ public class Mappings { debug("Field: ", field.name); + final Supplier propagated = lazy(()-> myFuture.propagateFieldAccess(field.name, it.name)); + // only if the field was a compile-time constant - if (!field.isPrivate() && (field.access & DESPERATE_MASK) == DESPERATE_MASK && d.hadValue()) { + if (!field.isPrivate() && (field.access & INLINABLE_FIELD_MODIFIERS_MASK) == INLINABLE_FIELD_MODIFIERS_MASK && d.hadValue()) { final int changedModifiers = d.addedModifiers() | d.removedModifiers(); final boolean harmful = (changedModifiers & (Opcodes.ACC_STATIC | Opcodes.ACC_FINAL)) != 0; final boolean accessChanged = (changedModifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) != 0; @@ -1804,12 +1701,12 @@ public class Mappings { final boolean valueChanged = (d.base() & Difference.VALUE) != 0; if (harmful || valueChanged || becameLessAccessible) { - debug("Inline field changed it's access or value => a switch to non-incremental mode requested"); - if (myConstantSearch != null) { - assert myDelayedWorks != null; - myDelayedWorks.addConstantWork(it.name, field, false, accessChanged); + if (myProcessConstantsIncrementally) { + debug("Potentially inlined field changed it's access or value => affecting field usages"); + myFuture.affectFieldUsages(field, propagated.get(), field.createUsage(myContext, it.name), state.myAffectedUsages, state.myDependants); } else { + debug("Potentially inlined field changed it's access or value => a switch to non-incremental mode requested"); if (!incrementalDecision(it.name, field, myAffectedFiles, myFilesToCompile, myFilter)) { debug("End of Differentiate, returning false"); return false; @@ -1819,7 +1716,6 @@ public class Mappings { } if (d.base() != Difference.NONE) { - final Supplier propagated = lazy(()-> myFuture.propagateFieldAccess(field.name, it.name)); if ((d.base() & Difference.TYPE) != 0 || (d.base() & Difference.SIGNATURE) != 0) { debug("Type or signature changed --- affecting field usages"); @@ -2289,7 +2185,7 @@ public class Mappings { } private void processDependentFile(int depClass, @NotNull File depFile) { - if (myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) { + if (myAffectedFiles.contains(depFile)) { return; } @@ -2299,7 +2195,12 @@ public class Mappings { if (repr == null) { return; } - + if (repr instanceof ClassRepr && !((ClassRepr)repr).hasInlinedConstants() && myCompiledFiles.contains(depFile)) { + // Classes containing inlined constants from other classes and compiled against older constant values + // may need to be recompiled several times within a compile session. + // Otherwise it is safe to skip the file if it has already been compiled in this session. + return; + } final Set depUsages = repr.getUsages(); if (depUsages == null || depUsages.isEmpty()) { return; @@ -2432,7 +2333,7 @@ public class Mappings { return false; } assert myAffectedFiles != null; - assert myDelayedWorks != null; + //assert myDelayedWorks != null; final Collection removed = myDelta.myRemovedFiles; if (removed != null) { @@ -2440,7 +2341,7 @@ public class Mappings { myAffectedFiles.remove(new File(r)); } } - return myDelayedWorks.doWork(myAffectedFiles); + return true/*myDelayedWorks.doWork(myAffectedFiles)*/; } finally { if (myFilesToCompile != null) { @@ -2587,7 +2488,7 @@ public class Mappings { final Collection affectedFiles, @NotNull final DependentFilesFilter filter, @Nullable final Callbacks.ConstantAffectionResolver constantSearch) { - return new Differential(delta, removed, filesToCompile, compiledWithErrors, compiledFiles, affectedFiles, filter, constantSearch).differentiate(); + return new Differential(delta, removed, filesToCompile, compiledWithErrors, compiledFiles, affectedFiles, filter).differentiate(); } private void cleanupBackDependency(final int className, @Nullable Set usages, final IntIntMultiMaplet buffer) { @@ -2854,6 +2755,9 @@ public class Mappings { public Callbacks.Backend getCallback() { return new Callbacks.Backend() { + // className -> {imports; static_imports} + private final Map, Collection>> myImportRefs = Collections.synchronizedMap(new HashMap<>()); + private final Map> myConstantRefs = Collections.synchronizedMap(new HashMap<>()); @Override public void associate(String classFileName, Collection sources, ClassReader cr) { @@ -2864,6 +2768,20 @@ public class Mappings { // since java9 'repr' can represent either a class or a compiled module-info.java final int className = result.name; + if (result instanceof ClassRepr) { + final ClassRepr classRepr = (ClassRepr)result; + final String classNameStr = myContext.getValue(className); + if (addConstantUsages(classRepr, myConstantRefs.remove(classNameStr))) { + // Important: should register constants before imports, because imports can produce additional + // field references too and addConstantUsages may return false in this case + classRepr.setHasInlinedConstants(true); + } + final Pair, Collection> imports = myImportRefs.remove(classNameStr); + if (imports != null) { + addImportUsages(classRepr, imports.getFirst(), imports.getSecond()); + } + } + for (String sourceFileName : sources) { String relative = myRelativizer.toRelative(sourceFileName); myClassToRelativeSourceFilePath.put(className, relative); @@ -2893,47 +2811,61 @@ public class Mappings { @Override public void registerImports(String className, Collection classImports, Collection staticImports) { + final String key = className.replace('.', '/'); if (!classImports.isEmpty() || !staticImports.isEmpty()) { - myPostPasses.offer(() -> { - final int rootClassName = myContext.get(className.replace(".", "/")); - final Collection files = classToSourceFileGet(rootClassName); - final ClassRepr repr = files != null && !files.isEmpty()? getClassReprByName(files.iterator().next(), rootClassName) : null; - boolean usageAdded = false; - - for (final String anImport : classImports) { - if (!anImport.endsWith(IMPORT_WILDCARD_SUFFIX)) { - final int iname = myContext.get(anImport.replace('.', '/')); - myClassToClassDependency.put(iname, rootClassName); - usageAdded |= repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname)); - } - } - - for (String anImport : staticImports) { - if (anImport.endsWith(IMPORT_WILDCARD_SUFFIX)) { - final int iname = myContext.get(anImport.substring(0, anImport.length() - IMPORT_WILDCARD_SUFFIX.length()).replace('.', '/')); - myClassToClassDependency.put(iname, rootClassName); - usageAdded |= repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname)); - usageAdded |= repr != null && repr.addUsage(UsageRepr.createImportStaticOnDemandUsage(myContext, iname)); - } - else { - final int i = anImport.lastIndexOf('.'); - if (i > 0 && i < anImport.length() - 1) { - final int iname = myContext.get(anImport.substring(0, i).replace('.', '/')); - final int memberName = myContext.get(anImport.substring(i+1)); - myClassToClassDependency.put(iname, rootClassName); - usageAdded |= repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname)); - usageAdded |= repr != null && repr.addUsage(UsageRepr.createImportStaticMemberUsage(myContext, memberName, iname)); - } - } - } - - if (usageAdded) { - for (File file : files) { - myRelativeSourceFilePathToClasses.put(toRelative(file), repr); - } - } - }); + myImportRefs.put(key, Pair.create(classImports, staticImports)); } + else { + myImportRefs.remove(key); + } + } + + @Override + public void registerConstantReferences(String className, Collection cRefs) { + final String key = className.replace('.', '/'); + if (!cRefs.isEmpty()) { + myConstantRefs.put(key, cRefs); + } + else { + myConstantRefs.remove(key); + } + } + + private void addImportUsages(ClassRepr repr, Collection classImports, Collection staticImports) { + for (final String anImport : classImports) { + if (!anImport.endsWith(IMPORT_WILDCARD_SUFFIX)) { + repr.addUsage(UsageRepr.createClassUsage(myContext, myContext.get(anImport.replace('.', '/')))); + } + } + for (String anImport : staticImports) { + if (anImport.endsWith(IMPORT_WILDCARD_SUFFIX)) { + final int iname = myContext.get(anImport.substring(0, anImport.length() - IMPORT_WILDCARD_SUFFIX.length()).replace('.', '/')); + repr.addUsage(UsageRepr.createClassUsage(myContext, iname)); + repr.addUsage(UsageRepr.createImportStaticOnDemandUsage(myContext, iname)); + } + else { + final int i = anImport.lastIndexOf('.'); + if (i > 0 && i < anImport.length() - 1) { + final int iname = myContext.get(anImport.substring(0, i).replace('.', '/')); + final int memberName = myContext.get(anImport.substring(i+1)); + repr.addUsage(UsageRepr.createClassUsage(myContext, iname)); + repr.addUsage(UsageRepr.createImportStaticMemberUsage(myContext, memberName, iname)); + } + } + } + } + + private boolean addConstantUsages(ClassRepr repr, Collection cRefs) { + boolean addedNewUsages = false; + if (cRefs != null) { + for (Callbacks.ConstantRef ref : cRefs) { + final int owner = myContext.get(ref.getOwner().replace('.', '/')); + if (repr.name != owner) { + addedNewUsages |= repr.addUsage(UsageRepr.createFieldUsage(myContext, myContext.get(ref.getName()), owner, myContext.get(ref.getDescriptor()))); + } + } + } + return addedNewUsages; } }; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index 769d019fdc7e..9c78f3b56e37 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -59,7 +59,7 @@ final class BuildSession implements Runnable, CanceledStatus { private volatile long myLastEventOrdinal; private volatile ProjectDescriptor myProjectDescriptor; private final Map, ConstantSearchFuture> mySearchTasks = Collections.synchronizedMap(new HashMap<>()); - private final ConstantSearch myConstantSearch = new ConstantSearch(); + private final ConstantSearch myConstantSearch = null/*new ConstantSearch()*/; @NotNull private final BuildRunner myBuildRunner; private final boolean myForceModelLoading; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ImportReferencesRegistrar.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ImportReferencesRegistrar.java deleted file mode 100644 index 96e044a84741..000000000000 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ImportReferencesRegistrar.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package org.jetbrains.jps.incremental.java; - -import gnu.trove.TObjectIntHashMap; -import org.jetbrains.jps.builders.java.JavaBuilderUtil; -import org.jetbrains.jps.builders.java.dependencyView.Callbacks; -import org.jetbrains.jps.incremental.CompileContext; -import org.jetbrains.jps.javac.ast.api.JavacDef; -import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar; -import org.jetbrains.jps.javac.ast.api.JavacRef; -import org.jetbrains.jps.javac.ast.api.JavacTypeCast; - -import java.util.*; - -public class ImportReferencesRegistrar implements JavacFileReferencesRegistrar { - @Override - public void initialize() { - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public boolean onlyImports() { - return true; - } - - @Override - public void registerFile(CompileContext context, - String filePath, - TObjectIntHashMap refs, - Collection defs, - Collection casts, - Collection implicitToString) { - if (refs.isEmpty() || defs.isEmpty()) { - return; - } - final Set classImports = new HashSet<>(); - final Set staticImports = new HashSet<>(); - for (Object key : refs.keys()) { - final JavacRef ref = (JavacRef)key; - if (ref instanceof JavacRef.JavacClass) { - classImports.add(ref.getName()); - final JavacRef.ImportProperties props = ref.getImportProperties(); - if (props != null && props.isStatic() && props.isOnDemand()) { - staticImports.add(ref.getName() + ".*"); - } - } - else { - if (ref instanceof JavacRef.JavacField || ref instanceof JavacRef.JavacMethod) { - staticImports.add(ref.getOwnerName() + "." + ref.getName()); - } - } - } - final List definedClasses = new ArrayList<>(); - for (JavacDef def : defs) { - if (def instanceof JavacDef.JavacClassDef) { - final JavacRef element = def.getDefinedElement(); - if (element instanceof JavacRef.JavacClass) { - definedClasses.add(element.getName()); - } - } - } - if (!definedClasses.isEmpty() && (!classImports.isEmpty() || !staticImports.isEmpty())) { - final Callbacks.Backend deps = JavaBuilderUtil.getDependenciesRegistrar(context); - for (String aClass : definedClasses) { - deps.registerImports(aClass, classImports, staticImports); - } - } - } -} \ No newline at end of file diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 4cc1606ad84a..564b9fdeaede 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -1139,7 +1139,7 @@ public class JavaBuilder extends ModuleLevelBuilder { @Override public void registerJavacFileData(JavacFileData data) { for (JavacFileReferencesRegistrar registrar : myRegistrars) { - registrar.registerFile(myContext, data.getFilePath(), registrar.onlyImports() ? data.getImportRefs() : data.getRefs(), data.getDefs(), data.getCasts(), data.getImplicitToStringRefs()); + registrar.registerFile(myContext, data.getFilePath(), data.getRefs(), data.getDefs(), data.getCasts(), data.getImplicitToStringRefs()); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JpsReferenceDependenciesRegistrar.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JpsReferenceDependenciesRegistrar.java new file mode 100644 index 000000000000..66335092dd11 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JpsReferenceDependenciesRegistrar.java @@ -0,0 +1,98 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.jps.incremental.java; + +import gnu.trove.TObjectIntHashMap; +import org.jetbrains.jps.builders.java.JavaBuilderUtil; +import org.jetbrains.jps.builders.java.dependencyView.Callbacks; +import org.jetbrains.jps.incremental.CompileContext; +import org.jetbrains.jps.javac.ast.api.JavacDef; +import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar; +import org.jetbrains.jps.javac.ast.api.JavacRef; +import org.jetbrains.jps.javac.ast.api.JavacTypeCast; + +import javax.lang.model.element.Modifier; +import java.util.*; + +/** + * register dependencies that are not discoverable from bytecode: + * - references caused by import statements + * - references to fields initialized with compile-time constant values. Such values can be inlined into referencing bytecode + */ +public class JpsReferenceDependenciesRegistrar implements JavacFileReferencesRegistrar { + @Override + public void initialize() { + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public void registerFile(CompileContext context, + String filePath, + TObjectIntHashMap refs, + Collection defs, + Collection casts, + Collection implicitToString) { + final Set definedClasses = new HashSet<>(); + for (JavacDef def : defs) { + if (def instanceof JavacDef.JavacClassDef) { + final JavacRef element = def.getDefinedElement(); + if (element instanceof JavacRef.JavacClass) { + definedClasses.add(element.getName()); + } + } + } + if (definedClasses.isEmpty()) { + return; + } + if (!refs.isEmpty()) { + final Set classImports = new HashSet<>(); + final Set staticImports = new HashSet<>(); + final Map> cRefs = new HashMap<>(); + refs.forEachKey(ref -> { + final JavacRef.ImportProperties importProps = ref.getImportProperties(); + if (importProps != null) { // the reference comes from import list + if (ref instanceof JavacRef.JavacClass) { + classImports.add(ref.getName()); + if (importProps.isStatic() && importProps.isOnDemand()) { + staticImports.add(ref.getName() + ".*"); + } + } + else { + if (ref instanceof JavacRef.JavacField || ref instanceof JavacRef.JavacMethod) { + staticImports.add(ref.getOwnerName() + "." + ref.getName()); + } + } + } + else if (ref instanceof JavacRef.JavacField && ref.getModifiers().contains(Modifier.FINAL)) { + final JavacRef.JavacField fieldRef = (JavacRef.JavacField)ref; + final String descriptor = fieldRef.getDescriptor(); + if (descriptor != null && definedClasses.contains(fieldRef.getContainingClass()) && !definedClasses.contains(fieldRef.getOwnerName())) { + List refsList = cRefs.get(fieldRef.getContainingClass()); + if (refsList == null) { + refsList = new ArrayList<>(); + cRefs.put(fieldRef.getContainingClass(), refsList); + } + refsList.add(Callbacks.createConstantReference(fieldRef.getOwnerName(), fieldRef.getName(), descriptor)); + } + } + return true; + }); + if (!classImports.isEmpty() || !staticImports.isEmpty()) { + final Callbacks.Backend reg = JavaBuilderUtil.getDependenciesRegistrar(context); + for (String aClass : definedClasses) { + reg.registerImports(aClass, classImports, staticImports); + } + } + if (!cRefs.isEmpty()) { + final Callbacks.Backend reg = JavaBuilderUtil.getDependenciesRegistrar(context); + for (String aClass : definedClasses) { + final List classCRefs = cRefs.get(aClass); + reg.registerConstantReferences(aClass, classCRefs != null? classCRefs : Collections.emptyList()); + } + } + } + } +} \ No newline at end of file diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/ast/InProcessRefCollectorCompilerToolExtension.java b/jps/jps-builders/src/org/jetbrains/jps/javac/ast/InProcessRefCollectorCompilerToolExtension.java index 16520fa46809..0746b64b39c4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/ast/InProcessRefCollectorCompilerToolExtension.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/ast/InProcessRefCollectorCompilerToolExtension.java @@ -28,15 +28,4 @@ public class InProcessRefCollectorCompilerToolExtension extends AbstractRefColle } } - @Override - protected boolean divideImportsRefs() { - if (hasServiceManager()) { - for (JavacFileReferencesRegistrar registrar : JpsServiceManager.getInstance().getExtensions(JavacFileReferencesRegistrar.class)) { - if (registrar.isEnabled() && registrar.onlyImports()) { - return true; - } - } - } - return false; - } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/ast/ReferenceCollectorExternalJavacOptionsProvider.java b/jps/jps-builders/src/org/jetbrains/jps/javac/ast/ReferenceCollectorExternalJavacOptionsProvider.java index af5050b42cf2..a5f567079cd9 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/ast/ReferenceCollectorExternalJavacOptionsProvider.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/ast/ReferenceCollectorExternalJavacOptionsProvider.java @@ -22,52 +22,25 @@ import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar; import org.jetbrains.jps.model.java.compiler.JavaCompilers; import org.jetbrains.jps.service.JpsServiceManager; -import java.util.ArrayList; import java.util.Collection; -import java.util.List; +import java.util.Collections; public class ReferenceCollectorExternalJavacOptionsProvider implements ExternalJavacOptionsProvider { @NotNull @Override public Collection getOptions(@NotNull JavaCompilingTool tool) { - List options = new ArrayList<>(2); if (tool.getId().equals(JavaCompilers.JAVAC_ID)) { - final JavacReferenceCollectorOptions - javacReferenceCollectorOptions = new JavacReferenceCollectorOptions(); - options.add("-D" + ExternalRefCollectorCompilerToolExtension.ENABLED_PARAM + "=" + javacReferenceCollectorOptions.isEnabled()); - if (javacReferenceCollectorOptions.isEnabled() && javacReferenceCollectorOptions.isImportRefsDivided()) { - options.add("-D" + ExternalRefCollectorCompilerToolExtension.DIVIDE_IMPORTS_PARAM + "=true"); - } + return Collections.singletonList("-D" + ExternalRefCollectorCompilerToolExtension.ENABLED_PARAM + "=" + isEnabled()); } - return options; + return Collections.emptyList(); } - private static class JavacReferenceCollectorOptions { - private final boolean myEnabled; - private final boolean myDivideImportRefs; - - private JavacReferenceCollectorOptions() { - boolean enabled = false; - boolean divideImportRefs = false; - for (JavacFileReferencesRegistrar listener : JpsServiceManager.getInstance().getExtensions(JavacFileReferencesRegistrar.class)) { - if (listener.isEnabled()) { - enabled = true; - if (listener.onlyImports()) { - divideImportRefs = true; - } - } + private static boolean isEnabled() { + for (JavacFileReferencesRegistrar listener : JpsServiceManager.getInstance().getExtensions(JavacFileReferencesRegistrar.class)) { + if (listener.isEnabled()) { + return true; } - - myEnabled = enabled; - myDivideImportRefs = divideImportRefs; - } - - public boolean isEnabled() { - return myEnabled; - } - - public boolean isImportRefsDivided() { - return myDivideImportRefs; } + return false; } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/ast/api/JavacFileReferencesRegistrar.java b/jps/jps-builders/src/org/jetbrains/jps/javac/ast/api/JavacFileReferencesRegistrar.java index 58a1835050d8..a71a690acdf5 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/ast/api/JavacFileReferencesRegistrar.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/ast/api/JavacFileReferencesRegistrar.java @@ -11,8 +11,6 @@ public interface JavacFileReferencesRegistrar { boolean isEnabled(); - boolean onlyImports(); - void registerFile(CompileContext context, String filePath, TObjectIntHashMap refs, diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java index ed824aec66f8..420b5387a797 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java @@ -15,6 +15,7 @@ */ package org.jetbrains.ether; +import org.jetbrains.jps.builders.java.dependencyView.Mappings; import org.jetbrains.jps.incremental.storage.ProjectStamps; import org.jetbrains.jps.model.JpsDummyElement; import org.jetbrains.jps.model.JpsModuleRootModificationUtil; @@ -174,8 +175,8 @@ public class CommonTest extends IncrementalTestCase { doTest(); } - public void testIntegrateOnNonIncrementalMake() { - doTest(); + public void testIntegrateOnNonIncrementalMake() throws Exception { + executeWithSystemProperty(Mappings.PROCESS_CONSTANTS_NON_INCREMENTAL_PROPERTY, String.valueOf(true), () -> doTest()); } public void testNothingChanged() { diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index c32329d484a9..602951b9e44d 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -40,6 +40,7 @@ import org.jetbrains.jps.util.JpsPathUtil; import java.io.File; import java.io.IOException; import java.util.*; +import java.util.concurrent.Callable; /** * @author db @@ -134,6 +135,22 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { return new File(workDir, StringUtil.trimEnd(path, suffix)); } + public T executeWithSystemProperty(String propName, String propValue, Callable action) throws Exception { + final String oldValue = System.getProperty(propName); + try { + System.setProperty(propName, propValue); + return action.call(); + } + finally { + if (oldValue != null) { + System.setProperty(propName, oldValue); + } + else { + System.clearProperty(propName); + } + } + } + public BuildResult doTest() { setupInitialProject(); diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java index 11f8eab6ac1b..7fa0eacbb2a5 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java @@ -17,6 +17,7 @@ package org.jetbrains.ether; import org.jetbrains.jps.builders.CompileScopeTestBuilder; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; +import org.jetbrains.jps.builders.java.dependencyView.Mappings; import org.jetbrains.jps.model.JpsDummyElement; import org.jetbrains.jps.model.JpsModuleRootModificationUtil; import org.jetbrains.jps.model.java.JpsJavaDependencyScope; @@ -97,7 +98,7 @@ public class MarkDirtyTest extends IncrementalTestCase { doTestBuild(1).assertSuccessful(); } - public void testTransitiveRecompile() { + public void testTransitiveRecompile() throws Exception { JpsModule module = addModule(); addTestRoot(module, "testSrc"); JpsModule util = addModule("util", "util/src"); @@ -106,7 +107,7 @@ public class MarkDirtyTest extends IncrementalTestCase { JpsModule lib = addModule("lib", "lib/src"); addTestRoot(lib, "lib/testSrc"); JpsModuleRootModificationUtil.addDependency(util, lib); - doTestBuild(1).assertSuccessful(); + executeWithSystemProperty(Mappings.PROCESS_CONSTANTS_NON_INCREMENTAL_PROPERTY, String.valueOf(true), () -> doTestBuild(1)).assertSuccessful(); } public void testRecompileTwinDependencies() {