Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

EclipseScope.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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<String>();
  145. List<String> importedPrefixesList = new ArrayList<String>();
  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 (int i = 0; i < imports.length; i++) {
  165. ImportBinding importBinding = imports[i];
  166. String importName = new String(CharOperation.concatWith(importBinding.compoundName, '.'));
  167. // XXX wrong behavior for java.util.Map.*
  168. if (importBinding.onDemand) {
  169. importedPrefixesList.add(importName + ".");
  170. } else {
  171. importedNamesList.add(importName);
  172. }
  173. }
  174. TypeBinding[] topTypes = cuScope.topLevelTypes;
  175. for (int i = 0; i < topTypes.length; i++) {
  176. importedNamesList.add(world.fromBinding(topTypes[i]).getName());
  177. }
  178. importedNames = importedNamesList.toArray(new String[importedNamesList.size()]);
  179. importedPrefixes = importedPrefixesList.toArray(new String[importedPrefixesList.size()]);
  180. }
  181. private void addClassAndParentsToPrefixes(ReferenceBinding binding, List<String> importedPrefixesList) {
  182. if (binding == null)
  183. return;
  184. importedPrefixesList.add(world.fromBinding(binding).getName() + "$");
  185. addClassAndParentsToPrefixes(binding.superclass(), importedPrefixesList);
  186. ReferenceBinding[] superinterfaces = binding.superInterfaces();
  187. if (superinterfaces != null) {
  188. for (int i = 0; i < superinterfaces.length; i++) {
  189. addClassAndParentsToPrefixes(superinterfaces[i], importedPrefixesList);
  190. }
  191. }
  192. }
  193. @Override
  194. public String[] getImportedNames() {
  195. computeImports();
  196. return importedNames;
  197. }
  198. @Override
  199. public String[] getImportedPrefixes() {
  200. computeImports();
  201. // System.err.println("prefixes: " + Arrays.asList(importedPrefixes));
  202. return importedPrefixes;
  203. }
  204. // XXX add good errors when would bind to extra parameters
  205. @Override
  206. public FormalBinding lookupFormal(String name) {
  207. for (int i = 0, len = bindings.length; i < len; i++) {
  208. if (bindings[i].getName().equals(name))
  209. return bindings[i];
  210. }
  211. return null;
  212. }
  213. @Override
  214. public FormalBinding getFormal(int i) {
  215. return bindings[i];
  216. }
  217. @Override
  218. public int getFormalCount() {
  219. return bindings.length;
  220. }
  221. public ISourceLocation makeSourceLocation(IHasPosition location) {
  222. return new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(), location.getStart(),
  223. location.getEnd());
  224. }
  225. @Override
  226. public IMessageHandler getMessageHandler() {
  227. return world.getWorld().getMessageHandler();
  228. }
  229. @Override
  230. public void message(IMessage.Kind kind, IHasPosition location1, IHasPosition location2, String message) {
  231. message(kind, location1, message);
  232. message(kind, location2, message);
  233. }
  234. @Override
  235. public void message(IMessage.Kind kind, IHasPosition location, String message) {
  236. // System.out.println("message: " + message + " loc: " +
  237. // makeSourceLocation(location));
  238. getMessageHandler().handleMessage(new Message(message, kind, null, makeSourceLocation(location)));
  239. }
  240. @Override
  241. public void message(IMessage aMessage) {
  242. getMessageHandler().handleMessage(aMessage);
  243. }
  244. @Override
  245. public World getWorld() {
  246. return world.getWorld();
  247. }
  248. @Override
  249. public ResolvedType getEnclosingType() {
  250. return enclosingType;
  251. }
  252. private boolean referenceFromAnnotationStylePointcut = false;
  253. private char[] validPackage;
  254. /**
  255. * Mark this scope as only allowing limited support for imports. This is to
  256. * ensure that references in annotation style pointcuts are accidentally
  257. * resolved against import statements. They won't be if javac is used (and
  258. * the resulting .class file will contain 'bad pointcuts') so this method
  259. * enables it to also be policed when compiling with ajc.
  260. *
  261. * @param validPackage unqualified references can be resolved if the type is
  262. * in the same package as the type containing the pointcut
  263. * declaration.
  264. */
  265. public void setLimitedImports(char[] validPackage) {
  266. referenceFromAnnotationStylePointcut = true;
  267. this.validPackage = validPackage;
  268. importedPrefixes = JL; // Consider only java.lang. as an import
  269. importedNames = NONE; // No imported names
  270. }
  271. }