feat(semantic): report error for empty JSX attribute expression (#8815)

https://www.typescriptlang.org/play/?#code/DwEwlgbgBAhgvAbwL4D5gHpwRUA

This is not a valid JSX syntax
This commit is contained in:
Dunqing 2025-02-01 02:30:39 +00:00
parent 1a4118148a
commit 256ae785ca
3 changed files with 44 additions and 2 deletions

View file

@ -117,6 +117,9 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
AstKind::TSImportEqualsDeclaration(decl) => {
ts::check_ts_import_equals_declaration(decl, ctx);
}
AstKind::JSXExpressionContainer(container) => {
ts::check_jsx_expression_container(container, ctx);
}
_ => {}
}
}

View file

@ -542,3 +542,19 @@ pub fn check_for_statement_left(left: &ForStatementLeft, is_for_in: bool, ctx: &
}
}
}
fn invalid_jsx_attribute_value(span: Span) -> OxcDiagnostic {
ts_error("17000", "JSX attributes must only be assigned a non-empty 'expression'.")
.with_label(span)
}
pub fn check_jsx_expression_container(
container: &JSXExpressionContainer,
ctx: &SemanticBuilder<'_>,
) {
if matches!(container.expression, JSXExpression::EmptyExpression(_))
&& matches!(ctx.nodes.parent_kind(ctx.current_node_id), Some(AstKind::JSXAttributeItem(_)))
{
ctx.error(invalid_jsx_attribute_value(container.span()));
}
}

View file

@ -3,7 +3,7 @@ commit: d85767ab
parser_typescript Summary:
AST Parsed : 6494/6503 (99.86%)
Positive Passed: 6483/6503 (99.69%)
Negative Passed: 1283/5747 (22.32%)
Negative Passed: 1284/5747 (22.34%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration24.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment7.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment8.ts
@ -1279,7 +1279,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsdocTypeCas
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsdocTypeNongenericInstantiationAttempt.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsdocTypedefMissingType.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsdocTypedefNoCrash2.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsxAttributeWithoutExpressionReact.tsx
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsxCallElaborationCheckNoCrash1.tsx
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsxChildWrongType.tsx
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/jsxChildrenArrayWrongType.tsx
@ -8920,6 +8919,30 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
2 │ const y = 0;
╰────
× TS(17000): JSX attributes must only be assigned a non-empty 'expression'.
╭─[typescript/tests/cases/compiler/jsxAttributeWithoutExpressionReact.tsx:4:35]
3 │ <ListView refreshControl={
4 │ <RefreshControl onRefresh={} refreshing={} />
· ──
5 │ } dataSource={this.state.ds} renderRow={}>
╰────
× TS(17000): JSX attributes must only be assigned a non-empty 'expression'.
╭─[typescript/tests/cases/compiler/jsxAttributeWithoutExpressionReact.tsx:4:49]
3 │ <ListView refreshControl={
4 │ <RefreshControl onRefresh={} refreshing={} />
· ──
5 │ } dataSource={this.state.ds} renderRow={}>
╰────
× TS(17000): JSX attributes must only be assigned a non-empty 'expression'.
╭─[typescript/tests/cases/compiler/jsxAttributeWithoutExpressionReact.tsx:5:44]
4 │ <RefreshControl onRefresh={} refreshing={} />
5 │ } dataSource={this.state.ds} renderRow={}>
· ──
6 │ </ListView>
╰────
× Unexpected token
╭─[typescript/tests/cases/compiler/jsxNamespacePrefixInName.tsx:7:32]
6 │