diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ca321068a..c8e49e2d9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,9 @@ #### :rocket: New Feature +- Add support for array spread. https://github.com/rescript-lang/rescript-compiler/pull/6608 - Support import attributes (https://github.com/tc39/proposal-import-attributes) in `@module()`. https://github.com/rescript-lang/rescript-compiler/pull/6599 +- allow hyphens in jsx tag names (e.g. ``). https://github.com/rescript-lang/rescript-compiler/pull/6609 #### :bug: Bug Fix @@ -36,7 +38,6 @@ - Experimental support of tagged template literals, e.g. ```sql`select * from ${table}```. https://github.com/rescript-lang/rescript-compiler/pull/6250 - Experimental support for generic/custom JSX transforms. https://github.com/rescript-lang/rescript-compiler/pull/6565 - `dict` is now a builtin type. https://github.com/rescript-lang/rescript-compiler/pull/6590 -- Add support for array spread. https://github.com/rescript-lang/rescript-compiler/pull/6608 #### :bug: Bug Fix diff --git a/jscomp/syntax/src/res_core.ml b/jscomp/syntax/src/res_core.ml index dca3a15bb2..eb44638408 100644 --- a/jscomp/syntax/src/res_core.ml +++ b/jscomp/syntax/src/res_core.ml @@ -2617,10 +2617,11 @@ and parseJsxOpeningOrSelfClosingElement ~startPos p = | GreaterThan -> ( (* bar *) let childrenStartPos = p.Parser.startPos in - Scanner.setJsxMode p.scanner; Parser.next p; let spread, children = parseJsxChildren p in let childrenEndPos = p.Parser.startPos in + Scanner.popMode p.scanner Jsx; + Scanner.setJsxMode p.scanner; let () = match p.token with | LessThanSlash -> Parser.next p @@ -2685,6 +2686,8 @@ and parseJsxOpeningOrSelfClosingElement ~startPos p = * jsx-children ::= primary-expr* * => 0 or more *) and parseJsx p = + Scanner.popMode p.scanner Jsx; + Scanner.setJsxMode p.Parser.scanner; Parser.leaveBreadcrumb p Grammar.Jsx; let startPos = p.Parser.startPos in Parser.expect LessThan p; @@ -2696,6 +2699,7 @@ and parseJsx p = parseJsxFragment p | _ -> parseJsxName p in + Scanner.popMode p.scanner Jsx; Parser.eatBreadcrumb p; {jsxExpr with pexp_attributes = [jsxAttr]} @@ -2706,12 +2710,12 @@ and parseJsx p = *) and parseJsxFragment p = let childrenStartPos = p.Parser.startPos in - Scanner.setJsxMode p.scanner; Parser.expect GreaterThan p; let _spread, children = parseJsxChildren p in let childrenEndPos = p.Parser.startPos in Parser.expect LessThanSlash p; Parser.expect GreaterThan p; + Scanner.popMode p.scanner Jsx; let loc = mkLoc childrenStartPos childrenEndPos in makeListExpression loc children None @@ -2743,6 +2747,7 @@ and parseJsxProp p = Parser.next p; (* no punning *) let optional = Parser.optional p Question in + Scanner.popMode p.scanner Jsx; let attrExpr = let e = parsePrimaryExpr ~operand:(parseAtomicExpr p) p in {e with pexp_attributes = propLocAttr :: e.pexp_attributes} @@ -2765,6 +2770,7 @@ and parseJsxProp p = Parser.next p; match p.Parser.token with | DotDotDot -> ( + Scanner.popMode p.scanner Jsx; Parser.next p; let loc = mkLoc p.Parser.startPos p.prevEndPos in let propLocAttr = @@ -2790,9 +2796,7 @@ and parseJsxProps p = and parseJsxChildren p = let rec loop p children = match p.Parser.token with - | Token.Eof | LessThanSlash -> - Scanner.popMode p.scanner Jsx; - List.rev children + | Token.Eof | LessThanSlash -> children | LessThan -> (* Imagine:
< * is `<` the start of a jsx-child?
let () = Scanner.popMode p.scanner Jsx in let child = parsePrimaryExpr ~operand:(parseAtomicExpr p) ~noCall:true p in loop p (child :: children) - | _ -> - Scanner.popMode p.scanner Jsx; - List.rev children + | _ -> children in match p.Parser.token with | DotDotDot -> Parser.next p; (true, [parsePrimaryExpr ~operand:(parseAtomicExpr p) ~noCall:true p]) - | _ -> (false, loop p []) + | _ -> + let children = List.rev (loop p []) in + Scanner.popMode p.scanner Jsx; + (false, children) and parseBracedOrRecordExpr p = let startPos = p.Parser.startPos in diff --git a/jscomp/syntax/src/res_printer.ml b/jscomp/syntax/src/res_printer.ml index fa9b43a1b9..9c2ef4b669 100644 --- a/jscomp/syntax/src/res_printer.ml +++ b/jscomp/syntax/src/res_printer.ml @@ -421,7 +421,7 @@ let printLongident = function type identifierStyle = ExoticIdent | NormalIdent -let classifyIdentContent ?(allowUident = false) txt = +let classifyIdentContent ?(allowUident = false) ?(allowHyphen = false) txt = if Token.isKeywordTxt txt then ExoticIdent else let len = String.length txt in @@ -431,16 +431,18 @@ let classifyIdentContent ?(allowUident = false) txt = match String.unsafe_get txt i with | 'A' .. 'Z' when allowUident -> loop (i + 1) | 'a' .. 'z' | '_' -> loop (i + 1) + | '-' when allowHyphen -> loop (i + 1) | _ -> ExoticIdent else match String.unsafe_get txt i with | 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '\'' | '_' -> loop (i + 1) + | '-' when allowHyphen -> loop (i + 1) | _ -> ExoticIdent in loop 0 -let printIdentLike ?allowUident txt = - match classifyIdentContent ?allowUident txt with +let printIdentLike ?allowUident ?allowHyphen txt = + match classifyIdentContent ?allowUident ?allowHyphen txt with | ExoticIdent -> Doc.concat [Doc.text "\\\""; Doc.text txt; Doc.text "\""] | NormalIdent -> Doc.text txt @@ -4462,7 +4464,7 @@ and printJsxProp ~state arg cmtTbl = * Navabar.createElement -> Navbar * Staff.Users.createElement -> Staff.Users *) and printJsxName {txt = lident} = - let printIdent = printIdentLike ~allowUident:true in + let printIdent = printIdentLike ~allowUident:true ~allowHyphen:true in let rec flatten acc lident = match lident with | Longident.Lident txt -> printIdent txt :: acc diff --git a/jscomp/syntax/src/res_scanner.ml b/jscomp/syntax/src/res_scanner.ml index afcd4b9f32..b169041034 100644 --- a/jscomp/syntax/src/res_scanner.ml +++ b/jscomp/syntax/src/res_scanner.ml @@ -182,8 +182,11 @@ let digitValue ch = let scanIdentifier scanner = let startOff = scanner.offset in let rec skipGoodChars scanner = - match scanner.ch with - | 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '\'' -> + match (scanner.ch, inJsxMode scanner) with + | ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '\''), false -> + next scanner; + skipGoodChars scanner + | ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '\'' | '-'), true -> next scanner; skipGoodChars scanner | _ -> () diff --git a/jscomp/syntax/tests/parsing/errors/expressions/expected/jsx.res.txt b/jscomp/syntax/tests/parsing/errors/expressions/expected/jsx.res.txt index ca61b12c08..02c96a2d5f 100644 --- a/jscomp/syntax/tests/parsing/errors/expressions/expected/jsx.res.txt +++ b/jscomp/syntax/tests/parsing/errors/expressions/expected/jsx.res.txt @@ -1,14 +1,4 @@ - Syntax error! - tests/parsing/errors/expressions/jsx.res:1:12 - - 1 │ let x = - 2 │ let x = ; - 3 │ let x = ; - - I'm not sure what to parse here when looking at "-". - - Syntax error! tests/parsing/errors/expressions/jsx.res:2:20 @@ -66,7 +56,7 @@ I'm not sure what to parse here when looking at ".". -let x = ((di ~children:[] ())[@JSX ]) - (v / ([%rescript.exprhole ])) +let x = ((di-v ~children:[] ())[@JSX ]) let x = ((Unclosed.createElement ~children:[] ())[@JSX ]) let x = ((Foo.Bar.createElement ~children:[] ())[@JSX ]) > ([%rescript.exprhole ]) diff --git a/jscomp/syntax/tests/printer/expr/expected/jsx.res.txt b/jscomp/syntax/tests/printer/expr/expected/jsx.res.txt index 1234bb6ecd..fe0101d26c 100644 --- a/jscomp/syntax/tests/printer/expr/expected/jsx.res.txt +++ b/jscomp/syntax/tests/printer/expr/expected/jsx.res.txt @@ -4,8 +4,8 @@ let x = let x = let x = let x = -let x = <\"custom-tag" className="container" /> -let x = +let x = +let x = // https://github.com/rescript-lang/syntax/issues/570 let x = @@ -38,15 +38,15 @@ let x = {b} let x = - <\"custom-tag" className="container"> + {a} - + let x = - + {a} - + let x =
diff --git a/jscomp/syntax/tests/printer/expr/jsx.res b/jscomp/syntax/tests/printer/expr/jsx.res index e44a26cd1f..acd7debfbe 100644 --- a/jscomp/syntax/tests/printer/expr/jsx.res +++ b/jscomp/syntax/tests/printer/expr/jsx.res @@ -6,8 +6,8 @@ let x = let x = -let x = <\"custom-tag" className="container" /> -let x = +let x = +let x = // https://github.com/rescript-lang/syntax/issues/570 let x = @@ -15,8 +15,8 @@ let x = {children} let x = {children} let x = {a} let x = {a} {b} -let x = <\"custom-tag" className="container" > {a} -let x = {a} +let x = {a} +let x = {a} let x =