aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorakuznetsov <akuznetsov@tradingview.com>2023-11-02 15:59:48 +0400
committerakuznetsov <akuznetsov@tradingview.com>2023-11-02 15:59:48 +0400
commit0824a7a04e2f5ca8acc355c2379cf625dadc8943 (patch)
treeba7325aadbc4262698016381a0e1799ce3db2d8b /src
parent15d56cfb702000400ff7d888e6084da72530221e (diff)
downloadjavassist-0824a7a04e2f5ca8acc355c2379cf625dadc8943.tar.gz
javassist-0824a7a04e2f5ca8acc355c2379cf625dadc8943.zip
fix line numbers in blocks & refactor test
Diffstat (limited to 'src')
-rw-r--r--src/main/javassist/compiler/Parser.java18
-rw-r--r--src/test/javassist/LineNumberTest.java79
-rw-r--r--src/test/javassist/bytecode/BytecodeTest.java60
3 files changed, 92 insertions, 65 deletions
diff --git a/src/main/javassist/compiler/Parser.java b/src/main/javassist/compiler/Parser.java
index 43e8a3ec..7e742a6b 100644
--- a/src/main/javassist/compiler/Parser.java
+++ b/src/main/javassist/compiler/Parser.java
@@ -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, lex.getLineNumber()));
+ body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s, lineNumber));
}
lex.get(); // '}'
if (body == null)
- return new Stmnt(BLOCK, lex.getLineNumber()); // 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, lex.getLineNumber()), lex.getLineNumber()), lex.getLineNumber());
+ 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, lex.getLineNumber());
+ return new Stmnt(t, expr, body, lineNumber);
}
/* do.statement : DO statement WHILE "(" 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, lex.getLineNumber()), lex.getLineNumber()), lex.getLineNumber());
+ new ASTList(expr3, body, expr3LineNumber), expr2LineNumber), expr1LineNumber);
}
/* switch.statement : SWITCH "(" expression ")" "{" switch.block "}"
diff --git a/src/test/javassist/LineNumberTest.java b/src/test/javassist/LineNumberTest.java
new file mode 100644
index 00000000..158efd01
--- /dev/null
+++ b/src/test/javassist/LineNumberTest.java
@@ -0,0 +1,79 @@
+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 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/bytecode/BytecodeTest.java b/src/test/javassist/bytecode/BytecodeTest.java
index cc02801d..eac420bc 100644
--- a/src/test/javassist/bytecode/BytecodeTest.java
+++ b/src/test/javassist/bytecode/BytecodeTest.java
@@ -302,66 +302,6 @@ 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 testLineNumberCompiler2() {
- CtClass testClass = loader.makeClass("javassist.bytecode.LineNumberCompilerClass2");
- String ctor = String.join("\n",
- "public LineNumberCompilerClass2() {",
- " super();",
- "}");
- String run = String.join("\n",
- "public void run() {",
- " return;",
- "}");
- String run2 = String.join("\n",
- "public void run2() {",
- " run()",
- "}");
- try {
- testClass.addConstructor(CtNewConstructor.make(ctor, testClass));
- testClass.addMethod(CtMethod.make(run, testClass));
- testClass.addMethod(CtMethod.make(run2, testClass));
- } catch (CannotCompileException e) {
- assertEquals("line 9: ; is missing", 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");