Skip to content

Commit c4dc91e

Browse files
authored
Merge pull request #624 from ahoppen/pr/more-diags
2 parents 8c76dc3 + 7488e49 commit c4dc91e

File tree

5 files changed

+91
-1
lines changed

5 files changed

+91
-1
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,9 @@ extension Parser {
10611061
public mutating func parseParameterClause(isClosure: Bool = false) -> RawParameterClauseSyntax {
10621062
let (unexpectedBeforeLParen, lparen) = self.expect(.leftParen)
10631063
var elements = [RawFunctionParameterSyntax]()
1064-
do {
1064+
// If we are missing the left parenthesis and the next token doesn't appear to be an argument label, don't parse any parameters.
1065+
let shouldSkipParameterParsing = lparen.isMissing && (!currentToken.canBeArgumentLabel || currentToken.isKeyword)
1066+
if !shouldSkipParameterParsing {
10651067
var keepGoing = true
10661068
while !self.at(.eof) && !self.at(.rightParen) && keepGoing {
10671069
// Attributes.

Sources/SwiftParser/Diagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,5 +158,27 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
158158
}
159159
return .visitChildren
160160
}
161+
162+
override public func visit(_ node: ParameterClauseSyntax) -> SyntaxVisitorContinueKind {
163+
if shouldSkip(node) {
164+
return .skipChildren
165+
}
166+
if node.leftParen.presence == .missing && node.parameterList.isEmpty && node.rightParen.presence == .missing {
167+
addDiagnostic(node, .missingFunctionParameterClause)
168+
markNodesAsHandled(node.leftParen.id, node.parameterList.id, node.rightParen.id)
169+
}
170+
return .visitChildren
171+
}
172+
173+
public override func visit(_ node: UnresolvedTernaryExprSyntax) -> SyntaxVisitorContinueKind {
174+
if shouldSkip(node) {
175+
return .skipChildren
176+
}
177+
if node.colonMark.presence == .missing {
178+
addDiagnostic(node.colonMark, .missingColonInTernaryExprDiagnostic)
179+
markNodesAsHandled(node.colonMark.id)
180+
}
181+
return .visitChildren
182+
}
161183
}
162184

Sources/SwiftParser/Diagnostics/ParserDiagnosticMessages.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ public extension ParserFixIt {
7676
/// Please order the cases in this enum alphabetically by case name.
7777
public enum StaticParserError: String, DiagnosticMessage {
7878
case cStyleForLoop = "C-style for statement has been removed in Swift 3"
79+
case missingColonInTernaryExprDiagnostic = "Expected ':' after '? ...' in ternary expression"
80+
case missingFunctionParameterClause = "Expected argument list in function declaration"
7981
case throwsInReturnPosition = "'throws' may only occur before '->'"
8082

8183
public var message: String { self.rawValue }

Tests/SwiftParserTest/DiagnosticTests.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,32 @@ public class DiagnosticTests: XCTestCase {
7777
expectedFixedSource: "() throws -> Int"
7878
)
7979
}
80+
81+
public func testNoParamsForFunction() throws {
82+
let source = """
83+
class MyClass {
84+
func withoutParameters
85+
86+
func withParameters() {}
87+
}
88+
"""
89+
90+
let classDecl = withParser(source: source) {
91+
Syntax(raw: $0.parseDeclaration().raw).as(ClassDeclSyntax.self)!
92+
}
93+
94+
XCTAssertSingleDiagnostic(in: classDecl, line: 2, column: 25, message: "Expected argument list in function declaration")
95+
}
96+
97+
func testMissingColonInTernary() throws {
98+
let source = """
99+
foo ? 1
100+
"""
101+
102+
let node = withParser(source: source) {
103+
Syntax(raw: $0.parseExpression().raw)
104+
}
105+
106+
XCTAssertSingleDiagnostic(in: node, line: 1, column: 8, message: "Expected ':' after '? ...' in ternary expression")
107+
}
80108
}

Tests/SwiftParserTest/RecoveryTests.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,4 +349,40 @@ public class RecoveryTests: XCTestCase {
349349
"""
350350
}
351351
}
352+
353+
public func testNoParamsForFunction() throws {
354+
let source = """
355+
class MyClass {
356+
func withoutParameters
357+
358+
func withParameters() {}
359+
}
360+
"""
361+
362+
let classDecl = withParser(source: source) {
363+
Syntax(raw: $0.parseDeclaration().raw)
364+
}
365+
try XCTAssertHasSubstructure(
366+
classDecl,
367+
FunctionDeclSyntax(
368+
attributes: nil,
369+
modifiers: nil,
370+
funcKeyword: .funcKeyword(),
371+
identifier: .identifier("withoutParameters"),
372+
genericParameterClause: nil,
373+
signature: FunctionSignatureSyntax(
374+
input: ParameterClauseSyntax(
375+
leftParen: .leftParenToken(presence: .missing),
376+
parameterList: FunctionParameterListSyntax([]),
377+
rightParen: .rightParenToken(presence: .missing)
378+
),
379+
asyncOrReasyncKeyword: nil,
380+
throwsOrRethrowsKeyword: nil,
381+
output: nil
382+
),
383+
genericWhereClause: nil,
384+
body: nil
385+
)
386+
)
387+
}
352388
}

0 commit comments

Comments
 (0)