You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EclipseScope.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.compiler.lookup;
  13. import java.util.ArrayList;
  14. import java.util.List;
  15. import org.aspectj.bridge.IMessage;
  16. import org.aspectj.bridge.IMessageHandler;
  17. import org.aspectj.bridge.ISourceLocation;
  18. import org.aspectj.bridge.Message;
  19. import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
  20. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  21. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
  22. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
  23. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  24. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
  25. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  26. import org.aspectj.weaver.IHasPosition;
  27. import org.aspectj.weaver.ResolvedType;
  28. import org.aspectj.weaver.UnresolvedType;
  29. import org.aspectj.weaver.World;
  30. import org.aspectj.weaver.patterns.FormalBinding;
  31. import org.aspectj.weaver.patterns.IScope;
  32. import org.aspectj.weaver.patterns.WildTypePattern;
  33. /**
  34. * Adaptor from org.eclipse.jdt.internal.compiler.lookup.Scope to
  35. * org.aspectj.weaver.IScope
  36. *
  37. * @author Jim Hugunin
  38. */
  39. public class EclipseScope implements IScope {
  40. private static final char[] javaLang = "java.lang".toCharArray();
  41. private static final String[] JL = new String[] { "java.lang." };
  42. private static final String[] NONE = new String[0];
  43. private final Scope scope;
  44. private final EclipseFactory world;
  45. private final ResolvedType enclosingType;
  46. private final FormalBinding[] bindings;
  47. private String[] importedPrefixes = null;
  48. private String[] importedNames = null;
  49. public EclipseScope(FormalBinding[] bindings, Scope scope) {
  50. this.bindings = bindings;
  51. this.scope = scope;
  52. world = EclipseFactory.fromScopeLookupEnvironment(scope);
  53. enclosingType = world.fromEclipse(scope.enclosingSourceType());
  54. }
  55. @Override
  56. public UnresolvedType lookupType(String name, IHasPosition location) {
  57. char[][] splitName = WildTypePattern.splitNames(name, true);
  58. TypeBinding b = scope.getType(splitName, splitName.length);
  59. // FIXME ??? need reasonable error handling...
  60. if (!b.isValidBinding()) {
  61. return ResolvedType.MISSING;
  62. }
  63. if (referenceFromAnnotationStylePointcut) { // pr265360
  64. // it must be fully qualified in the pointcut text or in the same
  65. // package as the type containing the pointcut
  66. char[] qualifiedPackageName = b.qualifiedPackageName();
  67. if (!CharOperation.equals(qualifiedPackageName, javaLang)) {
  68. String packagePrefix = new String(qualifiedPackageName);
  69. if (!name.startsWith(packagePrefix)) {
  70. if (validPackage != null && CharOperation.equals(validPackage, qualifiedPackageName)) {
  71. // it is OK, found in same package as the aspect
  72. } else {
  73. return ResolvedType.MISSING;
  74. }
  75. }
  76. }
  77. }
  78. // System.err.println("binding: " + b);
  79. // Binding(tokens, bits & RestrictiveFlagMASK, this)
  80. return world.fromBinding(b);
  81. /*
  82. * computeImports();
  83. *
  84. * // System.out.println("lookup: " + name + " in " + //
  85. * Arrays.asList(importedPrefixes));
  86. *
  87. * ResolvedType ret = null; String dotName = "." + name; for (int i=0;
  88. * i<importedNames.length; i++) { String importedName =
  89. * importedNames[i]; //??? can this be right if
  90. * (importedName.endsWith(name) && ((importedName.length() ==
  91. * name.length()) || (importedName.endsWith(dotName)))) { ResolvedType
  92. * found = resolveVisible(importedName); if (found ==
  93. * ResolvedType.MISSING) continue; if (ret != null) {
  94. * message(IMessage.ERROR, location, "ambiguous type reference, both " +
  95. * ret.getName() + " and " + importedName); return ResolvedType.MISSING;
  96. * } else { ret = found; } } }
  97. *
  98. * if (ret != null) return ret;
  99. *
  100. * //XXX need to handle ambiguous references here for (int i=0;
  101. * i<importedPrefixes.length; i++) { String importedPrefix =
  102. * importedPrefixes[i]; ResolvedType tryType =
  103. * resolveVisible(importedPrefix + name); if (tryType !=
  104. * ResolvedType.MISSING) { return tryType; } }
  105. *
  106. * return resolveVisible(name);
  107. */
  108. }
  109. // private ResolvedType resolveVisible(String name) {
  110. // ResolvedType found =
  111. // world.getWorld().resolve(UnresolvedType.forName(name), true);
  112. // if (found == ResolvedType.MISSING) return found;
  113. // if (ResolvedType.isVisible(found.getModifiers(), found, enclosingType))
  114. // return found;
  115. // return ResolvedType.MISSING;
  116. // }
  117. // public UnresolvedType lookupType(String name, IHasPosition location) {
  118. // char[][] namePieces = CharOperation.splitOn('.', name.toCharArray());
  119. // TypeBinding binding;
  120. // if (namePieces.length == 1) {
  121. // binding = scope.getType(namePieces[0]);
  122. // } else {
  123. // binding = scope.getType(namePieces);
  124. // }
  125. //
  126. //
  127. // if (!binding.isValidBinding()) {
  128. // //XXX do we do this always or sometimes
  129. // System.err.println("error: " + binding);
  130. //scope.problemReporter().invalidType(EclipseWorld.astForLocation(location),
  131. // binding);
  132. // return ResolvedType.MISSING;
  133. // }
  134. // //??? do we want this too
  135. // // if (AstNode.isTypeUseDeprecated(binding, scope))
  136. // // scope.problemReporter().deprecatedType(binding,
  137. // EclipseWorld.astForLocation(location));
  138. //
  139. // return EclipseWorld.fromBinding(binding);
  140. // }
  141. private void computeImports() {
  142. if (importedNames != null)
  143. return;
  144. List<String> importedNamesList = new ArrayList<>();
  145. List<String> importedPrefixesList = new ArrayList<>();
  146. Scope currentScope = scope;
  147. // add any enclosing types to this list
  148. while (!(currentScope instanceof CompilationUnitScope)) {
  149. if (currentScope == null) {
  150. throw new RuntimeException("unimplemented");
  151. }
  152. if (currentScope instanceof ClassScope) {
  153. addClassAndParentsToPrefixes(((ClassScope) currentScope).referenceType().binding, importedPrefixesList);
  154. }
  155. currentScope = currentScope.parent;
  156. }
  157. CompilationUnitScope cuScope = (CompilationUnitScope) currentScope;
  158. String packageName = new String(CharOperation.concatWith(cuScope.currentPackageName, '.'));
  159. // System.err.println("package: " + packageName);
  160. if (packageName.length() > 0) {
  161. importedPrefixesList.add(packageName + ".");
  162. }
  163. ImportBinding[] imports = cuScope.imports;
  164. for (ImportBinding importBinding : imports) {
  165. String importName = new String(CharOperation.concatWith(importBinding.compoundName, '.'));
  166. // XXX wrong behavior for java.util.Map.*
  167. if (importBinding.onDemand) {
  168. importedPrefixesList.add(importName + ".");
  169. } else {
  170. importedNamesList.add(importName);
  171. }
  172. }
  173. TypeBinding[] topTypes = cuScope.topLevelTypes;
  174. for (TypeBinding topType : topTypes) {
  175. importedNamesList.add(world.fromBinding(topType).getName());
  176. }
  177. importedNames = importedNamesList.toArray(new String[importedNamesList.size()]);
  178. importedPrefixes = importedPrefixesList.toArray(new String[importedPrefixesList.size()]);
  179. }
  180. private void addClassAndParentsToPrefixes(ReferenceBinding binding, List<String> importedPrefixesList) {
  181. if (binding == null)
  182. return;
  183. importedPrefixesList.add(world.fromBinding(binding).getName() + "$");
  184. addClassAndParentsToPrefixes(binding.superclass(), importedPrefixesList);
  185. ReferenceBinding[] superinterfaces = binding.superInterfaces();
  186. if (superinterfaces != null) {
  187. for (ReferenceBinding superinterface : superinterfaces) {
  188. addClassAndParentsToPrefixes(superinterface, importedPrefixesList);
  189. }
  190. }
  191. }
  192. @Override
  193. public String[] getImportedNames() {
  194. computeImports();
  195. return importedNames;
  196. }
  197. @Override
  198. public String[] getImportedPrefixes() {
  199. computeImports();
  200. // System.err.println("prefixes: " + Arrays.asList(importedPrefixes));
  201. return importedPrefixes;
  202. }
  203. // XXX add good errors when would bind to extra parameters
  204. @Override
  205. public FormalBinding lookupFormal(String name) {
  206. for (FormalBinding binding : bindings) {
  207. if (binding.getName().equals(name))
  208. return binding;
  209. }
  210. return null;
  211. }
  212. @Override
  213. public FormalBinding getFormal(int i) {
  214. return bindings[i];
  215. }
  216. @Override
  217. public int getFormalCount() {
  218. return bindings.length;
  219. }
  220. public ISourceLocation makeSourceLocation(IHasPosition location) {
  221. return new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(), location.getStart(),
  222. location.getEnd());
  223. }
  224. @Override
  225. public IMessageHandler getMessageHandler() {
  226. return world.getWorld().getMessageHandler();
  227. }
  228. @Override
  229. public void message(IMessage.Kind kind, IHasPosition location1, IHasPosition location2, String message) {
  230. message(kind, location1, message);
  231. message(kind, location2, message);
  232. }
  233. @Override
  234. public void message(IMessage.Kind kind, IHasPosition location, String message) {
  235. // System.out.println("message: " + message + " loc: " +
  236. // makeSourceLocation(location));
  237. getMessageHandler().handleMessage(new Message(message, kind, null, makeSourceLocation(location)));
  238. }
  239. @Override
  240. public void message(IMessage aMessage) {
  241. getMessageHandler().handleMessage(aMessage);
  242. }
  243. @Override
  244. public World getWorld() {
  245. return world.getWorld();
  246. }
  247. @Override
  248. public ResolvedType getEnclosingType() {
  249. return enclosingType;
  250. }
  251. private boolean referenceFromAnnotationStylePointcut = false;
  252. private char[] validPackage;
  253. /**
  254. * Mark this scope as only allowing limited support for imports. This is to
  255. * ensure that references in annotation style pointcuts are accidentally
  256. * resolved against import statements. They won't be if javac is used (and
  257. * the resulting .class file will contain 'bad pointcuts') so this method
  258. * enables it to also be policed when compiling with ajc.
  259. *
  260. * @param validPackage unqualified references can be resolved if the type is
  261. * in the same package as the type containing the pointcut
  262. * declaration.
  263. */
  264. public void setLimitedImports(char[] validPackage) {
  265. referenceFromAnnotationStylePointcut = true;
  266. this.validPackage = validPackage;
  267. importedPrefixes = JL; // Consider only java.lang. as an import
  268. importedNames = NONE; // No imported names
  269. }
  270. }