UNPKG

cst

Version:

JavaScript CST Implementation

310 lines (261 loc) 11 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); var _getIterator2 = require('babel-runtime/core-js/get-iterator'); var _getIterator3 = _interopRequireDefault(_getIterator2); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _babylon = require('babylon'); var _elementTree = require('./elementTree'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * @typedef {Object} CSTParserOptions * @property {String} sourceType Type of parsed code: "module" or "script". * @property {Boolean} allowReturnOutsideFunction * @property {Boolean} allowImportExportEverywhere * @property {Boolean} allowSuperOutsideMethod * @property {CSTParserExperimentalFeatureOptions} experimentalFeatures * @property {CSTParserLanguageExtensionsOptions} languageExtensions */ /** * @typedef {Object} CSTParserLanguageExtensionsOptions * @property {Boolean} jsx * @property {Boolean} flow */ /** * @typedef {Object} CSTParserExperimentalFeatureOptions * @property {Boolean} 'flow' * @property {Boolean} 'jsx' * @property {Boolean} 'asyncFunctions' * @property {Boolean} 'asyncGenerators' * @property {Boolean} 'classConstructorCall' * @property {Boolean} 'classProperties' * @property {Boolean} 'decorators' * @property {Boolean} 'doExpressions' * @property {Boolean} 'exponentiationOperator' * @property {Boolean} 'exportExtensions' * @property {Boolean} 'functionBind' * @property {Boolean} 'objectRestSpread' * @property {Boolean} 'trailingFunctionCommas */ // https://developer.apple.com/library/watchos/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UIAutomation.html var DIRECTIVE_APPLE_INSTRUMENTATION = { type: 'AppleInstrumentationDirective', regexp: /^#([^\n]+)/gm }; // https://www.chromium.org/developers/web-development-style-guide var DIRECTIVE_GRIT = { type: 'GritDirective', regexp: /^\s*<(\/?\s*(?:if|include)(?!\w)[^]*?)>/gim }; // checking for the options passed to the babel parse method /** * CST Parser. */ var Parser = function () { /** * @param {CSTParserOptions} options */ function Parser(options) { (0, _classCallCheck3.default)(this, Parser); this._options = { sourceType: 'module', strictMode: true, experimentalFeatures: { 'flow': true, 'jsx': true, 'asyncFunctions': true, 'asyncGenerators': true, 'classConstructorCall': true, 'classProperties': true, 'decorators': true, 'doExpressions': true, 'exponentiationOperator': true, 'exportExtensions': true, 'functionBind': true, 'objectRestSpread': true, 'trailingFunctionCommas': true }, languageExtensions: { jsx: true, flow: true }, plugins: [] }; if (options) { this.setOptions(options); } } (0, _createClass3.default)(Parser, [{ key: 'getOptions', /** * @returns {CSTParserOptions} */ value: function getOptions() { return this._options; } /** * @param {CSTParserOptions} newOptions */ }, { key: 'setOptions', value: function setOptions(newOptions) { var currentOptions = this._options; var currentExperimentalFeatures = currentOptions.experimentalFeatures; var currentLanguageExtensions = currentOptions.languageExtensions; var newExperimentalFeatures = newOptions.experimentalFeatures; var newLanguageExtensions = newOptions.languageExtensions; this._options = (0, _extends3.default)({}, currentOptions, newOptions, { experimentalFeatures: (0, _extends3.default)({}, currentExperimentalFeatures, newExperimentalFeatures), languageExtensions: (0, _extends3.default)({}, currentLanguageExtensions, newLanguageExtensions) }); } }, { key: 'parse', value: function parse(code) { var ast = this._parseAst(code); var tokens = this._processTokens(ast, code); var program = (0, _elementTree.buildElementTree)(ast, tokens); var programPlugins = {}; var plugins = this._options.plugins; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = (0, _getIterator3.default)(plugins), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var plugin = _step.value; var api = plugin.createApiForProgram(program); if (api) { var pluginName = plugin.getPluginName(); if (pluginName in programPlugins) { throw new Error('Plugin "' + pluginName + '" was already registered.'); } else { programPlugins[pluginName] = api; } } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } program._acceptPlugins(programPlugins); return program; } }, { key: '_parseAst', value: function _parseAst(code) { var options = this._options; var languageExtensions = options.languageExtensions; var directiveInstances = {}; var hasDirectives = false; var directiveTypes = []; if (languageExtensions.appleInstrumentationDirectives) { directiveTypes.push(DIRECTIVE_APPLE_INSTRUMENTATION); } if (languageExtensions.gritDirectives) { directiveTypes.push(DIRECTIVE_GRIT); } var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { var _loop = function _loop() { var directive = _step2.value; code = code.replace(directive.regexp, function (str, value, pos) { hasDirectives = true; directiveInstances[pos] = { type: directive.type, value: value }; // Cut 4 characters to save correct line/column info for surrounding code return '/*' + str.slice(4) + '*/'; }); }; for (var _iterator2 = (0, _getIterator3.default)(directiveTypes), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { _loop(); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } var ast = (0, _babylon.parse)(code, { sourceType: options.sourceType, strictMode: options.strictMode, allowImportExportEverywhere: options.allowImportExportEverywhere, allowReturnOutsideFunction: options.allowReturnOutsideFunction, allowSuperOutsideMethod: options.allowSuperOutsideMethod, plugins: [].concat((0, _toConsumableArray3.default)((0, _keys2.default)(options.experimentalFeatures)), (0, _toConsumableArray3.default)((0, _keys2.default)(options.languageExtensions))) }); var program = ast.program; program.tokens = ast.tokens; if (hasDirectives) { var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = (0, _getIterator3.default)(program.tokens), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var token = _step3.value; var directiveInstance = directiveInstances[token.start]; if (directiveInstances[token.start]) { token.type = directiveInstance.type; token.value = directiveInstance.value; } } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3.return) { _iterator3.return(); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } } if (code.substr(0, 2) === '#!') { program.tokens[0].type = 'Hashbang'; } return program; } }, { key: '_processTokens', value: function _processTokens(ast, code) { return (0, _elementTree.buildTokenList)(ast.tokens, code); } }]); return Parser; }(); exports.default = Parser; //# sourceMappingURL=Parser.js.map