add class property initializers, add more TraversalPath flexibility with additional node injection method

This commit is contained in:
Sebastian McKenzie 2015-03-24 03:34:34 +11:00
parent 6d87a99d1d
commit e52af24999
4 changed files with 67 additions and 26 deletions

View File

@ -710,27 +710,29 @@ acorn.plugins.flow = function (instance) {
}
})
instance.extend("parseClassProperty", function (inner) {
return function (node) {
if (this.type === tt.colon) {
node.typeAnnotation = this.flow_parseTypeAnnotation()
}
return inner.call(this, node)
}
})
instance.extend("isClassProperty", function (inner) {
return function () {
return this.type === tt.colon || inner.call(this)
}
})
instance.extend("parseClassMethod", function (inner) {
return function (classBody, method, isGenerator, isAsync) {
var classProperty = false
if (this.type === tt.colon) {
method.typeAnnotation = this.flow_parseTypeAnnotation()
classProperty = true
}
if (classProperty) {
this.semicolon()
classBody.body.push(this.finishNode(method, "ClassProperty"))
} else {
var typeParameters
if (this.isRelational("<")) {
typeParameters = this.flow_parseTypeParameterDeclaration()
}
method.value = this.parseMethod(isGenerator, isAsync)
method.value.typeParameters = typeParameters
classBody.body.push(this.finishNode(method, "MethodDefinition"))
var typeParameters
if (this.isRelational("<")) {
typeParameters = this.flow_parseTypeParameterDeclaration()
}
method.value = this.parseMethod(isGenerator, isAsync)
method.value.typeParameters = typeParameters
classBody.body.push(this.finishNode(method, "MethodDefinition"))
}
})

View File

@ -418,6 +418,7 @@ pp.parseParenAndDistinguishExpression = function(start, isAsync) {
par.expression = val
return this.finishNode(par, "ParenthesizedExpression")
} else {
val.parenthesizedExpression = true
return val
}
}

View File

@ -9,6 +9,14 @@ const pp = Parser.prototype
// if possible.
pp.toAssignable = function(node, isBinding) {
if (node.parenthesizedExpression) {
if (node.type === "ObjectExpression") {
this.raise(node.start, "You're trying to assign to a parenthesized expression, instead of `({ foo }) = {}` use `({ foo } = {})`");
} else {
this.raise(node.start, "Parenthesized left hand expressions are illegal");
}
}
if (this.options.ecmaVersion >= 6 && node) {
switch (node.type) {
case "Identifier":

View File

@ -150,10 +150,17 @@ pp.parseDebuggerStatement = function(node) {
}
pp.parseDoStatement = function(node) {
let start = this.markPosition()
this.next()
this.labels.push(loopLabel)
node.body = this.parseStatement(false)
this.labels.pop()
if (this.options.features["es7.doExpressions"] && this.type !== tt._while) {
let container = this.startNodeAt(start)
container.expression = this.finishNode(node, "DoExpression")
this.semicolon()
return this.finishNode(container, "ExpressionStatement")
}
this.expect(tt._while)
node.test = this.parseParenExpression()
if (this.options.ecmaVersion >= 6)
@ -455,13 +462,17 @@ pp.parseClass = function(node, isStatement) {
while (!this.eat(tt.braceR)) {
if (this.eat(tt.semi)) continue
if (this.options.features["es7.decorators"] && this.type === tt.at) {
decorators.push(this.parseDecorator());
decorators.push(this.parseDecorator())
continue;
}
var method = this.startNode()
if (this.options.features["es7.decorators"] && decorators.length) {
method.decorators = decorators
decorators = []
}
var isGenerator = this.eat(tt.star), isAsync = false
this.parsePropertyName(method)
if (this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
if (this.options.features["es7.classProperties"] && this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
method.key.name === "static") {
if (isGenerator) this.unexpected()
method['static'] = true
@ -470,6 +481,10 @@ pp.parseClass = function(node, isStatement) {
} else {
method['static'] = false
}
if (!isGenerator && method.key.type === "Identifier" && !method.computed && this.isClassProperty()) {
classBody.body.push(this.parseClassProperty(method))
continue
}
if (this.options.features["es7.asyncFunctions"] && this.type !== tt.parenL &&
!method.computed && method.key.type === "Identifier" && method.key.name === "async") {
isAsync = true
@ -488,9 +503,8 @@ pp.parseClass = function(node, isStatement) {
method.kind = "constructor"
}
}
if (this.options.features["es7.decorators"] && decorators.length) {
method.decorators = decorators
decorators = []
if (method.kind === "constructor" && method.decorators) {
this.raise(method.start, "You can't attach decorators to a class constructor")
}
this.parseClassMethod(classBody, method, isGenerator, isAsync)
}
@ -501,16 +515,32 @@ pp.parseClass = function(node, isStatement) {
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
}
pp.parseClassMethod = function (classBody, method, isGenerator, isAsync) {
pp.isClassProperty = function() {
return this.type === tt.eq || (this.type === tt.semi || this.canInsertSemicolon())
}
pp.parseClassProperty = function(node) {
if (this.type === tt.eq) {
if (!this.options.features["es7.classProperties"]) this.unexpected()
this.next()
node.value = this.parseMaybeAssign();
} else {
node.value = null;
}
this.semicolon()
return this.finishNode(node, "ClassProperty")
}
pp.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
method.value = this.parseMethod(isGenerator, isAsync)
classBody.body.push(this.finishNode(method, "MethodDefinition"))
}
pp.parseClassId = function (node, isStatement) {
pp.parseClassId = function(node, isStatement) {
node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null
}
pp.parseClassSuper = function (node) {
pp.parseClassSuper = function(node) {
node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null
}