UNPKG

sucrase

Version:

Super-fast alternative to Babel for when you can target modern JS runtimes

153 lines (152 loc) 6.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Scan the tokens and assign a "context" to each one. For example, we need to * know when a comma separates object literal fields vs array elements so that * we can properly handle object shorthand inline. */ function augmentTokenContext(tokens) { let index = 0; function processToToken(closingTokenLabel, context) { processRegion([closingTokenLabel], context); } function matchesTokens(labels) { for (let i = 0; i < labels.length; i++) { let newIndex = index + i; if (newIndex >= tokens.length || tokens[newIndex].type.label !== labels[i]) { return false; } } return true; } function processRegion(closingTokenLabels, context) { const contextStartIndex = index; function advance() { if (index < tokens.length) { tokens[index].contextName = context; tokens[index].contextStartIndex = contextStartIndex; } index++; } let pendingClass = false; while (index < tokens.length) { if (matchesTokens(closingTokenLabels)) { for (let i = 0; i < closingTokenLabels.length; i++) { advance(); } break; } const lastToken = tokens[index - 1]; const token = tokens[index]; advance(); // Keywords can be property values, so bail out if we're after a dot. if (!lastToken || lastToken.type.label !== '.') { if (token.type.label === 'if' || token.type.label === 'for' || token.type.label === 'while' || token.type.label === 'catch' || token.type.label === 'function') { // Code of the form TOKEN (...) BLOCK if (token.type.label === 'function' && tokens[index].type.label === 'name') { advance(); } if (tokens[index].type.label === '(') { advance(); processToToken(')', 'parens'); if (tokens[index].type.label === '{') { advance(); processToToken('}', 'block'); } continue; } } else if (token.type.label === '=>' || token.type.label === 'else' || token.type.label === 'try' || token.type.label === 'finally' || token.type.label === 'do' || token.type.label === '}' || token.type.label === ')' || (token.type.label === ';' && context === 'block')) { if (tokens[index].type.label === '{') { advance(); processToToken('}', 'block'); continue; } } else if (token.type.label === 'class') { pendingClass = true; continue; } else if (token.type.label === 'default') { if (tokens[index].type.label === ':' && tokens[index + 1].type.label === '{') { advance(); advance(); processToToken('}', 'block'); continue; } } } if (token.type.label === 'name') { if (context === 'class' && tokens[index].type.label === '(') { // Process class method. advance(); processToToken(')', 'parens'); if (tokens[index].type.label === '{') { advance(); processToToken('}', 'block'); } } else if (context === 'object' && tokens[index].type.label === '(' && (tokens[index - 2].type.label === ',' || tokens[index - 2].type.label === '{')) { // Process object method. advance(); processToToken(')', 'parens'); if (tokens[index].type.label === '{') { advance(); processToToken('}', 'block'); } } } else if (token.type.label === 'case') { processToToken(':', 'switchCaseCondition'); if (tokens[index].type.label === '{') { advance(); processToToken('}', 'block'); } } else if (token.type.label === 'jsxTagStart') { processToToken('jsxTagEnd', 'jsxTag'); // Non-self-closing tag, so use jsxChild context for the body. if (tokens[index - 2].type.label !== '/') { // All / tokens will be in JSX tags. processRegion(['jsxTagStart', '/'], 'jsxChild'); processToToken('jsxTagEnd', 'jsxTag'); } } else if (token.type.label === '{') { if (pendingClass && lastToken.type.label !== 'extends') { processToToken('}', 'class'); pendingClass = false; } else if (context === 'jsxTag' || context === 'jsxChild') { processToToken('}', 'jsxExpression'); } else { processToToken('}', 'object'); } } else if (token.type.label === '[') { processToToken(']', 'brackets'); } else if (token.type.label === '(') { processToToken(')', 'parens'); } else if (token.type.label === '${') { processToToken('}', 'interpolatedExpression'); } } } processToToken('NONE', 'block'); } exports.default = augmentTokenContext;