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.

IntertypeMemberClassDeclaration.java 11KB

14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /* *******************************************************************
  2. * Copyright (c) 2010 Contributors
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * Andy Clement - SpringSource
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.compiler.ast;
  13. import java.lang.reflect.Modifier;
  14. import java.util.Collections;
  15. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  16. import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
  17. import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
  18. import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope;
  19. import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
  20. import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
  21. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  22. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
  23. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
  24. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
  25. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  26. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
  27. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
  28. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
  30. import org.aspectj.weaver.AjAttribute;
  31. import org.aspectj.weaver.NewMemberClassTypeMunger;
  32. import org.aspectj.weaver.ResolvedType;
  33. import org.aspectj.weaver.ResolvedTypeMunger;
  34. /**
  35. * Represents an intertype member class declaration.
  36. *
  37. * @author Andy Clement
  38. * @since 1.6.9
  39. */
  40. public class IntertypeMemberClassDeclaration extends TypeDeclaration {
  41. // The target type for this inner class
  42. private TypeReference onType;
  43. private ReferenceBinding onTypeResolvedBinding;
  44. private NewMemberClassTypeMunger newMemberClassTypeMunger;
  45. protected InterTypeScope interTypeScope;
  46. // When set to true, the scope hierarchy for the field/method declaration has been correctly modified to include an intertype
  47. // scope which resolves things relative to the targeted type.
  48. private boolean scopeSetup = false;
  49. public IntertypeMemberClassDeclaration(CompilationResult compilationResult) {
  50. super(compilationResult);
  51. }
  52. public ResolvedTypeMunger getMunger() {
  53. return newMemberClassTypeMunger;
  54. }
  55. @Override
  56. public void resolve(ClassScope aspectScope) {
  57. resolveOnType(aspectScope);
  58. ensureScopeSetup();
  59. super.resolve(aspectScope);
  60. }
  61. /**
  62. * Bytecode generation for a member inner type
  63. */
  64. /*
  65. * public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) { if ((this.bits & ASTNode.HasBeenGenerated) !=
  66. * 0) { return; } try { Field f = ReferenceBinding.class.getDeclaredField("constantPoolName"); char[] name =
  67. * CharOperation.concat(onTypeResolvedBinding.constantPoolName(), binding.sourceName, '$'); f.setAccessible(true);
  68. * f.set(this.binding, name); } catch (Exception e) { e.printStackTrace(); } if (this.binding != null) { ((NestedTypeBinding)
  69. * this.binding).computeSyntheticArgumentSlotSizes(); } generateCode(enclosingClassFile); }
  70. */
  71. @Override
  72. public void resolve() {
  73. super.resolve();
  74. }
  75. @Override
  76. public void resolve(BlockScope blockScope) {
  77. throw new IllegalStateException();
  78. }
  79. @Override
  80. public void resolve(CompilationUnitScope upperScope) {
  81. throw new IllegalStateException();
  82. }
  83. @SuppressWarnings("unchecked")
  84. @Override
  85. protected void generateAttributes(ClassFile classFile) {
  86. // classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute()));
  87. super.generateAttributes(classFile);
  88. }
  89. public AjAttribute getAttribute() {
  90. // if there were problems then there is nothing to return
  91. if (newMemberClassTypeMunger == null) {
  92. return null;
  93. }
  94. return new AjAttribute.TypeMunger(newMemberClassTypeMunger);
  95. }
  96. /**
  97. * Called just before the compiler is going to start resolving elements of a declaration, this method adds an intertype scope so
  98. * that elements of the type targeted by the ITD can be resolved. For example, if type variables are referred to in the ontype
  99. * for the ITD, they have to be resolved against the ontype, not the aspect containing the ITD.
  100. */
  101. public void ensureScopeSetup() {
  102. if (scopeSetup) {
  103. return; // don't do it again
  104. }
  105. ClassScope scope = this.scope;
  106. // TODO [inner] ton of stuff related to parameterization support
  107. // if (ot instanceof ParameterizedQualifiedTypeReference) { // pr132349
  108. // ParameterizedQualifiedTypeReference pref = (ParameterizedQualifiedTypeReference) ot;
  109. // if (pref.typeArguments != null && pref.typeArguments.length != 0) {
  110. // boolean usingNonTypeVariableInITD = false;
  111. // // Check if any of them are not type variables
  112. // for (int i = 0; i < pref.typeArguments.length; i++) {
  113. // TypeReference[] refs = pref.typeArguments[i];
  114. // for (int j = 0; refs != null && j < refs.length; j++) {
  115. // TypeBinding tb = refs[j].getTypeBindingPublic(scope.parent);
  116. // if (!tb.isTypeVariable() && !(tb instanceof ProblemReferenceBinding)) {
  117. // usingNonTypeVariableInITD = true;
  118. // }
  119. //
  120. // }
  121. // }
  122. // if (usingNonTypeVariableInITD) {
  123. // scope.problemReporter().signalError(sourceStart, sourceEnd,
  124. // "Cannot make inter-type declarations on parameterized types");
  125. // // to prevent disgusting cascading errors after this problem - lets null out what leads to them (pr105038)
  126. // this.arguments = null;
  127. // this.returnType = new SingleTypeReference(TypeReference.VOID, 0L);
  128. //
  129. // this.ignoreFurtherInvestigation = true;
  130. // ReferenceBinding closestMatch = null;
  131. // rb = new ProblemReferenceBinding(ot.getParameterizedTypeName(), closestMatch, 0);
  132. // onType = null;
  133. // }
  134. // }
  135. //
  136. // }
  137. // // Work out the real base type
  138. // if (onType instanceof ParameterizedSingleTypeReference) {
  139. // ParameterizedSingleTypeReference pref = (ParameterizedSingleTypeReference) ot;
  140. // long pos = (((long) pref.sourceStart) << 32) | pref.sourceEnd;
  141. // ot = new SingleTypeReference(pref.token, pos);
  142. // } else if (ot instanceof ParameterizedQualifiedTypeReference) {
  143. // ParameterizedQualifiedTypeReference pref = (ParameterizedQualifiedTypeReference) ot;
  144. // long pos = (((long) pref.sourceStart) << 32) | pref.sourceEnd;
  145. // ot = new QualifiedTypeReference(pref.tokens, new long[] { pos });// SingleTypeReference(pref.Quatoken,pos);
  146. // }
  147. // resolve it
  148. // if (rb == null) {
  149. // rb = (ReferenceBinding) ot.getTypeBindingPublic(scope.parent);
  150. // }
  151. // pr203646 - if we have ended up with the raw type, get back to the underlying generic one.
  152. // if (rb.isRawType() && rb.isMemberType()) {
  153. // // if the real target type used a type variable alias then we can do this OK, but need to switch things around, we want
  154. // // the generic type
  155. // rb = ((RawTypeBinding) rb).type;
  156. // }
  157. // if (rb instanceof TypeVariableBinding) {
  158. // scope.problemReporter().signalError(sourceStart, sourceEnd,
  159. // "Cannot make inter-type declarations on type variables, use an interface and declare parents");
  160. // // to prevent disgusting cascading errors after this problem - lets null out what leads to them (pr105038)
  161. // this.arguments = null;
  162. // this.returnType = new SingleTypeReference(TypeReference.VOID, 0L);
  163. //
  164. // this.ignoreFurtherInvestigation = true;
  165. // ReferenceBinding closestMatch = null;
  166. // if (((TypeVariableBinding) rb).firstBound != null) {
  167. // closestMatch = ((TypeVariableBinding) rb).firstBound.enclosingType();
  168. // }
  169. // rb = new ProblemReferenceBinding(rb.compoundName, closestMatch, 0);
  170. // }
  171. // if resolution failed, give up - someone else is going to report an error
  172. // if (rb instanceof ProblemReferenceBinding) {
  173. // return;
  174. // }
  175. if (scope != null) {
  176. interTypeScope = new InterTypeScope(scope.parent, onTypeResolvedBinding, Collections.emptyList());
  177. // FIXME asc verify the choice of lines here...
  178. // Two versions of this next line.
  179. // First one tricks the JDT variable processing code so that it won't complain if
  180. // you refer to a type variable from a static ITD - it *is* a problem and it *will* be caught, but later and
  181. // by the AJDT code so we can put out a much nicer message.
  182. // scope.isStatic = (typeVariableAliases != null ? false : Modifier.isStatic(declaredModifiers));
  183. // this is the original version in case tricking the JDT causes grief (if you reinstate this variant, you
  184. // will need to change the expected messages output for some of the generic ITD tests)
  185. // scope.isStatic = Modifier.isStatic(declaredModifiers);
  186. // Use setter in order to also update member 'compilationUnitScope'
  187. scope.setParent(interTypeScope);
  188. }
  189. scopeSetup = true;
  190. }
  191. public void setOnType(TypeReference onType) {
  192. this.onType = onType;
  193. }
  194. private void resolveOnType(ClassScope cuScope) {
  195. if (onType == null || onTypeResolvedBinding != null) {
  196. return;
  197. } // error reported elsewhere.
  198. onTypeResolvedBinding = (ReferenceBinding) onType.getTypeBindingPublic(cuScope);
  199. if (!onTypeResolvedBinding.isValidBinding()) {
  200. cuScope.problemReporter().invalidType(onType, onTypeResolvedBinding);
  201. ignoreFurtherInvestigation = true;
  202. } else {
  203. // fix up the ITD'd type?
  204. if (this.binding != null) {
  205. ((NestedTypeBinding) this.binding).enclosingType = (SourceTypeBinding) onTypeResolvedBinding;
  206. }
  207. // this done at build type for the nested type now:
  208. // ((NestedTypeBinding) this.binding).compoundName = CharOperation.splitOn('.', "Basic$_".toCharArray());
  209. }
  210. }
  211. public EclipseTypeMunger build(ClassScope classScope) {
  212. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
  213. resolveOnType(classScope);
  214. ensureScopeSetup();
  215. if (ignoreFurtherInvestigation) {
  216. return null;
  217. }
  218. if (onTypeResolvedBinding.isInterface() || onTypeResolvedBinding.isEnum() || onTypeResolvedBinding.isAnnotationType()) {
  219. scope.problemReporter().signalError(
  220. sourceStart,
  221. sourceEnd,
  222. "Cannot declare new member type on '" + onType.toString()
  223. + "'. New member types can only be specified on classes (compiler limitation)");
  224. return null;
  225. }
  226. if (!Modifier.isStatic(modifiers)) {
  227. scope.problemReporter().signalError(sourceStart, sourceEnd,
  228. "Intertype declared member types can only be static (compiler limitation)");
  229. return null;
  230. }
  231. ResolvedType declaringType = world.fromBinding(onTypeResolvedBinding).resolve(world.getWorld());
  232. if (declaringType.isRawType() || declaringType.isParameterizedType()) {
  233. declaringType = declaringType.getGenericType();
  234. }
  235. if (interTypeScope == null) {
  236. return null; // We encountered a problem building the scope, don't continue - error already reported
  237. }
  238. // TODO [inner] use the interTypeScope.getRecoveryAliases
  239. // TODO [inner] should mark it in the aspect as unreachable - it is not to be considered part of the aspect
  240. newMemberClassTypeMunger = new NewMemberClassTypeMunger(declaringType, new String(this.name));
  241. newMemberClassTypeMunger.setSourceLocation(new EclipseSourceLocation(compilationResult, sourceStart, sourceEnd));
  242. ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
  243. return new EclipseTypeMunger(world, newMemberClassTypeMunger, aspectType, null);
  244. }
  245. public char[] alternativeName() {
  246. return CharOperation.concatWith(onType.getTypeName(),'.');//onType.getLastToken();
  247. }
  248. }