Allow simplified callback handler without curly braces, (#8764)

Closes #8401

ChangeLog: Callbacks handler no longer need curly-braces. Extra semi-colon is no longer an error.
This commit is contained in:
Varin Thakur 2025-06-26 15:33:56 +02:00 committed by GitHub
parent 9cc24ff284
commit 3640cb8b97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 62 additions and 7 deletions

View file

@ -349,7 +349,7 @@ declare_syntax! {
ArgumentDeclaration -> [DeclaredIdentifier, Type],
/// `-> type` (but without the ->)
ReturnType -> [Type],
CallbackConnection -> [ *DeclaredIdentifier, CodeBlock ],
CallbackConnection -> [ *DeclaredIdentifier, ?CodeBlock, ?Expression ],
/// Declaration of a property.
PropertyDeclaration-> [ ?Type , DeclaredIdentifier, ?BindingExpression, ?TwoWayBinding ],
/// QualifiedName are the properties name

View file

@ -274,6 +274,8 @@ pub fn parse_code_block(p: &mut impl Parser) {
#[cfg_attr(test, parser_test)]
/// ```test,CallbackConnection
/// clicked => {}
/// clicked => bar ;
/// clicked => { foo; } ;
/// clicked() => { foo; }
/// mouse_move(x, y) => {}
/// mouse_move(x, y, ) => { bar; goo; }
@ -294,7 +296,14 @@ fn parse_callback_connection(p: &mut impl Parser) {
p.expect(SyntaxKind::RParent);
}
p.expect(SyntaxKind::FatArrow);
parse_code_block(&mut *p);
if p.nth(0).kind() == SyntaxKind::LBrace && p.nth(2).kind() != SyntaxKind::Colon {
parse_code_block(&mut *p);
p.test(SyntaxKind::Semicolon);
} else if parse_expression(&mut *p) {
p.expect(SyntaxKind::Semicolon);
} else {
p.test(SyntaxKind::Semicolon);
}
}
#[cfg_attr(test, parser_test)]

View file

@ -257,11 +257,21 @@ impl Expression {
) -> Expression {
ctx.arguments =
node.DeclaredIdentifier().map(|x| identifier_text(&x).unwrap_or_default()).collect();
Self::from_codeblock_node(node.CodeBlock(), ctx).maybe_convert_to(
ctx.return_type().clone(),
&node,
ctx.diag,
)
if let Some(code_block_node) = node.CodeBlock() {
Self::from_codeblock_node(code_block_node, ctx).maybe_convert_to(
ctx.return_type().clone(),
&node,
ctx.diag,
)
} else if let Some(expr_node) = node.Expression() {
Self::from_expression_node(expr_node, ctx).maybe_convert_to(
ctx.return_type().clone(),
&node,
ctx.diag,
)
} else {
return Expression::Invalid;
}
}
fn from_function(node: syntax_nodes::Function, ctx: &mut LookupCtx) -> Expression {

View file

@ -0,0 +1,36 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
TestCase := Rectangle {
callback test_func(int) -> int;
test_func(val) => val ;
callback test_func2(int, string) -> string ;
test_func2(val, str) => {str + "=" + val} ;
property <int> test_prop: 4 + test_func(2);
property <string> test_prop2 : test_func2(54, "hello");
property <bool> test: test_prop == 6 && test_prop2 == "hello=54";
}
/*
```rust
let instance = TestCase::new().unwrap();
assert_eq!(instance.get_test_prop(), 6);
assert_eq!(instance.get_test_prop2(), slint::SharedString::from("hello=54"));
```
```cpp
auto handle = TestCase::create();
const TestCase &instance = *handle;
assert_eq(instance.get_test_prop(), 6);
assert_eq(instance.get_test_prop2(), slint::SharedString("hello=54"));
```
```js
var instance = new slint.TestCase();
assert.equal(instance.test_prop, 6);
assert.equal(instance.test_prop2, "hello=54");
```
*/