// @flow import type { Options } from "../options"; import * as N from "../types"; import { Position } from "../util/location"; import { types as ct, type TokContext } from "./context"; import type { Token } from "./index"; import { types as tt, type TokenType, type TopicContextState } from "./types"; export default class State { init(options: Options, input: string): void { this.strict = options.strictMode === false ? false : options.sourceType === "module"; this.input = input; this.potentialArrowAt = -1; this.noArrowAt = []; this.noArrowParamsConversionAt = []; this.inMethod = false; this.inFunction = false; this.inParameters = false; this.maybeInArrowParameters = false; this.inGenerator = false; this.inAsync = false; this.inPipeline = false; this.inPropertyName = false; this.inType = false; this.inClassProperty = false; this.noAnonFunctionType = false; this.hasFlowComment = false; this.isIterator = false; // Used by smartPipelines. this.topicContext = { maxNumOfResolvableTopics: 0, maxTopicIndex: null, }; this.classLevel = 0; this.labels = []; this.decoratorStack = [[]]; this.yieldOrAwaitInPossibleArrowParameters = null; this.tokens = []; this.comments = []; this.trailingComments = []; this.leadingComments = []; this.commentStack = []; // $FlowIgnore this.commentPreviousNode = null; this.pos = this.lineStart = 0; this.curLine = options.startLine; this.type = tt.eof; this.value = null; this.start = this.end = this.pos; this.startLoc = this.endLoc = this.curPosition(); // $FlowIgnore this.lastTokEndLoc = this.lastTokStartLoc = null; this.lastTokStart = this.lastTokEnd = this.pos; this.context = [ct.braceStatement]; this.exprAllowed = true; this.containsEsc = this.containsOctal = false; this.octalPosition = null; this.invalidTemplateEscapePosition = null; this.exportedIdentifiers = []; } // TODO strict: boolean; // TODO input: string; // Used to signify the start of a potential arrow function potentialArrowAt: number; // Used to signify the start of an expression which looks like a // typed arrow function, but it isn't // e.g. a ? (b) : c => d // ^ noArrowAt: number[]; // Used to signify the start of an expression whose params, if it looks like // an arrow function, shouldn't be converted to assignable nodes. // This is used to defer the validation of typed arrow functions inside // conditional expressions. // e.g. a ? (b) : c => d // ^ noArrowParamsConversionAt: number[]; // Flags to track whether we are in a function, a generator. inFunction: boolean; inParameters: boolean; maybeInArrowParameters: boolean; inGenerator: boolean; inMethod: boolean | N.MethodKind; inAsync: boolean; inPipeline: boolean; inType: boolean; noAnonFunctionType: boolean; inPropertyName: boolean; inClassProperty: boolean; hasFlowComment: boolean; isIterator: boolean; // For the smartPipelines plugin: topicContext: TopicContextState; // Check whether we are in a (nested) class or not. classLevel: number; // Labels in scope. labels: Array<{ kind: ?("loop" | "switch"), name?: ?string, statementStart?: number, }>; // Leading decorators. Last element of the stack represents the decorators in current context. // Supports nesting of decorators, e.g. @foo(@bar class inner {}) class outer {} // where @foo belongs to the outer class and @bar to the inner decoratorStack: Array>; // The first yield or await expression inside parenthesized expressions // and arrow function parameters. It is used to disallow yield and await in // arrow function parameters. yieldOrAwaitInPossibleArrowParameters: | N.YieldExpression | N.AwaitExpression | null; // Token store. tokens: Array; // Comment store. comments: Array; // Comment attachment store trailingComments: Array; leadingComments: Array; commentStack: Array<{ start: number, leadingComments: ?Array, trailingComments: ?Array, type: string, }>; commentPreviousNode: N.Node; // The current position of the tokenizer in the input. pos: number; lineStart: number; curLine: number; // Properties of the current token: // Its type type: TokenType; // For tokens that include more information than their type, the value value: any; // Its start and end offset start: number; end: number; // And, if locations are used, the {line, column} object // corresponding to those offsets startLoc: Position; endLoc: Position; // Position information for the previous token lastTokEndLoc: Position; lastTokStartLoc: Position; lastTokStart: number; lastTokEnd: number; // The context stack is used to superficially track syntactic // context to predict whether a regular expression is allowed in a // given position. context: Array; exprAllowed: boolean; // Used to signal to callers of `readWord1` whether the word // contained any escape sequences. This is needed because words with // escape sequences must not be interpreted as keywords. containsEsc: boolean; // TODO containsOctal: boolean; octalPosition: ?number; // Names of exports store. `default` is stored as a name for both // `export default foo;` and `export { foo as default };`. exportedIdentifiers: Array; invalidTemplateEscapePosition: ?number; curPosition(): Position { return new Position(this.curLine, this.pos - this.lineStart); } clone(skipArrays?: boolean): State { const state = new State(); Object.keys(this).forEach(key => { // $FlowIgnore let val = this[key]; if ((!skipArrays || key === "context") && Array.isArray(val)) { val = val.slice(); } // $FlowIgnore state[key] = val; }); return state; } }