/*
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Rhino code, released
* May 6, 1999.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1997-1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Nick Santos
*
* Alternatively, the contents of this file may be used under the terms of
* the GNU General Public License Version 2 or later (the "GPL"), in which
* case the provisions of the GPL are applicable instead of those above. If
* you wish to allow use of your version of this file only under the terms of
* the GPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replacing
* them with the notice and other provisions required by the GPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the GPL.
*
* ***** END LICENSE BLOCK ***** */
package com.google.javascript.rhino;
import com.google.common.collect.ImmutableList;
import com.google.javascript.rhino.testing.BaseJSTypeTestCase;
import com.google.javascript.rhino.testing.TestErrorReporter;
import java.util.List;
public class ParserTest extends BaseJSTypeTestCase {
private static final String TRAILING_COMMA_MESSAGE =
ScriptRuntime.getMessage0("msg.trailing.comma");
public void testLinenoCharnoAssign1() throws Exception {
Node assign = parse("a = b").getFirstChild().getFirstChild();
assertEquals(Token.ASSIGN, assign.getType());
assertEquals(0, assign.getLineno());
assertEquals(2, assign.getCharno());
}
public void testLinenoCharnoAssign2() throws Exception {
Node assign = parse("\n a.g.h.k = 45").getFirstChild().getFirstChild();
assertEquals(Token.ASSIGN, assign.getType());
assertEquals(1, assign.getLineno());
assertEquals(12, assign.getCharno());
}
public void testLinenoCharnoCall() throws Exception {
Node call = parse("\n foo(123);").getFirstChild().getFirstChild();
assertEquals(Token.CALL, call.getType());
assertEquals(1, call.getLineno());
assertEquals(4, call.getCharno());
}
public void testLinenoCharnoGetProp1() throws Exception {
Node getprop = parse("\n foo.bar").getFirstChild().getFirstChild();
assertEquals(Token.GETPROP, getprop.getType());
assertEquals(1, getprop.getLineno());
assertEquals(4, getprop.getCharno());
Node name = getprop.getFirstChild().getNext();
assertEquals(Token.STRING, name.getType());
assertEquals(1, name.getLineno());
assertEquals(5, name.getCharno());
}
public void testLinenoCharnoGetProp2() throws Exception {
Node getprop = parse("\n foo.\nbar").getFirstChild().getFirstChild();
assertEquals(Token.GETPROP, getprop.getType());
assertEquals(1, getprop.getLineno());
assertEquals(4, getprop.getCharno());
Node name = getprop.getFirstChild().getNext();
assertEquals(Token.STRING, name.getType());
assertEquals(2, name.getLineno());
assertEquals(0, name.getCharno());
}
public void testLinenoCharnoGetelem1() throws Exception {
Node call = parse("\n foo[123]").getFirstChild().getFirstChild();
assertEquals(Token.GETELEM, call.getType());
assertEquals(1, call.getLineno());
assertEquals(4, call.getCharno());
}
public void testLinenoCharnoGetelem2() throws Exception {
Node call = parse("\n \n foo()[123]").getFirstChild().getFirstChild();
assertEquals(Token.GETELEM, call.getType());
assertEquals(2, call.getLineno());
assertEquals(6, call.getCharno());
}
public void testLinenoCharnoGetelem3() throws Exception {
Node call = parse("\n \n (8 + kl)[123]").getFirstChild().getFirstChild();
assertEquals(Token.GETELEM, call.getType());
assertEquals(2, call.getLineno());
assertEquals(9, call.getCharno());
}
public void testLinenoCharnoForComparison() throws Exception {
Node lt =
parse("for (; i < j;){}").getFirstChild().getFirstChild().getNext();
assertEquals(Token.LT, lt.getType());
assertEquals(0, lt.getLineno());
assertEquals(9, lt.getCharno());
}
public void testLinenoCharnoHook() throws Exception {
Node n = parse("\n a ? 9 : 0").getFirstChild().getFirstChild();
assertEquals(Token.HOOK, n.getType());
assertEquals(1, n.getLineno());
assertEquals(3, n.getCharno());
}
public void testLinenoCharnoArrayLiteral() throws Exception {
Node n = parse("\n [8, 9]").getFirstChild().getFirstChild();
assertEquals(Token.ARRAYLIT, n.getType());
assertEquals(1, n.getLineno());
assertEquals(2, n.getCharno());
n = n.getFirstChild();
assertEquals(Token.NUMBER, n.getType());
assertEquals(1, n.getLineno());
assertEquals(3, n.getCharno());
n = n.getNext();
assertEquals(Token.NUMBER, n.getType());
assertEquals(1, n.getLineno());
assertEquals(6, n.getCharno());
}
public void testLinenoCharnoObjectLiteral() throws Exception {
Node n = parse("\n\n var a = {a:0\n,b :1};")
.getFirstChild().getFirstChild().getFirstChild();
assertEquals(Token.OBJECTLIT, n.getType());
assertEquals(2, n.getLineno());
assertEquals(9, n.getCharno());
n = n.getFirstChild();
assertEquals(Token.STRING, n.getType());
assertEquals(2, n.getLineno());
assertEquals(10, n.getCharno());
n = n.getNext();
assertEquals(Token.NUMBER, n.getType());
assertEquals(2, n.getLineno());
assertEquals(12, n.getCharno());
n = n.getNext();
assertEquals(Token.STRING, n.getType());
assertEquals(3, n.getLineno());
assertEquals(1, n.getCharno());
n = n.getNext();
assertEquals(Token.NUMBER, n.getType());
assertEquals(3, n.getLineno());
assertEquals(4, n.getCharno());
}
public void testLinenoCharnoAdd() throws Exception {
testLinenoCharnoBinop("+");
}
public void testLinenoCharnoSub() throws Exception {
testLinenoCharnoBinop("-");
}
public void testLinenoCharnoMul() throws Exception {
testLinenoCharnoBinop("*");
}
public void testLinenoCharnoDiv() throws Exception {
testLinenoCharnoBinop("/");
}
public void testLinenoCharnoMod() throws Exception {
testLinenoCharnoBinop("%");
}
public void testLinenoCharnoShift() throws Exception {
testLinenoCharnoBinop("<<");
}
public void testLinenoCharnoBinaryAnd() throws Exception {
testLinenoCharnoBinop("&");
}
public void testLinenoCharnoAnd() throws Exception {
testLinenoCharnoBinop("&&");
}
public void testLinenoCharnoBinaryOr() throws Exception {
testLinenoCharnoBinop("|");
}
public void testLinenoCharnoOr() throws Exception {
testLinenoCharnoBinop("||");
}
public void testLinenoCharnoLt() throws Exception {
testLinenoCharnoBinop("<");
}
public void testLinenoCharnoLe() throws Exception {
testLinenoCharnoBinop("<=");
}
public void testLinenoCharnoGt() throws Exception {
testLinenoCharnoBinop(">");
}
public void testLinenoCharnoGe() throws Exception {
testLinenoCharnoBinop(">=");
}
private void testLinenoCharnoBinop(String binop) {
Node op = parse("var a = 89 " + binop + " 76").getFirstChild().
getFirstChild().getFirstChild();
assertEquals(0, op.getLineno());
assertEquals(11, op.getCharno());
}
public void testUnescapedSlashInRegexpCharClass() throws Exception {
// The tokenizer without the fix for this bug throws an error.
parse("var foo = /[/]/;");
parse("var foo = /[hi there/]/;");
parse("var foo = /[/yo dude]/;");
parse("var foo = /\\/[@#$/watashi/wa/suteevu/desu]/;");
}
private void assertNodeEquality(Node expected, Node found) {
String message = expected.checkTreeEquals(found);
if (message != null) {
fail(message);
}
}
@SuppressWarnings("unchecked")
public void testParse() {
Node a = Node.newString(Token.NAME, "a");
a.addChildToFront(Node.newString(Token.NAME, "b"));
List<ParserResult> testCases = ImmutableList.of(
new ParserResult(
"3;",
createScript(new Node(Token.EXPR_RESULT, Node.newNumber(3.0)))),
new ParserResult(
"var a = b;",
createScript(new Node(Token.VAR, a))),
new ParserResult(
"\"hell\\\no\\ world\\\n\\\n!\"",
createScript(new Node(Token.EXPR_RESULT,
Node.newString(Token.STRING, "hello world!")))));
for (ParserResult testCase : testCases) {
assertNodeEquality(testCase.node, parse(testCase.code));
}
}
private Node createScript(Node n) {
Node script = new ScriptOrFnNode(Token.SCRIPT);
script.addChildToBack(n);
return script;
}
public void testTrailingCommaWarning1() {
parse("var a = ['foo', 'bar'];");
}
public void testTrailingCommaWarning2() {
parse("var a = ['foo',,'bar'];");
}
public void testTrailingCommaWarning3() {
parse("var a = ['foo', 'bar',];", TRAILING_COMMA_MESSAGE);
}
public void testTrailingCommaWarning4() {
parse("var a = [,];", TRAILING_COMMA_MESSAGE);
}
public void testTrailingCommaWarning5() {
parse("var a = {'foo': 'bar'};");
}
public void testTrailingCommaWarning6() {
parse("var a = {'foo': 'bar',};", TRAILING_COMMA_MESSAGE);
}
public void testTrailingCommaWarning7() {
parse("var a = {,};", TRAILING_COMMA_MESSAGE);
}
private Node parse(String string, String... warnings) {
CompilerEnvirons environment = new CompilerEnvirons();
TestErrorReporter testErrorReporter = new TestErrorReporter(null, warnings);
environment.setErrorReporter(testErrorReporter);
environment.setParseJSDoc(true);
environment.setParseJSDocDocumentation(true);
Parser p = new Parser(environment, testErrorReporter);
Node script = p.parse(string, null, 0);
// verifying that all warnings were seen
assertTrue(testErrorReporter.hasEncounteredAllErrors());
assertTrue(testErrorReporter.hasEncounteredAllWarnings());
return script;
}
private static class ParserResult {
private final String code;
private final Node node;
private ParserResult(String code, Node node) {
this.code = code;
this.node = node;
}
}
}