Browse Source

add line numbers and test

pull/484/head
akuznetsov 7 months ago
parent
commit
d5a7881381
38 changed files with 697 additions and 300 deletions
  1. 14
    0
      src/main/javassist/bytecode/CodeAttribute.java
  2. 1
    1
      src/main/javassist/bytecode/LineNumberAttribute.java
  3. 40
    0
      src/main/javassist/bytecode/LineNumberAttributeBuilder.java
  4. 40
    40
      src/main/javassist/compiler/CodeGen.java
  5. 12
    1
      src/main/javassist/compiler/CompileError.java
  6. 20
    18
      src/main/javassist/compiler/Javac.java
  7. 13
    13
      src/main/javassist/compiler/JvstCodeGen.java
  8. 265
    0
      src/main/javassist/compiler/JvstCodeGenWitlLineNumber.java
  9. 3
    3
      src/main/javassist/compiler/JvstTypeChecker.java
  10. 6
    1
      src/main/javassist/compiler/Lex.java
  11. 31
    31
      src/main/javassist/compiler/MemberCodeGen.java
  12. 1
    1
      src/main/javassist/compiler/NoFieldException.java
  13. 76
    76
      src/main/javassist/compiler/Parser.java
  14. 28
    27
      src/main/javassist/compiler/TypeChecker.java
  15. 8
    8
      src/main/javassist/compiler/ast/ASTList.java
  16. 10
    0
      src/main/javassist/compiler/ast/ASTree.java
  17. 5
    3
      src/main/javassist/compiler/ast/ArrayInit.java
  18. 4
    4
      src/main/javassist/compiler/ast/AssignExpr.java
  19. 4
    4
      src/main/javassist/compiler/ast/BinExpr.java
  20. 4
    4
      src/main/javassist/compiler/ast/CallExpr.java
  21. 4
    4
      src/main/javassist/compiler/ast/CastExpr.java
  22. 2
    2
      src/main/javassist/compiler/ast/CondExpr.java
  23. 10
    10
      src/main/javassist/compiler/ast/Declarator.java
  24. 9
    5
      src/main/javassist/compiler/ast/DoubleConst.java
  25. 8
    8
      src/main/javassist/compiler/ast/Expr.java
  26. 2
    2
      src/main/javassist/compiler/ast/FieldDecl.java
  27. 4
    4
      src/main/javassist/compiler/ast/InstanceOfExpr.java
  28. 7
    3
      src/main/javassist/compiler/ast/IntConst.java
  29. 2
    1
      src/main/javassist/compiler/ast/Keyword.java
  30. 2
    2
      src/main/javassist/compiler/ast/Member.java
  31. 2
    2
      src/main/javassist/compiler/ast/MethodDecl.java
  32. 8
    8
      src/main/javassist/compiler/ast/NewExpr.java
  33. 1
    0
      src/main/javassist/compiler/ast/Pair.java
  34. 10
    10
      src/main/javassist/compiler/ast/Stmnt.java
  35. 2
    1
      src/main/javassist/compiler/ast/StringL.java
  36. 2
    1
      src/main/javassist/compiler/ast/Symbol.java
  37. 2
    2
      src/main/javassist/compiler/ast/Variable.java
  38. 35
    0
      src/test/javassist/bytecode/BytecodeTest.java

+ 14
- 0
src/main/javassist/bytecode/CodeAttribute.java View File

@@ -347,6 +347,20 @@ public class CodeAttribute extends AttributeInfo implements Opcode {
attributes.add(sm);
}

/**
* 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.
*/

+ 1
- 1
src/main/javassist/bytecode/LineNumberAttribute.java View File

@@ -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);
}


+ 40
- 0
src/main/javassist/bytecode/LineNumberAttributeBuilder.java View File

@@ -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);
}
}
}

+ 40
- 40
src/main/javassist/compiler/CodeGen.java View File

@@ -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) {
@@ -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) {
@@ -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,7 +1649,7 @@ 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("[")) {
@@ -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());
}
}


+ 12
- 1
src/main/javassist/compiler/CompileError.java View File

@@ -25,11 +25,18 @@ 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, int lineNumber) {
this.lineNumber = lineNumber;
reason = String.format("line %d: %s", lineNumber, s);
}

public 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;

+ 20
- 18
src/main/javassist/compiler/Javac.java View File

@@ -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;
}
@@ -160,8 +160,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,10 +174,11 @@ 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);
@@ -446,11 +448,11 @@ public class Javac {
public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
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();
}
@@ -459,11 +461,11 @@ public class Javac {
public void setReturnType(JvstTypeChecker check, ASTList args)
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();
}
@@ -493,8 +495,8 @@ public class Javac {
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();
}
@@ -504,8 +506,8 @@ public class Javac {
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();
}

