Skip to content

Commit

Permalink
Merge pull request #1628 from DanielXMoore/jsx-attr-2
Browse files Browse the repository at this point in the history
Fix object literals and bulleted lists in JSX indented attributes, fix indentation detection
  • Loading branch information
edemaine authored Dec 2, 2024
2 parents 2e4e51e + 59853c5 commit 24c6391
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 26 deletions.
71 changes: 49 additions & 22 deletions source/parser.hera
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,8 @@ ArgumentsWithTrailingCallExpressions

# Does not match in the empty case
TrailingCallExpressions
# NOTE: Assert "." to not match "?" or "!" or string literal
# as a call expression on the following line
CallExpressionRest* IndentedTrailingCallExpressions? ->
# NOTE: Forbid nested implicit calls because trailing calls are dedented
ExplicitCallExpressionRest* IndentedTrailingCallExpressions? ->
$1 = $1.flat()
if (!$1.length && !$2) return $skip
if (!$2) return $1
Expand Down Expand Up @@ -1446,6 +1445,27 @@ CallExpressionRest
optional,
}, ...argsWithTrailing.slice(1) ]

ExplicitCallExpressionRest
MemberExpressionRest
# NOTE: TypeScript instantiation expressions
# https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#instantiation-expressions
# But x<y>z and x<y>0 is a comparison chain.
TypeArguments !( IdentifierName / NumericLiteral ) -> $1
# perf: assertion to exit early
/(?=['"`])/ ( TemplateLiteral / StringLiteral ):literal ->
if (literal.type === "StringLiteral") {
literal = "`" + literal.token.slice(1, -1).replace(/(`|\$\{)/g, "\\$1") + "`"
}
return literal
OptionalShorthand?:optional ExplicitArguments:call ->
if (!optional) return call

return {
...call,
children: [optional, ...call.children],
optional,
}

# NOTE: Added shorthand x?(3) -> x?.(3)
OptionalShorthand
# perf: assertion to exit early
Expand Down Expand Up @@ -5472,30 +5492,37 @@ Debugger

MaybeNestedNonPipelineExpression
NestedBulletedArray
PushIndent ( Nested NonPipelineExpression )? PopIndent ->
if ($3) return $3
return $skip
NestedImplicitObjectLiteral
PushIndent ( Nested NonPipelineExpression )?:expression PopIndent AllowedTrailingCallExpressions?:trailing ->
if (!expression) return $skip
if (!trailing) return expression
return [ expression, trailing ]
NonPipelineExpression

MaybeNestedPostfixedExpression
NestedBulletedArray
PushIndent ( Nested PostfixedExpression )? PopIndent ->
if ($3) return $3
return $skip
NestedImplicitObjectLiteral
PushIndent ( Nested PostfixedExpression )?:expression PopIndent AllowedTrailingCallExpressions?:trailing ->
if (!expression) return $skip
if (!trailing) return expression
return [ expression, trailing ]
PostfixedExpression

MaybeNestedExpression
NestedPostfixedExpressionNoTrailing
NestedBulletedArray
PushIndent ( Nested Expression )? PopIndent ->
if ($3) return $3
return $skip
Expression
NestedImplicitObjectLiteral
PushIndent ( Nested PostfixedExpression )?:expression PopIndent ->
if (!expression) return $skip
return expression

NestedExpression
MaybeNestedExpression
NestedBulletedArray
PushIndent ( Nested Expression )? PopIndent ->
if ($3) return $3
return $skip
NestedImplicitObjectLiteral
PushIndent ( Nested Expression )?:expression PopIndent AllowedTrailingCallExpressions?:trailing ->
if (!expression) return $skip
if (!trailing) return expression
return [ expression, trailing ]
Expression

# MaybeNestedExpression but where expression needs to be output with
# parentheses if indented, so that the expression starts on the same line.
Expand All @@ -5510,7 +5537,7 @@ MaybeParenNestedExpression
&EOS ( ArrayLiteral / ObjectLiteral ) -> $2
# Value after `return` needs to be wrapped in parentheses
# if it starts on another line.
&EOS InsertSpace InsertOpenParen PushIndent ( Nested Expression ):exp PopIndent InsertNewline InsertIndent InsertCloseParen ->
&EOS InsertSpace InsertOpenParen PushIndent ( Nested Expression ):exp PopIndent AllowedTrailingCallExpressions? InsertNewline InsertIndent InsertCloseParen ->
if (!exp) return $skip
return $0.slice(1)

Expand Down Expand Up @@ -7196,9 +7223,9 @@ JSXAttributeName
JSXAttributeInitializer
# Outside CoffeeScript compatibility mode,
# allow attribute value to be an indented expression
!CoffeeJSXEnabled Whitespace?:ws1 Equals:equals &( NonNewlineWhitespace* EOL ):ws2 InsertInlineOpenBrace:open PushIndent:indent PostfixedExpression?:expression PopIndent InsertCloseBrace:close ->
if (!expression) return $skip
return [ ws1, equals, ws2, open, indent, expression, close ]
# Forbid trailing expressions outside the indentation, as that should be JSX
!CoffeeJSXEnabled Whitespace?:ws1 Equals:equals &( NonNewlineWhitespace* EOL ) InsertInlineOpenBrace:open NestedPostfixedExpressionNoTrailing:expression InsertCloseBrace:close ->
return [ ws1, equals, open, trimFirstSpace(expression), close ]
Whitespace? Equals Whitespace? JSXAttributeValue

# https://facebook.github.io/jsx/#prod-JSXAttributeValue
Expand Down
12 changes: 11 additions & 1 deletion test/call-expression.civet
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{ testCase } from ./helper.civet
{ testCase, throws } from ./helper.civet

describe "call-expression", ->
testCase """
Expand Down Expand Up @@ -195,6 +195,16 @@ describe "call-expression", ->
.login(config.bot.token)
"""

throws """
dedent doesn't count as indented call
---
x =
a
b
---
ParseError
"""

describe "insert semicolons to prevent accidental calls", ->
testCase """
parenthetical
Expand Down
26 changes: 26 additions & 0 deletions test/jsx/attr.civet
Original file line number Diff line number Diff line change
Expand Up @@ -609,3 +609,29 @@ describe "JSX object literal shorthand", ->
</>}
/>
"""

testCase """
multiline literals
---
<For each=
. 1
. 2
. 3
>
<div style=
background: "white"
color: "black"
>
---
<For each={[
1,
2,
3]}
>
<div style={{
background: "white",
color: "black",
}}
/>
</For>
"""
7 changes: 4 additions & 3 deletions test/pipe.civet
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ describe "pipe", ->
---
x; // c
// @ts-expect-error
let ref;foo ??=(baz((ref = \n bar())),qux(ref),ref)
let ref;foo ??=
(baz((ref = bar())),qux(ref),ref)
"""

describe "ampersand", ->
Expand Down Expand Up @@ -711,8 +712,8 @@ describe "pipe", ->
foo()
|> await
---
({foo:await (
foo())})
({foo:
await foo()})
"""

testCase """
Expand Down

0 comments on commit 24c6391

Please sign in to comment.