@@ -9,5 +9,63 @@ import SwiftSyntax
9
9
///
10
10
/// - SeeAlso: https://google.github.io/swift#trailing-closures
11
11
public final class AmbiguousTrailingClosureOverload : SyntaxLintRule {
12
+ func diagnoseBadOverloads( _ overloads: [ String : [ FunctionDeclSyntax ] ] ) {
13
+ for (_, decls) in overloads where decls. count > 1 {
14
+ let decl = decls [ 0 ]
15
+ diagnose ( . ambiguousTrailingClosureOverload( decl. fullDeclName) , on: decl. identifier) {
16
+ for decl in decls. dropFirst ( ) {
17
+ $0. note (
18
+ . otherAmbiguousOverloadHere( decl. fullDeclName) ,
19
+ location: decl. identifier. startLocation ( in: self . context. fileURL)
20
+ )
21
+ }
22
+ }
23
+ }
24
+ }
12
25
26
+ func discoverAndDiagnoseOverloads( _ functions: [ FunctionDeclSyntax ] ) {
27
+ var overloads = [ String: [ FunctionDeclSyntax] ] ( )
28
+ var staticOverloads = [ String: [ FunctionDeclSyntax] ] ( )
29
+ for fn in functions {
30
+ let params = fn. signature. input. parameterList
31
+ guard params. count == 1 else { continue }
32
+ let firstParam = params [ 0 ]
33
+ guard firstParam. type is FunctionTypeSyntax else { continue }
34
+ if let mods = fn. modifiers, mods. has ( modifier: " static " ) || mods. has ( modifier: " class " ) {
35
+ staticOverloads [ fn. identifier. text, default: [ ] ] . append ( fn)
36
+ } else {
37
+ overloads [ fn. identifier. text, default: [ ] ] . append ( fn)
38
+ }
39
+ }
40
+
41
+ diagnoseBadOverloads ( overloads)
42
+ diagnoseBadOverloads ( staticOverloads)
43
+ }
44
+
45
+ public override func visit( _ node: SourceFileSyntax ) {
46
+ let functions = node. statements. compactMap { $0. item as? FunctionDeclSyntax }
47
+ discoverAndDiagnoseOverloads ( functions)
48
+ super. visit ( node)
49
+ }
50
+
51
+ public override func visit( _ node: CodeBlockSyntax ) {
52
+ let functions = node. statements. compactMap { $0. item as? FunctionDeclSyntax }
53
+ discoverAndDiagnoseOverloads ( functions)
54
+ super. visit ( node)
55
+ }
56
+
57
+ public override func visit( _ decls: MemberDeclBlockSyntax ) {
58
+ let functions = decls. members. compactMap { $0. decl as? FunctionDeclSyntax }
59
+ discoverAndDiagnoseOverloads ( functions)
60
+ super. visit ( decls)
61
+ }
62
+ }
63
+
64
+ extension Diagnostic . Message {
65
+ static func ambiguousTrailingClosureOverload( _ decl: String ) -> Diagnostic . Message {
66
+ return . init( . warning, " rename ' \( decl) ' so it is no longer ambiguous with a trailing closure " )
67
+ }
68
+ static func otherAmbiguousOverloadHere( _ decl: String ) -> Diagnostic . Message {
69
+ return . init( . note, " ambiguous overload ' \( decl) ' is here " )
70
+ }
13
71
}
0 commit comments