mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-176693 incremental modules compilation
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
Cleaning output files:
|
||||
out/production/A/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/module-info.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to B, C, D;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to B, C;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
ppp.Util.perform();
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import ppp.Util;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/A/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
out/production/B/qqq/Client.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
moduleB/src/qqq/Client.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to B, C, D;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to C, D;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
// do perform
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import ppp.Util;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/A/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/C/module-info.class
|
||||
out/production/C/qqq2/ClientC.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleC/src/module-info.java
|
||||
moduleC/src/qqq2/ClientC.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to B, C, D;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to B, D;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
ppp.Util.perform();
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import ppp.Util;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/C/module-info.class
|
||||
out/production/C/qqq2/ClientC.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleC/src/module-info.java
|
||||
moduleC/src/qqq2/ClientC.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to B;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
System.out.println("ClientB.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq2;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
// do perform
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/C/module-info.class
|
||||
out/production/C/qqq2/ClientC.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleC/src/module-info.java
|
||||
moduleC/src/qqq2/ClientC.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
System.out.println("ClientB.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import ppp.Util;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/A/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
out/production/B/qqq/Client.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
moduleB/src/qqq/Client.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
module A {
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
// do perform
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package qqq2;
|
||||
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
// do perform
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
out/production/B/qqq/Client.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
moduleB/src/qqq/Client.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires A;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
module B {
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package qqq;
|
||||
import ppp.Util;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import qqq.Client;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
new Client().perform();
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
Cleaning output files:
|
||||
out/production/A/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/module-info.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to C;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
module A {
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
// do perform
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package qqq2;
|
||||
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
// do perform
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/A/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/C/module-info.class
|
||||
out/production/C/qqq2/ClientC.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleC/src/module-info.java
|
||||
moduleC/src/qqq2/ClientC.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp to C;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
module A {
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
// do perform
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import ppp.Util;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
Cleaning output files:
|
||||
out/production/A/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleA/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
out/production/B/qqq/Client.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
moduleB/src/qqq/Client.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/C/module-info.class
|
||||
out/production/C/qqq2/ClientC.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleC/src/module-info.java
|
||||
moduleC/src/qqq2/ClientC.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
module A {
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
System.out.println("ClientB.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import ppp.Util;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/B/module-info.class
|
||||
out/production/B/qqq/Client.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleB/src/module-info.java
|
||||
moduleB/src/qqq/Client.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/C/module-info.class
|
||||
out/production/C/qqq2/ClientC.class
|
||||
End of files
|
||||
Compiling files:
|
||||
moduleC/src/module-info.java
|
||||
moduleC/src/qqq2/ClientC.java
|
||||
End of files
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module A {
|
||||
exports ppp;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package ppp;
|
||||
|
||||
public class Util {
|
||||
public static void perform() {
|
||||
System.out.println("Util.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module B {
|
||||
requires transitive A;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
module B {
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package qqq;
|
||||
|
||||
public class Client {
|
||||
public void perform() {
|
||||
System.out.println("ClientB.perform");
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
module C {
|
||||
requires B;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package qqq2;
|
||||
|
||||
import ppp.Util;
|
||||
|
||||
public class ClientC {
|
||||
public void perform() {
|
||||
Util.perform();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,9 @@ import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.incremental.messages.ProgressMessage;
|
||||
import org.jetbrains.jps.model.JpsDummyElement;
|
||||
import org.jetbrains.jps.model.JpsProject;
|
||||
import org.jetbrains.jps.model.java.JavaModuleIndex;
|
||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||
import org.jetbrains.jps.model.java.JpsJavaSdkType;
|
||||
import org.jetbrains.jps.model.library.JpsTypedLibrary;
|
||||
import org.jetbrains.jps.model.library.sdk.JpsSdk;
|
||||
@@ -63,6 +66,7 @@ public class JavaBuilderUtil {
|
||||
private static final Key<Set<File>> SUCCESSFULLY_COMPILED_FILES_KEY = Key.create("_successfully_compiled_files_");
|
||||
private static final Key<List<FileFilter>> SKIP_MARKING_DIRTY_FILTERS_KEY = Key.create("_skip_marking_dirty_filters_");
|
||||
private static final Key<Pair<Mappings, Callbacks.Backend>> MAPPINGS_DELTA_KEY = Key.create("_mappings_delta_");
|
||||
private static final String MODULE_INFO_FILE = "module-info.java";
|
||||
|
||||
public static void registerFileToCompile(CompileContext context, File file) {
|
||||
registerFilesToCompile(context, Collections.singleton(file));
|
||||
@@ -214,6 +218,7 @@ public class JavaBuilderUtil {
|
||||
LOG.debug("End Of Differentiate Results.");
|
||||
}
|
||||
|
||||
final boolean compilingIncrementally = isCompileJavaIncrementally(context);
|
||||
if (incremental) {
|
||||
final Set<File> newlyAffectedFiles = new HashSet<>(allAffectedFiles);
|
||||
newlyAffectedFiles.removeAll(affectedBeforeDif);
|
||||
@@ -241,10 +246,47 @@ public class JavaBuilderUtil {
|
||||
}
|
||||
}
|
||||
|
||||
Set<ModuleBuildTarget> targetsToMark = null;
|
||||
final JavaModuleIndex moduleIndex = getJavaModuleIndex(context);
|
||||
for (File file : newlyAffectedFiles) {
|
||||
FSOperations.markDirtyIfNotDeleted(context, markDirtyRound, file);
|
||||
if (MODULE_INFO_FILE.equals(file.getName())) {
|
||||
final JavaSourceRootDescriptor rootDescr = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context, file);
|
||||
if (rootDescr != null) {
|
||||
final ModuleBuildTarget target = rootDescr.getTarget();
|
||||
final File targetModuleInfo = moduleIndex.getModuleInfoFile(target.getModule(), target.isTests());
|
||||
if (FileUtil.filesEqual(targetModuleInfo, file)) {
|
||||
if (targetsToMark == null) {
|
||||
targetsToMark = new THashSet<>(); // lazy init
|
||||
}
|
||||
targetsToMark.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
FSOperations.markDirtyIfNotDeleted(context, markDirtyRound, file);
|
||||
}
|
||||
}
|
||||
additionalPassRequired = isCompileJavaIncrementally(context) && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
|
||||
if (targetsToMark != null) {
|
||||
boolean currentChunkAfected = false;
|
||||
for (ModuleBuildTarget target : targetsToMark) {
|
||||
if (chunk.getTargets().contains(target)) {
|
||||
currentChunkAfected = true;
|
||||
}
|
||||
else {
|
||||
FSOperations.markDirty(context, markDirtyRound, target, null);
|
||||
}
|
||||
}
|
||||
if (currentChunkAfected) {
|
||||
if (compilingIncrementally) {
|
||||
// turn on non-incremental mode for targets from the current chunk, if at least one of them was affected.
|
||||
for (ModuleBuildTarget target : chunk.getTargets()) {
|
||||
context.markNonIncremental(target);
|
||||
}
|
||||
}
|
||||
FSOperations.markDirty(context, markDirtyRound, chunk, null);
|
||||
}
|
||||
}
|
||||
additionalPassRequired = compilingIncrementally && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -254,7 +296,7 @@ public class JavaBuilderUtil {
|
||||
context.processMessage(new ProgressMessage(messageText));
|
||||
|
||||
final boolean alreadyMarkedDirty = FSOperations.isMarkedDirty(context, chunk);
|
||||
additionalPassRequired = isCompileJavaIncrementally(context) && !alreadyMarkedDirty;
|
||||
additionalPassRequired = compilingIncrementally && !alreadyMarkedDirty;
|
||||
|
||||
if (alreadyMarkedDirty) {
|
||||
// need this to make sure changes data stored in Delta is complete
|
||||
@@ -303,6 +345,17 @@ public class JavaBuilderUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File findModuleInfoFile(CompileContext context, ModuleBuildTarget target) {
|
||||
return getJavaModuleIndex(context).getModuleInfoFile(target.getModule(), target.isTests());
|
||||
}
|
||||
|
||||
private static JavaModuleIndex getJavaModuleIndex(CompileContext context) {
|
||||
JpsProject project = context.getProjectDescriptor().getProject();
|
||||
File storageRoot = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot();
|
||||
return JpsJavaExtensionService.getInstance().getJavaModuleIndex(project, storageRoot);
|
||||
}
|
||||
|
||||
private static FileFilter createOrFilter(final List<FileFilter> filters) {
|
||||
if (filters == null || filters.isEmpty()) return null;
|
||||
return pathname -> {
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
// Copyright 2000-2017 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.builders.java.dependencyView;
|
||||
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 30-Sep-17
|
||||
*/
|
||||
public abstract class ClassFileRepr extends Proto {
|
||||
protected final DependencyContext myContext;
|
||||
private final int myFileName;
|
||||
private final Set<UsageRepr.Usage> myUsages;
|
||||
|
||||
public ClassFileRepr(
|
||||
int access,
|
||||
int signature,
|
||||
int name,
|
||||
@NotNull Set<TypeRepr.ClassType> annotations,
|
||||
final int fileName, final DependencyContext context, final Set<UsageRepr.Usage> usages) {
|
||||
super(access, signature, name, annotations);
|
||||
myFileName = fileName;
|
||||
this.myContext = context;
|
||||
this.myUsages = usages;
|
||||
}
|
||||
|
||||
public ClassFileRepr(DependencyContext context, DataInput in) {
|
||||
super(context, in);
|
||||
myContext = context;
|
||||
try {
|
||||
myFileName = DataInputOutputUtil.readINT(in);
|
||||
myUsages = RW.read(UsageRepr.externalizer(context), new THashSet<>(), in);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getFileName() {
|
||||
return myFileName;
|
||||
}
|
||||
|
||||
public Set<UsageRepr.Usage> getUsages() {
|
||||
return myUsages;
|
||||
}
|
||||
|
||||
public boolean addUsage(final UsageRepr.Usage usage) {
|
||||
return myUsages.add(usage);
|
||||
}
|
||||
|
||||
protected abstract void updateClassUsages(DependencyContext context, Set<UsageRepr.Usage> s);
|
||||
|
||||
public void toStream(DependencyContext context, PrintStream stream) {
|
||||
super.toStream(context, stream);
|
||||
stream.print(" Filename : ");
|
||||
stream.println(context.getValue(myFileName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out) {
|
||||
try {
|
||||
super.save(out);
|
||||
DataInputOutputUtil.writeINT(out, myFileName);
|
||||
RW.save(myUsages, UsageRepr.externalizer(myContext), out);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * myFileName + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ClassFileRepr classRepr = (ClassFileRepr)o;
|
||||
|
||||
if (myFileName != classRepr.myFileName) return false;
|
||||
if (name != classRepr.name) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright 2000-2017 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.builders.java.dependencyView;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 04-Oct-17
|
||||
*/
|
||||
class ClassFileReprExternalizer implements DataExternalizer<ClassFileRepr> {
|
||||
|
||||
private static final byte CLASS = 0x1;
|
||||
private static final byte MODULE = 0x2;
|
||||
private final DataExternalizer<ClassRepr> myClassReprExternalizer;
|
||||
private final DataExternalizer<ModuleRepr> myModuleReprExternalizer;
|
||||
|
||||
public ClassFileReprExternalizer(DependencyContext context) {
|
||||
myClassReprExternalizer = ClassRepr.externalizer(context);
|
||||
myModuleReprExternalizer = ModuleRepr.externalizer(context);
|
||||
}
|
||||
|
||||
public void save(@NotNull DataOutput out, ClassFileRepr value) throws IOException {
|
||||
if (value instanceof ClassRepr) {
|
||||
out.writeByte(CLASS);
|
||||
myClassReprExternalizer.save(out, (ClassRepr)value);
|
||||
}
|
||||
else {
|
||||
out.writeByte(MODULE);
|
||||
myModuleReprExternalizer.save(out, (ModuleRepr)value);
|
||||
}
|
||||
}
|
||||
|
||||
public ClassFileRepr read(@NotNull DataInput in) throws IOException {
|
||||
return in.readByte() == CLASS ? myClassReprExternalizer.read(in) : myModuleReprExternalizer.read(in);
|
||||
}
|
||||
}
|
||||
+17
-76
@@ -31,9 +31,7 @@ import java.util.*;
|
||||
* @author: db
|
||||
* Date: 01.02.11
|
||||
*/
|
||||
public class ClassRepr extends Proto {
|
||||
private final DependencyContext myContext;
|
||||
private final int myFileName;
|
||||
public class ClassRepr extends ClassFileRepr {
|
||||
private final TypeRepr.ClassType mySuperClass;
|
||||
private final Set<TypeRepr.AbstractType> myInterfaces;
|
||||
private final Set<ElemType> myAnnotationTargets;
|
||||
@@ -41,7 +39,6 @@ public class ClassRepr extends Proto {
|
||||
|
||||
private final Set<FieldRepr> myFields;
|
||||
private final Set<MethodRepr> myMethods;
|
||||
private final Set<UsageRepr.Usage> myUsages;
|
||||
|
||||
private final int myOuterClassName;
|
||||
private final boolean myIsLocal;
|
||||
@@ -75,19 +72,16 @@ public class ClassRepr extends Proto {
|
||||
return myRetentionPolicy;
|
||||
}
|
||||
|
||||
public Set<UsageRepr.Usage> getUsages() {
|
||||
return myUsages;
|
||||
}
|
||||
|
||||
public boolean addUsage(final UsageRepr.Usage usage) {
|
||||
return myUsages.add(usage);
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return (access & Opcodes.ACC_INTERFACE) != 0;
|
||||
}
|
||||
|
||||
public abstract static class Diff extends Difference {
|
||||
public abstract static class Diff extends DifferenceImpl {
|
||||
|
||||
Diff(@NotNull Difference delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
public abstract Specifier<TypeRepr.AbstractType, Difference> interfaces();
|
||||
|
||||
public abstract Specifier<FieldRepr, Difference> fields();
|
||||
@@ -119,12 +113,12 @@ public class ClassRepr extends Proto {
|
||||
base |= Difference.SUPERCLASS;
|
||||
}
|
||||
|
||||
if (!myUsages.equals(pastClass.myUsages)) {
|
||||
if (!getUsages().equals(pastClass.getUsages())) {
|
||||
base |= Difference.USAGES;
|
||||
}
|
||||
final int d = base;
|
||||
|
||||
return new Diff() {
|
||||
return new Diff(diff) {
|
||||
@Override
|
||||
public boolean extendsAdded() {
|
||||
if ((d & Difference.SUPERCLASS) <= 0) {
|
||||
@@ -134,21 +128,6 @@ public class ClassRepr extends Proto {
|
||||
return "java/lang/Object".equals(pastSuperName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean packageLocalOn() {
|
||||
return diff.packageLocalOn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addedModifiers() {
|
||||
return diff.addedModifiers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removedModifiers() {
|
||||
return diff.removedModifiers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Difference.Specifier<TypeRepr.AbstractType, Difference> interfaces() {
|
||||
return Difference.make(pastClass.myInterfaces, myInterfaces);
|
||||
@@ -169,10 +148,6 @@ public class ClassRepr extends Proto {
|
||||
return Difference.make(pastClass.myAnnotationTargets, myAnnotationTargets);
|
||||
}
|
||||
|
||||
public Specifier<TypeRepr.ClassType, Difference> annotations() {
|
||||
return diff.annotations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retentionChanged() {
|
||||
return !((myRetentionPolicy == null && pastClass.myRetentionPolicy == RetentionPolicy.CLASS) ||
|
||||
@@ -189,11 +164,6 @@ public class ClassRepr extends Proto {
|
||||
public boolean hadValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean weakedAccess() {
|
||||
return diff.weakedAccess();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,7 +181,7 @@ public class ClassRepr extends Proto {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void updateClassUsages(final DependencyContext context, final Set<UsageRepr.Usage> s) {
|
||||
protected void updateClassUsages(final DependencyContext context, final Set<UsageRepr.Usage> s) {
|
||||
mySuperClass.updateClassUsages(context, name, s);
|
||||
|
||||
for (TypeRepr.AbstractType t : myInterfaces) {
|
||||
@@ -239,9 +209,7 @@ public class ClassRepr extends Proto {
|
||||
final boolean localClassFlag,
|
||||
final boolean anonymousClassFlag,
|
||||
final Set<UsageRepr.Usage> usages) {
|
||||
super(access, sig, name, annotations);
|
||||
this.myContext = context;
|
||||
myFileName = fileName;
|
||||
super(access, sig, name, annotations, fileName, context, usages);
|
||||
mySuperClass = TypeRepr.createClassType(context, superClass);
|
||||
myInterfaces = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, interfaces, new THashSet<>(1));
|
||||
myFields = fields;
|
||||
@@ -251,19 +219,17 @@ public class ClassRepr extends Proto {
|
||||
this.myOuterClassName = outerClassName;
|
||||
this.myIsLocal = localClassFlag;
|
||||
this.myIsAnonymous = anonymousClassFlag;
|
||||
this.myUsages = usages;
|
||||
updateClassUsages(context, usages);
|
||||
}
|
||||
|
||||
public ClassRepr(final DependencyContext context, final DataInput in) {
|
||||
super(context, in);
|
||||
try {
|
||||
this.myContext = context;
|
||||
myFileName = DataInputOutputUtil.readINT(in);
|
||||
mySuperClass = (TypeRepr.ClassType)TypeRepr.externalizer(context).read(in);
|
||||
myInterfaces = (Set<TypeRepr.AbstractType>)RW.read(TypeRepr.externalizer(context), new THashSet<>(1), in);
|
||||
myFields = (Set<FieldRepr>)RW.read(FieldRepr.externalizer(context), new THashSet<>(), in);
|
||||
myMethods = (Set<MethodRepr>)RW.read(MethodRepr.externalizer(context), new THashSet<>(), in);
|
||||
myAnnotationTargets = (Set<ElemType>)RW.read(UsageRepr.AnnotationUsage.elementTypeExternalizer, EnumSet.noneOf(ElemType.class), in);
|
||||
myInterfaces = RW.read(TypeRepr.externalizer(context), new THashSet<>(1), in);
|
||||
myFields = RW.read(FieldRepr.externalizer(context), new THashSet<>(), in);
|
||||
myMethods = RW.read(MethodRepr.externalizer(context), new THashSet<>(), in);
|
||||
myAnnotationTargets = RW.read(UsageRepr.AnnotationUsage.elementTypeExternalizer, EnumSet.noneOf(ElemType.class), in);
|
||||
|
||||
final String s = RW.readUTF(in);
|
||||
|
||||
@@ -273,7 +239,6 @@ public class ClassRepr extends Proto {
|
||||
int flags = DataInputOutputUtil.readINT(in);
|
||||
myIsLocal = (flags & LOCAL_MASK) != 0;
|
||||
myIsAnonymous = (flags & ANONYMOUS_MASK) != 0;
|
||||
myUsages =(Set<UsageRepr.Usage>)RW.read(UsageRepr.externalizer(context), new THashSet<>(), in);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
@@ -287,7 +252,6 @@ public class ClassRepr extends Proto {
|
||||
public void save(final DataOutput out) {
|
||||
try {
|
||||
super.save(out);
|
||||
DataInputOutputUtil.writeINT(out, myFileName);
|
||||
mySuperClass.save(out);
|
||||
RW.save(myInterfaces, out);
|
||||
RW.save(myFields, out);
|
||||
@@ -296,32 +260,12 @@ public class ClassRepr extends Proto {
|
||||
RW.writeUTF(out, myRetentionPolicy == null ? "" : myRetentionPolicy.toString());
|
||||
DataInputOutputUtil.writeINT(out, myOuterClassName);
|
||||
DataInputOutputUtil.writeINT(out, (myIsLocal ? LOCAL_MASK:0) | (myIsAnonymous ? ANONYMOUS_MASK : 0));
|
||||
|
||||
RW.save(myUsages, UsageRepr.externalizer(myContext), out);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ClassRepr classRepr = (ClassRepr)o;
|
||||
|
||||
if (myFileName != classRepr.myFileName) return false;
|
||||
if (name != classRepr.name) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * myFileName + name;
|
||||
}
|
||||
|
||||
public UsageRepr.Usage createUsage() {
|
||||
return UsageRepr.createClassUsage(myContext, name);
|
||||
}
|
||||
@@ -400,9 +344,6 @@ public class ClassRepr extends Proto {
|
||||
public void toStream(final DependencyContext context, final PrintStream stream) {
|
||||
super.toStream(context, stream);
|
||||
|
||||
stream.print(" Filename : ");
|
||||
stream.println(context.getValue(myFileName));
|
||||
|
||||
stream.print(" Superclass : ");
|
||||
stream.println(mySuperClass == null ? "<null>" : mySuperClass.getDescr(context));
|
||||
|
||||
@@ -494,7 +435,7 @@ public class ClassRepr extends Proto {
|
||||
|
||||
final List<String> usages = new LinkedList<>();
|
||||
|
||||
for (final UsageRepr.Usage u : myUsages) {
|
||||
for (final UsageRepr.Usage u : getUsages()) {
|
||||
final ByteArrayOutputStream bas = new ByteArrayOutputStream();
|
||||
|
||||
u.toStream(myContext, new PrintStream(bas));
|
||||
|
||||
+73
-17
@@ -16,7 +16,6 @@
|
||||
package org.jetbrains.jps.builders.java.dependencyView;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.SmartList;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -29,10 +28,7 @@ import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor;
|
||||
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author: db
|
||||
@@ -242,6 +238,51 @@ class ClassfileAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
private class ModuleCrawler extends ModuleVisitor {
|
||||
public ModuleCrawler() {
|
||||
super(ASM_API_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMainClass(String mainClass) {
|
||||
myUsages.add(UsageRepr.createClassUsage(myContext, myContext.get(mainClass)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRequire(String module, int access, String version) {
|
||||
if (isExplicit(access)) {
|
||||
// collect non-synthetic dependencies only
|
||||
myModuleRequires.add(new ModuleRequiresRepr(myContext, access, myContext.get(module), version));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExport(String packaze, int access, String... modules) {
|
||||
if (isExplicit(access)) {
|
||||
// collect non-synthetic dependencies only
|
||||
myModuleExports.add(new ModulePackageRepr(myContext, myContext.get(packaze), modules != null? Arrays.asList(modules) : Collections.emptyList()));
|
||||
}
|
||||
}
|
||||
|
||||
public void visitUse(String service) {
|
||||
myUsages.add(UsageRepr.createClassUsage(myContext, myContext.get(service)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProvide(String service, String... providers) {
|
||||
myUsages.add(UsageRepr.createClassUsage(myContext, myContext.get(service)));
|
||||
if (providers != null) {
|
||||
for (String provider : providers) {
|
||||
myUsages.add(UsageRepr.createClassUsage(myContext, myContext.get(provider)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isExplicit(int access) {
|
||||
return (access & (Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED)) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void processSignature(final String sig) {
|
||||
if (sig != null) {
|
||||
try {
|
||||
@@ -278,11 +319,12 @@ class ClassfileAnalyzer {
|
||||
}
|
||||
};
|
||||
|
||||
private Boolean myTakeIntoAccount = false;
|
||||
|
||||
private boolean myTakeIntoAccount = false;
|
||||
private boolean myIsModule = false;
|
||||
private final int myFileName;
|
||||
private int myAccess;
|
||||
private int myName;
|
||||
private int myVersion; // for class contains a class bytecode version, for module contains a module version
|
||||
private String mySuperClass;
|
||||
private String[] myInterfaces;
|
||||
private String mySignature;
|
||||
@@ -302,6 +344,9 @@ class ClassfileAnalyzer {
|
||||
private final Map<TypeRepr.ClassType, Set<ElemType>> myAnnotationTargets = new THashMap<>();
|
||||
private final Set<TypeRepr.ClassType> myAnnotations = new THashSet<>();
|
||||
|
||||
private final Set<ModuleRequiresRepr> myModuleRequires = new THashSet<>();
|
||||
private final Set<ModulePackageRepr> myModuleExports = new THashSet<>();
|
||||
|
||||
public ClassCrawler(final int fn) {
|
||||
super(ASM_API_VERSION);
|
||||
myFileName = fn;
|
||||
@@ -311,17 +356,18 @@ class ClassfileAnalyzer {
|
||||
return (access & Opcodes.ACC_PRIVATE) == 0;
|
||||
}
|
||||
|
||||
public Pair<ClassRepr, Set<UsageRepr.Usage>> getResult() {
|
||||
ClassRepr repr = myTakeIntoAccount ? new ClassRepr(
|
||||
public ClassFileRepr getResult() {
|
||||
if (!myTakeIntoAccount) {
|
||||
return null;
|
||||
}
|
||||
if (myIsModule) {
|
||||
return new ModuleRepr(myContext, myAccess, myVersion, myFileName, myName, myModuleRequires, myModuleExports, myUsages);
|
||||
}
|
||||
return new ClassRepr(
|
||||
myContext, myAccess, myFileName, myName, myContext.get(mySignature), myContext.get(mySuperClass), myInterfaces,
|
||||
myFields, myMethods, myAnnotations, myTargets, myRetentionPolicy, myContext.get(myOuterClassName.get()), myLocalClassFlag.get(),
|
||||
myAnonymousClassFlag.get(), myUsages) : null;
|
||||
|
||||
if (repr != null) {
|
||||
repr.updateClassUsages(myContext, myUsages);
|
||||
}
|
||||
|
||||
return Pair.create(repr, myUsages);
|
||||
myAnonymousClassFlag.get(), myUsages
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -330,6 +376,7 @@ class ClassfileAnalyzer {
|
||||
|
||||
myAccess = access;
|
||||
myName = myContext.get(name);
|
||||
myVersion = version;
|
||||
mySignature = sig;
|
||||
mySuperClass = superName;
|
||||
myInterfaces = interfaces;
|
||||
@@ -364,6 +411,15 @@ class ClassfileAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleVisitor visitModule(String name, int access, String version) {
|
||||
myIsModule = true;
|
||||
myAccess = access;
|
||||
myName = myContext.get(name);
|
||||
myVersion = myContext.get(version);
|
||||
return new ModuleCrawler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
|
||||
if (desc.equals("Ljava/lang/annotation/Target;")) {
|
||||
@@ -779,7 +835,7 @@ class ClassfileAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<ClassRepr, Set<UsageRepr.Usage>> analyze(int fileName, ClassReader cr) {
|
||||
public ClassFileRepr analyze(int fileName, ClassReader cr) {
|
||||
ClassCrawler visitor = new ClassCrawler(fileName);
|
||||
|
||||
try {
|
||||
|
||||
+21
-3
@@ -56,6 +56,26 @@ public abstract class Difference {
|
||||
}
|
||||
|
||||
public static <T, D extends Difference> Specifier<T, D> make(final Set<T> past, final Set<T> now) {
|
||||
if ((past == null || past.isEmpty()) && (now == null || now.isEmpty())) {
|
||||
return new Specifier<T, D>() {
|
||||
public Collection<T> added() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection<T> removed() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection<Pair<T, D>> changed() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public boolean unchanged() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (past == null) {
|
||||
final Collection<T> _now = Collections.unmodifiableCollection(now);
|
||||
return new Specifier<T, D>() {
|
||||
@@ -78,11 +98,9 @@ public abstract class Difference {
|
||||
}
|
||||
|
||||
final Set<T> added = new HashSet<>(now);
|
||||
|
||||
added.removeAll(past);
|
||||
|
||||
final Set<T> removed = new HashSet<>(past);
|
||||
|
||||
removed.removeAll(now);
|
||||
|
||||
final Set<Pair<T, D>> changed;
|
||||
@@ -133,7 +151,7 @@ public abstract class Difference {
|
||||
};
|
||||
}
|
||||
|
||||
private static <T> boolean canContainChangedElements(final Set<T> past, final Set<T> now) {
|
||||
private static <T> boolean canContainChangedElements(final Collection<T> past, final Collection<T> now) {
|
||||
if (past != null && now != null && !past.isEmpty() && !now.isEmpty()) {
|
||||
return past.iterator().next() instanceof Proto;
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright 2000-2017 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.builders.java.dependencyView;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 02-Oct-17
|
||||
*/
|
||||
class DifferenceImpl extends Difference{
|
||||
|
||||
private final Difference myDelegate;
|
||||
|
||||
public DifferenceImpl(@NotNull Difference delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
public int base() {
|
||||
return myDelegate.base();
|
||||
}
|
||||
|
||||
public boolean no() {
|
||||
return myDelegate.no();
|
||||
}
|
||||
|
||||
public boolean weakedAccess() {
|
||||
return myDelegate.weakedAccess();
|
||||
}
|
||||
|
||||
public int addedModifiers() {
|
||||
return myDelegate.addedModifiers();
|
||||
}
|
||||
|
||||
public int removedModifiers() {
|
||||
return myDelegate.removedModifiers();
|
||||
}
|
||||
|
||||
public boolean packageLocalOn() {
|
||||
return myDelegate.packageLocalOn();
|
||||
}
|
||||
|
||||
public boolean hadValue() {
|
||||
return myDelegate.hadValue();
|
||||
}
|
||||
|
||||
public Specifier<TypeRepr.ClassType, Difference> annotations() {
|
||||
return myDelegate.annotations();
|
||||
}
|
||||
}
|
||||
+311
-139
@@ -53,12 +53,6 @@ public class Mappings {
|
||||
private static final IntInlineKeyDescriptor INT_KEY_DESCRIPTOR = new IntInlineKeyDescriptor();
|
||||
private static final int DEFAULT_SET_CAPACITY = 32;
|
||||
private static final float DEFAULT_SET_LOAD_FACTOR = 0.98f;
|
||||
private static final CollectionFactory<ClassRepr> ourClassSetConstructor = new CollectionFactory<ClassRepr>() {
|
||||
public Set<ClassRepr> create() {
|
||||
// for IDEA codebase on average there is no more than 2.5 classes out of one source file, so we use smaller estimate
|
||||
return new THashSet<>(5, DEFAULT_SET_LOAD_FACTOR);
|
||||
}
|
||||
};
|
||||
|
||||
private final boolean myIsDelta;
|
||||
private final boolean myDeltaIsTransient;
|
||||
@@ -67,7 +61,7 @@ public class Mappings {
|
||||
|
||||
private final TIntHashSet myChangedClasses;
|
||||
private final THashSet<File> myChangedFiles;
|
||||
private final Set<Pair<ClassRepr, File>> myDeletedClasses;
|
||||
private final Set<Pair<ClassFileRepr, File>> myDeletedClasses;
|
||||
private final Set<ClassRepr> myAddedClasses;
|
||||
private final Object myLock;
|
||||
private final File myRootDir;
|
||||
@@ -85,7 +79,7 @@ public class Mappings {
|
||||
values: class names that use the class registered as the key
|
||||
*/
|
||||
private IntIntMultiMaplet myClassToClassDependency;
|
||||
private ObjectObjectMultiMaplet<File, ClassRepr> mySourceFileToClasses;
|
||||
private ObjectObjectMultiMaplet<File, ClassFileRepr> mySourceFileToClasses;
|
||||
private IntObjectMultiMaplet<File> myClassToSourceFile;
|
||||
/**
|
||||
* [short className] -> list of FQ names
|
||||
@@ -148,7 +142,7 @@ public class Mappings {
|
||||
myClassToSubclasses = new IntIntTransientMultiMaplet();
|
||||
myClassToClassDependency = new IntIntTransientMultiMaplet();
|
||||
myShortClassNameIndex = null;
|
||||
mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<>(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor);
|
||||
mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<>(FileUtil.FILE_HASHING_STRATEGY, () -> new THashSet<>(5, DEFAULT_SET_LOAD_FACTOR));
|
||||
myClassToSourceFile = new IntObjectTransientMultiMaplet<>(fileCollectionFactory);
|
||||
}
|
||||
else {
|
||||
@@ -159,12 +153,12 @@ public class Mappings {
|
||||
myClassToClassDependency = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_CLASS), INT_KEY_DESCRIPTOR);
|
||||
myShortClassNameIndex = myIsDelta? null : new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, SHORT_NAMES), INT_KEY_DESCRIPTOR);
|
||||
mySourceFileToClasses = new ObjectObjectPersistentMultiMaplet<>(
|
||||
DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext),
|
||||
ourClassSetConstructor
|
||||
DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), new ClassFileReprExternalizer(myContext),
|
||||
() -> new THashSet<>(5, DEFAULT_SET_LOAD_FACTOR)
|
||||
);
|
||||
myClassToSourceFile = new IntObjectPersistentMultiMaplet<>(
|
||||
DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), INT_KEY_DESCRIPTOR, new FileKeyDescriptor(), fileCollectionFactory
|
||||
);
|
||||
myClassToSourceFile =
|
||||
new IntObjectPersistentMultiMaplet<>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), INT_KEY_DESCRIPTOR,
|
||||
new FileKeyDescriptor(), fileCollectionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,14 +190,19 @@ public class Mappings {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassRepr getReprByName(final @Nullable File source, final int qName) {
|
||||
private ClassRepr getClassReprByName(final @Nullable File source, final int qName) {
|
||||
final ClassFileRepr reprByName = getReprByName(source, qName);
|
||||
return reprByName instanceof ClassRepr? (ClassRepr)reprByName : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassFileRepr getReprByName(@Nullable File source, int qName) {
|
||||
final Collection<File> sources = source != null? Collections.singleton(source) : myClassToSourceFile.get(qName);
|
||||
if (sources != null) {
|
||||
for (File src : sources) {
|
||||
final Collection<ClassRepr> reprs = mySourceFileToClasses.get(src);
|
||||
|
||||
final Collection<ClassFileRepr> reprs = mySourceFileToClasses.get(src);
|
||||
if (reprs != null) {
|
||||
for (ClassRepr repr : reprs) {
|
||||
for (ClassFileRepr repr : reprs) {
|
||||
if (repr.name == qName) {
|
||||
return repr;
|
||||
}
|
||||
@@ -236,9 +235,9 @@ public class Mappings {
|
||||
private final LinkedBlockingQueue<Runnable> myPostPasses = new LinkedBlockingQueue<>();
|
||||
|
||||
private void runPostPasses() {
|
||||
final Set<Pair<ClassRepr, File>> deleted = myDeletedClasses;
|
||||
final Set<Pair<ClassFileRepr, File>> deleted = myDeletedClasses;
|
||||
if (deleted != null) {
|
||||
for (Pair<ClassRepr, File> pair : deleted) {
|
||||
for (Pair<ClassFileRepr, File> pair : deleted) {
|
||||
final int deletedClassName = pair.first.name;
|
||||
final Collection<File> sources = myClassToSourceFile.get(deletedClassName);
|
||||
if (sources == null || sources.isEmpty()) { // if really deleted and not e.g. moved
|
||||
@@ -270,7 +269,7 @@ public class Mappings {
|
||||
myMappings = mappings;
|
||||
}
|
||||
|
||||
void appendDependents(final ClassRepr c, final TIntHashSet result) {
|
||||
void appendDependents(final ClassFileRepr c, final TIntHashSet result) {
|
||||
final TIntHashSet depClasses = myClassToClassDependency.get(c.name);
|
||||
|
||||
if (depClasses != null) {
|
||||
@@ -279,7 +278,7 @@ public class Mappings {
|
||||
}
|
||||
|
||||
void propagateMemberAccessRec(final TIntHashSet acc, final boolean isField, final boolean root, final MemberComparator comparator, final int reflcass) {
|
||||
final ClassRepr repr = reprByName(reflcass);
|
||||
final ClassRepr repr = classReprByName(reflcass);
|
||||
if (repr != null) {
|
||||
if (!root) {
|
||||
final Set<? extends ProtoMember> members = isField ? repr.getFields() : repr.getMethods();
|
||||
@@ -370,7 +369,7 @@ public class Mappings {
|
||||
}
|
||||
final TIntHashSet _visitedClasses = visitedClasses;
|
||||
subClasses.forEach(subClassName -> {
|
||||
final ClassRepr r = reprByName(subClassName);
|
||||
final ClassRepr r = classReprByName(subClassName);
|
||||
|
||||
if (r != null) {
|
||||
boolean cont = true;
|
||||
@@ -415,7 +414,7 @@ public class Mappings {
|
||||
if (!visitedClasses.add(superName) || superName == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
final ClassRepr superClass = classReprByName(superName);
|
||||
if (superClass != null) {
|
||||
for (MethodRepr mm : superClass.findMethods(predicate)) {
|
||||
if (isVisibleIn(superClass, mm, fromClass)) {
|
||||
@@ -439,7 +438,7 @@ public class Mappings {
|
||||
if (!visitedClasses.add(superName) || superName == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
final ClassRepr superClass = classReprByName(superName);
|
||||
if (superClass == null || extendsLibraryClass(superClass, visitedClasses)) {
|
||||
return true;
|
||||
}
|
||||
@@ -456,7 +455,7 @@ public class Mappings {
|
||||
if (!visitedClasses.add(superName)) {
|
||||
continue; // prevent SOE
|
||||
}
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
final ClassRepr superClass = classReprByName(superName);
|
||||
if (superClass != null) {
|
||||
boolean cont = true;
|
||||
final Collection<MethodRepr> methods = superClass.findMethods(predicate);
|
||||
@@ -485,7 +484,7 @@ public class Mappings {
|
||||
if (!visitedClasses.add(supername) || supername == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(supername);
|
||||
final ClassRepr superClass = classReprByName(supername);
|
||||
if (superClass != null) {
|
||||
final FieldRepr ff = superClass.findField(f.name);
|
||||
if (ff != null && isVisibleIn(superClass, ff, fromClass)) {
|
||||
@@ -507,7 +506,7 @@ public class Mappings {
|
||||
if (!visitedClasses.add(supername) || supername == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(supername);
|
||||
final ClassRepr superClass = classReprByName(supername);
|
||||
if (superClass != null) {
|
||||
final FieldRepr ff = superClass.findField(f.name);
|
||||
if (ff != null && isVisibleIn(superClass, ff, fromClass)) {
|
||||
@@ -523,9 +522,21 @@ public class Mappings {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ClassRepr reprByName(final int name) {
|
||||
ClassRepr classReprByName(final int name) {
|
||||
final ClassFileRepr r = reprByName(name);
|
||||
return r instanceof ClassRepr? (ClassRepr)r : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ModuleRepr moduleReprByName(final int name) {
|
||||
final ClassFileRepr r = reprByName(name);
|
||||
return r instanceof ModuleRepr? (ModuleRepr)r : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ClassFileRepr reprByName(final int name) {
|
||||
if (myMappings != null) {
|
||||
final ClassRepr r = myMappings.getReprByName(null, name);
|
||||
final ClassFileRepr r = myMappings.getReprByName(null, name);
|
||||
|
||||
if (r != null) {
|
||||
return r;
|
||||
@@ -541,7 +552,7 @@ public class Mappings {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
final ClassRepr repr = reprByName(who);
|
||||
final ClassRepr repr = classReprByName(who);
|
||||
|
||||
if (repr != null) {
|
||||
if (visitedClasses == null) {
|
||||
@@ -598,7 +609,7 @@ public class Mappings {
|
||||
}
|
||||
|
||||
boolean isFieldVisible(final int className, final FieldRepr field) {
|
||||
final ClassRepr r = reprByName(className);
|
||||
final ClassRepr r = classReprByName(className);
|
||||
if (r == null || r.getFields().contains(field)) {
|
||||
return true;
|
||||
}
|
||||
@@ -606,7 +617,7 @@ public class Mappings {
|
||||
}
|
||||
|
||||
void collectSupersRecursively(final int className, @NotNull final TIntHashSet container) {
|
||||
final ClassRepr classRepr = reprByName(className);
|
||||
final ClassRepr classRepr = classReprByName(className);
|
||||
if (classRepr != null) {
|
||||
final int[] supers = classRepr.getSupers();
|
||||
if (container.addAll(supers)) {
|
||||
@@ -637,7 +648,7 @@ public class Mappings {
|
||||
if (usages) {
|
||||
debug("Class usages affection requested");
|
||||
|
||||
final ClassRepr classRepr = reprByName(className);
|
||||
final ClassRepr classRepr = classReprByName(className);
|
||||
if (classRepr != null) {
|
||||
debug("Added class usage for ", classRepr.name);
|
||||
affectedUsages.add(classRepr.createUsage());
|
||||
@@ -698,11 +709,50 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class UsageConstraint {
|
||||
public abstract boolean checkResidence(final int residence);
|
||||
void affectModule(ModuleRepr m, final Collection<File> affectedFiles) {
|
||||
final Collection<File> depFiles = myClassToSourceFile.get(m.name);
|
||||
if (depFiles != null) {
|
||||
debug("Affecting module ", m.name);
|
||||
affectedFiles.addAll(depFiles);
|
||||
}
|
||||
}
|
||||
|
||||
public class FileFilterConstraint extends UsageConstraint {
|
||||
void affectDependentModules(Differential.DiffState state, final int moduleName, @Nullable UsageConstraint constraint, boolean checkTransitive) {
|
||||
new Object() {
|
||||
final TIntHashSet visited = new TIntHashSet();
|
||||
|
||||
void perform(final int modName) {
|
||||
final TIntHashSet depNames = myClassToClassDependency.get(modName);
|
||||
if (depNames != null && !depNames.isEmpty()) {
|
||||
final TIntHashSet next = new TIntHashSet();
|
||||
final UsageRepr.Usage moduleUsage = UsageRepr.createModuleUsage(myContext, modName);
|
||||
state.myAffectedUsages.add(moduleUsage);
|
||||
final UsageConstraint prevConstraint = state.myUsageConstraints.put(moduleUsage, constraint == null? UsageConstraint.ANY : constraint);
|
||||
if (prevConstraint != null) {
|
||||
state.myUsageConstraints.put(moduleUsage, prevConstraint.or(constraint));
|
||||
}
|
||||
depNames.forEach(depName -> {
|
||||
if (visited.add(depName)) {
|
||||
final ClassFileRepr depRepr = reprByName(depName);
|
||||
if (depRepr instanceof ModuleRepr) {
|
||||
state.myDependants.add(depName);
|
||||
if (checkTransitive && ((ModuleRepr)depRepr).requiresTransitevely(modName)) {
|
||||
next.add(depName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
next.forEach(m -> {
|
||||
perform(m);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}.perform(moduleName);
|
||||
}
|
||||
|
||||
public class FileFilterConstraint implements UsageConstraint {
|
||||
@NotNull
|
||||
private final DependentFilesFilter myFilter;
|
||||
|
||||
@@ -724,7 +774,7 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
public class PackageConstraint extends UsageConstraint {
|
||||
public class PackageConstraint implements UsageConstraint {
|
||||
public final String packageName;
|
||||
|
||||
public PackageConstraint(final String packageName) {
|
||||
@@ -751,34 +801,6 @@ public class Mappings {
|
||||
return inheritorOf == null || !inheritorOf || super.checkResidence(residence);
|
||||
}
|
||||
}
|
||||
|
||||
public class NegationConstraint extends UsageConstraint {
|
||||
final UsageConstraint x;
|
||||
|
||||
public NegationConstraint(UsageConstraint x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkResidence(final int residence) {
|
||||
return !x.checkResidence(residence);
|
||||
}
|
||||
}
|
||||
|
||||
public class IntersectionConstraint extends UsageConstraint {
|
||||
final UsageConstraint x;
|
||||
final UsageConstraint y;
|
||||
|
||||
public IntersectionConstraint(final UsageConstraint x, final UsageConstraint y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkResidence(final int residence) {
|
||||
return x.checkResidence(residence) && y.checkResidence(residence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void affectAll(final int className, @NotNull final File sourceFile, final Collection<File> affectedFiles, final Collection<File> alreadyCompiledFiles, @Nullable final DependentFilesFilter filter) {
|
||||
@@ -1022,11 +1044,19 @@ public class Mappings {
|
||||
|
||||
private class FileClasses {
|
||||
final File myFileName;
|
||||
final Set<ClassRepr> myFileClasses;
|
||||
final Set<ClassRepr> myFileClasses = new THashSet<>();
|
||||
final Set<ModuleRepr> myFileModules = new THashSet<>();
|
||||
|
||||
FileClasses(File fileName, Collection<ClassRepr> fileClasses) {
|
||||
this.myFileName = fileName;
|
||||
this.myFileClasses = new HashSet<>(fileClasses);
|
||||
FileClasses(File fileName, Collection<ClassFileRepr> fileContent) {
|
||||
myFileName = fileName;
|
||||
for (ClassFileRepr repr : fileContent) {
|
||||
if (repr instanceof ClassRepr) {
|
||||
myFileClasses.add((ClassRepr)repr);
|
||||
}
|
||||
else {
|
||||
myFileModules.add((ModuleRepr)repr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1035,12 +1065,14 @@ public class Mappings {
|
||||
|
||||
final public Set<UsageRepr.Usage> myAffectedUsages = new HashSet<>();
|
||||
final public Set<UsageRepr.AnnotationUsage> myAnnotationQuery = new HashSet<>();
|
||||
final public Map<UsageRepr.Usage, Util.UsageConstraint> myUsageConstraints = new HashMap<>();
|
||||
final public Map<UsageRepr.Usage, UsageConstraint> myUsageConstraints = new HashMap<>();
|
||||
|
||||
final Difference.Specifier<ClassRepr, ClassRepr.Diff> myClassDiff;
|
||||
final Difference.Specifier<ModuleRepr, ModuleRepr.Diff> myModulesDiff;
|
||||
|
||||
private DiffState(Difference.Specifier<ClassRepr, ClassRepr.Diff> classDiff) {
|
||||
this.myClassDiff = classDiff;
|
||||
DiffState(Difference.Specifier<ClassRepr, ClassRepr.Diff> classDiff, Difference.Specifier<ModuleRepr, ModuleRepr.Diff> modulesDiff) {
|
||||
myClassDiff = classDiff;
|
||||
myModulesDiff = modulesDiff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1120,10 +1152,10 @@ public class Mappings {
|
||||
if (removed != null) {
|
||||
for (final String file : removed) {
|
||||
final File sourceFile = new File(file);
|
||||
final Collection<ClassRepr> classes = mySourceFileToClasses.get(sourceFile);
|
||||
final Collection<ClassFileRepr> classes = mySourceFileToClasses.get(sourceFile);
|
||||
|
||||
if (classes != null) {
|
||||
for (ClassRepr c : classes) {
|
||||
for (ClassFileRepr c : classes) {
|
||||
debug("Affecting usages of removed class ", c.name);
|
||||
affectAll(c.name, sourceFile, myAffectedFiles, myCompiledFiles, myFilter);
|
||||
}
|
||||
@@ -1160,7 +1192,7 @@ public class Mappings {
|
||||
|
||||
if (!m.isPrivate() && m.name != myInitName) {
|
||||
if (oldItRef == null) {
|
||||
oldItRef = new Ref<>(getReprByName(null, it.name)); // lazy init
|
||||
oldItRef = new Ref<>(getClassReprByName(null, it.name)); // lazy init
|
||||
}
|
||||
final ClassRepr oldIt = oldItRef.get();
|
||||
|
||||
@@ -1240,7 +1272,7 @@ public class Mappings {
|
||||
|
||||
final TIntHashSet subClasses = getAllSubclasses(it.name);
|
||||
subClasses.forEach(subClass -> {
|
||||
final ClassRepr r = myFuture.reprByName(subClass);
|
||||
final ClassRepr r = myFuture.classReprByName(subClass);
|
||||
if (r == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -1248,7 +1280,7 @@ public class Mappings {
|
||||
if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
|
||||
final int outerClass = r.getOuterClassName();
|
||||
if (!isEmpty(outerClass)) {
|
||||
final ClassRepr outerClassRepr = myFuture.reprByName(outerClass);
|
||||
final ClassRepr outerClassRepr = myFuture.classReprByName(outerClass);
|
||||
if (outerClassRepr != null && (myFuture.isMethodVisible(outerClassRepr, m) || myFuture.extendsLibraryClass(outerClassRepr, null))) {
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
@@ -1320,7 +1352,7 @@ public class Mappings {
|
||||
if (!m.isAbstract()) {
|
||||
propagated.forEach(p -> {
|
||||
if (p != it.name) {
|
||||
final ClassRepr s = myFuture.reprByName(p);
|
||||
final ClassRepr s = myFuture.classReprByName(p);
|
||||
|
||||
if (s != null) {
|
||||
final Collection<Pair<MethodRepr, ClassRepr>> overridenInS = myFuture.findOverriddenMethods(m, s);
|
||||
@@ -1538,7 +1570,7 @@ public class Mappings {
|
||||
if (!f.isPrivate()) {
|
||||
final TIntHashSet subClasses = getAllSubclasses(classRepr.name);
|
||||
subClasses.forEach(subClass -> {
|
||||
final ClassRepr r = myFuture.reprByName(subClass);
|
||||
final ClassRepr r = myFuture.classReprByName(subClass);
|
||||
if (r != null) {
|
||||
final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
|
||||
if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
|
||||
@@ -1591,19 +1623,18 @@ public class Mappings {
|
||||
// nothing
|
||||
}
|
||||
else {
|
||||
Util.UsageConstraint constraint;
|
||||
UsageConstraint constraint;
|
||||
|
||||
if ((ff.isProtected() && f.isPublic()) || (f.isProtected() && ff.isPublic()) || (ff.isPackageLocal() && f.isProtected())) {
|
||||
constraint = myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name));
|
||||
constraint = myFuture.new InheritanceConstraint(cc.name).negate();
|
||||
}
|
||||
else if (ff.isPublic() && ff.isPackageLocal()) {
|
||||
constraint = myFuture.new NegationConstraint(myFuture.new PackageConstraint(cc.getPackageName()));
|
||||
constraint = myFuture.new PackageConstraint(cc.getPackageName()).negate();
|
||||
}
|
||||
else {
|
||||
constraint =
|
||||
myFuture.new IntersectionConstraint(myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name)),
|
||||
myFuture.new NegationConstraint(
|
||||
myFuture.new PackageConstraint(cc.getPackageName())));
|
||||
final Util.InheritanceConstraint inherit = myFuture.new InheritanceConstraint(cc.name);
|
||||
final Util.PackageConstraint matchPackage = myFuture.new PackageConstraint(cc.getPackageName());
|
||||
constraint = inherit.negate().and(matchPackage.negate());
|
||||
}
|
||||
|
||||
for (final UsageRepr.Usage usage : localUsages) {
|
||||
@@ -1803,7 +1834,7 @@ public class Mappings {
|
||||
if (superClassChanged) {
|
||||
myDelta.registerRemovedSuperClass(changedClass.name, changedClass.getSuperClass().className);
|
||||
|
||||
final ClassRepr newClass = myDelta.getReprByName(null, changedClass.name);
|
||||
final ClassRepr newClass = myDelta.getClassReprByName(null, changedClass.name);
|
||||
|
||||
assert (newClass != null);
|
||||
|
||||
@@ -2143,12 +2174,12 @@ public class Mappings {
|
||||
|
||||
debug("Dependent class: ", depClass);
|
||||
|
||||
final ClassRepr classRepr = getReprByName(depFile, depClass);
|
||||
if (classRepr == null) {
|
||||
final ClassFileRepr repr = getReprByName(depFile, depClass);
|
||||
if (repr == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Set<UsageRepr.Usage> depUsages = classRepr.getUsages();
|
||||
final Set<UsageRepr.Usage> depUsages = repr.getUsages();
|
||||
if (depUsages == null || depUsages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -2164,7 +2195,7 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
else if (state.myAffectedUsages.contains(usage)) {
|
||||
final Util.UsageConstraint constraint = state.myUsageConstraints.get(usage);
|
||||
final UsageConstraint constraint = state.myUsageConstraints.get(usage);
|
||||
if (constraint == null) {
|
||||
debug("Added file with no constraints");
|
||||
myAffectedFiles.add(depFile);
|
||||
@@ -2196,13 +2227,13 @@ public class Mappings {
|
||||
processDisappearedClasses();
|
||||
|
||||
final List<FileClasses> newClasses = new ArrayList<>();
|
||||
myDelta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
|
||||
myDelta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassFileRepr>>() {
|
||||
@Override
|
||||
public boolean execute(File fileName, Collection<ClassRepr> classes) {
|
||||
public boolean execute(File fileName, Collection<ClassFileRepr> content) {
|
||||
if (myFilesToCompile == null || myFilesToCompile.contains(fileName)) {
|
||||
// Consider only files actually compiled in this round.
|
||||
// For other sources the list of classes taken from this map will be possibly incomplete.
|
||||
newClasses.add(new FileClasses(fileName, classes));
|
||||
newClasses.add(new FileClasses(fileName, content));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -2210,10 +2241,28 @@ public class Mappings {
|
||||
|
||||
for (final FileClasses compiledFile : newClasses) {
|
||||
final File fileName = compiledFile.myFileName;
|
||||
final Set<ClassRepr> classes = compiledFile.myFileClasses;
|
||||
final Set<ClassRepr> pastClasses = (Set<ClassRepr>)mySourceFileToClasses.get(fileName);
|
||||
final DiffState state = new DiffState(Difference.make(pastClasses, classes));
|
||||
|
||||
final Set<ClassRepr> pastClasses = new THashSet<>();
|
||||
final Set<ModuleRepr> pastModules = new THashSet<>();
|
||||
final Collection<ClassFileRepr> past = mySourceFileToClasses.get(fileName);
|
||||
if (past != null) {
|
||||
for (ClassFileRepr repr : past) {
|
||||
if (repr instanceof ClassRepr) {
|
||||
pastClasses.add((ClassRepr)repr);
|
||||
}
|
||||
else {
|
||||
pastModules.add((ModuleRepr)repr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final DiffState state = new DiffState(
|
||||
Difference.make(pastClasses, compiledFile.myFileClasses),
|
||||
Difference.make(pastModules, compiledFile.myFileModules)
|
||||
);
|
||||
|
||||
if (!myEasyMode) {
|
||||
processModules(state, fileName);
|
||||
}
|
||||
if (!processChangedClasses(state)) {
|
||||
if (!myEasyMode) {
|
||||
// turning non-incremental
|
||||
@@ -2280,6 +2329,112 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processModules(final DiffState state, File fileName) {
|
||||
final Difference.Specifier<ModuleRepr, ModuleRepr.Diff> modulesDiff = state.myModulesDiff;
|
||||
if (modulesDiff.unchanged()) {
|
||||
return;
|
||||
}
|
||||
for (ModuleRepr removedModule : modulesDiff.removed()) {
|
||||
myDelta.addDeletedClass(removedModule, fileName);
|
||||
myPresent.affectDependentModules(state, removedModule.name, null, true);
|
||||
}
|
||||
|
||||
for (Pair<ModuleRepr, ModuleRepr.Diff> pair : modulesDiff.changed()) {
|
||||
final ModuleRepr moduleRepr = pair.first;
|
||||
final ModuleRepr.Diff d = pair.second;
|
||||
boolean affectSelf = false;
|
||||
boolean affectDeps = false;
|
||||
UsageConstraint constraint = null;
|
||||
|
||||
myDelta.addChangedClass(moduleRepr.name);
|
||||
|
||||
if (d.versionChanged()) {
|
||||
final int version = moduleRepr.getVersion();
|
||||
myPresent.affectDependentModules(state, moduleRepr.name, new UsageConstraint() {
|
||||
public boolean checkResidence(int dep) {
|
||||
final ModuleRepr depModule = myPresent.moduleReprByName(dep);
|
||||
if (depModule != null) {
|
||||
for (ModuleRequiresRepr requires : depModule.getRequires()) {
|
||||
if (requires.name == moduleRepr.name && requires.getVersion() == version) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
final Difference.Specifier<ModuleRequiresRepr, ModuleRequiresRepr.Diff> requiresDiff = d.requires();
|
||||
for (ModuleRequiresRepr removed : requiresDiff.removed()) {
|
||||
affectSelf = true;
|
||||
if (removed.isTransitive()) {
|
||||
affectDeps = true;
|
||||
constraint = UsageConstraint.ANY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (Pair<ModuleRequiresRepr, ModuleRequiresRepr.Diff> changed : requiresDiff.changed()) {
|
||||
affectSelf |= changed.second.versionChanged();
|
||||
if (changed.second.becameNonTransitive()) {
|
||||
affectDeps = true;
|
||||
// we could have created more precise constraint here: analyze if required module (recursively)
|
||||
// has only qualified exports that include given module's name. But this seems to be excessive since
|
||||
// in most cases module's exports are unqualified, so that any other module can access the exported API.
|
||||
constraint = UsageConstraint.ANY;
|
||||
}
|
||||
}
|
||||
|
||||
final Difference.Specifier<ModulePackageRepr, ModulePackageRepr.Diff> exportsDiff = d.exports();
|
||||
|
||||
if (!affectDeps) {
|
||||
for (ModulePackageRepr removedPackage : exportsDiff.removed()) {
|
||||
affectDeps = true;
|
||||
if (!removedPackage.isQualified()) {
|
||||
constraint = UsageConstraint.ANY;
|
||||
break;
|
||||
}
|
||||
for (Integer name : removedPackage.getModuleNames()) {
|
||||
final UsageConstraint matchName = UsageConstraint.exactMatch(name);
|
||||
if (constraint == null) {
|
||||
constraint = matchName;
|
||||
}
|
||||
else {
|
||||
constraint = constraint.or(matchName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!affectDeps || constraint != UsageConstraint.ANY) {
|
||||
for (Pair<ModulePackageRepr, ModulePackageRepr.Diff> p : exportsDiff.changed()) {
|
||||
final Collection<Integer> removedModuleNames = p.second.targetModules().removed();
|
||||
affectDeps |= !removedModuleNames.isEmpty();
|
||||
if (!removedModuleNames.isEmpty()) {
|
||||
affectDeps = true;
|
||||
for (Integer name : removedModuleNames) {
|
||||
final UsageConstraint matchName = UsageConstraint.exactMatch(name);
|
||||
if (constraint == null) {
|
||||
constraint = matchName;
|
||||
}
|
||||
else {
|
||||
constraint = constraint.or(matchName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (affectSelf) {
|
||||
myPresent.affectModule(moduleRepr, myAffectedFiles);
|
||||
}
|
||||
if (affectDeps) {
|
||||
myPresent.affectDependentModules(state, moduleRepr.name, constraint, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void differentiateOnRebuild(final Mappings delta) {
|
||||
@@ -2304,11 +2459,9 @@ public class Mappings {
|
||||
return new Differential(delta, removed, filesToCompile, compiledWithErrors, compiledFiles, affectedFiles, filter, constantSearch).differentiate();
|
||||
}
|
||||
|
||||
private void cleanupBackDependency(final int className,
|
||||
@Nullable Set<UsageRepr.Usage> usages,
|
||||
final IntIntMultiMaplet buffer) {
|
||||
private void cleanupBackDependency(final int className, @Nullable Set<UsageRepr.Usage> usages, final IntIntMultiMaplet buffer) {
|
||||
if (usages == null) {
|
||||
final ClassRepr repr = getReprByName(null, className);
|
||||
final ClassFileRepr repr = getReprByName(null, className);
|
||||
|
||||
if (repr != null) {
|
||||
usages = repr.getUsages();
|
||||
@@ -2322,7 +2475,7 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, File sourceFile, final Set<UsageRepr.Usage> usages, final IntIntMultiMaplet dependenciesTrashBin) {
|
||||
private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassFileRepr cr, File sourceFile, final Set<UsageRepr.Usage> usages, final IntIntMultiMaplet dependenciesTrashBin) {
|
||||
final int className = cr.name;
|
||||
|
||||
// it is safe to cleanup class information if it is mapped to non-existing files only
|
||||
@@ -2346,8 +2499,10 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
for (final int superSomething : cr.getSupers()) {
|
||||
delta.registerRemovedSuperClass(className, superSomething);
|
||||
if (cr instanceof ClassRepr) {
|
||||
for (final int superSomething : ((ClassRepr)cr).getSupers()) {
|
||||
delta.registerRemovedSuperClass(className, superSomething);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupBackDependency(className, usages, dependenciesTrashBin);
|
||||
@@ -2355,8 +2510,11 @@ public class Mappings {
|
||||
myClassToClassDependency.remove(className);
|
||||
myClassToSubclasses.remove(className);
|
||||
myClassToSourceFile.remove(className);
|
||||
if (!cr.isLocal() && !cr.isAnonymous()) {
|
||||
myShortClassNameIndex.removeFrom(myContext.get(cr.getShortName()), className);
|
||||
if (cr instanceof ClassRepr) {
|
||||
final ClassRepr _cr = (ClassRepr)cr;
|
||||
if (!_cr.isLocal() && !_cr.isAnonymous()) {
|
||||
myShortClassNameIndex.removeFrom(myContext.get(_cr.getShortName()), className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2374,10 +2532,10 @@ public class Mappings {
|
||||
if (removed != null) {
|
||||
for (final String file : removed) {
|
||||
final File deletedFile = new File(file);
|
||||
final Set<ClassRepr> fileClasses = (Set<ClassRepr>)mySourceFileToClasses.get(deletedFile);
|
||||
final Set<ClassFileRepr> fileClasses = (Set<ClassFileRepr>)mySourceFileToClasses.get(deletedFile);
|
||||
|
||||
if (fileClasses != null) {
|
||||
for (final ClassRepr aClass : fileClasses) {
|
||||
for (final ClassFileRepr aClass : fileClasses) {
|
||||
cleanupRemovedClass(delta, aClass, deletedFile, aClass.getUsages(), dependenciesTrashBin);
|
||||
}
|
||||
mySourceFileToClasses.remove(deletedFile);
|
||||
@@ -2386,8 +2544,8 @@ public class Mappings {
|
||||
}
|
||||
|
||||
if (!delta.isRebuild()) {
|
||||
for (final Pair<ClassRepr, File> pair : delta.getDeletedClasses()) {
|
||||
final ClassRepr deletedClass = pair.first;
|
||||
for (final Pair<ClassFileRepr, File> pair : delta.getDeletedClasses()) {
|
||||
final ClassFileRepr deletedClass = pair.first;
|
||||
cleanupRemovedClass(delta, deletedClass, pair.second, deletedClass.getUsages(), dependenciesTrashBin);
|
||||
}
|
||||
for (ClassRepr repr : delta.getAddedClasses()) {
|
||||
@@ -2450,7 +2608,7 @@ public class Mappings {
|
||||
});
|
||||
|
||||
delta.getChangedFiles().forEach(fileName -> {
|
||||
final Collection<ClassRepr> classes = delta.mySourceFileToClasses.get(fileName);
|
||||
final Collection<ClassFileRepr> classes = delta.mySourceFileToClasses.get(fileName);
|
||||
mySourceFileToClasses.replace(fileName, classes);
|
||||
return true;
|
||||
});
|
||||
@@ -2459,9 +2617,9 @@ public class Mappings {
|
||||
// In case some of these sources was not compiled, but the class was changed, we need to update
|
||||
// sourceToClasses mapping for such sources to include the updated ClassRepr version of the changed class
|
||||
final THashSet<File> unchangedSources = new THashSet<>(FileUtil.FILE_HASHING_STRATEGY);
|
||||
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
|
||||
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassFileRepr>>() {
|
||||
@Override
|
||||
public boolean execute(File source, Collection<ClassRepr> b) {
|
||||
public boolean execute(File source, Collection<ClassFileRepr> b) {
|
||||
unchangedSources.add(source);
|
||||
return true;
|
||||
}
|
||||
@@ -2469,11 +2627,11 @@ public class Mappings {
|
||||
unchangedSources.removeAll(delta.getChangedFiles());
|
||||
if (!unchangedSources.isEmpty()) {
|
||||
unchangedSources.forEach(unchangedSource -> {
|
||||
final Collection<ClassRepr> updatedClasses = delta.mySourceFileToClasses.get(unchangedSource);
|
||||
final Collection<ClassFileRepr> updatedClasses = delta.mySourceFileToClasses.get(unchangedSource);
|
||||
if (updatedClasses != null && !updatedClasses.isEmpty()) {
|
||||
final List<ClassRepr> classesToPut = new ArrayList<>();
|
||||
final List<ClassFileRepr> classesToPut = new ArrayList<>();
|
||||
final TIntHashSet updatedClassNames = new TIntHashSet();
|
||||
for (ClassRepr aClass : updatedClasses) {
|
||||
for (ClassFileRepr aClass : updatedClasses) {
|
||||
// from all generated classes on this round consider only 'differentiated' ones, for
|
||||
// which we can reliably say that the class has changed. Keep classes, for which no such checks were made,
|
||||
// to make it possible to create a diff and compare changes on next compilation rounds.
|
||||
@@ -2482,9 +2640,9 @@ public class Mappings {
|
||||
updatedClassNames.add(aClass.name);
|
||||
}
|
||||
}
|
||||
Collection<ClassRepr> currentClasses = mySourceFileToClasses.get(unchangedSource);
|
||||
final Collection<ClassFileRepr> currentClasses = mySourceFileToClasses.get(unchangedSource);
|
||||
if (currentClasses != null) {
|
||||
for (ClassRepr aClass : currentClasses) {
|
||||
for (ClassFileRepr aClass : currentClasses) {
|
||||
if (!updatedClassNames.contains(aClass.name)) {
|
||||
classesToPut.add(aClass);
|
||||
}
|
||||
@@ -2500,11 +2658,14 @@ public class Mappings {
|
||||
myClassToSubclasses.putAll(delta.myClassToSubclasses);
|
||||
myClassToSourceFile.replaceAll(delta.myClassToSourceFile);
|
||||
mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses);
|
||||
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
|
||||
public boolean execute(File src, Collection<ClassRepr> classes) {
|
||||
for (ClassRepr repr : classes) {
|
||||
if (!repr.isAnonymous() && !repr.isLocal()) {
|
||||
myShortClassNameIndex.put(myContext.get(repr.getShortName()), repr.name);
|
||||
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassFileRepr>>() {
|
||||
public boolean execute(File src, Collection<ClassFileRepr> classes) {
|
||||
for (ClassFileRepr repr : classes) {
|
||||
if (repr instanceof ClassRepr) {
|
||||
final ClassRepr clsRepr = (ClassRepr)repr;
|
||||
if (!clsRepr.isAnonymous() && !clsRepr.isLocal()) {
|
||||
myShortClassNameIndex.put(myContext.get(clsRepr.getShortName()), repr.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -2564,25 +2725,25 @@ public class Mappings {
|
||||
public void associate(String classFileName, Collection<String> sources, ClassReader cr) {
|
||||
synchronized (myLock) {
|
||||
final int classFileNameS = myContext.get(classFileName);
|
||||
final Pair<ClassRepr, Set<UsageRepr.Usage>> result = new ClassfileAnalyzer(myContext).analyze(classFileNameS, cr);
|
||||
final ClassRepr repr = result.first;
|
||||
if (repr != null) {
|
||||
final Set<UsageRepr.Usage> localUsages = result.second;
|
||||
final int className = repr.name;
|
||||
final ClassFileRepr result = new ClassfileAnalyzer(myContext).analyze(classFileNameS, cr);
|
||||
if (result != null) {
|
||||
// since java9 'repr' can represent either a class or a compiled module-info.java
|
||||
final int className = result.name;
|
||||
|
||||
for (String sourceFileName : sources) {
|
||||
final File sourceFile = new File(sourceFileName);
|
||||
myClassToSourceFile.put(className, sourceFile);
|
||||
mySourceFileToClasses.put(sourceFile, repr);
|
||||
mySourceFileToClasses.put(sourceFile, result);
|
||||
}
|
||||
|
||||
for (final int s : repr.getSupers()) {
|
||||
myClassToSubclasses.put(s, className);
|
||||
if (result instanceof ClassRepr) {
|
||||
for (final int s : ((ClassRepr)result).getSupers()) {
|
||||
myClassToSubclasses.put(s, className);
|
||||
}
|
||||
}
|
||||
|
||||
for (final UsageRepr.Usage u : localUsages) {
|
||||
for (final UsageRepr.Usage u : result.getUsages()) {
|
||||
final int owner = u.getOwner();
|
||||
|
||||
if (owner != className) {
|
||||
myClassToClassDependency.put(owner, className);
|
||||
}
|
||||
@@ -2618,7 +2779,7 @@ public class Mappings {
|
||||
myPostPasses.offer(() -> {
|
||||
final int rootClassName = myContext.get(className.replace(".", "/"));
|
||||
final Collection<File> fileNames = myClassToSourceFile.get(rootClassName);
|
||||
final ClassRepr repr = fileNames != null && !fileNames.isEmpty()? getReprByName(fileNames.iterator().next(), rootClassName) : null;
|
||||
final ClassRepr repr = fileNames != null && !fileNames.isEmpty()? getClassReprByName(fileNames.iterator().next(), rootClassName) : null;
|
||||
|
||||
for (final String i : allImports) {
|
||||
final int iname = myContext.get(i.replace('.', '/'));
|
||||
@@ -2637,8 +2798,19 @@ public class Mappings {
|
||||
|
||||
@Nullable
|
||||
public Set<ClassRepr> getClasses(final String sourceFileName) {
|
||||
final File f = new File(sourceFileName);
|
||||
synchronized (myLock) {
|
||||
return (Set<ClassRepr>)mySourceFileToClasses.get(new File(sourceFileName));
|
||||
final Collection<ClassFileRepr> reprs = mySourceFileToClasses.get(f);
|
||||
if (reprs == null || reprs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final Set<ClassRepr> result = new THashSet<>();
|
||||
for (ClassFileRepr repr : reprs) {
|
||||
if (repr instanceof ClassRepr) {
|
||||
result.add((ClassRepr)repr);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2736,7 +2908,7 @@ public class Mappings {
|
||||
return myIsRebuild;
|
||||
}
|
||||
|
||||
private void addDeletedClass(final ClassRepr cr, File fileName) {
|
||||
private void addDeletedClass(final ClassFileRepr cr, File fileName) {
|
||||
assert (myDeletedClasses != null);
|
||||
|
||||
myDeletedClasses.add(Pair.create(cr, fileName));
|
||||
@@ -2764,7 +2936,7 @@ public class Mappings {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<Pair<ClassRepr, File>> getDeletedClasses() {
|
||||
private Set<Pair<ClassFileRepr, File>> getDeletedClasses() {
|
||||
return myDeletedClasses == null ? Collections.emptySet() : Collections.unmodifiableSet(myDeletedClasses);
|
||||
}
|
||||
|
||||
|
||||
+10
-31
@@ -45,7 +45,11 @@ class MethodRepr extends ProtoMember {
|
||||
public final TypeRepr.AbstractType[] myArgumentTypes;
|
||||
public final Set<TypeRepr.AbstractType> myExceptions;
|
||||
|
||||
public static abstract class Diff extends Difference {
|
||||
public static abstract class Diff extends DifferenceImpl {
|
||||
|
||||
Diff(@NotNull Difference delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
public abstract Specifier<ParamAnnotation, Difference> parameterAnnotations();
|
||||
|
||||
@@ -62,28 +66,14 @@ class MethodRepr extends ProtoMember {
|
||||
final Difference diff = super.difference(past);
|
||||
final Difference.Specifier<TypeRepr.AbstractType, Difference> excs = Difference.make(m.myExceptions, myExceptions);
|
||||
final Difference.Specifier<ParamAnnotation, Difference> paramAnnotations = Difference.make(m.myParameterAnnotations, myParameterAnnotations);
|
||||
final int base = paramAnnotations.unchanged()? diff.base() : diff.base() | Difference.ANNOTATIONS;
|
||||
|
||||
return new Diff() {
|
||||
@Override
|
||||
public Specifier<TypeRepr.ClassType, Difference> annotations() {
|
||||
return diff.annotations();
|
||||
}
|
||||
|
||||
return new Diff(diff) {
|
||||
@Override
|
||||
public Specifier<ParamAnnotation, Difference> parameterAnnotations() {
|
||||
return paramAnnotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addedModifiers() {
|
||||
return diff.addedModifiers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removedModifiers() {
|
||||
return diff.removedModifiers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean no() {
|
||||
return base() == NONE && !defaultAdded() && !defaultRemoved() && excs.unchanged() && paramAnnotations.unchanged();
|
||||
@@ -106,24 +96,13 @@ class MethodRepr extends ProtoMember {
|
||||
|
||||
@Override
|
||||
public int base() {
|
||||
final int base = diff.base();
|
||||
return paramAnnotations.unchanged()? base : base | Difference.ANNOTATIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean packageLocalOn() {
|
||||
return diff.packageLocalOn();
|
||||
return base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hadValue() {
|
||||
return m.hasValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean weakedAccess() {
|
||||
return diff.weakedAccess();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -164,10 +143,10 @@ class MethodRepr extends ProtoMember {
|
||||
final int size = DataInputOutputUtil.readINT(in);
|
||||
myArgumentTypes = RW.read(externalizer, in, new TypeRepr.AbstractType[size]);
|
||||
|
||||
myExceptions = (Set<TypeRepr.AbstractType>)RW.read(externalizer, new THashSet<>(0), in);
|
||||
myExceptions = RW.read(externalizer, new THashSet<>(0), in);
|
||||
|
||||
final DataExternalizer<TypeRepr.ClassType> clsTypeExternalizer = TypeRepr.classTypeExternalizer(context);
|
||||
myParameterAnnotations = (Set<ParamAnnotation>)RW.read(new DataExternalizer<ParamAnnotation>() {
|
||||
myParameterAnnotations = RW.read(new DataExternalizer<ParamAnnotation>() {
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, ParamAnnotation value) throws IOException {
|
||||
value.save(out);
|
||||
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
// Copyright 2000-2017 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.builders.java.dependencyView;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 02-Oct-17
|
||||
*/
|
||||
public class ModulePackageRepr extends Proto {
|
||||
private static final DataExternalizer<Integer> INT_EXTERNALIZER = new DataExternalizer<Integer>() {
|
||||
public void save(@NotNull DataOutput out, Integer value) throws IOException {
|
||||
DataInputOutputUtil.writeINT(out, value);
|
||||
}
|
||||
|
||||
public Integer read(@NotNull DataInput in) throws IOException {
|
||||
return DataInputOutputUtil.readINT(in);
|
||||
}
|
||||
};
|
||||
private final Set<Integer> myModuleNames = new THashSet<>();
|
||||
|
||||
protected ModulePackageRepr(DependencyContext context, int name, Collection<String> modules) {
|
||||
super(0, context.get(null), name, Collections.emptySet());
|
||||
for (String module : modules) {
|
||||
myModuleNames.add(context.get(module));
|
||||
}
|
||||
}
|
||||
|
||||
protected ModulePackageRepr(DependencyContext context, DataInput in) {
|
||||
super(context, in);
|
||||
RW.read(INT_EXTERNALIZER, myModuleNames, in);
|
||||
}
|
||||
|
||||
public Set<Integer> getModuleNames() {
|
||||
return Collections.unmodifiableSet(myModuleNames);
|
||||
}
|
||||
|
||||
public boolean isQualified() {
|
||||
return !myModuleNames.isEmpty();
|
||||
}
|
||||
|
||||
public void save(DataOutput out) {
|
||||
super.save(out);
|
||||
RW.save(myModuleNames, INT_EXTERNALIZER, out);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return name == ((ModulePackageRepr)o).name;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 31 * name;
|
||||
}
|
||||
|
||||
public abstract static class Diff extends DifferenceImpl {
|
||||
|
||||
public abstract Specifier<Integer, Difference> targetModules();
|
||||
|
||||
Diff(@NotNull Difference delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
}
|
||||
|
||||
public Diff difference(Proto past) {
|
||||
final Difference.Specifier<Integer, Difference> targetModulesDiff = Difference.make(((ModulePackageRepr)past).myModuleNames, myModuleNames);
|
||||
return new Diff(super.difference(past)) {
|
||||
public Specifier<Integer, Difference> targetModules() {
|
||||
return targetModulesDiff;
|
||||
}
|
||||
|
||||
public boolean no() {
|
||||
return super.no() && targetModules().unchanged();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void toStream(DependencyContext context, PrintStream stream) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Module package: ").append(context.getValue(name));
|
||||
final Set<Integer> moduleNames = myModuleNames;
|
||||
if (moduleNames != null && !moduleNames.isEmpty()) {
|
||||
final List<String> names = new ArrayList<>();
|
||||
for (Integer moduleName : moduleNames) {
|
||||
names.add(context.getValue(moduleName));
|
||||
}
|
||||
Collections.sort(names, String::compareToIgnoreCase);
|
||||
sb.append(" to");
|
||||
for (String s : names) {
|
||||
sb.append(" ").append(s);
|
||||
}
|
||||
}
|
||||
stream.println(sb.toString());
|
||||
}
|
||||
|
||||
public static DataExternalizer<ModulePackageRepr> externalizer(final DependencyContext context) {
|
||||
return new DataExternalizer<ModulePackageRepr>() {
|
||||
public void save(@NotNull DataOutput out, ModulePackageRepr value) {
|
||||
value.save(out);
|
||||
}
|
||||
|
||||
public ModulePackageRepr read(@NotNull DataInput in) {
|
||||
return new ModulePackageRepr(context, in);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
// Copyright 2000-2017 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.builders.java.dependencyView;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 30-Sep-17
|
||||
*/
|
||||
public class ModuleRepr extends ClassFileRepr{
|
||||
private final int myVersion;
|
||||
private final Set<ModuleRequiresRepr> myRequires; // module names
|
||||
private final Set<ModulePackageRepr> myExports; // package names
|
||||
|
||||
public ModuleRepr(DependencyContext context, int access, int version, int fileName, int name, Set<ModuleRequiresRepr> requires, Set<ModulePackageRepr> exports, Set<UsageRepr.Usage> usages) {
|
||||
super(access, context.get(null), name, Collections.emptySet(), fileName, context, usages);
|
||||
myVersion = version;
|
||||
myRequires = requires;
|
||||
myExports = exports;
|
||||
updateClassUsages(context, usages);
|
||||
}
|
||||
|
||||
public ModuleRepr(DependencyContext context, DataInput in) {
|
||||
super(context, in);
|
||||
try {
|
||||
myVersion = DataInputOutputUtil.readINT(in);
|
||||
myRequires = RW.read(ModuleRequiresRepr.externalizer(context), new THashSet<>(), in);
|
||||
myExports = RW.read(ModulePackageRepr.externalizer(context), new THashSet<>(), in);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
public Set<ModuleRequiresRepr> getRequires() {
|
||||
return myRequires;
|
||||
}
|
||||
|
||||
public Set<ModulePackageRepr> getExports() {
|
||||
return myExports;
|
||||
}
|
||||
|
||||
public void save(DataOutput out) {
|
||||
super.save(out);
|
||||
try {
|
||||
DataInputOutputUtil.writeINT(out, myVersion);
|
||||
RW.save(myRequires, out);
|
||||
RW.save(myExports, out);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateClassUsages(DependencyContext context, Set<UsageRepr.Usage> s) {
|
||||
for (ModuleRequiresRepr require : myRequires) {
|
||||
if (require.name != name) {
|
||||
s.add(UsageRepr.createModuleUsage(context, require.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void toStream(DependencyContext context, PrintStream stream) {
|
||||
super.toStream(context, stream);
|
||||
|
||||
stream.println(" Requires:");
|
||||
streamProtoCollection(context, stream, myRequires);
|
||||
stream.println(" End Of Requires");
|
||||
|
||||
stream.println(" Exports:");
|
||||
streamProtoCollection(context, stream, myExports);
|
||||
stream.println(" End Of Exports");
|
||||
}
|
||||
|
||||
private static <T extends Proto> void streamProtoCollection(DependencyContext context, PrintStream stream, final Collection<T> collection) {
|
||||
final List<T> list = new ArrayList<>(collection);
|
||||
list.sort(Comparator.comparingInt(o -> o.name));
|
||||
for (T reqRepr : list) {
|
||||
reqRepr.toStream(context, stream);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean requiresTransitevely(int requirementName) {
|
||||
for (ModuleRequiresRepr require : myRequires) {
|
||||
if (require.name == requirementName) {
|
||||
return require.isTransitive();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract static class Diff extends DifferenceImpl {
|
||||
|
||||
Diff(@NotNull Difference delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
public abstract Specifier<ModuleRequiresRepr, ModuleRequiresRepr.Diff> requires();
|
||||
|
||||
public abstract Specifier<ModulePackageRepr, ModulePackageRepr.Diff> exports();
|
||||
|
||||
public abstract boolean versionChanged();
|
||||
|
||||
public boolean no() {
|
||||
return base() == NONE && requires().unchanged() && exports().unchanged() && !versionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public Diff difference(Proto past) {
|
||||
final Difference delegate = super.difference(past);
|
||||
final ModuleRepr pastModule = (ModuleRepr)past;
|
||||
final int base = !getUsages().equals(pastModule.getUsages())? delegate.base() | Difference.USAGES : delegate.base();
|
||||
|
||||
return new Diff(delegate) {
|
||||
public Specifier<ModuleRequiresRepr, ModuleRequiresRepr.Diff> requires() {
|
||||
return Difference.make(pastModule.myRequires, myRequires);
|
||||
}
|
||||
|
||||
public Specifier<ModulePackageRepr, ModulePackageRepr.Diff> exports() {
|
||||
return Difference.make(pastModule.myExports, myExports);
|
||||
}
|
||||
|
||||
public boolean versionChanged() {
|
||||
return pastModule.getVersion() != myVersion;
|
||||
}
|
||||
|
||||
public int base() {
|
||||
return base;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static DataExternalizer<ModuleRepr> externalizer(final DependencyContext context) {
|
||||
return new DataExternalizer<ModuleRepr>() {
|
||||
@Override
|
||||
public void save(@NotNull final DataOutput out, final ModuleRepr value) throws IOException {
|
||||
value.save(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleRepr read(@NotNull final DataInput in) throws IOException {
|
||||
return new ModuleRepr(context, in);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
// Copyright 2000-2017 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.builders.java.dependencyView;
|
||||
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 02-Oct-17
|
||||
*/
|
||||
public class ModuleRequiresRepr extends Proto {
|
||||
|
||||
private final int myVersion;
|
||||
|
||||
public ModuleRequiresRepr(DependencyContext context, int access, int name, String version) {
|
||||
super(access, context.get(null), name, Collections.emptySet());
|
||||
myVersion = context.get(version);
|
||||
}
|
||||
|
||||
public ModuleRequiresRepr(DependencyContext context, DataInput in) {
|
||||
super(context, in);
|
||||
try {
|
||||
myVersion = DataInputOutputUtil.readINT(in);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTransitive() {
|
||||
return (access & Opcodes.ACC_TRANSITIVE) != 0;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out) {
|
||||
try {
|
||||
super.save(out);
|
||||
DataInputOutputUtil.writeINT(out, myVersion);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static DataExternalizer<ModuleRequiresRepr> externalizer(DependencyContext context) {
|
||||
return new DataExternalizer<ModuleRequiresRepr>() {
|
||||
public void save(@NotNull DataOutput out, ModuleRequiresRepr value) throws IOException {
|
||||
value.save(out);
|
||||
}
|
||||
|
||||
public ModuleRequiresRepr read(@NotNull DataInput in) throws IOException {
|
||||
return new ModuleRequiresRepr(context, in);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public abstract static class Diff extends DifferenceImpl {
|
||||
|
||||
Diff(@NotNull Difference delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
public abstract boolean versionChanged();
|
||||
|
||||
public abstract boolean becameNonTransitive();
|
||||
}
|
||||
|
||||
public Diff difference(Proto past) {
|
||||
final ModuleRequiresRepr pastRequirement = (ModuleRequiresRepr)past;
|
||||
return new Diff(super.difference(past)) {
|
||||
public boolean versionChanged() {
|
||||
return pastRequirement.myVersion != myVersion;
|
||||
}
|
||||
|
||||
public boolean no() {
|
||||
return super.no() && !versionChanged();
|
||||
}
|
||||
|
||||
public boolean becameNonTransitive() {
|
||||
return pastRequirement.isTransitive() && !ModuleRequiresRepr.this.isTransitive();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return name == ((ModuleRequiresRepr)o).name;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 31 * name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toStream(final DependencyContext context, final PrintStream stream) {
|
||||
stream.println("Requires module: " + context.getValue(name) + ":" + access + ":" + myVersion);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user