EclipseFactory eFactory, IIntermediateResultsRequestor intRequestor, IProgressListener progressListener,
IOutputClassFileNameProvider outputFileNameProvider, IBinarySourceProvider binarySourceProvider,
Map fullBinarySourceEntries, /* fileName |-> List<UnwovenClassFile> */
- boolean isXterminateAfterCompilation, boolean proceedOnError, boolean noAtAspectJProcessing,
- boolean reflectable,
+ boolean isXterminateAfterCompilation, boolean proceedOnError, boolean noAtAspectJProcessing, boolean reflectable,
AjState incrementalCompilationState) {
this.compiler = compiler;
this.isBatchCompile = isBatchCompile;
this.proceedOnError = proceedOnError;
this.binarySourceSetForFullWeave = fullBinarySourceEntries;
this.eWorld = eFactory;
- this.reflectable= reflectable;
+ this.reflectable = reflectable;
this.inJava5Mode = false;
this.noAtAspectJAnnotationProcessing = noAtAspectJProcessing;
this.incrementalCompilationState = incrementalCompilationState;
- if (compiler.options.complianceLevel >= ClassFileConstants.JDK1_5)
+ if (compiler.options.complianceLevel >= ClassFileConstants.JDK1_5) {
inJava5Mode = true;
+ }
IMessageHandler msgHandler = world.getMessageHandler();
// Do we need to reset the message handler or create a new one? (This saves a ton of memory lost on incremental compiles...)
if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
- AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit,reflectable);
+ AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit, reflectable);
unit.traverse(atAspectJVisitor, unit.scope);
CompilationAndWeavingContext.leavingPhase(tok);
}
}
public void afterResolving(CompilationUnitDeclaration unit) {
- if (resolvingToken != null)
+ if (resolvingToken != null) {
CompilationAndWeavingContext.leavingPhase(resolvingToken);
+ }
}
public void beforeAnalysing(CompilationUnitDeclaration unit) {
}
public void afterAnalysing(CompilationUnitDeclaration unit) {
- if (analysingToken != null)
+ if (analysingToken != null) {
CompilationAndWeavingContext.leavingPhase(analysingToken);
+ }
}
public void beforeGenerating(CompilationUnitDeclaration unit) {
}
public void afterGenerating(CompilationUnitDeclaration unit) {
- if (generatingToken != null)
+ if (generatingToken != null) {
CompilationAndWeavingContext.leavingPhase(generatingToken);
+ }
}
public void afterCompiling(CompilationUnitDeclaration[] units) {
AbortCompilation ac = new AbortCompilation(null, ex);
throw ac;
} catch (RuntimeException rEx) {
- if (rEx instanceof AbortCompilation)
+ if (rEx instanceof AbortCompilation) {
throw rEx; // Don't wrap AbortCompilation exceptions!
+ }
// This will be unwrapped in Compiler.handleInternalException() and the nested
// RuntimeException thrown back to the original caller - which is AspectJ
CompilationAndWeavingContext.leavingPhase(processingToken);
eWorld.finishedCompilationUnit(unit);
InterimCompilationResult intRes = new InterimCompilationResult(unit.compilationResult, outputFileNameProvider);
- if (unit.compilationResult.hasErrors())
+ if (unit.compilationResult.hasErrors()) {
reportedErrors = true;
+ }
if (intermediateResultsRequestor != null) {
intermediateResultsRequestor.acceptResult(intRes);
for (Iterator iter = resultsPendingWeave.iterator(); iter.hasNext();) {
InterimCompilationResult iresult = (InterimCompilationResult) iter.next();
for (int i = 0; i < iresult.unwovenClassFiles().length; i++) {
- weaver.addClassFile(iresult.unwovenClassFiles()[i],false);
+ weaver.addClassFile(iresult.unwovenClassFiles()[i], false);
}
}
weaver.allWeavingComplete();
weaver.tidyUp();
IMessageHandler imh = weaver.getWorld().getMessageHandler();
- if (imh instanceof WeaverMessageHandler)
+ if (imh instanceof WeaverMessageHandler) {
((WeaverMessageHandler) imh).resetCompiler(null);
+ }
}
}
import org.aspectj.ajdt.internal.compiler.ast.AddAtAspectJAnnotationsVisitor;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.ValidateAtAspectJAnnotationsVisitor;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.core.builder.AjState;
import org.aspectj.bridge.context.ContextToken;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.Compiler;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.aspectj.weaver.bcel.BcelWeaver;
import org.aspectj.weaver.bcel.BcelWorld;
+import org.aspectj.weaver.bcel.UnwovenClassFile;
/**
* Adapts standard JDT Compiler to add in AspectJ specific behaviours. This version implements pipelining - where files are compiled
private IOutputClassFileNameProvider outputFileNameProvider;
private IBinarySourceProvider binarySourceProvider;
private WeaverMessageHandler weaverMessageHandler;
- private Map /* fileName > List<UnwovenClassFile> */binarySourceSetForFullWeave = new HashMap();
+ private Map<String, List<UnwovenClassFile>> binarySourceSetForFullWeave = new HashMap<String, List<UnwovenClassFile>>();
private ContextToken processingToken = null;
private ContextToken resolvingToken = null;
private AjState incrementalCompilationState;
// Maintains a list of whats weaving - whilst the pipeline is stalled, this accumulates aspects.
- List /* InterimResult */resultsPendingWeave = new ArrayList();
+ List<InterimCompilationResult> resultsPendingWeave = new ArrayList<InterimCompilationResult>();
// pipelining info
private boolean pipelineStalled = true;
}
// Break the units into two lists...
- List aspects = new ArrayList();
- List nonaspects = new ArrayList();
+ List<CompilationUnitDeclaration> aspects = new ArrayList<CompilationUnitDeclaration>();
+ List<CompilationUnitDeclaration> nonaspects = new ArrayList<CompilationUnitDeclaration>();
for (int i = 0; i < units.length; i++) {
if (containsAnAspect(units[i])) {
aspects.add(units[i]);
// ...and put them back together, aspects first
int posn = 0;
- for (Iterator iter = aspects.iterator(); iter.hasNext();) {
- units[posn++] = (CompilationUnitDeclaration) iter.next();
+ for (CompilationUnitDeclaration aspect : aspects) {
+ units[posn++] = aspect;
}
- for (Iterator iter = nonaspects.iterator(); iter.hasNext();) {
- units[posn++] = (CompilationUnitDeclaration) iter.next();
+ for (CompilationUnitDeclaration nonaspect : nonaspects) {
+ units[posn++] = nonaspect;
}
// Work out how long to stall the pipeline
}
public void beforeCompiling(ICompilationUnit[] sourceUnits) {
- resultsPendingWeave = new ArrayList();
+ resultsPendingWeave = new ArrayList<InterimCompilationResult>();
reportedErrors = false;
droppingBackToFullBuild = false;
}
if (inJava5Mode && !noAtAspectJAnnotationProcessing) {
ContextToken tok = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.ADDING_AT_ASPECTJ_ANNOTATIONS, unit.getFileName());
- AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit,makeReflectable);
+ AddAtAspectJAnnotationsVisitor atAspectJVisitor = new AddAtAspectJAnnotationsVisitor(unit, makeReflectable);
unit.traverse(atAspectJVisitor, unit.scope);
CompilationAndWeavingContext.leavingPhase(tok);
}
public void beforeGenerating(CompilationUnitDeclaration unit) {
generatingToken = CompilationAndWeavingContext.enteringPhase(
CompilationAndWeavingContext.GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT, unit.getFileName());
+ if (eWorld.pushinCollector != null) {
+ if (unit.types != null && unit.types.length > 0) {
+ for (int t = 0; t < unit.types.length; t++) {
+ TypeDeclaration type = unit.types[t];
+ if (type.methods != null) {
+ for (int m = 0; m < type.methods.length; m++) {
+ AbstractMethodDeclaration md = type.methods[m];
+ if (md instanceof InterTypeMethodDeclaration) {
+ InterTypeMethodDeclaration itmd = ((InterTypeMethodDeclaration) md);
+ ITDMethodPrinter printer = new ITDMethodPrinter(itmd, md.scope);
+ String s = printer.print();
+ eWorld.pushinCollector.recordInterTypeMethodDeclarationCode(md, s, getDeclarationLineNumber(md));
+ } else if (md instanceof InterTypeFieldDeclaration) {
+ ITDFieldPrinter printer = new ITDFieldPrinter(((InterTypeFieldDeclaration) md), md.scope);
+ String s = printer.print();
+ eWorld.pushinCollector.recordInterTypeFieldDeclarationCode(md, s, getDeclarationLineNumber(md));
+ } else if (md instanceof InterTypeConstructorDeclaration) {
+ ITDConstructorPrinter printer = new ITDConstructorPrinter(((InterTypeConstructorDeclaration) md),
+ md.scope);
+ String s = printer.print();
+ eWorld.pushinCollector.recordInterTypeConstructorDeclarationCode(md, s,
+ getDeclarationLineNumber(md));
+ // } else if (md instanceof DeclareAnnotationDeclaration) {
+ // DeclareAnnotationDeclaration dad = (DeclareAnnotationDeclaration) md;
+ // String value = new DeclareAnnotationsPrinter(dad, dad.scope).print();
+ // eWorld.pushinCollector.recordDeclareAnnotationDeclarationCode(md, value);
+ }
+ }
+ }
+ }
+ }
+ eWorld.pushinCollector.setOutputFileNameProvider(outputFileNameProvider);
+ }
+ }
+
+ /**
+ * @return the line number for this declaration in the source code
+ */
+ private int getDeclarationLineNumber(AbstractMethodDeclaration md) {
+ int sourceStart = md.sourceStart;
+ int[] separators = md.compilationResult.lineSeparatorPositions;
+ int declarationStartLine = 1;
+ for (int i = 0; i < separators.length; i++) {
+ if (sourceStart < separators[i]) {
+ break;
+ }
+ declarationStartLine++;
+ }
+ return declarationStartLine;
}
public void afterGenerating(CompilationUnitDeclaration unit) {
if (generatingToken != null) {
CompilationAndWeavingContext.leavingPhase(generatingToken);
}
+ if (eWorld.pushinCollector != null) {
+ eWorld.pushinCollector.dump(unit);
+ }
}
public void afterCompiling(CompilationUnitDeclaration[] units) {
// helper methods...
// ==================================================================================
- private List getBinarySourcesFrom(Map binarySourceEntries) {
+ private List<InterimCompilationResult> getBinarySourcesFrom(Map<String, List<UnwovenClassFile>> binarySourceEntries) {
// Map is fileName |-> List<UnwovenClassFile>
- List ret = new ArrayList();
- for (Iterator binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
- String sourceFileName = (String) binIter.next();
- List unwovenClassFiles = (List) binarySourceEntries.get(sourceFileName);
+ List<InterimCompilationResult> ret = new ArrayList<InterimCompilationResult>();
+ for (Iterator<String> binIter = binarySourceEntries.keySet().iterator(); binIter.hasNext();) {
+ String sourceFileName = binIter.next();
+ List<UnwovenClassFile> unwovenClassFiles = binarySourceEntries.get(sourceFileName);
// XXX - see bugs 57432,58679 - final parameter on next call should be "compiler.options.maxProblemsPerUnit"
CompilationResult result = new CompilationResult(sourceFileName.toCharArray(), 0, 0, Integer.MAX_VALUE);
result.noSourceAvailable();
* SECRET: FOR TESTING - this can be used to collect information that tests can verify.
*/
public static boolean pipelineTesting = false;
- public static Hashtable pipelineOutput = null;
+ public static Hashtable<String, String> pipelineOutput = null;
// Keys into pipelineOutput:
// compileOrder "[XXX,YYY]" a list of the order in which files will be woven (aspects should be first)
if (pipelineOutput == null) {
return "";
}
- return (String) pipelineOutput.get(key);
+ return pipelineOutput.get(key);
}
private final static boolean debugPipeline = false;
- public List getResultsPendingWeave() {
+ public List<InterimCompilationResult> getResultsPendingWeave() {
return resultsPendingWeave;
}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2010 Contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement - SpringSource
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import org.aspectj.asm.internal.CharOperation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AssertStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Block;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.BreakStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CaseStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CharLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ForStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.IntLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LongLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TryStatement;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedFieldBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class CommonPrinter {
+
+ StringBuilder output;
+ private int tab = 0;
+ MethodScope mscope;
+ AbstractMethodDeclaration declaration;
+ protected int expressionLevel = 0;
+
+ public CommonPrinter(MethodScope mscope) {
+ output = new StringBuilder();
+ this.mscope = mscope;
+ }
+
+ protected StringBuilder printTypeReference(TypeReference tr) {
+ if (tr instanceof Wildcard) {
+ Wildcard w = (Wildcard) tr;
+ output.append('?');
+ if (w.bound != null) {
+ if (w.kind == Wildcard.EXTENDS) {
+ output.append(" extends ");
+ } else if (w.kind == Wildcard.SUPER) {
+ output.append(" super ");
+ }
+ printTypeReference(w.bound);
+ }
+ return output;
+ } else if (tr instanceof ParameterizedSingleTypeReference) {
+ ParameterizedSingleTypeReference pstr = (ParameterizedSingleTypeReference) tr;
+ ReferenceBinding tb = (ReferenceBinding) mscope.getType(pstr.token);
+ output.append(CharOperation.concatWith(tb.compoundName, '.'));
+ output.append('<');
+ TypeReference[] typeArguments = pstr.typeArguments;
+ for (int i = 0; i < typeArguments.length; i++) {
+ if (i > 0) {
+ output.append(',');
+ }
+ printTypeReference(typeArguments[i]);
+ }
+ output.append('>');
+ for (int i = 0; i < pstr.dimensions; i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ return output;
+ } else if (tr instanceof ParameterizedQualifiedTypeReference) {
+ ParameterizedQualifiedTypeReference pqtr = (ParameterizedQualifiedTypeReference) tr;
+ output.append(CharOperation.concatWith(pqtr.tokens, '.'));
+ output.append('<');
+ TypeReference[][] typeArguments = pqtr.typeArguments;
+ // TODO don't support parameterized interim name components
+ TypeReference[] ofInterest = typeArguments[typeArguments.length - 1];
+ for (int i = 0; i < ofInterest.length; i++) {
+ if (i > 0) {
+ output.append(',');
+ }
+ printTypeReference(ofInterest[i]);
+ }
+ output.append('>');
+ for (int i = 0; i < pqtr.dimensions(); i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ return output;
+ } else if (tr instanceof SingleTypeReference) {
+ SingleTypeReference str = (SingleTypeReference) tr;
+ TypeBinding tb = mscope.getType(str.token);
+ output.append(tb.debugName()); // fq name
+ for (int i = 0; i < str.dimensions(); i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ return output;
+ } else if (tr instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qtr = (QualifiedTypeReference) tr;
+ output.append(CharOperation.concatWith(qtr.tokens, '.'));
+ for (int i = 0; i < qtr.dimensions(); i++) {
+ output.append("[]"); //$NON-NLS-1$
+ }
+ return output;
+ }
+ throwit(tr);
+ return output;
+ }
+
+ protected StringBuilder printMemberValuePair(MemberValuePair mvp) {
+ output.append(mvp.name).append(" = "); //$NON-NLS-1$
+ printExpression(mvp.value);
+ return output;
+ }
+
+ protected StringBuilder printAnnotations(Annotation[] annotations) {
+ int length = annotations.length;
+ for (int i = 0; i < length; i++) {
+ printAnnotation(annotations[i]);
+ output.append(" "); //$NON-NLS-1$
+ }
+ return output;
+ }
+
+ public StringBuilder printAnnotation(Annotation annotation) {
+ output.append('@');
+ printExpression(annotation.type);
+ MemberValuePair[] mvps = annotation.memberValuePairs();
+ if (mvps != null && mvps.length > 0) {
+ output.append('(');
+ for (int m = 0; m < mvps.length; m++) {
+ if (m > 0) {
+ output.append(',');
+ }
+ printMemberValuePair(mvps[m]);
+ }
+ output.append(')');
+ }
+ return output;
+ }
+
+ public String toString() {
+ return output.toString();
+ }
+
+ protected StringBuilder printBody(int indent) {
+
+ if (declaration.isAbstract()) { // || (md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) {
+ return output.append(';');
+ }
+
+ output.append(" {"); //$NON-NLS-1$
+ if (declaration.statements != null) {
+ for (int i = 0; i < declaration.statements.length; i++) {
+ output.append('\n');
+ printStatement(declaration.statements[i], indent);
+ }
+ }
+ output.append('\n');
+ printIndent(indent == 0 ? 0 : indent - 1).append('}');
+ return output;
+ }
+
+ protected StringBuilder printBody(AbstractMethodDeclaration amd, int indent) {
+
+ if (amd.isAbstract()) { // || (md.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) {
+ return output.append(';');
+ }
+
+ output.append(" {"); //$NON-NLS-1$
+ if (amd.statements != null) {
+ for (int i = 0; i < amd.statements.length; i++) {
+ output.append('\n');
+ printStatement(amd.statements[i], indent);
+ }
+ }
+ output.append('\n');
+ printIndent(indent == 0 ? 0 : indent - 1).append('}');
+ return output;
+ }
+
+ protected StringBuilder printArgument(Argument argument) {
+ // printIndent(indent, output);
+ printModifiers(argument.modifiers);
+ if (argument.annotations != null) {
+ printAnnotations(argument.annotations);
+ }
+ printTypeReference(argument.type).append(' ');
+ return output.append(argument.name);
+ }
+
+ void throwit(Object o) {
+ if (true) {
+ System.out.println("so far:" + output.toString());
+ throw new IllegalStateException(o == null ? "" : o.getClass().getName() + ":" + o);
+ }
+ }
+
+ void throwit() {
+ if (true) {
+ throw new IllegalStateException();
+ }
+ }
+
+ public StringBuilder printIndent(int indent) {
+ for (int i = indent; i > 0; i--) {
+ output.append(" "); //$NON-NLS-1$
+ }
+ return output;
+ }
+
+ public StringBuilder printModifiers(int modifiers) {
+
+ if ((modifiers & ClassFileConstants.AccPublic) != 0) {
+ output.append("public "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccPrivate) != 0) {
+ output.append("private "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccProtected) != 0) {
+ output.append("protected "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccStatic) != 0) {
+ output.append("static "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccFinal) != 0) {
+ output.append("final "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccSynchronized) != 0) {
+ output.append("synchronized "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccVolatile) != 0) {
+ output.append("volatile "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccTransient) != 0) {
+ output.append("transient "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccNative) != 0) {
+ output.append("native "); //$NON-NLS-1$
+ }
+ if ((modifiers & ClassFileConstants.AccAbstract) != 0) {
+ output.append("abstract "); //$NON-NLS-1$
+ }
+ return output;
+ }
+
+ public StringBuilder printExpression(Expression e) {
+ // TODO other literals
+ try {
+ expressionLevel++;
+ if (e instanceof TypeReference) {
+ return printTypeReference((TypeReference) e);
+ } else if (e instanceof IntLiteral) {
+ return output.append(((IntLiteral) e).value);
+ } else if (e instanceof CharLiteral) {
+ return output.append(((CharLiteral) e).source());
+ } else if (e instanceof DoubleLiteral) {
+ return output.append(((DoubleLiteral) e).source());
+ } else if (e instanceof LongLiteral) {
+ return output.append(((LongLiteral) e).source());
+ } else if (e instanceof FloatLiteral) {
+ return output.append(((FloatLiteral) e).source());
+ } else if (e instanceof TrueLiteral) {
+ return output.append(((TrueLiteral) e).source());
+ } else if (e instanceof FalseLiteral) {
+ return output.append(((FalseLiteral) e).source());
+ } else if (e instanceof ClassLiteralAccess) {
+ printTypeReference(((ClassLiteralAccess) e).type);
+ return output.append(".class");
+ } else if (e instanceof StringLiteral) {
+ return printStringLiteral((StringLiteral) e);
+ } else if (e instanceof SingleNameReference) {
+ SingleNameReference snr = (SingleNameReference) e;
+ if (snr.binding instanceof ReferenceBinding) {
+ output.append(CharOperation.concatWith(((ReferenceBinding) snr.binding).compoundName, '.'));
+ } else if (snr.binding instanceof ParameterizedFieldBinding) {
+ ParameterizedFieldBinding pfb = (ParameterizedFieldBinding) snr.binding;
+ output.append(pfb.name);
+ } else if (snr.binding instanceof LocalVariableBinding) {
+ LocalVariableBinding lvb = (LocalVariableBinding) snr.binding;
+ output.append(lvb.name);
+ } else if (snr.binding instanceof FieldBinding) {
+ FieldBinding fb = (FieldBinding) snr.binding;
+ ReferenceBinding rb = fb.declaringClass;
+ if (fb.isStatic()) {
+ // qualify it
+ output.append(CharOperation.concatWith(rb.compoundName, '.'));
+ output.append('.');
+ output.append(fb.name);
+ } else {
+ output.append(snr.token);
+ }
+ int stop = 1;
+ } else {
+ throwit(snr.binding);
+ }
+ return output;
+ } else if (e instanceof QualifiedNameReference) {
+ QualifiedNameReference qnr = (QualifiedNameReference) e;
+ if (qnr.binding instanceof FieldBinding) {
+ FieldBinding fb = (FieldBinding) qnr.binding;
+ ReferenceBinding rb = fb.declaringClass;
+ if (fb.isStatic()) {
+ output.append(CharOperation.concatWith(rb.compoundName, '.'));
+ output.append('.');
+ output.append(fb.name);
+ } else {
+ output.append(CharOperation.concatWith(qnr.tokens, '.'));// ((ReferenceBinding) qnr.binding).compoundName,
+ }
+ } else if (qnr.binding instanceof ReferenceBinding) {
+ output.append(CharOperation.concatWith(qnr.tokens, '.'));// ((ReferenceBinding) qnr.binding).compoundName,
+ // '.'));
+ } else if (qnr.binding instanceof LocalVariableBinding) {
+ output.append(CharOperation.concatWith(qnr.tokens, '.'));// oncatWith(((LocalVariableBinding)
+ // qnr.binding).compoundName, '.'));
+ // LocalVariableBinding lvb = (LocalVariableBinding) qnr.binding;
+ // output.append(lvb.name);
+ } else {
+ throwit(qnr.binding);
+ }
+ // output.append(qnr.actualReceiverType.debugName());
+ // output.append('.');
+ // output.append(qnr.tokens[qnr.tokens.length - 1]);
+ return output;
+ } else if (e instanceof ArrayReference) {
+ ArrayReference ar = (ArrayReference) e;
+ printExpression(ar.receiver).append('[');
+ return printExpression(ar.position).append(']');
+ } else if (e instanceof MessageSend) {
+ return printMessageSendStatement((MessageSend) e);
+ } else if (e instanceof ThisReference) {
+ ThisReference tr = (ThisReference) e;
+ if (tr.isImplicitThis()) {
+ return output;
+ }
+ return output.append("this"); //$NON-NLS-1$
+ } else if (e instanceof CastExpression) {
+ return printCastExpression((CastExpression) e);
+ } else if (e instanceof BinaryExpression) {
+ if (expressionLevel != 0) {
+ output.append('(');
+ }
+ expressionLevel++;
+ BinaryExpression be = (BinaryExpression) e;
+ printExpression(be.left).append(' ').append(be.operatorToString()).append(' ');
+ printExpression(be.right);
+ expressionLevel--;
+ if (expressionLevel != 0) {
+ output.append(')');
+ }
+ return output;
+ } else if (e instanceof NullLiteral) {
+ return output.append("null");
+ } else if (e instanceof QualifiedAllocationExpression) {
+ return printQualifiedAllocationExpression((QualifiedAllocationExpression) e, 0);
+ } else if (e instanceof AllocationExpression) {
+ return printAllocationExpression((AllocationExpression) e);
+ } else if (e instanceof ArrayInitializer) {
+ return printArrayInitialized((ArrayInitializer) e);
+ } else if (e instanceof FieldReference) {
+ return printFieldReference((FieldReference) e);
+ } else if (e instanceof UnaryExpression) {
+ return printUnaryExpression((UnaryExpression) e);
+ } else if (e instanceof InstanceOfExpression) {
+ return printInstanceOfExpression((InstanceOfExpression) e);
+ } else if (e instanceof Assignment) {
+ return printAssignment((Assignment) e, false);
+ } else if (e instanceof ArrayAllocationExpression) {
+ return printArrayAllocationExpression((ArrayAllocationExpression) e);
+ } else if (e instanceof ConditionalExpression) {
+ return printConditionalExpression((ConditionalExpression) e);
+ }
+ throwit(e);
+ return output;
+ } finally {
+ expressionLevel--;
+ }
+ }
+
+ private StringBuilder printConditionalExpression(ConditionalExpression e) {
+ if (expressionLevel != 0) {
+ output.append('(');
+ }
+ expressionLevel++;
+ printExpression(e.condition).append(" ? ");
+ printExpression(e.valueIfTrue).append(" : ");
+ printExpression(e.valueIfFalse);
+ expressionLevel--;
+ if (expressionLevel != 0) {
+ output.append(')');
+ }
+ return output;
+ }
+
+ private StringBuilder printArrayAllocationExpression(ArrayAllocationExpression aae) {
+ output.append("new "); //$NON-NLS-1$
+ printTypeReference(aae.type);
+ for (int i = 0; i < aae.dimensions.length; i++) {
+ if (aae.dimensions[i] == null) {
+ output.append("[]"); //$NON-NLS-1$
+ } else {
+ output.append('[');
+ printExpression(aae.dimensions[i]);
+ output.append(']');
+ }
+ }
+ if (aae.initializer != null) {
+ printExpression(aae.initializer);
+ }
+ return output;
+ }
+
+ private StringBuilder printInstanceOfExpression(InstanceOfExpression e) {
+ if (expressionLevel != 0) {
+ output.append('(');
+ }
+ expressionLevel++;
+ printExpression(e.expression).append(" instanceof "); //$NON-NLS-1$
+ printTypeReference(e.type);
+ expressionLevel--;
+ if (expressionLevel != 0) {
+ output.append(')');
+ }
+ return output;
+ }
+
+ private StringBuilder printUnaryExpression(UnaryExpression e) {
+ if (expressionLevel != 0) {
+ output.append('(');
+ }
+ expressionLevel++;
+ output.append(e.operatorToString()).append(' ');
+ printExpression(e.expression);
+ expressionLevel--;
+ if (expressionLevel != 0) {
+ output.append(')');
+ }
+ return output;
+ }
+
+ private StringBuilder printFieldReference(FieldReference fr) {
+ printExpression(fr.receiver).append('.').append(fr.token);
+ return output;
+ }
+
+ private StringBuilder printArrayInitialized(ArrayInitializer e) {
+
+ output.append('{');
+ if (e.expressions != null) {
+ // int j = 20;
+ for (int i = 0; i < e.expressions.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printExpression(e.expressions[i]);
+ // expressions[i].printExpression(0, output);
+ // j--;
+ // if (j == 0) {
+ // output.append('\n');
+ // printIndent(indent + 1, output);
+ // j = 20;
+ // }
+ }
+ }
+ return output.append('}');
+ }
+
+ private StringBuilder printCastExpression(CastExpression e) {
+ output.append('(');
+ output.append('(');
+ printExpression(e.type).append(") "); //$NON-NLS-1$
+ printExpression(e.expression);
+ output.append(')');
+ return output;
+ }
+
+ private StringBuilder printStringLiteral(StringLiteral e) {
+ output.append('\"');
+ for (int i = 0; i < e.source().length; i++) {
+ switch (e.source()[i]) {
+ case '\b':
+ output.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t':
+ output.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n':
+ output.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f':
+ output.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r':
+ output.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\"':
+ output.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'':
+ output.append("\\'"); //$NON-NLS-1$
+ break;
+ case '\\': // take care not to display the escape as a potential real char
+ output.append("\\\\"); //$NON-NLS-1$
+ break;
+ default:
+ output.append(e.source()[i]);
+ }
+ }
+ output.append('\"');
+ return output;
+ }
+
+ public StringBuilder printExpression(SingleTypeReference str) {
+ output.append(str.token);
+ return output;
+ }
+
+ protected StringBuilder printStatement(Statement statement, int indent) {
+ return printStatement(statement, indent, true);
+ }
+
+ protected StringBuilder printStatement(Statement statement, int indent, boolean applyIndent) {
+ if (statement instanceof ReturnStatement) {
+ printIndent(indent).append("return "); //$NON-NLS-1$
+ if (((ReturnStatement) statement).expression != null) {
+ printExpression(((ReturnStatement) statement).expression);
+ }
+ return output.append(';');
+ } else if (statement instanceof PostfixExpression) {
+ return printPostfixExpression((PostfixExpression) statement);
+ } else if (statement instanceof PrefixExpression) {
+ return printPrefixExpression((PrefixExpression) statement);
+ } else if (statement instanceof MessageSend) {
+ printIndent(indent);
+ MessageSend ms = (MessageSend) statement;
+ printMessageSendStatement(ms);
+ return output.append(';');
+ } else if (statement instanceof QualifiedAllocationExpression) {
+ printIndent(indent);
+ printQualifiedAllocationExpression((QualifiedAllocationExpression) statement, indent);
+ return output.append(';');
+ } else if (statement instanceof Assignment) {
+ printIndent(indent);
+ printAssignment((Assignment) statement);
+ return output.append(';');
+ } else if (statement instanceof TryStatement) {
+ printTryStatement((TryStatement) statement, indent);
+ return output;
+ } else if (statement instanceof IfStatement) {
+ printIndent(indent);
+ IfStatement is = (IfStatement) statement;
+ printIndent(indent).append("if ("); //$NON-NLS-1$
+ printExpression(is.condition).append(")\n"); //$NON-NLS-1$
+ printStatement(is.thenStatement, indent + 2);
+ if (is.elseStatement != null) {
+ output.append('\n');
+ printIndent(indent);
+ output.append("else\n"); //$NON-NLS-1$
+ printStatement(is.elseStatement, indent + 2);
+ }
+ return output;
+ } else if (statement instanceof Block) {
+ printBlock((Block) statement, indent, applyIndent);
+ return output;
+ } else if (statement instanceof LocalDeclaration) {
+ return printLocalDeclaration((LocalDeclaration) statement, indent);
+ } else if (statement instanceof SwitchStatement) {
+ return printSwitchStatement((SwitchStatement) statement, indent);
+ } else if (statement instanceof CaseStatement) {
+ return printCaseStatement((CaseStatement) statement, indent);
+ } else if (statement instanceof BreakStatement) {
+ return printBreakStatement((BreakStatement) statement, indent);
+ } else if (statement instanceof ThrowStatement) {
+ return printThrowStatement((ThrowStatement) statement, indent);
+ } else if (statement instanceof TypeDeclaration) {
+ return printTypeDeclaration((TypeDeclaration) statement, indent, false).append(';');
+ } else if (statement instanceof AssertStatement) {
+ return printAssertStatement((AssertStatement) statement, indent);
+ } else if (statement instanceof ForStatement) {
+ return printForStatement((ForStatement) statement, indent);
+ } else if (statement instanceof ForeachStatement) {
+ return printForeachStatement((ForeachStatement) statement, indent);
+ }
+ System.err.println(statement);
+ System.err.println(statement.getClass().getName());
+ throwit(statement);
+
+ return output;
+ }
+
+ private StringBuilder printPostfixExpression(PostfixExpression pe) {
+ printExpression(pe.lhs);
+ output.append(' ');
+ output.append(pe.operatorToString());
+ return output;
+ }
+
+ private StringBuilder printPrefixExpression(PrefixExpression pe) {
+ output.append(pe.operatorToString());
+ output.append(' ');
+ printExpression(pe.lhs);
+ return output;
+ }
+
+ public StringBuilder printAsExpression(LocalDeclaration ld, int indent) {
+ // printIndent(indent);
+ printModifiers(ld.modifiers);
+ if (ld.annotations != null) {
+ printAnnotations(ld.annotations);
+ }
+
+ if (ld.type != null) {
+ printTypeReference(ld.type).append(' ');
+ }
+ output.append(ld.name);
+ switch (ld.getKind()) {
+ case AbstractVariableDeclaration.ENUM_CONSTANT:
+ if (ld.initialization != null) {
+ printExpression(ld.initialization);
+ }
+ break;
+ default:
+ if (ld.initialization != null) {
+ output.append(" = "); //$NON-NLS-1$
+ printExpression(ld.initialization);
+ }
+ }
+ return output;
+ }
+
+ private StringBuilder printForeachStatement(ForeachStatement statement, int indent) {
+ printIndent(indent).append("for ("); //$NON-NLS-1$
+ printAsExpression(statement.elementVariable, indent);
+ output.append(" : ");//$NON-NLS-1$
+ printExpression(statement.collection).append(") "); //$NON-NLS-1$
+ // block
+ if (statement.action == null) {
+ output.append(';');
+ } else {
+ printStatement(statement.action, indent + 1);
+ }
+ return output;
+ }
+
+ private StringBuilder printForStatement(ForStatement fs, int indent) {
+ printIndent(indent).append("for ("); //$NON-NLS-1$
+
+ // inits
+ if (fs.initializations != null) {
+ for (int i = 0; i < fs.initializations.length; i++) {
+ // nice only with expressions
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printStatement(fs.initializations[i], 0);
+ }
+ }
+ if (!output.toString().endsWith(";")) {
+ output.append("; "); //$NON-NLS-1$
+ }
+ // cond
+ if (fs.condition != null) {
+ printExpression(fs.condition);
+ }
+ output.append("; "); //$NON-NLS-1$
+ // updates
+ if (fs.increments != null) {
+ for (int i = 0; i < fs.increments.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printStatement(fs.increments[i], 0);
+ }
+ }
+ output.append(") "); //$NON-NLS-1$
+ // block
+ if (fs.action == null) {
+ output.append(';');
+ } else {
+ // output.append('\n');
+ printStatement(fs.action, indent + 1, false);
+ }
+ return output;
+ }
+
+ private StringBuilder printAssertStatement(AssertStatement as, int indent) {
+ printIndent(indent);
+ output.append("assert "); //$NON-NLS-1$
+ printExpression(as.assertExpression);
+ if (as.exceptionArgument != null) {
+ output.append(": "); //$NON-NLS-1$
+ printExpression(as.exceptionArgument);
+ }
+ return output.append(';');
+ }
+
+ private StringBuilder printThrowStatement(ThrowStatement ts, int indent) {
+ printIndent(indent).append("throw "); //$NON-NLS-1$
+ printExpression(ts.exception);
+ return output.append(';');
+ }
+
+ private StringBuilder printBreakStatement(BreakStatement statement, int indent) {
+ printIndent(indent).append("break "); //$NON-NLS-1$
+ if (statement.label != null) {
+ output.append(statement.label);
+ }
+ return output.append(';');
+ }
+
+ private StringBuilder printCaseStatement(CaseStatement statement, int indent) {
+ printIndent(indent);
+ if (statement.constantExpression == null) {
+ output.append("default : "); //$NON-NLS-1$
+ } else {
+ output.append("case "); //$NON-NLS-1$
+ printExpression(statement.constantExpression).append(" : "); //$NON-NLS-1$
+ }
+ return output;// output.append(';');
+ }
+
+ private StringBuilder printSwitchStatement(SwitchStatement statement, int indent) {
+ printIndent(indent).append("switch ("); //$NON-NLS-1$
+ printExpression(statement.expression).append(") {"); //$NON-NLS-1$
+ if (statement.statements != null) {
+ for (int i = 0; i < statement.statements.length; i++) {
+ output.append('\n');
+ if (statement.statements[i] instanceof CaseStatement) {
+ printStatement(statement.statements[i], indent);
+ } else {
+ printStatement(statement.statements[i], indent + 2);
+ }
+ }
+ }
+ output.append("\n"); //$NON-NLS-1$
+ return printIndent(indent).append('}');
+ }
+
+ private StringBuilder printLocalDeclaration(LocalDeclaration statement, int indent) {
+ printAbstractVariableDeclarationAsExpression(statement, indent);
+ switch (statement.getKind()) {
+ case AbstractVariableDeclaration.ENUM_CONSTANT:
+ return output.append(',');
+ default:
+ return output.append(';');
+ }
+ }
+
+ private StringBuilder printAbstractVariableDeclarationAsExpression(AbstractVariableDeclaration avd, int indent) {
+ printIndent(indent);
+ printModifiers(avd.modifiers);
+ if (avd.annotations != null) {
+ printAnnotations(avd.annotations);
+ }
+
+ if (avd.type != null) {
+ printTypeReference(avd.type).append(' ');
+ }
+ output.append(avd.name);
+ switch (avd.getKind()) {
+ case AbstractVariableDeclaration.ENUM_CONSTANT:
+ if (avd.initialization != null) {
+ printExpression(avd.initialization);
+ }
+ break;
+ default:
+ if (avd.initialization != null) {
+ output.append(" = "); //$NON-NLS-1$
+ printExpression(avd.initialization);
+ }
+ }
+ return output;
+ }
+
+ private StringBuilder printBlock(Block b, int indent, boolean applyIndent) {
+ if (applyIndent) {
+ printIndent(indent);
+ }
+ output.append("{\n"); //$NON-NLS-1$
+ printBody(b, indent);
+ printIndent(indent);
+ return output.append('}');
+ }
+
+ public StringBuilder printBody(Block b, int indent) {
+ if (b.statements == null) {
+ return output;
+ }
+ for (int i = 0; i < b.statements.length; i++) {
+ printStatement(b.statements[i], indent + 1);
+ output.append('\n');
+ }
+ return output;
+ }
+
+ private StringBuilder printTryStatement(TryStatement statement, int indent) {
+ printIndent(indent).append("try "); //$NON-NLS-1$
+ printBlock(statement.tryBlock, indent, false);
+ // catches
+ if (statement.catchBlocks != null) {
+ for (int i = 0; i < statement.catchBlocks.length; i++) {
+ // output.append('\n');
+ // printIndent(indent).
+ output.append(" catch ("); //$NON-NLS-1$
+ printArgument(statement.catchArguments[i]).append(") "); //$NON-NLS-1$
+ printBlock(statement.catchBlocks[i], indent, false);
+ // statement.catchBlocks[i].printStatement(indent + 1, output);
+ }
+ }
+ // finally
+ if (statement.finallyBlock != null) {
+ // output.append('\n');
+ // printIndent(indent).
+ output.append(" finally "); //$NON-NLS-1$
+ printBlock(statement.finallyBlock, indent, false);// .printStatement(indent + 1, output);
+ }
+ return output;
+ }
+
+ private StringBuilder printAssignment(Assignment statement) {
+ return printAssignment(statement, expressionLevel != 0);
+ }
+
+ private StringBuilder printAssignment(Assignment statement, boolean parens) {
+ if (parens) {
+ output.append('(');
+ }
+ printExpression(statement.lhs).append(" = ");
+ printExpression(statement.expression);
+ if (parens) {
+ output.append(')');
+ }
+ return output;
+ }
+
+ private StringBuilder printMessageSendStatement(MessageSend ms) {
+ if (!ms.receiver.isImplicitThis()) {
+ printExpression(ms.receiver).append('.');
+ }
+ if (ms.typeArguments != null) {
+ output.append('<');
+ int max = ms.typeArguments.length - 1;
+ for (int j = 0; j < max; j++) {
+ printTypeReference(ms.typeArguments[j]);
+ // ms.typeArguments[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ printTypeReference(ms.typeArguments[max]);
+ // ms.typeArguments[max].print(0, output);
+ output.append('>');
+ }
+ output.append(ms.selector).append('(');
+ if (ms.arguments != null) {
+ for (int i = 0; i < ms.arguments.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printExpression(ms.arguments[i]);
+ }
+ }
+ return output.append(')');
+ }
+
+ protected StringBuilder printQualifiedAllocationExpression(QualifiedAllocationExpression qae, int indent) {
+ if (qae.enclosingInstance != null) {
+ printExpression(qae.enclosingInstance).append('.');
+ }
+ printAllocationExpression(qae);
+ if (qae.anonymousType != null) {
+ printTypeDeclaration(qae.anonymousType, indent, true);
+ }
+ return output;
+ }
+
+ protected StringBuilder printTypeDeclaration(TypeDeclaration td, int indent, boolean isAnonymous) {
+ if (td.javadoc != null) {
+ throwit(td);
+ // td.javadoc.print(indent, output);
+ }
+ if ((td.bits & ASTNode.IsAnonymousType) == 0) {
+ printIndent(tab);
+ printTypeDeclarationHeader(td);
+ }
+ printTypeDeclarationBody(td, indent, isAnonymous);
+ return output;
+ }
+
+ public StringBuilder printTypeDeclarationBody(TypeDeclaration td, int indent, boolean isAnonymous) {
+ output.append(" {"); //$NON-NLS-1$
+ if (td.memberTypes != null) {
+ for (int i = 0; i < td.memberTypes.length; i++) {
+ if (td.memberTypes[i] != null) {
+ output.append('\n');
+ printTypeDeclaration(td.memberTypes[i], indent + 1, false);
+ }
+ }
+ }
+ if (td.fields != null) {
+ for (int fieldI = 0; fieldI < td.fields.length; fieldI++) {
+ if (td.fields[fieldI] != null) {
+ output.append('\n');
+ printFieldDeclaration(td.fields[fieldI], indent + 1);
+ }
+ }
+ }
+ if (td.methods != null) {
+ for (int i = 0; i < td.methods.length; i++) {
+ if (td.methods[i] != null) {
+ AbstractMethodDeclaration amd = td.methods[i];
+ if (amd instanceof MethodDeclaration) {
+ output.append('\n');
+ printMethodDeclaration(((MethodDeclaration) amd), indent + 1);
+ } else if (amd instanceof ConstructorDeclaration) {
+ if (!isAnonymous) {
+ output.append('\n');
+ // likely to be just a ctor with name 'x' as set in TypeDeclaration.createDefaultConstructorWithBinding
+ printConstructorDeclaration(((ConstructorDeclaration) amd), indent + 1);
+ }
+ } else {
+ throwit(amd);
+ }
+ }
+ }
+ }
+ output.append('\n');
+ return printIndent(indent).append('}');
+ }
+
+ protected StringBuilder printFieldDeclaration(FieldDeclaration fd, int indent) {
+ printIndent(indent);
+ printModifiers(fd.modifiers);
+ if (fd.annotations != null) {
+ printAnnotations(fd.annotations);
+ }
+
+ if (fd.type != null) {
+ printTypeReference(fd.type).append(' ');
+ }
+ output.append(fd.name);
+ switch (fd.getKind()) {
+ case AbstractVariableDeclaration.ENUM_CONSTANT:
+ if (fd.initialization != null) {
+ printExpression(fd.initialization);
+ }
+ break;
+ default:
+ if (fd.initialization != null) {
+ output.append(" = "); //$NON-NLS-1$
+ printExpression(fd.initialization);
+ }
+ }
+ output.append(';');
+ return output;
+ }
+
+ protected StringBuilder printConstructorDeclaration(ConstructorDeclaration amd, int tab) {
+ if (amd.javadoc != null) {
+ throwit();
+ // amd.javadoc.print(tab, output);
+ }
+ printIndent(tab);
+ if (amd.annotations != null) {
+ printAnnotations(amd.annotations);
+ }
+ printModifiers(amd.modifiers);
+
+ TypeParameter[] typeParams = amd.typeParameters();
+ if (typeParams != null) {
+ output.append('<');
+ int max = typeParams.length - 1;
+ for (int j = 0; j < max; j++) {
+ printTypeParameter(typeParams[j]);
+ // typeParams[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ printTypeParameter(typeParams[max]);
+ output.append('>');
+ }
+
+ // TODO confirm selector is right name
+ output.append(amd.selector).append('(');
+ if (amd.arguments != null) {
+ for (int i = 0; i < amd.arguments.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printArgument(amd.arguments[i]);
+ }
+ }
+ output.append(')');
+ if (amd.thrownExceptions != null) {
+ output.append(" throws "); //$NON-NLS-1$
+ for (int i = 0; i < amd.thrownExceptions.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ throwit();
+ // this.thrownExceptions[i].print(0, output);
+ }
+ }
+ printBody(amd, tab + 1);
+ return output;
+ }
+
+ private StringBuilder printMethodDeclaration(MethodDeclaration amd, int tab) {
+
+ if (amd.javadoc != null) {
+ throwit();
+ // amd.javadoc.print(tab, output);
+ }
+ printIndent(tab);
+ if (amd.annotations != null) {
+ printAnnotations(amd.annotations);
+ }
+ printModifiers(amd.modifiers);
+
+ TypeParameter[] typeParams = amd.typeParameters();
+ if (typeParams != null) {
+ output.append('<');
+ int max = typeParams.length - 1;
+ for (int j = 0; j < max; j++) {
+ printTypeParameter(typeParams[j]);
+ // typeParams[j].print(0, output);
+ output.append(", ");//$NON-NLS-1$
+ }
+ printTypeParameter(typeParams[max]);
+ output.append('>');
+ }
+
+ printReturnType(amd.returnType).append(amd.selector).append('(');
+ if (amd.arguments != null) {
+ for (int i = 0; i < amd.arguments.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printArgument(amd.arguments[i]);
+ }
+ }
+ output.append(')');
+ if (amd.thrownExceptions != null) {
+ output.append(" throws "); //$NON-NLS-1$
+ for (int i = 0; i < amd.thrownExceptions.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ throwit();
+ // this.thrownExceptions[i].print(0, output);
+ }
+ }
+ printBody(amd, tab + 1);
+ return output;
+ }
+
+ public StringBuilder printReturnType(TypeReference tr) {
+ if (tr == null) {
+ return output;
+ }
+ return printExpression(tr).append(' ');
+ }
+
+ public final static int kind(int flags) {
+ switch (flags & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) {
+ case ClassFileConstants.AccInterface:
+ return TypeDeclaration.INTERFACE_DECL;
+ case ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation:
+ return TypeDeclaration.ANNOTATION_TYPE_DECL;
+ case ClassFileConstants.AccEnum:
+ return TypeDeclaration.ENUM_DECL;
+ default:
+ return TypeDeclaration.CLASS_DECL;
+ }
+ }
+
+ protected StringBuilder printTypeDeclarationHeader(TypeDeclaration td) {
+ printModifiers(td.modifiers);
+ if (td.annotations != null) {
+ printAnnotations(td.annotations);
+ }
+
+ switch (kind(td.modifiers)) {
+ case TypeDeclaration.CLASS_DECL:
+ output.append("class "); //$NON-NLS-1$
+ break;
+ case TypeDeclaration.INTERFACE_DECL:
+ output.append("interface "); //$NON-NLS-1$
+ break;
+ case TypeDeclaration.ENUM_DECL:
+ output.append("enum "); //$NON-NLS-1$
+ break;
+ case TypeDeclaration.ANNOTATION_TYPE_DECL:
+ output.append("@interface "); //$NON-NLS-1$
+ break;
+ }
+ output.append(td.name);
+ if (td.typeParameters != null) {
+ output.append("<");//$NON-NLS-1$
+ for (int i = 0; i < td.typeParameters.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printTypeParameter(td.typeParameters[i]);
+ // this.typeParameters[i].print(0, output);
+ }
+ output.append(">");//$NON-NLS-1$
+ }
+ if (td.superclass != null) {
+ output.append(" extends "); //$NON-NLS-1$
+ printTypeReference(td.superclass);
+ }
+ if (td.superInterfaces != null && td.superInterfaces.length > 0) {
+ switch (kind(td.modifiers)) {
+ case TypeDeclaration.CLASS_DECL:
+ case TypeDeclaration.ENUM_DECL:
+ output.append(" implements "); //$NON-NLS-1$
+ break;
+ case TypeDeclaration.INTERFACE_DECL:
+ case TypeDeclaration.ANNOTATION_TYPE_DECL:
+ output.append(" extends "); //$NON-NLS-1$
+ break;
+ }
+ for (int i = 0; i < td.superInterfaces.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printTypeReference(td.superInterfaces[i]);
+ }
+ }
+ return output;
+ }
+
+ protected StringBuilder printTypeParameter(TypeParameter tp) {
+ output.append(tp.name);
+ if (tp.type != null) {
+ output.append(" extends "); //$NON-NLS-1$
+ printTypeReference(tp.type);
+ }
+ if (tp.bounds != null) {
+ for (int i = 0; i < tp.bounds.length; i++) {
+ output.append(" & "); //$NON-NLS-1$
+ printTypeReference(tp.bounds[i]);
+ }
+ }
+ return output;
+ }
+
+ protected StringBuilder printAllocationExpression(AllocationExpression ae) {
+ if (ae.type != null) { // type null for enum constant initializations
+ output.append("new "); //$NON-NLS-1$
+ }
+ if (ae.typeArguments != null) {
+ output.append('<');
+ int max = ae.typeArguments.length - 1;
+ for (int j = 0; j < max; j++) {
+ printTypeReference(ae.typeArguments[j]);
+ output.append(", ");//$NON-NLS-1$
+ }
+ printTypeReference(ae.typeArguments[max]);
+ output.append('>');
+ }
+ if (ae.type != null) { // type null for enum constant initializations
+ printExpression(ae.type);
+ }
+ output.append('(');
+ if (ae.arguments != null) {
+ for (int i = 0; i < ae.arguments.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printExpression(ae.arguments[i]);
+ }
+ }
+ return output.append(')');
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2010 Contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement - SpringSource
+ * ******************************************************************/
+//package org.aspectj.ajdt.internal.compiler;
+//
+//import org.aspectj.ajdt.internal.compiler.ast.DeclareAnnotationDeclaration;
+//import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
+//import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+//
+//class DeclareAnnotationsPrinter extends HelperPrinter {
+//
+// private DeclareAnnotationDeclaration dad;
+//
+// DeclareAnnotationsPrinter(DeclareAnnotationDeclaration md, MethodScope mscope) {
+// super(mscope);
+// output = new StringBuilder();
+// this.amd = md;
+// this.dad = md;
+// }
+//
+// public String print() {
+// return print(2);
+// }
+//
+// public String print(int tab) {
+// output = new StringBuilder();
+// Annotation[] annos = dad.annotations;
+// int count = 0;
+// for (int a = 0; a < annos.length; a++) {
+// Annotation anno = annos[a];
+// String aa = anno.type.toString();
+// if (!aa.startsWith("org.aspectj")) {
+// if (count > 0) {
+// output.append(' ');
+// }
+// printAnnotation(anno);
+// count++;
+// }
+// }
+// return output.toString();
+// }
+// }
\ No newline at end of file
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2010 Contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement - SpringSource
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import java.lang.reflect.Modifier;
+
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration;
+import org.aspectj.asm.internal.CharOperation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+
+/**
+ * Prints the declaration for an intertype declared constructor.
+ *
+ * @author Andy Clement
+ */
+class ITDConstructorPrinter extends CommonPrinter {
+
+ private InterTypeConstructorDeclaration constructorDeclaration;
+
+ ITDConstructorPrinter(InterTypeConstructorDeclaration constructorDeclaration, MethodScope mscope) {
+ super(mscope);
+ this.output = new StringBuilder();
+ this.declaration = constructorDeclaration;
+ this.constructorDeclaration = constructorDeclaration;
+ }
+
+ public String print() {
+ return print(2);
+ }
+
+ public String print(int tab) {
+
+ this.output = new StringBuilder();
+
+ if (constructorDeclaration.javadoc != null) {
+ throwit(null);
+ // md.javadoc.print(tab, output);
+ }
+ printIndent(tab);
+ if (constructorDeclaration.annotations != null) {
+ printAnnotations(constructorDeclaration.annotations);
+ }
+ printModifiers(constructorDeclaration.declaredModifiers); // not md.modifiers
+
+ TypeParameter[] typeParams = constructorDeclaration.typeParameters();
+ if (typeParams != null) {
+ output.append('<');
+ int max = typeParams.length - 1;
+ for (int j = 0; j < max; j++) {
+ printTypeParameter(typeParams[j]);
+ output.append(", ");//$NON-NLS-1$
+ }
+ printTypeParameter(typeParams[max]);
+ output.append("> ");
+ }
+
+ char[] s = constructorDeclaration.getDeclaredSelector();
+
+ output.append(CharOperation.subarray(s, 0, s.length - 4)).append('(');
+ if (constructorDeclaration.arguments != null) {
+ for (int i = Modifier.isStatic(constructorDeclaration.declaredModifiers) ? 0 : 1; i < constructorDeclaration.arguments.length; i++) {
+
+ printArgument(constructorDeclaration.arguments[i]);
+ if ((i + 1) < constructorDeclaration.arguments.length) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ }
+ }
+ output.append(')');
+
+ if (constructorDeclaration.thrownExceptions != null) {
+ output.append(" throws "); //$NON-NLS-1$
+ for (int i = 0; i < constructorDeclaration.thrownExceptions.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printTypeReference(constructorDeclaration.thrownExceptions[i]);
+ }
+ }
+ printBody(tab + 1);
+ return output.toString();
+ }
+
+ // TODO better name
+ public StringBuilder printReturnType(int indent) {
+ if (constructorDeclaration.returnType == null) {
+ return output;
+ }
+ return printExpression(constructorDeclaration.returnType).append(' ');
+ }
+}
\ No newline at end of file
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2010 Contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement - SpringSource
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+
+/**
+ * Prints the declaration for an intertype declared field, including initializer.
+ *
+ * @author Andy Clement
+ */
+class ITDFieldPrinter extends CommonPrinter {
+
+ private InterTypeFieldDeclaration fieldDeclaration;
+
+ ITDFieldPrinter(InterTypeFieldDeclaration fieldDeclaration, MethodScope methodscope) {
+ super(methodscope);
+ output = new StringBuilder();
+ this.fieldDeclaration = fieldDeclaration;
+ }
+
+ public String print() {
+ return print(2);
+ }
+
+ public String print(int tab) {
+ this.output = new StringBuilder();
+
+ if (fieldDeclaration.javadoc != null) {
+ // TODO javadoc
+ // md.javadoc.print(tab, output);
+ }
+ printIndent(tab);
+ if (fieldDeclaration.annotations != null) {
+ printAnnotations(fieldDeclaration.annotations);
+ }
+ printModifiers(fieldDeclaration.declaredModifiers); // not md.modifiers
+
+ TypeParameter[] typeParams = fieldDeclaration.typeParameters();
+ if (typeParams != null) {
+ output.append('<');
+ int max = typeParams.length - 1;
+ for (int j = 0; j < max; j++) {
+ printTypeParameter(typeParams[j]);
+ output.append(", ");//$NON-NLS-1$
+ }
+ printTypeParameter(typeParams[max]);
+ output.append('>');
+ }
+ printReturnType(0).append(fieldDeclaration.getDeclaredSelector());
+ if (fieldDeclaration.initialization != null) {
+ output.append(" = ");
+ printExpression(fieldDeclaration.initialization);
+ }
+ output.append(';');
+ return output.toString();
+ }
+
+ // TODO better name
+ public StringBuilder printReturnType(int indent) {
+ if (fieldDeclaration.returnType == null) {
+ return output;
+ }
+ return printExpression(fieldDeclaration.returnType).append(' ');
+ }
+}
\ No newline at end of file
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2010 Contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement - SpringSource
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler;
+
+import java.lang.reflect.Modifier;
+
+import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+
+/**
+ * Prints the declaration for an intertype declared method.
+ *
+ * @author Andy Clement
+ */
+class ITDMethodPrinter extends CommonPrinter {
+ private InterTypeMethodDeclaration methodDeclaration;
+
+ ITDMethodPrinter(InterTypeMethodDeclaration methodDeclaration, MethodScope methodscope) {
+ super(methodscope);
+ output = new StringBuilder();
+ this.methodDeclaration = methodDeclaration;
+ this.declaration = methodDeclaration;
+ }
+
+ public String print() {
+ return print(2);
+ }
+
+ public StringBuilder printReturnType(int indent) {
+ if (methodDeclaration.returnType == null) {
+ return output;
+ }
+ return printExpression(methodDeclaration.returnType).append(' ');
+ }
+
+ public String print(int tab) {
+ this.output = new StringBuilder();
+
+ if (methodDeclaration.javadoc != null) {
+ // TODO javadoc support...
+ // md.javadoc.print(tab, output);
+ }
+ printIndent(tab);
+ if (methodDeclaration.annotations != null) {
+ printAnnotations(methodDeclaration.annotations);
+ }
+ printModifiers(methodDeclaration.declaredModifiers); // not md.modifiers
+
+ TypeParameter[] typeParams = methodDeclaration.typeParameters();
+ if (typeParams != null) {
+ output.append('<');
+ int max = typeParams.length - 1;
+ for (int j = 0; j < max; j++) {
+ printTypeParameter(typeParams[j]);
+ output.append(", ");//$NON-NLS-1$
+ }
+ printTypeParameter(typeParams[max]);
+ output.append("> ");
+ }
+
+ printReturnType(0).append(methodDeclaration.getDeclaredSelector()).append('(');
+ if (methodDeclaration.arguments != null) {
+ for (int i = Modifier.isStatic(methodDeclaration.declaredModifiers) ? 0 : 1; i < methodDeclaration.arguments.length; i++) {
+
+ printArgument(methodDeclaration.arguments[i]);
+ if ((i + 1) < methodDeclaration.arguments.length) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ }
+ }
+ output.append(')');
+
+ if (methodDeclaration.thrownExceptions != null) {
+ output.append(" throws "); //$NON-NLS-1$
+ for (int i = 0; i < methodDeclaration.thrownExceptions.length; i++) {
+ if (i > 0) {
+ output.append(", "); //$NON-NLS-1$
+ }
+ printTypeReference(methodDeclaration.thrownExceptions[i]);
+ }
+ }
+ printBody(tab + 1);
+ return output.toString();
+ }
+}
\ No newline at end of file
import java.util.List;
-import org.aspectj.weaver.bcel.UnwovenClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.aspectj.weaver.bcel.UnwovenClassFile;
/**
- * Holds a compilation result produced by the Java compilation phase,
- * ready for weaving in the weave phase.
- * NOTE: This class defines equality based solely on the fileName
- * of the compiled file (not the bytecodes produced for example)
+ * Holds a compilation result produced by the Java compilation phase, ready for weaving in the weave phase. NOTE: This class defines
+ * equality based solely on the fileName of the compiled file (not the bytecodes produced for example)
*/
public class InterimCompilationResult {
-
- private CompilationResult result;
- private UnwovenClassFile[] unwovenClassFiles; // longer term would be nice not to have two copies of
- // the byte codes, one in result.classFiles and another
- // in unwovenClassFiles;
- public InterimCompilationResult(CompilationResult cr,
- IOutputClassFileNameProvider np) {
- result = cr;
- unwovenClassFiles = ClassFileBasedByteCodeProvider.unwovenClassFilesFor(result,np);
- }
-
- public InterimCompilationResult(CompilationResult cr, List ucfList) {
- result = cr;
- unwovenClassFiles = new UnwovenClassFile[ucfList.size()];
- for (int i=0; i < ucfList.size(); i++) {
- UnwovenClassFile element = (UnwovenClassFile) ucfList.get(i);
+ private CompilationResult result;
+ private UnwovenClassFile[] unwovenClassFiles; // longer term would be nice not to have two copies of
+
+ // the byte codes, one in result.classFiles and another
+ // in unwovenClassFiles;
+
+ public InterimCompilationResult(CompilationResult cr, IOutputClassFileNameProvider np) {
+ result = cr;
+ unwovenClassFiles = ClassFileBasedByteCodeProvider.unwovenClassFilesFor(result, np);
+ }
+
+ public InterimCompilationResult(CompilationResult cr, List<UnwovenClassFile> ucfList) {
+ result = cr;
+ unwovenClassFiles = new UnwovenClassFile[ucfList.size()];
+ for (int i = 0; i < ucfList.size(); i++) {
+ UnwovenClassFile element = ucfList.get(i);
unwovenClassFiles[i] = element;
- AjClassFile ajcf = new AjClassFile(element.getClassNameAsChars(),
- element.getBytes());
- result.record(ajcf.fileName(),ajcf);
- }
- }
-
- public CompilationResult result() { return result; }
-
- public UnwovenClassFile[] unwovenClassFiles() { return unwovenClassFiles; }
-
- public String fileName() {
- return new String(result.fileName);
- }
-
- public boolean equals(Object other) {
- if( other == null || !(other instanceof InterimCompilationResult)) {
- return false;
- }
- InterimCompilationResult ir = (InterimCompilationResult) other;
- return fileName().equals(ir.fileName());
- }
- public int hashCode() {
- return fileName().hashCode();
- }
-
+ AjClassFile ajcf = new AjClassFile(element.getClassNameAsChars(), element.getBytes());
+ result.record(ajcf.fileName(), ajcf);
+ }
+ }
+
+ public CompilationResult result() {
+ return result;
+ }
+
+ public UnwovenClassFile[] unwovenClassFiles() {
+ return unwovenClassFiles;
+ }
+
+ public String fileName() {
+ return new String(result.fileName);
+ }
+
+ public boolean equals(Object other) {
+ if (other == null || !(other instanceof InterimCompilationResult)) {
+ return false;
+ }
+ InterimCompilationResult ir = (InterimCompilationResult) other;
+ return fileName().equals(ir.fileName());
+ }
+
+ public int hashCode() {
+ return fileName().hashCode();
+ }
+
}
import java.util.Map;
import java.util.Set;
+import org.aspectj.ajdt.internal.compiler.CommonPrinter;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.asm.AsmManager;
if (!decp.isMixin()) {
boolean didSomething = doDeclareParents(decp, sourceType);
if (didSomething) {
+ if (factory.pushinCollector != null) {
+ factory.pushinCollector.tagAsMunged(sourceType, decp.getParents().get(0));
+ }
anyNewParents = true;
} else {
if (!decp.getChild().isStarAnnotation()) {
DeclareAnnotation deca = (DeclareAnnotation) i.next();
boolean didSomething = doDeclareAnnotations(deca, sourceType, true);
if (didSomething) {
+
anyNewAnnotations = true;
} else {
if (!deca.getTypePattern().isStar()) {
DeclareParents decp = (DeclareParents) i.next();
boolean didSomething = doDeclareParents(decp, sourceType);
if (didSomething) {
+ if (factory.pushinCollector != null) {
+ factory.pushinCollector.tagAsMunged(sourceType, decp.getParents().get(0));
+ }
anyNewParents = true;
forRemoval.add(decp);
}
DeclareAnnotation deca = (DeclareAnnotation) i.next();
boolean didSomething = doDeclareAnnotations(deca, sourceType, false);
if (didSomething) {
+ if (factory.pushinCollector != null) {
+ factory.pushinCollector.tagAsMunged(sourceType, deca.getAnnotationString());
+ }
anyNewAnnotations = true;
forRemoval.add(deca);
}
onType.checkInterTypeMungers();
for (Iterator i = onType.getInterTypeMungers().iterator(); i.hasNext();) {
EclipseTypeMunger munger = (EclipseTypeMunger) i.next();
- munger.munge(sourceType, onType);
+ if (munger.munge(sourceType, onType)) {
+ if (factory.pushinCollector != null) {
+ factory.pushinCollector.tagAsMunged(sourceType, munger.getSourceMethod());
+ }
+ }
}
// Call if you would like to do source weaving of declare
Annotation[] toAdd = null;
long abits = 0;
+ AbstractMethodDeclaration methodDecl = null;
// Might have to retrieve the annotation through BCEL and construct an
// eclipse one for it.
if (stb instanceof BinaryTypeBinding) {
MethodBinding[] mbs = stb.getMethods(decA.getAnnotationMethod().toCharArray());
abits = mbs[0].getAnnotationTagBits(); // ensure resolved
TypeDeclaration typeDecl = ((SourceTypeBinding) mbs[0].declaringClass).scope.referenceContext;
- AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(mbs[0]);
+ methodDecl = typeDecl.declarationOf(mbs[0]);
toAdd = methodDecl.annotations; // this is what to add
toAdd[0] = createAnnotationCopy(toAdd[0]);
if (toAdd[0].resolvedType != null) {
}
sourceType.scope.referenceContext.annotations = newset;
CompilationAndWeavingContext.leavingPhase(tok);
+ if (factory.pushinCollector != null) {
+ factory.pushinCollector.tagAsMunged(sourceType, new CommonPrinter((methodDecl == null ? null : methodDecl.scope))
+ .printAnnotation(toAdd[0]).toString());
+ }
return true;
}
private final LookupEnvironment lookupEnvironment;
private final boolean xSerializableAspects;
private final World world;
+ public PushinCollector pushinCollector;
public Collection finishedTypeMungers = null;
// We can get clashes if we don't treat raw types differently - we end up looking
this.lookupEnvironment = lookupEnvironment;
this.buildManager = buildManager;
this.world = buildManager.getWorld();
+ this.pushinCollector = PushinCollector.createInstance(this.world);
this.xSerializableAspects = buildManager.buildConfig.isXserializableAspects();
}
this.lookupEnvironment = lookupEnvironment;
this.world = world;
this.xSerializableAspects = xSer;
+ this.pushinCollector = PushinCollector.createInstance(this.world);
this.buildManager = null;
}
public class EclipseTypeMunger extends ConcreteTypeMunger {
private ResolvedType targetTypeX;
// protected ReferenceBinding targetBinding = null;
- private AbstractMethodDeclaration sourceMethod;
+ public AbstractMethodDeclaration sourceMethod;
private EclipseFactory world;
private ISourceLocation sourceLocation;
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2010 Contributors
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement - SpringSource
+ * ******************************************************************/
+package org.aspectj.ajdt.internal.compiler.lookup;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.aspectj.ajdt.internal.compiler.IOutputClassFileNameProvider;
+import org.aspectj.asm.internal.CharOperation;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.ExactTypePattern;
+import org.aspectj.weaver.patterns.TypePattern;
+
+/**
+ * Collects up information about the application of ITDs and relevant declares - it can then output source code as if those ITDs had
+ * been pushed in. Supports the simulated push-in of:
+ * <ul>
+ * <li>declare at_type
+ * <li>itd method
+ * <li>itd field
+ * <li>itd ctor
+ * <li>declare parents
+ * </ul>
+ *
+ * @author Andy Clement
+ * @since 1.6.9
+ */
+public class PushinCollector {
+
+ private final static String OPTION_SUFFIX = "suffix";
+ private final static String OPTION_DIR = "dir";
+ private final static String OPTION_PKGDIRS = "packageDirs";
+ private final static String OPTION_DEBUG = "debug";
+ private final static String OPTION_LINENUMS = "lineNums";
+
+ private World world;
+ private boolean debug = false;
+ private IOutputClassFileNameProvider outputFileNameProvider;
+ private String specifiedOutputDirectory;
+ private boolean includePackageDirs;
+ private boolean includeLineNumberComments;
+ private String suffix;
+
+ // This first collection stores the 'text' for the declarations.
+ private Map<AbstractMethodDeclaration, RepresentationAndLocation> codeRepresentation = new HashMap<AbstractMethodDeclaration, RepresentationAndLocation>();
+
+ // This stores the new annotations
+ private Map<SourceTypeBinding, List<String>> additionalAnnotations = new HashMap<SourceTypeBinding, List<String>>();
+
+ // This stores the new parents
+ private Map<SourceTypeBinding, List<ExactTypePattern>> additionalParents = new HashMap<SourceTypeBinding, List<ExactTypePattern>>();
+
+ // This indicates which types are affected by which intertype declarations
+ private Map<SourceTypeBinding, List<AbstractMethodDeclaration>> newDeclarations = new HashMap<SourceTypeBinding, List<AbstractMethodDeclaration>>();
+
+ private PushinCollector(World world, Properties configuration) {
+ this.world = world;
+
+ // Configure the instance based on the input properties
+ specifiedOutputDirectory = configuration.getProperty(OPTION_DIR);
+ includePackageDirs = configuration.getProperty(OPTION_PKGDIRS, "true").equalsIgnoreCase("true");
+ includeLineNumberComments = configuration.getProperty(OPTION_LINENUMS, "false").equalsIgnoreCase("true");
+ debug = configuration.getProperty(OPTION_DEBUG, "false").equalsIgnoreCase("true");
+ String specifiedSuffix = configuration.getProperty(OPTION_SUFFIX, "pushedin");
+ if (specifiedSuffix.length() > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(".").append(specifiedSuffix);
+ suffix = sb.toString();
+ } else {
+ suffix = "";
+ }
+ if (debug) {
+ System.out.println("Configured to create pushin side files:" + configuration);
+ }
+
+ }
+
+ private String getName(CompilationUnitDeclaration cud) {
+ if (cud == null) {
+ return "UNKNOWN";
+ }
+ if (cud.scope == null) {
+ return "UNKNOWN";
+ }
+ if (cud.scope.referenceContext == null) {
+ return "UNKNOWN";
+ }
+ return new String(cud.scope.referenceContext.getFileName());
+ }
+
+ /**
+ * @return true if the type is affected by something (itd/declare anno/declare parent)
+ */
+ private boolean hasChanged(SourceTypeBinding stb) {
+ return newDeclarations.get(stb) != null || additionalParents.get(stb) != null || additionalAnnotations.get(stb) != null;
+ }
+
+ /**
+ * Produce the modified source that looks like the itds and declares have been applied.
+ */
+ public void dump(CompilationUnitDeclaration compilationUnitDeclaration, String outputFileLocation) {
+ if (compilationUnitDeclaration.scope.topLevelTypes == null || compilationUnitDeclaration.scope.topLevelTypes.length == 0) {
+ return;
+ }
+ SourceTypeBinding[] types = compilationUnitDeclaration.scope.topLevelTypes;
+ if (types == null || types.length == 0) {
+ return;
+ }
+
+ // Process all types working from end to start as whatever we do (insert-wise) will affect locations later in the file
+ StringBuffer sourceContents = new StringBuffer();
+ // put the whole original file in the buffer
+ sourceContents.append(compilationUnitDeclaration.compilationResult.compilationUnit.getContents());
+ for (int t = types.length - 1; t >= 0; t--) {
+ SourceTypeBinding sourceTypeBinding = compilationUnitDeclaration.scope.topLevelTypes[t];
+ if (!hasChanged(sourceTypeBinding)) {
+ if (debug) {
+ System.out.println(getName(compilationUnitDeclaration) + " has nothing applied");
+ }
+ continue;
+ }
+
+ int bodyEnd = sourceTypeBinding.scope.referenceContext.bodyEnd; // last '}' of the type
+ List<AbstractMethodDeclaration> declarations = newDeclarations.get(sourceTypeBinding);
+ if (declarations != null) {
+ for (AbstractMethodDeclaration md : declarations) {
+ RepresentationAndLocation ral = codeRepresentation.get(md);
+ if (ral != null) {
+ String s = ral.textualRepresentation;
+ sourceContents.insert(bodyEnd, "\n" + s + "\n");
+ if (includeLineNumberComments && ral.linenumber != -1) {
+ sourceContents.insert(bodyEnd, "\n // " + ral.linenumber);
+ }
+ }
+ }
+ }
+
+ // fix up declare parents - may need to attach them to existing ones
+ TypeReference sr = sourceTypeBinding.scope.referenceContext.superclass;
+ TypeReference[] trs = sourceTypeBinding.scope.referenceContext.superInterfaces;
+ List<ExactTypePattern> newParents = additionalParents.get(sourceTypeBinding);
+ StringBuffer extendsString = new StringBuffer();
+ StringBuffer implementsString = new StringBuffer();
+ if (newParents != null && newParents.size() > 0) {
+ for (ExactTypePattern newParent : newParents) {
+ ResolvedType newParentType = newParent.getExactType().resolve(world);
+ if (newParentType.isInterface()) {
+ if (implementsString.length() > 0) {
+ implementsString.append(",");
+ }
+ implementsString.append(newParentType.getName());
+ } else {
+ extendsString.append(newParentType.getName());
+ }
+ }
+ if (trs == null && sr == null) {
+ // nothing after the class declaration, let's insert what we need to
+ // Find the position just before the type opening '{'
+ int beforeOpeningCurly = sourceTypeBinding.scope.referenceContext.bodyStart - 1;
+ if (implementsString.length() != 0) {
+ implementsString.insert(0, "implements ");
+ implementsString.append(" ");
+ sourceContents.insert(beforeOpeningCurly, implementsString);
+ }
+ if (extendsString.length() != 0) {
+ extendsString.insert(0, "extends ");
+ extendsString.append(" ");
+ sourceContents.insert(beforeOpeningCurly, extendsString);
+ }
+ }
+ }
+ List<String> annos = additionalAnnotations.get(sourceTypeBinding);
+ if (annos != null && annos.size() > 0) {
+ for (String anno : annos) {
+ sourceContents.insert(sourceTypeBinding.scope.referenceContext.declarationSourceStart, anno + " ");
+ }
+ }
+ }
+ try {
+ if (debug) {
+ System.out.println("Pushed in output file being written to " + outputFileLocation);
+ System.out.println(sourceContents);
+ }
+ FileWriter fos = new FileWriter(new File(outputFileLocation));
+ fos.write(sourceContents.toString());
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Encapsulates a text representation (source code) for a member and the line where it was declared.
+ */
+ private static class RepresentationAndLocation {
+
+ String textualRepresentation;
+ int linenumber;
+
+ public RepresentationAndLocation(String textualRepresentation, int linenumber) {
+ this.textualRepresentation = textualRepresentation;
+ this.linenumber = linenumber;
+ }
+ }
+
+ public void recordInterTypeMethodDeclarationCode(AbstractMethodDeclaration md, String s, int line) {
+ codeRepresentation.put(md, new RepresentationAndLocation(s, line));
+ }
+
+ public void recordInterTypeFieldDeclarationCode(AbstractMethodDeclaration md, String s, int line) {
+ codeRepresentation.put(md, new RepresentationAndLocation(s, line));
+ }
+
+ public void recordInterTypeConstructorDeclarationCode(AbstractMethodDeclaration md, String s, int line) {
+ codeRepresentation.put(md, new RepresentationAndLocation(s, line));
+ }
+
+ // public void recordDeclareAnnotationDeclarationCode(AbstractMethodDeclaration md, String value) {
+ // codeRepresentation.put(md, new RepresentationAndLocation(value, -1));
+ // }
+
+ public void tagAsMunged(SourceTypeBinding sourceType, AbstractMethodDeclaration sourceMethod) {
+ if (sourceMethod == null) {
+ // seen when an ITD field is made onto an interface. It matches, but the sourceMethod is null.
+ // can be null for binary weave (there is no source method)
+ return;
+ }
+ List<AbstractMethodDeclaration> amds = newDeclarations.get(sourceType);
+ if (amds == null) {
+ amds = new ArrayList<AbstractMethodDeclaration>();
+ newDeclarations.put(sourceType, amds);
+ }
+ amds.add(sourceMethod);
+ }
+
+ public void tagAsMunged(SourceTypeBinding sourceType, String annotationString) {
+ List<String> annos = additionalAnnotations.get(sourceType);
+ if (annos == null) {
+ annos = new ArrayList<String>();
+ additionalAnnotations.put(sourceType, annos);
+ }
+ annos.add(annotationString);
+ }
+
+ public void dump(CompilationUnitDeclaration unit) {
+ String outputFile = getOutputFileFor(unit);
+ if (debug) {
+ System.out
+ .println("Output location is " + outputFile + " for " + new String(unit.scope.referenceContext.getFileName()));
+ }
+ dump(unit, outputFile);
+ }
+
+ private String getOutputFileFor(CompilationUnitDeclaration unit) {
+ StringBuffer sb = new StringBuffer();
+
+ // Create the directory portion of the output location
+ if (specifiedOutputDirectory != null) {
+ sb.append(specifiedOutputDirectory).append(File.separator);
+ } else {
+ String sss = outputFileNameProvider.getOutputClassFileName("A".toCharArray(), unit.compilationResult);
+ sb.append(sss, 0, sss.length() - 7);
+ }
+
+ // Create the subdirectory structure matching the package declaration
+ if (includePackageDirs) {
+ char[][] packageName = unit.compilationResult.packageName;
+ if (packageName != null) {
+ sb.append(CharOperation.concatWith(unit.compilationResult.packageName, File.separatorChar));
+ sb.append(File.separator);
+ }
+ }
+
+ new File(sb.toString()).mkdirs();
+
+ // Create the filename portion
+ String filename = new String(unit.getFileName()); // gives 'n:\A.java'
+ int index = filename.lastIndexOf('/');
+ int index2 = filename.lastIndexOf('\\');
+ if (index > index2) {
+ sb.append(filename.substring(index + 1));
+ } else if (index2 > index) {
+ sb.append(filename.substring(index2 + 1));
+ } else {
+ sb.append(filename);
+ }
+
+ // Add the suffix (may be an empty string)
+ sb.append(suffix);
+ return sb.toString();
+ }
+
+ public void tagAsMunged(SourceTypeBinding sourceType, TypePattern typePattern) {
+ if (typePattern instanceof ExactTypePattern) {
+ List<ExactTypePattern> annos = additionalParents.get(sourceType);
+ if (annos == null) {
+ annos = new ArrayList<ExactTypePattern>();
+ additionalParents.put(sourceType, annos);
+ }
+ annos.add((ExactTypePattern) typePattern);
+ }
+ }
+
+ /**
+ * Checks if the aspectj.pushin property is set - this is the main condition for triggering the creation of pushed-in source
+ * files. If not set just to 'true', the value of the property is processed as configuration. Configurable options are:
+ * <ul>
+ * <li>dir=XXXX - to set the output directory for the pushed in files
+ * <li>suffix=XXX - to set the suffix, can be blank to get just '.java'
+ * </ul>
+ */
+ public static PushinCollector createInstance(World world) {
+ try {
+ String property = System.getProperty("aspectj.pushin");
+ if (property == null) {
+ return null;
+ }
+ Properties configuration = new Properties();
+ StringTokenizer tokenizer = new StringTokenizer(property, ",");
+ while (tokenizer.hasMoreElements()) {
+ String token = tokenizer.nextToken();
+ // Simplest thing to do is turn it on 'aspectj.pushin=true'
+ if (token.equalsIgnoreCase("true")) {
+ continue;
+ }
+ int positionOfEquals = token.indexOf("=");
+ if (positionOfEquals != -1) {
+ // it is an option
+ String optionName = token.substring(0, positionOfEquals);
+ String optionValue = token.substring(positionOfEquals + 1);
+ configuration.put(optionName, optionValue);
+ } else {
+ // it is a flag
+ configuration.put(token, "true");
+ }
+ }
+ return new PushinCollector(world, configuration);
+ } catch (Exception e) {
+ // unable to read system properties...
+ }
+ return null;
+ }
+
+ public void setOutputFileNameProvider(IOutputClassFileNameProvider outputFileNameProvider) {
+ this.outputFileNameProvider = outputFileNameProvider;
+ }
+}