traceur
Version:
ES6 to ES5 compiler
647 lines (646 loc) • 29.7 kB
JavaScript
"use strict";
function $__interopRequire(id) {
id = require(id);
return id && id.__esModule && id || {default: id};
}
Object.defineProperties(module.exports, {
__esModule: {value: true},
ParseTreeValidator: {
enumerable: true,
get: function() {
return ParseTreeValidator;
}
}
});
var $__createClass = $__interopRequire("traceur/dist/commonjs/runtime/modules/createClass.js").default;
var $__superConstructor = $__interopRequire("traceur/dist/commonjs/runtime/modules/superConstructor.js").default;
var NewExpression = require("../syntax/trees/ParseTrees.js").NewExpression;
var ParseTreeVisitor = require("./ParseTreeVisitor.js").ParseTreeVisitor;
var TreeWriter = require("../outputgeneration/TreeWriter.js").TreeWriter;
var $__9 = require("./TokenType.js"),
AMPERSAND = $__9.AMPERSAND,
AMPERSAND_EQUAL = $__9.AMPERSAND_EQUAL,
AND = $__9.AND,
BAR = $__9.BAR,
BAR_EQUAL = $__9.BAR_EQUAL,
CARET = $__9.CARET,
CARET_EQUAL = $__9.CARET_EQUAL,
CLOSE_ANGLE = $__9.CLOSE_ANGLE,
EQUAL = $__9.EQUAL,
EQUAL_EQUAL = $__9.EQUAL_EQUAL,
EQUAL_EQUAL_EQUAL = $__9.EQUAL_EQUAL_EQUAL,
GREATER_EQUAL = $__9.GREATER_EQUAL,
IDENTIFIER = $__9.IDENTIFIER,
IN = $__9.IN,
INSTANCEOF = $__9.INSTANCEOF,
LEFT_SHIFT = $__9.LEFT_SHIFT,
LEFT_SHIFT_EQUAL = $__9.LEFT_SHIFT_EQUAL,
LESS_EQUAL = $__9.LESS_EQUAL,
MINUS = $__9.MINUS,
MINUS_EQUAL = $__9.MINUS_EQUAL,
NOT_EQUAL = $__9.NOT_EQUAL,
NOT_EQUAL_EQUAL = $__9.NOT_EQUAL_EQUAL,
NUMBER = $__9.NUMBER,
OPEN_ANGLE = $__9.OPEN_ANGLE,
OR = $__9.OR,
PERCENT = $__9.PERCENT,
PERCENT_EQUAL = $__9.PERCENT_EQUAL,
PLUS = $__9.PLUS,
PLUS_EQUAL = $__9.PLUS_EQUAL,
RIGHT_SHIFT = $__9.RIGHT_SHIFT,
RIGHT_SHIFT_EQUAL = $__9.RIGHT_SHIFT_EQUAL,
SLASH = $__9.SLASH,
SLASH_EQUAL = $__9.SLASH_EQUAL,
STAR = $__9.STAR,
STAR_EQUAL = $__9.STAR_EQUAL,
STAR_STAR = $__9.STAR_STAR,
STAR_STAR_EQUAL = $__9.STAR_STAR_EQUAL,
STRING = $__9.STRING,
UNSIGNED_RIGHT_SHIFT = $__9.UNSIGNED_RIGHT_SHIFT,
UNSIGNED_RIGHT_SHIFT_EQUAL = $__9.UNSIGNED_RIGHT_SHIFT_EQUAL,
YIELD = $__9.YIELD;
var $__10 = require("./trees/ParseTreeType.js"),
ARRAY_PATTERN = $__10.ARRAY_PATTERN,
ASSIGNMENT_ELEMENT = $__10.ASSIGNMENT_ELEMENT,
BINDING_ELEMENT = $__10.BINDING_ELEMENT,
BINDING_IDENTIFIER = $__10.BINDING_IDENTIFIER,
BLOCK = $__10.BLOCK,
CASE_CLAUSE = $__10.CASE_CLAUSE,
CATCH = $__10.CATCH,
CLASS_DECLARATION = $__10.CLASS_DECLARATION,
COMPUTED_PROPERTY_NAME = $__10.COMPUTED_PROPERTY_NAME,
DEFAULT_CLAUSE = $__10.DEFAULT_CLAUSE,
EXPORT_DEFAULT = $__10.EXPORT_DEFAULT,
EXPORT_SPECIFIER = $__10.EXPORT_SPECIFIER,
EXPORT_SPECIFIER_SET = $__10.EXPORT_SPECIFIER_SET,
EXPORT_STAR = $__10.EXPORT_STAR,
FINALLY = $__10.FINALLY,
FORMAL_PARAMETER = $__10.FORMAL_PARAMETER,
FORMAL_PARAMETER_LIST = $__10.FORMAL_PARAMETER_LIST,
FORWARD_DEFAULT_EXPORT = $__10.FORWARD_DEFAULT_EXPORT,
FUNCTION_BODY = $__10.FUNCTION_BODY,
FUNCTION_DECLARATION = $__10.FUNCTION_DECLARATION,
GET_ACCESSOR = $__10.GET_ACCESSOR,
IDENTIFIER_EXPRESSION = $__10.IDENTIFIER_EXPRESSION,
IMPORTED_BINDING = $__10.IMPORTED_BINDING,
IMPORT_CLAUSE_PAIR = $__10.IMPORT_CLAUSE_PAIR,
IMPORT_SPECIFIER_SET = $__10.IMPORT_SPECIFIER_SET,
IMPORT_TYPE_CLAUSE = $__10.IMPORT_TYPE_CLAUSE,
JSX_ATTRIBUTE = $__10.JSX_ATTRIBUTE,
JSX_ELEMENT_NAME = $__10.JSX_ELEMENT_NAME,
JSX_ELEMENT = $__10.JSX_ELEMENT,
JSX_PLACEHOLDER = $__10.JSX_PLACEHOLDER,
JSX_SPREAD_ATTRIBUTE = $__10.JSX_SPREAD_ATTRIBUTE,
JSX_TEXT = $__10.JSX_TEXT,
LITERAL_PROPERTY_NAME = $__10.LITERAL_PROPERTY_NAME,
METHOD = $__10.METHOD,
MODULE_SPECIFIER = $__10.MODULE_SPECIFIER,
NAMED_EXPORT = $__10.NAMED_EXPORT,
NAME_SPACE_EXPORT = $__10.NAME_SPACE_EXPORT,
NAME_SPACE_IMPORT = $__10.NAME_SPACE_IMPORT,
OBJECT_PATTERN = $__10.OBJECT_PATTERN,
OBJECT_PATTERN_FIELD = $__10.OBJECT_PATTERN_FIELD,
PROPERTY_NAME_ASSIGNMENT = $__10.PROPERTY_NAME_ASSIGNMENT,
PROPERTY_NAME_SHORTHAND = $__10.PROPERTY_NAME_SHORTHAND,
PROPERTY_VARIABLE_DECLARATION = $__10.PROPERTY_VARIABLE_DECLARATION,
REST_PARAMETER = $__10.REST_PARAMETER,
SET_ACCESSOR = $__10.SET_ACCESSOR,
SPREAD_EXPRESSION = $__10.SPREAD_EXPRESSION,
TEMPLATE_LITERAL_PORTION = $__10.TEMPLATE_LITERAL_PORTION,
TEMPLATE_SUBSTITUTION = $__10.TEMPLATE_SUBSTITUTION,
TYPE_ALIAS_DECLARATION = $__10.TYPE_ALIAS_DECLARATION,
TYPE_ARGUMENTS = $__10.TYPE_ARGUMENTS,
TYPE_NAME = $__10.TYPE_NAME,
TYPE_PARAMETER = $__10.TYPE_PARAMETER,
TYPE_PARAMETERS = $__10.TYPE_PARAMETERS,
VARIABLE_DECLARATION_LIST = $__10.VARIABLE_DECLARATION_LIST,
VARIABLE_STATEMENT = $__10.VARIABLE_STATEMENT;
var assert = require("../util/assert.js").assert;
var ValidationError = function($__super) {
function ValidationError(tree, message) {
$__superConstructor(ValidationError).call(this);
this.tree = tree;
this.message = message;
}
return ($__createClass)(ValidationError, {}, {}, $__super);
}(Error);
var ParseTreeValidator = function($__super) {
function ParseTreeValidator() {
$__superConstructor(ParseTreeValidator).apply(this, arguments);
}
return ($__createClass)(ParseTreeValidator, {
fail_: function(tree, message) {
throw new ValidationError(tree, message);
},
check_: function(condition, tree, message) {
if (!condition) {
this.fail_(tree, message);
}
},
checkVisit_: function(condition, tree, message) {
this.check_(condition, tree, message);
this.visitAny(tree);
},
checkType_: function(type, tree, message) {
this.checkVisit_(tree.type === type, tree, message);
},
visitArgumentList: function(tree) {
for (var i = 0; i < tree.args.length; i++) {
var argument = tree.args[i];
this.checkVisit_(argument.isAssignmentOrSpread(), argument, 'assignment or spread expected');
}
},
visitArrayLiteral: function(tree) {
for (var i = 0; i < tree.elements.length; i++) {
var element = tree.elements[i];
this.checkVisit_(element === null || element.isAssignmentOrSpread(), element, 'assignment or spread expected');
}
},
visitArrayPattern: function(tree) {
for (var i = 0; i < tree.elements.length; i++) {
var element = tree.elements[i];
this.checkVisit_(element === null || element.type === BINDING_ELEMENT || element.type === ASSIGNMENT_ELEMENT || element.isLeftHandSideExpression() || element.isPattern() || element.isSpreadPatternElement(), element, 'null, sub pattern, left hand side expression or spread expected');
if (element && element.isSpreadPatternElement()) {
this.check_(i === (tree.elements.length - 1), element, 'spread in array patterns must be the last element');
}
}
},
visitBinaryExpression: function(tree) {
switch (tree.operator.type) {
case EQUAL:
case STAR_EQUAL:
case STAR_STAR_EQUAL:
case SLASH_EQUAL:
case PERCENT_EQUAL:
case PLUS_EQUAL:
case MINUS_EQUAL:
case LEFT_SHIFT_EQUAL:
case RIGHT_SHIFT_EQUAL:
case UNSIGNED_RIGHT_SHIFT_EQUAL:
case AMPERSAND_EQUAL:
case CARET_EQUAL:
case BAR_EQUAL:
this.check_(tree.left.isLeftHandSideExpression() || tree.left.isPattern(), tree.left, 'left hand side expression or pattern expected');
this.check_(tree.right.isAssignmentExpression(), tree.right, 'assignment expression expected');
break;
case AND:
case OR:
case BAR:
case CARET:
case AMPERSAND:
case EQUAL_EQUAL:
case NOT_EQUAL:
case EQUAL_EQUAL_EQUAL:
case NOT_EQUAL_EQUAL:
case OPEN_ANGLE:
case CLOSE_ANGLE:
case GREATER_EQUAL:
case LESS_EQUAL:
case INSTANCEOF:
case IN:
case LEFT_SHIFT:
case RIGHT_SHIFT:
case UNSIGNED_RIGHT_SHIFT:
case PLUS:
case MINUS:
case STAR:
case SLASH:
case PERCENT:
case STAR_STAR:
this.check_(tree.left.isAssignmentExpression(), tree.left, 'assignment expression expected');
this.check_(tree.right.isAssignmentExpression(), tree.right, 'assignment expression expected');
break;
default:
this.fail_(tree, 'unexpected binary operator');
}
this.visitAny(tree.left);
this.visitAny(tree.right);
},
visitBindingElement: function(tree) {
var binding = tree.binding;
this.checkVisit_(binding.type === BINDING_IDENTIFIER || binding.type === OBJECT_PATTERN || binding.type === ARRAY_PATTERN, binding, 'expected valid binding element');
this.visitAny(tree.initializer);
},
visitAssignmentElement: function(tree) {
var assignment = tree.assignment;
this.checkVisit_(assignment.type === OBJECT_PATTERN || assignment.type === ARRAY_PATTERN || assignment.isLeftHandSideExpression(), assignment, 'expected valid assignment element');
this.visitAny(tree.initializer);
},
visitBlock: function(tree) {
for (var i = 0; i < tree.statements.length; i++) {
var statement = tree.statements[i];
this.checkVisit_(statement.isStatementListItem(), statement, 'statement or function declaration expected');
}
},
visitCallExpression: function(tree) {
this.check_(tree.operand.isMemberExpression(), tree.operand, 'member expression expected');
if (tree.operand instanceof NewExpression) {
this.check_(tree.operand.args !== null, tree.operand, 'new args expected');
}
this.visitAny(tree.operand);
this.visitAny(tree.args);
},
visitCaseClause: function(tree) {
this.checkVisit_(tree.expression.isExpression(), tree.expression, 'expression expected');
for (var i = 0; i < tree.statements.length; i++) {
var statement = tree.statements[i];
this.checkVisit_(statement.isStatementListItem(), statement, 'statement expected');
}
},
visitCatch: function(tree) {
this.checkVisit_(tree.binding.isPattern() || tree.binding.type === BINDING_IDENTIFIER, tree.binding, 'binding identifier expected');
this.checkVisit_(tree.catchBody.type === BLOCK, tree.catchBody, 'block expected');
},
visitClassDeclaration: function(tree) {
this.visitClassShared_(tree);
},
visitClassExpression: function(tree) {
this.visitClassShared_(tree);
},
visitClassShared_: function(tree) {
if (tree.typeParameters) {
this.checkVisit_(tree.typeParameters.type === TYPE_PARAMETERS, tree.typeParameters, 'type parameters expected');
}
for (var i = 0; i < tree.elements.length; i++) {
var element = tree.elements[i];
switch (element.type) {
case GET_ACCESSOR:
case SET_ACCESSOR:
case METHOD:
case PROPERTY_VARIABLE_DECLARATION:
break;
default:
this.fail_(element, 'class element expected');
}
this.visitAny(element);
}
},
visitCommaExpression: function(tree) {
for (var i = 0; i < tree.expressions.length; i++) {
var expression = tree.expressions[i];
this.checkVisit_(expression.isExpression(), expression, 'expression expected');
}
},
visitConditionalExpression: function(tree) {
this.checkVisit_(tree.condition.isAssignmentExpression(), tree.condition, 'expression expected');
this.checkVisit_(tree.left.isAssignmentExpression(), tree.left, 'expression expected');
this.checkVisit_(tree.right.isAssignmentExpression(), tree.right, 'expression expected');
},
visitCoverFormals: function(tree) {
this.fail_(tree, 'CoverFormals should have been removed');
},
visitCoverInitializedName: function(tree) {
this.fail_(tree, 'CoverInitializedName should have been removed');
},
visitDefaultClause: function(tree) {
for (var i = 0; i < tree.statements.length; i++) {
var statement = tree.statements[i];
this.checkVisit_(statement.isStatementListItem(), statement, 'statement expected');
}
},
visitDoWhileStatement: function(tree) {
this.checkVisit_(tree.body.isStatement(), tree.body, 'statement expected');
this.checkVisit_(tree.condition.isExpression(), tree.condition, 'expression expected');
},
visitExportDeclaration: function(tree) {
var declType = tree.declaration.type;
this.checkVisit_(declType === VARIABLE_STATEMENT || declType === FUNCTION_DECLARATION || declType === CLASS_DECLARATION || declType === NAMED_EXPORT || declType === EXPORT_DEFAULT || declType === TYPE_ALIAS_DECLARATION, tree.declaration, 'expected valid export tree');
},
visitNamedExport: function(tree) {
var specifierType = tree.exportClause.type;
this.checkVisit_(specifierType === EXPORT_SPECIFIER || specifierType === EXPORT_SPECIFIER_SET || specifierType === EXPORT_STAR || specifierType === FORWARD_DEFAULT_EXPORT || specifierType === NAME_SPACE_EXPORT, tree.exportClause, 'Invalid export clause');
if (tree.moduleSpecifier) {
this.checkVisit_(tree.moduleSpecifier.type === MODULE_SPECIFIER, tree.moduleSpecifier, 'module expression expected');
}
},
visitExportSpecifierSet: function(tree) {
this.check_(tree.specifiers.length > 0, tree, 'expected at least one identifier');
for (var i = 0; i < tree.specifiers.length; i++) {
var specifier = tree.specifiers[i];
this.checkVisit_(specifier.type === EXPORT_SPECIFIER || specifier.type === IDENTIFIER_EXPRESSION, specifier, 'expected valid export specifier');
}
},
visitExpressionStatement: function(tree) {
this.checkVisit_(tree.expression.isExpression(), tree.expression, 'expression expected');
},
visitFinally: function(tree) {
this.checkVisit_(tree.block.type === BLOCK, tree.block, 'block expected');
},
visitForOfStatement: function(tree) {
this.checkVisit_(tree.initializer.isPattern() || tree.initializer.type === IDENTIFIER_EXPRESSION || tree.initializer.type === VARIABLE_DECLARATION_LIST && tree.initializer.declarations.length === 1, tree.initializer, 'for-each statement may not have more than one variable declaration');
this.checkVisit_(tree.collection.isExpression(), tree.collection, 'expression expected');
this.checkVisit_(tree.body.isStatement(), tree.body, 'statement expected');
},
visitForInStatement: function(tree) {
if (tree.initializer.type === VARIABLE_DECLARATION_LIST) {
this.checkVisit_(tree.initializer.declarations.length <= 1, tree.initializer, 'for-in statement may not have more than one variable declaration');
} else {
this.checkVisit_(tree.initializer.isPattern() || tree.initializer.isExpression(), tree.initializer, 'variable declaration, expression or ' + 'pattern expected');
}
this.checkVisit_(tree.collection.isExpression(), tree.collection, 'expression expected');
this.checkVisit_(tree.body.isStatement(), tree.body, 'statement expected');
},
visitFormalParameterList: function(tree) {
for (var i = 0; i < tree.parameters.length; i++) {
var parameter = tree.parameters[i];
assert(parameter.type === FORMAL_PARAMETER);
parameter = parameter.parameter;
switch (parameter.type) {
case BINDING_ELEMENT:
break;
case REST_PARAMETER:
this.checkVisit_(i === tree.parameters.length - 1, parameter, 'rest parameters must be the last parameter in a parameter list');
this.checkType_(BINDING_IDENTIFIER, parameter.identifier, 'binding identifier expected');
break;
default:
this.fail_(parameter, 'parameters must be identifiers or rest' + (" parameters. Found: " + parameter.type));
break;
}
this.visitAny(parameter);
}
},
visitForStatement: function(tree) {
if (tree.initializer !== null) {
this.checkVisit_(tree.initializer.isExpression() || tree.initializer.type === VARIABLE_DECLARATION_LIST, tree.initializer, 'variable declaration list or expression expected');
}
if (tree.condition !== null) {
this.checkVisit_(tree.condition.isExpression(), tree.condition, 'expression expected');
}
if (tree.increment !== null) {
this.checkVisit_(tree.increment.isExpression(), tree.increment, 'expression expected');
}
this.checkVisit_(tree.body.isStatement(), tree.body, 'statement expected');
},
visitFunctionBody: function(tree) {
for (var i = 0; i < tree.statements.length; i++) {
var statement = tree.statements[i];
this.checkVisit_(statement.isStatementListItem(), statement, 'statement expected');
}
},
visitFunctionDeclaration: function(tree) {
this.checkType_(BINDING_IDENTIFIER, tree.name, 'binding identifier expected');
this.visitFunction_(tree);
},
visitFunctionExpression: function(tree) {
if (tree.name !== null) {
this.checkType_(BINDING_IDENTIFIER, tree.name, 'binding identifier expected');
}
this.visitFunction_(tree);
},
visitFunction_: function(tree) {
this.checkType_(FORMAL_PARAMETER_LIST, tree.parameterList, 'formal parameters expected');
this.checkType_(FUNCTION_BODY, tree.body, 'function body expected');
},
visitGetAccessor: function(tree) {
this.checkPropertyName_(tree.name);
this.checkType_(FUNCTION_BODY, tree.body, 'function body expected');
},
visitIfStatement: function(tree) {
this.checkVisit_(tree.condition.isExpression(), tree.condition, 'expression expected');
this.checkVisit_(tree.ifClause.isStatement(), tree.ifClause, 'statement expected');
if (tree.elseClause !== null) {
this.checkVisit_(tree.elseClause.isStatement(), tree.elseClause, 'statement expected');
}
},
visitImportDeclaration: function(tree) {
if (tree.importClause !== null) {
this.check_(tree.importClause.type === NAME_SPACE_IMPORT || tree.importClause.type === IMPORTED_BINDING || tree.importClause.type === IMPORT_SPECIFIER_SET || tree.importClause.type === IMPORT_CLAUSE_PAIR || tree.importClause.type === IMPORT_TYPE_CLAUSE, tree.importClause, 'Invalid import clause');
}
this.checkType_(MODULE_SPECIFIER, tree.moduleSpecifier, 'module specifier expected');
},
visitImportSpecifier: function(tree) {
this.checkType_(IMPORTED_BINDING, tree.binding, 'ImportedBinding expected');
},
visitImportedBinding: function(tree) {
this.checkType_(BINDING_IDENTIFIER, tree.binding, 'binding identifier expected');
},
visitImportClausePair: function(tree) {
this.checkType_(IMPORTED_BINDING, tree.first, 'ImportedBinding expected');
this.check_(tree.second.type === NAME_SPACE_IMPORT || tree.second.type === IMPORT_SPECIFIER_SET, tree.second, 'Invalid import clause');
},
visitJsxElement: function(tree) {
this.checkType_(JSX_ELEMENT_NAME, tree.name, 'JSX Element Name expected');
for (var i = 0; i < tree.attributes.length; i++) {
var attr = tree.attributes[i];
this.checkVisit_(attr.type === JSX_ATTRIBUTE || attr.type === JSX_SPREAD_ATTRIBUTE, attr, 'JSX Attribute expected');
}
for (var i$__3 = 0; i$__3 < tree.children.length; i$__3++) {
var child = tree.children[i$__3];
this.checkVisit_(child.type === JSX_ELEMENT || child.type === JSX_PLACEHOLDER || child.type === JSX_TEXT, child, 'JSX child expected');
}
},
visitLabelledStatement: function(tree) {
this.checkVisit_(tree.statement.isStatement(), tree.statement, 'statement expected');
},
visitMemberExpression: function(tree) {
this.check_(tree.operand.isMemberExpression(), tree.operand, 'member expression expected');
if (tree.operand instanceof NewExpression) {
this.check_(tree.operand.args !== null, tree.operand, 'new args expected');
}
this.visitAny(tree.operand);
},
visitMemberLookupExpression: function(tree) {
this.check_(tree.operand.isMemberExpression(), tree.operand, 'member expression expected');
if (tree.operand instanceof NewExpression) {
this.check_(tree.operand.args !== null, tree.operand, 'new args expected');
}
this.visitAny(tree.operand);
},
visitSyntaxErrorTree: function(tree) {
this.fail_(tree, ("parse tree contains SyntaxError: " + tree.message));
},
visitModuleSpecifier: function(tree) {
this.check_(tree.token.type === STRING, tree, 'string or identifier expected');
},
visitNewExpression: function(tree) {
this.checkVisit_(tree.operand.isMemberExpression(), tree.operand, 'member expression expected');
this.visitAny(tree.args);
},
visitObjectLiteral: function(tree) {
for (var i = 0; i < tree.propertyNameAndValues.length; i++) {
var propertyNameAndValue = tree.propertyNameAndValues[i];
switch (propertyNameAndValue.type) {
case GET_ACCESSOR:
case SET_ACCESSOR:
case METHOD:
this.check_(!propertyNameAndValue.isStatic, propertyNameAndValue, 'static is not allowed in object literal expression');
break;
case PROPERTY_NAME_ASSIGNMENT:
case PROPERTY_NAME_SHORTHAND:
case SPREAD_EXPRESSION:
break;
default:
this.fail_(propertyNameAndValue, 'accessor, property name ' + 'assignment or property method assigment expected');
}
this.visitAny(propertyNameAndValue);
}
},
visitObjectPattern: function(tree) {
for (var i = 0; i < tree.fields.length; i++) {
var field = tree.fields[i];
this.checkVisit_(field.type === OBJECT_PATTERN_FIELD || field.type === ASSIGNMENT_ELEMENT || field.type === BINDING_ELEMENT, field, 'object pattern field expected');
}
},
visitObjectPatternField: function(tree) {
this.checkPropertyName_(tree.name);
this.checkVisit_(tree.element.type === ASSIGNMENT_ELEMENT || tree.element.type === BINDING_ELEMENT || tree.element.isPattern() || tree.element.isLeftHandSideExpression(), tree.element, 'binding element expected');
},
visitParenExpression: function(tree) {
if (tree.expression.isPattern()) {
this.visitAny(tree.expression);
} else {
this.checkVisit_(tree.expression.isExpression(), tree.expression, 'expression expected');
}
},
visitPostfixExpression: function(tree) {
this.checkVisit_(tree.operand.isAssignmentExpression(), tree.operand, 'assignment expression expected');
},
visitPredefinedType: function(tree) {},
visitScript: function(tree) {
for (var i = 0; i < tree.scriptItemList.length; i++) {
var scriptItemList = tree.scriptItemList[i];
this.checkVisit_(scriptItemList.isScriptElement(), scriptItemList, 'global script item expected');
}
},
checkPropertyName_: function(tree) {
this.checkVisit_(tree.type === LITERAL_PROPERTY_NAME || tree.type === COMPUTED_PROPERTY_NAME, tree, 'property name expected');
},
visitPropertyNameAssignment: function(tree) {
this.checkPropertyName_(tree.name);
this.checkVisit_(tree.value.isAssignmentExpression(), tree.value, 'assignment expression expected');
},
visitPropertyNameShorthand: function(tree) {
this.check_(tree.name.type === IDENTIFIER || tree.name.type === YIELD || tree.name.isStrictKeyword(), tree, 'identifier token expected');
},
visitLiteralPropertyName: function(tree) {
var type = tree.literalToken.type;
this.check_(tree.literalToken.isKeyword() || type === IDENTIFIER || type === NUMBER || type === STRING, tree, 'Unexpected token in literal property name');
},
visitTemplateLiteralExpression: function(tree) {
if (tree.operand) {
this.checkVisit_(tree.operand.isMemberExpression(), tree.operand, 'member or call expression expected');
}
for (var i = 0; i < tree.elements.length; i++) {
var element = tree.elements[i];
if (i % 2) {
this.checkType_(TEMPLATE_SUBSTITUTION, element, 'Template literal substitution expected');
} else {
this.checkType_(TEMPLATE_LITERAL_PORTION, element, 'Template literal portion expected');
}
}
},
visitReturnStatement: function(tree) {
if (tree.expression !== null) {
this.checkVisit_(tree.expression.isExpression(), tree.expression, 'expression expected');
}
},
visitSetAccessor: function(tree) {
this.checkPropertyName_(tree.name);
this.checkType_(FUNCTION_BODY, tree.body, 'function body expected');
},
visitSpreadExpression: function(tree) {
this.checkVisit_(tree.expression.isAssignmentExpression(), tree.expression, 'assignment expression expected');
},
visitStateMachine: function(tree) {
this.fail_(tree, 'State machines are never valid outside of the ' + 'GeneratorTransformer pass.');
},
visitSwitchStatement: function(tree) {
this.checkVisit_(tree.expression.isExpression(), tree.expression, 'expression expected');
var defaultCount = 0;
for (var i = 0; i < tree.caseClauses.length; i++) {
var caseClause = tree.caseClauses[i];
if (caseClause.type === DEFAULT_CLAUSE) {
++defaultCount;
this.checkVisit_(defaultCount <= 1, caseClause, 'no more than one default clause allowed');
} else {
this.checkType_(CASE_CLAUSE, caseClause, 'case or default clause expected');
}
}
},
visitThrowStatement: function(tree) {
if (tree.value === null) {
return;
}
this.checkVisit_(tree.value.isExpression(), tree.value, 'expression expected');
},
visitTryStatement: function(tree) {
this.checkType_(BLOCK, tree.body, 'block expected');
if (tree.catchBlock !== null) {
this.checkType_(CATCH, tree.catchBlock, 'catch block expected');
}
if (tree.finallyBlock !== null) {
this.checkType_(FINALLY, tree.finallyBlock, 'finally block expected');
}
if (tree.catchBlock === null && tree.finallyBlock === null) {
this.fail_(tree, 'either catch or finally must be present');
}
},
visitTypeArguments: function(tree) {
var args = tree.args;
for (var i = 0; i < args.length; i++) {
this.checkVisit_(args[i].isType(), args[i], 'Type arguments must be type expressions');
}
},
visitTypeName: function(tree) {
this.checkVisit_(tree.moduleName === null || tree.moduleName.type === TYPE_NAME, tree.moduleName, 'moduleName must be null or a TypeName');
this.check_(tree.name.type === IDENTIFIER, tree, 'name must be an identifier');
},
visitTypeReference: function(tree) {
this.checkType_(TYPE_NAME, tree.typeName, 'typeName must be a TypeName');
this.checkType_(TYPE_ARGUMENTS, tree.args, 'args must be a TypeArguments');
},
visitTypeParameters: function(tree) {
var parameters = tree.parameters;
for (var i = 0; i < parameters.length; i++) {
this.checkType_(TYPE_PARAMETER, parameters[i], 'Type parameters must all be type parameters');
}
},
visitTypeParameter: function(tree) {
this.check_(tree.identifierToken.type === IDENTIFIER, tree, 'Type parameter must be an identifier token');
if (tree.extendsType) {
this.checkVisit_(tree.extendsType.isType(), tree.extendsType, 'extends type must be a type expression');
}
},
visitUnaryExpression: function(tree) {
this.checkVisit_(tree.operand.isAssignmentExpression(), tree.operand, 'assignment expression expected');
},
visitVariableDeclaration: function(tree) {
this.checkVisit_(tree.lvalue.isPattern() || tree.lvalue.type === BINDING_IDENTIFIER, tree.lvalue, 'binding identifier expected, found: ' + tree.lvalue.type);
if (tree.initializer !== null) {
this.checkVisit_(tree.initializer.isAssignmentExpression(), tree.initializer, 'assignment expression expected');
}
},
visitWhileStatement: function(tree) {
this.checkVisit_(tree.condition.isExpression(), tree.condition, 'expression expected');
this.checkVisit_(tree.body.isStatement(), tree.body, 'statement expected');
},
visitWithStatement: function(tree) {
this.checkVisit_(tree.expression.isExpression(), tree.expression, 'expression expected');
this.checkVisit_(tree.body.isStatement(), tree.body, 'statement expected');
},
visitYieldExpression: function(tree) {
if (tree.expression !== null) {
this.checkVisit_(tree.expression.isExpression(), tree.expression, 'expression expected');
}
}
}, {}, $__super);
}(ParseTreeVisitor);
ParseTreeValidator.validate = function(tree) {
var validator = new ParseTreeValidator();
try {
validator.visitAny(tree);
} catch (e) {
if (!(e instanceof ValidationError)) {
throw e;
}
var location = null;
if (e.tree !== null) {
location = e.tree.location;
}
if (location === null) {
location = tree.location;
}
var locationString = location !== null ? location.start.toString() : '(unknown)';
throw new Error(("Parse tree validation failure '" + e.message + "' at " + locationString + ":") + ("\n\n" + TreeWriter.write(tree) + "\n"));
}
};