Logo Search packages:      
Sourcecode: aspectj version File versions  Download package

EclipseScope.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 
 * ******************************************************************/

package org.aspectj.ajdt.internal.compiler.lookup;

import java.util.ArrayList;
import java.util.List;

import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.IMessageHandler;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
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.ImportBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.weaver.IHasPosition;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.FormalBinding;
import org.aspectj.weaver.patterns.IScope;
import org.aspectj.weaver.patterns.WildTypePattern;

/**
 * Adaptor from org.eclipse.jdt.internal.compiler.lookup.Scope to
 * org.aspectj.weaver.IScope
 * 
 * @author Jim Hugunin
 */
00043 public class EclipseScope implements IScope {
      private static final char[] javaLang = "java.lang".toCharArray();
      private static final String[] JL = new String[] { "java.lang." };
      private static final String[] NONE = new String[0];
      private final Scope scope;
      private final EclipseFactory world;
      private final ResolvedType enclosingType;
      private final FormalBinding[] bindings;

      private String[] importedPrefixes = null;
      private String[] importedNames = null;

      public EclipseScope(FormalBinding[] bindings, Scope scope) {
            this.bindings = bindings;

            this.scope = scope;
            world = EclipseFactory.fromScopeLookupEnvironment(scope);

            enclosingType = world.fromEclipse(scope.enclosingSourceType());
      }

      public UnresolvedType lookupType(String name, IHasPosition location) {
            char[][] splitName = WildTypePattern.splitNames(name, true);
            TypeBinding b = scope.getType(splitName, splitName.length);
            // FIXME ??? need reasonable error handling...
            if (!b.isValidBinding()) {
                  return ResolvedType.MISSING;
            }

            if (referenceFromAnnotationStylePointcut) { // pr265360
                  // it must be fully qualified in the pointcut text or in the same
                  // package as the type containing the pointcut
                  char[] qualifiedPackageName = b.qualifiedPackageName();
                  if (!CharOperation.equals(qualifiedPackageName, javaLang)) {
                        String packagePrefix = new String(qualifiedPackageName);
                        if (!name.startsWith(packagePrefix)) {
                              if (validPackage != null && CharOperation.equals(validPackage, qualifiedPackageName)) {
                                    // it is OK, found in same package as the aspect
                              } else {
                                    return ResolvedType.MISSING;
                              }
                        }
                  }
            }

            // System.err.println("binding: " + b);
            // Binding(tokens, bits & RestrictiveFlagMASK, this)
            return world.fromBinding(b);

            /*
             * computeImports();
             * 
             * // System.out.println("lookup: " + name + " in " + //
             * Arrays.asList(importedPrefixes));
             * 
             * ResolvedType ret = null; String dotName = "." + name; for (int i=0;
             * i<importedNames.length; i++) { String importedName =
             * importedNames[i]; //??? can this be right if
             * (importedName.endsWith(name) && ((importedName.length() ==
             * name.length()) || (importedName.endsWith(dotName)))) { ResolvedType
             * found = resolveVisible(importedName); if (found ==
             * ResolvedType.MISSING) continue; if (ret != null) {
             * message(IMessage.ERROR, location, "ambiguous type reference, both " +
             * ret.getName() + " and " + importedName); return ResolvedType.MISSING;
             * } else { ret = found; } } }
             * 
             * if (ret != null) return ret;
             * 
             * //XXX need to handle ambiguous references here for (int i=0;
             * i<importedPrefixes.length; i++) { String importedPrefix =
             * importedPrefixes[i]; ResolvedType tryType =
             * resolveVisible(importedPrefix + name); if (tryType !=
             * ResolvedType.MISSING) { return tryType; } }
             * 
             * return resolveVisible(name);
             */
      }

      // private ResolvedType resolveVisible(String name) {
      // ResolvedType found =
      // world.getWorld().resolve(UnresolvedType.forName(name), true);
      // if (found == ResolvedType.MISSING) return found;
      // if (ResolvedType.isVisible(found.getModifiers(), found, enclosingType))
      // return found;
      // return ResolvedType.MISSING;
      // }

      // public UnresolvedType lookupType(String name, IHasPosition location) {
      // char[][] namePieces = CharOperation.splitOn('.', name.toCharArray());
      // TypeBinding binding;
      // if (namePieces.length == 1) {
      // binding = scope.getType(namePieces[0]);
      // } else {
      // binding = scope.getType(namePieces);
      // }
      //          
      //          
      // if (!binding.isValidBinding()) {
      // //XXX do we do this always or sometimes
      // System.err.println("error: " + binding);
      //scope.problemReporter().invalidType(EclipseWorld.astForLocation(location),
      // binding);
      // return ResolvedType.MISSING;
      // }
      // //??? do we want this too
      // // if (AstNode.isTypeUseDeprecated(binding, scope))
      // // scope.problemReporter().deprecatedType(binding,
      // EclipseWorld.astForLocation(location));
      //          
      // return EclipseWorld.fromBinding(binding);
      // }

      private void computeImports() {
            if (importedNames != null)
                  return;

            List importedNamesList = new ArrayList();
            List importedPrefixesList = new ArrayList();

            Scope currentScope = scope;
            // add any enclosing types to this list
            while (!(currentScope instanceof CompilationUnitScope)) {
                  if (currentScope == null) {
                        throw new RuntimeException("unimplemented");
                  }
                  if (currentScope instanceof ClassScope) {
                        addClassAndParentsToPrefixes(((ClassScope) currentScope).referenceType().binding, importedPrefixesList);
                  }
                  currentScope = currentScope.parent;
            }

            CompilationUnitScope cuScope = (CompilationUnitScope) currentScope;

            String packageName = new String(CharOperation.concatWith(cuScope.currentPackageName, '.'));
            // System.err.println("package: " + packageName);
            if (packageName.length() > 0) {
                  importedPrefixesList.add(packageName + ".");
            }

            ImportBinding[] imports = cuScope.imports;
            for (int i = 0; i < imports.length; i++) {
                  ImportBinding importBinding = imports[i];
                  String importName = new String(CharOperation.concatWith(importBinding.compoundName, '.'));

                  // XXX wrong behavior for java.util.Map.*
                  if (importBinding.onDemand) {
                        importedPrefixesList.add(importName + ".");
                  } else {
                        importedNamesList.add(importName);
                  }
            }

            TypeBinding[] topTypes = cuScope.topLevelTypes;
            for (int i = 0; i < topTypes.length; i++) {
                  importedNamesList.add(world.fromBinding(topTypes[i]).getName());
            }

            importedNames = (String[]) importedNamesList.toArray(new String[importedNamesList.size()]);

            importedPrefixes = (String[]) importedPrefixesList.toArray(new String[importedPrefixesList.size()]);
      }

      private void addClassAndParentsToPrefixes(ReferenceBinding binding, List importedPrefixesList) {
            if (binding == null)
                  return;
            importedPrefixesList.add(world.fromBinding(binding).getName() + "$");

            addClassAndParentsToPrefixes(binding.superclass(), importedPrefixesList);
            ReferenceBinding[] superinterfaces = binding.superInterfaces();
            if (superinterfaces != null) {
                  for (int i = 0; i < superinterfaces.length; i++) {
                        addClassAndParentsToPrefixes(superinterfaces[i], importedPrefixesList);
                  }
            }
      }

      public String[] getImportedNames() {
            computeImports();
            return importedNames;
      }

      public String[] getImportedPrefixes() {
            computeImports();
            // System.err.println("prefixes: " + Arrays.asList(importedPrefixes));
            return importedPrefixes;
      }

      // XXX add good errors when would bind to extra parameters
      public FormalBinding lookupFormal(String name) {
            for (int i = 0, len = bindings.length; i < len; i++) {
                  if (bindings[i].getName().equals(name))
                        return bindings[i];
            }
            return null;
      }

      public FormalBinding getFormal(int i) {
            return bindings[i];
      }

      public int getFormalCount() {
            return bindings.length;
      }

      public ISourceLocation makeSourceLocation(IHasPosition location) {
            return new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(), location.getStart(),
                        location.getEnd());
      }

      public IMessageHandler getMessageHandler() {
            return world.getWorld().getMessageHandler();
      }

      public void message(IMessage.Kind kind, IHasPosition location1, IHasPosition location2, String message) {
            message(kind, location1, message);
            message(kind, location2, message);
      }

      public void message(IMessage.Kind kind, IHasPosition location, String message) {
            // System.out.println("message: " + message + " loc: " +
            // makeSourceLocation(location));
            getMessageHandler().handleMessage(new Message(message, kind, null, makeSourceLocation(location)));

      }

      public void message(IMessage aMessage) {
            getMessageHandler().handleMessage(aMessage);
      }

      public World getWorld() {
            return world.getWorld();
      }

      public ResolvedType getEnclosingType() {
            return enclosingType;
      }

      private boolean referenceFromAnnotationStylePointcut = false;
      private char[] validPackage;

      /**
       * Mark this scope as only allowing limited support for imports. This is to
       * ensure that references in annotation style pointcuts are accidentally
       * resolved against import statements. They won't be if javac is used (and
       * the resulting .class file will contain 'bad pointcuts') so this method
       * enables it to also be policed when compiling with ajc.
       * 
       * @param validPackage unqualified references can be resolved if the type is
       *            in the same package as the type containing the pointcut
       *            declaration.
       */
00294       public void setLimitedImports(char[] validPackage) {
            referenceFromAnnotationStylePointcut = true;
            this.validPackage = validPackage;
            importedPrefixes = JL; // Consider only java.lang. as an import
            importedNames = NONE; // No imported names
      }

}

Generated by  Doxygen 1.6.0   Back to index