851 lines
29 KiB
Java
851 lines
29 KiB
Java
|
/*
|
||
|
* Copyright 2010 The Closure Compiler Authors.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package com.google.javascript.jscomp.jsonml;
|
||
|
|
||
|
import com.google.javascript.jscomp.jsonml.JsonML;
|
||
|
import com.google.javascript.jscomp.jsonml.JsonMLUtil;
|
||
|
import com.google.javascript.jscomp.jsonml.TagAttr;
|
||
|
import com.google.javascript.jscomp.jsonml.TagType;
|
||
|
import com.google.javascript.jscomp.jsonml.Validator;
|
||
|
|
||
|
import junit.framework.TestCase;
|
||
|
|
||
|
/**
|
||
|
* Tests validation of particular JsonML elements.
|
||
|
*
|
||
|
* @author dhans@google.com (Daniel Hans)
|
||
|
*/
|
||
|
public class JsonMLValidationTest extends TestCase {
|
||
|
|
||
|
// Used for correct statements - error message should be null
|
||
|
private void testValidation(String jsonml) throws Exception {
|
||
|
JsonML jsonMLRoot = JsonMLUtil.parseString(jsonml);
|
||
|
String msg = Validator.validate(jsonMLRoot);
|
||
|
if (msg != null) {
|
||
|
String errorMsg = String.format(
|
||
|
"Validation error for %s.\n Received: %s\n", jsonml, msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void testValidation(String jsonml, String expected)
|
||
|
throws Exception {
|
||
|
JsonML jsonMLRoot = JsonMLUtil.parseString(jsonml);
|
||
|
String msg = Validator.validate(jsonMLRoot);
|
||
|
if (!msg.equals(expected)) {
|
||
|
String errorMsg = String.format(
|
||
|
"Validation error for %s.\n Received: %s\n Expected: %s\n",
|
||
|
jsonml, msg, expected);
|
||
|
assertEquals(errorMsg, expected, msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void testNotEnoughChildrenValidation(String jsonml, TagType type,
|
||
|
int expected, int actual) throws Exception {
|
||
|
testValidation(jsonml,
|
||
|
String.format(Validator.NOT_ENOUGH_CHILDREN_FMT,
|
||
|
type, expected, actual));
|
||
|
}
|
||
|
|
||
|
private void testTooManyChildrenValidation(String jsonml, TagType type,
|
||
|
int expected, int actual) throws Exception {
|
||
|
testValidation(jsonml,
|
||
|
String.format(Validator.TOO_MANY_CHILDREN_FMT,
|
||
|
type, expected, actual));
|
||
|
}
|
||
|
|
||
|
private void testWrongChildTypeValidation(String jsonml, TagType type,
|
||
|
TagType expected, TagType actual, int index) throws Exception {
|
||
|
testWrongChildTypeValidation(jsonml, type, new TagType[] { expected },
|
||
|
actual, index);
|
||
|
}
|
||
|
|
||
|
private void testWrongChildTypeValidation(String jsonml, TagType type,
|
||
|
TagType[] expected, TagType actual, int index) throws Exception {
|
||
|
testValidation(jsonml,
|
||
|
String.format(Validator.WRONG_CHILD_TYPE_FMT,
|
||
|
index, type, Validator.printList(expected), actual));
|
||
|
}
|
||
|
|
||
|
private void testMissingArgument(String jsonml, TagAttr attr, TagType type)
|
||
|
throws Exception {
|
||
|
testValidation(jsonml,
|
||
|
String.format(Validator.MISSING_ARGUMENT, attr, type));
|
||
|
}
|
||
|
|
||
|
public void testAssignExpr() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['AssignExpr',{'op':'='}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['AssignExpr',{'op':'='}," +
|
||
|
"['IdExpr',{'name':'x'}]]",
|
||
|
TagType.AssignExpr, 2, 1);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['AssignExpr',{'op':'='}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]," +
|
||
|
"['IdExpr',{'name':'z'}]]",
|
||
|
TagType.AssignExpr, 2, 3);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['AssignExpr',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]",
|
||
|
TagAttr.OP, TagType.AssignExpr);
|
||
|
}
|
||
|
|
||
|
public void testBinaryExpr() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['BinaryExpr',{'op':'+'}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['BinaryExpr',{'op':'+'}," +
|
||
|
"['IdExpr',{'name':'a'}]]",
|
||
|
TagType.BinaryExpr, 2, 1);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['BinaryExpr',{'op':'&&'}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['IdExpr',{'name':'b'}]," +
|
||
|
"['IdExpr',{'name':'c'}]]",
|
||
|
TagType.BinaryExpr, 2, 3);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['BinaryExpr',{}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]",
|
||
|
TagAttr.OP, TagType.BinaryExpr);
|
||
|
}
|
||
|
|
||
|
public void testCaseValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['Case',{}," +
|
||
|
"['IdExpr',{'name':'a'}]]");
|
||
|
testValidation("" +
|
||
|
"['Case',{}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'foo'}]]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['Case',{}]",
|
||
|
TagType.Case, 1, 0);
|
||
|
}
|
||
|
|
||
|
public void testCatchValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdPatt',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdPatt',{'name':'e'}]]",
|
||
|
TagType.CatchClause, 2, 1);
|
||
|
// wrong children types
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdExpr',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.CatchClause, TagType.IdPatt, TagType.IdExpr, 0);
|
||
|
}
|
||
|
|
||
|
public void testConditionalExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ConditionalExpr',{}," +
|
||
|
"['BinaryExpr',{'op':'=='}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['ConditionalExpr',{}," +
|
||
|
"['BinaryExpr',{'op':'=='}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]]",
|
||
|
TagType.ConditionalExpr, 3, 1);
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['ConditionalExpr',{}," +
|
||
|
"['BinaryExpr',{'op':'=='}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]",
|
||
|
TagType.ConditionalExpr, 3, 2);
|
||
|
}
|
||
|
|
||
|
public void testCountExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['CountExpr',{'isPrefix':false,'op':'++'}," +
|
||
|
"['IdExpr',{'name':'x'}]]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['CountExpr',{'isPrefix':false,'op':'++'}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.CountExpr, 1, 2);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['CountExpr',{'op':'++'}," +
|
||
|
"['IdExpr',{'name':'x'}]]",
|
||
|
TagAttr.IS_PREFIX, TagType.CountExpr);
|
||
|
testMissingArgument("" +
|
||
|
"['CountExpr',{'isPrefix':false}," +
|
||
|
"['IdExpr',{'name':'x'}]]",
|
||
|
TagAttr.OP, TagType.CountExpr);
|
||
|
}
|
||
|
|
||
|
public void testDataProp() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['DataProp',{'name':'x'}," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['DataProp',{'name':'x'}]",
|
||
|
TagType.DataProp, 1, 0);
|
||
|
// missing argument
|
||
|
testMissingArgument("" +
|
||
|
"['DataProp', {}," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]",
|
||
|
TagAttr.NAME, TagType.DataProp);
|
||
|
}
|
||
|
|
||
|
public void testDeleteExpr() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['DeleteExpr',{}," +
|
||
|
"['IdExpr',{'name':'x'}]]");
|
||
|
//wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['DeleteExpr',{}]",
|
||
|
TagType.DeleteExpr, 1, 0);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['DeleteExpr',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.DeleteExpr, 1, 2);
|
||
|
}
|
||
|
|
||
|
public void testDoWhileStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['DoWhileStmt',{}," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['DoWhileStmt',{}]",
|
||
|
TagType.DoWhileStmt, 2, 0);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['DoWhileStmt',{}," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]]",
|
||
|
TagType.DoWhileStmt, 2, 3);
|
||
|
}
|
||
|
|
||
|
public void testEmptyStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['EmptyStmt',{}]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['EmptyStmt',{}," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.EmptyStmt, 0, 1);
|
||
|
}
|
||
|
|
||
|
public void testForInStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ForInStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['ObjectExpr',{}]," +
|
||
|
"['BlockStmt',{}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['ForInStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['ObjectExpr',{}]],",
|
||
|
TagType.ForInStmt, 3, 2);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['ForInStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['ObjectExpr',{}]," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.ForInStmt, 3, 4);
|
||
|
}
|
||
|
|
||
|
public void testForStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ForStmt',{}," +
|
||
|
"['AssignExpr',{'op':'='}," +
|
||
|
"['IdExpr',{'name':'i'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]," +
|
||
|
"['BinaryExpr',{'op':'<'}," +
|
||
|
"['IdExpr',{'name':'i'}]," +
|
||
|
"['IdExpr',{'name':'n'}]]," +
|
||
|
"['CountExpr',{'isPrefix':true,'op':'++'}," +
|
||
|
"['IdExpr',{'name':'i'}]]," +
|
||
|
"['BlockStmt',{}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['ForStmt',{}," +
|
||
|
"['BinaryExpr',{'op':'<'}," +
|
||
|
"['IdExpr',{'name':'i'}]," +
|
||
|
"['IdExpr',{'name':'n'}]]," +
|
||
|
"['CountExpr',{'isPrefix':true,'op':'++'}," +
|
||
|
"['IdExpr',{'name':'i'}]]," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.ForStmt, 4, 3);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['ForStmt',{}," +
|
||
|
"['AssignExpr',{'op':'='}," +
|
||
|
"['IdExpr',{'name':'i'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]," +
|
||
|
"['BinaryExpr',{'op':'<'}," +
|
||
|
"['IdExpr',{'name':'i'}]," +
|
||
|
"['IdExpr',{'name':'n'}]]," +
|
||
|
"['CountExpr',{'isPrefix':true,'op':'++'}," +
|
||
|
"['IdExpr',{'name':'i'}]]," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.ForStmt, 4, 5);
|
||
|
}
|
||
|
|
||
|
public void testFunctionDeclValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['FunctionDecl',{}," +
|
||
|
"['IdPatt',{'name':'f'}]," +
|
||
|
"['ParamDecl',{}]]");
|
||
|
testValidation("" +
|
||
|
"['FunctionDecl',{}," +
|
||
|
"['IdPatt',{'name':'f'}]," +
|
||
|
"['ParamDecl',{}]," +
|
||
|
"['IdExpr',{'name':'foo'}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['FunctionDecl',{}," +
|
||
|
"['IdPatt',{'name':'f'}]]",
|
||
|
TagType.FunctionDecl, 2, 1);
|
||
|
// function name not specified
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['FunctionDecl',{}," +
|
||
|
"['Empty', {}]," +
|
||
|
"['ParamDecl',{}]]",
|
||
|
TagType.FunctionDecl, TagType.IdPatt, TagType.Empty, 0);
|
||
|
// list of formal arguments not specified
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['FunctionDecl',{}," +
|
||
|
"['IdPatt',{'name':'f'}]," +
|
||
|
"['Empty',{}]]",
|
||
|
TagType.FunctionDecl, TagType.ParamDecl, TagType.Empty, 1);
|
||
|
}
|
||
|
|
||
|
public void testFunctionExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['FunctionExpr',{}," +
|
||
|
"['IdPatt',{'name':'f'}]," +
|
||
|
"['ParamDecl',{}]]");
|
||
|
testValidation("" +
|
||
|
"['FunctionExpr',{}," +
|
||
|
"['IdPatt',{'name':'f'}]," +
|
||
|
"['ParamDecl',{}]," +
|
||
|
"['IdExpr',{'name':'foo'}]]");
|
||
|
testValidation("" +
|
||
|
"['FunctionExpr',{}," +
|
||
|
"['Empty', {}]," +
|
||
|
"['ParamDecl',{}]]");
|
||
|
}
|
||
|
|
||
|
public void testIdExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['IdExpr',{'name':'x'}]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['IdExpr',{'name':'x'}," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.IdExpr, 0, 1);
|
||
|
// missing name argument
|
||
|
testMissingArgument("" +
|
||
|
"['IdExpr', {}]",
|
||
|
TagAttr.NAME, TagType.IdExpr);
|
||
|
}
|
||
|
|
||
|
public void testIdPattValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['IdPatt',{'name':'x'}]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['IdPatt',{'name':'x'}," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.IdPatt, 0, 1);
|
||
|
// missing name argument
|
||
|
testMissingArgument("" +
|
||
|
"['IdPatt', {}]",
|
||
|
TagAttr.NAME, TagType.IdPatt);
|
||
|
}
|
||
|
|
||
|
public void testIfStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['IfStmt',{}," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['EmptyStmt',{}]]");
|
||
|
testValidation("" +
|
||
|
"['IfStmt',{}," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['BlockStmt',{}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['IfStmt',{}," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.IfStmt, 3, 2);
|
||
|
}
|
||
|
|
||
|
public void testInvokeExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['InvokeExpr',{'op':'.'}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'string','value':'foo'}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['InvokeExpr',{'op':'[]'}," +
|
||
|
"['IdExpr',{'name':'x'}]]",
|
||
|
TagType.InvokeExpr, 2, 1);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['InvokeExpr',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'string','value':'foo'}]]",
|
||
|
TagAttr.OP, TagType.InvokeExpr);
|
||
|
}
|
||
|
|
||
|
public void testJmpStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['BreakStmt',{}]");
|
||
|
testValidation("" +
|
||
|
"['BreakStmt',{'label':'s'}]");
|
||
|
testValidation("" +
|
||
|
"['ContinueStmt',{}]");
|
||
|
testValidation("" +
|
||
|
"['ContinueStmt',{'label':'s'}]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['BreakStmt',{}," +
|
||
|
"['IdExpr',{'name':'s'}]]",
|
||
|
TagType.BreakStmt, 0, 1);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['ContinueStmt',{}," +
|
||
|
"['IdExpr',{'name':'s'}]]",
|
||
|
TagType.ContinueStmt, 0, 1);
|
||
|
}
|
||
|
|
||
|
public void testLabelledStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['LabelledStmt',{'label':'s'}," +
|
||
|
"['IdExpr',{'name':'x'}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['LabelledStmt',{'label':'s'}]",
|
||
|
TagType.LabelledStmt, 1, 0);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['LabelledStmt',{'label':'s'}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.LabelledStmt, 1, 2);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['LabelledStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]]",
|
||
|
TagAttr.LABEL, TagType.LabelledStmt);
|
||
|
}
|
||
|
|
||
|
public void testLiteralExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['LiteralExpr',{'type':'string','value':'x'}]");
|
||
|
testValidation("" +
|
||
|
"['LiteralExpr',{'type':'boolean','value':'true'}]");
|
||
|
testValidation("" +
|
||
|
"['LiteralExpr',{'type':'number','value':'1.0'}]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['LiteralExpr',{'type':'number','value':'1.0'}," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.LiteralExpr, 0, 1);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['LiteralExpr',{'type':'string'}]",
|
||
|
TagAttr.VALUE, TagType.LiteralExpr);
|
||
|
testMissingArgument("" +
|
||
|
"['LiteralExpr',{'value':'1.0'}]",
|
||
|
TagAttr.TYPE, TagType.LiteralExpr);
|
||
|
}
|
||
|
|
||
|
public void testLogicalExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['LogicalAndExpr',{}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['IdExpr',{'name':'b'}]]");
|
||
|
testValidation("" +
|
||
|
"['LogicalOrExpr',{}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['IdExpr',{'name':'b'}]]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['LogicalAndExpr',{}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['IdExpr',{'name':'b'}]," +
|
||
|
"['IdExpr',{'name':'c'}]]",
|
||
|
TagType.LogicalAndExpr, 2, 3);
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['LogicalAndExpr',{}," +
|
||
|
"['IdExpr',{'name':'a'}]]",
|
||
|
TagType.LogicalAndExpr, 2, 1);
|
||
|
}
|
||
|
|
||
|
public void testNewExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['NewExpr',{}," +
|
||
|
"['IdExpr',{'name':'A'}]," +
|
||
|
"['IdExpr',{'name':'x'}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['NewExpr',{}]",
|
||
|
TagType.NewExpr, 1, 0);
|
||
|
}
|
||
|
|
||
|
public void testObjectExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ObjectExpr',{}]");
|
||
|
testValidation("" +
|
||
|
"['ObjectExpr',{}," +
|
||
|
"['DataProp',{'name':'x'}," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]," +
|
||
|
"['DataProp',{'name':'y'}," +
|
||
|
"['LiteralExpr',{'type':'number','value':2}]]]");
|
||
|
// wrong types of children
|
||
|
TagType[] tags =
|
||
|
{TagType.DataProp, TagType.GetterProp, TagType.SetterProp };
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['ObjectExpr',{}," +
|
||
|
"['DataProp',{'name':'x'}," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.ObjectExpr, tags, TagType.IdExpr, 1);
|
||
|
}
|
||
|
|
||
|
public void testParamDeclValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ParamDecl',{}]");
|
||
|
testValidation("" +
|
||
|
"['ParamDecl',{}," +
|
||
|
"['IdPatt',{'name':'x'}]," +
|
||
|
"['IdPatt',{'name':'y'}]]");
|
||
|
// wrong types of children
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['ParamDecl',{}," +
|
||
|
"['IdPatt',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.ParamDecl, TagType.IdPatt, TagType.IdExpr, 1);
|
||
|
}
|
||
|
|
||
|
public void testRegExpExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['RegExpExpr',{'body':'abc','flags':''}]");
|
||
|
testValidation("" +
|
||
|
"['RegExpExpr',{'body':'abc','flags':'g'}]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['RegExpExpr',{'body':'abc','flags':'g'}," +
|
||
|
"['IdExpr',{'name':'a'}]]",
|
||
|
TagType.RegExpExpr, 0, 1);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['RegExpExpr',{'body':'abc'}]",
|
||
|
TagAttr.FLAGS, TagType.RegExpExpr);
|
||
|
testMissingArgument("" +
|
||
|
"['RegExpExpr',{'flags':'g'}]",
|
||
|
TagAttr.BODY, TagType.RegExpExpr);
|
||
|
}
|
||
|
|
||
|
public void testReturnStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ReturnStmt',{}]");
|
||
|
testValidation("" +
|
||
|
"['ReturnStmt',{}," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['ReturnStmt',{}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['IdExpr',{'name':'b'}]]",
|
||
|
TagType.ReturnStmt, 1, 2);
|
||
|
}
|
||
|
|
||
|
public void testSwitchStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['SwitchStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['Case',{}," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'foo'}]]]," +
|
||
|
"['DefaultCase',{}," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'bar'}]]]]");
|
||
|
testValidation("" +
|
||
|
"['SwitchStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['SwitchStmt',{}]",
|
||
|
TagType.SwitchStmt, 1, 0);
|
||
|
// wrong types of children
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['SwitchStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['AssignExpr',{'op': '='}," +
|
||
|
"['LiteralExpr',{'type':'number','value':1}]," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'foo'}]]]," +
|
||
|
"['DefaultCase',{}," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'bar'}]]]]",
|
||
|
TagType.SwitchStmt,
|
||
|
new TagType[] { TagType.Case, TagType.DefaultCase },
|
||
|
TagType.AssignExpr, 1);
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['SwitchStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['DefaultCase',{}," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'foo'}]]]," +
|
||
|
"['DefaultCase',{}," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'bar'}]]]]",
|
||
|
TagType.SwitchStmt, TagType.Case, TagType.DefaultCase, 2);
|
||
|
}
|
||
|
|
||
|
public void testThisExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ThisExpr',{}]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['ThisExpr',{}," +
|
||
|
"['IdExpr',{'name':'a'}]]",
|
||
|
TagType.ThisExpr, 0, 1);
|
||
|
}
|
||
|
|
||
|
public void testThrowStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['ThrowStmt',{}," +
|
||
|
"['IdExpr',{'name':'e'}]]");
|
||
|
// wrong number of children
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['ThrowStmt',{}," +
|
||
|
"['IdExpr',{'name':'a'}]," +
|
||
|
"['IdExpr',{'name':'b'}]]",
|
||
|
TagType.ThrowStmt, 1, 2);
|
||
|
}
|
||
|
|
||
|
public void testTryStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['TryStmt',{}," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdPatt',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]]");
|
||
|
testValidation("" +
|
||
|
"['TryStmt',{}," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdPatt',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]," +
|
||
|
"['BlockStmt',{}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['TryStmt',{}," +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdPatt',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]]",
|
||
|
TagType.TryStmt, 2, 1);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['TryStmt',{}," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdPatt',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.TryStmt, 3, 4);
|
||
|
// wrong type of children
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['TryStmt',{}," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['BlockStmt',{}," +
|
||
|
"['IdPatt',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.TryStmt,
|
||
|
new TagType[] { TagType.CatchClause, TagType.Empty },
|
||
|
TagType.BlockStmt, 1);
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['TryStmt',{}," +
|
||
|
"['BlockStmt',{}]," +
|
||
|
"['CatchClause',{}," +
|
||
|
"['IdPatt',{'name':'e'}]," +
|
||
|
"['BlockStmt',{}]]," +
|
||
|
"['IdExpr',{'name': 'x'}]]",
|
||
|
TagType.TryStmt, TagType.BlockStmt, TagType.IdExpr, 2);
|
||
|
}
|
||
|
|
||
|
public void testUnaryExprValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['UnaryExpr',{'op':'-'}," +
|
||
|
"['IdExpr',{'name':'x'}]]");
|
||
|
testValidation("" +
|
||
|
"['UnaryExpr',{'op':'!'}," +
|
||
|
"['CallExpr',{}," +
|
||
|
"['IdExpr',{'name':'f'}]," +
|
||
|
"['IdExpr',{'name':'x'}]]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['UnaryExpr',{'op':'-'}]",
|
||
|
TagType.UnaryExpr, 1, 0);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['UnaryExpr',{'op':'+'}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.UnaryExpr, 1, 2);
|
||
|
// missing attribute
|
||
|
testMissingArgument("" +
|
||
|
"['UnaryExpr',{}," +
|
||
|
"['IdExpr',{'name':'x'}]]",
|
||
|
TagAttr.OP, TagType.UnaryExpr);
|
||
|
}
|
||
|
|
||
|
public void testVarDeclValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['VarDecl',{}," +
|
||
|
"['IdPatt',{'name':'x'}]]");
|
||
|
testValidation("" +
|
||
|
"['VarDecl',{}," +
|
||
|
"['InitPatt',{}," +
|
||
|
"['IdPatt',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]]");
|
||
|
testValidation("" +
|
||
|
"['VarDecl',{}," +
|
||
|
"['InitPatt',{}," +
|
||
|
"['IdPatt',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]," +
|
||
|
"['IdPatt',{'name':'y'}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['VarDecl',{}]",
|
||
|
TagType.VarDecl, 1, 0);
|
||
|
// wrong type of children
|
||
|
testWrongChildTypeValidation("" +
|
||
|
"['VarDecl',{}," +
|
||
|
"['InitPatt',{}," +
|
||
|
"['IdPatt',{'name':'x'}]," +
|
||
|
"['LiteralExpr',{'type':'number','value':0}]]," +
|
||
|
"['IdExpr',{'name':'y'}]," +
|
||
|
"['IdPatt',{'name':'z'}]]",
|
||
|
TagType.VarDecl,
|
||
|
new TagType[] { TagType.InitPatt, TagType.IdPatt },
|
||
|
TagType.IdExpr, 1);
|
||
|
}
|
||
|
|
||
|
public void testWhileStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['WhileStmt',{}," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]," +
|
||
|
"['BlockStmt',{}]]");
|
||
|
testValidation("" +
|
||
|
"['WhileStmt',{}," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]," +
|
||
|
"['IdExpr',{'name':'x'}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['WhileStmt',{}," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.WhileStmt, 2, 1);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['WhileStmt',{}," +
|
||
|
"['LiteralExpr',{'type':'boolean','value':true}]," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.WhileStmt, 2, 3);
|
||
|
}
|
||
|
|
||
|
public void testWithStmtValidation() throws Exception {
|
||
|
// correct statement
|
||
|
testValidation("" +
|
||
|
"['WithStmt',{}," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['BlockStmt',{}]]");
|
||
|
// wrong number of children
|
||
|
testNotEnoughChildrenValidation("" +
|
||
|
"['WithStmt',{}," +
|
||
|
"['BlockStmt',{}]]",
|
||
|
TagType.WithStmt, 2, 1);
|
||
|
testTooManyChildrenValidation("" +
|
||
|
"['WithStmt',{}," +
|
||
|
"['IdExpr',{'name':'A'}]," +
|
||
|
"['IdExpr',{'name':'x'}]," +
|
||
|
"['IdExpr',{'name':'y'}]]",
|
||
|
TagType.WithStmt, 2, 3);
|
||
|
}
|
||
|
}
|