Skip to content

Commit b17d282

Browse files
committed
Add parseDeclarationInterfaceNode to parse all declaration contexts
1 parent 3a0b5e5 commit b17d282

File tree

3 files changed

+146
-189
lines changed

3 files changed

+146
-189
lines changed

Tool/Sources/FocusedCodeFinder/ObjectiveC/ObjectiveCCodeFinder.swift

Lines changed: 53 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ public class ObjectiveCFocusedCodeFinder: KnownLanguageFocusedCodeFinder<
7171
) -> NodeInfo? {
7272
switch ObjectiveCNodeType(rawValue: node.nodeType ?? "") {
7373
case .classInterface, .categoryInterface:
74-
return parseClassInterfaceNode(node, textProvider: textProvider)
74+
return parseDeclarationInterfaceNode(node, textProvider: textProvider)
7575
case .classImplementation, .categoryImplementation:
76-
return parseClassImplementationNode(node, textProvider: textProvider)
76+
return parseDeclarationInterfaceNode(node, textProvider: textProvider)
7777
case .protocolDeclaration:
78-
return parseProtocolNode(node, textProvider: textProvider)
78+
return parseDeclarationInterfaceNode(node, textProvider: textProvider)
7979
case .methodDefinition:
8080
return parseMethodDefinitionNode(node, textProvider: textProvider)
8181
case .functionDefinition:
@@ -89,16 +89,23 @@ public class ObjectiveCFocusedCodeFinder: KnownLanguageFocusedCodeFinder<
8989
}
9090
}
9191

