@@ -125,6 +125,21 @@ function throwEmptyError(locationCalculator: LocationCalculator, expected: strin
125
125
throw err
126
126
}
127
127
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
+
128
143
/**
129
144
* Parse the given source code.
130
145
*
@@ -165,7 +180,6 @@ export interface ExpressionParseResult {
165
180
*/
166
181
export type ESLintCustomParserResult = ESLintProgram | ESLintExtendedProgram
167
182
168
-
169
183
/**
170
184
* Parse the given source code.
171
185
*
@@ -237,24 +251,29 @@ export function parseExpression(code: string, locationCalculator: LocationCalcul
237
251
debug ( "[script] parse expression: \"(%s)\"" , code )
238
252
239
253
if ( code . trim ( ) === "" ) {
240
- throwEmptyError ( locationCalculator , "an expression" )
254
+ return throwEmptyError ( locationCalculator , "an expression" )
241
255
}
242
256
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
+ }
258
277
}
259
278
260
279
/**
@@ -272,61 +291,66 @@ export function parseVForExpression(code: string, locationCalculator: LocationCa
272
291
throwEmptyError ( locationCalculator , "'<alias> in <expression>'" )
273
292
}
274
293
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,
304
318
}
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 ( )
314
319
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
+ }
323
325
}
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
+ }
326
347
}
327
- }
328
348
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
+ }
330
354
}
331
355
332
356
/**
@@ -343,43 +367,48 @@ export function parseVOnExpression(code: string, locationCalculator: LocationCal
343
367
throwEmptyError ( locationCalculator , "statements" )
344
368
}
345
369
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 || [ ]
371
396
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
+ }
376
401
377
- // Remvoe braces.
378
- tokens . shift ( )
379
- tokens . pop ( )
402
+ // Remvoe braces.
403
+ tokens . shift ( )
404
+ tokens . pop ( )
380
405
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" )
383
408
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
+ }
385
414
}
0 commit comments