add validation to node builders

This commit is contained in:
Sebastian McKenzie 2015-09-15 06:26:17 +01:00
parent c44fd54621
commit cfec910a17
8 changed files with 920 additions and 169 deletions

View File

@ -1,8 +1,11 @@
import define, { assertValueType, assertNodeType } from "./index";
import * as t from "../index";
import define, { assertValueType, assertNodeType, assertEach, chain, assertOneOf } from "./index";
define("ArrayExpression", {
fields: {
elements: { validate: assertValueType("array") }
elements: {
validate: assertValueType("array")
}
},
visitor: ["elements"],
aliases: ["Expression"]
@ -11,9 +14,15 @@ define("ArrayExpression", {
define("AssignmentExpression", {
fields: {
elements: {
operator: { validate: assertValueType("string") },
left: { validate: assertNodeType("LVal") },
right: { validate: assertNodeType("Expression") }
operator: {
validate: assertValueType("string")
},
left: {
validate: assertNodeType("LVal")
},
right: {
validate: assertNodeType("Expression")
}
}
},
builder: ["operator", "left", "right"],
@ -24,53 +33,104 @@ define("AssignmentExpression", {
define("BinaryExpression", {
builder: ["operator", "left", "right"],
fields: {
operator: { validate: assertValueType("string") },
left: { validate: assertNodeType("Expression") },
right: { validate: assertNodeType("Expression") }
operator: {
validate: assertValueType("string")
},
left: {
validate: assertNodeType("Expression")
},
right: {
validate: assertNodeType("Expression")
}
},
visitor: ["left", "right"],
aliases: ["Binary", "Expression"]
});
define("BlockStatement", {
visitor: ["body"],
define("Directive", {
fields: {
body: { validate: assertValueType("array") }
value: {
validate: assertValueType("string")
}
}
});
define("BlockStatement", {
builder: ["body", "directives"],
visitor: ["directives", "body"],
fields: {
directives: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("Directive"))),
default: []
},
body: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("Statement")))
}
},
aliases: ["Scopable", "BlockParent", "Block", "Statement"]
});
define("BreakStatement", {
visitor: ["label"],
fields: {
label: {
validate: assertNodeType("Identifier"),
optional: true
}
},
aliases: ["Statement", "Terminatorless", "CompletionStatement"]
});
define("CallExpression", {
visitor: ["callee", "arguments"],
fields: {
callee: { validate: assertNodeType("Expression") },
arguments: { validate: assertValueType("array") }
callee: {
validate: assertNodeType("Expression")
},
arguments: {
validate: assertValueType("array")
}
},
aliases: ["Expression"]
});
define("CatchClause", {
visitor: ["param", "body"],
fields: {
param: {
validate: assertNodeType("Identifier")
},
body: {
validate: assertNodeType("BlockStatement")
}
},
aliases: ["Scopable"]
});
define("ConditionalExpression", {
visitor: ["test", "consequent", "alternate"],
fields: {
test: { validate: assertNodeType("Expression") },
consequent: { validate: assertNodeType("Expression") },
alternate: { validate: assertNodeType("Expression") }
test: {
validate: assertNodeType("Expression")
},
consequent: {
validate: assertNodeType("Expression")
},
alternate: {
validate: assertNodeType("Expression")
}
},
aliases: ["Expression"]
});
define("ContinueStatement", {
visitor: ["label"],
fields: {
label: {
validate: assertNodeType("Identifier"),
optional: true
}
},
aliases: ["Statement", "Terminatorless", "CompletionStatement"]
});
@ -79,7 +139,15 @@ define("DebuggerStatement", {
});
define("DoWhileStatement", {
visitor: ["body", "test"],
visitor: ["test", "body"],
fields: {
test: {
validate: assertNodeType("Expression")
},
body: {
validate: assertNodeType("BlockStatement")
}
},
aliases: ["Statement", "BlockParent", "Loop", "While", "Scopable"]
});
@ -90,7 +158,9 @@ define("EmptyStatement", {
define("ExpressionStatement", {
visitor: ["expression"],
fields: {
expression: { validate: assertNodeType("Expression") }
expression: {
validate: assertNodeType("Expression")
}
},
aliases: ["Statement"]
});
@ -99,27 +169,60 @@ define("File", {
builder: ["program", "comments", "tokens"],
visitor: ["program"],
fields: {
program: { validate: assertNodeType("Program") }
program: {
validate: assertNodeType("Program")
}
}
});
define("ForInStatement", {
visitor: ["left", "right", "body"],
aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement"]
aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement"],
fields: {
left: {
validate: assertNodeType("VariableDeclaration", "LVal")
},
right: {
validate: assertNodeType("Expression")
},
body: {
validate: assertNodeType("Statement")
}
}
});
define("ForStatement", {
visitor: ["init", "test", "update", "body"],
aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop"]
aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop"],
fields: {
init: {
validate: assertNodeType("VariableDeclaration", "Expression")
},
test: {
validate: assertNodeType("Expression")
},
update: {
validate: assertNodeType("Expression")
},
body: {
validate: assertNodeType("Statement")
}
}
});
define("FunctionDeclaration", {
builder: ["id", "params", "body", "generator", "async"],
visitor: ["id", "params", "body", "returnType", "typeParameters"],
fields: {
id: { validate: assertNodeType("Identifier") },
params: { validate: assertValueType("array") },
body: { validate: assertNodeType("BlockStatement") },
id: {
validate: assertNodeType("Identifier")
},
params: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("LVal")))
},
body: {
validate: assertNodeType("BlockStatement")
},
generator: {
default: false,
validate: assertValueType("boolean")
@ -129,14 +232,22 @@ define("FunctionDeclaration", {
validate: assertValueType("boolean")
}
},
aliases: ["Scopable", "Function", "Func", "BlockParent", "FunctionParent", "Statement", "Pure", "Declaration"]
aliases: ["Scopable", "Function", "BlockParent", "FunctionParent", "Statement", "Pure", "Declaration"]
});
define("FunctionExpression", {
builder: ["id", "params", "body", "generator", "async"],
fields: {
params: { validate: assertValueType("array") },
body: { validate: assertNodeType("BlockStatement") },
id: {
validate: assertNodeType("Identifier"),
optional: true
},
params: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("LVal")))
},
body: {
validate: assertNodeType("BlockStatement")
},
generator: {
default: false,
validate: assertValueType("boolean")
@ -147,29 +258,61 @@ define("FunctionExpression", {
}
},
visitor: ["id", "params", "body", "returnType", "typeParameters"],
aliases: ["Scopable", "Function", "Func", "BlockParent", "FunctionParent", "Expression", "Pure"]
aliases: ["Scopable", "Function", "BlockParent", "FunctionParent", "Expression", "Pure"]
});
define("Identifier", {
builder: ["name"],
visitor: ["typeAnnotation"],
aliases: ["Expression", "LVal"]
aliases: ["Expression", "LVal"],
fields: {
name: {
validate(node, key, val) {
if (!t.isValidIdentifier(val)) {
// todo
}
}
}
}
});
define("IfStatement", {
visitor: ["test", "consequent", "alternate"],
aliases: ["Statement"]
aliases: ["Statement"],
fields: {
test: {
validate: assertNodeType("Expression")
},
consequent: {
optional: true,
validate: assertNodeType("Statement")
},
alternate: {
optional: true,
validate: assertNodeType("Statement")
}
}
});
define("LabeledStatement", {
visitor: ["label", "body"],
aliases: ["Statement"]
aliases: ["Statement"],
fields: {
label: {
validate: assertNodeType("Identifier")
},
body: {
validate: assertNodeType("Statement")
}
}
});
define("StringLiteral", {
builder: ["value"],
fields: {
value: { validate: assertValueType("string") }
value: {
validate: assertValueType("string")
}
},
aliases: ["Expression", "Pure", "Literal", "Immutable"]
});
@ -177,7 +320,9 @@ define("StringLiteral", {
define("NumberLiteral", {
builder: ["value"],
fields: {
value: { validate: assertValueType("number") }
value: {
validate: assertValueType("number")
}
},
aliases: ["Expression", "Pure", "Literal", "Immutable"]
});
@ -189,73 +334,161 @@ define("NullLiteral", {
define("BooleanLiteral", {
builder: ["value"],
fields: {
value: { validate: assertValueType("boolean") }
value: {
validate: assertValueType("boolean")
}
},
aliases: ["Expression", "Pure", "Literal", "Immutable"]
});
define("RegexLiteral", {
builder: ["pattern", "flags"],
aliases: ["Expression", "Literal"],
fields: {
pattern: { validate: assertValueType("string") },
pattern: {
validate: assertValueType("string")
},
flags: {
validate: assertValueType("string"),
default: ""
}
},
aliases: ["Expression", "Literal"]
}
});
define("LogicalExpression", {
builder: ["operator", "left", "right"],
visitor: ["left", "right"],
aliases: ["Binary", "Expression"]
aliases: ["Binary", "Expression"],
fields: {
operator: {
// todo
},
left: {
validate: assertNodeType("Expression")
},
right: {
validate: assertNodeType("Expression")
}
}
});
define("MemberExpression", {
builder: ["object", "property", "computed"],
fields: {
computed: { default: false }
},
visitor: ["object", "property"],
aliases: ["Expression", "LVal"]
aliases: ["Expression", "LVal"],
fields: {
object: {
validate: assertNodeType("Expression")
},
property: {
validate(node, key, val) {
var expectedType = node.computed ? "Expression" : "Identifier";
assertNodeType(expectedType)(node, key, val);
}
},
computed: {
default: false
}
}
});
define("NewExpression", {
visitor: ["callee", "arguments"],
aliases: ["Expression"]
aliases: ["Expression"],
fields: {
callee: {
validate: assertNodeType("Expression")
},
arguments: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("Expression")))
}
}
});
define("ObjectExpression", {
visitor: ["properties"],
aliases: ["Expression"]
aliases: ["Expression"],
fields: {
properties: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("Property", "SpreadProperty")))
}
}
});
define("Program", {
visitor: ["body"],
visitor: ["directives", "body"],
builder: ["body", "directives"],
fields: {
body: { validate: assertValueType("array") }
directives: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("Directive"))),
default: []
},
body: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("Statement")))
}
},
aliases: ["Scopable", "BlockParent", "Block", "FunctionParent"]
});
define("Property", {
builder: ["kind", "key", "value", "computed"],
builder: ["kind", "key", "value", "computed", "method", "shorthand"],
fields: {
kind: { default: "init" },
computed: { default: false }
kind: {
validate: chain(assertValueType("string"), assertOneOf("init", "get", "set")),
default: "init"
},
computed: {
validate: assertValueType("boolean"),
default: false
},
key: {
validate(node, key, val) {
var expectedTypes = node.computed ? "Expression" : ["Identifier", "Literal"];
assertNodeType(...expectedTypes)(node, key, val);
}
},
value: {
validate(node, key, val) {
var expectedType = "Expression";
if (node.kind === "get" || node.kind === "set" || node.method) {
expectedType = "FunctionExpression";
}
assertNodeType(expectedType)(node, key, val);
}
},
method: {
validate: assertValueType("boolean"),
default: false
},
shorthand: {
validate: assertValueType("boolean"),
default: false
},
decorators: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("Decorator")))
}
},
visitor: ["key", "value", "decorators"],
aliases: ["UserWhitespacable"]
});
define("RestElement", {
visitor: ["argument", "typeAnnotation"]
visitor: ["argument", "typeAnnotation"],
fields: {
argument: {
validate: assertNodeType("LVal")
}
}
});
define("ReturnStatement", {
visitor: ["argument"],
aliases: ["Statement", "Terminatorless", "CompletionStatement"]
aliases: ["Statement", "Terminatorless", "CompletionStatement"],
fields: {
argument: {
validate: assertNodeType("Expression")
}
}
});
define("SequenceExpression", {
@ -267,12 +500,18 @@ define("SequenceExpression", {
});
define("SwitchCase", {
visitor: ["test", "consequent"]
visitor: ["test", "consequent"],
fields: {
// todo
}
});
define("SwitchStatement", {
visitor: ["discriminant", "cases"],
aliases: ["Statement", "BlockParent", "Scopable"]
aliases: ["Statement", "BlockParent", "Scopable"],
fields: {
// todo
}
});
define("ThisExpression", {
@ -281,19 +520,45 @@ define("ThisExpression", {
define("ThrowStatement", {
visitor: ["argument"],
aliases: ["Statement", "Terminatorless", "CompletionStatement"]
aliases: ["Statement", "Terminatorless", "CompletionStatement"],
fields: {
argument: {
validate: assertNodeType("Expression")
}
}
});
// todo: at least handler or finalizer should be set to be valid
define("TryStatement", {
builder: ["block", "handler", "finalizer"],
visitor: ["block", "handlers", "handler", "guardedHandlers", "finalizer"],
aliases: ["Statement"]
visitor: ["block", "handler", "finalizer"],
aliases: ["Statement"],
fields: {
body: {
validate: assertNodeType("BlockStatement")
},
handler: {
optional: true,
handler: assertNodeType("BlockStatement")
},
finalizer: {
optional: true,
validate: assertNodeType("BlockStatement")
}
}
});
define("UnaryExpression", {
builder: ["operator", "argument", "prefix"],
fields: {
prefix: { default: false }
prefix: {
default: false
},
argument: {
validate: assertNodeType("Expression")
},
operator: {
// todo
}
},
visitor: ["argument"],
aliases: ["UnaryLike", "Expression"]
@ -302,7 +567,15 @@ define("UnaryExpression", {
define("UpdateExpression", {
builder: ["operator", "argument", "prefix"],
fields: {
prefix: { default: false }
prefix: {
default: false
},
argument: {
validate: assertNodeType("Expression")
},
operator: {
// todo
}
},
visitor: ["argument"],
aliases: ["Expression"]
@ -311,19 +584,52 @@ define("UpdateExpression", {
define("VariableDeclaration", {
builder: ["kind", "declarations"],
visitor: ["declarations"],
aliases: ["Statement", "Declaration"]
aliases: ["Statement", "Declaration"],
fields: {
kind: {
validate: chain(assertValueType("string"), assertOneOf("var", "let", "const"))
},
declarations: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("VariableDeclarator")))
}
}
});
define("VariableDeclarator", {
visitor: ["id", "init"]
visitor: ["id", "init"],
fields: {
id: {
validate: assertNodeType("LVal")
},
init: {
optional: true,
validate: assertNodeType("Expression")
}
}
});
define("WhileStatement", {
visitor: ["test", "body"],
aliases: ["Statement", "BlockParent", "Loop", "While", "Scopable"]
aliases: ["Statement", "BlockParent", "Loop", "While", "Scopable"],
fields: {
test: {
validate: assertNodeType("Expression")
},
body: {
validate: assertNodeType("BlockStatement", "Statement")
}
}
});
define("WithStatement", {
visitor: ["object", "body"],
aliases: ["Statement"]
aliases: ["Statement"],
fields: {
object: {
object: assertNodeType("Expression")
},
body: {
validate: assertNodeType("BlockStatement")
}
}
});

View File

@ -1,113 +1,248 @@
import define from "./index";
import define, { assertNodeType, assertValueType, chain, assertEach, assertOneOf } from "./index";
define("AssignmentPattern", {
visitor: ["left", "right"],
aliases: ["Pattern", "LVal"]
aliases: ["Pattern", "LVal"],
fields: {
left: {
validate: assertNodeType("Identifier")
},
right: {
validate: assertNodeType("Expression")
}
}
});
define("ArrayPattern", {
visitor: ["elements", "typeAnnotation"],
aliases: ["Pattern", "LVal"]
aliases: ["Pattern", "LVal"],
fields: {
elements: {
validate: chain(assertValueType("array"), assertEach(assertValueType("Expression")))
}
}
});
define("ArrowFunctionExpression", {
builder: ["params", "body", "async"],
visitor: ["params", "body", "returnType"],
aliases: ["Scopable", "Function", "Func", "BlockParent", "FunctionParent", "Expression", "Pure"]
aliases: ["Scopable", "Function", "BlockParent", "FunctionParent", "Expression", "Pure"],
fields: {
params: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("LVal")))
},
body: {
validate: assertNodeType("BlockStatement", "Expression")
},
async: {
validate: assertValueType("boolean"),
default: false
}
}
});
define("ClassBody", {
visitor: ["body"]
visitor: ["body"],
fields: {
body: {
validate: chain(assertValueType("array"), assertEach(assertValueType("MethodDefinition", "ClassProperty")))
}
}
});
define("ClassDeclaration", {
builder: ["id", "superClass", "body", "decorators"],
visitor: ["id", "body", "superClass", "typeParameters", "superTypeParameters", "implements", "decorators"],
aliases: ["Scopable", "Class", "Statement", "Declaration"]
aliases: ["Scopable", "Class", "Statement", "Declaration"],
fields: {
id: {
validate: assertNodeType("Identifier")
},
body: {
validate: assertNodeType("ClassBody")
},
superClass: {
optional: true,
validate: assertNodeType("Expression")
},
decorators: {
validate: chain(assertValueType("array"), assertEach(assertValueType("Decorator")))
}
}
});
define("ClassExpression", {
builder: ["id", "superClass", "body", "decorators"],
visitor: ["id", "body", "superClass", "typeParameters", "superTypeParameters", "implements", "decorators"],
aliases: ["Scopable", "Class", "Expression"]
aliases: ["Scopable", "Class", "Expression"],
fields: {
id: {
optional: true,
validate: assertNodeType("Identifier")
},
body: {
validate: assertNodeType("ClassBody")
},
superClass: {
optional: true,
validate: assertNodeType("Expression")
},
decorators: {
validate: chain(assertValueType("array"), assertEach(assertValueType("Decorator")))
}
}
});
define("ExportAllDeclaration", {
visitor: ["source", "exported"],
aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"]
aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"],
fields: {
// todo
}
});
define("ExportDefaultDeclaration", {
visitor: ["declaration"],
aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"]
aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"],
fields: {
// todo
}
});
define("ExportNamedDeclaration", {
visitor: ["declaration", "specifiers", "source"],
aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"]
});
define("ExportDefaultSpecifier", {
visitor: ["exported"],
aliases: ["ModuleSpecifier"]
});
define("ExportNamespaceSpecifier", {
visitor: ["exported"],
aliases: ["ModuleSpecifier"]
aliases: ["Statement", "Declaration", "ModuleDeclaration", "ExportDeclaration"],
fields: {
// todo
}
});
define("ExportSpecifier", {
visitor: ["local", "exported"],
aliases: ["ModuleSpecifier"]
aliases: ["ModuleSpecifier"],
fields: {
local: {
validate: assertNodeType("Identifier")
},
imported: {
validate: assertNodeType("Identifier")
}
}
});
define("ForOfStatement", {
visitor: ["left", "right", "body"],
aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement"]
aliases: ["Scopable", "Statement", "For", "BlockParent", "Loop", "ForXStatement"],
fields: {
left: {
validate: assertNodeType("VariableDeclaration", "LVal")
},
right: {
validate: assertNodeType("Expression")
},
body: {
validate: assertNodeType("Statement")
}
}
});
define("ImportDeclaration", {
visitor: ["specifiers", "source"],
aliases: ["Statement", "Declaration", "ModuleDeclaration"]
aliases: ["Statement", "Declaration", "ModuleDeclaration"],
fields: {
specifiers: {
// todo
},
source: {
validate: assertNodeType("StringLiteral")
}
}
});
define("ImportDefaultSpecifier", {
visitor: ["local"],
aliases: ["ModuleSpecifier"]
aliases: ["ModuleSpecifier"],
fields: {
local: {
validate: assertNodeType("Identifier")
}
}
});
define("ImportNamespaceSpecifier", {
visitor: ["local"],
aliases: ["ModuleSpecifier"]
aliases: ["ModuleSpecifier"],
fields: {
local: {
validate: assertNodeType("Identifier")
}
}
});
define("ImportSpecifier", {
visitor: ["local", "imported"],
aliases: ["ModuleSpecifier"]
aliases: ["ModuleSpecifier"],
fields: {
local: {
validate: assertNodeType("Identifier")
},
imported: {
validate: assertNodeType("Identifier")
}
}
});
define("MetaProperty", {
visitor: ["meta", "property"],
aliases: ["Expression"]
aliases: ["Expression"],
fields: {
// todo: limit to new.target
meta: {
validate: assertValueType("string")
},
property: {
validate: assertValueType("string")
}
}
});
define("MethodDefinition", {
builder: ["key", "value", "kind", "computed", "static"],
visitor: ["key", "value", "decorators"],
fields: {
kind: { default: "method" },
computed: { default: false },
static: { default: false }
},
visitor: ["key", "value", "decorators"]
kind: {
validate: chain(assertValueType("string"), assertOneOf("get", "set", "method", "constructor")),
default: "method"
},
computed: {
default: false,
validate: assertValueType("boolean")
},
static: {
default: false,
validate: assertValueType("boolean")
}
}
});
define("ObjectPattern", {
visitor: ["properties", "typeAnnotation"],
aliases: ["Pattern", "LVal"]
aliases: ["Pattern", "LVal"],
fields: {
properties: {
validate: chain(assertValueType("array"), assertEach(assertValueType("RestProperty", "Property")))
}
}
});
define("SpreadElement", {
visitor: ["argument"],
aliases: ["UnaryLike"]
aliases: ["UnaryLike"],
fields: {
argument: {
validate: assertNodeType("Expression")
}
}
});
define("Super", {
@ -116,18 +251,50 @@ define("Super", {
define("TaggedTemplateExpression", {
visitor: ["tag", "quasi"],
aliases: ["Expression"]
aliases: ["Expression"],
fields: {
tag: {
validate: assertNodeType("Expression")
},
quasi: {
validate: assertNodeType("TemplateLiteral")
}
}
});
define("TemplateElement");
define("TemplateElement", {
builder: ["value", "tail"],
fields: {
value: {
// todo: flatten `raw` into main node
},
tail: {
validate: assertValueType("boolean"),
default: false
}
}
});
define("TemplateLiteral", {
visitor: ["quasis", "expressions"],
aliases: ["Expression", "Literal"]
aliases: ["Expression", "Literal"],
fields: {
// todo
}
});
define("YieldExpression", {
builder: ["argument", "delegate"],
visitor: ["argument"],
aliases: ["Expression", "Terminatorless"]
aliases: ["Expression", "Terminatorless"],
fields: {
delegate: {
validate: assertValueType("boolean"),
default: false
},
argument: {
optional: true,
validate: assertNodeType("Expression"),
}
}
});

View File

@ -1,34 +1,97 @@
import define from "./index";
import define, { assertNodeType, assertValueType } from "./index";
define("AwaitExpression", {
builder: ["argument", "all"],
visitor: ["argument"],
aliases: ["Expression", "Terminatorless"]
aliases: ["Expression", "Terminatorless"],
fields: {
all: {
validate: assertValueType("boolean"),
default: false
},
argument: {
validate: assertNodeType("Expression"),
}
}
});
define("BindExpression", {
visitor: ["object", "callee"]
visitor: ["object", "callee"],
fields: {
// todo
}
});
define("ComprehensionBlock", {
visitor: ["left", "right"]
visitor: ["left", "right"],
fields: {
// todo
}
});
define("ComprehensionExpression", {
visitor: ["filter", "blocks", "body"],
aliases: ["Expression", "Scopable"]
aliases: ["Expression", "Scopable"],
fields: {
// todo
}
});
define("Decorator", {
visitor: ["expression"]
visitor: ["expression"],
fields: {
expression: {
validate: assertNodeType("Expression")
}
}
});
define("DoExpression", {
visitor: ["body"],
aliases: ["Expression"]
aliases: ["Expression"],
fields: {
body: {
validate: assertNodeType("BlockStatement")
}
}
});
define("ExportDefaultSpecifier", {
visitor: ["exported"],
aliases: ["ModuleSpecifier"],
fields: {
exported: {
validate: assertNodeType("Identifier")
}
}
});
define("ExportNamespaceSpecifier", {
visitor: ["exported"],
aliases: ["ModuleSpecifier"],
fields: {
exported: {
validate: assertNodeType("Identifier")
}
}
});
define("RestProperty", {
visitor: ["argument"],
aliases: ["UnaryLike"],
fields: {
argument: {
validate: assertNodeType("LVal")
}
}
});
define("SpreadProperty", {
visitor: ["argument"],
aliases: ["UnaryLike"]
aliases: ["UnaryLike"],
fields: {
argument: {
validate: assertNodeType("Expression")
}
}
});

View File

@ -1,80 +1,128 @@
import define from "./index";
define("AnyTypeAnnotation", {
aliases: ["Flow", "FlowBaseAnnotation"]
aliases: ["Flow", "FlowBaseAnnotation"],
fields: {
// todo
}
});
define("ArrayTypeAnnotation", {
visitor: ["elementType"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("BooleanTypeAnnotation", {
aliases: ["Flow", "FlowBaseAnnotation"]
aliases: ["Flow", "FlowBaseAnnotation"],
fields: {
// todo
}
});
define("BooleanLiteralTypeAnnotation", {
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("ClassImplements", {
visitor: ["id", "typeParameters"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("ClassProperty", {
visitor: ["key", "value", "typeAnnotation", "decorators"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("DeclareClass", {
visitor: ["id", "typeParameters", "extends", "body"],
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"]
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"],
fields: {
// todo
}
});
define("DeclareFunction", {
visitor: ["id"],
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"]
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"],
fields: {
// todo
}
});
define("DeclareModule", {
visitor: ["id", "body"],
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"]
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"],
fields: {
// todo
}
});
define("DeclareVariable", {
visitor: ["id"],
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"]
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"],
fields: {
// todo
}
});
define("FunctionTypeAnnotation", {
visitor: ["typeParameters", "params", "rest", "returnType"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("FunctionTypeParam", {
visitor: ["name", "typeAnnotation"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("GenericTypeAnnotation", {
visitor: ["id", "typeParameters"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("InterfaceExtends", {
visitor: ["id", "typeParameters"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("InterfaceDeclaration", {
visitor: ["id", "typeParameters", "extends", "body"],
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"]
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"],
fields: {
// todo
}
});
define("IntersectionTypeAnnotation", {
visitor: ["types"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("MixedTypeAnnotation", {
@ -83,90 +131,147 @@ define("MixedTypeAnnotation", {
define("NullableTypeAnnotation", {
visitor: ["typeAnnotation"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("NumberLiteralTypeAnnotation", {
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("NumberTypeAnnotation", {
aliases: ["Flow", "FlowBaseAnnotation"]
aliases: ["Flow", "FlowBaseAnnotation"],
fields: {
// todo
}
});
define("StringLiteralTypeAnnotation", {
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("StringTypeAnnotation", {
aliases: ["Flow", "FlowBaseAnnotation"]
aliases: ["Flow", "FlowBaseAnnotation"],
fields: {
// todo
}
});
define("TupleTypeAnnotation", {
visitor: ["types"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("TypeofTypeAnnotation", {
visitor: ["argument"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("TypeAlias", {
visitor: ["id", "typeParameters", "right"],
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"]
aliases: ["Flow", "FlowDeclaration", "Statement", "Declaration"],
fields: {
// todo
}
});
define("TypeAnnotation", {
visitor: ["typeAnnotation"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("TypeCastExpression", {
visitor: ["expression", "typeAnnotation"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("TypeParameterDeclaration", {
visitor: ["params"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("TypeParameterInstantiation", {
visitor: ["params"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("ObjectTypeAnnotation", {
visitor: ["properties", "indexers", "callProperties"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("ObjectTypeCallProperty", {
visitor: ["value"],
aliases: ["Flow", "UserWhitespacable"]
aliases: ["Flow", "UserWhitespacable"],
fields: {
// todo
}
});
define("ObjectTypeIndexer", {
visitor: ["id", "key", "value"],
aliases: ["Flow", "UserWhitespacable"]
aliases: ["Flow", "UserWhitespacable"],
fields: {
// todo
}
});
define("ObjectTypeProperty", {
visitor: ["key", "value"],
aliases: ["Flow", "UserWhitespacable"]
aliases: ["Flow", "UserWhitespacable"],
fields: {
// todo
}
});
define("QualifiedTypeIdentifier", {
visitor: ["id", "qualification"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("UnionTypeAnnotation", {
visitor: ["types"],
aliases: ["Flow"]
aliases: ["Flow"],
fields: {
// todo
}
});
define("VoidTypeAnnotation", {
aliases: ["Flow", "FlowBaseAnnotation"]
aliases: ["Flow", "FlowBaseAnnotation"],
fields: {
// todo
}
});

View File

@ -5,38 +5,76 @@ export var ALIAS_KEYS = {};
export var NODE_FIELDS = {};
export var BUILDER_KEYS = {};
function getType(val) {
if (Array.isArray(val)) {
return "array";
} else if (val === null) {
return "null";
} else if (val === undefined) {
return "undefined";
} else {
return typeof val;
}
}
export function assertContains(vals) {
return function (val, key) {
if (vals.indexOf(val) < 0) {
throw new TypeError(`Property ${key} with the value of ${val} expected to be one of ${JSON.stringify(vals)}`);
throw new TypeError(`Property ${key} with the value of ${JSON.stringify(val)} expected to be one of ${JSON.stringify(vals)}`);
}
};
}
export function assertEach(callback) {
return function (node, key, val) {
if (!Array.isArray(val)) return;
for (var i = 0; i < val.length; i++) {
callback(node, `${key}[${i}]`, val[i]);
}
};
}
export function assertOneOf(...vals) {
return function (node, key, val) {
if (vals.indexOf(val) < 0) {
throw new TypeError(`Property ${key} expected value to be one of ${JSON.stringify(vals)} but got ${JSON.stringify(val)}`);
}
};
}
export function assertNodeType(...types) {
return function (node, key) {
return function (node, key, val) {
var valid = false;
for (var type of types) {
if (t.is(type, node)) {
if (t.is(type, val)) {
valid = true;
break;
}
}
if (!valid) {
throw new TypeError(`Property ${key} expected node to be of a type ${JSON.stringify(types)} but instead got ${node && node.type}`);
throw new TypeError(`Property ${key} expected node to be of a type ${JSON.stringify(types)} but instead got ${JSON.stringify(val && val.type)}`);
}
};
}
export function assertValueType(type) {
return function (val, key) {
var valid = typeof val === type;
if (type === "array" && Array.isArray(val)) valid = true;
return function (node, key, val) {
var valid = getType(val) === type;
if (!valid) {
throw new TypeError(`Property ${key} expected type of ${type} but got ${typeof val}`);
console.log(type, key, val);
throw new TypeError(`Property ${key} expected type of ${type} but got ${getType(val)}`);
}
};
}
export function chain(...fns) {
return function (...args) {
for (var fn of fns) {
fn(...args);
}
};
}

View File

@ -1,13 +1,27 @@
import define, { assertValueType } from "./index";
import define, { assertNodeType, assertValueType, chain, assertEach } from "./index";
define("JSXAttribute", {
visitor: ["name", "value"],
aliases: ["JSX", "Immutable"]
aliases: ["JSX", "Immutable"],
fields: {
name: {
validate: assertNodeType("JSXIdentifier", "JSXMemberExpression")
},
value: {
optional: true,
validate: assertNodeType("JSXElement", "StringLiteral", "JSXExpressionContainer")
}
}
});
define("JSXClosingElement", {
visitor: ["name"],
aliases: ["JSX", "Immutable"]
aliases: ["JSX", "Immutable"],
fields: {
name: {
validate: assertNodeType("JSXIdentifier", "JSXMemberExpression")
}
}
});
define("JSXElement", {
@ -34,37 +48,79 @@ define("JSXEmptyExpression", {
define("JSXExpressionContainer", {
visitor: ["expression"],
aliases: ["JSX", "Immutable"]
aliases: ["JSX", "Immutable"],
fields: {
expression: {
validate: assertNodeType("Expression")
}
}
});
define("JSXIdentifier", {
builder: ["name"],
aliases: ["JSX", "Expression"]
});
define("JSXMemberExpression", {
visitor: ["object", "property"],
aliases: ["JSX", "Expression"]
aliases: ["JSX", "Expression"],
fields: {
object: {
validate: assertNodeType("JSXIdentifier")
},
property: {
validate: assertNodeType("JSXIdentifier")
}
}
});
define("JSXNamespacedName", {
visitor: ["namespace", "name"],
aliases: ["JSX"]
aliases: ["JSX"],
fields: {
namespace: {
validate: assertNodeType("JSXIdentifier")
},
name: {
validate: assertNodeType("JSXIdentifier")
}
}
});
define("JSXOpeningElement", {
builder: ["name", "attributes", "selfClosing"],
visitor: ["name", "attributes"],
aliases: ["JSX", "Immutable"]
aliases: ["JSX", "Immutable"],
fields: {
name: {
validate: assertNodeType("JSXIdentifier", "JSXMemberExpression")
},
selfClosing: {
default: false,
validate: assertValueType("boolean")
},
attributes: {
validate: chain(assertValueType("array"), assertEach(assertNodeType("JSXAttribute", "JSXSpreadAttribute")))
}
}
});
define("JSXSpreadAttribute", {
visitor: ["argument"],
aliases: ["JSX"]
aliases: ["JSX"],
fields: {
argument: {
validate: assertNodeType("Expression")
}
}
});
define("JSXText", {
aliases: ["JSX"],
builder: ["value"],
fields: {
value: { validate: assertValueType("string") }
value: {
validate: assertValueType("string")
}
}
});

View File

@ -1,4 +1,4 @@
import define from "./index";
import define, { assertNodeType } from "./index";
define("Noop", {
visitor: []
@ -6,5 +6,10 @@ define("Noop", {
define("ParenthesizedExpression", {
visitor: ["expression"],
aliases: ["Expression"]
aliases: ["Expression"],
fields: {
expression: {
validate: assertNodeType("expression")
}
}
});

View File

@ -1,6 +1,7 @@
import toFastProperties from "to-fast-properties";
import compact from "lodash/array/compact";
import assign from "lodash/object/assign";
import loClone from "lodash/lang/clone";
import each from "lodash/collection/each";
import uniq from "lodash/array/uniq";
@ -129,21 +130,28 @@ export function isType(nodeType: string, targetType: string): boolean {
each(t.BUILDER_KEYS, function (keys, type) {
function builder() {
if (arguments.length > keys.length) {
// todo: error
}
var node = {};
node.type = type;
var i = 0;
for (var key of (keys: Array)) {
for (let key of (keys: Array)) {
var field = t.NODE_FIELDS[type][key];
var arg = arguments[i++];
if (arg === undefined) arg = field.default;
if (field.validate) field.validate(arg, key);
if (arg === undefined) arg = loClone(field.default);
node[key] = arg;
}
for (let key in node) {
validate(node, key, node[key]);
}
return node;
}
@ -155,14 +163,17 @@ each(t.BUILDER_KEYS, function (keys, type) {
* Description
*/
export function validate(key, parent, node) {
var fields = t.NODE_FIELDS[parent.type];
export function validate(node, key, val) {
if (!node) return;
var fields = t.NODE_FIELDS[node.type];
if (!fields) return;
var field = fields[key];
if (!field || !field.validate) return;
if (field.optional && val == null) return;
field.validate(node, key);
field.validate(node, key, val);
}
/**