Skip to content

Commit

Permalink
Started implementing tests for column numbers. Fixing bugs as found.
Browse files Browse the repository at this point in the history
  • Loading branch information
andreabergia committed Nov 11, 2024
1 parent 05c0476 commit 433f116
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 20 deletions.
2 changes: 1 addition & 1 deletion rhino/src/main/java/org/mozilla/javascript/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,7 @@ protected void setColumn(int column) {

/**
* @return the column of where a Node is defined in source. If the column is -1, it was never
* initialized.
* initialized. One-based.
* <p>May be overridden by sub classes
*/
public int column() {
Expand Down
44 changes: 25 additions & 19 deletions rhino/src/main/java/org/mozilla/javascript/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public class Parser {
private int prevNameTokenStart;
private String prevNameTokenString = "";
private int prevNameTokenLineno;
private int prevNameTokenColumn;

private boolean defaultUseStrictDirective;

Expand Down Expand Up @@ -1306,9 +1307,10 @@ private AstNode statementHelper() throws IOException {
case Token.CONST:
case Token.VAR:
consumeToken();
int lineno = ts.lineno;
int lineno = ts.lineno, col = ts.getTokenColumn();
pn = variables(currentToken, ts.tokenBeg, true);
pn.setLineno(lineno);
pn.setColumn(col);
break;

case Token.LET:
Expand Down Expand Up @@ -1400,7 +1402,7 @@ private void autoInsertSemicolon(AstNode pn) throws IOException {
private IfStatement ifStatement() throws IOException {
if (currentToken != Token.IF) codeBug();
consumeToken();
int pos = ts.tokenBeg, lineno = ts.lineno, elsePos = -1;
int pos = ts.tokenBeg, lineno = ts.lineno, elsePos = -1, col = ts.getTokenColumn();
IfStatement pn = new IfStatement(pos);
ConditionData data = condition();
AstNode ifTrue = getNextStatementAfterInlineComments(pn), ifFalse = null;
Expand All @@ -1421,10 +1423,7 @@ private IfStatement ifStatement() throws IOException {
pn.setElsePart(ifFalse);
pn.setElsePosition(elsePos);
pn.setLineno(lineno);
if (pn.getCondition() != null) {
AstNode condition = pn.getCondition();
if (condition.wasColumnAssigned()) pn.setColumn(condition.column());
}
pn.setColumn(col);

return pn;
}
Expand Down Expand Up @@ -1995,14 +1994,15 @@ private WithStatement withStatement() throws IOException {
private AstNode letStatement() throws IOException {
if (currentToken != Token.LET) codeBug();
consumeToken();
int lineno = ts.lineno, pos = ts.tokenBeg;
int lineno = ts.lineno, pos = ts.tokenBeg, col = ts.getTokenColumn();
AstNode pn;
if (peekToken() == Token.LP) {
pn = let(true, pos);
} else {
pn = variables(Token.LET, pos, true); // else, e.g.: let x=6, y=7;
}
pn.setLineno(lineno);
pn.setColumn(col);
return pn;
}

Expand Down Expand Up @@ -2100,6 +2100,7 @@ private AstNode block() throws IOException {
int pos = ts.tokenBeg;
Scope block = new Scope(pos);
block.setLineno(ts.lineno);
block.setColumn(ts.getTokenColumn());
pushScope(block);
try {
statements(block);
Expand Down Expand Up @@ -2174,7 +2175,8 @@ private AstNode nameOrLabel() throws IOException {

if (expr.getType() != Token.LABEL) {
AstNode n = new ExpressionStatement(expr, !insideFunction());
n.lineno = expr.lineno;
n.setLineno(expr.lineno);
n.setColumn(expr.column());
return n;
}

Expand Down Expand Up @@ -2857,7 +2859,7 @@ private List<AstNode> argumentList() throws IOException {
* @param allowCallSyntax passed down to {@link #memberExprTail}
*/
private AstNode memberExpr(boolean allowCallSyntax) throws IOException {
int tt = peekToken(), lineno = ts.lineno;
int tt = peekToken(), lineno = ts.lineno, column = ts.getTokenColumn();
AstNode pn;

if (tt != Token.NEW) {
Expand Down Expand Up @@ -2897,8 +2899,8 @@ private AstNode memberExpr(boolean allowCallSyntax) throws IOException {
pn = nx;
}
pn.setLineno(lineno);
AstNode tail = memberExprTail(allowCallSyntax, pn);
return tail;
pn.setColumn(column);
return memberExprTail(allowCallSyntax, pn);
}

/**
Expand Down Expand Up @@ -3053,7 +3055,7 @@ private AstNode propertyAccess(int tt, AstNode pn, boolean isOptionalChain) thro
switch (token) {
case Token.THROW:
// needed for generator.throw();
saveNameTokenData(ts.tokenBeg, "throw", ts.lineno);
saveNameTokenData(ts.tokenBeg, "throw", ts.lineno, ts.getTokenColumn());
ref = propertyName(-1, memberTypeFlags);
break;

Expand All @@ -3064,7 +3066,7 @@ private AstNode propertyAccess(int tt, AstNode pn, boolean isOptionalChain) thro

case Token.MUL:
// handles: *, *::name, *::*, *::[expr]
saveNameTokenData(ts.tokenBeg, "*", ts.lineno);
saveNameTokenData(ts.tokenBeg, "*", ts.lineno, ts.getTokenColumn());
ref = propertyName(-1, memberTypeFlags);
break;

Expand All @@ -3077,7 +3079,7 @@ private AstNode propertyAccess(int tt, AstNode pn, boolean isOptionalChain) thro
case Token.RESERVED:
{
String name = ts.getString();
saveNameTokenData(ts.tokenBeg, name, ts.lineno);
saveNameTokenData(ts.tokenBeg, name, ts.lineno, ts.getTokenColumn());
ref = propertyName(-1, memberTypeFlags);
break;
}
Expand Down Expand Up @@ -3108,7 +3110,7 @@ private AstNode propertyAccess(int tt, AstNode pn, boolean isOptionalChain) thro
// allow keywords as property names, e.g. ({if: 1})
String name = Token.keywordToName(token);
if (name != null) {
saveNameTokenData(ts.tokenBeg, name, ts.lineno);
saveNameTokenData(ts.tokenBeg, name, ts.lineno, ts.getTokenColumn());
ref = propertyName(-1, memberTypeFlags);
break;
}
Expand Down Expand Up @@ -3169,7 +3171,7 @@ private AstNode attributeAccess() throws IOException {

// handles: @*, @*::name, @*::*, @*::[expr]
case Token.MUL:
saveNameTokenData(ts.tokenBeg, "*", ts.lineno);
saveNameTokenData(ts.tokenBeg, "*", ts.lineno, ts.getTokenColumn());
return propertyName(atPos, 0);

// handles @[expr]
Expand Down Expand Up @@ -3209,7 +3211,7 @@ private AstNode propertyName(int atPos, int memberTypeFlags) throws IOException

// handles name::*
case Token.MUL:
saveNameTokenData(ts.tokenBeg, "*", ts.lineno);
saveNameTokenData(ts.tokenBeg, "*", ts.lineno, ts.getTokenColumn());
name = createNameNode(false, -1);
break;

Expand Down Expand Up @@ -3425,7 +3427,7 @@ private AstNode name(int ttFlagged, int tt) throws IOException {
// Not a label. Unfortunately peeking the next token to check for
// a colon has biffed ts.tokenBeg, ts.tokenEnd. We store the name's
// bounds in instance vars and createNameNode uses them.
saveNameTokenData(namePos, nameString, nameLineno);
saveNameTokenData(namePos, nameString, nameLineno, ts.getTokenColumn());

if (compilerEnv.isXmlAvailable()) {
return propertyName(-1, 0);
Expand Down Expand Up @@ -3953,10 +3955,12 @@ private Name createNameNode(boolean checkActivation, int token) {
int beg = ts.tokenBeg;
String s = ts.getString();
int lineno = ts.lineno;
int column = ts.getTokenColumn();
if (!"".equals(prevNameTokenString)) {
beg = prevNameTokenStart;
s = prevNameTokenString;
lineno = prevNameTokenLineno;
column = prevNameTokenColumn;
prevNameTokenStart = 0;
prevNameTokenString = "";
prevNameTokenLineno = 0;
Expand All @@ -3970,6 +3974,7 @@ private Name createNameNode(boolean checkActivation, int token) {
}
Name name = new Name(beg, s, ts.getTokenColumn(beg));
name.setLineno(lineno);
name.setColumn(column);
if (checkActivation) {
checkActivationName(s, token);
}
Expand Down Expand Up @@ -4116,10 +4121,11 @@ private static int nodeEnd(AstNode node) {
return node.getPosition() + node.getLength();
}

private void saveNameTokenData(int pos, String name, int lineno) {
private void saveNameTokenData(int pos, String name, int lineno, int column) {
prevNameTokenStart = pos;
prevNameTokenString = name;
prevNameTokenLineno = lineno;
prevNameTokenColumn = column;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package org.mozilla.javascript.tests;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ast.AstNode;
import org.mozilla.javascript.ast.AstRoot;
import org.mozilla.javascript.ast.ExpressionStatement;
import org.mozilla.javascript.ast.IfStatement;
import org.mozilla.javascript.ast.Name;
import org.mozilla.javascript.ast.Scope;
import org.mozilla.javascript.ast.VariableDeclaration;
import org.mozilla.javascript.ast.VariableInitializer;

class ParserLineColumnNumberTest {
CompilerEnvirons environment;

@BeforeEach
public void setUp() throws Exception {
environment = new CompilerEnvirons();
}

@Test
void declarationVar() {
AstRoot root = myParse("var a =\n1;");
VariableDeclaration varStatement = assertInstanceOf(VariableDeclaration.class, root.getFirstChild());
assertEquals(0, varStatement.getLineno());
assertEquals(1, varStatement.column());
assertEquals(1, varStatement.getVariables().size());
VariableInitializer varInitializer = varStatement.getVariables().get(0);
assertEquals(0, varInitializer.getTarget().getLineno());
assertEquals(5, varInitializer.getTarget().column());
assertEquals(1, varInitializer.getInitializer().getLineno());
assertEquals(1, varInitializer.getInitializer().column());
}

@Test
void declarationConst() {
AstRoot root = myParse("const a =\n1;");
VariableDeclaration varStatement = assertInstanceOf(VariableDeclaration.class, root.getFirstChild());
assertEquals(0, varStatement.getLineno());
assertEquals(1, varStatement.column());
assertEquals(1, varStatement.getVariables().size());
VariableInitializer varInitializer = varStatement.getVariables().get(0);
assertEquals(0, varInitializer.getTarget().getLineno());
assertEquals(7, varInitializer.getTarget().column());
assertEquals(1, varInitializer.getInitializer().getLineno());
assertEquals(1, varInitializer.getInitializer().column());
}

@Test
void declarationLet() {
AstRoot root = myParse("let a =\n1;");
VariableDeclaration varStatement = assertInstanceOf(VariableDeclaration.class, root.getFirstChild());
assertEquals(0, varStatement.getLineno());
assertEquals(1, varStatement.column());
assertEquals(1, varStatement.getVariables().size());
VariableInitializer varInitializer = varStatement.getVariables().get(0);
assertEquals(0, varInitializer.getTarget().getLineno());
assertEquals(5, varInitializer.getTarget().column());
assertEquals(1, varInitializer.getInitializer().getLineno());
assertEquals(1, varInitializer.getInitializer().column());
}

@Test
void controlFlowIf() {
AstRoot root = myParse(
"if (a) {\n" +
" b\n" +
"} else {\n" +
" c;\n" +
"}");
IfStatement ifStatement = assertInstanceOf(IfStatement.class, root.getFirstChild());
assertEquals(0, ifStatement.getLineno());
assertEquals(1, ifStatement.column());
assertEquals(0, ifStatement.getCondition().getLineno());
assertEquals(5, ifStatement.getCondition().column());

Scope thenPart = assertInstanceOf(Scope.class, ifStatement.getThenPart());
assertEquals(0, thenPart.getLineno());
assertEquals(8, thenPart.column());
assertEquals(1, thenPart.getStatements().get(0).getLineno());
assertEquals(3, thenPart.getStatements().get(0).column());

assertEquals(3, ifStatement.getElsePart().getFirstChild().getLineno());
assertEquals(3, ifStatement.getElsePart().getFirstChild().column());
}

@Test
void expressionName() {
AstRoot root = myParse(" a");
ExpressionStatement nameExpr = assertInstanceOf(ExpressionStatement.class, root.getFirstChild());
assertEquals(0, nameExpr.getLineno());
assertEquals(2, nameExpr.column());
Name name = assertInstanceOf(Name.class, nameExpr.getExpression());
assertEquals(0, name.getLineno());
assertEquals(2, name.column());
}

@Test
void expressionInBlock() {
AstRoot root = myParse(" {a}");
Scope block = assertInstanceOf(Scope.class, root.getFirstChild());
assertEquals(0, block.getLineno());
assertEquals(2, block.column());

assertEquals(1, block.getStatements().size());
AstNode firstStatement = block.getStatements().get(0);
assertEquals(0, firstStatement.getLineno());
assertEquals(3, firstStatement.column());
}

private AstRoot myParse(String source) {
environment.setLanguageVersion(Context.VERSION_ES6);
return ParserTest.parse(source, null, null, true, environment);
}
}

0 comments on commit 433f116

Please sign in to comment.