92-
func parseClassInterfaceNode(
92+
func parseDeclarationInterfaceNode(
9393
_ node: ASTNode,
9494
textProvider: @escaping TextProvider
9595
) -> NodeInfo? {
9696
var name = ""
97-
var superClass = ""
9897
var category = ""
99-
var protocols = [String]()
98+
/// Attributes, declaration kind, and name.
99+
var prefix = ""
100+
/// Generics, super class, etc.
101+
var extra = ""
102+
100103
if let nameNode = node.child(byFieldName: "name") {
101104
name = textProvider(.node(nameNode))
105+
prefix = textProvider(.range(
106+
range: node.range.notSurpassing(nameNode.range),
107+
pointRange: node.pointRange.notSurpassing(nameNode.pointRange)
108+
))
102109
}
103110
if let categoryNode = node.child(byFieldName: "category") {
104111
category = textProvider(.node(categoryNode))
@@ -107,135 +114,45 @@ public class ObjectiveCFocusedCodeFinder: KnownLanguageFocusedCodeFinder<
107114
for i in 0..<node.childCount {
108115
guard let childNode = node.child(at: i) else { continue }
109116
switch ObjectiveCNodeType(rawValue: childNode.nodeType) {
110-
case .protocolQualifiers:
111-
var protocolNames = [String]()
112-
for j in 0..<childNode.childCount {
113-
guard let protocolNode = childNode.child(at: j) else { continue }
114-
guard ObjectiveCNodeType(rawValue: protocolNode.nodeType) == .identifier
115-
else { continue }
116-
protocolNames.append(
117-
textProvider(.node(protocolNode))
118-
.trimmingCharacters(in: .whitespacesAndNewlines)
119-
)
117+
case .superclassReference,
118+
.protocolQualifiers,
119+
.parameterizedClassTypeArguments:
120+
extra.append(textProvider(.node(childNode)))
121+
case .genericsTypeReference:
122+
// When it's a category of a generic type, e.g.
123+
// @interface __GENERICS(NSArray, ObjectType) (BlocksKit)
124+
if let nameNode = childNode.child(byFieldName: "name") {
125+
name = textProvider(.node(nameNode))
120126
}
121-
protocols = protocolNames.filter { $0 != "," && !$0.isEmpty }
122-
case .superclassReference:
123-
if let superClassNode = childNode.child(byFieldName: "name") {
124-
superClass = textProvider(.node(superClassNode))
125-
.trimmingCharacters(in: .whitespacesAndNewlines)
126-
}
127-
default:
128-
continue
127+
prefix = textProvider(.range(
128+
range: node.range.notSurpassing(childNode.range),
129+
pointRange: node.pointRange.notSurpassing(childNode.pointRange)
130+
))
131+
default: continue
129132
}
130133
}
131134

132-
var signature = "@interface \(name)"
133-
if !category.isEmpty {
134-
signature += " (\(category))"
135-
}
136-
if !protocols.isEmpty {
137-
signature += "<\(protocols.joined(separator: ", "))>"
138-
}
139-
if !superClass.isEmpty {
140-
signature += ": \(superClass)"
141-
}
142-
143-
return .init(
144-
node: node,
145-
signature: signature,
146-
name: name,
147-
canBeUsedAsCodeRange: true
148-
)
149-
}
150-
151-
func parseClassImplementationNode(
152-
_ node: ASTNode,
153-
textProvider: @escaping TextProvider
154-
) -> NodeInfo? {
155-
var name = ""
156-
var superClass = ""
157-
var category = ""
158-
var protocols = [String]()
159-
if let nameNode = node.child(byFieldName: "name") {
160-
name = textProvider(.node(nameNode))
161-
}
162-
if let categoryNode = node.child(byFieldName: "category") {
163-
category = textProvider(.node(categoryNode))
164-
}
165-
166-
for i in 0..<node.childCount {
167-
guard let childNode = node.child(at: i) else { continue }
168-
switch ObjectiveCNodeType(rawValue: childNode.nodeType) {
169-
case .protocolQualifiers:
170-
var protocolNames = [String]()
171-
for j in 0..<childNode.childCount {
172-
guard let protocolNode = childNode.child(at: j) else { continue }
173-
guard ObjectiveCNodeType(rawValue: protocolNode.nodeType) == .identifier
174-
else { continue }
175-
protocolNames.append(
176-
textProvider(.node(protocolNode))
177-
.trimmingCharacters(in: .whitespacesAndNewlines)
178-
)
179-
}
180-
protocols = protocolNames.filter { $0 != "," && !$0.isEmpty }
181-
case .superclassReference:
182-
if let superClassNode = childNode.child(byFieldName: "name") {
183-
superClass = textProvider(.node(superClassNode))
184-
.trimmingCharacters(in: .whitespacesAndNewlines)
185-
}
186-
default:
187-
continue
188-
}
189-
}
135+
prefix = prefix.split(separator: "\n")
136+
.joined(separator: " ")
137+
.trimmingCharacters(in: .whitespacesAndNewlines)
138+
139+
extra = extra.split(separator: "\n")
140+
.joined(separator: " ")
141+
.trimmingCharacters(in: .whitespacesAndNewlines)
190142

191-
var signature = "@implementation \(name)"
143+
var signature = "\(prefix)\(extra)"
192144
if !category.isEmpty {
193145
signature += " (\(category))"
194146
}
195-
if !protocols.isEmpty {
196-
signature += "<\(protocols.joined(separator: ", "))>"
197-
}
198-
if !superClass.isEmpty {
199-
signature += ": \(superClass)"
200-
}
201-
return .init(
202-
node: node,
203-
signature: signature,
204-
name: name,
205-
canBeUsedAsCodeRange: true
206-
)
207-
}
208147

209-
func parseProtocolNode(
210-
_ node: ASTNode,
211-
textProvider: @escaping TextProvider
212-
) -> NodeInfo? {
213-
var name = ""
214-
var protocols = [String]()
215-
if let nameNode = node.child(byFieldName: "name") {
216-
name = textProvider(.node(nameNode))
217-
}
218-
if let protocolsNode = node.child(byFieldName: "protocols") {
219-
for protocolNode in protocolsNode.children {
220-
let protocolName = textProvider(.node(protocolNode))
221-
if !protocolName.isEmpty {
222-
protocols.append(protocolName)
223-
}
224-
}
225-
}
226-
227-
var signature = "@protocol \(name)"
228-
if !protocols.isEmpty {
229-
signature += "<\(protocols.joined(separator: ","))>"
230-
}
231148
return .init(
232149
node: node,
233150
signature: signature,
234151
name: name,
235152
canBeUsedAsCodeRange: true
236153
)
237154
}
238-
155+
239156
func parseMethodDefinitionNode(
240157
_ node: ASTNode,
241158
textProvider: @escaping TextProvider
@@ -273,7 +190,7 @@ public class ObjectiveCFocusedCodeFinder: KnownLanguageFocusedCodeFinder<
273190
signaturePointRange
274191
) = node.extractInformationBeforeNode(withFieldName: "body")
275192
let signature = textProvider(.range(range: signatureRange, pointRange: signaturePointRange))
276-
.replacingOccurrences(of: "\n", with: "")
193+
.replacingOccurrences(of: "\n", with: " ")
277194
.trimmingCharacters(in: .whitespacesAndNewlines)
278195
if signature.isEmpty { return nil }
279196
return .init(
@@ -342,6 +259,12 @@ extension NSRange {
342259
let end = Swift.max(lowerBound, Swift.min(upperBound, range.lowerBound))
343260
return NSRange(location: start, length: end - start)
344261
}
262+
263+
func notSurpassing(_ range: NSRange) -> NSRange {
264+
let start = lowerBound
265+
let end = Swift.max(lowerBound, Swift.min(upperBound, range.upperBound))
266+
return NSRange(location: start, length: end - start)
267+
}
345268
}
346269

347270
extension Range where Bound == Point {
@@ -354,5 +277,15 @@ extension Range where Bound == Point {
354277
}
355278
return Range(uncheckedBounds: (start, end))
356279
}
280+
281+
func notSurpassing(_ range: Range<Bound>) -> Range<Bound> {
282+
let start = lowerBound
283+
let end = if range.lowerBound >= upperBound {
284+
upperBound
285+
} else {
286+
Swift.max(range.upperBound, lowerBound)
287+
}
288+
return Range(uncheckedBounds: (start, end))
289+
}
357290
}
358291

Tool/Sources/FocusedCodeFinder/ObjectiveC/ObjectiveCSyntax.swift

Lines changed: 11 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import Foundation
22

3-
/// https://github.com/merico-dev/tree-sitter-objc/test/corpus/imports.txt
4-
/// https://github.com/merico-dev/tree-sitter-objc/test/corpus/expressions.txt
5-
/// https://github.com/merico-dev/tree-sitter-objc/test/corpus/declarations.txt
6-
/// https://github.com/merico-dev/tree-sitter-objc/node-types.json
3+
/// https://github.com/lukepistrol/tree-sitter-objc/blob/feature/spm/test/corpus/imports.txt
4+
/// https://github.com/lukepistrol/tree-sitter-objc/blob/feature/spm/test/corpus/expressions.txt
5+
/// https://github.com/lukepistrol/tree-sitter-objc/blob/feature/spm/test/corpus/declarations.txt
6+
/// https://github.com/lukepistrol/tree-sitter-objc/blob/feature/spm/node-types.json
7+
/// Some of the test cases are actually incorrect?
78
enum ObjectiveCNodeType: String {
89
/// The top most item
910
case translationUnit = "translation_unit"
@@ -22,26 +23,6 @@ enum ObjectiveCNodeType: String {
2223
/// + (tr)k1:(t1)a1 : (t2)a2 k2: a3;
2324
/// @end
2425
/// ```
25-
///
26-
/// will parse into:
27-
/// ```
28-
/// (translation_unit
29-
/// (class_interface
30-
/// name: (identifier)
31-
/// superclass: (identifier))) < SuperClass
32-
/// protocols: (protocol_reference_list < Protocols
33-
/// (identifier)
34-
/// (identifier))))
35-
/// (field_declaration < iv1
36-
/// type: (type_identifier)
37-
/// declarator: (field_identifier))
38-
/// (field_declaration < iv2
39-
/// type: (type_identifier)
40-
/// declarator: (field_identifier))))
41-
/// (property_declaration ...) < property value
42-
/// (method_declaration ...) < method
43-
/// ```
44-
///
4526
case classInterface = "class_interface"
4627
/// `@implementation`
4728
case classImplementation = "class_implementation"
@@ -56,52 +37,14 @@ enum ObjectiveCNodeType: String {
5637
/// ```objc
5738
/// @class C1, C2;
5839
/// ```
59-
///
60-
/// will parse into:
61-
/// ```
62-
/// (translation_unit
63-
/// (class_declaration_list
64-
/// (identifier)
65-
/// (identifier)))
66-
/// ```
6740
case classDeclarationList = "class_declaration_list"
6841
/// ```
6942
/// + (tr)k1: (t1)a1 : (t2)a2 k2: a3;
7043
/// ```
71-
///
72-
/// will parse into:
73-
/// ```
74-
/// (property_declaration
75-
/// (readwrite)
76-
/// (copy)
77-
/// type: (type_identifier) < type
78-
/// name: (identifier)))) < name
79-
/// ```
8044
case propertyDeclaration = "property_declaration"
8145
/// ```objc
8246
/// + (tr)k1: (t1)a1 : (t2)a2 k2: a3;
8347
/// ```
84-
///
85-
/// will parse into:
86-
/// ```
87-
/// (method_declaration
88-
/// scope: (class_scope)
89-
/// return_type: (type_descriptor
90-
/// type: (type_identifier))
91-
/// selector: (keyword_selector
92-
/// (keyword_declarator
93-
/// keyword: (identifier)
94-
/// type: (type_descriptor
95-
/// type: (type_identifier))
96-
/// name: (identifier))
97-
/// (keyword_declarator
98-
/// type: (type_descriptor
99-
/// type: (type_identifier))
100-
/// name: (identifier))
101-
/// (keyword_declarator
102-
/// keyword: (identifier)
103-
/// name: (identifier))))))
104-
/// ```
10548
case methodDeclaration = "method_declaration"
10649
/// `- (rt)sel {}`
10750
case methodDefinition = "method_definition"
@@ -127,6 +70,12 @@ enum ObjectiveCNodeType: String {
12770
case protocolQualifiers = "protocol_qualifiers"
12871
/// Superclass of a type.
12972
case superclassReference = "superclass_reference"
73+
/// The generic type arguments.
74+
case parameterizedClassTypeArguments = "parameterized_class_type_arguments"
75+
/// `__GENERICS` in category interface and implementation.
76+
case genericsTypeReference = "generics_type_reference"
77+
/// `IB_DESIGNABLE`, etc. The typo is from the original source.
78+
case classInterfaceAttributeSpecifier = "class_interface_attribute_sepcifier"
13079
}
13180

13281
extension ObjectiveCNodeType {

0 commit comments

Comments
 (0)