From c1c4a4d41f3173bb72040d91d42d07662ab703bd Mon Sep 17 00:00:00 2001 From: Andy Clement Date: Tue, 18 Mar 2014 22:21:20 -0700 Subject: [PATCH] merging 1.7.4 fixes into 1.8.0 --- docs/dist/doc/README-174.html | 51 +++ docs/dist/doc/README-180.html | 29 +- docs/dist/doc/index.html | 3 +- .../org/aspectj/ajdt/ajc/messages.properties | 2 +- .../internal/core/builder/AjBuildConfig.java | 60 ++- .../internal/core/builder/AjBuildManager.java | 3 + .../ajdt/internal/core/builder/AjState.java | 354 +++++++++++++++++- .../src/org/aspectj/weaver/Checker.java | 16 + .../src/org/aspectj/weaver/Lint.java | 12 + .../org/aspectj/testing/CompileSpec.java | 3 +- tests/bugs174/ajdt_markers/Code.java | 20 + tests/bugs174/extra_inserts/Code.java | 18 + tests/bugs174/pr419279/Code.java | 10 + .../systemtest/ajc174/Ajc174Tests.java | 14 + .../org/aspectj/systemtest/ajc174/ajc174.xml | 41 ++ 15 files changed, 595 insertions(+), 41 deletions(-) create mode 100644 docs/dist/doc/README-174.html create mode 100644 tests/bugs174/ajdt_markers/Code.java create mode 100644 tests/bugs174/extra_inserts/Code.java create mode 100644 tests/bugs174/pr419279/Code.java diff --git a/docs/dist/doc/README-174.html b/docs/dist/doc/README-174.html new file mode 100644 index 000000000..24b53318f --- /dev/null +++ b/docs/dist/doc/README-174.html @@ -0,0 +1,51 @@ + + +AspectJ 1.7.4 Readme + + + + +
+© Copyright 2013 Contributors. +All rights reserved. +
+ +

AspectJ 1.7.4 Readme

+ +

Available 24-Oct-2013

+ +

The list of resolved issues in 1.7.4 is available +here.

+ +Notes + + + + + + + diff --git a/docs/dist/doc/README-180.html b/docs/dist/doc/README-180.html index f28a5ed66..78b55d8cb 100644 --- a/docs/dist/doc/README-180.html +++ b/docs/dist/doc/README-180.html @@ -24,36 +24,18 @@ All rights reserved. here.

-

Overview

- -

In previous AspectJ major releases the first milestone normally tolerates weaving bytecode for the -comparable Java level whilst the ability to compile source code for that Java level comes later. -However, AspectJ 1.8.0.M1 is a Java 8 compiler. So why change the approach this time? Some -consumers of AspectJ are choosing to exploit Java8 library features even though they are not -using Java8 language constructs in their source. The Eclipse JDT compiler (in eclipse 4.3) actually -includes a number of changes to facilitate this (basically compiling with -source 1.7 but on top -of a 1.8 JRE). The changes are necessary because the 1.8 classes include metadata that the 1.7 -compiler just isn't expecting. For example default method implementations in interfaces. In order -to support this mode of working AspectJ would need to update to the Eclipse 4.3 compiler. However, -performing upgrades of the compiler inside AspectJ is non trivial and to avoid doing the -upgrade to 4.3 and then doing a further upgrade to the Java8 compiler, we decided to jump straight -to the Java8 compiler which already includes these changes. -

-

Notable changes

Java 8 compilation

-

AspectJ has been updated to the latest available BETA_JAVA8 support level in the Eclipse Java -compiler. The BETA_JAVA8 tag chosen was commit #3D6E745.

-

NOTE:The Java8 libraries are still in flux and changing regularly. If you are going to -use AspectJ 1.8.0.M1 you must run with a compatible level of Java8. We have been testing with -beta 97. Code compiled with this compiler is not guaranteed to run on a later JDK level. +

AspectJ has been updated to the latest available Eclipse Java +compiler version that compiles Java8 code.

-

AspectJ 1.8.0.M1 will now compile Java 8 code, here is a sample:

+

Here is a sample AspectJ8 program:


 === 8< ==== C.java ==== 8< ===
