diff --git a/packages/babel-parser/benchmark/many-arrow-function-flow-types/bench.mjs b/packages/babel-parser/benchmark/many-arrow-function-flow-types/bench.mjs new file mode 100644 index 000000000000..b57eee28f278 --- /dev/null +++ b/packages/babel-parser/benchmark/many-arrow-function-flow-types/bench.mjs @@ -0,0 +1,22 @@ +import Benchmark from "benchmark"; +import baseline from "@babel-baseline/parser"; +import current from "../../lib/index.js"; +import { report } from "../util.mjs"; + +const suite = new Benchmark.Suite(); +function createInput(length) { + return "type A = " + "| (x) => void".repeat(length); +} +function benchCases(name, implementation, options) { + for (const length of [256, 512, 1024, 2048]) { + const input = createInput(length); + suite.add(`${name} ${length} arrow function types`, () => { + implementation.parse(input, options); + }); + } +} + +benchCases("baseline", baseline, { plugins: ["flow"] }); +benchCases("current", current, { plugins: ["flow"] }); + +suite.on("cycle", report).run(); diff --git a/packages/babel-parser/src/plugins/flow/index.js b/packages/babel-parser/src/plugins/flow/index.js index d9c3c33b94db..7addd6523824 100644 --- a/packages/babel-parser/src/plugins/flow/index.js +++ b/packages/babel-parser/src/plugins/flow/index.js @@ -9,7 +9,6 @@ import type Parser from "../../parser"; import { types as tt, type TokenType } from "../../tokenizer/types"; import * as N from "../../types"; import type { Pos, Position } from "../../util/location"; -import type State from "../../tokenizer/state"; import { types as tc } from "../../tokenizer/context"; import * as charCodes from "charcodes"; import { isIteratorStart, isKeyword } from "../../util/identifier"; @@ -154,7 +153,7 @@ function hasTypeImportKind(node: N.Node): boolean { return node.importKind === "type" || node.importKind === "typeof"; } -function isMaybeDefaultImport(state: State): boolean { +function isMaybeDefaultImport(state: { type: TokenType, value: any }): boolean { return ( (state.type === tt.name || !!state.type.keyword) && state.value !== "from" ); diff --git a/packages/babel-parser/src/plugins/jsx/index.js b/packages/babel-parser/src/plugins/jsx/index.js index 45da3e7873a2..02a7a04f0492 100644 --- a/packages/babel-parser/src/plugins/jsx/index.js +++ b/packages/babel-parser/src/plugins/jsx/index.js @@ -15,6 +15,10 @@ import { isIdentifierChar, isIdentifierStart } from "../../util/identifier"; import type { Position } from "../../util/location"; import { isNewLine } from "../../util/whitespace"; import { Errors, makeErrorTemplates, ErrorCodes } from "../../parser/error"; +import type { LookaheadState } from "../../tokenizer/state"; +import State from "../../tokenizer/state"; + +type JSXLookaheadState = LookaheadState & { inPropertyName: boolean }; const HEX_NUMBER = /^[\da-fA-F]+$/; const DECIMAL_NUMBER = /^\d+$/; @@ -573,6 +577,14 @@ export default (superClass: Class): Class => } } + createLookaheadState(state: State): JSXLookaheadState { + const lookaheadState = ((super.createLookaheadState( + state, + ): any): JSXLookaheadState); + lookaheadState.inPropertyName = state.inPropertyName; + return lookaheadState; + } + getTokenFromCode(code: number): void { if (this.state.inPropertyName) return super.getTokenFromCode(code); diff --git a/packages/babel-parser/src/tokenizer/context.js b/packages/babel-parser/src/tokenizer/context.js index 854db1ccbfe5..bf07dba9e5ac 100644 --- a/packages/babel-parser/src/tokenizer/context.js +++ b/packages/babel-parser/src/tokenizer/context.js @@ -7,22 +7,15 @@ import { types as tt } from "./types"; export class TokContext { - constructor( - token: string, - isExpr?: boolean, - preserveSpace?: boolean, - override?: ?Function, // Takes a Tokenizer as a this-parameter, and returns void. - ) { + constructor(token: string, isExpr?: boolean, preserveSpace?: boolean) { this.token = token; this.isExpr = !!isExpr; this.preserveSpace = !!preserveSpace; - this.override = override; } token: string; isExpr: boolean; preserveSpace: boolean; - override: ?Function; } export const types: { @@ -34,7 +27,7 @@ export const types: { templateQuasi: new TokContext("${", false), parenStatement: new TokContext("(", false), parenExpression: new TokContext("(", true), - template: new TokContext("`", true, true, p => p.readTmplToken()), + template: new TokContext("`", true, true), functionExpression: new TokContext("function", true), functionStatement: new TokContext("function", false), }; diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index f89193432916..524d05a694e9 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -19,6 +19,7 @@ import { skipWhiteSpace, } from "../util/whitespace"; import State from "./state"; +import type { LookaheadState } from "./state"; const VALID_REGEX_FLAGS = new Set(["g", "m", "s", "i", "y", "u"]); @@ -144,11 +145,9 @@ export default class Tokenizer extends ParserErrors { // Move to the next token next(): void { - if (!this.isLookahead) { - this.checkKeywordEscapes(); - if (this.options.tokens) { - this.pushToken(new Token(this.state)); - } + this.checkKeywordEscapes(); + if (this.options.tokens) { + this.pushToken(new Token(this.state)); } this.state.lastTokEnd = this.state.end; @@ -175,14 +174,51 @@ export default class Tokenizer extends ParserErrors { return this.state.type === type; } - // TODO + /** + * Create a LookaheadState from current parser state + * + * @param {State} state + * @returns {LookaheadState} + * @memberof Tokenizer + */ + createLookaheadState(state: State): LookaheadState { + return { + pos: state.pos, + value: null, + type: state.type, + start: state.start, + end: state.end, + lastTokEnd: state.end, + context: [this.curContext()], + exprAllowed: state.exprAllowed, + inType: state.inType, + }; + } - lookahead(): State { + /** + * lookahead peeks the next token, skipping changes to token context and + * comment stack. For performance it returns a limited LookaheadState + * instead of full parser state. + * + * The { column, line } Loc info is not included in lookahead since such usage + * is rare. Although it may return other location properties e.g. `curLine` and + * `lineStart`, these properties are not listed in the LookaheadState interface + * and thus the returned value is _NOT_ reliable. + * + * The tokenizer should make best efforts to avoid using any parser state + * other than those defined in LookaheadState + * + * @returns {LookaheadState} + * @memberof Tokenizer + */ + lookahead(): LookaheadState { const old = this.state; - this.state = old.clone(true); + // For performance we use a simpified tokenizer state structure + // $FlowIgnore + this.state = this.createLookaheadState(old); this.isLookahead = true; - this.next(); + this.nextToken(); this.isLookahead = false; const curr = this.state; @@ -247,17 +283,16 @@ export default class Tokenizer extends ParserErrors { nextToken(): void { const curContext = this.curContext(); - if (!curContext?.preserveSpace) this.skipSpace(); + if (!curContext.preserveSpace) this.skipSpace(); this.state.start = this.state.pos; - this.state.startLoc = this.state.curPosition(); + if (!this.isLookahead) this.state.startLoc = this.state.curPosition(); if (this.state.pos >= this.length) { this.finishToken(tt.eof); return; } - const override = curContext?.override; - if (override) { - override(this); + if (curContext === ct.template) { + this.readTmplToken(); } else { this.getTokenFromCode(this.codePointAtPos(this.state.pos)); } @@ -285,7 +320,8 @@ export default class Tokenizer extends ParserErrors { } skipBlockComment(): void { - const startLoc = this.state.curPosition(); + let startLoc; + if (!this.isLookahead) startLoc = this.state.curPosition(); const start = this.state.pos; const end = this.input.indexOf("*/", this.state.pos + 2); if (end === -1) throw this.raise(start, Errors.UnterminatedComment); @@ -304,6 +340,7 @@ export default class Tokenizer extends ParserErrors { // If we are doing a lookahead right now we need to advance the position (above code) // but we do not want to push the comment to the state. if (this.isLookahead) return; + /*:: invariant(startLoc) */ this.pushComment( true, @@ -317,7 +354,8 @@ export default class Tokenizer extends ParserErrors { skipLineComment(startSkip: number): void { const start = this.state.pos; - const startLoc = this.state.curPosition(); + let startLoc; + if (!this.isLookahead) startLoc = this.state.curPosition(); let ch = this.input.charCodeAt((this.state.pos += startSkip)); if (this.state.pos < this.length) { while (!isNewLine(ch) && ++this.state.pos < this.length) { @@ -328,6 +366,7 @@ export default class Tokenizer extends ParserErrors { // If we are doing a lookahead right now we need to advance the position (above code) // but we do not want to push the comment to the state. if (this.isLookahead) return; + /*:: invariant(startLoc) */ this.pushComment( false, @@ -398,12 +437,14 @@ export default class Tokenizer extends ParserErrors { finishToken(type: TokenType, val: any): void { this.state.end = this.state.pos; - this.state.endLoc = this.state.curPosition(); const prevType = this.state.type; this.state.type = type; this.state.value = val; - if (!this.isLookahead) this.updateContext(prevType); + if (!this.isLookahead) { + this.state.endLoc = this.state.curPosition(); + this.updateContext(prevType); + } } // ### Token reading diff --git a/packages/babel-parser/src/tokenizer/state.js b/packages/babel-parser/src/tokenizer/state.js index 9eb9c533d07b..ed6c90c7abb9 100644 --- a/packages/babel-parser/src/tokenizer/state.js +++ b/packages/babel-parser/src/tokenizer/state.js @@ -178,3 +178,14 @@ export default class State { return state; } } + +export type LookaheadState = { + pos: number, + value: any, + type: TokenType, + start: number, + end: number, + /* Used only in readSlashToken */ + exprAllowed: boolean, + inType: boolean, +}; diff --git a/packages/babel-parser/test/fixtures/typescript/export/internal-comments/input.ts b/packages/babel-parser/test/fixtures/typescript/export/internal-comments/input.ts new file mode 100644 index 000000000000..452d10253f21 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/internal-comments/input.ts @@ -0,0 +1,2 @@ +/*1*/ export /*2*/ { /*3*/ A /*4*/, /*5*/ B /*6*/ as /*7*/ C /*8*/ } /*9*/ from /*10*/ "foo"; +/*1*/ export /*2*/ * /*3*/ from /*4*/ "foo" diff --git a/packages/babel-parser/test/fixtures/typescript/export/internal-comments/output.json b/packages/babel-parser/test/fixtures/typescript/export/internal-comments/output.json new file mode 100644 index 000000000000..3bea67d601ae --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/export/internal-comments/output.json @@ -0,0 +1,242 @@ +{ + "type": "File", + "start":0,"end":137,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":43}}, + "program": { + "type": "Program", + "start":0,"end":137,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":43}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":6,"end":93,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":93}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "1", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": "1", + "start":94,"end":99,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5}} + } + ], + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "2", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":18}} + }, + { + "type": "CommentBlock", + "value": "3", + "start":21,"end":26,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":26}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": "4", + "start":29,"end":34,"loc":{"start":{"line":1,"column":29},"end":{"line":1,"column":34}} + }, + { + "type": "CommentBlock", + "value": "5", + "start":36,"end":41,"loc":{"start":{"line":1,"column":36},"end":{"line":1,"column":41}} + } + ], + "local": { + "type": "Identifier", + "start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28},"identifierName":"A"}, + "name": "A" + }, + "exported": { + "type": "Identifier", + "start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28},"identifierName":"A"}, + "name": "A" + } + }, + { + "type": "ExportSpecifier", + "start":42,"end":60,"loc":{"start":{"line":1,"column":42},"end":{"line":1,"column":60}}, + "trailingComments": [ + { + "type": "CommentBlock", + "value": "8", + "start":61,"end":66,"loc":{"start":{"line":1,"column":61},"end":{"line":1,"column":66}} + }, + { + "type": "CommentBlock", + "value": "9", + "start":69,"end":74,"loc":{"start":{"line":1,"column":69},"end":{"line":1,"column":74}} + }, + { + "type": "CommentBlock", + "value": "10", + "start":80,"end":86,"loc":{"start":{"line":1,"column":80},"end":{"line":1,"column":86}} + } + ], + "local": { + "type": "Identifier", + "start":42,"end":43,"loc":{"start":{"line":1,"column":42},"end":{"line":1,"column":43},"identifierName":"B"}, + "trailingComments": [ + { + "type": "CommentBlock", + "value": "6", + "start":44,"end":49,"loc":{"start":{"line":1,"column":44},"end":{"line":1,"column":49}} + } + ], + "name": "B" + }, + "exported": { + "type": "Identifier", + "start":59,"end":60,"loc":{"start":{"line":1,"column":59},"end":{"line":1,"column":60},"identifierName":"C"}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "6", + "start":44,"end":49,"loc":{"start":{"line":1,"column":44},"end":{"line":1,"column":49}} + }, + { + "type": "CommentBlock", + "value": "7", + "start":53,"end":58,"loc":{"start":{"line":1,"column":53},"end":{"line":1,"column":58}} + } + ], + "name": "C" + } + } + ], + "source": { + "type": "StringLiteral", + "start":87,"end":92,"loc":{"start":{"line":1,"column":87},"end":{"line":1,"column":92}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + }, + "declaration": null + }, + { + "type": "ExportAllDeclaration", + "start":100,"end":137,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":43}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "1", + "start":94,"end":99,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5}} + } + ], + "exportKind": "value", + "source": { + "type": "StringLiteral", + "start":132,"end":137,"loc":{"start":{"line":2,"column":38},"end":{"line":2,"column":43}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "2", + "start":107,"end":112,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":18}} + }, + { + "type": "CommentBlock", + "value": "3", + "start":115,"end":120,"loc":{"start":{"line":2,"column":21},"end":{"line":2,"column":26}} + }, + { + "type": "CommentBlock", + "value": "4", + "start":126,"end":131,"loc":{"start":{"line":2,"column":32},"end":{"line":2,"column":37}} + } + ], + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": "1", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}} + }, + { + "type": "CommentBlock", + "value": "2", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":18}} + }, + { + "type": "CommentBlock", + "value": "3", + "start":21,"end":26,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":26}} + }, + { + "type": "CommentBlock", + "value": "4", + "start":29,"end":34,"loc":{"start":{"line":1,"column":29},"end":{"line":1,"column":34}} + }, + { + "type": "CommentBlock", + "value": "5", + "start":36,"end":41,"loc":{"start":{"line":1,"column":36},"end":{"line":1,"column":41}} + }, + { + "type": "CommentBlock", + "value": "6", + "start":44,"end":49,"loc":{"start":{"line":1,"column":44},"end":{"line":1,"column":49}} + }, + { + "type": "CommentBlock", + "value": "7", + "start":53,"end":58,"loc":{"start":{"line":1,"column":53},"end":{"line":1,"column":58}} + }, + { + "type": "CommentBlock", + "value": "8", + "start":61,"end":66,"loc":{"start":{"line":1,"column":61},"end":{"line":1,"column":66}} + }, + { + "type": "CommentBlock", + "value": "9", + "start":69,"end":74,"loc":{"start":{"line":1,"column":69},"end":{"line":1,"column":74}} + }, + { + "type": "CommentBlock", + "value": "10", + "start":80,"end":86,"loc":{"start":{"line":1,"column":80},"end":{"line":1,"column":86}} + }, + { + "type": "CommentBlock", + "value": "1", + "start":94,"end":99,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5}} + }, + { + "type": "CommentBlock", + "value": "2", + "start":107,"end":112,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":18}} + }, + { + "type": "CommentBlock", + "value": "3", + "start":115,"end":120,"loc":{"start":{"line":2,"column":21},"end":{"line":2,"column":26}} + }, + { + "type": "CommentBlock", + "value": "4", + "start":126,"end":131,"loc":{"start":{"line":2,"column":32},"end":{"line":2,"column":37}} + } + ] +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/import/internal-comments/input.ts b/packages/babel-parser/test/fixtures/typescript/import/internal-comments/input.ts new file mode 100644 index 000000000000..98b18ec15218 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/internal-comments/input.ts @@ -0,0 +1,2 @@ +/*1*/ import /*2*/ D /*3*/, /*4*/ { /*5*/ A /*6*/, /*7*/ B /*8*/ as /*9*/ C /*10*/ } /*11*/ from /*12*/ "foo"; +/*1*/ import /*2*/ * /*3*/ as /*4*/ foo /*5*/ from /*6*/ "foo"; diff --git a/packages/babel-parser/test/fixtures/typescript/import/internal-comments/output.json b/packages/babel-parser/test/fixtures/typescript/import/internal-comments/output.json new file mode 100644 index 000000000000..909242f2af20 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/import/internal-comments/output.json @@ -0,0 +1,331 @@ +{ + "type": "File", + "start":0,"end":174,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":63}}, + "program": { + "type": "Program", + "start":0,"end":174,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":63}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":6,"end":110,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":110}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "1", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": "1", + "start":111,"end":116,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5}} + } + ], + "importKind": "value", + "specifiers": [ + { + "type": "ImportDefaultSpecifier", + "start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "2", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":18}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": "3", + "start":21,"end":26,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":26}} + } + ], + "local": { + "type": "Identifier", + "start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20},"identifierName":"D"}, + "name": "D" + } + }, + { + "type": "ImportSpecifier", + "start":42,"end":43,"loc":{"start":{"line":1,"column":42},"end":{"line":1,"column":43}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "1", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}} + }, + { + "type": "CommentBlock", + "value": "2", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":18}} + }, + { + "type": "CommentBlock", + "value": "3", + "start":21,"end":26,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":26}} + }, + { + "type": "CommentBlock", + "value": "4", + "start":28,"end":33,"loc":{"start":{"line":1,"column":28},"end":{"line":1,"column":33}} + }, + { + "type": "CommentBlock", + "value": "5", + "start":36,"end":41,"loc":{"start":{"line":1,"column":36},"end":{"line":1,"column":41}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": "6", + "start":44,"end":49,"loc":{"start":{"line":1,"column":44},"end":{"line":1,"column":49}} + }, + { + "type": "CommentBlock", + "value": "7", + "start":51,"end":56,"loc":{"start":{"line":1,"column":51},"end":{"line":1,"column":56}} + } + ], + "imported": { + "type": "Identifier", + "start":42,"end":43,"loc":{"start":{"line":1,"column":42},"end":{"line":1,"column":43},"identifierName":"A"}, + "name": "A" + }, + "local": { + "type": "Identifier", + "start":42,"end":43,"loc":{"start":{"line":1,"column":42},"end":{"line":1,"column":43},"identifierName":"A"}, + "name": "A" + } + }, + { + "type": "ImportSpecifier", + "start":57,"end":75,"loc":{"start":{"line":1,"column":57},"end":{"line":1,"column":75}}, + "trailingComments": [ + { + "type": "CommentBlock", + "value": "10", + "start":76,"end":82,"loc":{"start":{"line":1,"column":76},"end":{"line":1,"column":82}} + }, + { + "type": "CommentBlock", + "value": "11", + "start":85,"end":91,"loc":{"start":{"line":1,"column":85},"end":{"line":1,"column":91}} + }, + { + "type": "CommentBlock", + "value": "12", + "start":97,"end":103,"loc":{"start":{"line":1,"column":97},"end":{"line":1,"column":103}} + } + ], + "imported": { + "type": "Identifier", + "start":57,"end":58,"loc":{"start":{"line":1,"column":57},"end":{"line":1,"column":58},"identifierName":"B"}, + "trailingComments": [ + { + "type": "CommentBlock", + "value": "8", + "start":59,"end":64,"loc":{"start":{"line":1,"column":59},"end":{"line":1,"column":64}} + } + ], + "name": "B" + }, + "local": { + "type": "Identifier", + "start":74,"end":75,"loc":{"start":{"line":1,"column":74},"end":{"line":1,"column":75},"identifierName":"C"}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "8", + "start":59,"end":64,"loc":{"start":{"line":1,"column":59},"end":{"line":1,"column":64}} + }, + { + "type": "CommentBlock", + "value": "9", + "start":68,"end":73,"loc":{"start":{"line":1,"column":68},"end":{"line":1,"column":73}} + } + ], + "name": "C" + } + } + ], + "source": { + "type": "StringLiteral", + "start":104,"end":109,"loc":{"start":{"line":1,"column":104},"end":{"line":1,"column":109}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + }, + { + "type": "ImportDeclaration", + "start":117,"end":174,"loc":{"start":{"line":2,"column":6},"end":{"line":2,"column":63}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "1", + "start":111,"end":116,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5}} + } + ], + "importKind": "value", + "specifiers": [ + { + "type": "ImportNamespaceSpecifier", + "start":130,"end":150,"loc":{"start":{"line":2,"column":19},"end":{"line":2,"column":39}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "2", + "start":124,"end":129,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":18}} + } + ], + "trailingComments": [ + { + "type": "CommentBlock", + "value": "5", + "start":151,"end":156,"loc":{"start":{"line":2,"column":40},"end":{"line":2,"column":45}} + } + ], + "local": { + "type": "Identifier", + "start":147,"end":150,"loc":{"start":{"line":2,"column":36},"end":{"line":2,"column":39},"identifierName":"foo"}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "3", + "start":132,"end":137,"loc":{"start":{"line":2,"column":21},"end":{"line":2,"column":26}} + }, + { + "type": "CommentBlock", + "value": "4", + "start":141,"end":146,"loc":{"start":{"line":2,"column":30},"end":{"line":2,"column":35}} + } + ], + "name": "foo" + } + } + ], + "source": { + "type": "StringLiteral", + "start":168,"end":173,"loc":{"start":{"line":2,"column":57},"end":{"line":2,"column":62}}, + "leadingComments": [ + { + "type": "CommentBlock", + "value": "5", + "start":151,"end":156,"loc":{"start":{"line":2,"column":40},"end":{"line":2,"column":45}} + }, + { + "type": "CommentBlock", + "value": "6", + "start":162,"end":167,"loc":{"start":{"line":2,"column":51},"end":{"line":2,"column":56}} + } + ], + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "directives": [] + }, + "comments": [ + { + "type": "CommentBlock", + "value": "1", + "start":0,"end":5,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":5}} + }, + { + "type": "CommentBlock", + "value": "2", + "start":13,"end":18,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":18}} + }, + { + "type": "CommentBlock", + "value": "3", + "start":21,"end":26,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":26}} + }, + { + "type": "CommentBlock", + "value": "4", + "start":28,"end":33,"loc":{"start":{"line":1,"column":28},"end":{"line":1,"column":33}} + }, + { + "type": "CommentBlock", + "value": "5", + "start":36,"end":41,"loc":{"start":{"line":1,"column":36},"end":{"line":1,"column":41}} + }, + { + "type": "CommentBlock", + "value": "6", + "start":44,"end":49,"loc":{"start":{"line":1,"column":44},"end":{"line":1,"column":49}} + }, + { + "type": "CommentBlock", + "value": "7", + "start":51,"end":56,"loc":{"start":{"line":1,"column":51},"end":{"line":1,"column":56}} + }, + { + "type": "CommentBlock", + "value": "8", + "start":59,"end":64,"loc":{"start":{"line":1,"column":59},"end":{"line":1,"column":64}} + }, + { + "type": "CommentBlock", + "value": "9", + "start":68,"end":73,"loc":{"start":{"line":1,"column":68},"end":{"line":1,"column":73}} + }, + { + "type": "CommentBlock", + "value": "10", + "start":76,"end":82,"loc":{"start":{"line":1,"column":76},"end":{"line":1,"column":82}} + }, + { + "type": "CommentBlock", + "value": "11", + "start":85,"end":91,"loc":{"start":{"line":1,"column":85},"end":{"line":1,"column":91}} + }, + { + "type": "CommentBlock", + "value": "12", + "start":97,"end":103,"loc":{"start":{"line":1,"column":97},"end":{"line":1,"column":103}} + }, + { + "type": "CommentBlock", + "value": "1", + "start":111,"end":116,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":5}} + }, + { + "type": "CommentBlock", + "value": "2", + "start":124,"end":129,"loc":{"start":{"line":2,"column":13},"end":{"line":2,"column":18}} + }, + { + "type": "CommentBlock", + "value": "3", + "start":132,"end":137,"loc":{"start":{"line":2,"column":21},"end":{"line":2,"column":26}} + }, + { + "type": "CommentBlock", + "value": "4", + "start":141,"end":146,"loc":{"start":{"line":2,"column":30},"end":{"line":2,"column":35}} + }, + { + "type": "CommentBlock", + "value": "5", + "start":151,"end":156,"loc":{"start":{"line":2,"column":40},"end":{"line":2,"column":45}} + }, + { + "type": "CommentBlock", + "value": "6", + "start":162,"end":167,"loc":{"start":{"line":2,"column":51},"end":{"line":2,"column":56}} + } + ] +} \ No newline at end of file