org.aspectj.ajdt.internal.compiler.ast.AstUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
Tools from the AspectJ project
/* *******************************************************************
* 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.ArrayList;
import java.util.List;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.IAttribute;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.patterns.WildTypePattern;
public class AstUtil {
private AstUtil() {
}
public static void addMethodBinding(SourceTypeBinding sourceType, MethodBinding method) {
int len = sourceType.methods.length;
MethodBinding[] temp = new MethodBinding[len + 1];
System.arraycopy(sourceType.methods, 0, temp, 0, len);
temp[len] = method;
sourceType.methods = temp;
}
public static void addMethodDeclaration(TypeDeclaration typeDec, AbstractMethodDeclaration dec) {
AbstractMethodDeclaration[] methods = typeDec.methods;
int len = methods.length;
AbstractMethodDeclaration[] newMethods = new AbstractMethodDeclaration[len + 1];
System.arraycopy(methods, 0, newMethods, 0, len);
newMethods[len] = dec;
typeDec.methods = newMethods;
}
public static Argument makeFinalArgument(char[] name, TypeBinding typeBinding) {
long pos = 0; // XXX encode start and end location
LocalVariableBinding binding = new LocalVariableBinding(name, typeBinding, Modifier.FINAL, true);
Argument ret = new Argument(name, pos, makeTypeReference(typeBinding), Modifier.FINAL);
ret.binding = binding;
return ret;
}
public static TypeReference makeTypeReference(TypeBinding binding) {
// ??? does this work for primitives
QualifiedTypeReference ref = new QualifiedTypeReference(new char[][] { binding.sourceName() }, new long[] { 0 }); // ???
ref.resolvedType = binding;
ref.constant = Constant.NotAConstant;
return ref;
}
public static NameReference makeNameReference(TypeBinding binding) {
char[][] name = new char[][] { binding.sourceName() };
long[] dummyPositions = new long[name.length];
QualifiedNameReference ref = new QualifiedNameReference(name, dummyPositions, 0, 0);
ref.binding = binding;
ref.constant = Constant.NotAConstant;
return ref;
}
public static ReturnStatement makeReturnStatement(Expression expr) {
return new ReturnStatement(expr, 0, 0);
}
public static MethodDeclaration makeMethodDeclaration(MethodBinding binding) {
MethodDeclaration ret = new MethodDeclaration(null);
ret.binding = binding;
int nargs = binding.parameters.length;
ret.arguments = new Argument[nargs];
for (int i = 0; i < nargs; i++) {
ret.arguments[i] = makeFinalArgument(("arg" + i).toCharArray(), binding.parameters[i]);
}
return ret;
}
public static void setStatements(MethodDeclaration ret, List statements) {
ret.statements = (Statement[]) statements.toArray(new Statement[0]);
}
public static SingleNameReference makeLocalVariableReference(LocalVariableBinding binding) {
SingleNameReference ret = new SingleNameReference(binding.name, 0);
ret.binding = binding;
// ret.codegenBinding = binding;
ret.constant = Constant.NotAConstant;
ret.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
ret.bits |= Binding.VARIABLE;
return ret;
}
public static SingleNameReference makeResolvedLocalVariableReference(LocalVariableBinding binding) {
SingleNameReference ret = new SingleNameReference(binding.name, 0);
ret.binding = binding;
// ret.codegenBinding = binding;
ret.constant = Constant.NotAConstant;
ret.bits &= ~ASTNode.RestrictiveFlagMASK; // clear bits
ret.bits |= Binding.LOCAL;
return ret;
}
public static int makePublic(int modifiers) {
return makePackageVisible(modifiers) | ClassFileConstants.AccPublic;
}
public static int makePackageVisible(int modifiers) {
modifiers &= ~(ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected);
return modifiers;
}
public static CompilationUnitScope getCompilationUnitScope(Scope scope) {
if (scope instanceof CompilationUnitScope) {
return (CompilationUnitScope) scope;
}
return getCompilationUnitScope(scope.parent);
}
public static void generateParameterLoads(TypeBinding[] parameters, CodeStream codeStream) {
int paramIndex = 0;
int varIndex = 0;
while (paramIndex < parameters.length) {
TypeBinding param = parameters[paramIndex++];
codeStream.load(param, varIndex);
varIndex += slotsNeeded(param);
}
}
public static void generateParameterLoads(TypeBinding[] parameters, CodeStream codeStream, int offset) {
int paramIndex = 0;
int varIndex = offset;
while (paramIndex < parameters.length) {
TypeBinding param = parameters[paramIndex++];
codeStream.load(param, varIndex);
varIndex += slotsNeeded(param);
}
}
public static void generateReturn(TypeBinding returnType, CodeStream codeStream) {
if (returnType.id == TypeIds.T_void) {
codeStream.return_();
} else if (returnType.isBaseType()) {
switch (returnType.id) {
case TypeIds.T_boolean:
case TypeIds.T_int:
case TypeIds.T_byte:
case TypeIds.T_short:
case TypeIds.T_char:
codeStream.ireturn();
break;
case TypeIds.T_float:
codeStream.freturn();
break;
case TypeIds.T_long:
codeStream.lreturn();
break;
case TypeIds.T_double:
codeStream.dreturn();
break;
default:
throw new RuntimeException("huh");
}
} else {
codeStream.areturn();
}
}
// XXX this could be inconsistent for wierd case, i.e. a class named "java_lang_String"
public static char[] makeMangledName(ReferenceBinding type) {
return CharOperation.concatWith(type.compoundName, '_');
}
public static final char[] PREFIX = "ajc".toCharArray();
// XXX not efficient
public static char[] makeAjcMangledName(char[] kind, ReferenceBinding type, char[] name) {
return CharOperation.concat(CharOperation.concat(PREFIX, new char[] { '$' }, kind), '$', makeMangledName(type), '$', name);
}
public static char[] makeAjcMangledName(char[] kind, char[] p, char[] name) {
return CharOperation.concat(CharOperation.concat(PREFIX, new char[] { '$' }, kind), '$', p, '$', name);
}
public static List getAjSyntheticAttribute() {
List ret = new ArrayList<>(1);
ret.add(new EclipseAttributeAdapter(new AjAttribute.AjSynthetic()));
return ret;
}
public static long makeLongPos(int start, int end) {
return (long) end | ((long) start << 32);
}
public static char[][] getCompoundName(String string) {
return WildTypePattern.splitNames(string, true);
}
public static TypeBinding[] insert(TypeBinding first, TypeBinding[] rest) {
if (rest == null) {
return new TypeBinding[] { first };
}
int len = rest.length;
TypeBinding[] ret = new TypeBinding[len + 1];
ret[0] = first;
System.arraycopy(rest, 0, ret, 1, len);
return ret;
}
public static Argument[] insert(Argument first, Argument[] rest) {
if (rest == null) {
return new Argument[] { first };
}
int len = rest.length;
Argument[] ret = new Argument[len + 1];
ret[0] = first;
System.arraycopy(rest, 0, ret, 1, len);
return ret;
}
public static TypeParameter[] insert(TypeParameter first, TypeParameter[] rest) {
if (rest == null) {
return new TypeParameter[]{first};
}
int len = rest.length;
TypeParameter[] ret = new TypeParameter[len + 1];
ret[0] = first;
System.arraycopy(rest, 0, ret, 1, len);
return ret;
}
public static TypeVariableBinding[] insert(TypeVariableBinding first, TypeVariableBinding[] rest) {
if (rest == null) {
return new TypeVariableBinding[]{first};
}
int len = rest.length;
TypeVariableBinding[] ret = new TypeVariableBinding[len + 1];
ret[0] = first;
System.arraycopy(rest, 0, ret, 1, len);
return ret;
}
public static TypeVariableBinding[] insert(TypeVariableBinding[] first, TypeVariableBinding[] rest) {
if (rest == null) {
TypeVariableBinding[] ret = new TypeVariableBinding[first.length];
System.arraycopy(first, 0, ret, 0, first.length);
return ret;
}
int len = rest.length;
TypeVariableBinding[] ret = new TypeVariableBinding[first.length+len];
System.arraycopy(first,0,ret,0,first.length);
System.arraycopy(rest,0,ret,first.length,len);
return ret;
}
public static Expression[] insert(Expression first, Expression[] rest) {
if (rest == null) {
return new Expression[] { first };
}
int len = rest.length;
Expression[] ret = new Expression[len + 1];
ret[0] = first;
System.arraycopy(rest, 0, ret, 1, len);
return ret;
}
public static Argument[] copyArguments(Argument[] inArgs) {
// Lets do a proper copy
if (inArgs == null)
return new Argument[] {};
Argument[] outArgs = new Argument[inArgs.length];
for (int i = 0; i < inArgs.length; i++) {
Argument argument = inArgs[i];
outArgs[i] = new Argument(argument.name, 0, argument.type, argument.modifiers);
}
return outArgs;
// if (inArgs == null) return new Argument[] {};
// int len = inArgs.length;
// Argument[] outArgs = new Argument[len];
// //??? we're not sure whether or not copying these is okay
// System.arraycopy(inArgs, 0, outArgs, 0, len);
// return outArgs;
}
public static Statement[] remove(int i, Statement[] statements) {
int len = statements.length;
Statement[] ret = new Statement[len - 1];
System.arraycopy(statements, 0, ret, 0, i);
System.arraycopy(statements, i + 1, ret, i, len - i - 1);
return ret;
}
public static int slotsNeeded(TypeBinding type) {
if (type == TypeBinding.DOUBLE || type == TypeBinding.LONG)
return 2;
else
return 1;
}
public static void replaceMethodBinding(MessageSend send, MethodBinding newBinding) {
send.binding =/* send.codegenBinding =*/ newBinding;
send.setActualReceiverType(newBinding.declaringClass);
}
}