All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.aspectj.ajdt.internal.compiler.ast.SuperFixerVisitor Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/* *******************************************************************
 * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
 * 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:
 *     PARC     initial implementation
 * ******************************************************************/

package org.aspectj.ajdt.internal.compiler.ast;

import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;

import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.compiler.lookup.InterTypeMethodBinding;
import org.aspectj.asm.internal.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.weaver.NameMangler;
import org.aspectj.weaver.ResolvedMember;

/**
 * Takes a method that already has the three extra parameters thisJoinPointStaticPart, thisJoinPoint and
 * thisEnclosingJoinPointStaticPart
 */

public class SuperFixerVisitor extends ASTVisitor {
	Set superMethodsCalled = new HashSet();
	AbstractMethodDeclaration method;
	ReferenceBinding targetClass;
	private int depthCounter = 0; // Keeps track of whether we are inside any nested local type declarations

	SuperFixerVisitor(AbstractMethodDeclaration method, ReferenceBinding targetClass) {
		this.method = method;
		this.targetClass = targetClass;
	}

	private static final char[] ctor = "".toCharArray();

	public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
		if (localTypeDeclaration.binding instanceof LocalTypeBinding) {
			if (((LocalTypeBinding)localTypeDeclaration.binding).isAnonymousType()) {
				localTypeDeclaration.binding.modifiers |=Modifier.PUBLIC;
				MethodBinding[] bindings = localTypeDeclaration.binding.methods;
				if (bindings!=null) {
					for (MethodBinding binding : bindings) {
						if (CharOperation.equals(binding.selector, ctor)) {
							binding.modifiers |= Modifier.PUBLIC;
						}
					}
				}
//				localTypeDeclaration.modifiers|=Modifier.PUBLIC;
			}
		}
		depthCounter++;
		return super.visit(localTypeDeclaration, scope);
	}

	public void endVisit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
		depthCounter--;
	}

	public void endVisit(MessageSend call, BlockScope scope) {
		// System.out.println("endVisit: " + call);
		// an error has already occurred
		if (call.binding/*codegenBinding*/ == null)
			return;

		MethodBinding superBinding = call.binding/*codegenBinding*/;
		if (superBinding instanceof ProblemMethodBinding) {
			return;
		}
		// InterTypeMethodBindings are always statically bound, so there's no
		// need to treat super calls specially here
		if (superBinding instanceof InterTypeMethodBinding) {
			return;
			// InterTypeMethodBinding m = (InterTypeMethodBinding)superBinding;
			// if (m.postDispatchMethod != null) {
			// call.binding = m.postDispatchMethod;
			// }
			// return;
		}
		if (superBinding instanceof ParameterizedMethodBinding) {
			superBinding = ((ParameterizedMethodBinding) superBinding).original();
		}
		EclipseFactory factory = ((AjLookupEnvironment) method.scope.environment()).factory;
		if (depthCounter != 0 && targetClass.isInterface()) {// pr198196 - when calling MarkerInterface.super.XXX()
			if (call.isSuperAccess() && !call.binding.isStatic()) {
				MethodScope currentMethodScope = scope.methodScope();
				SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
				FieldBinding field = sourceType.addSyntheticFieldForInnerclass(targetClass);
				call.receiver = new KnownFieldReference(field, call.receiver.sourceStart, call.receiver.sourceEnd);
			} else {
				return;
			}
		} else if (depthCounter == 0) { // Allow case testSuperItds_pr198196_2/3

			char[] accessName;
			if (call.isSuperAccess() && !call.binding.isStatic()) {
				call.receiver = new ThisReference(call.receiver.sourceStart, call.receiver.sourceEnd);
				accessName = NameMangler.superDispatchMethod(factory.fromBinding(targetClass), new String(superBinding.selector))
						.toCharArray();
			} else if (call.receiver.isThis() && call.binding.isProtected() && !call.binding.isStatic()) {
				// XXX this is a hack that violates some binary compatibility rules
				ReferenceBinding superBindingDeclaringClass = superBinding.declaringClass;
				if (superBindingDeclaringClass.isParameterizedType()) {
					superBindingDeclaringClass = ((ParameterizedTypeBinding) superBindingDeclaringClass).type;
				}
				if (superBindingDeclaringClass.equals(targetClass)) {
					accessName = NameMangler.protectedDispatchMethod(factory.fromBinding(targetClass),
							new String(superBinding.selector)).toCharArray();
				} else {
					accessName = NameMangler.superDispatchMethod(factory.fromBinding(targetClass),
							new String(superBinding.selector)).toCharArray();
				}
			} else {
				return;
			}

			// ??? do we want these to be unique
			MethodBinding superAccessBinding = new MethodBinding(ClassFileConstants.AccPublic, accessName, superBinding.returnType,
					superBinding.parameters, superBinding.thrownExceptions, targetClass);

			AstUtil.replaceMethodBinding(call, superAccessBinding);
		} else {
			return;
		}
		ResolvedMember targetMember = null;
		if (superBinding.declaringClass.isParameterizedType()) { // pr206911
			targetMember = factory.makeResolvedMember(superBinding, ((ParameterizedTypeBinding) superBinding.declaringClass)
					.genericType());
		} else {
			targetMember = factory.makeResolvedMember(superBinding);
		}
		superMethodsCalled.add(targetMember);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy