mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
recompile classes with potentially ambiguous method calls when vararg method is added
This commit is contained in:
@@ -5,8 +5,10 @@ Compiling files:
|
||||
src/A.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/AddMethod/C.class
|
||||
out/production/AddMethod/D.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/C.java
|
||||
src/D.java
|
||||
End of files
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
Cleaning output files:
|
||||
out/production/AddVarargMethod/A.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/A.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/AddVarargMethod/C.class
|
||||
out/production/AddVarargMethod/D.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/C.java
|
||||
src/D.java
|
||||
End of files
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class A {
|
||||
void f (String x, Integer y) {
|
||||
|
||||
}
|
||||
|
||||
void f (String x, Integer y, Long z, String... v){
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class A {
|
||||
void f (String x, Integer y, String... v) {
|
||||
|
||||
}
|
||||
|
||||
void f (String x, Integer y, Long z, String... v){
|
||||
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class C {
|
||||
void f (A a){
|
||||
a.f("1", 2);
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class D {
|
||||
void f(A a){
|
||||
a.f("1", 2, null, "comment");
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -173,7 +173,7 @@ class ClassfileAnalyzer {
|
||||
}
|
||||
|
||||
myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className));
|
||||
|
||||
myUsedArguments.add(methodName);
|
||||
}
|
||||
@@ -183,7 +183,7 @@ class ClassfileAnalyzer {
|
||||
final String methodDescr = "()" + desc;
|
||||
|
||||
myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className, methodDescr));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, myType.className));
|
||||
|
||||
myUsedArguments.add(methodName);
|
||||
}
|
||||
@@ -526,7 +526,7 @@ class ClassfileAnalyzer {
|
||||
final int methodOwner = myContext.get(owner);
|
||||
|
||||
myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner, desc));
|
||||
myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner));
|
||||
addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc)));
|
||||
|
||||
super.visitMethodInsn(opcode, owner, name, desc, itf);
|
||||
|
||||
@@ -400,16 +400,31 @@ public class Mappings {
|
||||
|
||||
private boolean hasOverriddenMethods(final ClassRepr fromClass, final MethodRepr.Predicate predicate) {
|
||||
for (int superName : fromClass.getSupers()) {
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
if (superClass == null) {
|
||||
return true; // assumption
|
||||
if (superName == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
for (MethodRepr mm : superClass.findMethods(predicate)) {
|
||||
if (isVisibleIn(superClass, mm, fromClass)) {
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
if (superClass != null) {
|
||||
for (MethodRepr mm : superClass.findMethods(predicate)) {
|
||||
if (isVisibleIn(superClass, mm, fromClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (hasOverriddenMethods(superClass, predicate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (hasOverriddenMethods(superClass, predicate)) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean extendsLibraryClass(final ClassRepr fromClass) {
|
||||
for (int superName : fromClass.getSupers()) {
|
||||
if (superName != myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(superName);
|
||||
if (superClass == null || extendsLibraryClass(superClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -440,6 +455,9 @@ public class Mappings {
|
||||
|
||||
void addOverriddenFields(final FieldRepr f, final ClassRepr fromClass, final Collection<Pair<FieldRepr, ClassRepr>> container) {
|
||||
for (int supername : fromClass.getSupers()) {
|
||||
if (supername == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(supername);
|
||||
if (superClass != null) {
|
||||
final FieldRepr ff = superClass.findField(f.name);
|
||||
@@ -455,6 +473,9 @@ public class Mappings {
|
||||
|
||||
boolean hasOverriddenFields(final FieldRepr f, final ClassRepr fromClass) {
|
||||
for (int supername : fromClass.getSupers()) {
|
||||
if (supername == myObjectClassName) {
|
||||
continue;
|
||||
}
|
||||
final ClassRepr superClass = reprByName(supername);
|
||||
if (superClass != null) {
|
||||
final FieldRepr ff = superClass.findField(f.name);
|
||||
@@ -534,15 +555,8 @@ public class Mappings {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
boolean isMethodVisible(final int className, final MethodRepr m) {
|
||||
final ClassRepr r = reprByName(className);
|
||||
if (r != null) {
|
||||
if (r.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0) {
|
||||
return true;
|
||||
}
|
||||
return hasOverriddenMethods(r, MethodRepr.equalByJavaRules(m));
|
||||
}
|
||||
return false;
|
||||
boolean isMethodVisible(final ClassRepr classRepr, final MethodRepr m) {
|
||||
return classRepr.findMethods(MethodRepr.equalByJavaRules(m)).size() > 0 || hasOverriddenMethods(classRepr, MethodRepr.equalByJavaRules(m));
|
||||
}
|
||||
|
||||
boolean isFieldVisible(final int className, final FieldRepr field) {
|
||||
@@ -1082,10 +1096,7 @@ public class Mappings {
|
||||
}
|
||||
final ClassRepr oldIt = oldItRef.get();
|
||||
|
||||
if (oldIt != null && myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) {
|
||||
|
||||
}
|
||||
else {
|
||||
if (oldIt == null || !myPresent.hasOverriddenMethods(oldIt, MethodRepr.equalByJavaRules(m))) {
|
||||
if (m.myArgumentTypes.length > 0) {
|
||||
propagated = myFuture.propagateMethodAccess(m, it.name);
|
||||
debug("Conservative case on overriding methods, affecting method usages");
|
||||
@@ -1170,10 +1181,13 @@ public class Mappings {
|
||||
final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
|
||||
if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
|
||||
final int outerClass = r.getOuterClassName();
|
||||
if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
debug("Affecting file due to local overriding: ", sourceFileName);
|
||||
if (!isEmpty(outerClass)) {
|
||||
final ClassRepr outerClassRepr = myFuture.reprByName(outerClass);
|
||||
if (outerClassRepr != null && (myFuture.isMethodVisible(outerClassRepr, m) || myFuture.extendsLibraryClass(outerClassRepr))) {
|
||||
myAffectedFiles.addAll(sourceFileNames);
|
||||
for (File sourceFileName : sourceFileNames) {
|
||||
debug("Affecting file due to local overriding: ", sourceFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -112,8 +112,8 @@ class MethodRepr extends ProtoMember {
|
||||
public void updateClassUsages(final DependencyContext context, final int owner, final Set<UsageRepr.Usage> s) {
|
||||
myType.updateClassUsages(context, owner, s);
|
||||
|
||||
for (int i = 0; i < myArgumentTypes.length; i++) {
|
||||
myArgumentTypes[i].updateClassUsages(context, owner, s);
|
||||
for (final TypeRepr.AbstractType argType : myArgumentTypes) {
|
||||
argType.updateClassUsages(context, owner, s);
|
||||
}
|
||||
|
||||
if (myExceptions != null) {
|
||||
@@ -124,17 +124,17 @@ class MethodRepr extends ProtoMember {
|
||||
}
|
||||
|
||||
public MethodRepr(final DependencyContext context,
|
||||
final int a,
|
||||
final int n,
|
||||
final int s,
|
||||
final String d,
|
||||
final String[] e,
|
||||
final Object value) {
|
||||
super(a, s, n, TypeRepr.getType(context, Type.getReturnType(d)), value);
|
||||
final int accessFlags,
|
||||
final int name,
|
||||
final int signature,
|
||||
final String descriptor,
|
||||
final String[] exceptions,
|
||||
final Object defaultValue) {
|
||||
super(accessFlags, signature, name, TypeRepr.getType(context, Type.getReturnType(descriptor)), defaultValue);
|
||||
Set<TypeRepr.AbstractType> typeCollection =
|
||||
e != null ? new THashSet<TypeRepr.AbstractType>(e.length) : Collections.<TypeRepr.AbstractType>emptySet();
|
||||
myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, e, typeCollection);
|
||||
myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(d));
|
||||
exceptions != null ? new THashSet<TypeRepr.AbstractType>(exceptions.length) : Collections.<TypeRepr.AbstractType>emptySet();
|
||||
myExceptions = (Set<TypeRepr.AbstractType>)TypeRepr.createClassType(context, exceptions, typeCollection);
|
||||
myArgumentTypes = TypeRepr.getType(context, Type.getArgumentTypes(descriptor));
|
||||
}
|
||||
|
||||
public MethodRepr(final DependencyContext context, final DataInput in) {
|
||||
@@ -216,7 +216,7 @@ class MethodRepr extends ProtoMember {
|
||||
}
|
||||
|
||||
public UsageRepr.Usage createMetaUsage(final DependencyContext context, final int owner) {
|
||||
return UsageRepr.createMetaMethodUsage(context, name, owner, getDescr(context));
|
||||
return UsageRepr.createMetaMethodUsage(context, name, owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -278,52 +278,18 @@ class UsageRepr {
|
||||
}
|
||||
|
||||
public static class MetaMethodUsage extends FMUsage {
|
||||
private int myArity;
|
||||
|
||||
public MetaMethodUsage(final DependencyContext context, final int n, final int o, final String descr) {
|
||||
public MetaMethodUsage(final int n, final int o) {
|
||||
super(n, o);
|
||||
myArity = TypeRepr.getType(context, Type.getArgumentTypes(descr)).length;
|
||||
}
|
||||
|
||||
public MetaMethodUsage(final DataInput in) {
|
||||
super(in);
|
||||
try {
|
||||
myArity = DataInputOutputUtil.readINT(in);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final DataOutput out) {
|
||||
save(METAMETHOD_USAGE, out);
|
||||
try {
|
||||
DataInputOutputUtil.writeINT(out, myArity);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new BuildDataCorruptedException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
|
||||
MetaMethodUsage that = (MetaMethodUsage)o;
|
||||
|
||||
if (myArity != that.myArity) return false;
|
||||
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + myArity;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -334,7 +300,6 @@ class UsageRepr {
|
||||
@Override
|
||||
public void toStream(DependencyContext context, PrintStream stream) {
|
||||
super.toStream(context, stream);
|
||||
stream.println(" Arity: " + Integer.toString(myArity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,8 +644,8 @@ class UsageRepr {
|
||||
return context.getUsage(new MethodUsage(context, name, owner, descr));
|
||||
}
|
||||
|
||||
public static Usage createMetaMethodUsage(final DependencyContext context, final int name, final int owner, final String descr) {
|
||||
return context.getUsage(new MetaMethodUsage(context, name, owner, descr));
|
||||
public static Usage createMetaMethodUsage(final DependencyContext context, final int name, final int owner) {
|
||||
return context.getUsage(new MetaMethodUsage(name, owner));
|
||||
}
|
||||
|
||||
public static Usage createClassUsage(final DependencyContext context, final int name) {
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* Date: 10/7/11
|
||||
*/
|
||||
public class BuildDataManager implements StorageOwner {
|
||||
private static final int VERSION = 25;
|
||||
private static final int VERSION = 26;
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
|
||||
private static final String SRC_TO_FORM_STORAGE = "src-form";
|
||||
private static final String OUT_TARGET_STORAGE = "out-target";
|
||||
|
||||
@@ -203,4 +203,8 @@ public class MemberChangeTest extends IncrementalTestCase {
|
||||
public void testAddMethod() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAddVarargMethod() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user