@@ -69,4 +69,140 @@ final class InterfaceTypeTests: XCTestCase {
69
69
XCTAssertEqual ( symbol. api. name, " A " )
70
70
}
71
71
}
72
+
73
+ func testFunctionsInPublicExtension( ) throws {
74
+ let source = #"""
75
+ public extension Int {
76
+ func a() {}
77
+ public func b() {}
78
+ internal func c() {}
79
+ fileprivate func d() {}
80
+ private func e() {}
81
+ }
82
+ """#
83
+
84
+ let url = try temporaryFile ( contents: source)
85
+ let sourceFile = try SourceFile ( file: url, relativeTo: url. deletingLastPathComponent ( ) )
86
+ let module = Module ( name: " Module " , sourceFiles: [ sourceFile] )
87
+
88
+ XCTAssertEqual ( sourceFile. symbols. count, 5 )
89
+ XCTAssertTrue ( sourceFile. symbols [ 0 ] . isPublic, " Function `a()` should BE marked as public - its visibility is specified by extension " )
90
+ XCTAssertTrue ( sourceFile. symbols [ 1 ] . isPublic, " Function `b()` should BE marked as public - its visibility is public " )
91
+ XCTAssertFalse ( sourceFile. symbols [ 2 ] . isPublic, " Function `c()` should NOT be marked as public - its visibility is internal " )
92
+ XCTAssertFalse ( sourceFile. symbols [ 3 ] . isPublic, " Function `d()` should NOT be marked as public - its visibility is fileprivate " )
93
+ XCTAssertFalse ( sourceFile. symbols [ 4 ] . isPublic, " Function `e()` should NOT be marked as public - its visibility is private " )
94
+
95
+ XCTAssertEqual ( module. interface. symbols. count, 2 )
96
+ XCTAssertEqual ( module. interface. symbols [ 0 ] . name, " a() " , " Function `a()` should be in documented interface " )
97
+ XCTAssertEqual ( module. interface. symbols [ 1 ] . name, " b() " , " Function `b()` should be in documented interface " )
98
+ }
99
+
100
+ func testComputedPropertiesInPublicExtension( ) throws {
101
+ let source = #"""
102
+ public extension Int {
103
+ var a: Int { 1 }
104
+ public var b: Int { 1 }
105
+ internal var c: Int { 1 }
106
+ fileprivate var d: Int { 1 }
107
+ private var e: Int { 1 }
108
+ }
109
+ """#
110
+
111
+ let url = try temporaryFile ( contents: source)
112
+ let sourceFile = try SourceFile ( file: url, relativeTo: url. deletingLastPathComponent ( ) )
113
+ let module = Module ( name: " Module " , sourceFiles: [ sourceFile] )
114
+
115
+ XCTAssertEqual ( sourceFile. symbols. count, 5 )
116
+ XCTAssertTrue ( sourceFile. symbols [ 0 ] . isPublic, " Property `a` should BE marked as public - its visibility is specified by extension " )
117
+ XCTAssertTrue ( sourceFile. symbols [ 1 ] . isPublic, " Property `b` should BE marked as public - its visibility is public " )
118
+ XCTAssertFalse ( sourceFile. symbols [ 2 ] . isPublic, " Property `c` should NOT be marked as public - its visibility is internal " )
119
+ XCTAssertFalse ( sourceFile. symbols [ 3 ] . isPublic, " Property `d` should NOT be marked as public - its visibility is fileprivate " )
120
+ XCTAssertFalse ( sourceFile. symbols [ 4 ] . isPublic, " Property `e` should NOT be marked as public - its visibility is private " )
121
+
122
+ XCTAssertEqual ( module. interface. symbols. count, 2 )
123
+ XCTAssertEqual ( module. interface. symbols [ 0 ] . name, " a " , " Property `a` should be in documented interface " )
124
+ XCTAssertEqual ( module. interface. symbols [ 1 ] . name, " b " , " Property `b` should be in documented interface " )
125
+ }
126
+
127
+ func testComputedPropertiesWithMultipleAccessModifiersInPublicExtension( ) throws {
128
+ let source = #"""
129
+ public extension Int {
130
+ internal(set) var a: Int {
131
+ get { 1 }
132
+ set {}
133
+ }
134
+ private(set) var b: Int {
135
+ get { 1 }
136
+ set {}
137
+ }
138
+ public internal(set) var c: Int {
139
+ get { 1 }
140
+ set {}
141
+ }
142
+ public fileprivate(set) var d: Int {
143
+ get { 1 }
144
+ set {}
145
+ }
146
+ public private(set) var e: Int {
147
+ get { 1 }
148
+ set {}
149
+ }
150
+ }
151
+ """#
152
+
153
+ let url = try temporaryFile ( contents: source)
154
+ let sourceFile = try SourceFile ( file: url, relativeTo: url. deletingLastPathComponent ( ) )
155
+ let module = Module ( name: " Module " , sourceFiles: [ sourceFile] )
156
+
157
+ XCTAssertEqual ( sourceFile. symbols. count, 5 )
158
+ XCTAssertTrue ( sourceFile. symbols [ 0 ] . isPublic, " Property `a` should be marked as public - the visibility of its getter is public " )
159
+ XCTAssertTrue ( sourceFile. symbols [ 1 ] . isPublic, " Property `b` should be marked as public - the visibility of its getter is public " )
160
+ XCTAssertTrue ( sourceFile. symbols [ 2 ] . isPublic, " Property `c` should be marked as public - the visibility of its getter is public " )
161
+ XCTAssertTrue ( sourceFile. symbols [ 3 ] . isPublic, " Property `d` should be marked as public - the visibility of its getter is public " )
162
+ XCTAssertTrue ( sourceFile. symbols [ 4 ] . isPublic, " Property `e` should be marked as public - the visibility of its getter is public " )
163
+
164
+ XCTAssertEqual ( module. interface. symbols. count, 5 )
165
+ XCTAssertEqual ( module. interface. symbols [ 0 ] . name, " a " , " Property `a` should be in documented interface " )
166
+ XCTAssertEqual ( module. interface. symbols [ 1 ] . name, " b " , " Property `b` should be in documented interface " )
167
+ XCTAssertEqual ( module. interface. symbols [ 2 ] . name, " c " , " Property `c` should be in documented interface " )
168
+ XCTAssertEqual ( module. interface. symbols [ 3 ] . name, " d " , " Property `d` should be in documented interface " )
169
+ XCTAssertEqual ( module. interface. symbols [ 4 ] . name, " e " , " Property `e` should be in documented interface " )
170
+ }
171
+
172
+ func testNestedPropertiesInPublicExtension( ) throws {
173
+ let source = #"""
174
+ public class RootController {}
175
+
176
+ public extension RootController {
177
+ class ControllerExtension {
178
+ public var public_properties: ExtendedProperties = ExtendedProperties()
179
+ internal var internal_properties: InternalProperties = InternalProperties()
180
+ }
181
+ }
182
+
183
+ public extension RootController.ControllerExtension {
184
+ struct ExtendedProperties {
185
+ public var public_prop: Int = 1
186
+ }
187
+ }
188
+
189
+ internal extension RootController.ControllerExtension {
190
+ struct InternalProperties {
191
+ internal var internal_prop: String = "FOO"
192
+ }
193
+ }
194
+ """#
195
+
196
+
197
+ let url = try temporaryFile ( contents: source)
198
+ let sourceFile = try SourceFile ( file: url, relativeTo: url. deletingLastPathComponent ( ) )
199
+ let module = Module ( name: " Module " , sourceFiles: [ sourceFile] )
200
+
201
+ XCTAssertEqual ( module. interface. symbols. count, 5 )
202
+ XCTAssertEqual ( module. interface. symbols [ 0 ] . name, " RootController " )
203
+ XCTAssertEqual ( module. interface. symbols [ 1 ] . name, " ControllerExtension " )
204
+ XCTAssertEqual ( module. interface. symbols [ 2 ] . name, " public_properties " )
205
+ XCTAssertEqual ( module. interface. symbols [ 3 ] . name, " ExtendedProperties " )
206
+ XCTAssertEqual ( module. interface. symbols [ 4 ] . name, " public_prop " )
207
+ }
72
208
}
0 commit comments