Convert each plugin to a function from a class to an overriding class (#459)

* Convert each plugin to a function from a class to an overriding class

* Handle undefined options

* Fix indentation

* Fix double space
This commit is contained in:
Andy
2017-04-21 04:53:51 -07:00
committed by Daniel Tschinder
parent 2ef436641e
commit ad284d5c36
5 changed files with 671 additions and 763 deletions

View File

@@ -43,206 +43,178 @@ function isSimpleProperty(node) {
node.method === false;
}
export default function (instance) {
instance.extend("checkDeclaration", function(inner) {
return function (node) {
if (isSimpleProperty(node)) {
this.checkDeclaration(node.value);
export default (superClass) => class extends superClass {
checkDeclaration(node) {
if (isSimpleProperty(node)) {
this.checkDeclaration(node.value);
} else {
super.checkDeclaration(node);
}
}
checkGetterSetterParamCount(prop) {
const paramCount = prop.kind === "get" ? 0 : 1;
if (prop.value.params.length !== paramCount) {
const start = prop.start;
if (prop.kind === "get") {
this.raise(start, "getter should have no params");
} else {
inner.call(this, node);
this.raise(start, "setter should have exactly one param");
}
};
});
}
}
instance.extend("checkGetterSetterParamCount", function() {
return function (prop) {
const paramCount = prop.kind === "get" ? 0 : 1;
if (prop.value.params.length !== paramCount) {
const start = prop.start;
if (prop.kind === "get") {
this.raise(start, "getter should have no params");
checkLVal(expr, isBinding, checkClashes, ...args) {
switch (expr.type) {
case "ObjectPattern":
expr.properties.forEach((prop) => {
this.checkLVal(
prop.type === "Property" ? prop.value : prop,
isBinding,
checkClashes,
"object destructuring pattern"
);
});
break;
default:
super.checkLVal(expr, isBinding, checkClashes, ...args);
}
}
checkPropClash(prop, propHash) {
if (prop.computed || !isSimpleProperty(prop)) return;
const key = prop.key;
// It is either an Identifier or a String/NumericLiteral
const name = key.type === "Identifier" ? key.name : String(key.value);
if (name === "__proto__") {
if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property");
propHash.proto = true;
}
}
isStrictBody(node, isExpression) {
if (!isExpression && node.body.body.length > 0) {
for (const directive of (node.body.body: Array<Object>)) {
if (directive.type === "ExpressionStatement" && directive.expression.type === "Literal") {
if (directive.expression.value === "use strict") return true;
} else {
this.raise(start, "setter should have exactly one param");
}
}
};
});
instance.extend("checkLVal", function(inner) {
return function (expr, isBinding, checkClashes, ...args) {
switch (expr.type) {
case "ObjectPattern":
expr.properties.forEach((prop) => {
this.checkLVal(
prop.type === "Property" ? prop.value : prop,
isBinding,
checkClashes,
"object destructuring pattern"
);
});
// Break for the first non literal expression
break;
default:
inner.call(this, expr, isBinding, checkClashes, ...args);
}
}
};
});
}
instance.extend("checkPropClash", function () {
return function (prop, propHash) {
if (prop.computed || !isSimpleProperty(prop)) return;
return false;
}
const key = prop.key;
// It is either an Identifier or a String/NumericLiteral
const name = key.type === "Identifier" ? key.name : String(key.value);
isValidDirective(stmt) {
return stmt.type === "ExpressionStatement" &&
stmt.expression.type === "Literal" &&
typeof stmt.expression.value === "string" &&
(!stmt.expression.extra || !stmt.expression.extra.parenthesized);
}
if (name === "__proto__") {
if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property");
propHash.proto = true;
}
};
});
parseBlockBody(node, ...args) {
super.parseBlockBody(node, ...args);
instance.extend("isStrictBody", function () {
return function (node, isExpression) {
if (!isExpression && node.body.body.length > 0) {
for (const directive of (node.body.body: Array<Object>)) {
if (directive.type === "ExpressionStatement" && directive.expression.type === "Literal") {
if (directive.expression.value === "use strict") return true;
} else {
// Break for the first non literal expression
break;
}
node.directives.reverse().forEach((directive) => {
node.body.unshift(this.directiveToStmt(directive));
});
delete node.directives;
}
parseClassMethod(classBody, ...args) {
super.parseClassMethod(classBody, ...args);
const body = classBody.body;
body[body.length - 1].type = "MethodDefinition";
}
parseExprAtom(...args) {
switch (this.state.type) {
case tt.regexp:
return this.estreeParseRegExpLiteral(this.state.value);
case tt.num:
case tt.string:
return this.estreeParseLiteral(this.state.value);
case tt._null:
return this.estreeParseLiteral(null);
case tt._true:
return this.estreeParseLiteral(true);
case tt._false:
return this.estreeParseLiteral(false);
default:
return super.parseExprAtom(...args);
}
}
parseLiteral(...args) {
const node = super.parseLiteral(...args);
node.raw = node.extra.raw;
delete node.extra;
return node;
}
parseMethod(node, ...args) {
let funcNode = this.startNode();
funcNode.kind = node.kind; // provide kind, so super method correctly sets state
funcNode = super.parseMethod(funcNode, ...args);
delete funcNode.kind;
node.value = this.finishNode(funcNode, "FunctionExpression");
return node;
}
parseObjectMethod(...args) {
const node = super.parseObjectMethod(...args);
if (node) {
if (node.kind === "method") node.kind = "init";
node.type = "Property";
}
return node;
}
parseObjectProperty(...args) {
const node = super.parseObjectProperty(...args);
if (node) {
node.kind = "init";
node.type = "Property";
}
return node;
}
toAssignable(node, isBinding, ...args) {
if (isSimpleProperty(node)) {
this.toAssignable(node.value, isBinding, ...args);
return node;
} else if (node.type === "ObjectExpression") {
node.type = "ObjectPattern";
for (const prop of (node.properties: Array<Object>)) {
if (prop.kind === "get" || prop.kind === "set") {
this.raise(prop.key.start, "Object pattern can't contain getter or setter");
} else if (prop.method) {
this.raise(prop.key.start, "Object pattern can't contain methods");
} else {
this.toAssignable(prop, isBinding, "object destructuring pattern");
}
}
return false;
};
});
instance.extend("isValidDirective", function () {
return function (stmt) {
return stmt.type === "ExpressionStatement" &&
stmt.expression.type === "Literal" &&
typeof stmt.expression.value === "string" &&
(!stmt.expression.extra || !stmt.expression.extra.parenthesized);
};
});
instance.extend("parseBlockBody", function (inner) {
return function (node, ...args) {
inner.call(this, node, ...args);
node.directives.reverse().forEach((directive) => {
node.body.unshift(this.directiveToStmt(directive));
});
delete node.directives;
};
});
instance.extend("parseClassMethod", function (inner) {
return function (classBody, ...args) {
inner.call(this, classBody, ...args);
const body = classBody.body;
body[body.length - 1].type = "MethodDefinition";
};
});
instance.extend("parseExprAtom", function(inner) {
return function (...args) {
switch (this.state.type) {
case tt.regexp:
return this.estreeParseRegExpLiteral(this.state.value);
case tt.num:
case tt.string:
return this.estreeParseLiteral(this.state.value);
case tt._null:
return this.estreeParseLiteral(null);
case tt._true:
return this.estreeParseLiteral(true);
case tt._false:
return this.estreeParseLiteral(false);
default:
return inner.call(this, ...args);
}
};
});
instance.extend("parseLiteral", function(inner) {
return function (...args) {
const node = inner.call(this, ...args);
node.raw = node.extra.raw;
delete node.extra;
return node;
};
});
}
instance.extend("parseMethod", function(inner) {
return function (node, ...args) {
let funcNode = this.startNode();
funcNode.kind = node.kind; // provide kind, so inner method correctly sets state
funcNode = inner.call(this, funcNode, ...args);
delete funcNode.kind;
node.value = this.finishNode(funcNode, "FunctionExpression");
return node;
};
});
instance.extend("parseObjectMethod", function(inner) {
return function (...args) {
const node = inner.call(this, ...args);
if (node) {
if (node.kind === "method") node.kind = "init";
node.type = "Property";
}
return node;
};
});
instance.extend("parseObjectProperty", function(inner) {
return function (...args) {
const node = inner.call(this, ...args);
if (node) {
node.kind = "init";
node.type = "Property";
}
return node;
};
});
instance.extend("toAssignable", function(inner) {
return function (node, isBinding, ...args) {
if (isSimpleProperty(node)) {
this.toAssignable(node.value, isBinding, ...args);
return node;
} else if (node.type === "ObjectExpression") {
node.type = "ObjectPattern";
for (const prop of (node.properties: Array<Object>)) {
if (prop.kind === "get" || prop.kind === "set") {
this.raise(prop.key.start, "Object pattern can't contain getter or setter");
} else if (prop.method) {
this.raise(prop.key.start, "Object pattern can't contain methods");
} else {
this.toAssignable(prop, isBinding, "object destructuring pattern");
}
}
return node;
}
return inner.call(this, node, isBinding, ...args);
};
});
}
return super.toAssignable(node, isBinding, ...args);
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -395,72 +395,66 @@ pp.jsxParseElement = function() {
return this.jsxParseElementAt(startPos, startLoc);
};
export default function(instance) {
instance.extend("parseExprAtom", function(inner) {
return function(refShortHandDefaultPos) {
if (this.match(tt.jsxText)) {
return this.parseLiteral(this.state.value, "JSXText");
} else if (this.match(tt.jsxTagStart)) {
return this.jsxParseElement();
} else {
return inner.call(this, refShortHandDefaultPos);
}
};
});
export default (superClass) => class extends superClass {
parseExprAtom(refShortHandDefaultPos) {
if (this.match(tt.jsxText)) {
return this.parseLiteral(this.state.value, "JSXText");
} else if (this.match(tt.jsxTagStart)) {
return this.jsxParseElement();
} else {
return super.parseExprAtom(refShortHandDefaultPos);
}
}
instance.extend("readToken", function(inner) {
return function(code) {
if (this.state.inPropertyName) return inner.call(this, code);
readToken(code) {
if (this.state.inPropertyName) return super.readToken(code);
const context = this.curContext();
const context = this.curContext();
if (context === tc.j_expr) {
return this.jsxReadToken();
if (context === tc.j_expr) {
return this.jsxReadToken();
}
if (context === tc.j_oTag || context === tc.j_cTag) {
if (isIdentifierStart(code)) {
return this.jsxReadWord();
}
if (context === tc.j_oTag || context === tc.j_cTag) {
if (isIdentifierStart(code)) {
return this.jsxReadWord();
}
if (code === 62) {
++this.state.pos;
return this.finishToken(tt.jsxTagEnd);
}
if ((code === 34 || code === 39) && context === tc.j_oTag) {
return this.jsxReadString(code);
}
}
if (code === 60 && this.state.exprAllowed) {
if (code === 62) {
++this.state.pos;
return this.finishToken(tt.jsxTagStart);
return this.finishToken(tt.jsxTagEnd);
}
return inner.call(this, code);
};
});
if ((code === 34 || code === 39) && context === tc.j_oTag) {
return this.jsxReadString(code);
}
}
instance.extend("updateContext", function(inner) {
return function(prevType) {
if (this.match(tt.braceL)) {
const curContext = this.curContext();
if (curContext === tc.j_oTag) {
this.state.context.push(tc.braceExpression);
} else if (curContext === tc.j_expr) {
this.state.context.push(tc.templateQuasi);
} else {
inner.call(this, prevType);
}
this.state.exprAllowed = true;
} else if (this.match(tt.slash) && prevType === tt.jsxTagStart) {
this.state.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
this.state.context.push(tc.j_cTag); // reconsider as closing tag context
this.state.exprAllowed = false;
if (code === 60 && this.state.exprAllowed) {
++this.state.pos;
return this.finishToken(tt.jsxTagStart);
}
return super.readToken(code);
}
updateContext(prevType) {
if (this.match(tt.braceL)) {
const curContext = this.curContext();
if (curContext === tc.j_oTag) {
this.state.context.push(tc.braceExpression);
} else if (curContext === tc.j_expr) {
this.state.context.push(tc.templateQuasi);
} else {
return inner.call(this, prevType);
super.updateContext(prevType);
}
};
});
}
this.state.exprAllowed = true;
} else if (this.match(tt.slash) && prevType === tt.jsxTagStart) {
this.state.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
this.state.context.push(tc.j_cTag); // reconsider as closing tag context
this.state.exprAllowed = false;
} else {
return super.updateContext(prevType);
}
}
};