mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Parse] Create SwitchStmt nodes for switch statements with errors
At the moment, if there is an error in the `switch` statement expression or if the `{` is missing, we return `nullptr` from `parseStmtSwitch`, but we consume tokens while trying to parse the `switch` statement. This causes the AST to not contain any nodes for the tokens that were consumed while trying to parse the `switch` statement.
While this doesn’t cause any issues during compilation (compiling fails anyway so not having the `switch` statement in the AST is not a problem) this causes issues when trying to complete inside an expression that was consumed while trying to parse the `switch` statement but doesn’t have a representation in the AST. The solver-based completion approach can’t find the expression that contains the completion token (because it’s not part of the AST) and thus return empty results.
To fix this, make sure we are always creating a `SwitchStmt` when consuming tokens for it.
Previously, one could always assume that a `SwitchStmt` had a valid `LBraceLoc` and `RBraceLoc`. This is no longer the case because of the recovery. In order to form the `SwitchStmt`’s `SourceRange`, I needed to add a `EndLoc` property to `SwitchStmt` that keeps track of the last token in the `SwitchStmt`. Theoretically we should be able to compute this location by traversing the right brace, case stmts, subject expression, … in reverse order until we find something that’s not missing. But if the `SubjectExpr` is an `ErrorExpr`, representing a missing expression, it might have a source range that points to one after the last token in the statement (this is due to the way the `ErrorExpr` is being constructed), therefore returning an invalid range. So overall I thought it was easier and safer to add another property.
Fixes rdar://76688441 [SR-14490]
This commit is contained in:
@@ -234,7 +234,7 @@ deriveBodyCodingKey_enum_stringValue(AbstractFunctionDecl *strValDecl, void *) {
|
||||
auto *selfRef = DerivedConformance::createSelfDeclRef(strValDecl);
|
||||
auto *switchStmt = SwitchStmt::create(LabeledStmtInfo(), SourceLoc(),
|
||||
selfRef, SourceLoc(), cases,
|
||||
SourceLoc(), C);
|
||||
SourceLoc(), SourceLoc(), C);
|
||||
body = BraceStmt::create(C, SourceLoc(), ASTNode(switchStmt), SourceLoc());
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
|
||||
/*Implicit=*/true);
|
||||
auto *switchStmt = SwitchStmt::create(LabeledStmtInfo(), SourceLoc(),
|
||||
stringValueRef, SourceLoc(), cases,
|
||||
SourceLoc(), C);
|
||||
SourceLoc(), SourceLoc(), C);
|
||||
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(switchStmt),
|
||||
SourceLoc());
|
||||
return { body, /*isTypeChecked=*/false };
|
||||
|
||||
Reference in New Issue
Block a user