5656 */
5757/* eslint no-undefined:0, no-use-before-define: 0 */
5858
59+ // ----------------------------------------------------------------------------
60+ // Types exported from file
61+ // ----------------------------------------------------------------------------
62+ /**
63+ * `jsx.Options` gives us 2 optional properties, so extend it
64+ *
65+ * `allowReserved`, `ranges`, `locations`, `allowReturnOutsideFunction`,
66+ * `onToken`, and `onComment` are as in `acorn.Options`
67+ *
68+ * `ecmaVersion` as in `acorn.Options` though optional
69+ *
70+ * `sourceType` as in `acorn.Options` but also allows `commonjs`
71+ *
72+ * `ecmaFeatures`, `range`, `loc`, `tokens` are not in `acorn.Options`
73+ *
74+ * `comment` is not in `acorn.Options` and doesn't err without it, but is used
75+ * @typedef {{
76+ * allowReserved?: boolean | "never",
77+ * ranges?: boolean,
78+ * locations?: boolean,
79+ * allowReturnOutsideFunction?: boolean,
80+ * onToken?: ((token: acorn.Token) => any) | acorn.Token[],
81+ * onComment?: ((
82+ * isBlock: boolean, text: string, start: number, end: number, startLoc?: acorn.Position,
83+ * endLoc?: acorn.Position
84+ * ) => void) | acorn.Comment[],
85+ * ecmaVersion?: acorn.ecmaVersion,
86+ * sourceType?: "script"|"module"|"commonjs",
87+ * ecmaFeatures?: {
88+ * jsx?: boolean,
89+ * globalReturn?: boolean,
90+ * impliedStrict?: boolean
91+ * },
92+ * range?: boolean,
93+ * loc?: boolean,
94+ * tokens?: boolean | null,
95+ * comment?: boolean,
96+ * } & jsx.Options } ParserOptions
97+ */
98+
99+ // ----------------------------------------------------------------------------
100+ // Local type imports
101+ // ----------------------------------------------------------------------------
102+ /**
103+ * @local
104+ * @typedef {import('acorn') } acorn
105+ * @typedef {typeof import('acorn-jsx').AcornJsxParser } AcornJsxParser
106+ * @typedef {import('./lib/espree').EnhancedSyntaxError } EnhancedSyntaxError
107+ * @typedef {typeof import('./lib/espree').EspreeParser } IEspreeParser
108+ */
109+
59110import * as acorn from "acorn" ;
60111import jsx from "acorn-jsx" ;
61112import espree from "./lib/espree.js" ;
@@ -66,23 +117,43 @@ import { getLatestEcmaVersion, getSupportedEcmaVersions } from "./lib/options.js
66117
67118// To initialize lazily.
68119const parsers = {
69- _regular : null ,
70- _jsx : null ,
120+ _regular : /** @type { IEspreeParser| null} */ ( null ) ,
121+ _jsx : /** @type { IEspreeParser| null} */ ( null ) ,
71122
123+ /**
124+ * Returns regular Parser
125+ * @returns {IEspreeParser } Regular Acorn parser
126+ */
72127 get regular ( ) {
73128 if ( this . _regular === null ) {
74- this . _regular = acorn . Parser . extend ( espree ( ) ) ;
129+ const espreeParserFactory = espree ( ) ;
130+
131+ // Cast the `acorn.Parser` to our own for required properties not specified in *.d.ts
132+ this . _regular = espreeParserFactory ( /** @type {AcornJsxParser } */ ( acorn . Parser ) ) ;
75133 }
76134 return this . _regular ;
77135 } ,
78136
137+ /**
138+ * Returns JSX Parser
139+ * @returns {IEspreeParser } JSX Acorn parser
140+ */
79141 get jsx ( ) {
80142 if ( this . _jsx === null ) {
81- this . _jsx = acorn . Parser . extend ( jsx ( ) , espree ( ) ) ;
143+ const espreeParserFactory = espree ( ) ;
144+ const jsxFactory = jsx ( ) ;
145+
146+ // Cast the `acorn.Parser` to our own for required properties not specified in *.d.ts
147+ this . _jsx = espreeParserFactory ( jsxFactory ( acorn . Parser ) ) ;
82148 }
83149 return this . _jsx ;
84150 } ,
85151
152+ /**
153+ * Returns Regular or JSX Parser
154+ * @param {ParserOptions } options Parser options
155+ * @returns {IEspreeParser } Regular or JSX Acorn parser
156+ */
86157 get ( options ) {
87158 const useJsx = Boolean (
88159 options &&
@@ -101,9 +172,9 @@ const parsers = {
101172/**
102173 * Tokenizes the given code.
103174 * @param {string } code The code to tokenize.
104- * @param {Object } options Options defining how to tokenize.
105- * @returns {Token[] } An array of tokens.
106- * @throws {SyntaxError } If the input code is invalid.
175+ * @param {ParserOptions } options Options defining how to tokenize.
176+ * @returns {acorn. Token[]|null } An array of tokens.
177+ * @throws {EnhancedSyntaxError } If the input code is invalid.
107178 * @private
108179 */
109180export function tokenize ( code , options ) {
@@ -124,9 +195,9 @@ export function tokenize(code, options) {
124195/**
125196 * Parses the given code.
126197 * @param {string } code The code to tokenize.
127- * @param {Object } options Options defining how to tokenize.
128- * @returns {ASTNode } The "Program" AST node.
129- * @throws {SyntaxError } If the input code is invalid.
198+ * @param {ParserOptions } options Options defining how to tokenize.
199+ * @returns {acorn.Node } The "Program" AST node.
200+ * @throws {EnhancedSyntaxError } If the input code is invalid.
130201 */
131202export function parse ( code , options ) {
132203 const Parser = parsers . get ( options ) ;
@@ -148,17 +219,15 @@ export const VisitorKeys = (function() {
148219// Derive node types from VisitorKeys
149220/* istanbul ignore next */
150221export const Syntax = ( function ( ) {
151- let name ,
222+ let /** @type { Object<string,string> } */
152223 types = { } ;
153224
154225 if ( typeof Object . create === "function" ) {
155226 types = Object . create ( null ) ;
156227 }
157228
158- for ( name in VisitorKeys ) {
159- if ( Object . hasOwnProperty . call ( VisitorKeys , name ) ) {
160- types [ name ] = name ;
161- }
229+ for ( const name of Object . keys ( VisitorKeys ) ) {
230+ types [ name ] = name ;
162231 }
163232
164233 if ( typeof Object . freeze === "function" ) {
0 commit comments