+ 13
- 13
src/main/javassist/compiler/JvstCodeGen.java View File

@@ -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,11 +141,11 @@ 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);
if (!doDup)
@@ -211,7 +211,7 @@ public class JvstCodeGen extends MemberCodeGen {
className = null;
}
else
throw new CompileError("invalid cast");
throw new CompileError("invalid cast", expr.getLineNumber());
}

protected void atCastToWrapper(CastExpr expr) throws CompileError {
@@ -253,7 +253,7 @@ public class JvstCodeGen extends MemberCodeGen {
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).
@@ -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);
}

@@ -573,7 +573,7 @@ public class JvstCodeGen extends MemberCodeGen {

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;
}
@@ -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);
}


+ 265
- 0
src/main/javassist/compiler/JvstCodeGenWitlLineNumber.java View File

@@ -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);
}
}

+ 3
- 3
src/main/javassist/compiler/JvstTypeChecker.java View File

@@ -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,7 +124,7 @@ 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());
@@ -258,7 +258,7 @@ public class JvstTypeChecker extends TypeChecker {
addNullIfVoid();
}

protected void compileUnwrapValue(CtClass type) throws CompileError
protected void compileUnwrapValue(CtClass type, int lineNumber) throws CompileError
{
if (type == CtClass.voidType)
addNullIfVoid();

+ 6
- 1
src/main/javassist/compiler/Lex.java View File

@@ -163,7 +163,8 @@ public class Lex implements TokenId {
ungetc(c);
c = '/';
}
}
} else if (c == '\n')
++lineNumber;
} while(isBlank(c));
return c;
}
@@ -529,4 +530,8 @@ public class Lex implements TokenId {
lastChar = -1;
return c;
}

public int getLineNumber() {
return lineNumber + 1;
}
}

+ 31
- 31
src/main/javassist/compiler/MemberCodeGen.java View File

@@ -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) {
@@ -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,7 +369,7 @@ 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) {
@@ -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)
@@ -563,7 +563,7 @@ public class MemberCodeGen extends CodeGen {
badMethod();
}
else
fatal();
fatal(expr.getLineNumber());

atMethodCallCore(targetClass, mname, args, isStatic, isSpecial,
aload0pos, cached);
@@ -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,
@@ -844,14 +844,14 @@ public class MemberCodeGen extends CodeGen {
if (op == '=') {
FieldInfo finfo = f.getFieldInfo2();
setFieldType(finfo);
AccessorMaker maker = isAccessibleField(f, finfo);
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,9 +921,9 @@ 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());
@@ -932,7 +932,7 @@ public class MemberCodeGen extends CodeGen {

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);
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
@@ -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 {

+ 1
- 1
src/main/javassist/compiler/NoFieldException.java View File

@@ -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;
}

+ 76
- 76
src/main/javassist/compiler/Parser.java View File

@@ -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);
@@ -306,12 +306,12 @@ public final class Parser implements TokenId {
while (lex.lookAhead() != '}') {
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, lex.getLineNumber()));
}

lex.get(); // '}'
if (body == null)
return new Stmnt(BLOCK); // empty block
return new Stmnt(BLOCK, lex.getLineNumber()); // empty block
return body;
}

@@ -330,7 +330,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()), lex.getLineNumber()), lex.getLineNumber());
}

