All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.ajdt.internal.core.builder.AsmHierarchyBuilder Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/* *******************************************************************
 * 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
 *     Mik Kersten	revisions, added additional relationships
 *     Alexandre Vasseur        support for @AJ style
 * ******************************************************************/

package org.aspectj.ajdt.internal.core.builder;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import java.util.Stack;
import java.util.StringTokenizer;

import org.aspectj.ajdt.internal.compiler.CompilationResultDestinationManager;
import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.asm.AsmManager;
import org.aspectj.asm.IProgramElement;
import org.aspectj.asm.internal.CharOperation;
import org.aspectj.asm.internal.ProgramElement;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.SourceLocation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
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.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Literal;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.OperatorExpression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Reference;
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.lookup.BlockScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.util.Util;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.AndPointcut;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.patterns.DeclareParents;
import org.aspectj.weaver.patterns.OrPointcut;
import org.aspectj.weaver.patterns.Pointcut;
import org.aspectj.weaver.patterns.ReferencePointcut;
import org.aspectj.weaver.patterns.TypePatternList;

/**
 * At each iteration of processCompilationUnit the declarations for a particular compilation unit are added to the
 * hierarchy passed as a a parameter.
 * 

* Clients who extend this class need to ensure that they do not override any of the existing behavior. If they do, the structure * model will not be built properly and tools such as IDE structure views and ajdoc will fail. *

* Note: this class is not considered public API and the overridable methods are subject to change. * * @author Mik Kersten */ public class AsmHierarchyBuilder extends ASTVisitor { protected AsmElementFormatter formatter = new AsmElementFormatter(); // pr148027 - stop generating uses pointcut/pointcut used by relationship // until we do it in the same way as other relationships. // public static boolean shouldAddUsesPointcut = false; /** * Reset for every compilation unit. */ protected AjBuildConfig buildConfig; /** * Reset for every compilation unit. */ protected Stack stack; protected ImportReference packageDecl = null; /** * Reset for every compilation unit. */ private CompilationResult currCompilationResult; private String filename; int[] lineseps; /** * * @param cuDeclaration * @param buildConfig * @param structureModel * hiearchy to add this unit's declarations to */ public void buildStructureForCompilationUnit(CompilationUnitDeclaration cuDeclaration, AsmManager structureModel, AjBuildConfig buildConfig) { currCompilationResult = cuDeclaration.compilationResult(); filename = new String(currCompilationResult.fileName); lineseps = currCompilationResult.lineSeparatorPositions; LangUtil.throwIaxIfNull(currCompilationResult, "result"); stack = new Stack<>(); packageDecl = null; this.buildConfig = buildConfig; internalBuild(cuDeclaration, structureModel); this.buildConfig = null; // clear reference since this structure is // anchored in static currCompilationResult = null; stack.clear(); // throw new RuntimeException("not implemented"); } private void internalBuild(CompilationUnitDeclaration unit, AsmManager structureModel) { LangUtil.throwIaxIfNull(structureModel, "structureModel"); try { activeStructureModel = structureModel; // if (!currCompilationResult.equals(unit.compilationResult())) { // throw new IllegalArgumentException("invalid unit: " + unit); // } // ---- summary // add unit to package (or root if no package), // first removing any duplicate (XXX? removes children if 3 classes in // same file?) // push the node on the stack // and traverse // -- create node to add final File file = new File(new String(unit.getFileName())); final IProgramElement cuNode; { // AMC - use the source start and end from the compilation unit decl int startLine = getStartLine(unit); int endLine = getEndLine(unit); SourceLocation sourceLocation = new SourceLocation(file, startLine, endLine); sourceLocation.setOffset(unit.sourceStart); cuNode = new ProgramElement(structureModel, new String(file.getName()), IProgramElement.Kind.FILE_JAVA, sourceLocation, 0, null, null); } // container for import declarations - this may move to position 1 in the child list, if there // is a package declaration cuNode.addChild(new ProgramElement(structureModel, "", IProgramElement.Kind.IMPORT_REFERENCE, null, 0, null, null)); final IProgramElement addToNode = genAddToNode(file, unit, structureModel); // -- remove duplicates before adding (XXX use them instead?) if (addToNode != null && addToNode.getChildren() != null) { for (ListIterator itt = addToNode.getChildren().listIterator(); itt.hasNext();) { IProgramElement child = itt.next(); ISourceLocation childLoc = child.getSourceLocation(); if (null == childLoc) { // XXX ok, packages have null source locations // signal others? } else if (childLoc.getSourceFile().equals(file)) { itt.remove(); } } } // -- add and traverse addToNode.addChild(cuNode); stack.push(cuNode); unit.traverse(this, unit.scope); // -- update file map (XXX do this before traversal?) try { structureModel.getHierarchy().addToFileMap(file.getCanonicalPath(), cuNode); } catch (IOException e) { System.err.println("IOException " + e.getMessage() + " creating path for " + file); // XXX signal IOException when canonicalizing file path } } finally { activeStructureModel = null; } } private AsmManager activeStructureModel = null; private IProgramElement findOrCreateChildSourceFolder(String sourceFolder, AsmManager structureModel) { IProgramElement root = structureModel.getHierarchy().getRoot(); // Check if already there IProgramElement sourceFolderNode = null; List kids = root.getChildren(); for (IProgramElement child : kids) { if (child.getKind() == IProgramElement.Kind.SOURCE_FOLDER && child.getName().equals(sourceFolder)) { sourceFolderNode = child; break; } } if (sourceFolderNode == null) { sourceFolderNode = new ProgramElement(structureModel, sourceFolder, IProgramElement.Kind.SOURCE_FOLDER, new ArrayList<>()); root.addChild(sourceFolderNode); } return sourceFolderNode; } /** * Get/create the node (package or root) to add to. */ private IProgramElement genAddToNode(File sourceFile, CompilationUnitDeclaration unit, AsmManager structureModel) { final IProgramElement addToNode; { CompilationResultDestinationManager manager = buildConfig.getCompilationResultDestinationManager(); String sourceFolder = (manager == null ? null : manager.getSourceFolderForFile(sourceFile)); ImportReference unitPackage = unit.currentPackage; // if (null == unitPackage) { // // Is there a sourceFolder to stick in? // if (sourceFolder == null) { // addToNode = structureModel.getRoot(); // } else { // addToNode = findOrCreateChildSourceFolder(sourceFolder, structureModel); // } // } else { IProgramElement rootForSource = structureModel.getHierarchy().getRoot(); if (sourceFolder != null) { rootForSource = findOrCreateChildSourceFolder(sourceFolder, structureModel); } String pkgName; if (unitPackage == null) { pkgName = ""; } else { StringBuilder nameBuffer = new StringBuilder(); final char[][] importName = unitPackage.getImportName(); final int last = importName.length - 1; for (int i = 0; i < importName.length; i++) { nameBuffer.append(new String(importName[i])); if (i < last) { nameBuffer.append('.'); } } pkgName = nameBuffer.toString(); } IProgramElement pkgNode = null; if (structureModel != null && structureModel.getHierarchy().getRoot() != null && rootForSource.getChildren() != null) { for (IProgramElement currNode : rootForSource.getChildren()) { if (pkgName.equals(currNode.getName())) { pkgNode = currNode; break; } } } if (pkgNode == null) { // note packages themselves have no source location pkgNode = new ProgramElement(activeStructureModel, pkgName, IProgramElement.Kind.PACKAGE, new ArrayList<>()); rootForSource.addChild(pkgNode); } addToNode = pkgNode; // } } return addToNode; } public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) { String name = new String(typeDeclaration.name); IProgramElement.Kind kind = IProgramElement.Kind.CLASS; if (typeDeclaration instanceof AspectDeclaration) { kind = IProgramElement.Kind.ASPECT; } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.INTERFACE_DECL) { kind = IProgramElement.Kind.INTERFACE; } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) { kind = IProgramElement.Kind.ENUM; } else if (TypeDeclaration.kind(typeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) { kind = IProgramElement.Kind.ANNOTATION; } boolean isAnnotationStyleAspect = false; // @AJ support if (typeDeclaration.annotations != null) { for (int i = 0; i < typeDeclaration.annotations.length; i++) { Annotation annotation = typeDeclaration.annotations[i]; if (Arrays.equals(annotation.type.getTypeBindingPublic(scope).signature(), "Lorg/aspectj/lang/annotation/Aspect;".toCharArray())) { kind = IProgramElement.Kind.ASPECT; if (!(typeDeclaration instanceof AspectDeclaration)) { isAnnotationStyleAspect = true; } } else if (annotation.resolvedType != null) { // Fix for the case where in a privileged aspect a parent declaration : // declare parents: (@A C+) implements (B); // is causing the resolvedType to be null when it shouldn't // for the aspect and privileged annotation of that aspect. // Creating the char[][] needed for ImportReference String[] temp = (new String(annotation.resolvedType.constantPoolName())).split("/"); if (temp.length > 1) { char[][] path = new char[temp.length][]; for (int k = 0; k < temp.length; k++) { path[k] = temp[k].toCharArray(); } // Create the ImportReference needed to add a // ProgramElement ImportReference importRef = new ImportReference(path, new long[] { 0 }, false, 0); IProgramElement ceNode = new ProgramElement(activeStructureModel, importRef.toString(), IProgramElement.Kind.IMPORT_REFERENCE, makeLocation(importRef), 0, null, null); ceNode.setSourceSignature(genSourceSignature(importRef)); // Add Element to Imports of Current Class ProgramElement imports = getImportReferencesRoot();// (ProgramElement) ((IProgramElement) // stack.peek()).getChildren().get(0); imports.addChild(0, ceNode); } } } } int typeModifiers = typeDeclaration.modifiers; if (typeDeclaration instanceof AspectDeclaration) { typeModifiers = ((AspectDeclaration) typeDeclaration).getDeclaredModifiers(); } IProgramElement peNode = new ProgramElement(activeStructureModel, name, kind, makeLocation(typeDeclaration), typeModifiers, null, null); peNode.setSourceSignature(genSourceSignature(typeDeclaration)); peNode.setFormalComment(generateJavadocComment(typeDeclaration)); peNode.setAnnotationStyleDeclaration(isAnnotationStyleAspect); stack.peek().addChild(peNode); stack.push(peNode); return true; } public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) { // Is there a package declaration to insert into the model? if (packageDecl != null) { int dotIndex = packageDecl.toString().lastIndexOf('.'); String packageString = packageDecl.toString(); ProgramElement packageDeclaration = new ProgramElement(activeStructureModel, packageString, IProgramElement.Kind.PACKAGE_DECLARATION, makeLocation(packageDecl), 0, null, null); StringBuilder packageSourceDeclaration = new StringBuilder(); packageSourceDeclaration.append("package "); packageSourceDeclaration.append(packageString); packageSourceDeclaration.append(";"); packageDeclaration.setSourceSignature(packageSourceDeclaration.toString()); stack.pop(); ProgramElement containingTypeElement = (ProgramElement) stack.peek(); containingTypeElement.addChild(0, packageDeclaration); packageDecl = null; } else { stack.pop(); } } // ??? share impl with visit(TypeDeclaration, ..) ? public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) { String name = new String(memberTypeDeclaration.name); IProgramElement.Kind kind = IProgramElement.Kind.CLASS; int typeDeclarationKind = TypeDeclaration.kind(memberTypeDeclaration.modifiers); if (memberTypeDeclaration instanceof AspectDeclaration) { kind = IProgramElement.Kind.ASPECT; } else if (typeDeclarationKind == TypeDeclaration.INTERFACE_DECL) { kind = IProgramElement.Kind.INTERFACE; } else if (typeDeclarationKind == TypeDeclaration.ENUM_DECL) { kind = IProgramElement.Kind.ENUM; } else if (typeDeclarationKind == TypeDeclaration.ANNOTATION_TYPE_DECL) { kind = IProgramElement.Kind.ANNOTATION; } boolean isAnnotationStyleAspect = false; // @AJ support if (memberTypeDeclaration.annotations != null) { for (int i = 0; i < memberTypeDeclaration.annotations.length; i++) { Annotation annotation = memberTypeDeclaration.annotations[i]; if (Arrays.equals(annotation.type.getTypeBindingPublic(scope).signature(), "Lorg/aspectj/lang/annotation/Aspect;".toCharArray())) { kind = IProgramElement.Kind.ASPECT; if (!(memberTypeDeclaration instanceof AspectDeclaration)) { isAnnotationStyleAspect = true; } } } } int typeModifiers = memberTypeDeclaration.modifiers; if (memberTypeDeclaration instanceof AspectDeclaration) { typeModifiers = ((AspectDeclaration) memberTypeDeclaration).getDeclaredModifiers(); } IProgramElement peNode = new ProgramElement(activeStructureModel, name, kind, makeLocation(memberTypeDeclaration), typeModifiers, null, null); peNode.setSourceSignature(genSourceSignature(memberTypeDeclaration)); peNode.setFormalComment(generateJavadocComment(memberTypeDeclaration)); peNode.setAnnotationStyleDeclaration(isAnnotationStyleAspect); stack.peek().addChild(peNode); stack.push(peNode); return true; } public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope scope) { stack.pop(); } public boolean visit(TypeDeclaration memberTypeDeclaration, BlockScope scope) { String fullName = ""; if (memberTypeDeclaration.allocation != null && memberTypeDeclaration.allocation.type != null) { // Create a name something like 'new Runnable() {..}' fullName = "new " + memberTypeDeclaration.allocation.type.toString() + "() {..}"; } else if (memberTypeDeclaration.binding != null && memberTypeDeclaration.binding.constantPoolName() != null) { // If we couldn't find a nice name like 'new Runnable() {..}' then // use the number after the $ fullName = new String(memberTypeDeclaration.name); // fullName = new String(memberTypeDeclaration.binding // .constantPoolName()); int dollar = fullName.indexOf('$'); fullName = fullName.substring(dollar + 1); } IProgramElement.Kind kind = IProgramElement.Kind.CLASS; if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.INTERFACE_DECL) { kind = IProgramElement.Kind.INTERFACE; } else if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.ENUM_DECL) { kind = IProgramElement.Kind.ENUM; } else if (TypeDeclaration.kind(memberTypeDeclaration.modifiers) == TypeDeclaration.ANNOTATION_TYPE_DECL) { kind = IProgramElement.Kind.ANNOTATION; } // @AJ support boolean isAnnotationStyleAspect = false; if (memberTypeDeclaration.annotations != null) { for (int i = 0; i < memberTypeDeclaration.annotations.length; i++) { Annotation annotation = memberTypeDeclaration.annotations[i]; if (Arrays.equals(annotation.type.getTypeBindingPublic(scope).signature(), "Lorg/aspectj/lang/annotation/Aspect;".toCharArray())) { kind = IProgramElement.Kind.ASPECT; if (!(memberTypeDeclaration instanceof AspectDeclaration)) { isAnnotationStyleAspect = true; } break; } } } IProgramElement peNode = new ProgramElement(activeStructureModel, fullName, kind, makeLocation(memberTypeDeclaration), memberTypeDeclaration.modifiers, null, null); peNode.setSourceSignature(genSourceSignature(memberTypeDeclaration)); peNode.setFormalComment(generateJavadocComment(memberTypeDeclaration)); peNode.setAnnotationStyleDeclaration(isAnnotationStyleAspect); // if we're something like 'new Runnable(){..}' then set the // bytecodeSignature to be the typename so we can match it later // when creating the structure model if (peNode.getBytecodeSignature() == null && memberTypeDeclaration.binding != null && memberTypeDeclaration.binding.constantPoolName() != null) { StringTokenizer st = new StringTokenizer(new String(memberTypeDeclaration.binding.constantPoolName()), "/"); while (st.hasMoreTokens()) { String s = st.nextToken(); if (!st.hasMoreTokens()) { peNode.setBytecodeSignature(s); } } } IProgramElement ipe = stack.peek(); if (ipe!=null) { // With AspectJ 1.8.9 the type structure must be slightly different as the guard // is required (the null is due to a default constructor). stack.peek().addChild(peNode); } stack.push(peNode); return true; } public void endVisit(TypeDeclaration memberTypeDeclaration, BlockScope scope) { stack.pop(); } private String genSourceSignature(TypeDeclaration typeDeclaration) { StringBuilder output = new StringBuilder(); typeDeclaration.printHeader(0, output); return output.toString(); } // private IProgramElement findEnclosingClass(Stack stack) { // for (int i = stack.size() - 1; i >= 0; i--) { // IProgramElement pe = (IProgramElement) stack.get(i); // if (pe.getKind() == IProgramElement.Kind.CLASS) { // return pe; // } // // } // return (IProgramElement) stack.peek(); // } public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { IProgramElement peNode = null; // For intertype decls, use the modifiers from the original signature, // not the generated method if (methodDeclaration instanceof InterTypeDeclaration) { InterTypeDeclaration itd = (InterTypeDeclaration) methodDeclaration; ResolvedMember sig = itd.getSignature(); peNode = new ProgramElement(activeStructureModel, null, IProgramElement.Kind.ERROR, makeLocation(methodDeclaration), (sig != null ? sig.getModifiers() : 0), null, null); } else { peNode = new ProgramElement(activeStructureModel, null, IProgramElement.Kind.ERROR, makeLocation(methodDeclaration), methodDeclaration.modifiers, null, null); } formatter.genLabelAndKind(methodDeclaration, peNode); // will set the // name genBytecodeInfo(methodDeclaration, peNode); List namedPointcuts = genNamedPointcuts(methodDeclaration); // if (shouldAddUsesPointcut) // addUsesPointcutRelationsForNode(peNode, namedPointcuts, methodDeclaration); if (methodDeclaration instanceof DeclareDeclaration) { DeclareDeclaration dDeclaration = (DeclareDeclaration) methodDeclaration; Declare decl = dDeclaration.declareDecl; if (decl instanceof DeclareParents) { TypePatternList tpl = ((DeclareParents) decl).getParents(); List parents = new ArrayList<>(); for (int i = 0; i < tpl.size(); i++) { parents.add(tpl.get(i).getExactType().getName().replaceAll("\\$", ".")); } peNode.setParentTypes(parents); } if (decl instanceof DeclareAnnotation) { DeclareAnnotation da = (DeclareAnnotation) decl; ResolvedType annotationType = da.getAnnotationType(); if (annotationType == null) { String s = ((DeclareAnnotation) decl).getAnnotationString(); if (s != null && s.length() > 0) { s = s.substring(1); } peNode.setAnnotationType(s); } else { peNode.setAnnotationType(annotationType.getName()); } if (da.isRemover()) { peNode.setAnnotationRemover(true); } } } if (methodDeclaration.returnType != null) { // if we don't make the distinction between ITD fields and other // methods, then we loose the type, for example int, for the field // and instead get "void". if (peNode.getKind().equals(IProgramElement.Kind.INTER_TYPE_FIELD)) { InterTypeFieldDeclaration itfd = (InterTypeFieldDeclaration) methodDeclaration; if (itfd.getRealFieldType() != null) { peNode.setCorrespondingType(new String(itfd.getRealFieldType().readableName())); } else { peNode.setCorrespondingType(null); } // was peNode.setCorrespondingType(methodDeclaration.returnType.toString()); } else { if (methodDeclaration.returnType.resolvedType != null) { peNode.setCorrespondingType(new String(methodDeclaration.returnType.resolvedType.readableName())); } else { peNode.setCorrespondingType(null); } } } else { peNode.setCorrespondingType(null); } peNode.setSourceSignature(genSourceSignature(methodDeclaration)); peNode.setFormalComment(generateJavadocComment(methodDeclaration)); // TODO: add return type test if (peNode.getKind().equals(IProgramElement.Kind.METHOD)) { if ((peNode.getName().charAt(0) == 'm') && (peNode.toLabelString().equals("main(String[])") || peNode.toLabelString() .equals("main(java.lang.String[])")) && peNode.getModifiers().contains(IProgramElement.Modifiers.STATIC) && peNode.getAccessibility().equals(IProgramElement.Accessibility.PUBLIC)) { stack.peek().setRunnable(true); } } stack.push(peNode); return true; } // private void addUsesPointcutRelationsForNode(IProgramElement peNode, List namedPointcuts, MethodDeclaration declaration) { // for (Iterator it = namedPointcuts.iterator(); it.hasNext();) { // ReferencePointcut rp = (ReferencePointcut) it.next(); // ResolvedMember member = getPointcutDeclaration(rp, declaration); // if (member != null) { // IRelationship foreward = AsmManager.getDefault().getRelationshipMap().get(peNode.getHandleIdentifier(), // IRelationship.Kind.USES_POINTCUT, "uses pointcut", false, true); // IProgramElement forwardIPE = AsmManager.getDefault().getHierarchy().findElementForSourceLine( // member.getSourceLocation()); // foreward.addTarget(AsmManager.getDefault().getHandleProvider().createHandleIdentifier(forwardIPE)); // // IRelationship back = AsmManager.getDefault().getRelationshipMap().get( // AsmManager.getDefault().getHandleProvider().createHandleIdentifier(forwardIPE), // IRelationship.Kind.USES_POINTCUT, "pointcut used by", false, true); // back.addTarget(peNode.getHandleIdentifier()); // } // } // } private ResolvedMember getPointcutDeclaration(ReferencePointcut rp, MethodDeclaration declaration) { EclipseFactory factory = ((AjLookupEnvironment) declaration.scope.environment()).factory; World world = factory.getWorld(); UnresolvedType onType = rp.onType; if (onType == null) { if (declaration.binding != null) { Member member = factory.makeResolvedMember(declaration.binding); onType = member.getDeclaringType(); } else { return null; } } ResolvedMember[] members = onType.resolve(world).getDeclaredPointcuts(); if (members != null) { for (ResolvedMember member : members) { if (member.getName().equals(rp.name)) { return member; } } } return null; } /** * @param methodDeclaration * @return all of the named pointcuts referenced by the PCD of this declaration */ private List genNamedPointcuts(MethodDeclaration methodDeclaration) { List pointcuts = new ArrayList<>(); if (methodDeclaration instanceof AdviceDeclaration) { if (((AdviceDeclaration) methodDeclaration).pointcutDesignator != null) { addAllNamed(((AdviceDeclaration) methodDeclaration).pointcutDesignator.getPointcut(), pointcuts); } } else if (methodDeclaration instanceof PointcutDeclaration) { if (((PointcutDeclaration) methodDeclaration).pointcutDesignator != null) { addAllNamed(((PointcutDeclaration) methodDeclaration).pointcutDesignator.getPointcut(), pointcuts); } } return pointcuts; } /** * @param left * @param pointcuts * accumulator for named pointcuts */ private void addAllNamed(Pointcut pointcut, List pointcuts) { if (pointcut == null) { return; } if (pointcut instanceof ReferencePointcut) { ReferencePointcut rp = (ReferencePointcut) pointcut; pointcuts.add(rp); } else if (pointcut instanceof AndPointcut) { AndPointcut ap = (AndPointcut) pointcut; addAllNamed(ap.getLeft(), pointcuts); addAllNamed(ap.getRight(), pointcuts); } else if (pointcut instanceof OrPointcut) { OrPointcut op = (OrPointcut) pointcut; addAllNamed(op.getLeft(), pointcuts); addAllNamed(op.getRight(), pointcuts); } } private String genSourceSignature(MethodDeclaration methodDeclaration) { StringBuilder output = new StringBuilder(); ASTNode.printModifiers(methodDeclaration.modifiers, output); // Append Type Parameters if any TypeParameter types[] = methodDeclaration.typeParameters(); if (types != null && types.length != 0) { output.append("<"); for (int i = 0; i < types.length; i++) { if (i > 0) { output.append(", "); } types[i].printStatement(0, output); } output.append("> "); } String methodName = methodDeclaration.selector==null?"null":new String(methodDeclaration.selector); methodDeclaration.printReturnType(0, output).append(methodName).append('('); if (methodDeclaration.arguments != null) { for (int i = 0; i < methodDeclaration.arguments.length; i++) { if (i > 0) { output.append(", "); //$NON-NLS-1$ } methodDeclaration.arguments[i].print(0, output); } } 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$ } methodDeclaration.thrownExceptions[i].print(0, output); } } return output.toString(); } // protected void genBytecodeInfo(MethodDeclaration methodDeclaration, // IProgramElement peNode) { // if (methodDeclaration.binding != null) { // String memberName = ""; // String memberBytecodeSignature = ""; // try { // EclipseFactory factory = // ((AjLookupEnvironment)methodDeclaration.scope.environment()).factory; // Member member = factory.makeResolvedMember(methodDeclaration.binding); // memberName = member.getName(); // memberBytecodeSignature = member.getSignature(); // } catch (BCException bce) { // bad type name // memberName = ""; // } catch (NullPointerException npe) { // memberName = ""; // } // // peNode.setBytecodeName(memberName); // peNode.setBytecodeSignature(memberBytecodeSignature); // } // ((IProgramElement)stack.peek()).addChild(peNode); // } protected void genBytecodeInfo(MethodDeclaration methodDeclaration, IProgramElement peNode) { if (methodDeclaration.binding != null) { try { EclipseFactory factory = ((AjLookupEnvironment) methodDeclaration.scope.environment()).factory; Member member = factory.makeResolvedMember(methodDeclaration.binding); peNode.setBytecodeName(member.getName()); peNode.setBytecodeSignature(member.getSignature()); } catch (BCException bce) { // bad type name bce.printStackTrace(); } catch (NullPointerException npe) { npe.printStackTrace(); } } stack.peek().addChild(peNode); } public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) { stack.pop(); } public boolean visit(ImportReference importRef, CompilationUnitScope scope) { // 3.3 compiler used to represent the package statement in such a way that toString() would return 'foo.*' for 'package foo;' // 3.7 compiler doesn't create an 'ondemand' import reference so it is purely toString()'d as 'foo' String currPackageImport = importRef.toString(); String stackPackageName = stack.peek().getPackageName(); if (stackPackageName.equals(currPackageImport)) { packageDecl = importRef; } else { ProgramElement peNode = new ProgramElement(activeStructureModel, new String(importRef.toString()), IProgramElement.Kind.IMPORT_REFERENCE, makeLocation(importRef), 0,// could set static here, but for // some reason the info is // private null, null); // set it here instead if (importRef.isStatic()) { peNode.addModifiers(IProgramElement.Modifiers.STATIC); } // create Source signature for import peNode.setSourceSignature(genSourceSignature(importRef)); IProgramElement containingTypeElement = stack.peek(); ProgramElement imports = getImportReferencesRoot(); imports.addChild(0, peNode); stack.push(peNode); } return true; } private ProgramElement getImportReferencesRoot() { IProgramElement element = stack.peek(); boolean hasPackageDeclaration = (element.getChildren().get(0)).getKind().isPackageDeclaration(); return (ProgramElement) element.getChildren().get(hasPackageDeclaration ? 1 : 0); } public void endVisit(ImportReference importRef, CompilationUnitScope scope) { // 3.3 compiler used to represent the package statement in such a way that toString() would return 'foo.*' for 'package foo;' // 3.7 compiler doesn't create an 'ondemand' import reference so it is purely toString()'d as 'foo' String currPackageImport = importRef.toString(); if (!stack.peek().getPackageName().equals(currPackageImport)) { stack.pop(); } } private String genSourceSignature(ImportReference importreference) { StringBuilder output = new StringBuilder(); output.append("import "); ASTNode.printModifiers(importreference.modifiers, output); output.append(importreference); output.append(";"); return output.toString(); } public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { IProgramElement peNode = null; if (fieldDeclaration.type == null) { // The field represents an enum // value peNode = new ProgramElement(activeStructureModel, new String(fieldDeclaration.name), IProgramElement.Kind.ENUM_VALUE, makeLocation(fieldDeclaration), fieldDeclaration.modifiers, null, null); String type = null; boolean isOk = true; if (fieldDeclaration.binding == null) { type="fieldDeclaration_binding_is_null"; System.err.println("DebugFor402832: null fieldDeclaration.binding for "+fieldDeclaration); isOk=false; } else { if (fieldDeclaration.binding.type==null) { System.err.println("DebugFor402832: null fieldDeclaration.binding.type for "+fieldDeclaration); type="fieldDeclaration_binding_type_is_null"; isOk=false; } else { type=fieldDeclaration.binding.type.debugName(); } } if (!isOk) { if (fieldDeclaration.type!=null && fieldDeclaration.type.resolvedType!=null) { type = fieldDeclaration.type.resolvedType.debugName(); System.err.println("DebugFor402832: used secondary route to compute name for "+fieldDeclaration+", set to "+type); isOk=true; } } peNode.setCorrespondingType(type); // peNode.setCorrespondingType(fieldDeclaration.binding.type.debugName()); } else { peNode = new ProgramElement(activeStructureModel, new String(fieldDeclaration.name), IProgramElement.Kind.FIELD, makeLocation(fieldDeclaration), fieldDeclaration.modifiers, null, null); if (fieldDeclaration.type.resolvedType != null) { char[] cs = fieldDeclaration.type.resolvedType.readableName(); // fieldDeclaration.type.resolvedType.genericTypeSignature() peNode.setCorrespondingType(new String(cs)); } else { // peNode.setCorrespondingType(null); peNode.setCorrespondingType(fieldDeclaration.type.toString()); } } peNode.setSourceSignature(genSourceSignature(fieldDeclaration)); peNode.setFormalComment(generateJavadocComment(fieldDeclaration)); // peNode.setBytecodeSignature(new String(fieldDeclaration.binding.type.signature())); stack.peek().addChild(peNode); stack.push(peNode); return true; } public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) { stack.pop(); } /** * Checks if comments should be added to the model before generating. */ protected String generateJavadocComment(ASTNode astNode) { if (buildConfig != null && !buildConfig.isGenerateJavadocsInModelMode()) { return null; } // StringBuffer sb = new StringBuffer(); // !!! specify length? // boolean completed = false; int startIndex = -1; if (astNode instanceof MethodDeclaration) { startIndex = ((MethodDeclaration) astNode).declarationSourceStart; } else if (astNode instanceof FieldDeclaration) { startIndex = ((FieldDeclaration) astNode).declarationSourceStart; } else if (astNode instanceof TypeDeclaration) { startIndex = ((TypeDeclaration) astNode).declarationSourceStart; } else if (astNode instanceof ConstructorDeclaration) { startIndex = ((ConstructorDeclaration) astNode).declarationSourceStart; } if (startIndex == -1) { return null; } else if (currCompilationResult.compilationUnit.getContents()[startIndex] == '/') { char[] comment = CharOperation.subarray(currCompilationResult.compilationUnit.getContents(), startIndex, astNode.sourceStart); while (comment.length > 2) { int star = CharOperation.indexOf('*', comment); if (star == -1) { return null; } // looking for '/**' and not '//' or '//*' if (star != 0 && (comment[star - 1] == '/') && (comment[star + 1] == '*') && (star - 2 < 0 || comment[star - 2] != '/')) { boolean completed = false; StringBuilder sb = new StringBuilder(); for (int i = 0; i < comment.length && !completed; i++) { char curr = comment[i]; if (curr == '/' && sb.length() > 2 && sb.charAt(sb.length() - 1) == '*') { completed = true; // found */ } sb.append(comment[i]); } // The following will remove any non-javadoc comments // preceeding a javadoc comment in this block if (sb.toString().indexOf("/**") != 0) { return sb.toString().substring(sb.toString().indexOf("/**")); } return sb.toString(); } comment = CharOperation.subarray(comment, star + 1, comment.length); } } return null; } /** * */ protected String genSourceSignature(FieldDeclaration fieldDeclaration) { StringBuilder output = new StringBuilder(); if (fieldDeclaration.type == null) { // This is an enum value output.append(fieldDeclaration.name); // the "," or ";" has to be // put on by whatever uses // the sourceSignature return output.toString(); } else { FieldDeclaration.printModifiers(fieldDeclaration.modifiers, output); fieldDeclaration.type.print(0, output).append(' ').append(fieldDeclaration.name); } output.append(" = "); if (fieldDeclaration.initialization != null && (fieldDeclaration.initialization instanceof Literal || fieldDeclaration.initialization instanceof OperatorExpression || fieldDeclaration.initialization instanceof Reference)) { fieldDeclaration.initialization.printExpression(0, output); } else { output.append("null"); } output.append(";\n"); return output.toString(); } // public boolean visit(ImportReference importRef, CompilationUnitScope // scope) { // ProgramElementNode peNode = new ProgramElementNode( // new String(importRef.toString()), // ProgramElementNode.Kind., // makeLocation(importRef), // 0, // "", // new ArrayList()); // ((IProgramElement)stack.peek()).addChild(0, peNode); // stack.push(peNode); // return true; // } // public void endVisit(ImportReference importRef,CompilationUnitScope // scope) { // stack.pop(); // } public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { if ((constructorDeclaration.bits & ASTNode.IsDefaultConstructor) != 0) { stack.push(null); // a little weird but does the job return true; } StringBuilder argumentsSignature = new StringBuilder(); argumentsSignature.append("("); if (constructorDeclaration.arguments != null) { for (int i = 0; i < constructorDeclaration.arguments.length; i++) { argumentsSignature.append(constructorDeclaration.arguments[i].type); if (i + 1 < constructorDeclaration.arguments.length) { argumentsSignature.append(","); } } } argumentsSignature.append(")"); IProgramElement peNode = new ProgramElement(activeStructureModel, new String(constructorDeclaration.selector), IProgramElement.Kind.CONSTRUCTOR, makeLocation(constructorDeclaration), constructorDeclaration.modifiers, null, null); formatter.setParameters(constructorDeclaration, peNode); peNode.setModifiers(constructorDeclaration.modifiers); peNode.setSourceSignature(genSourceSignature(constructorDeclaration)); peNode.setFormalComment(generateJavadocComment(constructorDeclaration)); // Fix to enable us to anchor things from ctor nodes if (constructorDeclaration.binding != null) { String memberName = ""; String memberBytecodeSignature = ""; try { EclipseFactory factory = ((AjLookupEnvironment) constructorDeclaration.scope.environment()).factory; Member member = factory.makeResolvedMember(constructorDeclaration.binding); memberName = member.getName(); memberBytecodeSignature = member.getSignature(); } catch (BCException bce) { // bad type name memberName = ""; } catch (NullPointerException npe) { memberName = ""; } peNode.setBytecodeName(memberName); peNode.setBytecodeSignature(memberBytecodeSignature); } stack.peek().addChild(peNode); stack.push(peNode); return true; } public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { stack.pop(); } private String genSourceSignature(ConstructorDeclaration constructorDeclaration) { StringBuilder output = new StringBuilder(); ASTNode.printModifiers(constructorDeclaration.modifiers, output); // Append Type Parameters if any TypeParameter types[] = constructorDeclaration.typeParameters(); if (types != null && types.length != 0) { output.append("<"); for (int i = 0; i < types.length; i++) { if (i > 0) { output.append(", "); } types[i].printStatement(0, output); } output.append("> "); } output.append(constructorDeclaration.selector).append('('); if (constructorDeclaration.arguments != null) { for (int i = 0; i < constructorDeclaration.arguments.length; i++) { if (i > 0) { output.append(", "); //$NON-NLS-1$ } constructorDeclaration.arguments[i].print(0, output); } } 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$ } constructorDeclaration.thrownExceptions[i].print(0, output); } } return output.toString(); } // public boolean visit(Clinit clinit, ClassScope scope) { // ProgramElementNode peNode = new ProgramElementNode( // "", // ProgramElementNode.Kind.INITIALIZER, // makeLocation(clinit), // clinit.modifiers, // "", // new ArrayList()); // ((IProgramElement)stack.peek()).addChild(peNode); // stack.push(peNode); // return false; // } // public void endVisit(Clinit clinit, ClassScope scope) { // stack.pop(); // } /** * This method works-around an odd traverse implementation on Initializer */ private Initializer inInitializer = null; public boolean visit(Initializer initializer, MethodScope scope) { if (initializer == inInitializer) { return false; } inInitializer = initializer; IProgramElement peNode = new ProgramElement(activeStructureModel, "...", IProgramElement.Kind.INITIALIZER, makeLocation(initializer), initializer.modifiers, null, null); // "", // new ArrayList()); stack.peek().addChild(peNode); stack.push(peNode); initializer.block.traverse(this, scope); stack.pop(); inInitializer = null; return false; } // ??? handle non-existant files protected ISourceLocation makeLocation(ASTNode node) { String fileName = ""; if (filename != null) { fileName = filename; } // AMC - different strategies based on node kind int startLine = getStartLine(node); int endLine = getEndLine(node); SourceLocation loc = null; if (startLine <= endLine) { // found a valid end line for this node... loc = new SourceLocation(new File(fileName), startLine, endLine); loc.setOffset(node.sourceStart); } else { loc = new SourceLocation(new File(fileName), startLine); loc.setOffset(node.sourceStart); } return loc; } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! protected int getStartLine(ASTNode n) { // if ( n instanceof AbstractVariableDeclaration ) return getStartLine( // (AbstractVariableDeclaration)n); // if ( n instanceof AbstractMethodDeclaration ) return getStartLine( // (AbstractMethodDeclaration)n); // if ( n instanceof TypeDeclaration ) return getStartLine( // (TypeDeclaration)n); return Util.getLineNumber(n.sourceStart, lineseps, 0, lineseps.length - 1); // return ProblemHandler.searchLineNumber(lineseps, // currCompilationResult.lineSeparatorPositions, // n.sourceStart); } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! protected int getEndLine(ASTNode n) { if (n instanceof AbstractVariableDeclaration) { return getEndLine((AbstractVariableDeclaration) n); } if (n instanceof AbstractMethodDeclaration) { return getEndLine((AbstractMethodDeclaration) n); } if (n instanceof TypeDeclaration) { return getEndLine((TypeDeclaration) n); } return Util.getLineNumber(n.sourceEnd, lineseps, 0, lineseps.length - 1); // return ProblemHandler.searchLineNumber(lineseps, // currCompilationResult.lineSeparatorPositions, // n.sourceEnd); } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! // private int getStartLine( AbstractVariableDeclaration avd ) { // return ProblemHandler.searchLineNumber( // currCompilationResult.lineSeparatorPositions, // avd.declarationSourceStart); // } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! private int getEndLine(AbstractVariableDeclaration avd) { return Util.getLineNumber(avd.declarationSourceEnd, lineseps, 0, lineseps.length - 1); } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! // private int getStartLine( AbstractMethodDeclaration amd ){ // return ProblemHandler.searchLineNumber( // currCompilationResult.lineSeparatorPositions, // amd.declarationSourceStart); // } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! private int getEndLine(AbstractMethodDeclaration amd) { return Util.getLineNumber(amd.declarationSourceEnd, lineseps, 0, lineseps.length - 1); } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! // private int getStartLine( TypeDeclaration td ){ // return ProblemHandler.searchLineNumber( // currCompilationResult.lineSeparatorPositions, // td.declarationSourceStart); // } // AMC - overloaded set of methods to get start and end lines for // various ASTNode types. They have no common ancestor in the // hierarchy!! private int getEndLine(TypeDeclaration td) { return Util.getLineNumber(td.declarationSourceEnd, lineseps, 0, lineseps.length - 1); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy