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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  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. scope.parent = interTypeScope;
  187. }
  188. scopeSetup = true;
  189. }
  190. public void setOnType(TypeReference onType) {
  191. this.onType = onType;
  192. }
  193. private void resolveOnType(ClassScope cuScope) {
  194. if (onType == null || onTypeResolvedBinding != null) {
  195. return;
  196. } // error reported elsewhere.
  197. onTypeResolvedBinding = (ReferenceBinding) onType.getTypeBindingPublic(cuScope);
  198. if (!onTypeResolvedBinding.isValidBinding()) {
  199. cuScope.problemReporter().invalidType(onType, onTypeResolvedBinding);
  200. ignoreFurtherInvestigation = true;
  201. } else {
  202. // fix up the ITD'd type?
  203. if (this.binding != null) {
  204. ((NestedTypeBinding) this.binding).enclosingType = (SourceTypeBinding) onTypeResolvedBinding;
  205. }
  206. // this done at build type for the nested type now:
  207. // ((NestedTypeBinding) this.binding).compoundName = CharOperation.splitOn('.', "Basic$_".toCharArray());
  208. }
  209. }
  210. public EclipseTypeMunger build(ClassScope classScope) {
  211. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
  212. resolveOnType(classScope);
  213. ensureScopeSetup();
  214. if (ignoreFurtherInvestigation) {
  215. return null;
  216. }
  217. if (onTypeResolvedBinding.isInterface() || onTypeResolvedBinding.isEnum() || onTypeResolvedBinding.isAnnotationType()) {
  218. scope.problemReporter().signalError(
  219. sourceStart,
  220. sourceEnd,
  221. "Cannot declare new member type on '" + onType.toString()
  222. + "'. New member types can only be specified on classes (compiler limitation)");
  223. return null;
  224. }
  225. if (!Modifier.isStatic(modifiers)) {
  226. scope.problemReporter().signalError(sourceStart, sourceEnd,
  227. "Intertype declared member types can only be static (compiler limitation)");
  228. return null;
  229. }
  230. ResolvedType declaringType = world.fromBinding(onTypeResolvedBinding).resolve(world.getWorld());
  231. if (declaringType.isRawType() || declaringType.isParameterizedType()) {
  232. declaringType = declaringType.getGenericType();
  233. }
  234. if (interTypeScope == null) {
  235. return null; // We encountered a problem building the scope, don't continue - error already reported
  236. }
  237. // TODO [inner] use the interTypeScope.getRecoveryAliases
  238. // TODO [inner] should mark it in the aspect as unreachable - it is not to be considered part of the aspect
  239. newMemberClassTypeMunger = new NewMemberClassTypeMunger(declaringType, new String(this.name));
  240. newMemberClassTypeMunger.setSourceLocation(new EclipseSourceLocation(compilationResult, sourceStart, sourceEnd));
  241. ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
  242. return new EclipseTypeMunger(world, newMemberClassTypeMunger, aspectType, null);
  243. }
  244. public char[] alternativeName() {
  245. return CharOperation.concatWith(onType.getTypeName(),'.');//onType.getLastToken();
  246. }
  247. }