Browse Source

merging 1.7.4 fixes into 1.8.0

tags/V1_8_0RC1
Andy Clement 10 years ago
parent
commit
c1c4a4d41f

+ 51
- 0
docs/dist/doc/README-174.html View File

@@ -0,0 +1,51 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html> <head>
<title>AspectJ 1.7.4 Readme</title>
<style type="text/css">
<!--
P { margin-left: 20px; }
PRE { margin-left: 20px; }
LI { margin-left: 20px; }
H4 { margin-left: 20px; }
H3 { margin-left: 10px; }
-->
</style>
</head>

<body>
<div align="right"><small>
&copy; Copyright 2013 Contributors.
All rights reserved.
</small></div>

<h1>AspectJ 1.7.4 Readme</h1>

<p>Available 24-Oct-2013</p>

<p>The list of resolved issues in 1.7.4 is available
<a href="https://bugs.eclipse.org/bugs/buglist.cgi?query_format=advanced;bug_status=RESOLVED;bug_status=VERIFIED;bug_status=CLOSED;product=AspectJ;target_milestone=1.7.4;">here</a></h2>.</p>

<b>Notes</b>
<ul>
<li>This release includes an important fix for using loadtime weaving in a JVM where JMX is turned on (<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=415266">415266</a>)
<p>
<li>There are some new message insert keys usable in declare error/warning (<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=420210">420210</a>)
The new keys are:
<tt>
<pre>
joinpoint.enclosingclass // Bar
joinpoint.enclosingmember // void Bar.foo(String)
joinpoint.enclosingmember.name // foo
</pre>
</tt>
All keys are case insensitive.
<p>
<li>It is now possible to specify individual xlint settings without needing to supply a file (<a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=419279">419279</a>)
<tt><pre>ajc -Xlint:adviceDidNotMatch=error,noGuardForLazyTjp=ignore Foo.java</pre></tt>
</ul>


<!-- ============================== -->
</body>
</html>


+ 7
- 22
docs/dist/doc/README-180.html View File

@@ -24,36 +24,18 @@ All rights reserved.
<a href="https://bugs.eclipse.org/bugs/buglist.cgi?query_format=advanced;bug_status=RESOLVED;bug_status=VERIFIED;bug_status=CLOSED;product=AspectJ;target_milestone=1.8.0;">here</a></h2>.</p>

<ul>
<li>1.8.0.RC1 available 18-Mar-2014
<li>1.8.0.M1 available 29-Jul-2013
</ul>

<h2>Overview</h2>

<p>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.
</p>

<h2>Notable changes</h2>

<h3>Java 8 compilation</h3>

<p>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.</p>
<p><b>NOTE:</b>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.
<p>AspectJ has been updated to the latest available Eclipse Java
compiler version that compiles Java8 code.</p>
</p>
<p>AspectJ 1.8.0.M1 will now compile Java 8 code, here is a sample:</p>
<p>Here is a sample AspectJ8 program:</p>

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

<h4>
<h3>Other</h3>
<p>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.</p>
<!-- ============================== -->
</body>
</html>

+ 2
- 1
docs/dist/doc/index.html View File

@@ -138,7 +138,8 @@
<tr> <td>README's
</td>
<td>Changes and porting guide for AspectJ
<a href="README-180.html">1.8.0.M1</a>,
<a href="README-180.html">1.8.0</a>,
<a href="README-174.html">1.7.4</a>,
<a href="README-173.html">1.7.3</a>,
<a href="README-172.html">1.7.2</a>,
<a href="README-171.html">1.7.1</a>,

+ 1
- 1
org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/messages.properties View File

@@ -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...

+ 49
- 11
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildConfig.java View File

@@ -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;
}

+ 3
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjBuildManager.java View File

@@ -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());
}

+ 349
- 5
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AjState.java View File

@@ -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;

+ 16
- 0
org.aspectj.matcher/src/org/aspectj/weaver/Checker.java View File

@@ -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")) {

