diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log new file mode 100644 index 000000000000..98d7347e73f2 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log @@ -0,0 +1,16 @@ +Cleaning output files: +out/production/ChangeLambdaSAMMethodSignature/ppp/Client.class +out/production/ChangeLambdaSAMMethodSignature/ppp/DataProvider.class +out/production/ChangeLambdaSAMMethodSignature/ppp/Repository.class +End of files +Compiling files: +src/ppp/Client.java +src/ppp/DataProvider.java +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeLambdaSAMMethodSignature/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new new file mode 100644 index 000000000000..bcef65b859f9 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData(10)) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new new file mode 100644 index 000000000000..48cad7204add --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(int param); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java new file mode 100644 index 000000000000..83badb8b4311 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(()-> repo.getStorages()); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new new file mode 100644 index 000000000000..29625a07d866 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages(int param) { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log new file mode 100644 index 000000000000..74c5f74e7cc3 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/ChangeLambdaTargetReturnType/ppp/Repository.class +End of files +Compiling files: +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeLambdaTargetReturnType/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java new file mode 100644 index 000000000000..83badb8b4311 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(()-> repo.getStorages()); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new new file mode 100644 index 000000000000..f70ad61f7ea8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.Collection; + +public class Repository { + public Collection getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log new file mode 100644 index 000000000000..19e7ce03cf1f --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/ChangeMethodRefReturnType/ppp/Repository.class +End of files +Compiling files: +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeMethodRefReturnType/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java new file mode 100644 index 000000000000..3f1e0382a832 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(repo::getStorages); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new new file mode 100644 index 000000000000..f70ad61f7ea8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.Collection; + +public class Repository { + public Collection getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log new file mode 100644 index 000000000000..4b61261611d1 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log @@ -0,0 +1,16 @@ +Cleaning output files: +out/production/ChangeSAMMethodSignature/ppp/Client.class +out/production/ChangeSAMMethodSignature/ppp/DataProvider.class +out/production/ChangeSAMMethodSignature/ppp/Repository.class +End of files +Compiling files: +src/ppp/Client.java +src/ppp/DataProvider.java +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeSAMMethodSignature/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new new file mode 100644 index 000000000000..bcef65b859f9 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData(10)) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new new file mode 100644 index 000000000000..48cad7204add --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(int param); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java new file mode 100644 index 000000000000..3f1e0382a832 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(repo::getStorages); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new new file mode 100644 index 000000000000..29625a07d866 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages(int param) { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java index 137f4527b5a8..a67fa2563769 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.Pair; import gnu.trove.THashMap; import gnu.trove.THashSet; import gnu.trove.TIntHashSet; +import org.jetbrains.annotations.Nullable; import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.signature.SignatureReader; import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor; @@ -34,6 +35,7 @@ import java.util.Set; */ class ClassfileAnalyzer { + public static final String LAMBDA_FACTORY_CLASS = "java/lang/invoke/LambdaMetafactory"; private final DependencyContext myContext; ClassfileAnalyzer(DependencyContext context) { @@ -390,11 +392,11 @@ class ClassfileAnalyzer { } @Override - public FieldVisitor visitField(int access, String n, String desc, String signature, Object value) { + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { processSignature(signature); if ((access & Opcodes.ACC_SYNTHETIC) == 0) { - myFields.add(new FieldRepr(myContext, access, myContext.get(n), myContext.get(desc), myContext.get(signature), value)); + myFields.add(new FieldRepr(myContext, access, myContext.get(name), myContext.get(desc), myContext.get(signature), value)); } return new FieldVisitor(Opcodes.ASM5) { @@ -504,34 +506,118 @@ class ClassfileAnalyzer { @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { - final int fieldName = myContext.get(name); - final int fieldOwner = myContext.get(owner); - final int descr = myContext.get(desc); - - if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { - myUsages.add(UsageRepr.createFieldAssignUsage(myContext, fieldName, fieldOwner, descr)); - } - - if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) { - addClassUsage(TypeRepr.getType(myContext, descr)); - } - - myUsages.add(UsageRepr.createFieldUsage(myContext, fieldName, fieldOwner, descr)); + registerFieldUsage(opcode, owner, name, desc); super.visitFieldInsn(opcode, owner, name, desc); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - final int methodName = myContext.get(name); - final int methodOwner = myContext.get(owner); - - myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc)); - myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner)); - addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc))); - + registerMethodUsage(owner, name, desc); super.visitMethodInsn(opcode, owner, name, desc, itf); } + @Override + public void visitInvokeDynamicInsn(String methodName, String desc, Handle bsm, Object... bsmArgs) { + final Type returnType = Type.getReturnType(desc); + addClassUsage(TypeRepr.getType(myContext, returnType)); + + // common args processing + for (Object arg : bsmArgs) { + if (arg instanceof Type) { + final Type type = (Type)arg; + if (type.getSort() == Type.METHOD) { + for (Type argType : type.getArgumentTypes()) { + addClassUsage(TypeRepr.getType(myContext, argType)); + } + addClassUsage(TypeRepr.getType(myContext, type.getReturnType())); + } + else { + addClassUsage(TypeRepr.getType(myContext, type)); + } + } + else if (arg instanceof Handle) { + processMethodHandle((Handle)arg); + } + } + + if (LAMBDA_FACTORY_CLASS.equals(bsm.getOwner())) { + // This invokeDynamic implements a lambda or method reference usage. + // Need to register method usage for the corresponding SAM-type. + // First three arguments to the bootstrap methods are provided automatically by VM. + // Arguments in args array are expected to be as following: + // [0]: Type: Signature and return type of method to be implemented by the function object. + // [1]: Handle: implementation method handle + // [2]: Type: The signature and return type that should be enforced dynamically at invocation time. May be the same as samMethodType, or may be a specialization of it + // [...]: optional additional arguments + + if (returnType.getSort() == Type.OBJECT && bsmArgs.length >= 3) { + if (bsmArgs[0] instanceof Type) { + final Type samMethodType = (Type)bsmArgs[0]; + if (samMethodType.getSort() == Type.METHOD) { + registerMethodUsage(returnType.getInternalName(), methodName, samMethodType.getDescriptor()); + } + } + } + } + + super.visitInvokeDynamicInsn(methodName, desc, bsm, bsmArgs); + } + + private void processMethodHandle(Handle handle) { + final String memberOwner = handle.getOwner(); + if (myContext.get(memberOwner) != myName) { + // do not register access to own class members + final String memberName = handle.getName(); + final String memberDescriptor = handle.getDesc(); + if (isFieldAccessHandle(handle)) { + final int tag = handle.getTag(); + int opCode; + if (tag == Opcodes.H_GETFIELD) { + opCode = Opcodes.GETFIELD; + } + else if (tag == Opcodes.H_GETSTATIC) { + opCode = Opcodes.GETSTATIC; + } + else if (tag == Opcodes.H_PUTFIELD) { + opCode = Opcodes.PUTFIELD; + } + else if (tag == Opcodes.H_PUTSTATIC) { + opCode = Opcodes.PUTSTATIC; + } + else { + opCode = Opcodes.H_GETFIELD; + } + registerFieldUsage(opCode, memberOwner, memberName, memberDescriptor); + } + else { + registerMethodUsage(memberOwner, memberName, memberDescriptor); + } + } + } + + private void registerFieldUsage(int opcode, String owner, String fName, String desc) { + final int fieldName = myContext.get(fName); + final int fieldOwner = myContext.get(owner); + final int descr = myContext.get(desc); + if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { + myUsages.add(UsageRepr.createFieldAssignUsage(myContext, fieldName, fieldOwner, descr)); + } + if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) { + addClassUsage(TypeRepr.getType(myContext, descr)); + } + myUsages.add(UsageRepr.createFieldUsage(myContext, fieldName, fieldOwner, descr)); + } + + private void registerMethodUsage(String owner, String name, @Nullable String desc) { + final int methodOwner = myContext.get(owner); + final int methodName = myContext.get(name); + myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner)); + if (desc != null) { + myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc)); + addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc))); + } + } + private void addClassUsage(final TypeRepr.AbstractType type) { TypeRepr.ClassType classType = null; if (type instanceof TypeRepr.ClassType) { @@ -551,6 +637,11 @@ class ClassfileAnalyzer { }; } + private boolean isFieldAccessHandle(Handle handle) { + final int tag = handle.getTag(); + return tag == Opcodes.H_GETFIELD || tag == Opcodes.H_GETSTATIC || tag == Opcodes.H_PUTFIELD || tag == Opcodes.H_PUTSTATIC; + } + @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { if (outerName != null) { diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 4525aa74bd4d..f8b4e51ccd52 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -37,7 +37,9 @@ import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.serialization.PathMacroUtil; import org.jetbrains.jps.util.JpsPathUtil; -import java.io.*; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; /** * @author db @@ -212,6 +214,20 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { module.addSourceRoot(getUrl(testRootRelativePath), JavaSourceRootType.TEST_SOURCE); } + protected static boolean isRunningOnAtLeastJava(int javaVersion) { + final String versionString = System.getProperty("java.version"); + final String prefix = "1."; + final int startIndex = versionString.startsWith(prefix) ? prefix.length() : 0; + final int dotIndex = versionString.indexOf('.', startIndex); + try { + int version = Integer.parseInt(versionString.substring(startIndex, dotIndex > startIndex? dotIndex : versionString.length())); + return version >= javaVersion; + } + catch (NumberFormatException ignored) { + } + return false; + } + private static class StringProjectBuilderLogger extends ProjectBuilderLoggerBase { private final String myRoot; private StringBuilder myLog; diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java index 28093d91f8b8..839effbe7ac8 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java @@ -32,6 +32,42 @@ public class MethodPropertyTest extends IncrementalTestCase { doTest(); } + public void testChangeMethodRefReturnType() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeLambdaTargetReturnType() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeSAMMethodSignature() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeLambdaSAMMethodSignature() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + public void testChangeReturnType1() throws Exception { doTest(); }