/* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). * All rights reserved. * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v 2.0 * which accompanies this distribution and is available at * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt * * Contributors: * PARC initial implementation * ******************************************************************/ package org.aspectj.ajdt.internal.compiler.ast; //import java.util.List; import java.util.Collection; import java.util.Iterator; import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope; import org.aspectj.org.eclipse.jdt.core.Flags; import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; 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.ast.TypeReference; import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser; import org.aspectj.weaver.AjAttribute; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.patterns.Declare; import org.aspectj.weaver.patterns.DeclareAnnotation; import org.aspectj.weaver.patterns.DeclareErrorOrWarning; import org.aspectj.weaver.patterns.DeclareParents; import org.aspectj.weaver.patterns.DeclarePrecedence; import org.aspectj.weaver.patterns.DeclareSoft; import org.aspectj.weaver.patterns.FormalBinding; public class DeclareDeclaration extends AjMethodDeclaration { public Declare declareDecl; /** * Constructor for IntraTypeDeclaration. */ public DeclareDeclaration(CompilationResult result, Declare symbolicDeclare) { super(result); this.declareDecl = symbolicDeclare; if (declareDecl != null) { // AMC added init of declarationSourceXXX fields which are used // in AsmBuilder for processing of MethodDeclaration locations. declarationSourceStart = sourceStart = declareDecl.getStart(); declarationSourceEnd = sourceEnd = declareDecl.getEnd(); } // ??? we might need to set parameters to be empty this.returnType = TypeReference.baseTypeReference(T_void, 0, null); } public void addAtAspectJAnnotations() { Annotation annotation = null; if (declareDecl instanceof DeclareAnnotation) { DeclareAnnotation da = (DeclareAnnotation) declareDecl; String patternString = da.getPatternAsString(); String annString = da.getAnnotationString(); String kind = da.getKind().toString(); annotation = AtAspectJAnnotationFactory.createDeclareAnnAnnotation(patternString, annString, kind, declarationSourceStart); } else if (declareDecl instanceof DeclareErrorOrWarning) { DeclareErrorOrWarning dd = (DeclareErrorOrWarning) declareDecl; annotation = AtAspectJAnnotationFactory.createDeclareErrorOrWarningAnnotation(dd.getPointcut().toString(), dd.getMessage(), dd.isError(), declarationSourceStart); } else if (declareDecl instanceof DeclareParents) { DeclareParents dp = (DeclareParents) declareDecl; String childPattern = dp.getChild().toString(); Collection parentPatterns = dp.getParents().getExactTypes(); StringBuilder parents = new StringBuilder(); for (Iterator iter = parentPatterns.iterator(); iter.hasNext();) { UnresolvedType urt = iter.next(); parents.append(urt.getName()); if (iter.hasNext()) { parents.append(", "); } } annotation = AtAspectJAnnotationFactory.createDeclareParentsAnnotation(childPattern, parents.toString(), dp.isExtends(), declarationSourceStart); } else if (declareDecl instanceof DeclarePrecedence) { DeclarePrecedence dp = (DeclarePrecedence) declareDecl; String precedenceList = dp.getPatterns().toString(); annotation = AtAspectJAnnotationFactory.createDeclarePrecedenceAnnotation(precedenceList, declarationSourceStart); } else if (declareDecl instanceof DeclareSoft) { DeclareSoft ds = (DeclareSoft) declareDecl; annotation = AtAspectJAnnotationFactory.createDeclareSoftAnnotation(ds.getPointcut().toString(), ds.getException() .getExactType().getName(), declarationSourceStart); } if (annotation != null) { AtAspectJAnnotationFactory.addAnnotation(this, annotation, this.scope); } } /** * A declare declaration exists in a classfile only as an attibute on the class. Unlike advice and inter-type declarations, it * has no corresponding method. **AMC** changed the above policy in the case of declare annotation, which uses a corresponding * method as the anchor for the declared annotation */ public void generateCode(ClassScope classScope, ClassFile classFile) { if (shouldBeSynthetic()) { this.binding.modifiers |= Flags.AccSynthetic; } classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.DeclareAttribute(declareDecl))); if (shouldDelegateCodeGeneration()) { super.generateCode(classScope, classFile); } return; } protected boolean shouldDelegateCodeGeneration() { return true; } protected boolean shouldBeSynthetic() { return true; } public void parseStatements(Parser parser, CompilationUnitDeclaration unit) { // do nothing } public void resolveStatements(ClassScope upperScope) { // do nothing } // public boolean finishResolveTypes(SourceTypeBinding sourceTypeBinding) { // // there's nothing for our super to resolve usefully // //if (!super.finishResolveTypes(sourceTypeBinding)) return false; // // if (declare == null) return true; // // // // EclipseScope scope = new EclipseScope(new FormalBinding[0], this.scope); // // // // declare.resolve(scope); // // return true; // } public Declare build(ClassScope classScope) { if (declareDecl == null) { return null; } EclipseScope scope = new EclipseScope(FormalBinding.NONE, classScope); declareDecl.resolve(scope); return declareDecl; } public StringBuffer print(int tab, StringBuffer output) { printIndent(tab, output); if (declareDecl == null) { output.append(""); } else { output.append(declareDecl.toString()); } return output; } /** * We need the ajc$declare method that is created to represent this declare to be marked as synthetic */ protected int generateInfoAttributes(ClassFile classFile) { return super.generateInfoAttributes(classFile, true); } public void postParse(TypeDeclaration typeDec) { super.postParse(typeDec); int declareSequenceNumberInType = ((AspectDeclaration) typeDec).declareCounter++; // FIXME asc the name should perhaps include the hashcode of the pattern (type/sig) for binary compatibility reasons! StringBuilder sb = new StringBuilder(); sb.append("ajc$declare"); // Declares can choose to provide a piece of the name - to enable // them to be easily distinguised at weave time (e.g. see declare annotation) if (declareDecl != null) { String suffix = declareDecl.getNameSuffix(); if (suffix.length() != 0) { sb.append("_"); sb.append(suffix); } } sb.append("_"); sb.append(declareSequenceNumberInType); this.selector = sb.toString().toCharArray(); } }