+ 12
- 0
org.aspectj.matcher/src/org/aspectj/weaver/Lint.java View File

@@ -166,6 +166,18 @@ public class Lint {
kind.setKind(messageKind);
}
}
public void setFromMap(Map<String,String> 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()) {

+ 2
- 1
testing/newsrc/org/aspectj/testing/CompileSpec.java View File

@@ -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(" ");
}
}

+ 20
- 0
tests/bugs174/ajdt_markers/Code.java View File

@@ -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(..)) {}
}

+ 18
- 0
tests/bugs174/extra_inserts/Code.java View File

@@ -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() {}
}

+ 10
- 0
tests/bugs174/pr419279/Code.java View File

@@ -0,0 +1,10 @@
public aspect Code {
before(): execution(* *(String)) { }
before(): call(* someMethod(..)) {
System.out.println(thisJoinPoint);
}
public void foo() {
someMethod();
}
public void someMethod(){}
}

+ 14
- 0
tests/src/org/aspectj/systemtest/ajc174/Ajc174Tests.java View File

@@ -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");
}

+ 41
- 0
tests/src/org/aspectj/systemtest/ajc174/ajc174.xml View File

@@ -2,6 +2,47 @@

<suite>

<ajc-test dir="bugs174/ajdt_markers" title="ajdt markers">
<compile files="Code.java" options="-1.5 -showWeaveInfo">
</compile>
</ajc-test>


<ajc-test dir="bugs174/extra_inserts" title="extra inserts">
<compile files="Code.java" options="-1.5">
<message kind="warning" line="8" text="Call to foo made inside class Bar"/>
<message kind="warning" line="15" text="Call to foo made inside class Boo"/>
<message kind="warning" line="8" text="Call to foo made inside member booble"/>
<message kind="warning" line="15" text="Call to foo made inside member m"/>
<message kind="warning" line="8" text="Call to foo made inside member void Bar.booble()"/>
<message kind="warning" line="15" text="Call to foo made inside member void Boo.m()"/>
</compile>
</ajc-test>

<ajc-test dir="bugs174/pr419279" title="more configurable lint">
<compile files="Code.java" options="-1.5">
<message kind="warning" text="advice defined in Code has not been applied [Xlint:adviceDidNotMatch]"/>
</compile>
<compile files="Code.java" options="-1.5 -Xlint:adviceDidNotMatch=ignore">
</compile>
<compile files="Code.java" options="-1.5 -Xlint:adviceDidNotMatch=error">
<message kind="error" text="advice defined in Code has not been applied [Xlint:adviceDidNotMatch]"/>
</compile>
<compile files="Code.java" options="-1.5 -Xlint:foo=bar">
<message kind="error" text="invalid Xlint key: foo"/>
</compile>
<compile files="Code.java" options="-1.5 -Xlint:adviceDidNotMatch=wibble">
<message kind="error" text="invalid Xlint message kind (must be one of ignore, warning, error): wibble"/>
</compile>
<compile files="Code.java" options="-1.5 -Xlint:adviceDidNotMatch=ignore{adviceDidNotMatch=error">
<message kind="error" text="advice defined in Code has not been applied [Xlint:adviceDidNotMatch]"/>
</compile>
<compile files="Code.java" options="-1.5 -Xlint:adviceDidNotMatch=error{noGuardForLazyTjp=error">
<message kind="error" text="advice defined in Code has not been applied [Xlint:adviceDidNotMatch]"/>
<message kind="error" text="can not build thisJoinPoint lazily for this advice since it has no suitable guard [Xlint:noGuardForLazyTjp]"/>
</compile>
</ajc-test>

<ajc-test dir="bugs174/pr418129" title="annotated itd">
<compile files="Target.java" options="-1.5 -showWeaveInfo">
<message kind="weave" text="Type 'Behavior' (Target.java) has intertyped method from 'Trait' (Target.java:'java.lang.String Behavior.hello()')"/>

Loading…
Cancel
Save