@@ -105,6 +87,9 @@ class MyClass {
 

+

Other

+

The fixes in the 1.7 branch which have occurred since this 1.8 branch was created +have been merged into the 1.8 release.

diff --git a/docs/dist/doc/index.html b/docs/dist/doc/index.html index ad2bdd71d..6040bc034 100644 --- a/docs/dist/doc/index.html +++ b/docs/dist/doc/index.html @@ -138,7 +138,8 @@ README's Changes and porting guide for AspectJ - 1.8.0.M1, + 1.8.0, + 1.7.4, 1.7.3, 1.7.2, 1.7.1, 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 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 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(); + 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 lintOptions = new HashMap(); - 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 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 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; diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Checker.java b/org.aspectj.matcher/src/org/aspectj/weaver/Checker.java index 384c5d6cd..4a765a9e5 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/Checker.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/Checker.java @@ -222,6 +222,22 @@ public class Checker extends ShadowMunger { return shadow.toString(); } else if (key.equalsIgnoreCase("joinpoint.kind")) { return shadow.getKind().getName(); + } else if (key.equalsIgnoreCase("joinpoint.enclosingclass")) { + return shadow.getEnclosingType().getName(); + } else if (key.equalsIgnoreCase("joinpoint.enclosingmember.name")) { + Member member = shadow.getEnclosingCodeSignature(); + if (member==null) { + return ""; + } else { + return member.getName(); + } + } else if (key.equalsIgnoreCase("joinpoint.enclosingmember")) { + Member member = shadow.getEnclosingCodeSignature(); + if (member==null) { + return ""; + } else { + return member.toString(); + } } else if (key.equalsIgnoreCase("joinpoint.signature")) { return shadow.getSignature().toString(); } else if (key.equalsIgnoreCase("joinpoint.signature.declaringtype")) { diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Lint.java b/org.aspectj.matcher/src/org/aspectj/weaver/Lint.java index d68ce4142..36d647512 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/Lint.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/Lint.java @@ -166,6 +166,18 @@ public class Lint { kind.setKind(messageKind); } } + + public void setFromMap(Map lintOptionsMap) { + for (String key: lintOptionsMap.keySet()) { + String value = lintOptionsMap.get(key); + Kind kind = kinds.get(key); + if (kind == null) { + MessageUtil.error(world.getMessageHandler(), WeaverMessages.format(WeaverMessages.XLINT_KEY_ERROR, key)); + } else { + kind.setKind(getMessageKind(value)); + } + } + } public void setFromProperties(File file) { if (trace.isTraceEnabled()) { diff --git a/testing/newsrc/org/aspectj/testing/CompileSpec.java b/testing/newsrc/org/aspectj/testing/CompileSpec.java index 897e41228..6d42149ff 100644 --- a/testing/newsrc/org/aspectj/testing/CompileSpec.java +++ b/testing/newsrc/org/aspectj/testing/CompileSpec.java @@ -234,7 +234,8 @@ public class CompileSpec implements ITestStep { if (getOptions() != null) { StringTokenizer strTok = new StringTokenizer(getOptions(),","); while (strTok.hasMoreTokens()) { - args.append(strTok.nextToken()); + // For an option containing a comma, pass in a { in its place + args.append(strTok.nextToken().replace('{', ',')); args.append(" "); } } diff --git a/tests/bugs174/ajdt_markers/Code.java b/tests/bugs174/ajdt_markers/Code.java new file mode 100644 index 000000000..b5b52c1e9 --- /dev/null +++ b/tests/bugs174/ajdt_markers/Code.java @@ -0,0 +1,20 @@ +public class Code extends A implements I { + + public static void main(String[] argv) { + Code code = new Code(); + code.am(); + code.im(); + } +} + +class A { + public void am() {} +} + +interface I { +} + +aspect X { + public void I.im() {} + before(): call(* A+.*m(..)) {} +} diff --git a/tests/bugs174/extra_inserts/Code.java b/tests/bugs174/extra_inserts/Code.java new file mode 100644 index 000000000..fa4d85990 --- /dev/null +++ b/tests/bugs174/extra_inserts/Code.java @@ -0,0 +1,18 @@ +public aspect Code { + declare warning: call(* foo(..)): "Call to foo made inside class {joinpoint.enclosingclass}"; + declare warning: call(* foo(..)): "Call to foo made inside member {joinpoint.enclosingmember.name}"; + declare warning: call(* foo(..)): "Call to foo made inside member {joinpoint.enclosingmember}"; +} +class Bar { + public void booble() { + foo(); + } + public void foo() {} +} + +class Boo { + public void m() { + foo(); + } + public void foo() {} +} diff --git a/tests/bugs174/pr419279/Code.java b/tests/bugs174/pr419279/Code.java new file mode 100644 index 000000000..672d720ef --- /dev/null +++ b/tests/bugs174/pr419279/Code.java @@ -0,0 +1,10 @@ +public aspect Code { + before(): execution(* *(String)) { } + before(): call(* someMethod(..)) { + System.out.println(thisJoinPoint); + } + public void foo() { + someMethod(); + } + public void someMethod(){} +} diff --git a/tests/src/org/aspectj/systemtest/ajc174/Ajc174Tests.java b/tests/src/org/aspectj/systemtest/ajc174/Ajc174Tests.java index 1e300dd0a..e647532fd 100644 --- a/tests/src/org/aspectj/systemtest/ajc174/Ajc174Tests.java +++ b/tests/src/org/aspectj/systemtest/ajc174/Ajc174Tests.java @@ -21,6 +21,20 @@ import org.aspectj.testing.XMLBasedAjcTestCase; */ public class Ajc174Tests extends org.aspectj.testing.XMLBasedAjcTestCase { +/* wip + public void testAjdtMarkers() throws Exception { + runTest("ajdt markers"); + } +*/ + + public void testExtraInserts() throws Exception { + runTest("extra inserts"); + } + + public void testMoreConfigurableLint_419279() throws Exception { + runTest("more configurable lint"); + } + public void testAnnotatedItd_418129() throws Exception { runTest("annotated itd"); } diff --git a/tests/src/org/aspectj/systemtest/ajc174/ajc174.xml b/tests/src/org/aspectj/systemtest/ajc174/ajc174.xml index 5b47cf4d3..2ee09c456 100644 --- a/tests/src/org/aspectj/systemtest/ajc174/ajc174.xml +++ b/tests/src/org/aspectj/systemtest/ajc174/ajc174.xml @@ -2,6 +2,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.39.5