Browse Source

Revised and added tests for ASM containment hierarchy.

tags/V1_1_1
mkersten 21 years ago
parent
commit
5594a6579a

+ 7
- 1
ajde/src/org/aspectj/ajde/ui/AbstractIconRegistry.java View File

@@ -107,7 +107,11 @@ public abstract class AbstractIconRegistry {
return ASPECT;
} else if (kind == ProgramElementNode.Kind.INITIALIZER) {
return INITIALIZER;
} else if (kind == ProgramElementNode.Kind.INTRODUCTION) {
} else if (kind == ProgramElementNode.Kind.INTER_TYPE_CONSTRUCTOR) {
return INTRODUCTION;
} else if (kind == ProgramElementNode.Kind.INTER_TYPE_FIELD) {
return INTRODUCTION;
} else if (kind == ProgramElementNode.Kind.INTER_TYPE_METHOD) {
return INTRODUCTION;
} else if (kind == ProgramElementNode.Kind.CONSTRUCTOR) {
return CONSTRUCTOR;
@@ -127,6 +131,8 @@ public abstract class AbstractIconRegistry {
return DECLARE_ERROR;
} else if (kind == ProgramElementNode.Kind.DECLARE_SOFT) {
return DECLARE_SOFT;
} else if (kind == ProgramElementNode.Kind.DECLARE_PRECEDENCE) {
return DECLARE_SOFT;
} else if (kind == ProgramElementNode.Kind.CODE) {
return CODE;
} else if (kind == ProgramElementNode.Kind.ERROR) {

+ 42
- 13
ajde/testdata/examples/coverage/ModelCoverage.java View File

@@ -15,6 +15,11 @@ class Point {
public void setX(int x) { this.x = x; }
public int changeX(int x) {
this.x = x;
return x;
}
void doIt() {
try {
File f = new File(".");
@@ -27,6 +32,10 @@ class Point {
}
}

class SubPoint extends Point { }

class Line { }

aspect AdvisesRelationCoverage {
before(): execution(*..*.new(..)) { }
before(): get(int *.*) { }
@@ -40,27 +49,47 @@ aspect AdvisesRelationCoverage {
before(): within(*) && execution(Point.new()) { }
}

aspect AdviceNamingCoverage {
pointcut named(): call(* *.mumble());
pointcut namedWithOneArg(int i): call(int Point.changeX(int)) && args(i);
pointcut namedWithArgs(int i, int j): set(int Point.x) && args(i, j);

after(): named() { }
after(int i, int j) returning: namedWithArgs(i, j) { }
after() throwing: named() { }
after(): named() { }
before(): named() { }
int around(int i): namedWithOneArg(i) { return i;}
int around(int i) throws SizeException: namedWithOneArg(i) { return proceed(i); }
before(): named() { }
before(): call(* *.mumble()) { }
}
aspect InterTypeDecCoverage {

pointcut illegalNewFigElt(): call(Point.new(..)) && !withincode(* *.doIt(..));

declare error: illegalNewFigElt():
"Illegal figure element constructor call.";

declare warning: illegalNewFigElt():
"Illegal figure element constructor call.";
declare error: illegalNewFigElt(): "Illegal constructor call.";
declare warning: illegalNewFigElt(): "Illegal constructor call.";

declare parents: Point extends java.io.Serializable;

declare parents: Point implements java.util.Observable;

//declare soft: Point: call(* *(..));

public String Point.getName() { return "xxx"; }

public int Point.xxx = 0;
declare parents: Point+ implements java.util.Observable;
declare parents: Point && Line implements java.util.Observable;
declare soft: SizeException : call(* Point.getX());
declare precedence: AdviceCoverage, InterTypeDecCoverage, *;
public int Point.xxx = 0;
public int Point.check(int i, Line l) { return 1 + i; }
// public Line.new(String s) { }
}

class SizeException extends Exception { }

aspect AdviceCoverage {

}

BIN
ajde/testdata/examples/coverage/coverage.ajsym View File


+ 2
- 1
ajde/testsrc/org/aspectj/ajde/AjdeTestCase.java View File

@@ -36,7 +36,7 @@ public class AjdeTestCase extends TestCase {
/**
* Waits on the build complete.
*/
protected void doSynchronousBuild(String configFilePath) {
protected boolean doSynchronousBuild(String configFilePath) {
testerBuildListener.reset();
File configFile = openFile(configFilePath);
Ajde.getDefault().getBuildManager().build(configFile.getAbsolutePath());
@@ -45,6 +45,7 @@ public class AjdeTestCase extends TestCase {
Thread.sleep(300);
} catch (InterruptedException ie) { }
}
return testerBuildListener.getBuildSucceeded();
}

protected void setUp(String testDataPath) throws Exception {

+ 2
- 0
ajde/testsrc/org/aspectj/ajde/AjdeTests.java View File

@@ -27,6 +27,8 @@ public class AjdeTests extends TestCase {
suite.addTestSuite(StructureModelTest.class);
suite.addTestSuite(VersionTest.class);
suite.addTestSuite(CompilerMessagesTest.class);
suite.addTestSuite(AsmDeclarationsTest.class);
//$JUnit-END$
return suite;
}

+ 141
- 0
ajde/testsrc/org/aspectj/ajde/AsmDeclarationsTest.java View File

@@ -0,0 +1,141 @@

/* *******************************************************************
* 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 Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* ******************************************************************/

package org.aspectj.ajde;

import java.util.Iterator;

import org.aspectj.ajdt.internal.core.builder.AsmNodeFormatter;
import org.aspectj.asm.*;
import org.aspectj.asm.ProgramElementNode.Kind;


public class AsmDeclarationsTest extends AjdeTestCase {

private StructureModel model = null;
private static final String CONFIG_FILE_PATH = "../examples/coverage/coverage.lst";
private static final int DEC_MESSAGE_LENGTH = AsmNodeFormatter.MAX_MESSAGE_LENGTH;

public AsmDeclarationsTest(String name) {
super(name);
}

public void testDeclares() {
ProgramElementNode node = (ProgramElementNode)model.getRoot();
assertNotNull(node);
ProgramElementNode aspect = StructureModelManager.getDefault().getStructureModel().findNodeForClass(null, "InterTypeDecCoverage");
assertNotNull(aspect);
String decErrMessage = "declare error: Illegal construct..";
ProgramElementNode decErrNode = model.findNode(aspect, ProgramElementNode.Kind.DECLARE_ERROR, decErrMessage);
assertNotNull(decErrNode);
assertEquals(decErrNode.getName(), decErrMessage);
String decWarnMessage = "declare warning: Illegal construct..";
ProgramElementNode decWarnNode = model.findNode(aspect, ProgramElementNode.Kind.DECLARE_WARNING, decWarnMessage);
assertNotNull(decWarnNode);
assertEquals(decWarnNode.getName(), decWarnMessage);
String decParentsMessage = "declare parents: Point";
ProgramElementNode decParentsNode = model.findNode(aspect, ProgramElementNode.Kind.DECLARE_PARENTS, decParentsMessage);
assertNotNull(decParentsNode);
assertEquals(decParentsNode.getName(), decParentsMessage);
String decParentsPtnMessage = "declare parents: Point+";
ProgramElementNode decParentsPtnNode = model.findNode(aspect, ProgramElementNode.Kind.DECLARE_PARENTS, decParentsPtnMessage);
assertNotNull(decParentsPtnNode);
assertEquals(decParentsPtnNode.getName(), decParentsPtnMessage);

String decParentsTPMessage = "declare parents: <type pattern>";
ProgramElementNode decParentsTPNode = model.findNode(aspect, ProgramElementNode.Kind.DECLARE_PARENTS, decParentsTPMessage);
assertNotNull(decParentsTPNode);
assertEquals(decParentsTPNode.getName(), decParentsTPMessage);
String decSoftMessage = "declare soft: SizeException";
ProgramElementNode decSoftNode = model.findNode(aspect, ProgramElementNode.Kind.DECLARE_SOFT, decSoftMessage);
assertNotNull(decSoftNode);
assertEquals(decSoftNode.getName(), decSoftMessage);

String decPrecMessage = "declare precedence: AdviceCoverage, InterTypeDecCoverage, <type pattern>";
ProgramElementNode decPrecNode = model.findNode(aspect, ProgramElementNode.Kind.DECLARE_PRECEDENCE, decPrecMessage);
assertNotNull(decPrecNode);
assertEquals(decPrecNode.getName(), decPrecMessage);
}

public void testInterTypeMemberDeclares() {
ProgramElementNode node = (ProgramElementNode)model.getRoot();
assertNotNull(node);
ProgramElementNode aspect = StructureModelManager.getDefault().getStructureModel().findNodeForClass(null, "InterTypeDecCoverage");
assertNotNull(aspect);
String fieldMsg = "Point.xxx";
ProgramElementNode fieldNode = model.findNode(aspect, ProgramElementNode.Kind.INTER_TYPE_FIELD, fieldMsg);
assertNotNull(fieldNode);
assertEquals(fieldNode.getName(), fieldMsg);

String methodMsg = "Point.check(int, Line)";
ProgramElementNode methodNode = model.findNode(aspect, ProgramElementNode.Kind.INTER_TYPE_METHOD, methodMsg);
assertNotNull(methodNode);
assertEquals(methodNode.getName(), methodMsg);

// TODO: enable
// String constructorMsg = "Point.new(int, int, int)";
// ProgramElementNode constructorNode = model.findNode(aspect, ProgramElementNode.Kind.INTER_TYPE_CONSTRUCTOR, constructorMsg);
// assertNotNull(constructorNode);
// assertEquals(constructorNode.getName(), constructorMsg);
}

public void testPointcuts() {
ProgramElementNode node = (ProgramElementNode)model.getRoot();
assertNotNull(node);
ProgramElementNode aspect = StructureModelManager.getDefault().getStructureModel().findNodeForClass(null, "AdviceNamingCoverage");
assertNotNull(aspect);
String ptct = "named()";
ProgramElementNode ptctNode = model.findNode(aspect, ProgramElementNode.Kind.POINTCUT, ptct);
assertNotNull(ptctNode);
assertEquals(ptctNode.getName(), ptct);

String params = "namedWithArgs(int, int)";
ProgramElementNode paramsNode = model.findNode(aspect, ProgramElementNode.Kind.POINTCUT, params);
assertNotNull(paramsNode);
assertEquals(paramsNode.getName(), params);


}

public void testAdvice() {
ProgramElementNode node = (ProgramElementNode)model.getRoot();
assertNotNull(node);
ProgramElementNode aspect = StructureModelManager.getDefault().getStructureModel().findNodeForClass(null, "AdviceNamingCoverage");
assertNotNull(aspect);

// String anon = "<anonymous pointcut>";
// ProgramElementNode anonNode = model.findNode(aspect, ProgramElementNode.Kind.POINTCUT, anon);
// assertNotNull(anonNode);
// assertEquals(anonNode.getName(), anon);
}

protected void setUp() throws Exception {
super.setUp("examples");
assertTrue("build success", doSynchronousBuild(CONFIG_FILE_PATH));
model = StructureModelManager.getDefault().getStructureModel();
}

protected void tearDown() throws Exception {
super.tearDown();
}

}

+ 3
- 3
ajde/testsrc/org/aspectj/ajde/NullIdeTaskListManager.java View File

@@ -43,15 +43,15 @@ public class NullIdeTaskListManager implements TaskListManager {
if (!hasWarning && IMessage.WARNING.isSameOrLessThan(message.getKind())) {
hasWarning = true;
}
// System.out.println("> added sourceline task: " + message + ", file: " + sourceLocation.getSourceFile().getAbsolutePath()
// + ": " + sourceLocation.getLine());
System.out.println("> added sourceline task: " + message + ", file: " + message.getISourceLocation().getSourceFile().getAbsolutePath()
+ ": " + message.getISourceLocation().getLine());
}
public void addProjectTask(String message, IMessage.Kind kind) {
if (!hasWarning && IMessage.WARNING.isSameOrLessThan(kind)) {
hasWarning = true;
}
// System.out.println("> added project task: " + message + ", kind: " + kind);
System.out.println("> added project task: " + message + ", kind: " + kind);
}

public boolean hasWarning() {

+ 5
- 1
ajde/testsrc/org/aspectj/ajde/StructureModelTest.java View File

@@ -100,8 +100,12 @@ public class StructureModelTest extends AjdeTestCase {
ProgramElementNode pNode = (ProgramElementNode)((ProgramElementNode)node).getChildren().get(1);
ProgramElementNode pointcut = (ProgramElementNode)pNode.getChildren().get(0);
assertTrue("kind", pointcut.getProgramElementKind().equals(ProgramElementNode.Kind.POINTCUT));
assertTrue("found node: " + pointcut.getName(), pointcut.getName().equals("testptct"));
assertTrue("found node: " + pointcut.getName(), pointcut.getName().equals("testptct()"));
}

public void testDeclare() {
}

public void testFileNodeFind() throws IOException {

+ 3
- 1
asm/src/org/aspectj/asm/LinkNode.java View File

@@ -42,7 +42,9 @@ public class LinkNode extends StructureNode {
public String toString() {
String name = "";
if (programElementNode.getProgramElementKind().equals(ProgramElementNode.Kind.ADVICE) ||
programElementNode.getProgramElementKind().equals(ProgramElementNode.Kind.INTRODUCTION) ||
programElementNode.getProgramElementKind().equals(ProgramElementNode.Kind.INTER_TYPE_FIELD) ||
programElementNode.getProgramElementKind().equals(ProgramElementNode.Kind.INTER_TYPE_METHOD) ||
programElementNode.getProgramElementKind().equals(ProgramElementNode.Kind.INTER_TYPE_CONSTRUCTOR) ||
programElementNode.getProgramElementKind().equals(ProgramElementNode.Kind.CODE)) {
name = programElementNode.parent.toString() + ": " + programElementNode.getName();
StructureNode grandparent = programElementNode.parent.parent;

+ 26
- 5
asm/src/org/aspectj/asm/ProgramElementNode.java View File

@@ -25,7 +25,7 @@ import org.aspectj.bridge.ISourceLocation;
*/
public class ProgramElementNode extends StructureNode {
private List modifiers = new ArrayList();
private List modifiers = new ArrayList();
private List relations = new ArrayList();

private Kind kind;
@@ -39,7 +39,8 @@ public class ProgramElementNode extends StructureNode {
private String bytecodeName;
private String bytecodeSignature;
private String fullSignature;
private String returnType;
/**
* Used during de-externalization.
@@ -278,7 +279,9 @@ public class ProgramElementNode extends StructureNode {
public static final Kind INTERFACE = new Kind("interface");
public static final Kind ASPECT = new Kind("aspect");
public static final Kind INITIALIZER = new Kind("initializer");
public static final Kind INTRODUCTION = new Kind("introduction");
public static final Kind INTER_TYPE_FIELD = new Kind("inter-type field");
public static final Kind INTER_TYPE_METHOD = new Kind("inter-type method");
public static final Kind INTER_TYPE_CONSTRUCTOR = new Kind("inter-type constructor");
public static final Kind CONSTRUCTOR = new Kind("constructor");
public static final Kind METHOD = new Kind("method");
public static final Kind FIELD = new Kind("field");
@@ -288,13 +291,15 @@ public class ProgramElementNode extends StructureNode {
public static final Kind DECLARE_WARNING = new Kind("declare warning");
public static final Kind DECLARE_ERROR = new Kind("declare error");
public static final Kind DECLARE_SOFT = new Kind("declare soft");
public static final Kind DECLARE_PRECEDENCE= new Kind("declare precedence");
public static final Kind CODE = new Kind("decBodyElement");
public static final Kind ERROR = new Kind("error");

public static final Kind[] ALL = { PROJECT, PACKAGE, FILE, FILE_JAVA,
FILE_ASPECTJ, FILE_LST, CLASS, INTERFACE, ASPECT,
INITIALIZER, INTRODUCTION, CONSTRUCTOR, METHOD, FIELD, POINTCUT, ADVICE,
DECLARE_PARENTS, DECLARE_WARNING, DECLARE_ERROR, DECLARE_SOFT, CODE, ERROR };
INITIALIZER, INTER_TYPE_FIELD, INTER_TYPE_METHOD, INTER_TYPE_CONSTRUCTOR,
CONSTRUCTOR, METHOD, FIELD, POINTCUT, ADVICE, DECLARE_PARENTS,
DECLARE_WARNING, DECLARE_ERROR, DECLARE_SOFT, CODE, ERROR };
public static Kind getKindForString(String kindString) {
for (int i = 0; i < ALL.length; i++) {
@@ -384,5 +389,21 @@ public class ProgramElementNode extends StructureNode {
this.bytecodeSignature = bytecodeSignature;
}

public String getFullSignature() {
return fullSignature;
}

public void setFullSignature(String string) {
fullSignature = string;
}
public void setKind(Kind kind) {
this.kind = kind;
}

public void setReturnType(String returnType) {
this.returnType = returnType;
}

}


+ 21
- 0
asm/src/org/aspectj/asm/StructureModel.java View File

@@ -63,6 +63,27 @@ public class StructureModel implements Serializable {
return root != null && fileMap != null;
}

/**
* Returns the first match
*
* @param parent
* @param kind not null
* @param decErrLabel
* @return null if not found
*/
public ProgramElementNode findNode(ProgramElementNode parent, ProgramElementNode.Kind kind, String name) {
for (Iterator it = parent.getChildren().iterator(); it.hasNext(); ) {
ProgramElementNode node = (ProgramElementNode)it.next();
if (node.getProgramElementKind().equals(kind)
&& name.equals(node.getName())) {
return node;
} else {
ProgramElementNode childSearch = findNode(node, kind, name);
if (childSearch != null) return childSearch;
}
}
return null;
}

/**
* @param packageName if null default package is searched

+ 5
- 0
asm/src/org/aspectj/asm/StructureNode.java View File

@@ -188,6 +188,11 @@ public abstract class StructureNode implements Serializable, Comparable {
// StructureNode cloneNode = new StructureNode(name, kind, cloneChildren);
// return cloneNode;
// }

public void setName(String string) {
name = string;
}

}



+ 23
- 87
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmBuilder.java View File

@@ -21,7 +21,8 @@ import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.asm.*;
import org.aspectj.bridge.*;
import org.aspectj.util.LangUtil;
import org.aspectj.weaver.Member;
import org.aspectj.weaver.*;
import org.aspectj.weaver.patterns.*;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -39,6 +40,7 @@ public class AsmBuilder extends AbstractSyntaxTreeVisitorAdapter {

private final Stack stack;
private final CompilationResult currCompilationResult;
private AsmNodeFormatter formatter = new AsmNodeFormatter();
protected AsmBuilder(CompilationResult result) {
LangUtil.throwIaxIfNull(result, "result");
@@ -159,10 +161,11 @@ public class AsmBuilder extends AbstractSyntaxTreeVisitorAdapter {
name,
kind,
makeLocation(typeDeclaration),
typeDeclaration.modifiers,
"",
typeDeclaration.modifiers, "",
new ArrayList());
// peNode.setFullSignature(typeDeclaration.());
((StructureNode)stack.peek()).addChild(peNode);
stack.push(peNode);
return true;
@@ -188,6 +191,8 @@ public class AsmBuilder extends AbstractSyntaxTreeVisitorAdapter {
"",
new ArrayList());
peNode.setFullSignature(memberTypeDeclaration.toString());
((StructureNode)stack.peek()).addChild(peNode);
stack.push(peNode);
return true;
@@ -250,54 +255,30 @@ public class AsmBuilder extends AbstractSyntaxTreeVisitorAdapter {
return (StructureNode)stack.peek();
}
// !!! improve name and type generation
// TODO: improve handling of malformed methodDeclaration.binding
public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
ProgramElementNode.Kind kind = ProgramElementNode.Kind.METHOD;
String label = new String(methodDeclaration.selector);
if (methodDeclaration instanceof AdviceDeclaration) {
kind = ProgramElementNode.Kind.ADVICE;
label = translateAdviceName(label);
} else if (methodDeclaration instanceof PointcutDeclaration) {
kind = ProgramElementNode.Kind.POINTCUT;
label = translatePointcutName(label);
} else if (methodDeclaration instanceof DeclareDeclaration) {
DeclareDeclaration declare = (DeclareDeclaration)methodDeclaration;
label = translateDeclareName(declare.toString());
// TODO: fix this horrible way of checking what kind of declare it is
if (label.indexOf("warning") != -1) {
kind = ProgramElementNode.Kind.DECLARE_WARNING;
} else if (label.indexOf("error") != -1) {
kind = ProgramElementNode.Kind.DECLARE_ERROR;
} else if (label.indexOf("parents") != -1) {
kind = ProgramElementNode.Kind.DECLARE_PARENTS;
} else if (label.indexOf("soft") != -1) {
kind = ProgramElementNode.Kind.DECLARE_SOFT;
} else {
kind = ProgramElementNode.Kind.ERROR;
}
} else if (methodDeclaration instanceof InterTypeDeclaration) {
kind = ProgramElementNode.Kind.INTRODUCTION;
label = translateInterTypeDecName(new String(((InterTypeDeclaration)methodDeclaration).selector));
}
public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
ProgramElementNode peNode = new ProgramElementNode(
label,
kind,
"",
ProgramElementNode.Kind.ERROR,
makeLocation(methodDeclaration),
methodDeclaration.modifiers,
"",
new ArrayList());

if (kind == ProgramElementNode.Kind.METHOD) {
// TODO: should improve determining what the main method is
if (label.equals("main")) {
formatter.genLabelAndKind(methodDeclaration, peNode);
genBytecodeInfo(methodDeclaration, peNode);

// TODO: should improve determining what the main method is
if (peNode.getProgramElementKind().equals(ProgramElementNode.Kind.METHOD)) {
if (peNode.getName().equals("main")) {
((ProgramElementNode)stack.peek()).setRunnable(true);
}
}
stack.push(peNode);
return true;
}

private void genBytecodeInfo(MethodDeclaration methodDeclaration, ProgramElementNode peNode) {
if (methodDeclaration.binding != null) {
String memberName = "";
String memberBytecodeSignature = "";
@@ -308,14 +289,11 @@ public class AsmBuilder extends AbstractSyntaxTreeVisitorAdapter {
} catch (NullPointerException npe) {
memberName = "<undefined>";
}
peNode.setBytecodeName(memberName);
peNode.setBytecodeSignature(memberBytecodeSignature);
}
((StructureNode)stack.peek()).addChild(peNode);
stack.push(peNode);
return true;
}

public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
@@ -509,46 +487,4 @@ public class AsmBuilder extends AbstractSyntaxTreeVisitorAdapter {
currCompilationResult.lineSeparatorPositions,
td.declarationSourceEnd);
}

// !!! move or replace
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 "<advice>";
}
// !!! 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;
}
}

}

+ 188
- 0
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/core/builder/AsmNodeFormatter.java View File

@@ -0,0 +1,188 @@
/* *******************************************************************
* 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 Common Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* ******************************************************************/

package org.aspectj.ajdt.internal.core.builder;

import java.util.Iterator;

import org.aspectj.ajdt.internal.compiler.ast.*;
import org.aspectj.asm.ProgramElementNode;
import org.aspectj.weaver.*;
import org.aspectj.weaver.patterns.*;
import org.eclipse.jdt.internal.compiler.ast.*;

public class AsmNodeFormatter {

public static final int MAX_MESSAGE_LENGTH = 18;
public static final String DEC_LABEL = "declare";

public void genLabelAndKind(MethodDeclaration methodDeclaration, ProgramElementNode node) {
if (methodDeclaration instanceof AdviceDeclaration) {
node.setKind( ProgramElementNode.Kind.ADVICE);
node.setName(translateAdviceName(new String(methodDeclaration.selector)));
} else if (methodDeclaration instanceof PointcutDeclaration) {
PointcutDeclaration pd = (PointcutDeclaration)methodDeclaration;
node.setKind( ProgramElementNode.Kind.POINTCUT);
String label = translatePointcutName(new String(methodDeclaration.selector));
label += "(" + genArguments(pd) + ")";
node.setName(label);
} else if (methodDeclaration instanceof DeclareDeclaration) {
DeclareDeclaration declare = (DeclareDeclaration)methodDeclaration;
String label = DEC_LABEL + " ";
if (declare.declare instanceof DeclareErrorOrWarning) {
DeclareErrorOrWarning deow = (DeclareErrorOrWarning)declare.declare;
if (deow.isError()) {
node.setKind( ProgramElementNode.Kind.DECLARE_ERROR);
label += "error: ";
} else {
node.setKind( ProgramElementNode.Kind.DECLARE_WARNING);
label += "warning: ";
}
node.setName(label + genDeclareMessage(deow.getMessage())) ;
} else if (declare.declare instanceof DeclareParents) {
node.setKind( ProgramElementNode.Kind.DECLARE_PARENTS);
DeclareParents dp = (DeclareParents)declare.declare;
node.setName(label + "parents: " + genTypePatternLabel(dp.getChild()));
} else if (declare.declare instanceof DeclareSoft) {
node.setKind( ProgramElementNode.Kind.DECLARE_SOFT);
DeclareSoft ds = (DeclareSoft)declare.declare;
node.setName(label + "soft: " + genTypePatternLabel(ds.getException()));
} else if (declare.declare instanceof DeclarePrecedence) {
node.setKind( ProgramElementNode.Kind.DECLARE_PRECEDENCE);
DeclarePrecedence ds = (DeclarePrecedence)declare.declare;
node.setName(label + "precedence: " + genPrecedenceListLabel(ds.getPatterns()));
} else {
node.setKind( ProgramElementNode.Kind.ERROR);
node.setName("<unknown declare>");
}
} else if (methodDeclaration instanceof InterTypeDeclaration) {
InterTypeDeclaration itd = (InterTypeDeclaration)methodDeclaration;
String label = itd.onType.toString() + "." + new String(itd.getDeclaredSelector());
if (methodDeclaration instanceof InterTypeFieldDeclaration) {
node.setKind(ProgramElementNode.Kind.INTER_TYPE_FIELD);
} else if (methodDeclaration instanceof InterTypeMethodDeclaration) {
node.setKind(ProgramElementNode.Kind.INTER_TYPE_METHOD);
InterTypeMethodDeclaration itmd = (InterTypeMethodDeclaration)methodDeclaration;
label += "(" + genArguments(itd) + ")";
} else if (methodDeclaration instanceof InterTypeConstructorDeclaration) {
node.setKind(ProgramElementNode.Kind.INTER_TYPE_CONSTRUCTOR);
InterTypeConstructorDeclaration itcd = (InterTypeConstructorDeclaration)methodDeclaration;
} else {
node.setKind(ProgramElementNode.Kind.ERROR);
}
node.setName(label);
node.setReturnType(itd.returnType.toString());
} else {
node.setKind(ProgramElementNode.Kind.METHOD);
node.setName(new String(methodDeclaration.selector));
}
}


private String genPrecedenceListLabel(TypePatternList list) {
String tpList = "";
for (int i = 0; i < list.size(); i++) {
tpList += genTypePatternLabel(list.get(i));
if (i < list.size()-1) tpList += ", ";
}
return tpList;
}
private String genArguments(MethodDeclaration md) {
String args = "";
Argument[] argArray = md.arguments;
if (argArray == null) return args;
for (int i = 0; i < argArray.length; i++) {
String argName = new String(argArray[i].name);
String argType = argArray[i].type.toString();
// TODO: fix this way of determing ajc-added arguments, make subtype of Argument with extra info
if (!argName.startsWith("ajc$this_")) {
args += argType;
if (i < argArray.length-1) args += ", ";
}
}
return args;
}

public String genTypePatternLabel(TypePattern tp) {
final String TYPE_PATTERN_LITERAL = "<type pattern>";
String label;
TypeX typeX = tp.getExactType();
if (typeX != ResolvedTypeX.MISSING) {
label = typeX.getName();
if (tp.isIncludeSubtypes()) label += "+";
} else {
label = TYPE_PATTERN_LITERAL;
}
return label;
}

public String genDeclareMessage(String message) {
int length = message.length();
if (length < MAX_MESSAGE_LENGTH) {
return message;
} else {
return message.substring(0, MAX_MESSAGE_LENGTH-1) + "..";
}
}
// !!! move or replace
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 "<advice>";
}
// // !!! 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;
}
}


}

Loading…
Cancel
Save