Logo Search packages:      
Sourcecode: aspectj version File versions

AsmHierarchyBuilder.java

/* *******************************************************************
 * 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 v1.0
 * which accompanies this distribution and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * 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.Iterator;
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.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.AndPointcut;
import org.aspectj.weaver.patterns.Declare;
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 <CODE>processCompilationUnit</CODE> the declarations for a particular compilation unit are added to the
 * hierarchy passed as a a parameter.
 * <p>
 * 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.
 * <p>
 * <b>Note:</b> this class is not considered public API and the overridable methods are subject to change.
 * 
 * @author Mik Kersten
 */
00089 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.
       */
00098       protected AjBuildConfig buildConfig;

      /**
       * Reset for every compilation unit.
       */
00103       protected Stack stack;

      protected ImportReference packageDecl = null;

      /**
       * Reset for every compilation unit.
       */
00110       private CompilationResult currCompilationResult;
      private String filename;
      int[] lineseps;

      /**
       * 
       * @param cuDeclaration
       * @param buildConfig
       * @param structureModel hiearchy to add this unit's declarations to
       */
00120       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 = (IProgramElement) 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 (Iterator iterator = kids.iterator(); iterator.hasNext();) {
                  IProgramElement child = (IProgramElement) iterator.next();
                  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.
       */
00227       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 {
                        StringBuffer nameBuffer = new StringBuffer();
                        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 (Iterator it = rootForSource.getChildren().iterator(); it.hasNext();) {
                              IProgramElement currNode = (IProgramElement) it.next();
                              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);

            ((IProgramElement) 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();
                  if (dotIndex != -1) {
                        packageString = packageDecl.toString().substring(0, dotIndex);
                  }
                  ProgramElement packageDeclaration = new ProgramElement(activeStructureModel, packageString,
                              IProgramElement.Kind.PACKAGE_DECLARATION, makeLocation(packageDecl),0,null,null);
                  StringBuffer packageSourceDeclaration = new StringBuffer();
                  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);

            ((IProgramElement) 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 = "<undefined>";
            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) stack.peek()).addChild(peNode);
            stack.push(peNode);
            return true;
      }

      public void endVisit(TypeDeclaration memberTypeDeclaration, BlockScope scope) {
            stack.pop();
      }

      private String genSourceSignature(TypeDeclaration typeDeclaration) {
            StringBuffer output = new StringBuffer();
            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 (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)) {
                        ((IProgramElement) 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 (int i = 0; i < members.length; i++) {
                        if (members[i].getName().equals(rp.name)) {
                              return members[i];
                        }
                  }
            }
            return null;
      }

      /**
       * @param methodDeclaration
       * @return all of the named pointcuts referenced by the PCD of this declaration
       */
00634       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
       */
00650       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) {
            StringBuffer output = new StringBuffer();
            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("> ");
            }

            methodDeclaration.printReturnType(0, output).append(methodDeclaration.selector).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 = "<undefined>";
      // } catch (NullPointerException npe) {
      // memberName = "<undefined>";
      // }
      //                
      // 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();
                  }
            }
            ((IProgramElement) stack.peek()).addChild(peNode);
      }

      public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
            stack.pop();
      }

      public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
            int dotIndex = importRef.toString().lastIndexOf('.');
            String currPackageImport = "";
            if (dotIndex != -1) {
                  currPackageImport = importRef.toString().substring(0, dotIndex);
            }
            if (((IProgramElement) stack.peek()).getPackageName().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 = (IProgramElement)stack.peek();
                  ProgramElement imports = getImportReferencesRoot();
                  imports.addChild(0, peNode);
                  stack.push(peNode);
            }
            return true;
      }
      
      private ProgramElement getImportReferencesRoot() {
            IProgramElement element = (IProgramElement)stack.peek();
            boolean hasPackageDeclaration = ((IProgramElement)element.getChildren().get(0)).getKind().isPackageDeclaration();
            return (ProgramElement)element.getChildren().get(hasPackageDeclaration?1:0);
      }

      public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
            int dotIndex = importRef.toString().lastIndexOf('.');
            String currPackageImport = "";
            if (dotIndex != -1) {
                  currPackageImport = importRef.toString().substring(0, dotIndex);
            }
            if (!((IProgramElement) stack.peek()).getPackageName().equals(currPackageImport)) {
                  stack.pop();
            }
      }



      
      private String genSourceSignature(ImportReference importreference) {
            StringBuffer output = new StringBuffer();
            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);
                  peNode.setCorrespondingType(fieldDeclaration.binding.type.debugName());
            } else {
                  peNode = new ProgramElement(activeStructureModel, new String(fieldDeclaration.name), IProgramElement.Kind.FIELD,
                              makeLocation(fieldDeclaration), fieldDeclaration.modifiers, null, null);
                  peNode.setCorrespondingType(fieldDeclaration.type.toString());
            }
            peNode.setSourceSignature(genSourceSignature(fieldDeclaration));
            peNode.setFormalComment(generateJavadocComment(fieldDeclaration));

            ((IProgramElement) 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.
       */
00832       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;
                              StringBuffer sb = new StringBuffer();
                              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) {
            StringBuffer output = new StringBuffer();
            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;
            }
            StringBuffer argumentsSignature = new StringBuffer();
            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 = "<undefined>";
                  } catch (NullPointerException npe) {
                        memberName = "<undefined>";
                  }
                  peNode.setBytecodeName(memberName);
                  peNode.setBytecodeSignature(memberBytecodeSignature);
            }

            ((IProgramElement) stack.peek()).addChild(peNode);
            stack.push(peNode);
            return true;
      }

      public void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
            stack.pop();
      }

      private String genSourceSignature(ConstructorDeclaration constructorDeclaration) {
            StringBuffer output = new StringBuffer();
            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(
      // "<clinit>",
      // 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
       */
01036       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());
            ((IProgramElement) 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);
      }
}

Generated by  Doxygen 1.6.0   Back to index