diff --git a/src/res_core.ml b/src/res_core.ml index f6cae271..506ceea3 100644 --- a/src/res_core.ml +++ b/src/res_core.ml @@ -815,7 +815,7 @@ let parseTemplateConstant ~prefix (p : Parser.t) = let startPos = p.startPos in Parser.nextTemplateLiteralToken p; match p.token with - | TemplateTail txt -> + | TemplateTail (txt, _) -> Parser.next p; Parsetree.Pconst_string (txt, prefix) | _ -> @@ -2147,36 +2147,34 @@ and parseTemplateExpr ?(prefix = "js") p = let op = Location.mknoloc (Longident.Lident "^") in Ast_helper.Exp.ident op in - let rec parseParts acc = + let concat (e1 : Parsetree.expression) (e2 : Parsetree.expression) = + let loc = mkLoc e1.pexp_loc.loc_start e2.pexp_loc.loc_end in + Ast_helper.Exp.apply ~attrs:[templateLiteralAttr] ~loc hiddenOperator + [(Nolabel, e1); (Nolabel, e2)] + in + let rec parseParts (acc : Parsetree.expression) = let startPos = p.Parser.startPos in Parser.nextTemplateLiteralToken p; match p.token with - | TemplateTail txt -> + | TemplateTail (txt, lastPos) -> Parser.next p; - let loc = mkLoc startPos p.prevEndPos in + let loc = mkLoc startPos lastPos in let str = Ast_helper.Exp.constant ~attrs:[templateLiteralAttr] ~loc (Pconst_string (txt, Some prefix)) in - Ast_helper.Exp.apply ~attrs:[templateLiteralAttr] ~loc hiddenOperator - [(Nolabel, acc); (Nolabel, str)] - | TemplatePart txt -> + concat acc str + | TemplatePart (txt, lastPos) -> Parser.next p; - let loc = mkLoc startPos p.prevEndPos in + let loc = mkLoc startPos lastPos in let expr = parseExprBlock p in - let fullLoc = mkLoc startPos p.prevEndPos in let str = Ast_helper.Exp.constant ~attrs:[templateLiteralAttr] ~loc (Pconst_string (txt, Some prefix)) in let next = - let a = - Ast_helper.Exp.apply ~attrs:[templateLiteralAttr] ~loc:fullLoc - hiddenOperator - [(Nolabel, acc); (Nolabel, str)] - in - Ast_helper.Exp.apply ~loc:fullLoc hiddenOperator - [(Nolabel, a); (Nolabel, expr)] + let a = concat acc str in + concat a expr in parseParts next | token -> @@ -2186,25 +2184,20 @@ and parseTemplateExpr ?(prefix = "js") p = let startPos = p.startPos in Parser.nextTemplateLiteralToken p; match p.token with - | TemplateTail txt -> + | TemplateTail (txt, lastPos) -> Parser.next p; Ast_helper.Exp.constant ~attrs:[templateLiteralAttr] - ~loc:(mkLoc startPos p.prevEndPos) + ~loc:(mkLoc startPos lastPos) (Pconst_string (txt, Some prefix)) - | TemplatePart txt -> + | TemplatePart (txt, lastPos) -> Parser.next p; - let constantLoc = mkLoc startPos p.prevEndPos in + let constantLoc = mkLoc startPos lastPos in let expr = parseExprBlock p in - let fullLoc = mkLoc startPos p.prevEndPos in let str = Ast_helper.Exp.constant ~attrs:[templateLiteralAttr] ~loc:constantLoc (Pconst_string (txt, Some prefix)) in - let next = - Ast_helper.Exp.apply ~attrs:[templateLiteralAttr] ~loc:fullLoc - hiddenOperator - [(Nolabel, str); (Nolabel, expr)] - in + let next = concat str expr in parseParts next | token -> Parser.err p (Diagnostics.unexpected token p.breadcrumbs); diff --git a/src/res_scanner.ml b/src/res_scanner.ml index fee95698..6fbfac95 100644 --- a/src/res_scanner.ml +++ b/src/res_scanner.ml @@ -587,12 +587,15 @@ let scanTemplateLiteralToken scanner = let startPos = position scanner in let rec scan () = + let lastPos = position scanner in match scanner.ch with | '`' -> next scanner; - Token.TemplateTail - ((String.sub [@doesNotRaise]) scanner.src startOff - (scanner.offset - 1 - startOff)) + let contents = + (String.sub [@doesNotRaise]) scanner.src startOff + (scanner.offset - 1 - startOff) + in + Token.TemplateTail (contents, lastPos) | '$' -> ( match peek scanner with | '{' -> @@ -601,7 +604,7 @@ let scanTemplateLiteralToken scanner = (String.sub [@doesNotRaise]) scanner.src startOff (scanner.offset - 2 - startOff) in - Token.TemplatePart contents + Token.TemplatePart (contents, lastPos) | _ -> next scanner; scan ()) @@ -617,9 +620,11 @@ let scanTemplateLiteralToken scanner = | ch when ch = hackyEOFChar -> let endPos = position scanner in scanner.err ~startPos ~endPos Diagnostics.unclosedTemplate; - Token.TemplateTail - ((String.sub [@doesNotRaise]) scanner.src startOff - (max (scanner.offset - 1 - startOff) 0)) + let contents = + (String.sub [@doesNotRaise]) scanner.src startOff + (max (scanner.offset - 1 - startOff) 0) + in + Token.TemplateTail (contents, lastPos) | _ -> next scanner; scan () diff --git a/src/res_token.ml b/src/res_token.ml index 4955d763..2c4f8f26 100644 --- a/src/res_token.ml +++ b/src/res_token.ml @@ -88,8 +88,8 @@ type t = | PercentPercent | Comment of Comment.t | List - | TemplateTail of string - | TemplatePart of string + | TemplateTail of string * Lexing.position + | TemplatePart of string * Lexing.position | Backtick | BarGreater | Try @@ -198,8 +198,8 @@ let toString = function | PercentPercent -> "%%" | Comment c -> "Comment" ^ Comment.toString c | List -> "list{" - | TemplatePart text -> text ^ "${" - | TemplateTail text -> "TemplateTail(" ^ text ^ ")" + | TemplatePart (text, _) -> text ^ "${" + | TemplateTail (text, _) -> "TemplateTail(" ^ text ^ ")" | Backtick -> "`" | BarGreater -> "|>" | Try -> "try" diff --git a/tests/parsing/errors/structure/expected/gh16B.res.txt b/tests/parsing/errors/structure/expected/gh16B.res.txt index 23cfa8a5..3580faf6 100644 --- a/tests/parsing/errors/structure/expected/gh16B.res.txt +++ b/tests/parsing/errors/structure/expected/gh16B.res.txt @@ -19,12 +19,12 @@ let log msg = (((((({js|> Server: |js})[@res.template ]) ^ msg)[@res.template ]) ^ (({js||js})[@res.template ]))[@res.template ]) ;;log - (((((((((((({js|Running on: |js})[@res.template ]) ^ address.address) - [@res.template ]) ^ (({js|:|js})[@res.template ])) - [@res.template ]) ^ (address.port |. string_of_int)) - ^ (({js| (|js})[@res.template ])) - [@res.template ]) ^ address.family) - ^ (({js|)|js})[@res.template ]))[@res.template ]) + (((((((((((((({js|Running on: |js})[@res.template ]) ^ address.address) + [@res.template ]) ^ (({js|:|js})[@res.template ])) + [@res.template ]) ^ (address.port |. string_of_int)) + [@res.template ]) ^ (({js| (|js})[@res.template ])) + [@res.template ]) ^ address.family) + [@res.template ]) ^ (({js|)|js})[@res.template ]))[@res.template ]) module ClientSet = struct module T = diff --git a/tests/parsing/grammar/expressions/expected/es6template.res.txt b/tests/parsing/grammar/expressions/expected/es6template.res.txt index c2960506..b84d1fc7 100644 --- a/tests/parsing/grammar/expressions/expected/es6template.res.txt +++ b/tests/parsing/grammar/expressions/expected/es6template.res.txt @@ -33,46 +33,46 @@ let s = (({js| after|js})[@res.template ])) [@res.template ]) let s = - ((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ (({js||js}) - [@res.template ])) - [@res.template ]) ^ bar) - ^ (({js||js})[@res.template ])) + (((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ (({js||js}) + [@res.template ])) + [@res.template ]) ^ bar) + [@res.template ]) ^ (({js||js})[@res.template ])) [@res.template ]) let s = - (((((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ - (({js||js})[@res.template ])) - [@res.template ]) ^ bar) - ^ (({js||js})[@res.template ])) - [@res.template ]) ^ baz) - ^ (({js||js})[@res.template ])) + (((((((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ + (({js||js})[@res.template ])) + [@res.template ]) ^ bar) + [@res.template ]) ^ (({js||js})[@res.template ])) + [@res.template ]) ^ baz) + [@res.template ]) ^ (({js||js})[@res.template ])) [@res.template ]) let s = - ((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ (({js| |js}) - [@res.template ])) - [@res.template ]) ^ bar) - ^ (({js||js})[@res.template ])) + (((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ (({js| |js}) + [@res.template ])) + [@res.template ]) ^ bar) + [@res.template ]) ^ (({js||js})[@res.template ])) [@res.template ]) let s = - (((((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ - (({js| |js})[@res.template ])) - [@res.template ]) ^ bar) - ^ (({js| |js})[@res.template ])) - [@res.template ]) ^ baz) - ^ (({js||js})[@res.template ])) + (((((((((((((({js||js})[@res.template ]) ^ foo)[@res.template ]) ^ + (({js| |js})[@res.template ])) + [@res.template ]) ^ bar) + [@res.template ]) ^ (({js| |js})[@res.template ])) + [@res.template ]) ^ baz) + [@res.template ]) ^ (({js||js})[@res.template ])) [@res.template ]) let s = - ((((((((({js| before |js})[@res.template ]) ^ foo)[@res.template ]) ^ - (({js| |js})[@res.template ])) - [@res.template ]) ^ bar) - ^ (({js| after |js})[@res.template ])) + (((((((((({js| before |js})[@res.template ]) ^ foo)[@res.template ]) ^ + (({js| |js})[@res.template ])) + [@res.template ]) ^ bar) + [@res.template ]) ^ (({js| after |js})[@res.template ])) [@res.template ]) let s = - (((((((((((({js|before |js})[@res.template ]) ^ foo)[@res.template ]) ^ - (({js| middle |js})[@res.template ])) - [@res.template ]) ^ bar) - ^ (({js| |js})[@res.template ])) - [@res.template ]) ^ baz) - ^ (({js| wow |js})[@res.template ])) + (((((((((((((({js|before |js})[@res.template ]) ^ foo)[@res.template ]) ^ + (({js| middle |js})[@res.template ])) + [@res.template ]) ^ bar) + [@res.template ]) ^ (({js| |js})[@res.template ])) + [@res.template ]) ^ baz) + [@res.template ]) ^ (({js| wow |js})[@res.template ])) [@res.template ]) let s = (({js| @@ -93,10 +93,10 @@ let s = (({js|$dollar without $braces $interpolation|js})[@res.template ]) let s = (({json|null|json})[@res.template ]) let x = (({js|foo\`bar\$\\foo|js})[@res.template ]) let x = - ((((((((({js|foo\`bar\$\\foo|js})[@res.template ]) ^ a)[@res.template ]) ^ - (({js| \` |js})[@res.template ])) - [@res.template ]) ^ b) - ^ (({js| \` xx|js})[@res.template ])) + (((((((((({js|foo\`bar\$\\foo|js})[@res.template ]) ^ a)[@res.template ]) ^ + (({js| \` |js})[@res.template ])) + [@res.template ]) ^ b) + [@res.template ]) ^ (({js| \` xx|js})[@res.template ])) [@res.template ]) let thisIsFine = (({js|$something|js})[@res.template ]) let thisIsAlsoFine = (({js|fine\$|js})[@res.template ])