Skip to content

Commit 19d6393

Browse files
committed
Add more declaration test cases
1 parent 8966f04 commit 19d6393

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,16 +1050,25 @@ extension Parser {
10501050
) -> RawFunctionDeclSyntax {
10511051
let (unexpectedBeforeFuncKeyword, funcKeyword) = self.eat(handle)
10521052
let unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?
1053+
let unexpectedAfterIdentifier: RawUnexpectedNodesSyntax?
10531054
let identifier: RawTokenSyntax
10541055
if self.at(anyIn: Operator.self) != nil || self.at(.exclamationMark, .prefixAmpersand) {
10551056
var name = self.currentToken.tokenText
1056-
if name.count > 1 && name.hasSuffix("<") && self.peek(isAt: .identifier) {
1057+
if !currentToken.isEditorPlaceholder && name.count > 1 && name.hasSuffix("<") && self.peek(isAt: .identifier) {
10571058
name = SyntaxText(rebasing: name.dropLast())
10581059
}
10591060
unexpectedBeforeIdentifier = nil
10601061
identifier = self.consumePrefix(name, as: .binaryOperator)
1062+
unexpectedAfterIdentifier = nil
10611063
} else {
10621064
(unexpectedBeforeIdentifier, identifier) = self.expectIdentifier(keywordRecovery: true)
1065+
1066+
if currentToken.isEditorPlaceholder {
1067+
let editorPlaceholder = self.parseAnyIdentifier()
1068+
unexpectedAfterIdentifier = RawUnexpectedNodesSyntax([editorPlaceholder], arena: self.arena)
1069+
} else {
1070+
unexpectedAfterIdentifier = nil
1071+
}
10631072
}
10641073

10651074
let genericParams: RawGenericParameterClauseSyntax?
@@ -1086,6 +1095,7 @@ extension Parser {
10861095
funcKeyword: funcKeyword,
10871096
unexpectedBeforeIdentifier,
10881097
name: identifier,
1098+
unexpectedAfterIdentifier,
10891099
genericParameterClause: genericParams,
10901100
signature: signature,
10911101
genericWhereClause: generics,

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
388388
]
389389
)
390390
} else if let firstToken = node.first?.as(TokenSyntax.self),
391+
!firstToken.isEditorPlaceholder,
391392
firstToken.tokenKind.isIdentifier == true,
392393
firstToken.presence == .present,
393394
let previousToken = node.previousToken(viewMode: .sourceAccurate),

Sources/SwiftSyntax/TokenSyntax.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,16 @@ public struct TokenSyntax: SyntaxProtocol, SyntaxHashable {
131131
return raw.totalLength
132132
}
133133

134+
/// Whether the token text is an editor placeholder or not.
135+
public var isEditorPlaceholder: Bool {
136+
switch self.tokenKind {
137+
case .identifier(let text):
138+
return text.hasPrefix("<#") && text.hasSuffix("#>")
139+
default:
140+
return false
141+
}
142+
}
143+
134144
/// A token by itself has no structure, so we represent its structure by an
135145
/// empty layout node.
136146
///

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2551,7 +2551,7 @@ final class DeclarationTests: ParserTestCase {
25512551
)
25522552
}
25532553

2554-
func testFunctionDeclarationWithPlaceholder() {
2554+
func testDeclarationsWithPlaceholders() {
25552555
assertParse(
25562556
"""
25572557
func 1️⃣<#name#>(2️⃣<#parameters#>3️⃣) -> 4️⃣<#return type#> {
@@ -2606,5 +2606,110 @@ final class DeclarationTests: ParserTestCase {
26062606
}
26072607
"""
26082608
)
2609+
2610+
assertParse(
2611+
"""
2612+
func test1️⃣<#name#>() {
2613+
2️⃣<#function body#>
2614+
}
2615+
""",
2616+
substructure: FunctionDeclSyntax(
2617+
funcKeyword: .keyword(.func),
2618+
name: .identifier("test"),
2619+
UnexpectedNodesSyntax([
2620+
TokenSyntax.identifier("<#name#>")
2621+
]),
2622+
signature: FunctionSignatureSyntax(
2623+
parameterClause: FunctionParameterClauseSyntax(
2624+
parameters: FunctionParameterListSyntax([])
2625+
)
2626+
),
2627+
body: CodeBlockSyntax(
2628+
statements: CodeBlockItemListSyntax([
2629+
CodeBlockItemSyntax(
2630+
item: .expr(
2631+
ExprSyntax(
2632+
EditorPlaceholderExprSyntax(
2633+
placeholder: .identifier("<#function body#>")
2634+
)
2635+
)
2636+
)
2637+
)
2638+
])
2639+
)
2640+
),
2641+
diagnostics: [
2642+
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code '<#name#>' in function"),
2643+
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
2644+
]
2645+
)
2646+
2647+
assertParse(
2648+
"""
2649+
class 1️⃣<#name#>: 2️⃣<#super class#> {
2650+
3️⃣<#code#>
2651+
}
2652+
""",
2653+
diagnostics: [
2654+
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"),
2655+
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
2656+
DiagnosticSpec(locationMarker: "3️⃣", message: "editor placeholder in source file"),
2657+
]
2658+
)
2659+
2660+
assertParse(
2661+
"""
2662+
enum 1️⃣<#name#> {
2663+
case 2️⃣<#code#>
2664+
}
2665+
""",
2666+
diagnostics: [
2667+
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"),
2668+
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
2669+
]
2670+
)
2671+
2672+
assertParse(
2673+
"""
2674+
struct 1️⃣<#name#> {
2675+
2️⃣<#code#>
2676+
}
2677+
""",
2678+
diagnostics: [
2679+
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"),
2680+
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
2681+
]
2682+
)
2683+
2684+
assertParse(
2685+
"""
2686+
protocol 1️⃣<#name#> {
2687+
2️⃣<#code#>
2688+
}
2689+
""",
2690+
diagnostics: [
2691+
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"),
2692+
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
2693+
]
2694+
)
2695+
2696+
assertParse(
2697+
"""
2698+
import 1️⃣<#name#>
2699+
""",
2700+
diagnostics: [
2701+
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file")
2702+
]
2703+
)
2704+
2705+
assertParse(
2706+
"""
2707+
typealias 1️⃣<#name#> = 2️⃣<#code#>
2708+
""",
2709+
diagnostics: [
2710+
DiagnosticSpec(locationMarker: "1️⃣", message: "editor placeholder in source file"),
2711+
DiagnosticSpec(locationMarker: "2️⃣", message: "editor placeholder in source file"),
2712+
]
2713+
)
26092714
}
26102715
}

0 commit comments

Comments
 (0)