org.aspectj.ajdt.internal.core.builder.AsmElementFormatter 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 v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* PARC initial implementation
* Alexandre Vasseur support for @AJ style
* ******************************************************************/
package org.aspectj.ajdt.internal.core.builder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.aspectj.ajdt.internal.compiler.ast.AdviceDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.DeclareDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.InterTypeConstructorDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.InterTypeDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.InterTypeFieldDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.PointcutDeclaration;
import org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment;
import org.aspectj.asm.IProgramElement;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.weaver.AdviceKind;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.model.AsmRelationshipUtils;
import org.aspectj.weaver.patterns.DeclareAnnotation;
import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
import org.aspectj.weaver.patterns.DeclareParents;
import org.aspectj.weaver.patterns.DeclarePrecedence;
import org.aspectj.weaver.patterns.DeclareSoft;
import org.aspectj.weaver.patterns.TypePattern;
import org.aspectj.weaver.patterns.TypePatternList;
/**
* @author Mik Kersten
*/
public class AsmElementFormatter {
private final static String ASPECTJ_ANNOTATION_PACKAGE = "org.aspectj.lang.annotation";
private final static char PACKAGE_INITIAL_CHAR = ASPECTJ_ANNOTATION_PACKAGE.charAt(0);
public void genLabelAndKind(MethodDeclaration methodDeclaration, IProgramElement node) {
if (methodDeclaration instanceof AdviceDeclaration) {
AdviceDeclaration ad = (AdviceDeclaration) methodDeclaration;
node.setKind(IProgramElement.Kind.ADVICE);
if (ad.kind == AdviceKind.Around) {
node.setCorrespondingType(ad.returnType.toString()); // returnTypeToString(0));
}
StringBuffer details = new StringBuffer();
if (ad.pointcutDesignator != null) {
details.append(AsmRelationshipUtils.genPointcutDetails(ad.pointcutDesignator.getPointcut()));
} else {
details.append(AsmRelationshipUtils.POINTCUT_ABSTRACT);
}
node.setName(ad.kind.toString());
// if (details.length()!=0)
node.setDetails(details.toString());
setParameters(methodDeclaration, node);
} else if (methodDeclaration instanceof PointcutDeclaration) {
// PointcutDeclaration pd = (PointcutDeclaration) methodDeclaration;
node.setKind(IProgramElement.Kind.POINTCUT);
node.setName(translatePointcutName(new String(methodDeclaration.selector)));
setParameters(methodDeclaration, node);
} else if (methodDeclaration instanceof DeclareDeclaration) {
DeclareDeclaration declare = (DeclareDeclaration) methodDeclaration;
String name = AsmRelationshipUtils.DEC_LABEL + " ";
if (declare.declareDecl instanceof DeclareErrorOrWarning) {
DeclareErrorOrWarning deow = (DeclareErrorOrWarning) declare.declareDecl;
if (deow.isError()) {
node.setKind(IProgramElement.Kind.DECLARE_ERROR);
name += AsmRelationshipUtils.DECLARE_ERROR;
} else {
node.setKind(IProgramElement.Kind.DECLARE_WARNING);
name += AsmRelationshipUtils.DECLARE_WARNING;
}
node.setName(name);
node.setDetails("\"" + AsmRelationshipUtils.genDeclareMessage(deow.getMessage()) + "\"");
} else if (declare.declareDecl instanceof DeclareParents) {
node.setKind(IProgramElement.Kind.DECLARE_PARENTS);
DeclareParents dp = (DeclareParents) declare.declareDecl;
node.setName(name + AsmRelationshipUtils.DECLARE_PARENTS);
String kindOfDP = null;
StringBuffer details = new StringBuffer("");
TypePattern[] newParents = dp.getParents().getTypePatterns();
for (int i = 0; i < newParents.length; i++) {
TypePattern tp = newParents[i];
UnresolvedType tx = tp.getExactType();
if (kindOfDP == null) {
kindOfDP = "implements ";
try {
ResolvedType rtx = tx.resolve(((AjLookupEnvironment) declare.scope.environment()).factory.getWorld());
if (!rtx.isInterface()) {
kindOfDP = "extends ";
}
} catch (Throwable t) {
// What can go wrong???? who knows!
}
}
String typename = tp.toString();
if (typename.lastIndexOf(".") != -1) {
typename = typename.substring(typename.lastIndexOf(".") + 1);
}
details.append(typename);
if ((i + 1) < newParents.length) {
details.append(",");
}
}
node.setDetails(kindOfDP + details.toString());
} else if (declare.declareDecl instanceof DeclareSoft) {
node.setKind(IProgramElement.Kind.DECLARE_SOFT);
DeclareSoft ds = (DeclareSoft) declare.declareDecl;
node.setName(name + AsmRelationshipUtils.DECLARE_SOFT);
node.setDetails(genTypePatternLabel(ds.getException()));
} else if (declare.declareDecl instanceof DeclarePrecedence) {
node.setKind(IProgramElement.Kind.DECLARE_PRECEDENCE);
DeclarePrecedence ds = (DeclarePrecedence) declare.declareDecl;
node.setName(name + AsmRelationshipUtils.DECLARE_PRECEDENCE);
node.setDetails(genPrecedenceListLabel(ds.getPatterns()));
} else if (declare.declareDecl instanceof DeclareAnnotation) {
DeclareAnnotation deca = (DeclareAnnotation) declare.declareDecl;
String thekind = deca.getKind().toString();
node.setName(name + "@" + thekind.substring(3));
if (deca.getKind() == DeclareAnnotation.AT_CONSTRUCTOR) {
node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_CONSTRUCTOR);
} else if (deca.getKind() == DeclareAnnotation.AT_FIELD) {
node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_FIELD);
} else if (deca.getKind() == DeclareAnnotation.AT_METHOD) {
node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_METHOD);
} else if (deca.getKind() == DeclareAnnotation.AT_TYPE) {
node.setKind(IProgramElement.Kind.DECLARE_ANNOTATION_AT_TYPE);
}
node.setDetails(genDecaLabel(deca));
} else {
node.setKind(IProgramElement.Kind.ERROR);
node.setName(AsmRelationshipUtils.DECLARE_UNKNONWN);
}
} else if (methodDeclaration instanceof InterTypeDeclaration) {
InterTypeDeclaration itd = (InterTypeDeclaration) methodDeclaration;
String fqname = itd.getOnType().toString();
if (fqname.indexOf(".") != -1) {
// TODO the string handling round here is embarrassing
node.addFullyQualifiedName(fqname + "." + new String(itd.getDeclaredSelector()));
fqname = fqname.substring(fqname.lastIndexOf(".") + 1);
}
String name = fqname + "." + new String(itd.getDeclaredSelector());
if (methodDeclaration instanceof InterTypeFieldDeclaration) {
node.setKind(IProgramElement.Kind.INTER_TYPE_FIELD);
node.setName(name);
} else if (methodDeclaration instanceof InterTypeMethodDeclaration) {
node.setKind(IProgramElement.Kind.INTER_TYPE_METHOD);
node.setName(name);
} else if (methodDeclaration instanceof InterTypeConstructorDeclaration) {
node.setKind(IProgramElement.Kind.INTER_TYPE_CONSTRUCTOR);
// StringBuffer argumentsSignature = new StringBuffer("fubar");
// argumentsSignature.append("(");
// if (methodDeclaration.arguments!=null && methodDeclaration.arguments.length>1) {
//
// for (int i = 1;i 0; i--) {
handleSig.append("\\[");
}
handleSig.append('Q').append(pstr.token);
TypeReference[] typeRefs = pstr.typeArguments;
if (typeRefs != null && typeRefs.length > 0) {
handleSig.append("\\<");
for (int i = 0; i < typeRefs.length; i++) {
TypeReference typeR = typeRefs[i];
TypeBinding typeB = typeR.resolvedType;
if (typeB == null) {
typeB = typeR.resolveType(scope);
}
createHandleSigForReference(typeR, typeB, scope, handleSig);
}
handleSig.append('>');
}
handleSig.append(';');
} else if (ref instanceof ArrayTypeReference) {
ArrayTypeReference atr = (ArrayTypeReference) ref;
for (int i = 0; i < atr.dimensions; i++) {
handleSig.append("\\[");
}
TypeBinding typeB = atr.resolvedType;
if (typeB == null) {
typeB = atr.resolveType(scope);
}
if (typeB.leafComponentType().isBaseType()) {
handleSig.append(tb.leafComponentType().signature());
} else {
handleSig.append('Q').append(atr.token).append(';');
}
} else if (ref instanceof SingleTypeReference) {
SingleTypeReference str = (SingleTypeReference) ref;
if (tb.isBaseType()) {
handleSig.append(tb.signature());
} else {
handleSig.append('Q').append(str.token).append(';');
}
} else if (ref instanceof ParameterizedQualifiedTypeReference) {
ParameterizedQualifiedTypeReference pstr = (ParameterizedQualifiedTypeReference) ref;
char[][] tokens = pstr.tokens;
for (int i = pstr.dimensions(); i > 0; i--) {
handleSig.append("\\[");
}
handleSig.append('Q');
for (int i = 0; i < tokens.length; i++) {
if (i > 0) {
handleSig.append('.');
}
handleSig.append(tokens[i]);
TypeReference[] typeRefs = pstr.typeArguments[i];
if (typeRefs != null && typeRefs.length > 0) {
handleSig.append("\\<");
for (int j = 0; j < typeRefs.length; j++) {
TypeReference typeR = typeRefs[j];
TypeBinding typeB = typeR.resolvedType;
if (typeB == null) {
typeB = typeR.resolveType(scope);
}
createHandleSigForReference(typeR, typeB, scope, handleSig);
}
handleSig.append('>');
}
}
handleSig.append(';');
} else if (ref instanceof ArrayQualifiedTypeReference) {
ArrayQualifiedTypeReference atr = (ArrayQualifiedTypeReference) ref;
for (int i = 0; i < atr.dimensions(); i++) {
handleSig.append("\\[");
}
TypeBinding typeB = atr.resolvedType;
if (typeB == null) {
typeB = atr.resolveType(scope);
}
if (typeB.leafComponentType().isBaseType()) {
handleSig.append(tb.leafComponentType().signature());
} else {
char[][] tokens = atr.tokens;
handleSig.append('Q');
for (int i = 0; i < tokens.length; i++) {
if (i > 0) {
handleSig.append('.');
}
handleSig.append(tokens[i]);
}
handleSig.append(';');
}
} else if (ref instanceof QualifiedTypeReference) {
QualifiedTypeReference qtr = (QualifiedTypeReference) ref;
char[][] tokens = qtr.tokens;
handleSig.append('Q');
for (int i = 0; i < tokens.length; i++) {
if (i > 0) {
handleSig.append('.');
}
handleSig.append(tokens[i]);
}
handleSig.append(';');
} else {
throw new RuntimeException("Cant handle " + ref.getClass());
}
}
public void setParameters(AbstractMethodDeclaration md, IProgramElement pe) {
Argument[] argArray = md.arguments;
if (argArray == null) {
pe.setParameterNames(Collections.emptyList());
pe.setParameterSignatures(Collections.emptyList(), Collections.emptyList());
} else {
List names = new ArrayList();
List paramSigs = new ArrayList();
List paramSourceRefs = new ArrayList();
boolean problemWithSourceRefs = false;
for (int i = 0; i < argArray.length; i++) {
String argName = new String(argArray[i].name);
// String argType = ""; // pr135052
if (acceptArgument(argName, argArray[i].type.toString())) {
TypeReference typeR = argArray[i].type;
if (typeR != null && md.scope != null) {
TypeBinding typeB = typeR.resolvedType;
if (typeB == null) {
typeB = typeR.resolveType(md.scope);
}
// This code will conjure up a 'P' style signature:
// EclipseFactory factory = EclipseFactory.fromScopeLookupEnvironment(md.scope);
// UnresolvedType ut = factory.fromBinding(typeB);
// paramSigs.add(ut.getSignature().toCharArray());
paramSigs.add(typeB.genericTypeSignature());
String hsig = handleSigForReference(typeR, typeB, md.scope);
if (hsig == null) {
problemWithSourceRefs = true;
} else {
paramSourceRefs.add(hsig);
}
}
names.add(argName);
}
}
pe.setParameterNames(names);
if (!paramSigs.isEmpty()) {
pe.setParameterSignatures(paramSigs, (problemWithSourceRefs ? null : paramSourceRefs));
}
}
}
// TODO: fix this way of determing ajc-added arguments, make subtype of Argument with extra info
private boolean acceptArgument(String name, String type) {
if (name.charAt(0) != 'a' && type.charAt(0) != PACKAGE_INITIAL_CHAR) {
return true;
}
return !name.startsWith("ajc$this_") && !type.equals("org.aspectj.lang.JoinPoint.StaticPart")
&& !type.equals("org.aspectj.lang.JoinPoint") && !type.equals("org.aspectj.runtime.internal.AroundClosure");
}
public String genTypePatternLabel(TypePattern tp) {
final String TYPE_PATTERN_LITERAL = "";
String label;
UnresolvedType typeX = tp.getExactType();
if (!ResolvedType.isMissing(typeX)) {
label = typeX.getName();
if (tp.isIncludeSubtypes()) {
label += "+";
}
} else {
label = TYPE_PATTERN_LITERAL;
}
return label;
}
// // TODO:
// private String translateAdviceName(String label) {
// if (label.indexOf("before") != -1) return "before";
// if (label.indexOf("returning") != -1) return "after returning";
// if (label.indexOf("after") != -1) return "after";
// if (label.indexOf("around") != -1) return "around";
// else return "";
// }
// // !!! move or replace
// private String translateDeclareName(String name) {
// int colonIndex = name.indexOf(":");
// if (colonIndex != -1) {
// return name.substring(0, colonIndex);
// } else {
// return name;
// }
// }
// !!! move or replace
// private String translateInterTypeDecName(String name) {
// int index = name.lastIndexOf('$');
// if (index != -1) {
// return name.substring(index+1);
// } else {
// return name;
// }
// }
// !!! move or replace
private String translatePointcutName(String name) {
int index = name.indexOf("$$") + 2;
int endIndex = name.lastIndexOf('$');
if (index != -1 && endIndex != -1) {
return name.substring(index, endIndex);
} else {
return name;
}
}
}