|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- /* *******************************************************************
- * Copyright (c) 2010 Contributors
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors:
- * Andy Clement - SpringSource
- * ******************************************************************/
- package org.aspectj.ajdt.internal.compiler.ast;
-
- import java.lang.reflect.Modifier;
- import java.util.Collections;
-
- import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
- import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
- import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
- import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope;
- import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
- import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
- import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
- 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.NestedTypeBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
- import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
- import org.aspectj.weaver.AjAttribute;
- import org.aspectj.weaver.NewMemberClassTypeMunger;
- import org.aspectj.weaver.ResolvedType;
- import org.aspectj.weaver.ResolvedTypeMunger;
-
- /**
- * Represents an intertype member class declaration.
- *
- * @author Andy Clement
- * @since 1.6.9
- */
- public class IntertypeMemberClassDeclaration extends TypeDeclaration {
-
- // The target type for this inner class
- private TypeReference onType;
- private ReferenceBinding onTypeResolvedBinding;
- private NewMemberClassTypeMunger newMemberClassTypeMunger;
- protected InterTypeScope interTypeScope;
- // When set to true, the scope hierarchy for the field/method declaration has been correctly modified to include an intertype
- // scope which resolves things relative to the targeted type.
- private boolean scopeSetup = false;
-
- public IntertypeMemberClassDeclaration(CompilationResult compilationResult) {
- super(compilationResult);
- }
-
- public ResolvedTypeMunger getMunger() {
- return newMemberClassTypeMunger;
- }
-
- @Override
- public void resolve(ClassScope aspectScope) {
- resolveOnType(aspectScope);
- ensureScopeSetup();
- super.resolve(aspectScope);
- }
-
- /**
- * Bytecode generation for a member inner type
- */
- /*
- * public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) { if ((this.bits & ASTNode.HasBeenGenerated) !=
- * 0) { return; } try { Field f = ReferenceBinding.class.getDeclaredField("constantPoolName"); char[] name =
- * CharOperation.concat(onTypeResolvedBinding.constantPoolName(), binding.sourceName, '$'); f.setAccessible(true);
- * f.set(this.binding, name); } catch (Exception e) { e.printStackTrace(); } if (this.binding != null) { ((NestedTypeBinding)
- * this.binding).computeSyntheticArgumentSlotSizes(); } generateCode(enclosingClassFile); }
- */
- @Override
- public void resolve() {
- super.resolve();
- }
-
- @Override
- public void resolve(BlockScope blockScope) {
- throw new IllegalStateException();
- }
-
- @Override
- public void resolve(CompilationUnitScope upperScope) {
- throw new IllegalStateException();
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected void generateAttributes(ClassFile classFile) {
- // classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute()));
- super.generateAttributes(classFile);
- }
-
- public AjAttribute getAttribute() {
- // if there were problems then there is nothing to return
- if (newMemberClassTypeMunger == null) {
- return null;
- }
- return new AjAttribute.TypeMunger(newMemberClassTypeMunger);
- }
-
- /**
- * Called just before the compiler is going to start resolving elements of a declaration, this method adds an intertype scope so
- * that elements of the type targeted by the ITD can be resolved. For example, if type variables are referred to in the ontype
- * for the ITD, they have to be resolved against the ontype, not the aspect containing the ITD.
- */
- public void ensureScopeSetup() {
- if (scopeSetup) {
- return; // don't do it again
- }
- ClassScope scope = this.scope;
-
- // TODO [inner] ton of stuff related to parameterization support
-
- // if (ot instanceof ParameterizedQualifiedTypeReference) { // pr132349
- // ParameterizedQualifiedTypeReference pref = (ParameterizedQualifiedTypeReference) ot;
- // if (pref.typeArguments != null && pref.typeArguments.length != 0) {
- // boolean usingNonTypeVariableInITD = false;
- // // Check if any of them are not type variables
- // for (int i = 0; i < pref.typeArguments.length; i++) {
- // TypeReference[] refs = pref.typeArguments[i];
- // for (int j = 0; refs != null && j < refs.length; j++) {
- // TypeBinding tb = refs[j].getTypeBindingPublic(scope.parent);
- // if (!tb.isTypeVariable() && !(tb instanceof ProblemReferenceBinding)) {
- // usingNonTypeVariableInITD = true;
- // }
- //
- // }
- // }
- // if (usingNonTypeVariableInITD) {
- // scope.problemReporter().signalError(sourceStart, sourceEnd,
- // "Cannot make inter-type declarations on parameterized types");
- // // to prevent disgusting cascading errors after this problem - lets null out what leads to them (pr105038)
- // this.arguments = null;
- // this.returnType = new SingleTypeReference(TypeReference.VOID, 0L);
- //
- // this.ignoreFurtherInvestigation = true;
- // ReferenceBinding closestMatch = null;
- // rb = new ProblemReferenceBinding(ot.getParameterizedTypeName(), closestMatch, 0);
- // onType = null;
- // }
- // }
- //
- // }
-
- // // Work out the real base type
- // if (onType instanceof ParameterizedSingleTypeReference) {
- // ParameterizedSingleTypeReference pref = (ParameterizedSingleTypeReference) ot;
- // long pos = (((long) pref.sourceStart) << 32) | pref.sourceEnd;
- // ot = new SingleTypeReference(pref.token, pos);
- // } else if (ot instanceof ParameterizedQualifiedTypeReference) {
- // ParameterizedQualifiedTypeReference pref = (ParameterizedQualifiedTypeReference) ot;
- // long pos = (((long) pref.sourceStart) << 32) | pref.sourceEnd;
- // ot = new QualifiedTypeReference(pref.tokens, new long[] { pos });// SingleTypeReference(pref.Quatoken,pos);
- // }
-
- // resolve it
- // if (rb == null) {
- // rb = (ReferenceBinding) ot.getTypeBindingPublic(scope.parent);
- // }
-
- // pr203646 - if we have ended up with the raw type, get back to the underlying generic one.
- // if (rb.isRawType() && rb.isMemberType()) {
- // // if the real target type used a type variable alias then we can do this OK, but need to switch things around, we want
- // // the generic type
- // rb = ((RawTypeBinding) rb).type;
- // }
-
- // if (rb instanceof TypeVariableBinding) {
- // scope.problemReporter().signalError(sourceStart, sourceEnd,
- // "Cannot make inter-type declarations on type variables, use an interface and declare parents");
- // // to prevent disgusting cascading errors after this problem - lets null out what leads to them (pr105038)
- // this.arguments = null;
- // this.returnType = new SingleTypeReference(TypeReference.VOID, 0L);
- //
- // this.ignoreFurtherInvestigation = true;
- // ReferenceBinding closestMatch = null;
- // if (((TypeVariableBinding) rb).firstBound != null) {
- // closestMatch = ((TypeVariableBinding) rb).firstBound.enclosingType();
- // }
- // rb = new ProblemReferenceBinding(rb.compoundName, closestMatch, 0);
- // }
-
- // if resolution failed, give up - someone else is going to report an error
- // if (rb instanceof ProblemReferenceBinding) {
- // return;
- // }
- if (scope != null) {
- interTypeScope = new InterTypeScope(scope.parent, onTypeResolvedBinding, Collections.emptyList());
- // FIXME asc verify the choice of lines here...
- // Two versions of this next line.
- // First one tricks the JDT variable processing code so that it won't complain if
- // you refer to a type variable from a static ITD - it *is* a problem and it *will* be caught, but later and
- // by the AJDT code so we can put out a much nicer message.
- // scope.isStatic = (typeVariableAliases != null ? false : Modifier.isStatic(declaredModifiers));
- // this is the original version in case tricking the JDT causes grief (if you reinstate this variant, you
- // will need to change the expected messages output for some of the generic ITD tests)
- // scope.isStatic = Modifier.isStatic(declaredModifiers);
- // Use setter in order to also update member 'compilationUnitScope'
- scope.setParent(interTypeScope);
- }
- scopeSetup = true;
- }
-
- public void setOnType(TypeReference onType) {
- this.onType = onType;
- }
-
- private void resolveOnType(ClassScope cuScope) {
- if (onType == null || onTypeResolvedBinding != null) {
- return;
- } // error reported elsewhere.
-
- onTypeResolvedBinding = (ReferenceBinding) onType.getTypeBindingPublic(cuScope);
- if (!onTypeResolvedBinding.isValidBinding()) {
- cuScope.problemReporter().invalidType(onType, onTypeResolvedBinding);
- ignoreFurtherInvestigation = true;
- } else {
- // fix up the ITD'd type?
- if (this.binding != null) {
- ((NestedTypeBinding) this.binding).enclosingType = (SourceTypeBinding) onTypeResolvedBinding;
- }
- // this done at build type for the nested type now:
- // ((NestedTypeBinding) this.binding).compoundName = CharOperation.splitOn('.', "Basic$_".toCharArray());
- }
- }
-
- public EclipseTypeMunger build(ClassScope classScope) {
- EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
- resolveOnType(classScope);
- ensureScopeSetup();
-
- if (ignoreFurtherInvestigation) {
- return null;
- }
-
- if (onTypeResolvedBinding.isInterface() || onTypeResolvedBinding.isEnum() || onTypeResolvedBinding.isAnnotationType()) {
- scope.problemReporter().signalError(
- sourceStart,
- sourceEnd,
- "Cannot declare new member type on '" + onType.toString()
- + "'. New member types can only be specified on classes (compiler limitation)");
- return null;
- }
-
- if (!Modifier.isStatic(modifiers)) {
- scope.problemReporter().signalError(sourceStart, sourceEnd,
- "Intertype declared member types can only be static (compiler limitation)");
- return null;
- }
-
- ResolvedType declaringType = world.fromBinding(onTypeResolvedBinding).resolve(world.getWorld());
- if (declaringType.isRawType() || declaringType.isParameterizedType()) {
- declaringType = declaringType.getGenericType();
- }
-
- if (interTypeScope == null) {
- return null; // We encountered a problem building the scope, don't continue - error already reported
- }
-
- // TODO [inner] use the interTypeScope.getRecoveryAliases
- // TODO [inner] should mark it in the aspect as unreachable - it is not to be considered part of the aspect
- newMemberClassTypeMunger = new NewMemberClassTypeMunger(declaringType, new String(this.name));
- newMemberClassTypeMunger.setSourceLocation(new EclipseSourceLocation(compilationResult, sourceStart, sourceEnd));
- ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
- return new EclipseTypeMunger(world, newMemberClassTypeMunger, aspectType, null);
- }
-
- public char[] alternativeName() {
- return CharOperation.concatWith(onType.getTypeName(),'.');//onType.getLastToken();
- }
- }
|