aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShigeru Chiba <chibash@users.noreply.github.com>2024-05-03 19:01:47 +0900
committerGitHub <noreply@github.com>2024-05-03 19:01:47 +0900
commitbb261b443831e52409eeed6e49ddfb24db2c4d08 (patch)
tree3f8189ef73984d71ad0b8fe595c0e3a2a425e6bb
parent204d67844433c9b781054154695eeb14c2291847 (diff)
parent9777bae93cc84249fe08a7e81b2101c415bd55e5 (diff)
downloadjavassist-bb261b443831e52409eeed6e49ddfb24db2c4d08.tar.gz
javassist-bb261b443831e52409eeed6e49ddfb24db2c4d08.zip
Merge pull request #484 from kuznet1/master
Line numbers support
-rw-r--r--src/main/javassist/CtClass.java10
-rw-r--r--src/main/javassist/CtNewConstructor.java1
-rw-r--r--src/main/javassist/CtNewMethod.java1
-rw-r--r--src/main/javassist/bytecode/CodeAttribute.java14
-rw-r--r--src/main/javassist/bytecode/LineNumberAttribute.java2
-rw-r--r--src/main/javassist/bytecode/LineNumberAttributeBuilder.java40
-rw-r--r--src/main/javassist/compiler/CodeGen.java88
-rw-r--r--src/main/javassist/compiler/CompileError.java15
-rw-r--r--src/main/javassist/compiler/Javac.java67
-rw-r--r--src/main/javassist/compiler/JvstCodeGen.java72
-rw-r--r--src/main/javassist/compiler/JvstCodeGenWitlLineNumber.java265
-rw-r--r--src/main/javassist/compiler/JvstTypeChecker.java30
-rw-r--r--src/main/javassist/compiler/Lex.java13
-rw-r--r--src/main/javassist/compiler/MemberCodeGen.java112
-rw-r--r--src/main/javassist/compiler/MemberResolver.java72
-rw-r--r--src/main/javassist/compiler/NoFieldException.java2
-rw-r--r--src/main/javassist/compiler/Parser.java160
-rw-r--r--src/main/javassist/compiler/ProceedHandler.java4
-rw-r--r--src/main/javassist/compiler/TypeChecker.java111
-rw-r--r--src/main/javassist/compiler/ast/ASTList.java16
-rw-r--r--src/main/javassist/compiler/ast/ASTree.java10
-rw-r--r--src/main/javassist/compiler/ast/ArrayInit.java8
-rw-r--r--src/main/javassist/compiler/ast/AssignExpr.java8
-rw-r--r--src/main/javassist/compiler/ast/BinExpr.java8
-rw-r--r--src/main/javassist/compiler/ast/CallExpr.java8
-rw-r--r--src/main/javassist/compiler/ast/CastExpr.java8
-rw-r--r--src/main/javassist/compiler/ast/CondExpr.java4
-rw-r--r--src/main/javassist/compiler/ast/Declarator.java20
-rw-r--r--src/main/javassist/compiler/ast/DoubleConst.java14
-rw-r--r--src/main/javassist/compiler/ast/Expr.java16
-rw-r--r--src/main/javassist/compiler/ast/FieldDecl.java4
-rw-r--r--src/main/javassist/compiler/ast/InstanceOfExpr.java8
-rw-r--r--src/main/javassist/compiler/ast/IntConst.java10
-rw-r--r--src/main/javassist/compiler/ast/Keyword.java3
-rw-r--r--src/main/javassist/compiler/ast/Member.java4
-rw-r--r--src/main/javassist/compiler/ast/MethodDecl.java4
-rw-r--r--src/main/javassist/compiler/ast/NewExpr.java16
-rw-r--r--src/main/javassist/compiler/ast/Pair.java1
-rw-r--r--src/main/javassist/compiler/ast/Stmnt.java20
-rw-r--r--src/main/javassist/compiler/ast/StringL.java3
-rw-r--r--src/main/javassist/compiler/ast/Symbol.java3
-rw-r--r--src/main/javassist/compiler/ast/Variable.java4
-rw-r--r--src/main/javassist/expr/Cast.java10
-rw-r--r--src/main/javassist/expr/FieldAccess.java20
-rw-r--r--src/main/javassist/expr/Instanceof.java10
-rw-r--r--src/main/javassist/expr/NewArray.java10
-rw-r--r--src/main/javassist/expr/NewExpr.java10
-rw-r--r--src/test/javassist/LineNumberTest.java93
-rw-r--r--src/test/javassist/compiler/CompTest.java4
49 files changed, 958 insertions, 478 deletions
diff --git a/src/main/javassist/CtClass.java b/src/main/javassist/CtClass.java
index 128d8b20..3b73f8ac 100644
--- a/src/main/javassist/CtClass.java
+++ b/src/main/javassist/CtClass.java
@@ -71,6 +71,8 @@ public abstract class CtClass {
*/
public static final String version = "3.30.2-GA";
+ private int linesCount = 0;
+
/**
* Prints the version number and the copyright notice.
*
@@ -1575,6 +1577,14 @@ public abstract class CtClass {
new DelayedFileOutputStream(filename)));
}
+ public int getLinesCount() {
+ return linesCount;
+ }
+
+ void addLines(int count) {
+ this.linesCount += count;
+ }
+
/**
* Writes a class file as <code>writeFile()</code> does although this
* method does not prune or freeze the class after writing the class
diff --git a/src/main/javassist/CtNewConstructor.java b/src/main/javassist/CtNewConstructor.java
index 9f4225f1..ed3e379b 100644
--- a/src/main/javassist/CtNewConstructor.java
+++ b/src/main/javassist/CtNewConstructor.java
@@ -69,6 +69,7 @@ public class CtNewConstructor {
Javac compiler = new Javac(declaring);
try {
CtMember obj = compiler.compile(src);
+ declaring.addLines(src.split("\n").length);
if (obj instanceof CtConstructor) {
// a stack map table has been already created.
return (CtConstructor)obj;
diff --git a/src/main/javassist/CtNewMethod.java b/src/main/javassist/CtNewMethod.java
index 3daaa026..2cd363b0 100644
--- a/src/main/javassist/CtNewMethod.java
+++ b/src/main/javassist/CtNewMethod.java
@@ -77,6 +77,7 @@ public class CtNewMethod {
compiler.recordProceed(delegateObj, delegateMethod);
CtMember obj = compiler.compile(src);
+ declaring.addLines(src.split("\n").length);
if (obj instanceof CtMethod)
return (CtMethod)obj;
}
diff --git a/src/main/javassist/bytecode/CodeAttribute.java b/src/main/javassist/bytecode/CodeAttribute.java
index 091edf4c..cf8806ef 100644
--- a/src/main/javassist/bytecode/CodeAttribute.java
+++ b/src/main/javassist/bytecode/CodeAttribute.java
@@ -353,6 +353,20 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
}
/**
+ * Adds a line number table. If another copy of line number table
+ * is already contained, the old one is removed.
+ *
+ * @param lnt the line number table added to this code attribute.
+ * If it is null, a new line number is not added.
+ * Only the old line number is removed.
+ */
+ public void setAttribute(LineNumberAttribute lnt) {
+ AttributeInfo.remove(attributes, LineNumberAttribute.tag);
+ if (lnt != null)
+ attributes.add(lnt);
+ }
+
+ /**
* Copies code.
*/
private byte[] copyCode(ConstPool destCp, Map<String,String> classnames,
diff --git a/src/main/javassist/bytecode/LineNumberAttribute.java b/src/main/javassist/bytecode/LineNumberAttribute.java
index cead96e0..16b37377 100644
--- a/src/main/javassist/bytecode/LineNumberAttribute.java
+++ b/src/main/javassist/bytecode/LineNumberAttribute.java
@@ -35,7 +35,7 @@ public class LineNumberAttribute extends AttributeInfo {
super(cp, n, in);
}
- private LineNumberAttribute(ConstPool cp, byte[] i) {
+ LineNumberAttribute(ConstPool cp, byte[] i) {
super(cp, tag, i);
}
diff --git a/src/main/javassist/bytecode/LineNumberAttributeBuilder.java b/src/main/javassist/bytecode/LineNumberAttributeBuilder.java
new file mode 100644
index 00000000..52d9d0c8
--- /dev/null
+++ b/src/main/javassist/bytecode/LineNumberAttributeBuilder.java
@@ -0,0 +1,40 @@
+package javassist.bytecode;
+
+import javassist.compiler.ast.ASTree;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class LineNumberAttributeBuilder {
+ private final HashMap<Integer, Integer> map = new HashMap<>();
+
+ public void put(int newPc, ASTree tree) {
+ if (tree != null)
+ put(newPc, tree.getLineNumber());
+ }
+
+ private void put(int newPc, int lineNum) {
+ Integer pc = map.get(lineNum);
+ if (pc == null || newPc < pc) {
+ map.put(lineNum, newPc);
+ }
+ }
+
+ public LineNumberAttribute build(ConstPool cp) {
+ int size = map.size();
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream(size * 4 + 2);
+ DataOutputStream dos = new DataOutputStream(bos)) {
+ dos.writeShort(size);
+ for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
+ dos.writeShort(entry.getValue());
+ dos.writeShort(entry.getKey());
+ }
+ return new LineNumberAttribute(cp, bos.toByteArray());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/javassist/compiler/CodeGen.java b/src/main/javassist/compiler/CodeGen.java
index e3115617..e7e274b9 100644
--- a/src/main/javassist/compiler/CodeGen.java
+++ b/src/main/javassist/compiler/CodeGen.java
@@ -121,8 +121,8 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
typeChecker = checker;
}
- protected static void fatal() throws CompileError {
- throw new CompileError("fatal");
+ protected static void fatal(int lineNumber) throws CompileError {
+ throw new CompileError("fatal", lineNumber);
}
public static boolean is2word(int type, int dim) {
@@ -184,7 +184,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
/* Expands a simple class name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
- protected abstract String resolveClassName(String jvmClassName)
+ protected abstract String resolveClassName(String jvmClassName, int lineNumber)
throws CompileError;
/**
@@ -267,13 +267,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
@Override
- public void atASTList(ASTList n) throws CompileError { fatal(); }
+ public void atASTList(ASTList n) throws CompileError { fatal(n.getLineNumber()); }
@Override
- public void atPair(Pair n) throws CompileError { fatal(); }
+ public void atPair(Pair n) throws CompileError { fatal(n.getLineNumber()); }
@Override
- public void atSymbol(Symbol n) throws CompileError { fatal(); }
+ public void atSymbol(Symbol n) throws CompileError { fatal(n.getLineNumber()); }
@Override
public void atFieldDecl(FieldDecl field) throws CompileError {
@@ -325,7 +325,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
hasReturned = true;
}
else
- throw new CompileError("no return statement");
+ throw new CompileError("no return statement", s.getLineNumber());
}
private boolean needsSuperCall(Stmnt body) throws CompileError {
@@ -403,7 +403,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
// LABEL, SWITCH label stament might be null?.
hasReturned = false;
throw new CompileError(
- "sorry, not supported statement: TokenId " + op);
+ "sorry, not supported statement: TokenId " + op, st.getLineNumber());
}
}
@@ -590,7 +590,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
if (op == DEFAULT)
defaultPc = bytecode.currentPc();
else if (op != CASE)
- fatal();
+ fatal(st.getLineNumber());
else {
int curPos = bytecode.currentPc();
long caseLabel;
@@ -638,7 +638,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
expr = TypeChecker.stripPlusExpr(expr);
if (expr instanceof IntConst)
return (int)((IntConst)expr).get();
- throw new CompileError("bad case label");
+ throw new CompileError("bad case label", expr.getLineNumber());
}
private int computeStringLabel(ASTree expr, int tmpVar, List<Integer> gotoDefaults)
@@ -658,7 +658,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
gotoDefaults.add(pc);
return (int)label.hashCode();
}
- throw new CompileError("bad case label");
+ throw new CompileError("bad case label", expr.getLineNumber());
}
private void atBreakStmnt(Stmnt st, boolean notCont)
@@ -666,7 +666,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
{
if (st.head() != null)
throw new CompileError(
- "sorry, not support labeled break or continue");
+ "sorry, not support labeled break or continue", st.getLineNumber());
bytecode.addOpcode(Opcode.GOTO);
Integer pc = Integer.valueOf(bytecode.currentPc());
@@ -718,7 +718,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
ASTree e = st.getLeft();
compileExpr(e);
if (exprType != CLASS || arrayDim > 0)
- throw new CompileError("bad throw statement");
+ throw new CompileError("bad throw statement", st.getLineNumber());
bytecode.addOpcode(ATHROW);
hasReturned = true;
@@ -736,7 +736,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
compileExpr(st.head());
if (exprType != CLASS && arrayDim == 0)
- throw new CompileError("bad type expr for synchronized block");
+ throw new CompileError("bad type expr for synchronized block", st.getLineNumber());
Bytecode bc = bytecode;
final int var = bc.getMaxLocals();
@@ -783,7 +783,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
if (getListSize(breakList) != nbreaks
|| getListSize(continueList) != ncontinues)
throw new CompileError(
- "sorry, cannot break/continue in synchronized block");
+ "sorry, cannot break/continue in synchronized block", st.getLineNumber());
}
private static int getListSize(List<Integer> list) {
@@ -802,7 +802,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
@Override
public void atDeclarator(Declarator d) throws CompileError {
d.setLocalVar(getMaxLocals());
- d.setClassName(resolveClassName(d.getClassName()));
+ d.setClassName(resolveClassName(d.getClassName(), d.getLineNumber()));
int size;
if (is2word(d.getType(), d.getArrayDim()))
@@ -863,7 +863,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
else
msg = "incompatible type for " + expr.getName();
- throw new CompileError(msg);
+ throw new CompileError(msg, expr.getLineNumber());
}
/* op is either =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, or >>>=.
@@ -962,7 +962,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
int token = assignOps[op - MOD_E];
int k = lookupBinOp(token);
if (k < 0)
- fatal();
+ fatal(right.getLineNumber());
atArithBinExpr(expr, token, k, type);
}
@@ -981,9 +981,9 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
if (!jvmJavaLangString.equals(cname))
badAssign(expr);
- convToString(type, dim); // the value might be null.
+ convToString(type, dim, expr.getLineNumber()); // the value might be null.
right.accept(this);
- convToString(exprType, arrayDim);
+ convToString(exprType, arrayDim, expr.getLineNumber());
bytecode.addInvokevirtual(javaLangString, "concat",
"(Ljava/lang/String;)Ljava/lang/String;");
exprType = CLASS;
@@ -1025,7 +1025,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);
expr.elseExpr().accept(this);
if (dim1 != arrayDim)
- throw new CompileError("type mismatch in ?:");
+ throw new CompileError("type mismatch in ?:", expr.getLineNumber());
bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);
}
@@ -1072,7 +1072,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
String cname1 = className;
right.accept(this);
if (dim1 != arrayDim)
- throw new CompileError("incompatible array types");
+ throw new CompileError("incompatible array types", expr.getLineNumber());
if (token == '+' && dim1 == 0
&& (type1 == CLASS || exprType == CLASS))
@@ -1139,7 +1139,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
= (type2 == CLASS && jvmJavaLangString.equals(className));
if (type2Is2)
- convToString(type2, dim2);
+ convToString(type2, dim2, expr.getLineNumber());
if (is2word(type1, dim1)) {
bytecode.addOpcode(DUP_X2);
@@ -1149,11 +1149,11 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
bytecode.addOpcode(SWAP);
// even if type1 is String, the left operand might be null.
- convToString(type1, dim1);
+ convToString(type1, dim1, expr.getLineNumber());
bytecode.addOpcode(SWAP);
if (!type2Is2 && !type2IsString)
- convToString(type2, dim2);
+ convToString(type2, dim2, expr.getLineNumber());
bytecode.addInvokevirtual(javaLangString, "concat",
"(Ljava/lang/String;)Ljava/lang/String;");
@@ -1162,7 +1162,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
className = jvmJavaLangString;
}
- private void convToString(int type, int dim) throws CompileError {
+ private void convToString(int type, int dim, int lineNumber) throws CompileError {
final String method = "valueOf";
if (isRefType(type) || dim > 0)
@@ -1184,7 +1184,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
bytecode.addInvokestatic(javaLangString, method,
"(C)Ljava/lang/String;");
else if (type == VOID)
- throw new CompileError("void type expression");
+ throw new CompileError("void type expression", lineNumber);
else /* INT, BYTE, SHORT */
bytecode.addInvokestatic(javaLangString, method,
"(I)Ljava/lang/String;");
@@ -1237,7 +1237,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
else { // others
expr.accept(this);
if (exprType != BOOLEAN || arrayDim != 0)
- throw new CompileError("boolean expr is required");
+ throw new CompileError("boolean expr is required", expr.getLineNumber());
bytecode.addOpcode(branchIf ? IFNE : IFEQ);
}
@@ -1280,7 +1280,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
expr.oprand2().accept(this);
if (dim1 != arrayDim)
if (type1 != NULL && exprType != NULL)
- throw new CompileError("incompatible array types");
+ throw new CompileError("incompatible array types", expr.getLineNumber());
else if (exprType == NULL)
arrayDim = dim1;
@@ -1348,7 +1348,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
else if (p == P_LONG)
bytecode.addOpcode(LCMP); // 1: >, 0: =, -1: <
else
- fatal();
+ fatal(expr.getLineNumber());
int[] op = ifOp2;
for (int i = 0; i < op.length; i += 3)
@@ -1362,7 +1362,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
protected static void badTypes(Expr expr) throws CompileError {
- throw new CompileError("invalid types for " + expr.getName());
+ throw new CompileError("invalid types for " + expr.getName(), expr.getLineNumber());
}
private static final int P_DOUBLE = 0;
@@ -1462,7 +1462,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
bytecode.addOpcode(SWAP);
}
else
- fatal();
+ fatal(expr.getLineNumber());
}
else if (op != NOP)
bytecode.addOpcode(op);
@@ -1503,11 +1503,11 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
int srcDim = arrayDim;
if (invalidDim(srcType, arrayDim, className, type, dim, name, true)
|| srcType == VOID || type == VOID)
- throw new CompileError(msg);
+ throw new CompileError(msg, expr.getLineNumber());
if (type == CLASS) {
if (!isRefType(srcType) && srcDim == 0)
- throw new CompileError(msg);
+ throw new CompileError(msg, expr.getLineNumber());
return toJvmArrayName(name, dim);
}
@@ -1591,7 +1591,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
bytecode.addIconst(0);
}
else if (token == CALL) // method call
- fatal();
+ fatal(expr.getLineNumber());
else {
expr.oprand1().accept(this);
int type = typePrecedence(exprType);
@@ -1633,12 +1633,12 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
// do nothing. ignore.
}
else
- fatal();
+ fatal(expr.getLineNumber());
}
}
protected static void badType(Expr expr) throws CompileError {
- throw new CompileError("invalid type for " + expr.getName());
+ throw new CompileError("invalid type for " + expr.getName(), expr.getLineNumber());
}
@Override
@@ -1649,14 +1649,14 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
public void atClassObject(Expr expr) throws CompileError {
ASTree op1 = expr.oprand1();
if (!(op1 instanceof Symbol))
- throw new CompileError("fatal error: badly parsed .class expr");
+ throw new CompileError("fatal error: badly parsed .class expr", expr.getLineNumber());
String cname = ((Symbol)op1).get();
if (cname.startsWith("[")) {
int i = cname.indexOf("[L");
if (i >= 0) {
String name = cname.substring(i + 2, cname.length() - 1);
- String name2 = resolveClassName(name);
+ String name2 = resolveClassName(name, expr.getLineNumber());
if (!name.equals(name2)) {
/* For example, to obtain String[].class,
* "[Ljava.lang.String;" (not "[Ljava/lang/String"!)
@@ -1673,7 +1673,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
}
}
else {
- cname = resolveClassName(MemberResolver.javaToJvmName(cname));
+ cname = resolveClassName(MemberResolver.javaToJvmName(cname), expr.getLineNumber());
cname = MemberResolver.jvmToJavaName(cname);
}
@@ -1736,13 +1736,13 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
int type = exprType;
int dim = arrayDim;
if (dim == 0)
- throw new CompileError("bad array access");
+ throw new CompileError("bad array access", array.getLineNumber());
String cname = className;
index.accept(this);
if (typePrecedence(exprType) != P_INT || arrayDim > 0)
- throw new CompileError("bad array index");
+ throw new CompileError("bad array index", array.getLineNumber());
exprType = type;
arrayDim = dim - 1;
@@ -1992,7 +1992,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
case SUPER :
if (inStaticMethod)
throw new CompileError("not-available: "
- + (token == THIS ? "this" : "super"));
+ + (token == THIS ? "this" : "super"), k.getLineNumber());
bytecode.addAload(0);
exprType = CLASS;
@@ -2002,7 +2002,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId {
className = getSuperName();
break;
default :
- fatal();
+ fatal(k.getLineNumber());
}
}
diff --git a/src/main/javassist/compiler/CompileError.java b/src/main/javassist/compiler/CompileError.java
index 5b857cf2..3a41779c 100644
--- a/src/main/javassist/compiler/CompileError.java
+++ b/src/main/javassist/compiler/CompileError.java
@@ -25,12 +25,19 @@ public class CompileError extends Exception {
private Lex lex;
private String reason;
+ private int lineNumber = -1;
+
public CompileError(String s, Lex l) {
- reason = s;
+ this(s, l.getLineNumber());
lex = l;
}
- public CompileError(String s) {
+ public CompileError(String s, int lineNumber) {
+ this.lineNumber = lineNumber;
+ reason = String.format("line %d: %s", lineNumber, s);
+ }
+
+ private CompileError(String s) {
reason = s;
lex = null;
}
@@ -45,6 +52,10 @@ public class CompileError extends Exception {
public Lex getLex() { return lex; }
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
@Override
public String getMessage() {
return reason;
diff --git a/src/main/javassist/compiler/Javac.java b/src/main/javassist/compiler/Javac.java
index 084487b4..8d1a04f3 100644
--- a/src/main/javassist/compiler/Javac.java
+++ b/src/main/javassist/compiler/Javac.java
@@ -43,7 +43,7 @@ import javassist.compiler.ast.Stmnt;
import javassist.compiler.ast.Symbol;
public class Javac {
- JvstCodeGen gen;
+ JvstCodeGenWitlLineNumber gen;
SymbolTable stable;
private Bytecode bytecode;
@@ -71,7 +71,7 @@ public class Javac {
* belongs to.
*/
public Javac(Bytecode b, CtClass thisClass) {
- gen = new JvstCodeGen(b, thisClass, thisClass.getClassPool());
+ gen = new JvstCodeGenWitlLineNumber(b, thisClass, thisClass.getClassPool());
stable = new SymbolTable();
bytecode = b;
}
@@ -94,7 +94,9 @@ public class Javac {
* @see #recordProceed(String,String)
*/
public CtMember compile(String src) throws CompileError {
- Parser p = new Parser(new Lex(src));
+ int startLine = gen.thisClass.getLinesCount();
+ Lex lex = new Lex(src, startLine);
+ Parser p = new Parser(lex);
ASTList mem = p.parseMember1(stable);
try {
if (mem instanceof FieldDecl)
@@ -106,11 +108,8 @@ public class Javac {
decl.getClassFile2());
return cb;
}
- catch (BadBytecode bb) {
- throw new CompileError(bb.getMessage());
- }
- catch (CannotCompileException e) {
- throw new CompileError(e.getMessage());
+ catch (BadBytecode | CannotCompileException bb) {
+ throw new CompileError(bb.getMessage(), lex.getLineNumber());
}
}
@@ -160,8 +159,9 @@ public class Javac {
gen.getThisClass());
cons.setModifiers(mod);
md.accept(gen);
- cons.getMethodInfo().setCodeAttribute(
- bytecode.toCodeAttribute());
+ CodeAttribute cattr = bytecode.toCodeAttribute();
+ cattr.setAttribute(gen.toLineNumberAttribute());
+ cons.getMethodInfo().setCodeAttribute(cattr);
cons.setExceptionTypes(tlist);
return cons;
}
@@ -173,17 +173,18 @@ public class Javac {
method.setModifiers(mod);
gen.setThisMethod(method);
md.accept(gen);
- if (md.getBody() != null)
- method.getMethodInfo().setCodeAttribute(
- bytecode.toCodeAttribute());
- else
+ if (md.getBody() != null) {
+ CodeAttribute cattr = bytecode.toCodeAttribute();
+ cattr.setAttribute(gen.toLineNumberAttribute());
+ method.getMethodInfo().setCodeAttribute(cattr);
+ } else
method.setModifiers(mod | Modifier.ABSTRACT);
method.setExceptionTypes(tlist);
return method;
}
catch (NotFoundException e) {
- throw new CompileError(e.toString());
+ throw new CompileError(e.toString(), md.getLineNumber());
}
}
@@ -219,7 +220,7 @@ public class Javac {
Stmnt s = p.parseStatement(stb);
if (p.hasMore())
throw new CompileError(
- "the method/constructor body must be surrounded by {}");
+ "the method/constructor body must be surrounded by {}", s.getLineNumber());
boolean callSuper = false;
if (method instanceof CtConstructor)
@@ -231,7 +232,7 @@ public class Javac {
return bytecode;
}
catch (NotFoundException e) {
- throw new CompileError(e.toString());
+ throw new CompileError(e.toString(), -1);
}
}
@@ -443,27 +444,27 @@ public class Javac {
ProceedHandler h = new ProceedHandler() {
@Override
- public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber)
throws CompileError
{
- ASTree expr = new Member(m);
+ ASTree expr = new Member(m, texpr.getLineNumber());
if (texpr != null)
- expr = Expr.make('.', texpr, expr);
+ expr = Expr.make('.', texpr, expr, texpr.getLineNumber());
- expr = CallExpr.makeCall(expr, args);
+ expr = CallExpr.makeCall(expr, args, texpr.getLineNumber());
gen.compileExpr(expr);
gen.addNullIfVoid();
}
@Override
- public void setReturnType(JvstTypeChecker check, ASTList args)
+ public void setReturnType(JvstTypeChecker check, ASTList args, int lineNumber)
throws CompileError
{
- ASTree expr = new Member(m);
+ ASTree expr = new Member(m, texpr.getLineNumber());
if (texpr != null)
- expr = Expr.make('.', texpr, expr);
+ expr = Expr.make('.', texpr, expr, texpr.getLineNumber());
- expr = CallExpr.makeCall(expr, args);
+ expr = CallExpr.makeCall(expr, args, texpr.getLineNumber());
expr.accept(check);
check.addNullIfVoid();
}
@@ -489,23 +490,23 @@ public class Javac {
ProceedHandler h = new ProceedHandler() {
@Override
- public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber)
throws CompileError
{
Expr expr = Expr.make(TokenId.MEMBER,
- new Symbol(c), new Member(m));
- expr = CallExpr.makeCall(expr, args);
+ new Symbol(c, args.getLineNumber()), new Member(m, args.getLineNumber()), args.getLineNumber());
+ expr = CallExpr.makeCall(expr, args, args.getLineNumber());
gen.compileExpr(expr);
gen.addNullIfVoid();
}
@Override
- public void setReturnType(JvstTypeChecker check, ASTList args)
+ public void setReturnType(JvstTypeChecker check, ASTList args, int lineNumber)
throws CompileError
{
Expr expr = Expr.make(TokenId.MEMBER,
- new Symbol(c), new Member(m));
- expr = CallExpr.makeCall(expr, args);
+ new Symbol(c, args.getLineNumber()), new Member(m, args.getLineNumber()), args.getLineNumber());
+ expr = CallExpr.makeCall(expr, args, args.getLineNumber());
expr.accept(check);
check.addNullIfVoid();
}
@@ -535,14 +536,14 @@ public class Javac {
ProceedHandler h = new ProceedHandler() {
@Override
- public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber)
throws CompileError
{
gen.compileInvokeSpecial(texpr, methodIndex, descriptor, args);
}
@Override
- public void setReturnType(JvstTypeChecker c, ASTList args)
+ public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.compileInvokeSpecial(texpr, classname, methodname, descriptor, args);
diff --git a/src/main/javassist/compiler/JvstCodeGen.java b/src/main/javassist/compiler/JvstCodeGen.java
index 714b9699..6a372018 100644
--- a/src/main/javassist/compiler/JvstCodeGen.java
+++ b/src/main/javassist/compiler/JvstCodeGen.java
@@ -110,14 +110,14 @@ public class JvstCodeGen extends MemberCodeGen {
}
else if (name.equals(dollarTypeName)) {
if (dollarType == null)
- throw new CompileError(dollarTypeName + " is not available");
+ throw new CompileError(dollarTypeName + " is not available", mem.getLineNumber());
bytecode.addLdc(Descriptor.of(dollarType));
callGetType("getType");
}
else if (name.equals(clazzName)) {
if (param0Type == null)
- throw new CompileError(clazzName + " is not available");
+ throw new CompileError(clazzName + " is not available", mem.getLineNumber());
bytecode.addLdc(param0Type);
callGetType("getClazz");
@@ -141,13 +141,13 @@ public class JvstCodeGen extends MemberCodeGen {
if (left instanceof Member
&& ((Member)left).get().equals(paramArrayName)) {
if (op != '=')
- throw new CompileError("bad operator for " + paramArrayName);
+ throw new CompileError("bad operator for " + paramArrayName, expr.getLineNumber());
right.accept(this);
if (arrayDim != 1 || exprType != CLASS)
- throw new CompileError("invalid type for " + paramArrayName);
+ throw new CompileError("invalid type for " + paramArrayName, expr.getLineNumber());
- atAssignParamList(paramTypeList, bytecode);
+ atAssignParamList(paramTypeList, bytecode, expr.getLineNumber());
if (!doDup)
bytecode.addOpcode(POP);
}
@@ -155,7 +155,7 @@ public class JvstCodeGen extends MemberCodeGen {
super.atFieldAssign(expr, op, left, right, doDup);
}
- protected void atAssignParamList(CtClass[] params, Bytecode code)
+ protected void atAssignParamList(CtClass[] params, Bytecode code, int lineNumber)
throws CompileError
{
if (params == null)
@@ -167,7 +167,7 @@ public class JvstCodeGen extends MemberCodeGen {
code.addOpcode(DUP);
code.addIconst(i);
code.addOpcode(AALOAD);
- compileUnwrapValue(params[i], code);
+ compileUnwrapValue(params[i], code, lineNumber);
code.addStore(varNo, params[i]);
varNo += is2word(exprType, arrayDim) ? 2 : 1;
}
@@ -201,17 +201,17 @@ public class JvstCodeGen extends MemberCodeGen {
protected void atCastToRtype(CastExpr expr) throws CompileError {
expr.getOprand().accept(this);
if (exprType == VOID || isRefType(exprType) || arrayDim > 0)
- compileUnwrapValue(returnType, bytecode);
+ compileUnwrapValue(returnType, bytecode, expr.getLineNumber());
else if (returnType instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)returnType;
- int destType = MemberResolver.descToType(pt.getDescriptor());
+ int destType = MemberResolver.descToType(pt.getDescriptor(), expr.getLineNumber());
atNumCastExpr(exprType, destType);
exprType = destType;
arrayDim = 0;
className = null;
}
else
- throw new CompileError("invalid cast");
+ throw new CompileError("invalid cast", expr.getLineNumber());
}
protected void atCastToWrapper(CastExpr expr) throws CompileError {
@@ -219,7 +219,7 @@ public class JvstCodeGen extends MemberCodeGen {
if (isRefType(exprType) || arrayDim > 0)
return; // Object type. do nothing.
- CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
+ CtClass clazz = resolver.lookupClass(exprType, arrayDim, className, expr.getLineNumber());
if (clazz instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)clazz;
String wrapper = pt.getWrapperName();
@@ -249,11 +249,11 @@ public class JvstCodeGen extends MemberCodeGen {
if (method instanceof Member) {
String name = ((Member)method).get();
if (procHandler != null && name.equals(proceedName)) {
- procHandler.doit(this, bytecode, (ASTList)expr.oprand2());
+ procHandler.doit(this, bytecode, (ASTList)expr.oprand2(), expr.getLineNumber());
return;
}
else if (name.equals(cflowName)) {
- atCflow((ASTList)expr.oprand2());
+ atCflow((ASTList)expr.oprand2(), expr.getLineNumber());
return;
}
}
@@ -263,16 +263,16 @@ public class JvstCodeGen extends MemberCodeGen {
/* To support $cflow().
*/
- protected void atCflow(ASTList cname) throws CompileError {
+ protected void atCflow(ASTList cname, int lineNumber) throws CompileError {
StringBuilder sbuf = new StringBuilder();
if (cname == null || cname.tail() != null)
- throw new CompileError("bad " + cflowName);
+ throw new CompileError("bad " + cflowName, lineNumber);
makeCflowName(sbuf, cname.head());
String name = sbuf.toString();
Object[] names = resolver.getClassPool().lookupCflow(name);
if (names == null)
- throw new CompileError("no such " + cflowName + ": " + name);
+ throw new CompileError("no such " + cflowName + ": " + name, lineNumber);
bytecode.addGetstatic((String)names[0], (String)names[1],
"Ljavassist/runtime/Cflow;");
@@ -305,7 +305,7 @@ public class JvstCodeGen extends MemberCodeGen {
}
}
- throw new CompileError("bad " + cflowName);
+ throw new CompileError("bad " + cflowName, name.getLineNumber());
}
/* To support $$. ($$) is equivalent to ($1, ..., $n).
@@ -364,7 +364,7 @@ public class JvstCodeGen extends MemberCodeGen {
for (int k = 0; k < n; ++k) {
CtClass p = params[k];
regno += bytecode.addLoad(regno, p);
- setType(p);
+ setType(p, a.getLineNumber());
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = className;
@@ -420,7 +420,7 @@ public class JvstCodeGen extends MemberCodeGen {
atMethodArgs(args, new int[nargs], new int[nargs],
new String[nargs]);
bytecode.addInvokespecial(methodIndex, descriptor);
- setReturnType(descriptor, false, false);
+ setReturnType(descriptor, false, false, target.getLineNumber());
addNullIfVoid();
}
@@ -530,7 +530,7 @@ public class JvstCodeGen extends MemberCodeGen {
String varName = prefix + "0";
Declarator decl
= new Declarator(CLASS, MemberResolver.javaToJvmName(target),
- 0, varNo++, new Symbol(varName));
+ 0, varNo++, new Symbol(varName, 0), 0);
tbl.append(varName, decl);
}
@@ -569,11 +569,11 @@ public class JvstCodeGen extends MemberCodeGen {
className = jvmJavaLangObject;
}
else
- setType(cc);
+ setType(cc, cc.getLinesCount());
Declarator decl
= new Declarator(exprType, className, arrayDim,
- varNo, new Symbol(varName));
+ varNo, new Symbol(varName, 0), 0);
tbl.append(varName, decl);
return is2word(exprType, arrayDim) ? 2 : 1;
}
@@ -593,7 +593,7 @@ public class JvstCodeGen extends MemberCodeGen {
while ((c = typeDesc.charAt(dim)) == '[')
++dim;
- int type = MemberResolver.descToType(c);
+ int type = MemberResolver.descToType(c, -1);
String cname = null;
if (type == CLASS) {
if (dim == 0)
@@ -603,7 +603,7 @@ public class JvstCodeGen extends MemberCodeGen {
}
Declarator decl
- = new Declarator(type, cname, dim, varNo, new Symbol(varName));
+ = new Declarator(type, cname, dim, varNo, new Symbol(varName, 0), 0);
tbl.append(varName, decl);
}
@@ -653,7 +653,7 @@ public class JvstCodeGen extends MemberCodeGen {
return 8;
}
- protected void compileUnwrapValue(CtClass type, Bytecode code)
+ protected void compileUnwrapValue(CtClass type, Bytecode code, int lineNumber)
throws CompileError
{
if (type == CtClass.voidType) {
@@ -662,7 +662,7 @@ public class JvstCodeGen extends MemberCodeGen {
}
if (exprType == VOID)
- throw new CompileError("invalid type for " + returnCastName);
+ throw new CompileError("invalid type for " + returnCastName, lineNumber);
if (type instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)type;
@@ -671,34 +671,34 @@ public class JvstCodeGen extends MemberCodeGen {
code.addCheckcast(wrapper);
code.addInvokevirtual(wrapper, pt.getGetMethodName(),
pt.getGetMethodDescriptor());
- setType(type);
+ setType(type, lineNumber);
}
else {
code.addCheckcast(type);
- setType(type);
+ setType(type, lineNumber);
}
}
/* Sets exprType, arrayDim, and className;
* If type is void, then this method does nothing.
*/
- public void setType(CtClass type) throws CompileError {
- setType(type, 0);
+ public void setType(CtClass type, int lineNumber) throws CompileError {
+ setType(type, 0, lineNumber);
}
- private void setType(CtClass type, int dim) throws CompileError {
+ private void setType(CtClass type, int dim, int lineNumber) throws CompileError {
if (type.isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType)type;
- exprType = MemberResolver.descToType(pt.getDescriptor());
+ exprType = MemberResolver.descToType(pt.getDescriptor(), lineNumber);
arrayDim = dim;
className = null;
}
else if (type.isArray())
try {
- setType(type.getComponentType(), dim + 1);
+ setType(type.getComponentType(), dim + 1, lineNumber);
}
catch (NotFoundException e) {
- throw new CompileError("undefined type: " + type.getName());
+ throw new CompileError("undefined type: " + type.getName(), lineNumber);
}
else {
exprType = CLASS;
@@ -714,9 +714,9 @@ public class JvstCodeGen extends MemberCodeGen {
if (type instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)type;
atNumCastExpr(exprType,
- MemberResolver.descToType(pt.getDescriptor()));
+ MemberResolver.descToType(pt.getDescriptor(), type.getLinesCount() - 1));
}
else
- throw new CompileError("type mismatch");
+ throw new CompileError("type mismatch", type.getLinesCount() - 1);
}
}
diff --git a/src/main/javassist/compiler/JvstCodeGenWitlLineNumber.java b/src/main/javassist/compiler/JvstCodeGenWitlLineNumber.java
new file mode 100644
index 00000000..969948c5
--- /dev/null
+++ b/src/main/javassist/compiler/JvstCodeGenWitlLineNumber.java
@@ -0,0 +1,265 @@
+package javassist.compiler;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.bytecode.Bytecode;
+import javassist.bytecode.LineNumberAttribute;
+import javassist.bytecode.LineNumberAttributeBuilder;
+import javassist.compiler.ast.*;
+
+public class JvstCodeGenWitlLineNumber extends JvstCodeGen {
+ private final LineNumberAttributeBuilder lineNumberAttributeBuilder = new LineNumberAttributeBuilder();
+ public JvstCodeGenWitlLineNumber(Bytecode b, CtClass cc, ClassPool cp) {
+ super(b, cc, cp);
+ }
+
+ public LineNumberAttribute toLineNumberAttribute() {
+ return lineNumberAttributeBuilder.build(bytecode.getConstPool());
+ }
+
+ @Override
+ public void atASTList(ASTList n) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), n);
+ super.atASTList(n);
+ }
+
+ @Override
+ public void atPair(Pair n) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), n);
+ super.atPair(n);
+ }
+
+ @Override
+ public void atSymbol(Symbol n) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), n);
+ super.atSymbol(n);
+ }
+
+ @Override
+ public void atFieldDecl(FieldDecl field) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), field);
+ super.atFieldDecl(field);
+ }
+
+ @Override
+ public void atMethodDecl(MethodDecl method) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), method);
+ super.atMethodDecl(method);
+ }
+
+ @Override
+ public void atMethodBody(Stmnt s, boolean isCons, boolean isVoid) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), s);
+ super.atMethodBody(s, isCons, isVoid);
+ }
+
+ @Override
+ public void atStmnt(Stmnt st) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), st);
+ super.atStmnt(st);
+ }
+
+ @Override
+ public void atDeclarator(Declarator d) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), d);
+ super.atDeclarator(d);
+ }
+
+ @Override
+ public void atAssignExpr(AssignExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atAssignExpr(expr);
+ }
+
+ @Override
+ protected void atAssignExpr(AssignExpr expr, boolean doDup) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atAssignExpr(expr, doDup);
+ }
+
+ @Override
+ protected void atAssignCore(Expr expr, int op, ASTree right, int type, int dim, String cname) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atAssignCore(expr, op, right, type, dim, cname);
+ }
+
+ @Override
+ public void atCondExpr(CondExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atCondExpr(expr);
+ }
+
+ @Override
+ public void atBinExpr(BinExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atBinExpr(expr);
+ }
+
+ @Override
+ public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atInstanceOfExpr(expr);
+ }
+
+ @Override
+ public void atExpr(Expr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atExpr(expr);
+ }
+
+ @Override
+ public void atClassObject(Expr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atClassObject(expr);
+ }
+
+ @Override
+ public void atArrayRead(ASTree array, ASTree index) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), array);
+ super.atArrayRead(array, index);
+ }
+
+ @Override
+ protected void arrayAccess(ASTree array, ASTree index) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), array);
+ super.arrayAccess(array, index);
+ }
+
+ @Override
+ public void atArrayPlusPlus(int token, boolean isPost, Expr expr, boolean doDup) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atArrayPlusPlus(token, isPost, expr, doDup);
+ }
+
+ @Override
+ protected void atPlusPlusCore(int dup_code, boolean doDup, int token, boolean isPost, Expr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atPlusPlusCore(dup_code, doDup, token, isPost, expr);
+ }
+
+ @Override
+ public void atVariable(Variable v) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), v);
+ super.atVariable(v);
+ }
+
+ @Override
+ public void atKeyword(Keyword k) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), k);
+ super.atKeyword(k);
+ }
+
+ @Override
+ public void atStringL(javassist.compiler.ast.StringL s) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), s);
+ super.atStringL(s);
+ }
+
+ @Override
+ public void atIntConst(IntConst i) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), i);
+ super.atIntConst(i);
+ }
+
+ @Override
+ public void atDoubleConst(DoubleConst d) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), d);
+ super.atDoubleConst(d);
+ }
+
+ @Override
+ public void atMember(Member mem) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), mem);
+ super.atMember(mem);
+ }
+
+ @Override
+ protected void atFieldAssign(Expr expr, int op, ASTree left, ASTree right, boolean doDup) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atFieldAssign(expr, op, left, right, doDup);
+ }
+
+ @Override
+ public void atCastExpr(CastExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atCastExpr(expr);
+ }
+
+ @Override
+ protected void atCastToRtype(CastExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atCastToRtype(expr);
+ }
+
+ @Override
+ protected void atCastToWrapper(CastExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atCastToWrapper(expr);
+ }
+
+ @Override
+ public void atCallExpr(CallExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atCallExpr(expr);
+ }
+
+ @Override
+ protected void atCflow(ASTList cname, int lineNumber) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), cname);
+ super.atCflow(cname, lineNumber);
+ }
+
+ @Override
+ protected void atTryStmnt(Stmnt st) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), st);
+ super.atTryStmnt(st);
+ }
+
+ @Override
+ public void atNewExpr(NewExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atNewExpr(expr);
+ }
+
+ @Override
+ public void atNewArrayExpr(NewExpr expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atNewArrayExpr(expr);
+ }
+
+ @Override
+ protected void atArrayVariableAssign(ArrayInit init, int varType, int varArray, String varClass) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), init);
+ super.atArrayVariableAssign(init, varType, varArray, varClass);
+ }
+
+ @Override
+ public void atArrayInit(ArrayInit init) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), init);
+ super.atArrayInit(init);
+ }
+
+ @Override
+ protected void atMultiNewArray(int type, ASTList classname, ASTList size) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), classname);
+ super.atMultiNewArray(type, classname, size);
+ }
+
+ @Override
+ public void atMethodCallCore(CtClass targetClass, String mname, ASTList args, boolean isStatic, boolean isSpecial, int aload0pos, MemberResolver.Method found) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), args);
+ super.atMethodCallCore(targetClass, mname, args, isStatic, isSpecial, aload0pos, found);
+ }
+
+ @Override
+ protected void atFieldRead(ASTree expr) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atFieldRead(expr);
+ }
+
+ @Override
+ protected void atFieldPlusPlus(int token, boolean isPost, ASTree oprand, Expr expr, boolean doDup) throws CompileError {
+ lineNumberAttributeBuilder.put(bytecode.currentPc(), expr);
+ super.atFieldPlusPlus(token, isPost, oprand, expr, doDup);
+ }
+}
diff --git a/src/main/javassist/compiler/JvstTypeChecker.java b/src/main/javassist/compiler/JvstTypeChecker.java
index 13e47291..dbd1b358 100644
--- a/src/main/javassist/compiler/JvstTypeChecker.java
+++ b/src/main/javassist/compiler/JvstTypeChecker.java
@@ -89,7 +89,7 @@ public class JvstTypeChecker extends TypeChecker {
int n = params.length;
for (int i = 0; i < n; ++i)
- compileUnwrapValue(params[i]);
+ compileUnwrapValue(params[i], expr.getLineNumber());
}
else
super.atFieldAssign(expr, op, left, right);
@@ -124,10 +124,10 @@ public class JvstTypeChecker extends TypeChecker {
CtClass returnType = codeGen.returnType;
expr.getOprand().accept(this);
if (exprType == VOID || CodeGen.isRefType(exprType) || arrayDim > 0)
- compileUnwrapValue(returnType);
+ compileUnwrapValue(returnType, expr.getLineNumber());
else if (returnType instanceof CtPrimitiveType) {
CtPrimitiveType pt = (CtPrimitiveType)returnType;
- int destType = MemberResolver.descToType(pt.getDescriptor());
+ int destType = MemberResolver.descToType(pt.getDescriptor(), expr.getLineNumber());
exprType = destType;
arrayDim = 0;
className = null;
@@ -139,7 +139,7 @@ public class JvstTypeChecker extends TypeChecker {
if (CodeGen.isRefType(exprType) || arrayDim > 0)
return; // Object type. do nothing.
- CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
+ CtClass clazz = resolver.lookupClass(exprType, arrayDim, className, expr.getLineNumber());
if (clazz instanceof CtPrimitiveType) {
exprType = CLASS;
arrayDim = 0;
@@ -158,7 +158,7 @@ public class JvstTypeChecker extends TypeChecker {
if (codeGen.procHandler != null
&& name.equals(codeGen.proceedName)) {
codeGen.procHandler.setReturnType(this,
- (ASTList)expr.oprand2());
+ (ASTList)expr.oprand2(), expr.getLineNumber());
return;
}
else if (name.equals(JvstCodeGen.cflowName)) {
@@ -223,7 +223,7 @@ public class JvstTypeChecker extends TypeChecker {
int n = params.length;
for (int k = 0; k < n; ++k) {
CtClass p = params[k];
- setType(p);
+ setType(p, a.getLineNumber());
types[i] = exprType;
dims[i] = arrayDim;
cnames[i] = className;
@@ -254,38 +254,38 @@ public class JvstTypeChecker extends TypeChecker {
int nargs = getMethodArgsLength(args);
atMethodArgs(args, new int[nargs], new int[nargs],
new String[nargs]);
- setReturnType(descriptor);
+ setReturnType(descriptor, target.getLineNumber());
addNullIfVoid();
}
- protected void compileUnwrapValue(CtClass type) throws CompileError
+ protected void compileUnwrapValue(CtClass type, int lineNumber) throws CompileError
{
if (type == CtClass.voidType)
addNullIfVoid();
else
- setType(type);
+ setType(type, lineNumber);
}
/* Sets exprType, arrayDim, and className;
* If type is void, then this method does nothing.
*/
- public void setType(CtClass type) throws CompileError {
- setType(type, 0);
+ public void setType(CtClass type, int lineNumber) throws CompileError {
+ setType(type, 0, lineNumber);
}
- private void setType(CtClass type, int dim) throws CompileError {
+ private void setType(CtClass type, int dim, int lineNumber) throws CompileError {
if (type.isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType)type;
- exprType = MemberResolver.descToType(pt.getDescriptor());
+ exprType = MemberResolver.descToType(pt.getDescriptor(), lineNumber);
arrayDim = dim;
className = null;
}
else if (type.isArray())
try {
- setType(type.getComponentType(), dim + 1);
+ setType(type.getComponentType(), dim + 1, lineNumber);
}
catch (NotFoundException e) {
- throw new CompileError("undefined type: " + type.getName());
+ throw new CompileError("undefined type: " + type.getName(), lineNumber);
}
else {
exprType = CLASS;
diff --git a/src/main/javassist/compiler/Lex.java b/src/main/javassist/compiler/Lex.java
index b7c39a98..9f7f2ec2 100644
--- a/src/main/javassist/compiler/Lex.java
+++ b/src/main/javassist/compiler/Lex.java
@@ -39,6 +39,10 @@ public class Lex implements TokenId {
* Constructs a lexical analyzer.
*/
public Lex(String s) {
+ this(s, 0);
+ }
+
+ Lex(String s, int startLineNumber) {
lastChar = -1;
textBuffer = new StringBuilder();
currentToken = new Token();
@@ -47,7 +51,7 @@ public class Lex implements TokenId {
input = s;
position = 0;
maxlen = s.length();
- lineNumber = 0;
+ lineNumber = startLineNumber;
}
public int get() {
@@ -163,7 +167,8 @@ public class Lex implements TokenId {
ungetc(c);
c = '/';
}
- }
+ } else if (c == '\n')
+ ++lineNumber;
} while(isBlank(c));
return c;
}
@@ -529,4 +534,8 @@ public class Lex implements TokenId {
lastChar = -1;
return c;
}
+
+ public int getLineNumber() {
+ return lineNumber + 1;
+ }
}
diff --git a/src/main/javassist/compiler/MemberCodeGen.java b/src/main/javassist/compiler/MemberCodeGen.java
index e8e9912b..884b39df 100644
--- a/src/main/javassist/compiler/MemberCodeGen.java
+++ b/src/main/javassist/compiler/MemberCodeGen.java
@@ -234,7 +234,7 @@ public class MemberCodeGen extends CodeGen {
body.accept(this);
int end = bc.currentPc();
if (start == end)
- throw new CompileError("empty try block");
+ throw new CompileError("empty try block", st.getLineNumber());
boolean tryNotReturn = !hasReturned;
if (tryNotReturn) {
@@ -254,7 +254,7 @@ public class MemberCodeGen extends CodeGen {
decl.setLocalVar(var);
- CtClass type = resolver.lookupClassByJvmName(decl.getClassName());
+ CtClass type = resolver.lookupClassByJvmName(decl.getClassName(), st.getLineNumber());
decl.setClassName(MemberResolver.javaToJvmName(type.getName()));
bc.addExceptionHandler(start, end, bc.currentPc(), type);
bc.growStack(1);
@@ -346,21 +346,21 @@ public class MemberCodeGen extends CodeGen {
if (init != null)
throw new CompileError(
"sorry, multi-dimensional array initializer " +
- "for new is not supported");
+ "for new is not supported", expr.getLineNumber());
atMultiNewArray(type, classname, size);
return;
}
ASTree sizeExpr = size.head();
- atNewArrayExpr2(type, sizeExpr, Declarator.astToClassName(classname, '/'), init);
+ atNewArrayExpr2(type, sizeExpr, Declarator.astToClassName(classname, '/'), init, expr.getLineNumber());
}
private void atNewArrayExpr2(int type, ASTree sizeExpr,
- String jvmClassname, ArrayInit init) throws CompileError {
+ String jvmClassname, ArrayInit init, int lineNumber) throws CompileError {
if (init == null)
if (sizeExpr == null)
- throw new CompileError("no array size");
+ throw new CompileError("no array size", lineNumber);
else
sizeExpr.accept(this);
else
@@ -369,11 +369,11 @@ public class MemberCodeGen extends CodeGen {
bytecode.addIconst(s);
}
else
- throw new CompileError("unnecessary array size specified for new");
+ throw new CompileError("unnecessary array size specified for new", lineNumber);
String elementClass;
if (type == CLASS) {
- elementClass = resolveClassName(jvmClassname);
+ elementClass = resolveClassName(jvmClassname, lineNumber);
bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClass));
}
else {
@@ -405,7 +405,7 @@ public class MemberCodeGen extends CodeGen {
atype = T_LONG;
break;
default :
- badNewExpr();
+ badNewExpr(lineNumber);
break;
}
@@ -433,19 +433,19 @@ public class MemberCodeGen extends CodeGen {
className = elementClass;
}
- private static void badNewExpr() throws CompileError {
- throw new CompileError("bad new expression");
+ private static void badNewExpr(int lineNumber) throws CompileError {
+ throw new CompileError("bad new expression", lineNumber);
}
@Override
protected void atArrayVariableAssign(ArrayInit init, int varType,
int varArray, String varClass) throws CompileError {
- atNewArrayExpr2(varType, null, varClass, init);
+ atNewArrayExpr2(varType, null, varClass, init, init.getLineNumber());
}
@Override
public void atArrayInit(ArrayInit init) throws CompileError {
- throw new CompileError("array initializer is not supported");
+ throw new CompileError("array initializer is not supported", init.getLineNumber());
}
protected void atMultiNewArray(int type, ASTList classname, ASTList size)
@@ -461,7 +461,7 @@ public class MemberCodeGen extends CodeGen {
++count;
s.accept(this);
if (exprType != INT)
- throw new CompileError("bad type for array size");
+ throw new CompileError("bad type for array size", classname.getLineNumber());
}
String desc;
@@ -503,7 +503,7 @@ public class MemberCodeGen extends CodeGen {
mname = MethodInfo.nameInit; // <init>
targetClass = thisClass;
if (inStaticMethod)
- throw new CompileError("a constructor cannot be static");
+ throw new CompileError("a constructor cannot be static", expr.getLineNumber());
bytecode.addAload(0); // this
if (((Keyword)method).get() == SUPER)
@@ -515,7 +515,7 @@ public class MemberCodeGen extends CodeGen {
int op = e.getOperator();
if (op == MEMBER) { // static method
targetClass
- = resolver.lookupClass(((Symbol)e.oprand1()).get(), false);
+ = resolver.lookupClass(((Symbol)e.oprand1()).get(), false, expr.getLineNumber());
isStatic = true;
}
else if (op == '.') {
@@ -552,25 +552,25 @@ public class MemberCodeGen extends CodeGen {
}
if (arrayDim > 0)
- targetClass = resolver.lookupClass(javaLangObject, true);
+ targetClass = resolver.lookupClass(javaLangObject, true, expr.getLineNumber());
else if (exprType == CLASS /* && arrayDim == 0 */)
- targetClass = resolver.lookupClassByJvmName(className);
+ targetClass = resolver.lookupClassByJvmName(className, expr.getLineNumber());
else
- badMethod();
+ badMethod(e.getLineNumber());
}
}
else
- badMethod();
+ badMethod(expr.getLineNumber());
}
else
- fatal();
+ fatal(expr.getLineNumber());
atMethodCallCore(targetClass, mname, args, isStatic, isSpecial,
aload0pos, cached);
}
- private static void badMethod() throws CompileError {
- throw new CompileError("bad method");
+ private static void badMethod(int lineNumber) throws CompileError {
+ throw new CompileError("bad method", lineNumber);
}
/*
@@ -612,7 +612,7 @@ public class MemberCodeGen extends CodeGen {
msg = "Method " + mname + " not found in "
+ targetClass.getName();
- throw new CompileError(msg);
+ throw new CompileError(msg, args.getLineNumber());
}
atMethodCallCore2(targetClass, mname, isStatic, isSpecial,
@@ -645,7 +645,7 @@ public class MemberCodeGen extends CodeGen {
if (mname.equals(MethodInfo.nameInit)) {
isSpecial = true;
if (declClass != targetClass)
- throw new CompileError("no such constructor: " + targetClass.getName());
+ throw new CompileError("no such constructor: " + targetClass.getName(), targetClass.getLinesCount() - 1);
if (declClass != thisClass && AccessFlag.isPrivate(acc)) {
if (declClass.getClassFile().getMajorVersion() < ClassFile.JAVA_8
@@ -701,12 +701,12 @@ public class MemberCodeGen extends CodeGen {
}
else
if (isStatic)
- throw new CompileError(mname + " is not static");
+ throw new CompileError(mname + " is not static", targetClass.getLinesCount() - 1);
else
bytecode.addInvokevirtual(declClass, mname, desc);
}
- setReturnType(desc, isStatic, popTarget);
+ setReturnType(desc, isStatic, popTarget, targetClass.getLinesCount() - 1);
}
/*
@@ -729,7 +729,7 @@ public class MemberCodeGen extends CodeGen {
}
throw new CompileError("Method " + methodName
- + " is private");
+ + " is private", declClass.getLinesCount() - 1);
}
/*
@@ -752,7 +752,7 @@ public class MemberCodeGen extends CodeGen {
}
throw new CompileError("the called constructor is private in "
- + declClass.getName());
+ + declClass.getName(), declClass.getLinesCount() - 1);
}
private boolean isEnclosing(CtClass outer, CtClass inner) {
@@ -785,12 +785,12 @@ public class MemberCodeGen extends CodeGen {
}
}
- void setReturnType(String desc, boolean isStatic, boolean popTarget)
+ void setReturnType(String desc, boolean isStatic, boolean popTarget, int lineNumber)
throws CompileError
{
int i = desc.indexOf(')');
if (i < 0)
- badMethod();
+ badMethod(lineNumber);
char c = desc.charAt(++i);
int dim = 0;
@@ -803,13 +803,13 @@ public class MemberCodeGen extends CodeGen {
if (c == 'L') {
int j = desc.indexOf(';', i + 1);
if (j < 0)
- badMethod();
+ badMethod(lineNumber);
exprType = CLASS;
className = desc.substring(i + 1, j);
}
else {
- exprType = MemberResolver.descToType(c);
+ exprType = MemberResolver.descToType(c, lineNumber);
className = null;
}
@@ -843,15 +843,15 @@ public class MemberCodeGen extends CodeGen {
int fi;
if (op == '=') {
FieldInfo finfo = f.getFieldInfo2();
- setFieldType(finfo);
- AccessorMaker maker = isAccessibleField(f, finfo);
+ setFieldType(finfo, expr.getLineNumber());
+ AccessorMaker maker = isAccessibleField(f, finfo, expr.getLineNumber());
if (maker == null)
fi = addFieldrefInfo(f, finfo);
else
fi = 0;
}
else
- fi = atFieldRead(f, is_static);
+ fi = atFieldRead(f, is_static, expr.getLineNumber());
int fType = exprType;
int fDim = arrayDim;
@@ -921,18 +921,18 @@ public class MemberCodeGen extends CodeGen {
}
boolean is_static = resultStatic;
- ASTree cexpr = TypeChecker.getConstantFieldValue(f);
+ ASTree cexpr = TypeChecker.getConstantFieldValue(f, expr.getLineNumber());
if (cexpr == null)
- atFieldRead(f, is_static);
+ atFieldRead(f, is_static,expr.getLineNumber() );
else {
cexpr.accept(this);
- setFieldType(f.getFieldInfo2());
+ setFieldType(f.getFieldInfo2(), expr.getLineNumber());
}
}
private void atArrayLength(ASTree expr) throws CompileError {
if (arrayDim == 0)
- throw new CompileError(".length applied to a non array");
+ throw new CompileError(".length applied to a non array", expr.getLineNumber());
bytecode.addOpcode(ARRAYLENGTH);
exprType = INT;
@@ -944,10 +944,10 @@ public class MemberCodeGen extends CodeGen {
* It returns a fieldref_info index or zero if the field is a private
* one declared in an enclosing class.
*/
- private int atFieldRead(CtField f, boolean isStatic) throws CompileError {
+ private int atFieldRead(CtField f, boolean isStatic, int lineNumber) throws CompileError {
FieldInfo finfo = f.getFieldInfo2();
- boolean is2byte = setFieldType(finfo);
- AccessorMaker maker = isAccessibleField(f, finfo);
+ boolean is2byte = setFieldType(finfo, lineNumber);
+ AccessorMaker maker = isAccessibleField(f, finfo, lineNumber);
if (maker != null) {
MethodInfo minfo = maker.getFieldGetter(finfo, isStatic);
bytecode.addInvokestatic(f.getDeclaringClass(), minfo.getName(),
@@ -973,7 +973,7 @@ public class MemberCodeGen extends CodeGen {
* an exception or it returns AccessorMaker if the field is a private
* one declared in an enclosing class.
*/
- private AccessorMaker isAccessibleField(CtField f, FieldInfo finfo)
+ private AccessorMaker isAccessibleField(CtField f, FieldInfo finfo, int lineNumber)
throws CompileError
{
if (AccessFlag.isPrivate(finfo.getAccessFlags())
@@ -985,7 +985,7 @@ public class MemberCodeGen extends CodeGen {
return maker;
}
throw new CompileError("Field " + f.getName() + " in "
- + declClass.getName() + " is private.");
+ + declClass.getName() + " is private.", lineNumber);
}
return null; // accessible field
@@ -996,7 +996,7 @@ public class MemberCodeGen extends CodeGen {
*
* @return true if the field type is long or double.
*/
- private boolean setFieldType(FieldInfo finfo) throws CompileError {
+ private boolean setFieldType(FieldInfo finfo, int lineNumber) throws CompileError {
String type = finfo.getDescriptor();
int i = 0;
@@ -1008,7 +1008,7 @@ public class MemberCodeGen extends CodeGen {
}
arrayDim = dim;
- exprType = MemberResolver.descToType(c);
+ exprType = MemberResolver.descToType(c, lineNumber);
if (c == 'L')
className = type.substring(i + 1, type.indexOf(';', i + 1));
@@ -1046,7 +1046,7 @@ public class MemberCodeGen extends CodeGen {
if (!is_static)
bytecode.addOpcode(DUP);
- int fi = atFieldRead(f, is_static);
+ int fi = atFieldRead(f, is_static, oprand.getLineNumber());
int t = exprType;
boolean is2w = is2word(t, arrayDim);
@@ -1082,7 +1082,7 @@ public class MemberCodeGen extends CodeGen {
if (!is_static)
if (inStaticMethod)
throw new CompileError(
- "not available in a static method: " + name);
+ "not available in a static method: " + name, expr.getLineNumber());
else
bytecode.addAload(0); // this
@@ -1117,7 +1117,7 @@ public class MemberCodeGen extends CodeGen {
&& ((Symbol)e.oprand2()).get().equals("length"))
return null; // expr is an array length.
else
- badLvalue();
+ badLvalue(expr.getLineNumber());
boolean is_static = Modifier.isStatic(f.getModifiers());
if (is_static)
@@ -1142,17 +1142,17 @@ public class MemberCodeGen extends CodeGen {
}
}
else
- badLvalue();
+ badLvalue(expr.getLineNumber());
}
else
- badLvalue();
+ badLvalue(expr.getLineNumber());
resultStatic = false;
return null; // never reach
}
- private static void badLvalue() throws CompileError {
- throw new CompileError("bad l-value");
+ private static void badLvalue(int lineNumber) throws CompileError {
+ throw new CompileError("bad l-value", lineNumber);
}
public CtClass[] makeParamList(MethodDecl md) throws CompileError {
@@ -1201,7 +1201,7 @@ public class MemberCodeGen extends CodeGen {
* For example, this converts Object into java/lang/Object.
*/
@Override
- protected String resolveClassName(String jvmName) throws CompileError {
- return resolver.resolveJvmClassName(jvmName);
+ protected String resolveClassName(String jvmName, int lineNumber) throws CompileError {
+ return resolver.resolveJvmClassName(jvmName, lineNumber);
}
}
diff --git a/src/main/javassist/compiler/MemberResolver.java b/src/main/javassist/compiler/MemberResolver.java
index dd271368..3b0cc012 100644
--- a/src/main/javassist/compiler/MemberResolver.java
+++ b/src/main/javassist/compiler/MemberResolver.java
@@ -50,8 +50,8 @@ public class MemberResolver implements TokenId {
public ClassPool getClassPool() { return classPool; }
- private static void fatal() throws CompileError {
- throw new CompileError("fatal");
+ private static void fatal(int lineNumber) throws CompileError {
+ throw new CompileError("fatal", lineNumber);
}
public static class Method {
@@ -85,7 +85,7 @@ public class MemberResolver implements TokenId {
if (current != null && clazz == currentClass)
if (current.getName().equals(methodName)) {
int res = compareSignature(current.getDescriptor(),
- argTypes, argDims, argClassNames);
+ argTypes, argDims, argClassNames, currentClass.getLinesCount() - 1);
if (res != NO) {
Method r = new Method(clazz, current, res);
if (res == YES)
@@ -116,7 +116,7 @@ public class MemberResolver implements TokenId {
if (minfo.getName().equals(methodName)
&& (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0) {
int res = compareSignature(minfo.getDescriptor(),
- argTypes, argDims, argClassNames);
+ argTypes, argDims, argClassNames, clazz.getLinesCount() - 1);
if (res != NO) {
Method r = new Method(clazz, minfo, res);
if (res == YES)
@@ -199,7 +199,7 @@ public class MemberResolver implements TokenId {
* of parameter types that do not exactly match.
*/
private int compareSignature(String desc, int[] argTypes,
- int[] argDims, String[] argClassNames)
+ int[] argDims, String[] argClassNames, int lineNumber)
throws CompileError
{
int result = YES;
@@ -247,9 +247,9 @@ public class MemberResolver implements TokenId {
String cname = desc.substring(i, j);
if (!cname.equals(argClassNames[n])) {
- CtClass clazz = lookupClassByJvmName(argClassNames[n]);
+ CtClass clazz = lookupClassByJvmName(argClassNames[n], lineNumber);
try {
- if (clazz.subtypeOf(lookupClassByJvmName(cname)))
+ if (clazz.subtypeOf(lookupClassByJvmName(cname, lineNumber)))
result++;
else
return NO;
@@ -262,7 +262,7 @@ public class MemberResolver implements TokenId {
i = j + 1;
}
else {
- int t = descToType(c);
+ int t = descToType(c, lineNumber);
int at = argTypes[n];
if (t != at)
if (t == INT
@@ -280,7 +280,7 @@ public class MemberResolver implements TokenId {
* Only used by fieldAccess() in MemberCodeGen and TypeChecker.
*
* @param jvmClassName a JVM class name. e.g. java/lang/String
- * @see #lookupClass(String, boolean)
+ * @see #lookupClass(String, boolean, int)
*/
public CtField lookupFieldByJvmName2(String jvmClassName, Symbol fieldSym,
ASTree expr) throws NoFieldException
@@ -288,7 +288,7 @@ public class MemberResolver implements TokenId {
String field = fieldSym.get();
CtClass cc = null;
try {
- cc = lookupClass(jvmToJavaName(jvmClassName), true);
+ cc = lookupClass(jvmToJavaName(jvmClassName), true, expr.getLineNumber());
}
catch (CompileError e) {
// EXPR might be part of a qualified class name.
@@ -320,55 +320,56 @@ public class MemberResolver implements TokenId {
public CtField lookupField(String className, Symbol fieldName)
throws CompileError
{
- CtClass cc = lookupClass(className, false);
+ CtClass cc = lookupClass(className, false, fieldName.getLineNumber());
try {
return cc.getField(fieldName.get());
}
catch (NotFoundException e) {}
- throw new CompileError("no such field: " + fieldName.get());
+ throw new CompileError("no such field: " + fieldName.get(), fieldName.getLineNumber());
}
public CtClass lookupClassByName(ASTList name) throws CompileError {
- return lookupClass(Declarator.astToClassName(name, '.'), false);
+ return lookupClass(Declarator.astToClassName(name, '.'), false, name.getLineNumber());
}
- public CtClass lookupClassByJvmName(String jvmName) throws CompileError {
- return lookupClass(jvmToJavaName(jvmName), false);
+ public CtClass lookupClassByJvmName(String jvmName, int lineNumber) throws CompileError {
+ return lookupClass(jvmToJavaName(jvmName), false, lineNumber);
}
public CtClass lookupClass(Declarator decl) throws CompileError {
return lookupClass(decl.getType(), decl.getArrayDim(),
- decl.getClassName());
+ decl.getClassName(), decl.getLineNumber());
}
/**
- * @param classname jvm class name.
+ * @param classname jvm class name.
+ * @param lineNumber
*/
- public CtClass lookupClass(int type, int dim, String classname)
+ public CtClass lookupClass(int type, int dim, String classname, int lineNumber)
throws CompileError
{
String cname = "";
CtClass clazz;
if (type == CLASS) {
- clazz = lookupClassByJvmName(classname);
+ clazz = lookupClassByJvmName(classname, lineNumber);
if (dim > 0)
cname = clazz.getName();
else
return clazz;
}
else
- cname = getTypeName(type);
+ cname = getTypeName(type, lineNumber);
while (dim-- > 0)
cname += "[]";
- return lookupClass(cname, false);
+ return lookupClass(cname, false, lineNumber);
}
/*
* type cannot be CLASS
*/
- static String getTypeName(int type) throws CompileError {
+ static String getTypeName(int type, int lineNumber) throws CompileError {
String cname = "";
switch (type) {
case BOOLEAN :
@@ -399,22 +400,23 @@ public class MemberResolver implements TokenId {
cname = "void";
break;
default :
- fatal();
+ fatal(lineNumber);
}
return cname;
}
/**
- * @param name a qualified class name. e.g. java.lang.String
+ * @param name a qualified class name. e.g. java.lang.String
+ * @param lineNumber
*/
- public CtClass lookupClass(String name, boolean notCheckInner)
+ public CtClass lookupClass(String name, boolean notCheckInner, int lineNumber)
throws CompileError
{
Map<String,String> cache = getInvalidNames();
String found = cache.get(name);
if (found == INVALID)
- throw new CompileError("no such class: " + name);
+ throw new CompileError("no such class: " + name, lineNumber);
else if (found != null)
try {
return classPool.get(found);
@@ -426,7 +428,7 @@ public class MemberResolver implements TokenId {
cc = lookupClass0(name, notCheckInner);
}
catch (NotFoundException e) {
- cc = searchImports(name);
+ cc = searchImports(name, lineNumber);
}
cache.put(name, cc.getName());
@@ -461,7 +463,7 @@ public class MemberResolver implements TokenId {
return ht;
}
- private CtClass searchImports(String orgName)
+ private CtClass searchImports(String orgName, int lineNumber)
throws CompileError
{
if (orgName.indexOf('.') < 0) {
@@ -483,7 +485,7 @@ public class MemberResolver implements TokenId {
}
getInvalidNames().put(orgName, INVALID);
- throw new CompileError("no such class: " + orgName);
+ throw new CompileError("no such class: " + orgName, lineNumber);
}
private CtClass lookupClass0(String classname, boolean notCheckInner)
@@ -520,10 +522,10 @@ public class MemberResolver implements TokenId {
/* Expands a simple class name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
- public String resolveJvmClassName(String jvmName) throws CompileError {
+ public String resolveJvmClassName(String jvmName, int lineNumber) throws CompileError {
if (jvmName == null)
return null;
- return javaToJvmName(lookupClassByJvmName(jvmName).getName());
+ return javaToJvmName(lookupClassByJvmName(jvmName, lineNumber).getName());
}
public static CtClass getSuperclass(CtClass c) throws CompileError {
@@ -534,7 +536,7 @@ public class MemberResolver implements TokenId {
}
catch (NotFoundException e) {}
throw new CompileError("cannot find the super class of "
- + c.getName());
+ + c.getName(), c.getLinesCount() - 1);
}
public static CtClass getSuperInterface(CtClass c, String interfaceName)
@@ -547,7 +549,7 @@ public class MemberResolver implements TokenId {
return intfs[i];
} catch (NotFoundException e) {}
throw new CompileError("cannot find the super interface " + interfaceName
- + " of " + c.getName());
+ + " of " + c.getName(), c.getLinesCount() - 1);
}
public static String javaToJvmName(String classname) {
@@ -558,7 +560,7 @@ public class MemberResolver implements TokenId {
return classname.replace('/', '.');
}
- public static int descToType(char c) throws CompileError {
+ public static int descToType(char c, int lineNumber) throws CompileError {
switch (c) {
case 'Z' :
return BOOLEAN;
@@ -582,7 +584,7 @@ public class MemberResolver implements TokenId {
case '[' :
return CLASS;
default :
- fatal();
+ fatal(lineNumber);
return VOID; // never reach here
}
}
diff --git a/src/main/javassist/compiler/NoFieldException.java b/src/main/javassist/compiler/NoFieldException.java
index dd878590..898998d1 100644
--- a/src/main/javassist/compiler/NoFieldException.java
+++ b/src/main/javassist/compiler/NoFieldException.java
@@ -27,7 +27,7 @@ public class NoFieldException extends CompileError {
/* NAME must be JVM-internal representation.
*/
public NoFieldException(String name, ASTree e) {
- super("no such field: " + name);
+ super("no such field: " + name, e.getLineNumber());
fieldName = name;
expr = e;
}
diff --git a/src/main/javassist/compiler/Parser.java b/src/main/javassist/compiler/Parser.java
index 2b0dfd69..7e742a6b 100644
--- a/src/main/javassist/compiler/Parser.java
+++ b/src/main/javassist/compiler/Parser.java
@@ -66,7 +66,7 @@ public final class Parser implements TokenId {
Declarator d;
boolean isConstructor = false;
if (lex.lookAhead() == Identifier && lex.lookAhead(1) == '(') {
- d = new Declarator(VOID, 0);
+ d = new Declarator(VOID, 0, lex.getLineNumber());
isConstructor = true;
}
else
@@ -81,7 +81,7 @@ public final class Parser implements TokenId {
else
name = lex.getString();
- d.setVariable(new Symbol(name));
+ d.setVariable(new Symbol(name, lex.getLineNumber()));
if (isConstructor || lex.lookAhead() == '(')
return parseMethod1(tbl, isConstructor, mods, d);
return parseField(tbl, mods, d);
@@ -103,7 +103,7 @@ public final class Parser implements TokenId {
int c = lex.get();
if (c == ';')
- return new FieldDecl(mods, new ASTList(d, new ASTList(expr)));
+ return new FieldDecl(mods, new ASTList(d, new ASTList(expr, lex.getLineNumber()), lex.getLineNumber()), lex.getLineNumber());
else if (c == ',')
throw new CompileError(
"only one field can be declared in one declaration", lex);
@@ -131,7 +131,7 @@ public final class Parser implements TokenId {
ASTList parms = null;
if (lex.lookAhead() != ')')
while (true) {
- parms = ASTList.append(parms, parseFormalParam(tbl));
+ parms = ASTList.append(parms, parseFormalParam(tbl), lex.getLineNumber());
int t = lex.lookAhead();
if (t == ',')
lex.get();
@@ -148,7 +148,7 @@ public final class Parser implements TokenId {
if (lex.lookAhead() == THROWS) {
lex.get();
while (true) {
- throwsList = ASTList.append(throwsList, parseClassType(tbl));
+ throwsList = ASTList.append(throwsList, parseClassType(tbl), lex.getLineNumber());
if (lex.lookAhead() == ',')
lex.get();
else
@@ -157,7 +157,7 @@ public final class Parser implements TokenId {
}
return new MethodDecl(mods, new ASTList(d,
- ASTList.make(parms, throwsList, null)));
+ ASTList.make(parms, throwsList, null, lex.getLineNumber()), lex.getLineNumber()), lex.getLineNumber());
}
/* Parses a method body.
@@ -171,7 +171,7 @@ public final class Parser implements TokenId {
else {
body = parseBlock(tbl);
if (body == null)
- body = new Stmnt(BLOCK);
+ body = new Stmnt(BLOCK, lex.getLineNumber());
}
md.sublist(4).setHead(body);
@@ -191,7 +191,7 @@ public final class Parser implements TokenId {
if (t == ABSTRACT || t == FINAL || t == PUBLIC || t == PROTECTED
|| t == PRIVATE || t == SYNCHRONIZED || t == STATIC
|| t == VOLATILE || t == TRANSIENT || t == STRICT)
- list = new ASTList(new Keyword(lex.get()), list);
+ list = new ASTList(new Keyword(lex.get(), lex.getLineNumber()), list, lex.getLineNumber());
else
break;
}
@@ -206,11 +206,11 @@ public final class Parser implements TokenId {
if (isBuiltinType(t) || t == VOID) {
lex.get(); // primitive type
int dim = parseArrayDimension();
- return new Declarator(t, dim);
+ return new Declarator(t, dim, lex.getLineNumber());
}
ASTList name = parseClassType(tbl);
int dim = parseArrayDimension();
- return new Declarator(name, dim);
+ return new Declarator(name, dim, lex.getLineNumber());
}
private static boolean isBuiltinType(int t) {
@@ -228,7 +228,7 @@ public final class Parser implements TokenId {
throw new SyntaxError(lex);
String name = lex.getString();
- d.setVariable(new Symbol(name));
+ d.setVariable(new Symbol(name, lex.getLineNumber()));
d.addArrayDim(parseArrayDimension());
tbl.append(name, d);
return d;
@@ -261,13 +261,13 @@ public final class Parser implements TokenId {
return parseBlock(tbl);
else if (t == ';') {
lex.get();
- return new Stmnt(BLOCK); // empty statement
+ return new Stmnt(BLOCK, lex.getLineNumber()); // empty statement
}
else if (t == Identifier && lex.lookAhead(1) == ':') {
lex.get(); // Identifier
String label = lex.getString();
lex.get(); // ':'
- return Stmnt.make(LABEL, new Symbol(label), parseStatement(tbl));
+ return Stmnt.make(LABEL, new Symbol(label, lex.getLineNumber()), parseStatement(tbl), lex.getLineNumber());
}
else if (t == IF)
return parseIf(tbl);
@@ -298,20 +298,22 @@ public final class Parser implements TokenId {
/* block.statement : "{" statement* "}"
*/
private Stmnt parseBlock(SymbolTable tbl) throws CompileError {
+ int blockLineNumber = lex.getLineNumber();
if (lex.get() != '{')
throw new SyntaxError(lex);
Stmnt body = null;
SymbolTable tbl2 = new SymbolTable(tbl);
while (lex.lookAhead() != '}') {
+ int lineNumber = lex.getLineNumber();
Stmnt s = parseStatement(tbl2);
if (s != null)
- body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s));
+ body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s, lineNumber));
}
lex.get(); // '}'
if (body == null)
- return new Stmnt(BLOCK); // empty block
+ return new Stmnt(BLOCK, blockLineNumber); // empty block
return body;
}
@@ -321,7 +323,9 @@ public final class Parser implements TokenId {
private Stmnt parseIf(SymbolTable tbl) throws CompileError {
int t = lex.get(); // IF
ASTree expr = parseParExpression(tbl);
+ int exprLineNum = lex.getLineNumber();
Stmnt thenp = parseStatement(tbl);
+ int thenLineNum = lex.getLineNumber();
Stmnt elsep;
if (lex.lookAhead() == ELSE) {
lex.get();
@@ -330,7 +334,7 @@ public final class Parser implements TokenId {
else
elsep = null;
- return new Stmnt(t, expr, new ASTList(thenp, new ASTList(elsep)));
+ return new Stmnt(t, expr, new ASTList(thenp, new ASTList(elsep, lex.getLineNumber()), thenLineNum), exprLineNum);
}
/* while.statement : WHILE "(" expression ")" statement
@@ -340,8 +344,9 @@ public final class Parser implements TokenId {
{
int t = lex.get(); // WHILE
ASTree expr = parseParExpression(tbl);
+ int lineNumber = lex.getLineNumber();
Stmnt body = parseStatement(tbl);
- return new Stmnt(t, expr, body);
+ return new Stmnt(t, expr, body, lineNumber);
}
/* do.statement : DO statement WHILE "(" expression ")" ";"
@@ -356,7 +361,7 @@ public final class Parser implements TokenId {
if (lex.get() != ')' || lex.get() != ';')
throw new SyntaxError(lex);
- return new Stmnt(t, expr, body);
+ return new Stmnt(t, expr, body, lex.getLineNumber());
}
/* for.statement : FOR "(" decl.or.expr expression ";" expression ")"
@@ -372,6 +377,7 @@ public final class Parser implements TokenId {
if (lex.get() != '(')
throw new SyntaxError(lex);
+ int expr1LineNumber = lex.getLineNumber();
if (lex.lookAhead() == ';') {
lex.get();
expr1 = null;
@@ -379,6 +385,7 @@ public final class Parser implements TokenId {
else
expr1 = parseDeclarationOrExpression(tbl2, true);
+ int expr2LineNumber = lex.getLineNumber();
if (lex.lookAhead() == ';')
expr2 = null;
else
@@ -387,6 +394,7 @@ public final class Parser implements TokenId {
if (lex.get() != ';')
throw new CompileError("; is missing", lex);
+ int expr3LineNumber = lex.getLineNumber();
if (lex.lookAhead() == ')')
expr3 = null;
else
@@ -397,7 +405,7 @@ public final class Parser implements TokenId {
Stmnt body = parseStatement(tbl2);
return new Stmnt(t, expr1, new ASTList(expr2,
- new ASTList(expr3, body)));
+ new ASTList(expr3, body, expr3LineNumber), expr2LineNumber), expr1LineNumber);
}
/* switch.statement : SWITCH "(" expression ")" "{" switch.block "}"
@@ -411,7 +419,7 @@ public final class Parser implements TokenId {
int t = lex.get(); // SWITCH
ASTree expr = parseParExpression(tbl);
Stmnt body = parseSwitchBlock(tbl);
- return new Stmnt(t, expr, body);
+ return new Stmnt(t, expr, body, lex.getLineNumber());
}
private Stmnt parseSwitchBlock(SymbolTable tbl) throws CompileError {
@@ -428,17 +436,17 @@ public final class Parser implements TokenId {
throw new CompileError("no case or default in a switch block",
lex);
- Stmnt body = new Stmnt(BLOCK, s);
+ Stmnt body = new Stmnt(BLOCK, s, lex.getLineNumber());
while (lex.lookAhead() != '}') {
Stmnt s2 = parseStmntOrCase(tbl2);
if (s2 != null) {
int op2 = s2.getOperator();
if (op2 == CASE || op2 == DEFAULT) {
- body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s2));
+ body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s2, lex.getLineNumber()));
s = s2;
}
else
- s = (Stmnt)ASTList.concat(s, new Stmnt(BLOCK, s2));
+ s = (Stmnt)ASTList.concat(s, new Stmnt(BLOCK, s2, lex.getLineNumber()));
}
}
@@ -454,9 +462,9 @@ public final class Parser implements TokenId {
lex.get();
Stmnt s;
if (t == CASE)
- s = new Stmnt(t, parseExpression(tbl));
+ s = new Stmnt(t, parseExpression(tbl), lex.getLineNumber());
else
- s = new Stmnt(DEFAULT);
+ s = new Stmnt(DEFAULT, lex.getLineNumber());
if (lex.get() != ':')
throw new CompileError(": is missing", lex);
@@ -477,7 +485,7 @@ public final class Parser implements TokenId {
throw new SyntaxError(lex);
Stmnt body = parseBlock(tbl);
- return new Stmnt(t, expr, body);
+ return new Stmnt(t, expr, body, lex.getLineNumber());
}
/* try.statement
@@ -503,7 +511,7 @@ public final class Parser implements TokenId {
throw new SyntaxError(lex);
Stmnt b = parseBlock(tbl2);
- catchList = ASTList.append(catchList, new Pair(d, b));
+ catchList = ASTList.append(catchList, new Pair(d, b), lex.getLineNumber());
}
Stmnt finallyBlock = null;
@@ -512,14 +520,14 @@ public final class Parser implements TokenId {
finallyBlock = parseBlock(tbl);
}
- return Stmnt.make(TRY, block, catchList, finallyBlock);
+ return Stmnt.make(TRY, block, catchList, finallyBlock, lex.getLineNumber());
}
/* return.statement : RETURN [ expression ] ";"
*/
private Stmnt parseReturn(SymbolTable tbl) throws CompileError {
int t = lex.get(); // RETURN
- Stmnt s = new Stmnt(t);
+ Stmnt s = new Stmnt(t, lex.getLineNumber());
if (lex.lookAhead() != ';')
s.setLeft(parseExpression(tbl));
@@ -537,7 +545,7 @@ public final class Parser implements TokenId {
if (lex.get() != ';')
throw new CompileError("; is missing", lex);
- return new Stmnt(t, expr);
+ return new Stmnt(t, expr, lex.getLineNumber());
}
/* break.statement : BREAK [ Identifier ] ";"
@@ -554,10 +562,10 @@ public final class Parser implements TokenId {
throws CompileError
{
int t = lex.get(); // CONTINUE
- Stmnt s = new Stmnt(t);
+ Stmnt s = new Stmnt(t, lex.getLineNumber());
int t2 = lex.get();
if (t2 == Identifier) {
- s.setLeft(new Symbol(lex.getString()));
+ s.setLeft(new Symbol(lex.getString(), lex.getLineNumber()));
t2 = lex.get();
}
@@ -589,7 +597,7 @@ public final class Parser implements TokenId {
if (isBuiltinType(t)) {
t = lex.get();
int dim = parseArrayDimension();
- return parseDeclarators(tbl, new Declarator(t, dim));
+ return parseDeclarators(tbl, new Declarator(t, dim, lex.getLineNumber()));
}
else if (t == Identifier) {
int i = nextIsClassType(0);
@@ -597,7 +605,7 @@ public final class Parser implements TokenId {
if (lex.lookAhead(i) == Identifier) {
ASTList name = parseClassType(tbl);
int dim = parseArrayDimension();
- return parseDeclarators(tbl, new Declarator(name, dim));
+ return parseDeclarators(tbl, new Declarator(name, dim, lex.getLineNumber()));
}
}
@@ -605,7 +613,7 @@ public final class Parser implements TokenId {
if (exprList)
expr = parseExprList(tbl);
else
- expr = new Stmnt(EXPR, parseExpression(tbl));
+ expr = new Stmnt(EXPR, parseExpression(tbl), lex.getLineNumber());
if (lex.get() != ';')
throw new CompileError("; is missing", lex);
@@ -618,8 +626,8 @@ public final class Parser implements TokenId {
private Stmnt parseExprList(SymbolTable tbl) throws CompileError {
Stmnt expr = null;
for (;;) {
- Stmnt e = new Stmnt(EXPR, parseExpression(tbl));
- expr = (Stmnt)ASTList.concat(expr, new Stmnt(BLOCK, e));
+ Stmnt e = new Stmnt(EXPR, parseExpression(tbl), lex.getLineNumber());
+ expr = (Stmnt)ASTList.concat(expr, new Stmnt(BLOCK, e, lex.getLineNumber()));
if (lex.lookAhead() == ',')
lex.get();
else
@@ -635,7 +643,7 @@ public final class Parser implements TokenId {
Stmnt decl = null;
for (;;) {
decl = (Stmnt)ASTList.concat(decl,
- new Stmnt(DECL, parseDeclarator(tbl, d)));
+ new Stmnt(DECL, parseDeclarator(tbl, d), lex.getLineNumber()));
int t = lex.get();
if (t == ';')
return decl;
@@ -653,7 +661,7 @@ public final class Parser implements TokenId {
throw new SyntaxError(lex);
String name = lex.getString();
- Symbol symbol = new Symbol(name);
+ Symbol symbol = new Symbol(name, lex.getLineNumber());
int dim = parseArrayDimension();
ASTree init = null;
if (lex.lookAhead() == '=') {
@@ -661,7 +669,7 @@ public final class Parser implements TokenId {
init = parseInitializer(tbl);
}
- Declarator decl = d.make(symbol, dim, init);
+ Declarator decl = d.make(symbol, dim, init, lex.getLineNumber());
tbl.append(name, decl);
return decl;
}
@@ -683,14 +691,14 @@ public final class Parser implements TokenId {
lex.get(); // '{'
if(lex.lookAhead() == '}'){
lex.get();
- return new ArrayInit(null);
+ return new ArrayInit(null, lex.getLineNumber());
}
ASTree expr = parseExpression(tbl);
- ArrayInit init = new ArrayInit(expr);
+ ArrayInit init = new ArrayInit(expr, lex.getLineNumber());
while (lex.lookAhead() == ',') {
lex.get();
expr = parseExpression(tbl);
- ASTList.append(init, expr);
+ ASTList.append(init, expr, lex.getLineNumber());
}
if (lex.get() != '}')
@@ -722,7 +730,7 @@ public final class Parser implements TokenId {
int t = lex.get();
ASTree right = parseExpression(tbl);
- return AssignExpr.makeAssign(t, left, right);
+ return AssignExpr.makeAssign(t, left, right, lex.getLineNumber());
}
private static boolean isAssignOp(int t) {
@@ -744,7 +752,7 @@ public final class Parser implements TokenId {
throw new CompileError(": is missing", lex);
ASTree elseExpr = parseExpression(tbl);
- return new CondExpr(cond, thenExpr, elseExpr);
+ return new CondExpr(cond, thenExpr, elseExpr, lex.getLineNumber());
}
return cond;
}
@@ -808,11 +816,11 @@ public final class Parser implements TokenId {
if (isBuiltinType(t)) {
lex.get(); // primitive type
int dim = parseArrayDimension();
- return new InstanceOfExpr(t, dim, expr);
+ return new InstanceOfExpr(t, dim, expr, lex.getLineNumber());
}
ASTList name = parseClassType(tbl);
int dim = parseArrayDimension();
- return new InstanceOfExpr(name, dim, expr);
+ return new InstanceOfExpr(name, dim, expr, lex.getLineNumber());
}
private ASTree binaryExpr2(SymbolTable tbl, ASTree expr, int prec)
@@ -829,7 +837,7 @@ public final class Parser implements TokenId {
if (p2 != 0 && prec > p2)
expr2 = binaryExpr2(tbl, expr2, p2);
else
- return BinExpr.makeBin(t, expr, expr2);
+ return BinExpr.makeBin(t, expr, expr2, lex.getLineNumber());
}
}
@@ -887,17 +895,17 @@ public final class Parser implements TokenId {
case IntConstant :
case CharConstant :
lex.get();
- return new IntConst(-lex.getLong(), t2);
+ return new IntConst(-lex.getLong(), t2, lex.getLineNumber());
case DoubleConstant :
case FloatConstant :
lex.get();
- return new DoubleConst(-lex.getDouble(), t2);
+ return new DoubleConst(-lex.getDouble(), t2, lex.getLineNumber());
default :
break;
}
}
- return Expr.make(t, parseUnaryExpr(tbl));
+ return Expr.make(t, parseUnaryExpr(tbl), lex.getLineNumber());
case '(' :
return parseCast(tbl);
default :
@@ -922,7 +930,7 @@ public final class Parser implements TokenId {
if (lex.get() != ')')
throw new CompileError(") is missing", lex);
- return new CastExpr(t, dim, parseUnaryExpr(tbl));
+ return new CastExpr(t, dim, parseUnaryExpr(tbl), lex.getLineNumber());
}
else if (t == Identifier && nextIsClassCast()) {
lex.get(); // '('
@@ -931,7 +939,7 @@ public final class Parser implements TokenId {
if (lex.get() != ')')
throw new CompileError(") is missing", lex);
- return new CastExpr(name, dim, parseUnaryExpr(tbl));
+ return new CastExpr(name, dim, parseUnaryExpr(tbl), lex.getLineNumber());
}
else
return parsePostfix(tbl);
@@ -1001,7 +1009,7 @@ public final class Parser implements TokenId {
if (lex.get() != Identifier)
throw new SyntaxError(lex);
- list = ASTList.append(list, new Symbol(lex.getString()));
+ list = ASTList.append(list, new Symbol(lex.getString(), lex.getLineNumber()), lex.getLineNumber());
if (lex.lookAhead() == '.')
lex.get();
else
@@ -1035,11 +1043,11 @@ public final class Parser implements TokenId {
case IntConstant :
case CharConstant :
lex.get();
- return new IntConst(lex.getLong(), token);
+ return new IntConst(lex.getLong(), token, lex.getLineNumber());
case DoubleConstant :
case FloatConstant :
lex.get();
- return new DoubleConst(lex.getDouble(), token);
+ return new DoubleConst(lex.getDouble(), token, lex.getLineNumber());
default :
break;
}
@@ -1066,13 +1074,13 @@ public final class Parser implements TokenId {
if (index == null)
throw new SyntaxError(lex);
- expr = Expr.make(ARRAY, expr, index);
+ expr = Expr.make(ARRAY, expr, index, lex.getLineNumber());
}
break;
case PLUSPLUS :
case MINUSMINUS :
t = lex.get();
- expr = Expr.make(t, null, expr);
+ expr = Expr.make(t, null, expr, lex.getLineNumber());
break;
case '.' :
lex.get();
@@ -1080,10 +1088,10 @@ public final class Parser implements TokenId {
if (t == CLASS)
expr = parseDotClass(expr, 0);
else if (t == SUPER)
- expr = Expr.make('.', new Symbol(toClassName(expr)), new Keyword(t));
+ expr = Expr.make('.', new Symbol(toClassName(expr), lex.getLineNumber()), new Keyword(t, lex.getLineNumber()), lex.getLineNumber());
else if (t == Identifier) {
str = lex.getString();
- expr = Expr.make('.', expr, new Member(str));
+ expr = Expr.make('.', expr, new Member(str, lex.getLineNumber()), lex.getLineNumber());
}
else
throw new CompileError("missing member name", lex);
@@ -1095,8 +1103,8 @@ public final class Parser implements TokenId {
throw new CompileError("missing static member name", lex);
str = lex.getString();
- expr = Expr.make(MEMBER, new Symbol(toClassName(expr)),
- new Member(str));
+ expr = Expr.make(MEMBER, new Symbol(toClassName(expr), lex.getLineNumber()),
+ new Member(str, lex.getLineNumber()), lex.getLineNumber());
break;
default :
return expr;
@@ -1121,7 +1129,7 @@ public final class Parser implements TokenId {
cname = sbuf.toString();
}
- return Expr.make('.', new Symbol(cname), new Member("class"));
+ return Expr.make('.', new Symbol(cname, className.getLineNumber()), new Member("class", className.getLineNumber()), lex.getLineNumber());
}
/* Parses a .class expression on a built-in type. For example,
@@ -1133,7 +1141,7 @@ public final class Parser implements TokenId {
{
if (dim > 0) {
String cname = CodeGen.toJvmTypeName(builtinType, dim);
- return Expr.make('.', new Symbol(cname), new Member("class"));
+ return Expr.make('.', new Symbol(cname, lex.getLineNumber()), new Member("class", lex.getLineNumber()), lex.getLineNumber());
}
String cname;
switch(builtinType) {
@@ -1166,10 +1174,10 @@ public final class Parser implements TokenId {
break;
default :
throw new CompileError("invalid builtin type: "
- + builtinType);
+ + builtinType, lex);
}
- return Expr.make(MEMBER, new Symbol(cname), new Member("TYPE"));
+ return Expr.make(MEMBER, new Symbol(cname, lex.getLineNumber()), new Member("TYPE", lex.getLineNumber()), lex.getLineNumber());
}
/* method.call : method.expr "(" argument.list ")"
@@ -1193,7 +1201,7 @@ public final class Parser implements TokenId {
throw new SyntaxError(lex);
}
- return CallExpr.makeCall(expr, parseArgumentList(tbl));
+ return CallExpr.makeCall(expr, parseArgumentList(tbl), lex.getLineNumber());
}
private String toClassName(ASTree name)
@@ -1246,15 +1254,15 @@ public final class Parser implements TokenId {
case TRUE :
case FALSE :
case NULL :
- return new Keyword(t);
+ return new Keyword(t, lex.getLineNumber());
case Identifier :
name = lex.getString();
decl = tbl.lookup(name);
if (decl == null)
- return new Member(name); // this or static member
- return new Variable(name, decl); // local variable
+ return new Member(name, lex.getLineNumber()); // this or static member
+ return new Variable(name, decl, lex.getLineNumber()); // local variable
case StringL :
- return new StringL(lex.getString());
+ return new StringL(lex.getString(), lex.getLineNumber());
case NEW :
return parseNew(tbl);
case '(' :
@@ -1286,21 +1294,21 @@ public final class Parser implements TokenId {
if (lex.lookAhead() == '{')
init = parseArrayInitializer(tbl);
- return new NewExpr(t, size, init);
+ return new NewExpr(t, size, init, lex.getLineNumber());
}
else if (t == Identifier) {
ASTList name = parseClassType(tbl);
t = lex.lookAhead();
if (t == '(') {
ASTList args = parseArgumentList(tbl);
- return new NewExpr(name, args);
+ return new NewExpr(name, args, lex.getLineNumber());
}
else if (t == '[') {
ASTList size = parseArraySize(tbl);
if (lex.lookAhead() == '{')
init = parseArrayInitializer(tbl);
- return NewExpr.makeObjectArray(name, size, init);
+ return NewExpr.makeObjectArray(name, size, init, lex.getLineNumber());
}
}
@@ -1312,7 +1320,7 @@ public final class Parser implements TokenId {
private ASTList parseArraySize(SymbolTable tbl) throws CompileError {
ASTList list = null;
while (lex.lookAhead() == '[')
- list = ASTList.append(list, parseArrayIndex(tbl));
+ list = ASTList.append(list, parseArrayIndex(tbl), lex.getLineNumber());
return list;
}
@@ -1341,7 +1349,7 @@ public final class Parser implements TokenId {
ASTList list = null;
if (lex.lookAhead() != ')')
for (;;) {
- list = ASTList.append(list, parseExpression(tbl));
+ list = ASTList.append(list, parseExpression(tbl), lex.getLineNumber());
if (lex.lookAhead() == ',')
lex.get();
else
diff --git a/src/main/javassist/compiler/ProceedHandler.java b/src/main/javassist/compiler/ProceedHandler.java
index 1c3cd47a..04023717 100644
--- a/src/main/javassist/compiler/ProceedHandler.java
+++ b/src/main/javassist/compiler/ProceedHandler.java
@@ -25,6 +25,6 @@ import javassist.compiler.ast.ASTList;
* @see javassist.compiler.JvstCodeGen#setProceedHandler(ProceedHandler, String)
*/
public interface ProceedHandler {
- void doit(JvstCodeGen gen, Bytecode b, ASTList args) throws CompileError;
- void setReturnType(JvstTypeChecker c, ASTList args) throws CompileError;
+ void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber) throws CompileError;
+ void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) throws CompileError;
}
diff --git a/src/main/javassist/compiler/TypeChecker.java b/src/main/javassist/compiler/TypeChecker.java
index bceba419..0d7c8e92 100644
--- a/src/main/javassist/compiler/TypeChecker.java
+++ b/src/main/javassist/compiler/TypeChecker.java
@@ -73,14 +73,14 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* into a String object.
*/
protected static String argTypesToString(int[] types, int[] dims,
- String[] cnames) {
+ String[] cnames, int lineNumber) {
StringBuilder sbuf = new StringBuilder();
sbuf.append('(');
int n = types.length;
if (n > 0) {
int i = 0;
while (true) {
- typeToString(sbuf, types[i], dims[i], cnames[i]);
+ typeToString(sbuf, types[i], dims[i], cnames[i], lineNumber);
if (++i < n)
sbuf.append(',');
else
@@ -97,7 +97,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* into a String object.
*/
protected static StringBuilder typeToString(StringBuilder sbuf,
- int type, int dim, String cname) {
+ int type, int dim, String cname, int lineNumber) {
String s;
if (type == CLASS)
s = MemberResolver.jvmToJavaName(cname);
@@ -105,7 +105,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
s = "Object";
else
try {
- s = MemberResolver.getTypeName(type);
+ s = MemberResolver.getTypeName(type, lineNumber);
}
catch (CompileError e) {
s = "?";
@@ -125,8 +125,8 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
thisMethod = m;
}
- protected static void fatal() throws CompileError {
- throw new CompileError("fatal");
+ protected static void fatal(int lineLum) throws CompileError {
+ throw new CompileError("fatal", lineLum);
}
/**
@@ -156,8 +156,8 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
/* Expands a simple class name to java.lang.*.
* For example, this converts Object into java/lang/Object.
*/
- protected String resolveClassName(String jvmName) throws CompileError {
- return resolver.resolveJvmClassName(jvmName);
+ protected String resolveClassName(String jvmName, int lineNumber) throws CompileError {
+ return resolver.resolveJvmClassName(jvmName, lineNumber);
}
@Override
@@ -168,7 +168,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
CtClass clazz = resolver.lookupClassByName(expr.getClassName());
String cname = clazz.getName();
ASTList args = expr.getArguments();
- atMethodCallCore(clazz, MethodInfo.nameInit, args);
+ atMethodCallCore(clazz, MethodInfo.nameInit, args, expr.getLineNumber());
exprType = CLASS;
arrayDim = 0;
className = MemberResolver.javaToJvmName(cname);
@@ -294,7 +294,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
throws CompileError
{
CtField f = fieldAccess(left);
- atFieldRead(f);
+ atFieldRead(f, expr.getLineNumber());
int fType = exprType;
int fDim = arrayDim;
String cname = className;
@@ -316,9 +316,9 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
if (dim1 == 0 && dim1 == arrayDim)
if (CodeGen.rightIsStrong(type1, exprType))
- expr.setThen(new CastExpr(exprType, 0, expr.thenExpr()));
+ expr.setThen(new CastExpr(exprType, 0, expr.thenExpr(), expr.getLineNumber()));
else if (CodeGen.rightIsStrong(exprType, type1)) {
- expr.setElse(new CastExpr(type1, 0, expr.elseExpr()));
+ expr.setElse(new CastExpr(type1, 0, expr.elseExpr(), expr.getLineNumber()));
exprType = type1;
}
}
@@ -343,7 +343,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* an expression using StringBuffer.
*/
e = CallExpr.makeCall(Expr.make('.', e,
- new Member("toString")), null);
+ new Member("toString", expr.getLineNumber()), expr.getLineNumber()), null, expr.getLineNumber());
expr.setOprand1(e);
expr.setOprand2(null); // <---- look at this!
className = jvmJavaLangString;
@@ -404,9 +404,10 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
if ((type1 == CLASS && dim1 == 0 && jvmJavaLangString.equals(cname))
|| (exprType == CLASS && arrayDim == 0
&& jvmJavaLangString.equals(className))) {
- ASTList sbufClass = ASTList.make(new Symbol("java"),
- new Symbol("lang"), new Symbol("StringBuffer"));
- ASTree e = new NewExpr(sbufClass, null);
+ int lineNum = expr.getLineNumber();
+ ASTList sbufClass = ASTList.make(new Symbol("java", lineNum),
+ new Symbol("lang", lineNum), new Symbol("StringBuffer", lineNum), lineNum);
+ ASTree e = new NewExpr(sbufClass, null, lineNum);
exprType = CLASS;
arrayDim = 0;
className = "java/lang/StringBuffer";
@@ -424,7 +425,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
ASTree newExpr = null;
if (left instanceof StringL && right instanceof StringL && op == '+')
newExpr = new StringL(((StringL)left).get()
- + ((StringL)right).get());
+ + ((StringL)right).get(), left.getLineNumber());
else if (left instanceof IntConst)
newExpr = ((IntConst)left).compute(op, right);
else if (left instanceof DoubleConst)
@@ -451,7 +452,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
Expr e = (Expr)expr;
int op = e.getOperator();
if (op == MEMBER) {
- ASTree cexpr = getConstantFieldValue((Member)e.oprand2());
+ ASTree cexpr = getConstantFieldValue((Member)e.oprand2(), expr.getLineNumber());
if (cexpr != null)
return cexpr;
}
@@ -459,7 +460,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
return e.getLeft();
}
else if (expr instanceof Member) {
- ASTree cexpr = getConstantFieldValue((Member)expr);
+ ASTree cexpr = getConstantFieldValue((Member)expr, expr.getLineNumber());
if (cexpr != null)
return cexpr;
}
@@ -471,11 +472,11 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* If MEM is a static final field, this method returns a constant
* expression representing the value of that field.
*/
- private static ASTree getConstantFieldValue(Member mem) {
- return getConstantFieldValue(mem.getField());
+ private static ASTree getConstantFieldValue(Member mem, int lineNumber) {
+ return getConstantFieldValue(mem.getField(), lineNumber);
}
- public static ASTree getConstantFieldValue(CtField f) {
+ public static ASTree getConstantFieldValue(CtField f, int lineNumber) {
if (f == null)
return null;
@@ -484,19 +485,19 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
return null;
if (value instanceof String)
- return new StringL((String)value);
+ return new StringL((String)value, lineNumber);
else if (value instanceof Double || value instanceof Float) {
int token = (value instanceof Double)
? DoubleConstant : FloatConstant;
- return new DoubleConst(((Number)value).doubleValue(), token);
+ return new DoubleConst(((Number)value).doubleValue(), token, lineNumber);
}
else if (value instanceof Number) {
int token = (value instanceof Long) ? LongConstant : IntConstant;
- return new IntConst(((Number)value).longValue(), token);
+ return new IntConst(((Number)value).longValue(), token, lineNumber);
}
else if (value instanceof Boolean)
return new Keyword(((Boolean)value).booleanValue()
- ? TokenId.TRUE : TokenId.FALSE);
+ ? TokenId.TRUE : TokenId.FALSE, lineNumber);
else
return null;
}
@@ -512,8 +513,8 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
}
private static Expr makeAppendCall(ASTree target, ASTree arg) {
- return CallExpr.makeCall(Expr.make('.', target, new Member("append")),
- new ASTList(arg));
+ return CallExpr.makeCall(Expr.make('.', target, new Member("append", target.getLineNumber()), target.getLineNumber()),
+ new ASTList(arg, target.getLineNumber()), target.getLineNumber());
}
private void computeBinExprType(BinExpr expr, int token, int type1)
@@ -561,7 +562,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
throws CompileError
{
if (CodeGen.rightIsStrong(type1, type2))
- expr.setLeft(new CastExpr(type2, 0, expr.oprand1()));
+ expr.setLeft(new CastExpr(type2, 0, expr.oprand1(), expr.getLineNumber()));
else
exprType = type1;
}
@@ -618,7 +619,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
else if (token == '!')
booleanExpr(expr);
else if (token == CALL) // method call
- fatal();
+ fatal(expr.getLineNumber());
else {
oprand.accept(this);
if (!isConstant(expr, token, oprand))
@@ -681,7 +682,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
if (op == MEMBER) // static method
targetClass
= resolver.lookupClass(((Symbol)e.oprand1()).get(),
- false);
+ false, e.getLineNumber());
else if (op == '.') {
ASTree target = e.oprand1();
String classFollowedByDotSuper = isDotSuper(target);
@@ -702,30 +703,30 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
className = nfe.getField(); // JVM-internal
e.setOperator(MEMBER);
e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(
- className)));
+ className), e.getLineNumber()));
}
if (arrayDim > 0)
- targetClass = resolver.lookupClass(javaLangObject, true);
+ targetClass = resolver.lookupClass(javaLangObject, true, e.getLineNumber());
else if (exprType == CLASS /* && arrayDim == 0 */)
- targetClass = resolver.lookupClassByJvmName(className);
+ targetClass = resolver.lookupClassByJvmName(className, e.getLineNumber());
else
- badMethod();
+ badMethod(e.getLineNumber());
}
}
else
- badMethod();
+ badMethod(expr.getLineNumber());
}
else
- fatal();
+ fatal(expr.getLineNumber());
MemberResolver.Method minfo
- = atMethodCallCore(targetClass, mname, args);
+ = atMethodCallCore(targetClass, mname, args, expr.getLineNumber());
expr.setMethod(minfo);
}
- private static void badMethod() throws CompileError {
- throw new CompileError("bad method");
+ private static void badMethod(int lineNumber) throws CompileError {
+ throw new CompileError("bad method", lineNumber);
}
/**
@@ -753,7 +754,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
* and the MethodInfo of that method. Never null.
*/
public MemberResolver.Method atMethodCallCore(CtClass targetClass,
- String mname, ASTList args)
+ String mname, ASTList args, int lineNumber)
throws CompileError
{
int nargs = getMethodArgsLength(args);
@@ -767,18 +768,18 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
mname, types, dims, cnames);
if (found == null) {
String clazz = targetClass.getName();
- String signature = argTypesToString(types, dims, cnames);
+ String signature = argTypesToString(types, dims, cnames, lineNumber);
String msg;
if (mname.equals(MethodInfo.nameInit))
msg = "cannot find constructor " + clazz + signature;
else
msg = mname + signature + " not found in " + clazz;
- throw new CompileError(msg);
+ throw new CompileError(msg, lineNumber);
}
String desc = found.info.getDescriptor();
- setReturnType(desc);
+ setReturnType(desc, lineNumber);
return found;
}
@@ -800,10 +801,10 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
}
}
- void setReturnType(String desc) throws CompileError {
+ void setReturnType(String desc, int lineNumber) throws CompileError {
int i = desc.indexOf(')');
if (i < 0)
- badMethod();
+ badMethod(lineNumber);
char c = desc.charAt(++i);
int dim = 0;
@@ -816,22 +817,22 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
if (c == 'L') {
int j = desc.indexOf(';', i + 1);
if (j < 0)
- badMethod();
+ badMethod(lineNumber);
exprType = CLASS;
className = desc.substring(i + 1, j);
}
else {
- exprType = MemberResolver.descToType(c);
+ exprType = MemberResolver.descToType(c, lineNumber);
className = null;
}
}
private void atFieldRead(ASTree expr) throws CompileError {
- atFieldRead(fieldAccess(expr));
+ atFieldRead(fieldAccess(expr), expr.getLineNumber());
}
- private void atFieldRead(CtField f) throws CompileError {
+ private void atFieldRead(CtField f, int lineNumber) throws CompileError {
FieldInfo finfo = f.getFieldInfo2();
String type = finfo.getDescriptor();
@@ -844,7 +845,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
}
arrayDim = dim;
- exprType = MemberResolver.descToType(c);
+ exprType = MemberResolver.descToType(c, lineNumber);
if (c == 'L')
className = type.substring(i + 1, type.indexOf(';', i + 1));
@@ -933,14 +934,14 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
}
}
- throw new CompileError("bad field access");
+ throw new CompileError("bad field access", expr.getLineNumber());
}
private CtField fieldAccess2(Expr e, String jvmClassName) throws CompileError {
Member fname = (Member)e.oprand2();
CtField f = resolver.lookupFieldByJvmName2(jvmClassName, fname, e);
e.setOperator(MEMBER);
- e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(jvmClassName)));
+ e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(jvmClassName), e.getLineNumber()));
fname.setField(f);
return f;
}
@@ -1006,7 +1007,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
protected void atFieldPlusPlus(ASTree oprand) throws CompileError
{
CtField f = fieldAccess(oprand);
- atFieldRead(f);
+ atFieldRead(f, oprand.getLineNumber());
int t = exprType;
if (t == INT || t == BYTE || t == CHAR || t == SHORT)
exprType = INT;
@@ -1046,7 +1047,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
className = getSuperName();
break;
default :
- fatal();
+ fatal(k.getLineNumber());
}
}
diff --git a/src/main/javassist/compiler/ast/ASTList.java b/src/main/javassist/compiler/ast/ASTList.java
index d9232ca0..786957f5 100644
--- a/src/main/javassist/compiler/ast/ASTList.java
+++ b/src/main/javassist/compiler/ast/ASTList.java
@@ -28,18 +28,18 @@ public class ASTList extends ASTree {
private ASTree left;
private ASTList right;
- public ASTList(ASTree _head, ASTList _tail) {
+ public ASTList(ASTree _head, ASTList _tail, int lineNumber) {
+ super(lineNumber);
left = _head;
right = _tail;
}
- public ASTList(ASTree _head) {
- left = _head;
- right = null;
+ public ASTList(ASTree _head, int lineNumber) {
+ this(_head, null, lineNumber);
}
- public static ASTList make(ASTree e1, ASTree e2, ASTree e3) {
- return new ASTList(e1, new ASTList(e2, new ASTList(e3)));
+ public static ASTList make(ASTree e1, ASTree e2, ASTree e3 , int lineNumber) {
+ return new ASTList(e1, new ASTList(e2, new ASTList(e3, lineNumber), lineNumber), lineNumber);
}
@Override
@@ -146,8 +146,8 @@ public class ASTList extends ASTree {
/**
* Appends an object to a list.
*/
- public static ASTList append(ASTList a, ASTree b) {
- return concat(a, new ASTList(b));
+ public static ASTList append(ASTList a, ASTree b, int lineNumber) {
+ return concat(a, new ASTList(b, lineNumber));
}
/**
diff --git a/src/main/javassist/compiler/ast/ASTree.java b/src/main/javassist/compiler/ast/ASTree.java
index 3d4dd842..f155fa87 100644
--- a/src/main/javassist/compiler/ast/ASTree.java
+++ b/src/main/javassist/compiler/ast/ASTree.java
@@ -29,6 +29,12 @@ public abstract class ASTree implements Serializable {
/** default serialVersionUID */
private static final long serialVersionUID = 1L;
+ private final int lineNumber;
+
+ public ASTree(int lineNumber) {
+ this.lineNumber = lineNumber;
+ }
+
public ASTree getLeft() { return null; }
public ASTree getRight() { return null; }
@@ -61,4 +67,8 @@ public abstract class ASTree implements Serializable {
String name = getClass().getName();
return name.substring(name.lastIndexOf('.') + 1);
}
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
}
diff --git a/src/main/javassist/compiler/ast/ArrayInit.java b/src/main/javassist/compiler/ast/ArrayInit.java
index 0b87200e..bc3f06ea 100644
--- a/src/main/javassist/compiler/ast/ArrayInit.java
+++ b/src/main/javassist/compiler/ast/ArrayInit.java
@@ -27,10 +27,12 @@ public class ArrayInit extends ASTList {
/**
* Constructs an object.
- * @param firstElement maybe null when the initializer is <code>{}</code> (empty).
+ *
+ * @param firstElement maybe null when the initializer is <code>{}</code> (empty).
+ * @param lineNumber
*/
- public ArrayInit(ASTree firstElement) {
- super(firstElement);
+ public ArrayInit(ASTree firstElement, int lineNumber) {
+ super(firstElement, lineNumber);
}
/**
diff --git a/src/main/javassist/compiler/ast/AssignExpr.java b/src/main/javassist/compiler/ast/AssignExpr.java
index a5e1857d..97dfc6e7 100644
--- a/src/main/javassist/compiler/ast/AssignExpr.java
+++ b/src/main/javassist/compiler/ast/AssignExpr.java
@@ -29,13 +29,13 @@ public class AssignExpr extends Expr {
/** default serialVersionUID */
private static final long serialVersionUID = 1L;
- private AssignExpr(int op, ASTree _head, ASTList _tail) {
- super(op, _head, _tail);
+ private AssignExpr(int op, ASTree _head, ASTList _tail, int lineNumber) {
+ super(op, _head, _tail, lineNumber);
}
public static AssignExpr makeAssign(int op, ASTree oprand1,
- ASTree oprand2) {
- return new AssignExpr(op, oprand1, new ASTList(oprand2));
+ ASTree oprand2, int lineNumber) {
+ return new AssignExpr(op, oprand1, new ASTList(oprand2, lineNumber), lineNumber);
}
@Override
diff --git a/src/main/javassist/compiler/ast/BinExpr.java b/src/main/javassist/compiler/ast/BinExpr.java
index 9630ada9..789312ec 100644
--- a/src/main/javassist/compiler/ast/BinExpr.java
+++ b/src/main/javassist/compiler/ast/BinExpr.java
@@ -33,12 +33,12 @@ public class BinExpr extends Expr {
/** default serialVersionUID */
private static final long serialVersionUID = 1L;
- private BinExpr(int op, ASTree _head, ASTList _tail) {
- super(op, _head, _tail);
+ private BinExpr(int op, ASTree _head, ASTList _tail, int lineNumber) {
+ super(op, _head, _tail, lineNumber);
}
- public static BinExpr makeBin(int op, ASTree oprand1, ASTree oprand2) {
- return new BinExpr(op, oprand1, new ASTList(oprand2));
+ public static BinExpr makeBin(int op, ASTree oprand1, ASTree oprand2, int lineNumber) {
+ return new BinExpr(op, oprand1, new ASTList(oprand2, lineNumber), lineNumber);
}
@Override
diff --git a/src/main/javassist/compiler/ast/CallExpr.java b/src/main/javassist/compiler/ast/CallExpr.java
index 395915ed..72a3ca51 100644
--- a/src/main/javassist/compiler/ast/CallExpr.java
+++ b/src/main/javassist/compiler/ast/CallExpr.java
@@ -28,8 +28,8 @@ public class CallExpr extends Expr {
private static final long serialVersionUID = 1L;
private MemberResolver.Method method; // cached result of lookupMethod()
- private CallExpr(ASTree _head, ASTList _tail) {
- super(TokenId.CALL, _head, _tail);
+ private CallExpr(ASTree _head, ASTList _tail, int lineNumber) {
+ super(TokenId.CALL, _head, _tail, lineNumber);
method = null;
}
@@ -41,8 +41,8 @@ public class CallExpr extends Expr {
return method;
}
- public static CallExpr makeCall(ASTree target, ASTree args) {
- return new CallExpr(target, new ASTList(args));
+ public static CallExpr makeCall(ASTree target, ASTree args, int lineNumber) {
+ return new CallExpr(target, new ASTList(args, lineNumber), lineNumber);
}
@Override
diff --git a/src/main/javassist/compiler/ast/CastExpr.java b/src/main/javassist/compiler/ast/CastExpr.java
index 903e5bbd..d3938078 100644
--- a/src/main/javassist/compiler/ast/CastExpr.java
+++ b/src/main/javassist/compiler/ast/CastExpr.java
@@ -28,14 +28,14 @@ public class CastExpr extends ASTList implements TokenId {
protected int castType;
protected int arrayDim;
- public CastExpr(ASTList className, int dim, ASTree expr) {
- super(className, new ASTList(expr));
+ public CastExpr(ASTList className, int dim, ASTree expr, int lineNumber) {
+ super(className, new ASTList(expr, lineNumber), lineNumber);
castType = CLASS;
arrayDim = dim;
}
- public CastExpr(int type, int dim, ASTree expr) {
- super(null, new ASTList(expr));
+ public CastExpr(int type, int dim, ASTree expr, int lineNumber) {
+ super(null, new ASTList(expr, lineNumber), lineNumber);
castType = type;
arrayDim = dim;
}
diff --git a/src/main/javassist/compiler/ast/CondExpr.java b/src/main/javassist/compiler/ast/CondExpr.java
index 46435012..e4b6e07b 100644
--- a/src/main/javassist/compiler/ast/CondExpr.java
+++ b/src/main/javassist/compiler/ast/CondExpr.java
@@ -25,8 +25,8 @@ public class CondExpr extends ASTList {
/** default serialVersionUID */
private static final long serialVersionUID = 1L;
- public CondExpr(ASTree cond, ASTree thenp, ASTree elsep) {
- super(cond, new ASTList(thenp, new ASTList(elsep)));
+ public CondExpr(ASTree cond, ASTree thenp, ASTree elsep, int lineNumber) {
+ super(cond, new ASTList(thenp, new ASTList(elsep, lineNumber), lineNumber), lineNumber);
}
public ASTree condExpr() { return head(); }
diff --git a/src/main/javassist/compiler/ast/Declarator.java b/src/main/javassist/compiler/ast/Declarator.java
index c29f6740..1713d908 100644
--- a/src/main/javassist/compiler/ast/Declarator.java
+++ b/src/main/javassist/compiler/ast/Declarator.java
@@ -30,16 +30,16 @@ public class Declarator extends ASTList implements TokenId {
protected int localVar;
protected String qualifiedClass; // JVM-internal representation
- public Declarator(int type, int dim) {
- super(null);
+ public Declarator(int type, int dim, int lineNumber) {
+ super(null, lineNumber);
varType = type;
arrayDim = dim;
localVar = -1;
qualifiedClass = null;
}
- public Declarator(ASTList className, int dim) {
- super(null);
+ public Declarator(ASTList className, int dim, int lineNumber) {
+ super(null, lineNumber);
varType = CLASS;
arrayDim = dim;
localVar = -1;
@@ -49,21 +49,21 @@ public class Declarator extends ASTList implements TokenId {
/* For declaring a pre-defined? local variable.
*/
public Declarator(int type, String jvmClassName, int dim,
- int var, Symbol sym) {
- super(null);
+ int var, Symbol sym, int lineNumber) {
+ super(null, lineNumber);
varType = type;
arrayDim = dim;
localVar = var;
qualifiedClass = jvmClassName;
setLeft(sym);
- append(this, null); // initializer
+ append(this, null, lineNumber); // initializer
}
- public Declarator make(Symbol sym, int dim, ASTree init) {
- Declarator d = new Declarator(this.varType, this.arrayDim + dim);
+ public Declarator make(Symbol sym, int dim, ASTree init, int lineNumber) {
+ Declarator d = new Declarator(this.varType, this.arrayDim + dim, lineNumber);
d.qualifiedClass = this.qualifiedClass;
d.setLeft(sym);
- append(d, init);
+ append(d, init, lineNumber);
return d;
}
diff --git a/src/main/javassist/compiler/ast/DoubleConst.java b/src/main/javassist/compiler/ast/DoubleConst.java
index f8d0afde..d55821f0 100644
--- a/src/main/javassist/compiler/ast/DoubleConst.java
+++ b/src/main/javassist/compiler/ast/DoubleConst.java
@@ -28,7 +28,11 @@ public class DoubleConst extends ASTree {
protected double value;
protected int type;
- public DoubleConst(double v, int tokenId) { value = v; type = tokenId; }
+ public DoubleConst(double v, int tokenId, int lineNumber) {
+ super(lineNumber);
+ value = v;
+ type = tokenId;
+ }
public double get() { return value; }
@@ -63,15 +67,15 @@ public class DoubleConst extends ASTree {
else
newType = TokenId.FloatConstant;
- return compute(op, this.value, right.value, newType);
+ return compute(op, this.value, right.value, newType, getLineNumber());
}
private DoubleConst compute0(int op, IntConst right) {
- return compute(op, this.value, right.value, this.type);
+ return compute(op, this.value, right.value, this.type, getLineNumber());
}
private static DoubleConst compute(int op, double value1, double value2,
- int newType)
+ int newType, int lineNumber)
{
double newValue;
switch (op) {
@@ -94,6 +98,6 @@ public class DoubleConst extends ASTree {
return null;
}
- return new DoubleConst(newValue, newType);
+ return new DoubleConst(newValue, newType, lineNumber);
}
}
diff --git a/src/main/javassist/compiler/ast/Expr.java b/src/main/javassist/compiler/ast/Expr.java
index ed5cb60b..4d2ce1a0 100644
--- a/src/main/javassist/compiler/ast/Expr.java
+++ b/src/main/javassist/compiler/ast/Expr.java
@@ -33,22 +33,22 @@ public class Expr extends ASTList implements TokenId {
private static final long serialVersionUID = 1L;
protected int operatorId;
- Expr(int op, ASTree _head, ASTList _tail) {
- super(_head, _tail);
+ Expr(int op, ASTree _head, ASTList _tail, int lineNumber) {
+ super(_head, _tail, lineNumber);
operatorId = op;
}
- Expr(int op, ASTree _head) {
- super(_head);
+ Expr(int op, ASTree _head, int lineNumber) {
+ super(_head, lineNumber);
operatorId = op;
}
- public static Expr make(int op, ASTree oprand1, ASTree oprand2) {
- return new Expr(op, oprand1, new ASTList(oprand2));
+ public static Expr make(int op, ASTree oprand1, ASTree oprand2, int lineNumber) {
+ return new Expr(op, oprand1, new ASTList(oprand2, lineNumber), lineNumber);
}
- public static Expr make(int op, ASTree oprand1) {
- return new Expr(op, oprand1);
+ public static Expr make(int op, ASTree oprand1, int lineNumber) {
+ return new Expr(op, oprand1, lineNumber);
}
public int getOperator() { return operatorId; }
diff --git a/src/main/javassist/compiler/ast/FieldDecl.java b/src/main/javassist/compiler/ast/FieldDecl.java
index e2a066e9..44df192e 100644
--- a/src/main/javassist/compiler/ast/FieldDecl.java
+++ b/src/main/javassist/compiler/ast/FieldDecl.java
@@ -22,8 +22,8 @@ public class FieldDecl extends ASTList {
/** default serialVersionUID */
private static final long serialVersionUID = 1L;
- public FieldDecl(ASTree _head, ASTList _tail) {
- super(_head, _tail);
+ public FieldDecl(ASTree _head, ASTList _tail, int lineNumber) {
+ super(_head, _tail, lineNumber);
}
public ASTList getModifiers() { return (ASTList)getLeft(); }
diff --git a/src/main/javassist/compiler/ast/InstanceOfExpr.java b/src/main/javassist/compiler/ast/InstanceOfExpr.java
index ddf07bd2..e012defe 100644
--- a/src/main/javassist/compiler/ast/InstanceOfExpr.java
+++ b/src/main/javassist/compiler/ast/InstanceOfExpr.java
@@ -25,12 +25,12 @@ public class InstanceOfExpr extends CastExpr {
/** default serialVersionUID */
private static final long serialVersionUID = 1L;
- public InstanceOfExpr(ASTList className, int dim, ASTree expr) {
- super(className, dim, expr);
+ public InstanceOfExpr(ASTList className, int dim, ASTree expr, int lineNumber) {
+ super(className, dim, expr, lineNumber);
}
- public InstanceOfExpr(int type, int dim, ASTree expr) {
- super(type, dim, expr);
+ public InstanceOfExpr(int type, int dim, ASTree expr, int lineNumber) {
+ super(type, dim, expr, lineNumber);
}
@Override
diff --git a/src/main/javassist/compiler/ast/IntConst.java b/src/main/javassist/compiler/ast/IntConst.java
index 7040b0c9..8ffce479 100644
--- a/src/main/javassist/compiler/ast/IntConst.java
+++ b/src/main/javassist/compiler/ast/IntConst.java
@@ -28,7 +28,11 @@ public class IntConst extends ASTree {
protected long value;
protected int type;
- public IntConst(long v, int tokenId) { value = v; type = tokenId; }
+ public IntConst(long v, int tokenId, int lineNumber) {
+ super(lineNumber);
+ value = v;
+ type = tokenId;
+ }
public long get() { return value; }
@@ -111,7 +115,7 @@ public class IntConst extends ASTree {
return null;
}
- return new IntConst(newValue, newType);
+ return new IntConst(newValue, newType, right.getLineNumber());
}
private DoubleConst compute0(int op, DoubleConst right) {
@@ -138,6 +142,6 @@ public class IntConst extends ASTree {
return null;
}
- return new DoubleConst(newValue, right.type);
+ return new DoubleConst(newValue, right.type, right.getLineNumber());
}
}
diff --git a/src/main/javassist/compiler/ast/Keyword.java b/src/main/javassist/compiler/ast/Keyword.java
index b509375c..858316d5 100644
--- a/src/main/javassist/compiler/ast/Keyword.java
+++ b/src/main/javassist/compiler/ast/Keyword.java
@@ -26,7 +26,8 @@ public class Keyword extends ASTree {
private static final long serialVersionUID = 1L;
protected int tokenId;
- public Keyword(int token) {
+ public Keyword(int token, int lineNumber) {
+ super(lineNumber);
tokenId = token;
}
diff --git a/src/main/javassist/compiler/ast/Member.java b/src/main/javassist/compiler/ast/Member.java
index 192c9ef3..279e2516 100644
--- a/src/main/javassist/compiler/ast/Member.java
+++ b/src/main/javassist/compiler/ast/Member.java
@@ -29,8 +29,8 @@ public class Member extends Symbol {
// this is used to obtain the value of a static final field.
private CtField field;
- public Member(String name) {
- super(name);
+ public Member(String name, int lineNumber) {
+ super(name, lineNumber);
field = null;
}
diff --git a/src/main/javassist/compiler/ast/MethodDecl.java b/src/main/javassist/compiler/ast/MethodDecl.java
index d96e3d4d..263775b0 100644
--- a/src/main/javassist/compiler/ast/MethodDecl.java
+++ b/src/main/javassist/compiler/ast/MethodDecl.java
@@ -23,8 +23,8 @@ public class MethodDecl extends ASTList {
private static final long serialVersionUID = 1L;
public static final String initName = "<init>";
- public MethodDecl(ASTree _head, ASTList _tail) {
- super(_head, _tail);
+ public MethodDecl(ASTree _head, ASTList _tail, int lineNumber) {
+ super(_head, _tail, lineNumber);
}
public boolean isConstructor() {
diff --git a/src/main/javassist/compiler/ast/NewExpr.java b/src/main/javassist/compiler/ast/NewExpr.java
index 44b264c0..d4f7f475 100644
--- a/src/main/javassist/compiler/ast/NewExpr.java
+++ b/src/main/javassist/compiler/ast/NewExpr.java
@@ -28,26 +28,26 @@ public class NewExpr extends ASTList implements TokenId {
protected boolean newArray;
protected int arrayType;
- public NewExpr(ASTList className, ASTList args) {
- super(className, new ASTList(args));
+ public NewExpr(ASTList className, ASTList args, int lineNumber) {
+ super(className, new ASTList(args, lineNumber), lineNumber);
newArray = false;
arrayType = CLASS;
}
- public NewExpr(int type, ASTList arraySize, ArrayInit init) {
- super(null, new ASTList(arraySize));
+ public NewExpr(int type, ASTList arraySize, ArrayInit init, int lineNumber) {
+ super(null, new ASTList(arraySize, lineNumber), lineNumber);
newArray = true;
arrayType = type;
if (init != null)
- append(this, init);
+ append(this, init, lineNumber);
}
public static NewExpr makeObjectArray(ASTList className,
- ASTList arraySize, ArrayInit init) {
- NewExpr e = new NewExpr(className, arraySize);
+ ASTList arraySize, ArrayInit init, int lineNumber) {
+ NewExpr e = new NewExpr(className, arraySize, lineNumber);
e.newArray = true;
if (init != null)
- append(e, init);
+ append(e, init, lineNumber);
return e;
}
diff --git a/src/main/javassist/compiler/ast/Pair.java b/src/main/javassist/compiler/ast/Pair.java
index 949028a4..44411b8d 100644
--- a/src/main/javassist/compiler/ast/Pair.java
+++ b/src/main/javassist/compiler/ast/Pair.java
@@ -28,6 +28,7 @@ public class Pair extends ASTree {
protected ASTree left, right;
public Pair(ASTree _left, ASTree _right) {
+ super(_left.getLineNumber());
left = _left;
right = _right;
}
diff --git a/src/main/javassist/compiler/ast/Stmnt.java b/src/main/javassist/compiler/ast/Stmnt.java
index c5aa5df3..7333d026 100644
--- a/src/main/javassist/compiler/ast/Stmnt.java
+++ b/src/main/javassist/compiler/ast/Stmnt.java
@@ -27,26 +27,26 @@ public class Stmnt extends ASTList implements TokenId {
private static final long serialVersionUID = 1L;
protected int operatorId;
- public Stmnt(int op, ASTree _head, ASTList _tail) {
- super(_head, _tail);
+ public Stmnt(int op, ASTree _head, ASTList _tail, int lineNumber) {
+ super(_head, _tail, lineNumber);
operatorId = op;
}
- public Stmnt(int op, ASTree _head) {
- super(_head);
+ public Stmnt(int op, ASTree _head, int lineNumber) {
+ super(_head, lineNumber);
operatorId = op;
}
- public Stmnt(int op) {
- this(op, null);
+ public Stmnt(int op, int lineNumber) {
+ this(op, null, lineNumber);
}
- public static Stmnt make(int op, ASTree oprand1, ASTree oprand2) {
- return new Stmnt(op, oprand1, new ASTList(oprand2));
+ public static Stmnt make(int op, ASTree oprand1, ASTree oprand2, int lineNumber) {
+ return new Stmnt(op, oprand1, new ASTList(oprand2, lineNumber), lineNumber);
}
- public static Stmnt make(int op, ASTree op1, ASTree op2, ASTree op3) {
- return new Stmnt(op, op1, new ASTList(op2, new ASTList(op3)));
+ public static Stmnt make(int op, ASTree op1, ASTree op2, ASTree op3, int lineNumber) {
+ return new Stmnt(op, op1, new ASTList(op2, new ASTList(op3, lineNumber), lineNumber), lineNumber);
}
@Override
diff --git a/src/main/javassist/compiler/ast/StringL.java b/src/main/javassist/compiler/ast/StringL.java
index 7c7e00c3..063bb5ed 100644
--- a/src/main/javassist/compiler/ast/StringL.java
+++ b/src/main/javassist/compiler/ast/StringL.java
@@ -26,7 +26,8 @@ public class StringL extends ASTree {
private static final long serialVersionUID = 1L;
protected String text;
- public StringL(String t) {
+ public StringL(String t, int lineNumber) {
+ super(lineNumber);
text = t;
}
diff --git a/src/main/javassist/compiler/ast/Symbol.java b/src/main/javassist/compiler/ast/Symbol.java
index 2b66207a..64c598eb 100644
--- a/src/main/javassist/compiler/ast/Symbol.java
+++ b/src/main/javassist/compiler/ast/Symbol.java
@@ -26,7 +26,8 @@ public class Symbol extends ASTree {
private static final long serialVersionUID = 1L;
protected String identifier;
- public Symbol(String sym) {
+ public Symbol(String sym, int lineNumber) {
+ super(lineNumber);
identifier = sym;
}
diff --git a/src/main/javassist/compiler/ast/Variable.java b/src/main/javassist/compiler/ast/Variable.java
index c9224a7a..2e186950 100644
--- a/src/main/javassist/compiler/ast/Variable.java
+++ b/src/main/javassist/compiler/ast/Variable.java
@@ -26,8 +26,8 @@ public class Variable extends Symbol {
private static final long serialVersionUID = 1L;
protected Declarator declarator;
- public Variable(String sym, Declarator d) {
- super(sym);
+ public Variable(String sym, Declarator d, int lineNumber) {
+ super(sym, lineNumber);
declarator = d;
}
diff --git a/src/main/javassist/expr/Cast.java b/src/main/javassist/expr/Cast.java
index 31522e5a..29f91f3e 100644
--- a/src/main/javassist/expr/Cast.java
+++ b/src/main/javassist/expr/Cast.java
@@ -163,26 +163,26 @@ public class Cast extends Expr {
}
@Override
- public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (gen.getMethodArgsLength(args) != 1)
throw new CompileError(Javac.proceedName
+ "() cannot take more than one parameter "
- + "for cast");
+ + "for cast", lineNumber);
gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
bytecode.addOpcode(Opcode.CHECKCAST);
bytecode.addIndex(index);
- gen.setType(retType);
+ gen.setType(retType, lineNumber);
}
@Override
- public void setReturnType(JvstTypeChecker c, ASTList args)
+ public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.atMethodArgs(args, new int[1], new int[1], new String[1]);
- c.setType(retType);
+ c.setType(retType, lineNumber);
}
}
}
diff --git a/src/main/javassist/expr/FieldAccess.java b/src/main/javassist/expr/FieldAccess.java
index 335314a5..9075e5fa 100644
--- a/src/main/javassist/expr/FieldAccess.java
+++ b/src/main/javassist/expr/FieldAccess.java
@@ -259,12 +259,12 @@ public class FieldAccess extends Expr {
}
@Override
- public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (args != null && !gen.isParamListName(args))
throw new CompileError(Javac.proceedName
- + "() cannot take a parameter for field reading");
+ + "() cannot take a parameter for field reading", lineNumber);
int stack;
if (isStatic(opcode))
@@ -282,14 +282,14 @@ public class FieldAccess extends Expr {
bytecode.add(opcode);
bytecode.addIndex(index);
bytecode.growStack(stack);
- gen.setType(fieldType);
+ gen.setType(fieldType, lineNumber);
}
@Override
- public void setReturnType(JvstTypeChecker c, ASTList args)
+ public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
- c.setType(fieldType);
+ c.setType(fieldType, lineNumber);
}
}
@@ -309,13 +309,13 @@ public class FieldAccess extends Expr {
}
@Override
- public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (gen.getMethodArgsLength(args) != 1)
throw new CompileError(Javac.proceedName
+ "() cannot take more than one parameter "
- + "for field writing");
+ + "for field writing", lineNumber);
int stack;
if (isStatic(opcode))
@@ -335,16 +335,16 @@ public class FieldAccess extends Expr {
bytecode.add(opcode);
bytecode.addIndex(index);
bytecode.growStack(stack);
- gen.setType(CtClass.voidType);
+ gen.setType(CtClass.voidType, lineNumber);
gen.addNullIfVoid();
}
@Override
- public void setReturnType(JvstTypeChecker c, ASTList args)
+ public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.atMethodArgs(args, new int[1], new int[1], new String[1]);
- c.setType(CtClass.voidType);
+ c.setType(CtClass.voidType, lineNumber);
c.addNullIfVoid();
}
}
diff --git a/src/main/javassist/expr/Instanceof.java b/src/main/javassist/expr/Instanceof.java
index a046ddbc..e56a3819 100644
--- a/src/main/javassist/expr/Instanceof.java
+++ b/src/main/javassist/expr/Instanceof.java
@@ -167,26 +167,26 @@ public class Instanceof extends Expr {
}
@Override
- public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
if (gen.getMethodArgsLength(args) != 1)
throw new CompileError(Javac.proceedName
+ "() cannot take more than one parameter "
- + "for instanceof");
+ + "for instanceof", lineNumber);
gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
bytecode.addOpcode(Opcode.INSTANCEOF);
bytecode.addIndex(index);
- gen.setType(CtClass.booleanType);
+ gen.setType(CtClass.booleanType, lineNumber);
}
@Override
- public void setReturnType(JvstTypeChecker c, ASTList args)
+ public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
c.atMethodArgs(args, new int[1], new int[1], new String[1]);
- c.setType(CtClass.booleanType);
+ c.setType(CtClass.booleanType, lineNumber);
}
}
}
diff --git a/src/main/javassist/expr/NewArray.java b/src/main/javassist/expr/NewArray.java
index df30e26f..33dc417f 100644
--- a/src/main/javassist/expr/NewArray.java
+++ b/src/main/javassist/expr/NewArray.java
@@ -270,13 +270,13 @@ public class NewArray extends Expr {
}
@Override
- public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
int num = gen.getMethodArgsLength(args);
if (num != dimension)
throw new CompileError(Javac.proceedName
- + "() with a wrong number of parameters");
+ + "() with a wrong number of parameters", lineNumber);
gen.atMethodArgs(args, new int[num],
new int[num], new String[num]);
@@ -291,14 +291,14 @@ public class NewArray extends Expr {
bytecode.growStack(1 - dimension);
}
- gen.setType(arrayType);
+ gen.setType(arrayType, lineNumber);
}
@Override
- public void setReturnType(JvstTypeChecker c, ASTList args)
+ public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
- c.setType(arrayType);
+ c.setType(arrayType, lineNumber);
}
}
}
diff --git a/src/main/javassist/expr/NewExpr.java b/src/main/javassist/expr/NewExpr.java
index ee065167..e45a4c54 100644
--- a/src/main/javassist/expr/NewExpr.java
+++ b/src/main/javassist/expr/NewExpr.java
@@ -263,7 +263,7 @@ public class NewExpr extends Expr {
}
@Override
- public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
+ public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber)
throws CompileError
{
bytecode.addOpcode(NEW);
@@ -271,15 +271,15 @@ public class NewExpr extends Expr {
bytecode.addOpcode(DUP);
gen.atMethodCallCore(newType, MethodInfo.nameInit, args,
false, true, -1, null);
- gen.setType(newType);
+ gen.setType(newType, lineNumber);
}
@Override
- public void setReturnType(JvstTypeChecker c, ASTList args)
+ public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber)
throws CompileError
{
- c.atMethodCallCore(newType, MethodInfo.nameInit, args);
- c.setType(newType);
+ c.atMethodCallCore(newType, MethodInfo.nameInit, args, lineNumber);
+ c.setType(newType, lineNumber);
}
}
}
diff --git a/src/test/javassist/LineNumberTest.java b/src/test/javassist/LineNumberTest.java
new file mode 100644
index 00000000..7e9fbd2f
--- /dev/null
+++ b/src/test/javassist/LineNumberTest.java
@@ -0,0 +1,93 @@
+package javassist;
+
+import junit.framework.TestCase;
+
+public class LineNumberTest extends TestCase {
+ private final ClassPool loader = ClassPool.getDefault();
+ private static int classNumber = 0;
+
+ public void testComma() {
+ doTestCompile(String.join("\n",
+ "public void run() {",
+ " return",
+ "}"), "line 3: syntax error near \" return\n}\"");
+ }
+
+ public void testUndevField() {
+ doTestCompile(String.join("\n",
+ "public void run() {",
+ " foo = 5;",
+ "}"), "line 2: no such field: foo");
+ }
+
+ public void testUndevMethod() {
+ doTestCompile(String.join("\n",
+ "public void run() {",
+ " foo();",
+ "}"), "line 2: foo() not found in javassist.LineNumberCompileTest2");
+ }
+
+ public void testException() {
+ doTestRuntime(String.join("\n",
+ "public void run() {",
+ " throw new java.lang.RuntimeException();",
+ "}"), 0, 5);
+ }
+
+ public void testIf() {
+ doTestRuntime(String.join("\n",
+ "public void run() {",
+ " if (throwException()) {",
+ " }",
+ "}"), 1, 5);
+ }
+
+ public void testWhile() {
+ doTestRuntime(String.join("\n",
+ "public void run() {",
+ " while (throwException()) {",
+ " }",
+ "}"), 1, 5);
+ }
+
+ public void testFor() {
+ doTestRuntime(String.join("\n",
+ "public void run() {",
+ " for (; throwException(); ) {",
+ " ",
+ " }",
+ "}"), 1, 5);
+ }
+
+ private void doTestCompile(String src, String msg) {
+ CtClass testClass = loader.makeClass("javassist.LineNumberCompileTest" + classNumber++);
+ try {
+ testClass.addMethod(CtMethod.make(src, testClass));
+ } catch (CannotCompileException e) {
+ assertEquals(msg, e.getCause().getMessage());
+ return;
+ }
+ fail("should not happen");
+ }
+
+ private void doTestRuntime(String src, int stackOffset, int lineNumber) {
+ CtClass testClass = loader.makeClass("javassist.LineNumberRuntimeTest" + classNumber++);
+ String test = String.join("\n",
+ "private boolean throwException() {",
+ " throw new java.lang.RuntimeException();",
+ "}");
+ try {
+ testClass.addInterface(loader.get("java.lang.Runnable"));
+ testClass.addMethod(CtMethod.make(test, testClass));
+ testClass.addMethod(CtMethod.make(src, testClass));
+ Class cls = testClass.toClass(LineNumberTest.class);
+ var runnable = (Runnable) cls.getConstructor().newInstance();
+ runnable.run();
+ } catch (Exception e) {
+ var lineNum = e.getStackTrace()[stackOffset].getLineNumber();
+ assertEquals("Line number should be right", lineNumber, lineNum);
+ return;
+ }
+ fail("should not happen");
+ }
+}
diff --git a/src/test/javassist/compiler/CompTest.java b/src/test/javassist/compiler/CompTest.java
index 4154935f..5774f7aa 100644
--- a/src/test/javassist/compiler/CompTest.java
+++ b/src/test/javassist/compiler/CompTest.java
@@ -105,11 +105,11 @@ public class CompTest extends TestCase {
public void testArgTypesToString() {
String s;
- s = TypeChecker.argTypesToString(new int[0], new int[0], new String[0]);
+ s = TypeChecker.argTypesToString(new int[0], new int[0], new String[0], 0);
assertEquals("()", s);
s = TypeChecker.argTypesToString(new int[] { TokenId.INT, TokenId.CHAR, TokenId.CLASS },
new int[] { 0, 1, 0 },
- new String[] { null, null, "String" });
+ new String[] { null, null, "String" }, 0);
assertEquals("(int,char[],String)", s);
}