123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- var _types = require('./parser/tokenizer/types');
- var _isAsyncOperation = require('./util/isAsyncOperation'); var _isAsyncOperation2 = _interopRequireDefault(_isAsyncOperation);
- class TokenProcessor {
- __init() {this.resultCode = ""}
- // Array mapping input token index to optional string index position in the
- // output code.
- __init2() {this.resultMappings = new Array(this.tokens.length)}
- __init3() {this.tokenIndex = 0}
- constructor(
- code,
- tokens,
- isFlowEnabled,
- disableESTransforms,
- helperManager,
- ) {;this.code = code;this.tokens = tokens;this.isFlowEnabled = isFlowEnabled;this.disableESTransforms = disableESTransforms;this.helperManager = helperManager;TokenProcessor.prototype.__init.call(this);TokenProcessor.prototype.__init2.call(this);TokenProcessor.prototype.__init3.call(this);}
- /**
- * Snapshot the token state in a way that can be restored later, useful for
- * things like lookahead.
- *
- * resultMappings do not need to be copied since in all use cases, they will
- * be overwritten anyway after restore.
- */
- snapshot() {
- return {
- resultCode: this.resultCode,
- tokenIndex: this.tokenIndex,
- };
- }
- restoreToSnapshot(snapshot) {
- this.resultCode = snapshot.resultCode;
- this.tokenIndex = snapshot.tokenIndex;
- }
- /**
- * Remove and return the code generated since the snapshot, leaving the
- * current token position in-place. Unlike most TokenProcessor operations,
- * this operation can result in input/output line number mismatches because
- * the removed code may contain newlines, so this operation should be used
- * sparingly.
- */
- dangerouslyGetAndRemoveCodeSinceSnapshot(snapshot) {
- const result = this.resultCode.slice(snapshot.resultCode.length);
- this.resultCode = snapshot.resultCode;
- return result;
- }
- reset() {
- this.resultCode = "";
- this.resultMappings = new Array(this.tokens.length);
- this.tokenIndex = 0;
- }
- matchesContextualAtIndex(index, contextualKeyword) {
- return (
- this.matches1AtIndex(index, _types.TokenType.name) &&
- this.tokens[index].contextualKeyword === contextualKeyword
- );
- }
- identifierNameAtIndex(index) {
- // TODO: We need to process escapes since technically you can have unicode escapes in variable
- // names.
- return this.identifierNameForToken(this.tokens[index]);
- }
- identifierNameAtRelativeIndex(relativeIndex) {
- return this.identifierNameForToken(this.tokenAtRelativeIndex(relativeIndex));
- }
- identifierName() {
- return this.identifierNameForToken(this.currentToken());
- }
- identifierNameForToken(token) {
- return this.code.slice(token.start, token.end);
- }
- rawCodeForToken(token) {
- return this.code.slice(token.start, token.end);
- }
- stringValueAtIndex(index) {
- return this.stringValueForToken(this.tokens[index]);
- }
- stringValue() {
- return this.stringValueForToken(this.currentToken());
- }
- stringValueForToken(token) {
- // This is used to identify when two imports are the same and to resolve TypeScript enum keys.
- // Ideally we'd process escapes within the strings, but for now we pretty much take the raw
- // code.
- return this.code.slice(token.start + 1, token.end - 1);
- }
- matches1AtIndex(index, t1) {
- return this.tokens[index].type === t1;
- }
- matches2AtIndex(index, t1, t2) {
- return this.tokens[index].type === t1 && this.tokens[index + 1].type === t2;
- }
- matches3AtIndex(index, t1, t2, t3) {
- return (
- this.tokens[index].type === t1 &&
- this.tokens[index + 1].type === t2 &&
- this.tokens[index + 2].type === t3
- );
- }
- matches1(t1) {
- return this.tokens[this.tokenIndex].type === t1;
- }
- matches2(t1, t2) {
- return this.tokens[this.tokenIndex].type === t1 && this.tokens[this.tokenIndex + 1].type === t2;
- }
- matches3(t1, t2, t3) {
- return (
- this.tokens[this.tokenIndex].type === t1 &&
- this.tokens[this.tokenIndex + 1].type === t2 &&
- this.tokens[this.tokenIndex + 2].type === t3
- );
- }
- matches4(t1, t2, t3, t4) {
- return (
- this.tokens[this.tokenIndex].type === t1 &&
- this.tokens[this.tokenIndex + 1].type === t2 &&
- this.tokens[this.tokenIndex + 2].type === t3 &&
- this.tokens[this.tokenIndex + 3].type === t4
- );
- }
- matches5(t1, t2, t3, t4, t5) {
- return (
- this.tokens[this.tokenIndex].type === t1 &&
- this.tokens[this.tokenIndex + 1].type === t2 &&
- this.tokens[this.tokenIndex + 2].type === t3 &&
- this.tokens[this.tokenIndex + 3].type === t4 &&
- this.tokens[this.tokenIndex + 4].type === t5
- );
- }
- matchesContextual(contextualKeyword) {
- return this.matchesContextualAtIndex(this.tokenIndex, contextualKeyword);
- }
- matchesContextIdAndLabel(type, contextId) {
- return this.matches1(type) && this.currentToken().contextId === contextId;
- }
- previousWhitespaceAndComments() {
- let whitespaceAndComments = this.code.slice(
- this.tokenIndex > 0 ? this.tokens[this.tokenIndex - 1].end : 0,
- this.tokenIndex < this.tokens.length ? this.tokens[this.tokenIndex].start : this.code.length,
- );
- if (this.isFlowEnabled) {
- whitespaceAndComments = whitespaceAndComments.replace(/@flow/g, "");
- }
- return whitespaceAndComments;
- }
- replaceToken(newCode) {
- this.resultCode += this.previousWhitespaceAndComments();
- this.appendTokenPrefix();
- this.resultMappings[this.tokenIndex] = this.resultCode.length;
- this.resultCode += newCode;
- this.appendTokenSuffix();
- this.tokenIndex++;
- }
- replaceTokenTrimmingLeftWhitespace(newCode) {
- this.resultCode += this.previousWhitespaceAndComments().replace(/[^\r\n]/g, "");
- this.appendTokenPrefix();
- this.resultMappings[this.tokenIndex] = this.resultCode.length;
- this.resultCode += newCode;
- this.appendTokenSuffix();
- this.tokenIndex++;
- }
- removeInitialToken() {
- this.replaceToken("");
- }
- removeToken() {
- this.replaceTokenTrimmingLeftWhitespace("");
- }
- /**
- * Remove all code until the next }, accounting for balanced braces.
- */
- removeBalancedCode() {
- let braceDepth = 0;
- while (!this.isAtEnd()) {
- if (this.matches1(_types.TokenType.braceL)) {
- braceDepth++;
- } else if (this.matches1(_types.TokenType.braceR)) {
- if (braceDepth === 0) {
- return;
- }
- braceDepth--;
- }
- this.removeToken();
- }
- }
- copyExpectedToken(tokenType) {
- if (this.tokens[this.tokenIndex].type !== tokenType) {
- throw new Error(`Expected token ${tokenType}`);
- }
- this.copyToken();
- }
- copyToken() {
- this.resultCode += this.previousWhitespaceAndComments();
- this.appendTokenPrefix();
- this.resultMappings[this.tokenIndex] = this.resultCode.length;
- this.resultCode += this.code.slice(
- this.tokens[this.tokenIndex].start,
- this.tokens[this.tokenIndex].end,
- );
- this.appendTokenSuffix();
- this.tokenIndex++;
- }
- copyTokenWithPrefix(prefix) {
- this.resultCode += this.previousWhitespaceAndComments();
- this.appendTokenPrefix();
- this.resultCode += prefix;
- this.resultMappings[this.tokenIndex] = this.resultCode.length;
- this.resultCode += this.code.slice(
- this.tokens[this.tokenIndex].start,
- this.tokens[this.tokenIndex].end,
- );
- this.appendTokenSuffix();
- this.tokenIndex++;
- }
- appendTokenPrefix() {
- const token = this.currentToken();
- if (token.numNullishCoalesceStarts || token.isOptionalChainStart) {
- token.isAsyncOperation = _isAsyncOperation2.default.call(void 0, this);
- }
- if (this.disableESTransforms) {
- return;
- }
- if (token.numNullishCoalesceStarts) {
- for (let i = 0; i < token.numNullishCoalesceStarts; i++) {
- if (token.isAsyncOperation) {
- this.resultCode += "await ";
- this.resultCode += this.helperManager.getHelperName("asyncNullishCoalesce");
- } else {
- this.resultCode += this.helperManager.getHelperName("nullishCoalesce");
- }
- this.resultCode += "(";
- }
- }
- if (token.isOptionalChainStart) {
- if (token.isAsyncOperation) {
- this.resultCode += "await ";
- }
- if (this.tokenIndex > 0 && this.tokenAtRelativeIndex(-1).type === _types.TokenType._delete) {
- if (token.isAsyncOperation) {
- this.resultCode += this.helperManager.getHelperName("asyncOptionalChainDelete");
- } else {
- this.resultCode += this.helperManager.getHelperName("optionalChainDelete");
- }
- } else if (token.isAsyncOperation) {
- this.resultCode += this.helperManager.getHelperName("asyncOptionalChain");
- } else {
- this.resultCode += this.helperManager.getHelperName("optionalChain");
- }
- this.resultCode += "([";
- }
- }
- appendTokenSuffix() {
- const token = this.currentToken();
- if (token.isOptionalChainEnd && !this.disableESTransforms) {
- this.resultCode += "])";
- }
- if (token.numNullishCoalesceEnds && !this.disableESTransforms) {
- for (let i = 0; i < token.numNullishCoalesceEnds; i++) {
- this.resultCode += "))";
- }
- }
- }
- appendCode(code) {
- this.resultCode += code;
- }
- currentToken() {
- return this.tokens[this.tokenIndex];
- }
- currentTokenCode() {
- const token = this.currentToken();
- return this.code.slice(token.start, token.end);
- }
- tokenAtRelativeIndex(relativeIndex) {
- return this.tokens[this.tokenIndex + relativeIndex];
- }
- currentIndex() {
- return this.tokenIndex;
- }
- /**
- * Move to the next token. Only suitable in preprocessing steps. When
- * generating new code, you should use copyToken or removeToken.
- */
- nextToken() {
- if (this.tokenIndex === this.tokens.length) {
- throw new Error("Unexpectedly reached end of input.");
- }
- this.tokenIndex++;
- }
- previousToken() {
- this.tokenIndex--;
- }
- finish() {
- if (this.tokenIndex !== this.tokens.length) {
- throw new Error("Tried to finish processing tokens before reaching the end.");
- }
- this.resultCode += this.previousWhitespaceAndComments();
- return {code: this.resultCode, mappings: this.resultMappings};
- }
- isAtEnd() {
- return this.tokenIndex === this.tokens.length;
- }
- } exports.default = TokenProcessor;
|