@@ -125,6 +125,21 @@ function throwEmptyError(locationCalculator: LocationCalculator, expected: strin
125125 throw err
126126}
127127
128+ /**
129+ * Throw syntax error of outside of code.
130+ * @param locationCalculator The location calculator to get line/column.
131+ */
132+ function throwErrorAsAdjustingOutsideOfCode ( err : any , code : string , locationCalculator : LocationCalculator ) : never {
133+ if ( ParseError . isParseError ( err ) ) {
134+ const endOffset = locationCalculator . getOffsetWithGap ( code . length )
135+ if ( err . index >= endOffset ) {
136+ err . message = "Unexpected end of expression."
137+ }
138+ }
139+
140+ throw err
141+ }
142+
128143/**
129144 * Parse the given source code.
130145 *
@@ -165,7 +180,6 @@ export interface ExpressionParseResult {
165180 */
166181export type ESLintCustomParserResult = ESLintProgram | ESLintExtendedProgram
167182
168-
169183/**
170184 * Parse the given source code.
171185 *
@@ -237,24 +251,29 @@ export function parseExpression(code: string, locationCalculator: LocationCalcul
237251 debug ( "[script] parse expression: \"(%s)\"" , code )
238252
239253 if ( code . trim ( ) === "" ) {
240- throwEmptyError ( locationCalculator , "an expression" )
254+ return throwEmptyError ( locationCalculator , "an expression" )
241255 }
242256
243- const ast = parseScriptFragment (
244- `(${ code } )` ,
245- locationCalculator . getSubCalculatorAfter ( - 1 ) ,
246- parserOptions
247- ) . ast
248- const references = analyzeExternalReferences ( ast , parserOptions )
249- const expression = ( ast . body [ 0 ] as ESLintExpressionStatement ) . expression
250- const tokens = ast . tokens || [ ]
251- const comments = ast . comments || [ ]
252-
253- // Remvoe parens.
254- tokens . shift ( )
255- tokens . pop ( )
256-
257- return { expression, tokens, comments, references, variables : [ ] }
257+ try {
258+ const ast = parseScriptFragment (
259+ `(${ code } )` ,
260+ locationCalculator . getSubCalculatorAfter ( - 1 ) ,
261+ parserOptions
262+ ) . ast
263+ const references = analyzeExternalReferences ( ast , parserOptions )
264+ const expression = ( ast . body [ 0 ] as ESLintExpressionStatement ) . expression
265+ const tokens = ast . tokens || [ ]
266+ const comments = ast . comments || [ ]
267+
268+ // Remvoe parens.
269+ tokens . shift ( )
270+ tokens . pop ( )
271+
272+ return { expression, tokens, comments, references, variables : [ ] }
273+ }
274+ catch ( err ) {
275+ return throwErrorAsAdjustingOutsideOfCode ( err , code , locationCalculator )
276+ }
258277}
259278
260279/**
@@ -272,61 +291,66 @@ export function parseVForExpression(code: string, locationCalculator: LocationCa
272291 throwEmptyError ( locationCalculator , "'<alias> in <expression>'" )
273292 }
274293
275- const replaced = processedCode !== code
276- const ast = parseScriptFragment (
277- `for(let ${ processedCode } );` ,
278- locationCalculator . getSubCalculatorAfter ( - 8 ) ,
279- parserOptions
280- ) . ast
281- const tokens = ast . tokens || [ ]
282- const comments = ast . comments || [ ]
283- const scope = analyzeVariablesAndExternalReferences ( ast , parserOptions )
284- const references = scope . references
285- const variables = scope . variables
286- const statement = ast . body [ 0 ] as ( ESLintForInStatement | ESLintForOfStatement )
287- const left = normalizeLeft ( statement . left , replaced )
288- const right = statement . right
289- const firstToken = tokens [ 3 ] || statement . left
290- const lastToken = tokens [ tokens . length - 3 ] || statement . right
291- const expression : VForExpression = {
292- type : "VForExpression" ,
293- range : [ firstToken . range [ 0 ] , lastToken . range [ 1 ] ] ,
294- loc : { start : firstToken . loc . start , end : lastToken . loc . end } ,
295- parent : DUMMY_PARENT ,
296- left,
297- right,
298- }
299-
300- // Modify parent.
301- for ( const l of left ) {
302- if ( l != null ) {
303- l . parent = expression
294+ try {
295+ const replaced = processedCode !== code
296+ const ast = parseScriptFragment (
297+ `for(let ${ processedCode } );` ,
298+ locationCalculator . getSubCalculatorAfter ( - 8 ) ,
299+ parserOptions
300+ ) . ast
301+ const tokens = ast . tokens || [ ]
302+ const comments = ast . comments || [ ]
303+ const scope = analyzeVariablesAndExternalReferences ( ast , parserOptions )
304+ const references = scope . references
305+ const variables = scope . variables
306+ const statement = ast . body [ 0 ] as ( ESLintForInStatement | ESLintForOfStatement )
307+ const left = normalizeLeft ( statement . left , replaced )
308+ const right = statement . right
309+ const firstToken = tokens [ 3 ] || statement . left
310+ const lastToken = tokens [ tokens . length - 3 ] || statement . right
311+ const expression : VForExpression = {
312+ type : "VForExpression" ,
313+ range : [ firstToken . range [ 0 ] , lastToken . range [ 1 ] ] ,
314+ loc : { start : firstToken . loc . start , end : lastToken . loc . end } ,
315+ parent : DUMMY_PARENT ,
316+ left,
317+ right,
304318 }
305- }
306- right . parent = expression
307-
308- // Remvoe `for` `(` `let` `)` `;`.
309- tokens . shift ( )
310- tokens . shift ( )
311- tokens . shift ( )
312- tokens . pop ( )
313- tokens . pop ( )
314319
315- // Restore parentheses from array brackets.
316- if ( replaced ) {
317- const closeOffset = statement . left . range [ 1 ] - 1
318- const open = tokens [ 0 ]
319- const close = tokens . find ( t => t . range [ 0 ] === closeOffset )
320-
321- if ( open != null ) {
322- open . value = "("
320+ // Modify parent.
321+ for ( const l of left ) {
322+ if ( l != null ) {
323+ l . parent = expression
324+ }
323325 }
324- if ( close != null ) {
325- close . value = ")"
326+ right . parent = expression
327+
328+ // Remvoe `for` `(` `let` `)` `;`.
329+ tokens . shift ( )
330+ tokens . shift ( )
331+ tokens . shift ( )
332+ tokens . pop ( )
333+ tokens . pop ( )
334+
335+ // Restore parentheses from array brackets.
336+ if ( replaced ) {
337+ const closeOffset = statement . left . range [ 1 ] - 1
338+ const open = tokens [ 0 ]
339+ const close = tokens . find ( t => t . range [ 0 ] === closeOffset )
340+
341+ if ( open != null ) {
342+ open . value = "("
343+ }
344+ if ( close != null ) {
345+ close . value = ")"
346+ }
326347 }
327- }
328348
329- return { expression, tokens, comments, references, variables}
349+ return { expression, tokens, comments, references, variables}
350+ }
351+ catch ( err ) {
352+ return throwErrorAsAdjustingOutsideOfCode ( err , code , locationCalculator )
353+ }
330354}
331355
332356/**
@@ -343,43 +367,48 @@ export function parseVOnExpression(code: string, locationCalculator: LocationCal
343367 throwEmptyError ( locationCalculator , "statements" )
344368 }
345369
346- const ast = parseScriptFragment (
347- `{${ code } }` ,
348- locationCalculator . getSubCalculatorAfter ( - 1 ) ,
349- parserOptions
350- ) . ast
351- const references = analyzeExternalReferences ( ast , parserOptions )
352- const block = ast . body [ 0 ] as ESLintBlockStatement
353- const body = block . body
354- const first = lodash . first ( body )
355- const last = lodash . last ( body )
356- const expression : VOnExpression = {
357- type : "VOnExpression" ,
358- range : [
359- ( first != null ) ? first . range [ 0 ] : block . range [ 0 ] + 1 ,
360- ( last != null ) ? last . range [ 1 ] : block . range [ 1 ] - 1 ,
361- ] ,
362- loc : {
363- start : ( first != null ) ? first . loc . start : locationCalculator . getLocation ( 1 ) ,
364- end : ( last != null ) ? last . loc . end : locationCalculator . getLocation ( code . length + 1 ) ,
365- } ,
366- parent : DUMMY_PARENT ,
367- body,
368- }
369- const tokens = ast . tokens || [ ]
370- const comments = ast . comments || [ ]
370+ try {
371+ const ast = parseScriptFragment (
372+ `{${ code } }` ,
373+ locationCalculator . getSubCalculatorAfter ( - 1 ) ,
374+ parserOptions
375+ ) . ast
376+ const references = analyzeExternalReferences ( ast , parserOptions )
377+ const block = ast . body [ 0 ] as ESLintBlockStatement
378+ const body = block . body
379+ const first = lodash . first ( body )
380+ const last = lodash . last ( body )
381+ const expression : VOnExpression = {
382+ type : "VOnExpression" ,
383+ range : [
384+ ( first != null ) ? first . range [ 0 ] : block . range [ 0 ] + 1 ,
385+ ( last != null ) ? last . range [ 1 ] : block . range [ 1 ] - 1 ,
386+ ] ,
387+ loc : {
388+ start : ( first != null ) ? first . loc . start : locationCalculator . getLocation ( 1 ) ,
389+ end : ( last != null ) ? last . loc . end : locationCalculator . getLocation ( code . length + 1 ) ,
390+ } ,
391+ parent : DUMMY_PARENT ,
392+ body,
393+ }
394+ const tokens = ast . tokens || [ ]
395+ const comments = ast . comments || [ ]
371396
372- // Modify parent.
373- for ( const b of body ) {
374- b . parent = expression
375- }
397+ // Modify parent.
398+ for ( const b of body ) {
399+ b . parent = expression
400+ }
376401
377- // Remvoe braces.
378- tokens . shift ( )
379- tokens . pop ( )
402+ // Remvoe braces.
403+ tokens . shift ( )
404+ tokens . pop ( )
380405
381- // Remove $event: https://vuejs.org/v2/api/#v-on
382- removeByName ( references , "$event" )
406+ // Remove $event: https://vuejs.org/v2/api/#v-on
407+ removeByName ( references , "$event" )
383408
384- return { expression, tokens, comments, references, variables : [ ] }
409+ return { expression, tokens, comments, references, variables : [ ] }
410+ }
411+ catch ( err ) {
412+ return throwErrorAsAdjustingOutsideOfCode ( err , code , locationCalculator )
413+ }
385414}
0 commit comments