11import {
22 type ASTWithSource ,
33 Lexer ,
4+ ParseError ,
45 ParseLocation ,
56 Parser ,
67 ParseSourceFile ,
@@ -11,16 +12,29 @@ import {
1112import { type CommentLine } from './types.ts' ;
1213import { sourceSpanToLocationInformation } from './utils.ts' ;
1314
14- let parseSourceSpan : ParseSourceSpan ;
15- // https://github.com/angular/angular/blob/5e9707dc84e6590ec8c9d41e7d3be7deb2fa7c53/packages/compiler/test/expression_parser/utils/span.ts
16- function getParseSourceSpan ( ) {
17- if ( ! parseSourceSpan ) {
18- const file = new ParseSourceFile ( '' , 'test.html' ) ;
19- const location = new ParseLocation ( file , - 1 , - 1 , - 1 ) ;
20- parseSourceSpan = new ParseSourceSpan ( location , location ) ;
21- }
15+ const FILE_NAME = 'test.html' ;
16+
17+ type ParseContext = {
18+ text : string ;
19+ file : ParseSourceFile ;
20+ start : ParseLocation ;
21+ end : ParseLocation ;
22+ sourceSpan : ParseSourceSpan ;
23+ } ;
2224
23- return parseSourceSpan ;
25+ // https://github.com/angular/angular/blob/5e9707dc84e6590ec8c9d41e7d3be7deb2fa7c53/packages/compiler/test/expression_parser/utils/span.ts
26+ function getParseSourceSpan ( text : string ) : ParseContext {
27+ const file = new ParseSourceFile ( text , FILE_NAME ) ;
28+ const start = new ParseLocation ( file , 0 , 0 , 0 ) ;
29+ const end = start . moveBy ( text . length ) ;
30+ const sourceSpan = new ParseSourceSpan ( start , end ) ;
31+ return {
32+ text,
33+ file,
34+ start,
35+ end,
36+ sourceSpan,
37+ } ;
2438}
2539
2640let parser : Parser ;
@@ -53,15 +67,50 @@ function extractComments(text: string) {
5367
5468function throwErrors <
5569 ResultType extends ASTWithSource | TemplateBindingParseResult ,
56- > ( result : ResultType ) {
70+ > (
71+ parseResult : ParseContext & {
72+ result : ResultType ;
73+ comments : CommentLine [ ] ;
74+ } ,
75+ ) {
76+ const { result } = parseResult ;
77+
5778 if ( result . errors . length !== 0 ) {
58- const [ { message } ] = result . errors ;
59- throw new SyntaxError (
60- message . replace ( / ^ P a r s e r E r r o r : | a t c o l u m n \d + i n [ ^ ] * $ / g, '' ) ,
61- ) ;
79+ const [ originalError ] = result . errors ;
80+
81+ /* c8 ignore next 3 @preserve */
82+ if ( ! ( originalError instanceof ParseError ) ) {
83+ throw originalError ;
84+ }
85+
86+ let { message } = originalError ;
87+ {
88+ const match = message . match ( / i n .* ?@ \d + : \d + $ / ) ;
89+ if ( match ) {
90+ message = message . slice ( 0 , match . index ) ;
91+ }
92+ }
93+
94+ let location = parseResult . start ;
95+ {
96+ const match = message . match ( / a t c o l u m n (?< index > \d + ) / ) ;
97+ if ( match ) {
98+ message = message . slice ( 0 , match . index ) ;
99+ location = location . moveBy ( Number ( match . groups ! . index ) ) ;
100+ }
101+ }
102+
103+ const error = new SyntaxError ( message . trim ( ) , { cause : originalError } ) ;
104+ Object . assign ( {
105+ cause : originalError ,
106+ location,
107+ span : originalError . span ,
108+ } ) ;
109+
110+ throw error ;
62111 }
63112
64- return result ;
113+ return parseResult ;
65114}
66115
67116const createAstParser =
@@ -72,24 +121,32 @@ const createAstParser =
72121 | 'parseAction'
73122 | 'parseInterpolationExpression' ,
74123 ) =>
75- ( text : string ) => ( {
76- result : throwErrors < ASTWithSource > (
77- getParser ( ) [ name ] ( text , getParseSourceSpan ( ) , 0 ) ,
78- ) ,
79- text,
80- comments : extractComments ( text ) ,
81- } ) ;
124+ ( text : string ) => {
125+ const context = getParseSourceSpan ( text ) ;
126+ return throwErrors < ASTWithSource > ( {
127+ ...context ,
128+ result : getParser ( ) [ name ] ( text , context . sourceSpan , 0 ) ,
129+ comments : extractComments ( text ) ,
130+ } ) ;
131+ } ;
82132
83133export const parseAction = createAstParser ( 'parseAction' ) ;
84134export const parseBinding = createAstParser ( 'parseBinding' ) ;
85135export const parseSimpleBinding = createAstParser ( 'parseSimpleBinding' ) ;
86136export const parseInterpolationExpression = createAstParser (
87137 'parseInterpolationExpression' ,
88138) ;
89- export const parseTemplateBindings = ( text : string ) => ( {
90- result : throwErrors < TemplateBindingParseResult > (
91- getParser ( ) . parseTemplateBindings ( '' , text , getParseSourceSpan ( ) , 0 , 0 ) ,
92- ) ,
93- text,
94- comments : [ ] ,
95- } ) ;
139+ export const parseTemplateBindings = ( text : string ) => {
140+ const context = getParseSourceSpan ( text ) ;
141+ return throwErrors < TemplateBindingParseResult > ( {
142+ ...context ,
143+ result : getParser ( ) . parseTemplateBindings (
144+ '' ,
145+ text ,
146+ context . sourceSpan ,
147+ 0 ,
148+ 0 ,
149+ ) ,
150+ comments : [ ] ,
151+ } ) ;
152+ } ;
0 commit comments