decaffeinate-parser
Version:
A better AST for CoffeeScript, inspired by CoffeeScriptRedux.
83 lines (82 loc) • 4.18 kB
JavaScript
;
exports.__esModule = true;
var coffee_lex_1 = require("coffee-lex");
var nodes_1 = require("decaffeinate-coffeescript2/lib/coffeescript/nodes");
var util_1 = require("util");
var nodes_2 = require("../nodes");
var getLocation_1 = require("../util/getLocation");
var isCommentOnlyNode_1 = require("../util/isCommentOnlyNode");
var mapAny_1 = require("./mapAny");
function mapBlock(context, node) {
var childContext = context;
if (context.parseState.isInClassBody()) {
// Replicate a bug in CoffeeScript: at any block where we see an
// object-style proto assignment, stop considering proto assignments in any
// sub-traversals. This is taken from the walkBody implementation.
var hasProtoAssignChild = node.expressions.some(function (child) { return child instanceof nodes_1.Value && child.isObject(true); });
if (hasProtoAssignChild) {
childContext = childContext.updateState(function (s) { return s.dropCurrentClass(); });
}
}
var _a = getLocation_1["default"](context, node), line = _a.line, column = _a.column, start = _a.start, end = _a.end, raw = _a.raw;
var previousTokenIndex = context.sourceTokens
.indexOfTokenNearSourceIndex(start)
.previous();
var previousToken = previousTokenIndex
? context.sourceTokens.tokenAtIndex(previousTokenIndex)
: null;
var inline = previousToken
? previousToken.type !== coffee_lex_1.SourceType.NEWLINE
: false;
return new nodes_2.Block(line, column, start, end, raw, node.expressions
.filter(function (expression) { return !isCommentOnlyNode_1["default"](expression); })
.map(function (expression) { return mapChild(context, childContext, expression); })
.reduce(function (arr, current) { return arr.concat(current); }, []), inline);
}
exports["default"] = mapBlock;
function mapChild(blockContext, childContext, node) {
if (blockContext.parseState.isInClassBody() &&
node instanceof nodes_1.Value &&
node.isObject(true)) {
var obj = node.base;
if (!(obj instanceof nodes_1.Obj)) {
throw new Error('Expected isObject node to be an object.');
}
var statements = [];
for (var _i = 0, _a = obj.properties; _i < _a.length; _i++) {
var property = _a[_i];
if (isCommentOnlyNode_1["default"](property)) {
continue;
}
if (property instanceof nodes_1.Assign) {
var _b = getLocation_1["default"](childContext, property), line = _b.line, column = _b.column, start = _b.start, end = _b.end, raw = _b.raw;
var key = mapAny_1["default"](childContext, property.variable);
var value = mapAny_1["default"](childContext, property.value);
var Node_1 = nodes_2.ClassProtoAssignOp;
if (key instanceof nodes_2.Identifier && key.data === 'constructor') {
Node_1 = nodes_2.Constructor;
}
else if (key instanceof nodes_2.MemberAccessOp &&
key.expression instanceof nodes_2.This) {
Node_1 = nodes_2.AssignOp;
}
var assignment = new Node_1(line, column, start, end, raw, key, value);
statements.push(assignment);
if (assignment instanceof nodes_2.ClassProtoAssignOp &&
(assignment.expression instanceof nodes_2.BoundFunction ||
assignment.expression instanceof nodes_2.BoundGeneratorFunction ||
assignment.expression instanceof nodes_2.BoundAsyncFunction)) {
blockContext.parseState.recordBoundMethod(assignment);
}
if (assignment instanceof nodes_2.Constructor) {
blockContext.parseState.recordConstructor(assignment);
}
}
else {
throw new Error("unexpected class assignment: " + util_1.inspect(property));
}
}
return statements;
}
return [mapAny_1["default"](childContext, node)];
}