/* while.statement : WHILE "(" expression ")" statement
@@ -341,7 +341,7 @@ public final class Parser implements TokenId {
int t = lex.get(); // WHILE
ASTree expr = parseParExpression(tbl);
Stmnt body = parseStatement(tbl);
return new Stmnt(t, expr, body);
return new Stmnt(t, expr, body, lex.getLineNumber());
}

/* do.statement : DO statement WHILE "(" expression ")" ";"
@@ -356,7 +356,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 ")"
@@ -397,7 +397,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, lex.getLineNumber()), lex.getLineNumber()), lex.getLineNumber());
}

/* switch.statement : SWITCH "(" expression ")" "{" switch.block "}"
@@ -411,7 +411,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 +428,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 +454,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 +477,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 +503,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 +512,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 +537,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 +554,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 +589,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 +597,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 +605,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 +618,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 +635,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 +653,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 +661,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 +683,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 +722,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 +744,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 +808,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 +829,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 +887,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 +922,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 +931,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 +1001,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 +1035,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 +1066,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 +1080,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 +1095,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 +1121,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 +1133,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 +1166,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 +1193,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 +1246,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 +1286,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 +1312,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 +1341,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

+ 28
- 27
src/main/javassist/compiler/TypeChecker.java View File

@@ -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);
}

/**
@@ -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))
@@ -702,7 +703,7 @@ 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)
@@ -717,7 +718,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
badMethod();
}
else
fatal();
fatal(expr.getLineNumber());

MemberResolver.Method minfo
= atMethodCallCore(targetClass, mname, args);
@@ -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;
}
@@ -1046,7 +1047,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId {
className = getSuperName();
break;
default :
fatal();
fatal(k.getLineNumber());
}
}


+ 8
- 8
src/main/javassist/compiler/ast/ASTList.java View File

@@ -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));
}

/**

+ 10
- 0
src/main/javassist/compiler/ast/ASTree.java View File

@@ -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;
}
}

+ 5
- 3
src/main/javassist/compiler/ast/ArrayInit.java View File

@@ -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);
}

/**

+ 4
- 4
src/main/javassist/compiler/ast/AssignExpr.java View File

@@ -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

+ 4
- 4
src/main/javassist/compiler/ast/BinExpr.java View File

@@ -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

+ 4
- 4
src/main/javassist/compiler/ast/CallExpr.java View File

@@ -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

+ 4
- 4
src/main/javassist/compiler/ast/CastExpr.java View File

@@ -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;
}

+ 2
- 2
src/main/javassist/compiler/ast/CondExpr.java View File

@@ -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(); }

+ 10
- 10
src/main/javassist/compiler/ast/Declarator.java View File

@@ -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;
}


+ 9
- 5
src/main/javassist/compiler/ast/DoubleConst.java View File

@@ -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);
}
}

+ 8
- 8
src/main/javassist/compiler/ast/Expr.java View File

@@ -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; }

+ 2
- 2
src/main/javassist/compiler/ast/FieldDecl.java View File

@@ -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(); }

+ 4
- 4
src/main/javassist/compiler/ast/InstanceOfExpr.java View File

@@ -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

+ 7
- 3
src/main/javassist/compiler/ast/IntConst.java View File

@@ -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());
}
}

+ 2
- 1
src/main/javassist/compiler/ast/Keyword.java View File

@@ -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;
}


+ 2
- 2
src/main/javassist/compiler/ast/Member.java View File

@@ -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;
}


+ 2
- 2
src/main/javassist/compiler/ast/MethodDecl.java View File

@@ -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() {

+ 8
- 8
src/main/javassist/compiler/ast/NewExpr.java View File

@@ -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;
}

+ 1
- 0
src/main/javassist/compiler/ast/Pair.java View File

@@ -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;
}

+ 10
- 10
src/main/javassist/compiler/ast/Stmnt.java View File

@@ -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

+ 2
- 1
src/main/javassist/compiler/ast/StringL.java View File

@@ -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;
}


+ 2
- 1
src/main/javassist/compiler/ast/Symbol.java View File

@@ -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;
}


+ 2
- 2
src/main/javassist/compiler/ast/Variable.java View File

@@ -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;
}


+ 35
- 0
src/test/javassist/bytecode/BytecodeTest.java View File

@@ -302,6 +302,41 @@ public class BytecodeTest extends TestCase {
assertEquals(20, pc.line);
}

public void testLineNumberCompiler() {
CtClass testClass = loader.makeClass("javassist.bytecode.LineNumberCompilerClass");
String run = String.join("\n",
"public void run() {",
" return",
"}");
try {
testClass.addMethod(CtMethod.make(run, testClass));
} catch (CannotCompileException e) {
assertEquals("line 3: syntax error near \" return\n}\"", e.getCause().getMessage());
return;
}
fail("should not happen");
}

public void testLineNumberException() {
CtClass testClass = loader.makeClass("javassist.bytecode.LineNumberExceptionClass");
String run = String.join("\n",
"public void run() {",
" throw new java.lang.RuntimeException();",
"}");
try {
testClass.addInterface(loader.get("java.lang.Runnable"));
testClass.addMethod(CtMethod.make(run, testClass));
Class cls = testClass.toClass(BytecodeTest.class);
var runnable = (Runnable) cls.getConstructor().newInstance();
runnable.run();
} catch (Exception e) {
var lineNum = e.getStackTrace()[0].getLineNumber();
assertEquals("Line number should be right", 2, lineNum);
return;
}
fail("should not happen");
}

public void testRenameClass() throws Exception {
CtClass cc = loader.get("test1.RenameClass");
cc.replaceClassName("test1.RenameClass2", "java.lang.String");

Loading…
Cancel
Save