@marko/babel-utils
Version:
Utilities for use with Marko babel plugins.
199 lines (170 loc) • 5.85 kB
JavaScript
;exports.__esModule = true;exports.parseArgs = parseArgs;exports.parseExpression = parseExpression;exports.parseParams = parseParams;exports.parseStatements = parseStatements;exports.parseTemplateLiteral = parseTemplateLiteral;exports.parseTypeArgs = parseTypeArgs;exports.parseTypeParams = parseTypeParams;exports.parseVar = parseVar;var babelParser = _interopRequireWildcard(require("@babel/parser"));
var _compiler = require("@marko/compiler");
var _loc = require("./loc");function _getRequireWildcardCache(e) {if ("function" != typeof WeakMap) return null;var r = new WeakMap(),t = new WeakMap();return (_getRequireWildcardCache = function (e) {return e ? t : r;})(e);}function _interopRequireWildcard(e, r) {if (!r && e && e.__esModule) return e;if (null === e || "object" != typeof e && "function" != typeof e) return { default: e };var t = _getRequireWildcardCache(r);if (t && t.has(e)) return t.get(e);var n = { __proto__: null },a = Object.defineProperty && Object.getOwnPropertyDescriptor;for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) {var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u];}return n.default = e, t && t.set(e, n), n;}
function parseStatements(
file,
str,
sourceStart,
sourceEnd,
sourceOffset)
{
return tryParse(file, false, str, sourceStart, sourceEnd, sourceOffset);
}
function parseExpression(
file,
str,
sourceStart,
sourceEnd,
sourceOffset)
{
return tryParse(file, true, str, sourceStart, sourceEnd, sourceOffset);
}
function parseParams(file, str, sourceStart, sourceEnd) {
const parsed = parseExpression(
file,
`(${str})=>{}`,
sourceStart,
sourceEnd,
1
);
if (parsed.type === "ArrowFunctionExpression") {
return parsed.params;
}
return [ensureParseError(file, parsed, sourceStart, sourceEnd)];
}
function parseArgs(file, str, sourceStart, sourceEnd) {
const parsed = parseExpression(file, `_(${str})`, sourceStart, sourceEnd, 2);
if (parsed.type === "CallExpression") {
return parsed.arguments;
}
return [ensureParseError(file, parsed, sourceStart, sourceEnd)];
}
function parseVar(file, str, sourceStart, sourceEnd) {
const parsed = parseExpression(
file,
`(${str})=>{}`,
sourceStart,
sourceEnd,
1
);
if (parsed.type === "ArrowFunctionExpression" && parsed.params.length === 1) {
return parsed.params[0];
}
return ensureParseError(file, parsed, sourceStart, sourceEnd);
}
function parseTemplateLiteral(file, str, sourceStart, sourceEnd) {
const parsed = parseExpression(
file,
"`" + str + "`",
sourceStart,
sourceEnd,
1
);
if (parsed.type === "TemplateLiteral") {
return parsed;
}
return ensureParseError(file, parsed, sourceStart, sourceEnd);
}
function parseTypeArgs(file, str, sourceStart, sourceEnd) {
const parsed = parseExpression(file, `_<${str}>`, sourceStart, sourceEnd, 2);
if (parsed.type === "TSInstantiationExpression") {
// typeArguments is Flow only (not TS), we need to use typeParameters
return parsed.typeParameters;
}
return [ensureParseError(file, parsed, sourceStart, sourceEnd)];
}
function parseTypeParams(file, str, sourceStart, sourceEnd) {
const parsed = parseExpression(
file,
`<${str}>()=>{}`,
sourceStart,
sourceEnd,
1
);
if (parsed.type === "ArrowFunctionExpression") {
return parsed.typeParameters;
}
return [ensureParseError(file, parsed, sourceStart, sourceEnd)];
}
function tryParse(
file,
isExpression,
code,
sourceStart,
sourceEnd,
sourceOffset)
{
const { parserOpts } = file.opts;
if (typeof sourceStart === "number") {
const startIndex = sourceStart - (sourceOffset || 0);
const startLoc = (0, _loc.getLoc)(file, startIndex);
parserOpts.startIndex = startIndex;
parserOpts.startColumn = startLoc.column;
parserOpts.startLine = startLoc.line;
try {
return isExpression ?
babelParser.parseExpression(code, parserOpts) :
babelParser.parse(code, parserOpts).program.body;
} catch (err) {
const parseError = createParseError(
file,
sourceStart,
sourceEnd,
err.message,
err.loc
);
if (isExpression) {
return parseError;
} else {
return [parseError];
}
} finally {
parserOpts.startIndex = 0;
parserOpts.startColumn = 0;
parserOpts.startLine = 1;
}
} else {
return isExpression ?
_compiler.types.cloneDeepWithoutLoc(babelParser.parseExpression(code, parserOpts)) :
babelParser.
parse(code, parserOpts).
program.body.map((node) => _compiler.types.cloneDeepWithoutLoc(node));
}
}
function ensureParseError(file, node, sourceStart, sourceEnd) {
if (node.type === "MarkoParseError") return node;
return createParseError(
file,
sourceStart,
sourceEnd,
`Unexpected node of type ${node.type} returned while parsing.`
);
}
function createParseError(file, sourceStart, sourceEnd, label, errorLoc) {
file.___hasParseErrors = true;
const loc = (0, _loc.getLocRange)(file, sourceStart, sourceEnd);
return {
type: "MarkoParseError",
source: file.code.slice(sourceStart, sourceEnd),
label: label.replace(/ *\(\d+:\d+\)$/, ""),
errorLoc: errorLoc && getBoundedRange(loc, errorLoc),
loc,
start: sourceStart,
end: sourceEnd
};
}
function getBoundedRange(range, loc) {
if (loc && typeof loc.line === "number") {
const { start, end } = range;
// If start is out of bounds return the source.
if (
loc.line < start.line ||
loc.line === start.line && loc.column < start.column ||
loc.line > end.line ||
loc.line === end.line && loc.column > end.column)
{
return range;
}
return { start: loc, end: loc };
}
}