425 lines
15 KiB
Java
425 lines
15 KiB
Java
/*
|
|
*
|
|
* ***** 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.javascript.rhino.Node.NodeMismatch;
|
|
import com.google.javascript.rhino.jstype.JSTypeNative;
|
|
import com.google.javascript.rhino.jstype.JSTypeRegistry;
|
|
import com.google.javascript.rhino.testing.TestErrorReporter;
|
|
|
|
import junit.framework.TestCase;
|
|
|
|
public class NodeTest extends TestCase {
|
|
public void testMergeExtractNormal() throws Exception {
|
|
testMergeExtract(5, 6);
|
|
testMergeExtract(456, 3423);
|
|
testMergeExtract(0, 0);
|
|
}
|
|
|
|
public void testMergeExtractErroneous() throws Exception {
|
|
assertEquals(-1, Node.mergeLineCharNo(-5, 90));
|
|
assertEquals(-1, Node.mergeLineCharNo(0, -1));
|
|
assertEquals(-1, Node.extractLineno(-1));
|
|
assertEquals(-1, Node.extractCharno(-1));
|
|
}
|
|
|
|
public void testMergeOverflowGraciously() throws Exception {
|
|
int linecharno = Node.mergeLineCharNo(89, 4096);
|
|
assertEquals(89, Node.extractLineno(linecharno));
|
|
assertEquals(4095, Node.extractCharno(linecharno));
|
|
}
|
|
|
|
public void testCheckTreeEqualsImplSame() {
|
|
Node node1 = new Node(1, new Node(2));
|
|
Node node2 = new Node(1, new Node(2));
|
|
assertEquals(null, node1.checkTreeEqualsImpl(node2));
|
|
}
|
|
|
|
public void testCheckTreeEqualsImplDifferentType() {
|
|
Node node1 = new Node(1, new Node(2));
|
|
Node node2 = new Node(2, new Node(2));
|
|
assertEquals(new NodeMismatch(node1, node2),
|
|
node1.checkTreeEqualsImpl(node2));
|
|
}
|
|
|
|
public void testCheckTreeEqualsImplDifferentChildCount() {
|
|
Node node1 = new Node(1, new Node(2));
|
|
Node node2 = new Node(1);
|
|
assertEquals(new NodeMismatch(node1, node2),
|
|
node1.checkTreeEqualsImpl(node2));
|
|
}
|
|
|
|
public void testCheckTreeEqualsImplDifferentChild() {
|
|
Node child1 = new Node(1);
|
|
Node child2 = new Node(2);
|
|
Node node1 = new Node(1, child1);
|
|
Node node2 = new Node(1, child2);
|
|
assertEquals(new NodeMismatch(child1, child2),
|
|
node1.checkTreeEqualsImpl(node2));
|
|
}
|
|
|
|
public void testCheckTreeEqualsSame() {
|
|
Node node1 = new Node(1);
|
|
assertEquals(null, node1.checkTreeEquals(node1));
|
|
}
|
|
|
|
public void testCheckTreeEqualsStringDifferent() {
|
|
Node node1 = new Node(Token.ADD);
|
|
Node node2 = new Node(Token.SUB);
|
|
assertNotNull(node1.checkTreeEquals(node2));
|
|
}
|
|
|
|
public void testCheckTreeEqualsBooleanSame() {
|
|
Node node1 = new Node(1);
|
|
assertEquals(true, node1.isEquivalentTo(node1));
|
|
}
|
|
|
|
public void testCheckTreeEqualsBooleanDifferent() {
|
|
Node node1 = new Node(1);
|
|
Node node2 = new Node(2);
|
|
assertEquals(false, node1.isEquivalentTo(node2));
|
|
}
|
|
|
|
public void testCheckTreeEqualsSlashVDifferent() {
|
|
Node node1 = Node.newString("\u000B");
|
|
node1.putBooleanProp(Node.SLASH_V, true);
|
|
Node node2 = Node.newString("\u000B");
|
|
assertEquals(false, node1.isEquivalentTo(node2));
|
|
}
|
|
|
|
public void testCheckTreeEqualsImplDifferentIncProp() {
|
|
Node node1 = new Node(Token.INC);
|
|
node1.putIntProp(Node.INCRDECR_PROP, 1);
|
|
Node node2 = new Node(Token.INC);
|
|
assertNotNull(node1.checkTreeEqualsImpl(node2));
|
|
}
|
|
|
|
public void testCheckTreeTypeAwareEqualsSame() {
|
|
TestErrorReporter testErrorReporter = new TestErrorReporter(null, null);
|
|
JSTypeRegistry registry = new JSTypeRegistry(testErrorReporter);
|
|
Node node1 = Node.newString(Token.NAME, "f");
|
|
node1.setJSType(registry.getNativeType(JSTypeNative.NUMBER_TYPE));
|
|
Node node2 = Node.newString(Token.NAME, "f");
|
|
node2.setJSType(registry.getNativeType(JSTypeNative.NUMBER_TYPE));
|
|
assertTrue(node1.isEquivalentToTyped(node2));
|
|
}
|
|
|
|
public void testCheckTreeTypeAwareEqualsSameNull() {
|
|
TestErrorReporter testErrorReporter = new TestErrorReporter(null, null);
|
|
JSTypeRegistry registry = new JSTypeRegistry(testErrorReporter);
|
|
Node node1 = Node.newString(Token.NAME, "f");
|
|
Node node2 = Node.newString(Token.NAME, "f");
|
|
assertTrue(node1.isEquivalentToTyped(node2));
|
|
}
|
|
|
|
public void testCheckTreeTypeAwareEqualsDifferent() {
|
|
TestErrorReporter testErrorReporter = new TestErrorReporter(null, null);
|
|
JSTypeRegistry registry = new JSTypeRegistry(testErrorReporter);
|
|
Node node1 = Node.newString(Token.NAME, "f");
|
|
node1.setJSType(registry.getNativeType(JSTypeNative.NUMBER_TYPE));
|
|
Node node2 = Node.newString(Token.NAME, "f");
|
|
node2.setJSType(registry.getNativeType(JSTypeNative.STRING_TYPE));
|
|
assertFalse(node1.isEquivalentToTyped(node2));
|
|
}
|
|
|
|
public void testCheckTreeTypeAwareEqualsDifferentNull() {
|
|
TestErrorReporter testErrorReporter = new TestErrorReporter(null, null);
|
|
JSTypeRegistry registry = new JSTypeRegistry(testErrorReporter);
|
|
Node node1 = Node.newString(Token.NAME, "f");
|
|
node1.setJSType(registry.getNativeType(JSTypeNative.NUMBER_TYPE));
|
|
Node node2 = Node.newString(Token.NAME, "f");
|
|
assertFalse(node1.isEquivalentToTyped(node2));
|
|
}
|
|
|
|
public void testVarArgs1() {
|
|
assertFalse(new Node(1).isVarArgs());
|
|
}
|
|
|
|
public void testVarArgs2() {
|
|
Node n = new Node(1);
|
|
n.setVarArgs(false);
|
|
assertFalse(n.isVarArgs());
|
|
}
|
|
|
|
public void testVarArgs3() {
|
|
Node n = new Node(1);
|
|
n.setVarArgs(true);
|
|
assertTrue(n.isVarArgs());
|
|
}
|
|
|
|
private void testMergeExtract(int lineno, int charno) {
|
|
int linecharno = Node.mergeLineCharNo(lineno, charno);
|
|
assertEquals(lineno, Node.extractLineno(linecharno));
|
|
assertEquals(charno, Node.extractCharno(linecharno));
|
|
}
|
|
|
|
public void testFileLevelJSDocAppender() {
|
|
Node n = new Node(1);
|
|
Node.FileLevelJsDocBuilder builder = n.getJsDocBuilderForNode();
|
|
builder.append("foo");
|
|
builder.append("bar");
|
|
assertEquals("foobar", n.getJSDocInfo().getLicense());
|
|
}
|
|
|
|
// TODO(johnlenz): reenable this test.
|
|
public void disable_testIsQualifiedName() {
|
|
assertTrue(getNode("a").isQualifiedName());
|
|
assertTrue(getNode("$").isQualifiedName());
|
|
assertTrue(getNode("_").isQualifiedName());
|
|
assertTrue(getNode("a.b").isQualifiedName());
|
|
assertTrue(getNode("a_b.cccccc$d4.x.y.zA$").isQualifiedName());
|
|
assertTrue(getNode("this.foo").isQualifiedName());
|
|
assertFalse(getNode("0").isQualifiedName());
|
|
assertFalse(getNode("[]").isQualifiedName());
|
|
assertFalse(getNode("{}").isQualifiedName());
|
|
assertFalse(getNode("''").isQualifiedName());
|
|
assertFalse(getNode("a[b]").isQualifiedName());
|
|
assertFalse(getNode("a[b].c").isQualifiedName());
|
|
assertFalse(getNode("c.a[b]").isQualifiedName());
|
|
assertFalse(getNode("a()").isQualifiedName());
|
|
assertFalse(getNode("a().b").isQualifiedName());
|
|
assertFalse(getNode("b.a()").isQualifiedName());
|
|
assertFalse(getNode("'a'").isQualifiedName());
|
|
assertFalse(getNode("/x/").isQualifiedName());
|
|
assertFalse(getNode("++x").isQualifiedName());
|
|
}
|
|
|
|
public void testCloneAnnontations() {
|
|
Node n = getVarRef("a");
|
|
assertFalse(n.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
n.putBooleanProp(Node.IS_CONSTANT_NAME, true);
|
|
assertTrue(n.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
|
|
Node nodeClone = n.cloneNode();
|
|
assertTrue(nodeClone.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
}
|
|
|
|
public void testSharedProps1() {
|
|
Node n = getVarRef("A");
|
|
n.putIntProp(Node.SIDE_EFFECT_FLAGS, 5);
|
|
Node m = new Node(Token.TRUE);
|
|
m.clonePropsFrom(n);
|
|
assertEquals(m.getPropListHeadForTesting(), n.getPropListHeadForTesting());
|
|
assertEquals(5, n.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
assertEquals(5, m.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
}
|
|
|
|
public void testSharedProps2() {
|
|
Node n = getVarRef("A");
|
|
n.putIntProp(Node.SIDE_EFFECT_FLAGS, 5);
|
|
Node m = new Node(Token.TRUE);
|
|
m.clonePropsFrom(n);
|
|
|
|
n.putIntProp(Node.SIDE_EFFECT_FLAGS, 6);
|
|
assertEquals(6, n.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
assertEquals(5, m.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
assertFalse(
|
|
m.getPropListHeadForTesting() == n.getPropListHeadForTesting());
|
|
|
|
m.putIntProp(Node.SIDE_EFFECT_FLAGS, 7);
|
|
assertEquals(6, n.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
assertEquals(7, m.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
}
|
|
|
|
public void testSharedProps3() {
|
|
Node n = getVarRef("A");
|
|
n.putIntProp(Node.SIDE_EFFECT_FLAGS, 2);
|
|
n.putIntProp(Node.INCRDECR_PROP, 3);
|
|
Node m = new Node(Token.TRUE);
|
|
m.clonePropsFrom(n);
|
|
|
|
n.putIntProp(Node.SIDE_EFFECT_FLAGS, 4);
|
|
assertEquals(4, n.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
assertEquals(2, m.getIntProp(Node.SIDE_EFFECT_FLAGS));
|
|
}
|
|
|
|
public void testBooleanProp() {
|
|
Node n = getVarRef("a");
|
|
|
|
n.putBooleanProp(Node.IS_CONSTANT_NAME, false);
|
|
|
|
assertNull(n.lookupProperty(Node.IS_CONSTANT_NAME));
|
|
assertFalse(n.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
|
|
n.putBooleanProp(Node.IS_CONSTANT_NAME, true);
|
|
|
|
assertNotNull(n.lookupProperty(Node.IS_CONSTANT_NAME));
|
|
assertTrue(n.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
|
|
n.putBooleanProp(Node.IS_CONSTANT_NAME, false);
|
|
|
|
assertNull(n.lookupProperty(Node.IS_CONSTANT_NAME));
|
|
assertFalse(n.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
}
|
|
|
|
// Verify that annotations on cloned nodes are properly handled.
|
|
public void testCloneAnnontations2() {
|
|
Node n = getVarRef("a");
|
|
n.putBooleanProp(Node.IS_CONSTANT_NAME, true);
|
|
n.putBooleanProp(Node.IS_DISPATCHER, true);
|
|
assertTrue(n.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
assertTrue(n.getBooleanProp(Node.IS_DISPATCHER));
|
|
|
|
Node nodeClone = n.cloneNode();
|
|
assertTrue(nodeClone.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
assertTrue(nodeClone.getBooleanProp(Node.IS_DISPATCHER));
|
|
|
|
n.putBooleanProp(Node.IS_DISPATCHER, false);
|
|
assertTrue(n.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
assertFalse(n.getBooleanProp(Node.IS_DISPATCHER));
|
|
|
|
assertTrue(nodeClone.getBooleanProp(Node.IS_CONSTANT_NAME));
|
|
assertTrue(nodeClone.getBooleanProp(Node.IS_DISPATCHER));
|
|
}
|
|
|
|
public void testGetIndexOfChild() {
|
|
Node assign = getAssignExpr("b","c");
|
|
assertEquals(2, assign.getChildCount());
|
|
|
|
Node firstChild = assign.getFirstChild();
|
|
Node secondChild = firstChild.getNext();
|
|
assertNotNull(secondChild);
|
|
|
|
assertEquals(0, assign.getIndexOfChild(firstChild));
|
|
assertEquals(1, assign.getIndexOfChild(secondChild));
|
|
assertEquals(-1, assign.getIndexOfChild(assign));
|
|
}
|
|
|
|
public void testCopyInformationFrom() {
|
|
Node assign = getAssignExpr("b","c");
|
|
assign.setSourceEncodedPosition(99);
|
|
assign.setSourceFileForTesting("foo.js");
|
|
|
|
Node lhs = assign.getFirstChild();
|
|
lhs.copyInformationFrom(assign);
|
|
assertEquals(99, lhs.getSourcePosition());
|
|
assertEquals("foo.js", lhs.getSourceFileName());
|
|
|
|
assign.setSourceEncodedPosition(101);
|
|
assign.setSourceFileForTesting("bar.js");
|
|
lhs.copyInformationFrom(assign);
|
|
assertEquals(99, lhs.getSourcePosition());
|
|
assertEquals("foo.js", lhs.getSourceFileName());
|
|
}
|
|
|
|
public void testUseSourceInfoIfMissingFrom() {
|
|
Node assign = getAssignExpr("b","c");
|
|
assign.setSourceEncodedPosition(99);
|
|
assign.setSourceFileForTesting("foo.js");
|
|
|
|
Node lhs = assign.getFirstChild();
|
|
lhs.useSourceInfoIfMissingFrom(assign);
|
|
assertEquals(99, lhs.getSourcePosition());
|
|
assertEquals("foo.js", lhs.getSourceFileName());
|
|
|
|
assign.setSourceEncodedPosition(101);
|
|
assign.setSourceFileForTesting("bar.js");
|
|
lhs.useSourceInfoIfMissingFrom(assign);
|
|
assertEquals(99, lhs.getSourcePosition());
|
|
assertEquals("foo.js", lhs.getSourceFileName());
|
|
}
|
|
|
|
public void testUseSourceInfoFrom() {
|
|
Node assign = getAssignExpr("b","c");
|
|
assign.setSourceEncodedPosition(99);
|
|
assign.setSourceFileForTesting("foo.js");
|
|
|
|
Node lhs = assign.getFirstChild();
|
|
lhs.useSourceInfoFrom(assign);
|
|
assertEquals(99, lhs.getSourcePosition());
|
|
assertEquals("foo.js", lhs.getSourceFileName());
|
|
|
|
assign.setSourceEncodedPosition(101);
|
|
assign.setSourceFileForTesting("bar.js");
|
|
lhs.useSourceInfoFrom(assign);
|
|
assertEquals(101, lhs.getSourcePosition());
|
|
assertEquals("bar.js", lhs.getSourceFileName());
|
|
}
|
|
|
|
public void testInvalidSourceOffset() {
|
|
Node string = Node.newString("a");
|
|
|
|
string.setSourceEncodedPosition(-1);
|
|
assertTrue(string.getSourceOffset() < 0);
|
|
|
|
string.setSourceFileForTesting("foo.js");
|
|
assertTrue(string.getSourceOffset() < 0);
|
|
}
|
|
|
|
public void testQualifiedName() {
|
|
assertNull(IR.name("").getQualifiedName());
|
|
assertEquals("a", IR.name("a").getQualifiedName());
|
|
assertEquals(
|
|
"a.b", IR.getprop(IR.name("a"), IR.string("b")).getQualifiedName());
|
|
assertEquals(
|
|
"this.b", IR.getprop(IR.thisNode(), IR.string("b")).getQualifiedName());
|
|
assertNull(
|
|
IR.getprop(IR.call(IR.name("a")), IR.string("b")).getQualifiedName());
|
|
}
|
|
|
|
private static Node getVarRef(String name) {
|
|
return Node.newString(Token.NAME, name);
|
|
}
|
|
|
|
private static Node getAssignExpr(String name1, String name2) {
|
|
return new Node(Token.ASSIGN, getVarRef(name1), getVarRef(name2));
|
|
}
|
|
|
|
private static Node getNode(String js) {
|
|
/*
|
|
Node root = parse("var a=(" + js + ");");
|
|
Node expr = root.getFirstChild();
|
|
Node var = expr.getFirstChild();
|
|
return var.getFirstChild();
|
|
*/
|
|
return null;
|
|
}
|
|
|
|
private static Node parse(String string) {
|
|
/*
|
|
CompilerEnvirons environment = new CompilerEnvirons();
|
|
TestErrorReporter testErrorReporter = new TestErrorReporter(null, null);
|
|
environment.setErrorReporter(testErrorReporter);
|
|
environment.setParseJSDoc(true);
|
|
Parser p = new Parser(environment, testErrorReporter);
|
|
return p.parse(string, null, 0);
|
|
*/
|
|
return null;
|
|
}
|
|
}
|