summaryrefslogtreecommitdiffstats
path: root/org.aspectj.ajdt.core/src
diff options
context:
space:
mode:
authorAndy Clement <aclement@gopivotal.com>2014-03-18 22:21:20 -0700
committerAndy Clement <aclement@gopivotal.com>2014-03-18 22:21:20 -0700
commitc1c4a4d41f3173bb72040d91d42d07662ab703bd (patch)
treeee5f5bb17e86908b93504db85d2886e0375a94c5 /org.aspectj.ajdt.core/src
parentbedb85ee870c2c0dad34d68662c83ff7033dd746 (diff)
downloadaspectj-c1c4a4d41f3173bb72040d91d42d07662ab703bd.tar.gz
aspectj-c1c4a4d41f3173bb72040d91d42d07662ab703bd.zip
merging 1.7.4 fixes into 1.8.0
Diffstat (limited to 'org.aspectj.ajdt.core/src')
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties2
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java60
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java3
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java354
4 files changed, 402 insertions, 17 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
index c9a2bf417..c52a6d545 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties
@@ -5,7 +5,7 @@
org/aspectj/weaver/XlintDefault.properties for the default behavior and a template to copy.
### AspectJ-specific messages
compiler.name = AspectJ Compiler 1.8.0
-compiler.version = Eclipse Compiler BETA_JAVA8_3D6E745, 3.9
+compiler.version = Eclipse Compiler BETA_JAVA8_8661797, 3.9
compiler.copyright =
## this next one superceded by above...
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
index ffd2c61af..c6cdd88e7 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.StringTokenizer;
import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
import org.aspectj.util.FileUtil;
@@ -59,6 +60,7 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags {
private File configFile;
private String lintMode = AJLINT_DEFAULT;
+ private Map<String,String> lintOptionsMap = null;
private File lintSpecFile = null;
private int changes = EVERYTHING; // bitflags, see CompilerConfigurationChangeFlags
@@ -443,35 +445,71 @@ public class AjBuildConfig implements CompilerConfigurationChangeFlags {
public String getLintMode() {
return lintMode;
}
+
+ public Map<String,String> getLintOptionsMap() {
+ return lintOptionsMap;
+ }
// options...
public void setLintMode(String lintMode) {
- this.lintMode = lintMode;
String lintValue = null;
+ this.lintMode = lintMode;
if (AJLINT_IGNORE.equals(lintMode)) {
lintValue = AjCompilerOptions.IGNORE;
} else if (AJLINT_WARN.equals(lintMode)) {
lintValue = AjCompilerOptions.WARNING;
} else if (AJLINT_ERROR.equals(lintMode)) {
lintValue = AjCompilerOptions.ERROR;
+ } else {
+ // Possibly a name=value comma separated list of configurations
+ if (lintMode.indexOf("=")!=-1) {
+ this.lintMode = AJLINT_DEFAULT;
+ lintOptionsMap = new HashMap<String,String>();
+ StringTokenizer tokenizer = new StringTokenizer(lintMode,",");
+ while (tokenizer.hasMoreElements()) {
+ String option = tokenizer.nextToken();
+ int equals = option.indexOf("=");
+ if (equals!=-1) {
+ String key = option.substring(0,equals);
+ String value = option.substring(equals+1);
+ lintOptionsMap.put(key,value);
+ }
+ }
+ }
}
- if (lintValue != null) {
+ if (lintValue != null || lintOptionsMap != null ) {
Map<String, String> lintOptions = new HashMap<String, String>();
- lintOptions.put(AjCompilerOptions.OPTION_ReportInvalidAbsoluteTypeName, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportInvalidWildcardTypeName, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportUnresolvableMember, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportTypeNotExposedToWeaver, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportShadowNotInStructure, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportUnmatchedSuperTypeInCall, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportCannotImplementLazyTJP, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportNeedSerialVersionUIDField, lintValue);
- lintOptions.put(AjCompilerOptions.OPTION_ReportIncompatibleSerialVersion, lintValue);
+ setOption(AjCompilerOptions.OPTION_ReportInvalidAbsoluteTypeName, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportInvalidWildcardTypeName, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportUnresolvableMember, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportTypeNotExposedToWeaver, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportShadowNotInStructure, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportUnmatchedSuperTypeInCall, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportCannotImplementLazyTJP, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportNeedSerialVersionUIDField, lintValue, lintOptions);
+ setOption(AjCompilerOptions.OPTION_ReportIncompatibleSerialVersion, lintValue, lintOptions);
options.set(lintOptions);
}
}
+ private void setOption(String optionKey, String lintValue, Map<String,String> lintOptionsAccumulator) {
+ if (lintOptionsMap!=null && lintOptionsMap.containsKey(optionKey)) {
+ String v = lintOptionsMap.get(lintOptionsMap);
+ if (AJLINT_IGNORE.equals(v)) {
+ lintValue = AjCompilerOptions.IGNORE;
+ } else if (AJLINT_WARN.equals(v)) {
+ lintValue = AjCompilerOptions.WARNING;
+ } else if (AJLINT_ERROR.equals(v)) {
+ lintValue = AjCompilerOptions.ERROR;
+ }
+ }
+ if (lintValue != null) {
+ lintOptionsAccumulator.put(optionKey,lintValue);
+ }
+ }
+
public boolean isTerminateAfterCompilation() {
return options.terminateAfterCompilation;
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
index dfa878d96..76b9f5b9e 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java
@@ -858,6 +858,9 @@ public class AjBuildManager implements IOutputClassFileNameProvider, IBinarySour
} else {
bcelWorld.getLint().setAll(buildConfig.getLintMode());
}
+ if (buildConfig.getLintOptionsMap() != null) {
+ bcelWorld.getLint().setFromMap(buildConfig.getLintOptionsMap());
+ }
if (buildConfig.getLintSpecFile() != null) {
bcelWorld.getLint().setFromProperties(buildConfig.getLintSpecFile());
}
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
index 88b81ebc1..965e87732 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java
@@ -35,6 +35,7 @@ import java.util.Set;
import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
import org.aspectj.ajdt.internal.compiler.InterimCompilationResult;
+import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
import org.aspectj.ajdt.internal.core.builder.AjBuildConfig.BinarySourceFile;
import org.aspectj.apache.bcel.classfile.ClassParser;
import org.aspectj.asm.AsmManager;
@@ -451,7 +452,7 @@ public class AjState implements CompilerConfigurationChangeFlags, TypeDelegateRe
if (state != null) {
recordDecision("ClassFileChangeChecking: found state instance managing output location : " + dir);
} else {
- recordDecision("ClassFileChangeChecking: failed to find a state instance managing output location : " + dir);
+ recordDecision("ClassFileChangeChecking: failed to find a state instance managing output location : " + dir + " (could be getting managed by JDT)");
}
}
@@ -1534,8 +1535,10 @@ public class AjState implements CompilerConfigurationChangeFlags, TypeDelegateRe
// ignore local types since they're only visible inside a single method
if (!(reader.isLocal() || reader.isAnonymous())) {
if (hasStructuralChanges(reader, existingStructure)) {
- if (world.forDEBUG_structuralChangesCode) {
- System.err.println("Detected a structural change in " + thisTime.getFilename());
+ if (listenerDefined()) {
+// if (world.forDEBUG_structuralChangesCode) {
+// System.err.println("Detected a structural change in " + thisTime.getFilename());
+ printStructuralChanges(thisTime.getFilename(),reader, existingStructure);
}
structuralChangesSinceLastFullBuild.put(thisTime.getFilename(), new Long(currentBuildTime));
recordTypeChanged(new String(reader.getName()).replace('/', '.'));
@@ -1802,6 +1805,348 @@ public class AjState implements CompilerConfigurationChangeFlags, TypeDelegateRe
return false;
}
+ private void logAnalysis(String filename, String info) {
+ if (listenerDefined()) {
+ getListener().recordDecision("StructuralAnalysis["+filename+"]: "+info);
+ }
+ }
+
+ private boolean printStructuralChanges(String filename, ClassFileReader reader, CompactTypeStructureRepresentation existingType) {
+ logAnalysis(filename,"appears to have structurally changed, printing changes:");
+ if (existingType == null) {
+ logAnalysis(filename,"have not seen this type before");
+ return true;
+ }
+
+ // modifiers
+ if (!modifiersEqual(reader.getModifiers(), existingType.modifiers)) {
+ logAnalysis(filename,"modifiers changed. old=0x"+Integer.toHexString(existingType.getModifiers())+" new=0x"+Integer.toHexString(reader.getModifiers()));
+ return true;
+ }
+
+ // generic signature
+ if (!CharOperation.equals(reader.getGenericSignature(), existingType.genericSignature)) {
+ logAnalysis(filename,"generic signature changed. old="+stringify(existingType.genericSignature)+" new="+stringify(reader.getGenericSignature()));
+ return true;
+ }
+
+ // superclass name
+ if (!CharOperation.equals(reader.getSuperclassName(), existingType.superclassName)) {
+ logAnalysis(filename,"superclass name changed. old="+stringify(existingType.superclassName)+" new="+stringify(reader.getSuperclassName()));
+ return true;
+ }
+
+ // have annotations changed on the type?
+ IBinaryAnnotation[] newAnnos = reader.getAnnotations();
+ if (newAnnos == null || newAnnos.length == 0) {
+ if (existingType.annotations != null && existingType.annotations.length != 0) {
+ logAnalysis(filename,"type used to have annotations and now does not: "+stringify(existingType.annotations));
+ return true;
+ }
+ } else {
+ IBinaryAnnotation[] existingAnnos = existingType.annotations;
+ if (existingAnnos == null || existingAnnos.length != newAnnos.length) {
+ logAnalysis(filename,"type now has annotations which it did not used to have: "+stringify(newAnnos));
+ return true;
+ }
+ // Does not allow for an order switch
+ // Does not cope with a change in values set on the annotation (hard to create a testcase where this is a problem tho)
+ for (int i = 0; i < newAnnos.length; i++) {
+ if (!CharOperation.equals(newAnnos[i].getTypeName(), existingAnnos[i].getTypeName())) {
+ logAnalysis(filename,"type annotation change at position "+i+" old="+new String(existingAnnos[i].getTypeName())+" new="+new String(newAnnos[i].getTypeName()));
+ return true;
+ }
+ }
+
+ }
+
+ // interfaces
+ char[][] existingIfs = existingType.interfaces;
+ char[][] newIfsAsChars = reader.getInterfaceNames();
+ if (newIfsAsChars == null) {
+ newIfsAsChars = EMPTY_CHAR_ARRAY;
+ } // damn I'm lazy...
+ if (existingIfs == null) {
+ existingIfs = EMPTY_CHAR_ARRAY;
+ }
+ if (existingIfs.length != newIfsAsChars.length) {
+ return true;
+ }
+ new_interface_loop: for (int i = 0; i < newIfsAsChars.length; i++) {
+ for (int j = 0; j < existingIfs.length; j++) {
+ if (CharOperation.equals(existingIfs[j], newIfsAsChars[i])) {
+ continue new_interface_loop;
+ }
+ }
+ logAnalysis(filename,"set of interfaces changed. old="+stringify(existingIfs)+" new="+stringify(newIfsAsChars));
+ return true;
+ }
+
+ // fields
+ // CompactMemberStructureRepresentation[] existingFields = existingType.fields;
+ IBinaryField[] newFields = reader.getFields();
+ if (newFields == null) {
+ newFields = CompactTypeStructureRepresentation.NoField;
+ }
+
+ // all redundant for now ... could be an optimization at some point...
+ // remove any ajc$XXX fields from those we compare with
+ // the existing fields - bug 129163
+ // List nonGenFields = new ArrayList();
+ // for (int i = 0; i < newFields.length; i++) {
+ // IBinaryField field = newFields[i];
+ // //if (!CharOperation.prefixEquals(NameMangler.AJC_DOLLAR_PREFIX,field.getName())) { // this would skip ajc$ fields
+ // //if ((field.getModifiers()&0x1000)==0) // 0x1000 => synthetic - this will skip synthetic fields (eg. this$0)
+ // nonGenFields.add(field);
+ // //}
+ // }
+ IBinaryField[] existingFs = existingType.binFields;
+ if (newFields.length != existingFs.length) {
+ logAnalysis(filename,"number of fields changed. old="+stringify(existingFs)+" new="+stringify(newFields));
+ return true;
+ }
+ new_field_loop: for (int i = 0; i < newFields.length; i++) {
+ IBinaryField field = newFields[i];
+ char[] fieldName = field.getName();
+ for (int j = 0; j < existingFs.length; j++) {
+ if (CharOperation.equals(existingFs[j].getName(), fieldName)) {
+ IBinaryField existing = existingFs[j];
+ if (!modifiersEqual(field.getModifiers(), existing.getModifiers())) {
+ logAnalysis(filename,"field modifiers changed '"+existing+"' old=0x"+Integer.toHexString(existing.getModifiers())+" new=0x"+Integer.toHexString(field.getModifiers()));
+ return true;
+ }
+ if (!CharOperation.equals(existing.getTypeName(), field.getTypeName())) {
+ logAnalysis(filename,"field type changed '"+existing+"' old="+new String(existing.getTypeName())+" new="+new String(field.getTypeName()));
+ return true;
+ }
+
+ char[] existingGSig = existing.getGenericSignature();
+ char[] fieldGSig = field.getGenericSignature();
+ if ((existingGSig == null && fieldGSig != null) || (existingGSig != null && fieldGSig == null)) {
+ logAnalysis(filename,"field generic sig changed '"+existing+"' old="+
+ (existingGSig==null?"null":new String(existingGSig))+" new="+(fieldGSig==null?"null":new String(fieldGSig)));
+ return true;
+ }
+ if (existingGSig != null) {
+ if (!CharOperation.equals(existingGSig, fieldGSig)) {
+ logAnalysis(filename,"field generic sig changed '"+existing+"' old="+
+ (existingGSig==null?"null":new String(existingGSig))+" new="+(fieldGSig==null?"null":new String(fieldGSig)));
+ return true;
+ }
+ }
+
+ continue new_field_loop;
+ }
+ }
+ logAnalysis(filename,"field changed. New field detected '"+field+"'");
+ return true;
+ }
+
+ // methods
+ // CompactMemberStructureRepresentation[] existingMethods = existingType.methods;
+ IBinaryMethod[] newMethods = reader.getMethods();
+ if (newMethods == null) {
+ newMethods = CompactTypeStructureRepresentation.NoMethod;
+ }
+
+ // all redundant for now ... could be an optimization at some point...
+
+ // Ctors in a non-static inner type have an 'extra parameter' of the enclosing type.
+ // If skippableDescriptorPrefix gets set here then it is set to the descriptor portion
+ // for this 'extra parameter'. For an inner class of pkg.Foo the skippable descriptor
+ // prefix will be '(Lpkg/Foo;' - so later when comparing <init> methods we know what to
+ // compare.
+ // IF THIS CODE NEEDS TO GET MORE COMPLICATED, I THINK ITS WORTH RIPPING IT ALL OUT AND
+ // CREATING THE STRUCTURAL CHANGES OBJECT BASED ON CLASSREADER OUTPUT RATHER THAN
+ // THE RESOLVEDTYPE - THEN THERE WOULD BE NO NEED TO TREAT SOME METHODS IN A PECULIAR
+ // WAY.
+ // char[] skippableDescriptorPrefix = null;
+ // char[] enclosingTypeName = reader.getEnclosingTypeName();
+ // boolean isStaticType = Modifier.isStatic(reader.getModifiers());
+ // if (!isStaticType && enclosingTypeName!=null) {
+ // StringBuffer sb = new StringBuffer();
+ // sb.append("(L").append(new String(enclosingTypeName)).append(";");
+ // skippableDescriptorPrefix = sb.toString().toCharArray();
+ // }
+ //
+ //
+ // // remove the aspectOf, hasAspect, clinit and ajc$XXX methods
+ // // from those we compare with the existing methods - bug 129163
+ // List nonGenMethods = new ArrayList();
+ // for (int i = 0; i < newMethods.length; i++) {
+ // IBinaryMethod method = newMethods[i];
+ // // if ((method.getModifiers() & 0x1000)!=0) continue; // 0x1000 => synthetic - will cause us to skip access$0 - is this
+ // always safe?
+ // char[] methodName = method.getSelector();
+ // // if (!CharOperation.equals(methodName,NameMangler.METHOD_ASPECTOF) &&
+ // // !CharOperation.equals(methodName,NameMangler.METHOD_HASASPECT) &&
+ // // !CharOperation.equals(methodName,NameMangler.STATIC_INITIALIZER) &&
+ // // !CharOperation.prefixEquals(NameMangler.AJC_DOLLAR_PREFIX,methodName) &&
+ // // !CharOperation.prefixEquals(NameMangler.CLINIT,methodName)) {
+ // nonGenMethods.add(method);
+ // // }
+ // }
+ IBinaryMethod[] existingMs = existingType.binMethods;
+ if (newMethods.length != existingMs.length) {
+ logAnalysis(filename,"number of methods changed. old="+stringify(existingMs)+" new="+stringify(newMethods));
+ return true;
+ }
+ new_method_loop: for (int i = 0; i < newMethods.length; i++) {
+ IBinaryMethod method = newMethods[i];
+ char[] methodName = method.getSelector();
+ for (int j = 0; j < existingMs.length; j++) {
+ if (CharOperation.equals(existingMs[j].getSelector(), methodName)) {
+ // candidate match
+ if (!CharOperation.equals(method.getMethodDescriptor(), existingMs[j].getMethodDescriptor())) {
+ // ok, the descriptors don't match, but is this a funky ctor on a non-static inner
+ // type?
+ // boolean mightBeOK =
+ // skippableDescriptorPrefix!=null && // set for inner types
+ // CharOperation.equals(methodName,NameMangler.INIT) && // ctor
+ // CharOperation.prefixEquals(skippableDescriptorPrefix,method.getMethodDescriptor()); // checking for
+ // prefix on the descriptor
+ // if (mightBeOK) {
+ // // OK, so the descriptor starts something like '(Lpkg/Foo;' - we now may need to look at the rest of the
+ // // descriptor if it takes >1 parameter.
+ // // eg. could be (Lpkg/C;Ljava/lang/String;) where the skippablePrefix is (Lpkg/C;
+ // char [] md = method.getMethodDescriptor();
+ // char[] remainder = CharOperation.subarray(md, skippableDescriptorPrefix.length, md.length);
+ // if (CharOperation.equals(remainder,BRACKET_V)) continue new_method_loop; // no other parameters to worry
+ // about
+ // char[] comparableSig = CharOperation.subarray(existingMethods[j].signature, 1,
+ // existingMethods[j].signature.length);
+ // boolean match = CharOperation.equals(comparableSig, remainder);
+ // if (match) continue new_method_loop;
+ // }
+ continue; // might be overloading
+ } else {
+ // matching sigs
+ IBinaryMethod existing = existingMs[j];
+ if (!modifiersEqual(method.getModifiers(), existing.getModifiers())) {
+ logAnalysis(filename,"method modifiers changed '"+existing+"' old=0x"+Integer.toHexString(existing.getModifiers())+" new=0x"+Integer.toHexString(method.getModifiers()));
+ return true;
+ }
+
+ if (exceptionClausesDiffer(existing, method)) {
+ logAnalysis(filename,"method exception clauses changed '"+existing+"' old="+existing+" new="+method);
+ return true;
+ }
+
+ char[] existingGSig = existing.getGenericSignature();
+ char[] methodGSig = method.getGenericSignature();
+ if ((existingGSig == null && methodGSig != null) || (existingGSig != null && methodGSig == null)) {
+ logAnalysis(filename,"method generic sig changed '"+existing+"' old="+
+ (existingGSig==null?"null":new String(existingGSig))+" new="+(methodGSig==null?"null":new String(methodGSig)));
+ return true;
+ }
+ if (existingGSig != null) {
+ if (!CharOperation.equals(existingGSig, methodGSig)) {
+ logAnalysis(filename,"method generic sig changed '"+existing+"' old="+
+ (existingGSig==null?"null":new String(existingGSig))+" new="+(methodGSig==null?"null":new String(methodGSig)));
+ return true;
+ }
+ }
+
+ continue new_method_loop;
+ }
+ }
+ // TODO missing a return true here? Meaning we have a field in the new that we can't find in the old!
+ }
+
+ logAnalysis(filename,"method changed. New method detected '"+stringify(method)+"' (might be a rename)");
+ return true; // (no match found)
+ }
+
+ // check for differences in inner types
+ // TODO could make order insensitive
+ IBinaryNestedType[] binaryNestedTypes = reader.getMemberTypes();
+ IBinaryNestedType[] existingBinaryNestedTypes = existingType.getMemberTypes();
+ if ((binaryNestedTypes == null && existingBinaryNestedTypes != null)
+ || (binaryNestedTypes != null && existingBinaryNestedTypes == null)) {
+ logAnalysis(filename,"nested types changed");
+ return true;
+ }
+ if (binaryNestedTypes != null) {
+ int bnLength = binaryNestedTypes.length;
+ if (existingBinaryNestedTypes.length != bnLength) {
+ logAnalysis(filename,"nested types changed. old="+stringify(existingBinaryNestedTypes)+" new="+stringify(binaryNestedTypes));
+ return true;
+ }
+ for (int m = 0; m < bnLength; m++) {
+ IBinaryNestedType bnt = binaryNestedTypes[m];
+ IBinaryNestedType existingBnt = existingBinaryNestedTypes[m];
+ if (!CharOperation.equals(bnt.getName(), existingBnt.getName())) {
+ logAnalysis(filename,"nested type changed name at position "+m+" old="+stringify(existingBinaryNestedTypes)+" new="+stringify(binaryNestedTypes));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private String stringify(char[] chars) {
+ if (chars == null) {
+ return "null";
+ }
+ return new String(chars);
+ }
+
+ private String stringify(IBinaryNestedType[] binaryNestedTypes) {
+ StringBuilder buf = new StringBuilder();
+ for (IBinaryNestedType binaryNestedType: binaryNestedTypes) {
+ buf.append(binaryNestedType).append(" ");
+ }
+ return buf.toString().trim();
+ }
+
+ private String stringify(IBinaryMethod[] methods) {
+ StringBuilder buf = new StringBuilder();
+ for (IBinaryMethod method: methods) {
+ buf.append(stringify(method)).append(" ");
+ }
+ return "["+buf.toString().trim()+"]";
+ }
+
+ private String stringify(IBinaryMethod m) {
+ StringBuilder buf = new StringBuilder();
+ buf.append("0x").append(Integer.toHexString(m.getModifiers())).append(" ");
+ buf.append(m.getSelector()).append(m.getMethodDescriptor());
+ // IBinaryAnnotation[] annos = m.getAnnotations();
+ // TODO include annotations, generic sig, etc
+ return buf.toString().trim();
+ }
+
+ private String stringify(IBinaryField[] fields) {
+ StringBuilder buf = new StringBuilder();
+ for (IBinaryField field: fields) {
+ buf.append(stringify(field)).append(" ");
+ }
+ return "["+buf.toString().trim()+"]";
+ }
+
+ private Object stringify(IBinaryField f) {
+ StringBuilder buf = new StringBuilder();
+ buf.append("0x").append(Integer.toHexString(f.getModifiers())).append(" ");
+ buf.append(f.getTypeName()).append(f.getName());
+ return buf.toString().trim();
+ }
+
+ private String stringify(char[][] arrayOfCharArrays) {
+ StringBuilder buf = new StringBuilder();
+ for (char[] charArray: arrayOfCharArrays) {
+ buf.append(charArray).append(" ");
+ }
+ return buf.toString().trim();
+ }
+
+ private String stringify(IBinaryAnnotation[] annotations) {
+ StringBuilder buf = new StringBuilder();
+ for (IBinaryAnnotation anno: annotations) {
+ buf.append(anno).append(" ");
+ }
+ return buf.toString().trim();
+ }
+
/**
* For two methods, discover if there has been a change in the exception types specified.
*
@@ -2204,8 +2549,7 @@ public class AjState implements CompilerConfigurationChangeFlags, TypeDelegateRe
ClassParser parser = new ClassParser(f.toString());
return world.buildBcelDelegate(referenceType, parser.parse(), true, false);
} catch (IOException e) {
- IMessage msg = new Message("Failed to recover " + referenceType,
- referenceType.getDelegate()==null?null:referenceType.getSourceLocation(), false);
+ IMessage msg = new Message("Failed to recover " + referenceType, referenceType.getDelegate()!=null?referenceType.getSourceLocation():null, false);
buildManager.handler.handleMessage(msg);
}
return null;