Skip to content

Commit f9c5301

Browse files
committed
Add ObjectiveCFocusedCodeFinder
1 parent 3516f57 commit f9c5301

14 files changed

+1040
-280
lines changed

Pro

Submodule Pro updated from c916c13 to c0ffa88
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import Foundation
2+
import SwiftTreeSitter
3+
4+
public enum ASTTreeVisitorContinueKind {
5+
/// The visitor should visit the descendants of the current node.
6+
case visitChildren
7+
/// The visitor should avoid visiting the descendants of the current node.
8+
case skipChildren
9+
}
10+
11+
// A SwiftSyntax style tree visitor.
12+
open class ASTTreeVisitor {
13+
public let tree: ASTTree
14+
15+
public init(tree: ASTTree) {
16+
self.tree = tree
17+
}
18+
19+
public func walk() {
20+
guard let cursor = tree.rootNode?.treeCursor else { return }
21+
visit(cursor)
22+
}
23+
24+
public func walk(_ node: ASTNode) {
25+
let cursor = node.treeCursor
26+
visit(cursor)
27+
}
28+
29+
open func visit(_: ASTNode) -> ASTTreeVisitorContinueKind {
30+
// do nothing
31+
return .skipChildren
32+
}
33+
34+
open func visitPost(_: ASTNode) {
35+
// do nothing
36+
}
37+
38+
private func visit(_ cursor: TreeCursor) {
39+
guard let currentNode = cursor.currentNode else { return }
40+
let continueKind = visit(currentNode)
41+
42+
switch continueKind {
43+
case .skipChildren:
44+
visitPost(currentNode)
45+
case .visitChildren:
46+
visitChildren(cursor)
47+
visitPost(currentNode)
48+
}
49+
}
50+
51+
private func visitChildren(_ cursor: TreeCursor) {
52+
let hasChild = cursor.goToFirstChild()
53+
guard hasChild else { return }
54+
visit(cursor)
55+
while cursor.goToNextSibling() {
56+
visit(cursor)
57+
}
58+
_ = cursor.gotoParent()
59+
}
60+
}
61+

Tool/Sources/FocusedCodeFinder/FocusedCodeFinder.swift

Lines changed: 14 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ public struct CodeContext: Equatable {
2929
public var includes: [String]
3030

3131
public static var empty: CodeContext {
32-
.init(scope: .file, contextRange: .zero, focusedRange: .zero, focusedCode: "", imports: [])
32+
.init(
33+
scope: .file,
34+
contextRange: .zero,
35+
focusedRange: .zero,
36+
focusedCode: "",
37+
imports: [],
38+
includes: []
39+
)
3340
}
3441

3542
public init(
@@ -51,19 +58,19 @@ public struct CodeContext: Equatable {
5158

5259
public struct FocusedCodeFinder {
5360
public init() {}
54-
61+
5562
public struct Document {
5663
var documentURL: URL
5764
var content: String
5865
var lines: [String]
59-
66+
6067
public init(documentURL: URL, content: String, lines: [String]) {
6168
self.documentURL = documentURL
6269
self.content = content
6370
self.lines = lines
6471
}
6572
}
66-
73+
6774
public func findFocusedCode(
6875
in document: Document,
6976
containingRange: CursorRange,
@@ -73,6 +80,8 @@ public struct FocusedCodeFinder {
7380
switch language {
7481
case .builtIn(.swift):
7582
return SwiftFocusedCodeFinder()
83+
case .builtIn(.objc), .builtIn(.objcpp), .builtIn(.c):
84+
return ObjectiveCFocusedCodeFinder()
7685
default:
7786
return UnknownLanguageFocusedCodeFinder(proposedSearchRange: 5)
7887
}
@@ -84,83 +93,10 @@ public struct FocusedCodeFinder {
8493

8594
public protocol FocusedCodeFinderType {
8695
typealias Document = FocusedCodeFinder.Document
87-
96+
8897
func findFocusedCode(
8998
in document: Document,
9099
containingRange: CursorRange
91100
) -> CodeContext
92101
}
93102

94-
public struct UnknownLanguageFocusedCodeFinder: FocusedCodeFinderType {
95-
let proposedSearchRange: Int
96-
97-
public init(proposedSearchRange: Int) {
98-
self.proposedSearchRange = proposedSearchRange
99-
}
100-
101-
public func findFocusedCode(
102-
in document: Document,
103-
containingRange: CursorRange
104-
) -> CodeContext {
105-
guard !document.lines.isEmpty else { return .empty }
106-
107-
// when user is not selecting any code.
108-
if containingRange.start == containingRange.end {
109-
// search up and down for up to `proposedSearchRange * 2 + 1` lines.
110-
let lines = document.lines
111-
let proposedLineCount = proposedSearchRange * 2 + 1
112-
let startLineIndex = max(containingRange.start.line - proposedSearchRange, 0)
113-
let endLineIndex = min(
114-
max(
115-
startLineIndex,
116-
min(startLineIndex + proposedLineCount - 1, lines.count - 1)
117-
),
118-
lines.count - 1
119-
)
120-
121-
guard endLineIndex >= startLineIndex else { return .empty }
122-
let focusedLines = lines[startLineIndex...endLineIndex]
123-
124-
let contextStartLine = max(startLineIndex - 5, 0)
125-
let contextEndLine = min(endLineIndex + 5, lines.count - 1)
126-
127-
return .init(
128-
scope: .top,
129-
contextRange: .init(
130-
start: .init(line: contextStartLine, character: 0),
131-
end: .init(line: contextEndLine, character: lines[contextEndLine].count)
132-
),
133-
focusedRange: .init(
134-
start: .init(line: startLineIndex, character: 0),
135-
end: .init(line: endLineIndex, character: lines[endLineIndex].count)
136-
),
137-
focusedCode: focusedLines.joined(),
138-
imports: []
139-
)
140-
}
141-
142-
let startLine = max(containingRange.start.line, 0)
143-
let endLine = min(containingRange.end.line, document.lines.count - 1)
144-
145-
if endLine < startLine { return .empty }
146-
147-
let focusedLines = document.lines[startLine...endLine]
148-
let contextStartLine = max(startLine - 3, 0)
149-
let contextEndLine = min(endLine + 3, document.lines.count - 1)
150-
151-
return CodeContext(
152-
scope: .top,
153-
contextRange: .init(
154-
start: .init(line: contextStartLine, character: 0),
155-
end: .init(
156-
line: contextEndLine,
157-
character: document.lines[contextEndLine].count
158-
)
159-
),
160-
focusedRange: containingRange,
161-
focusedCode: focusedLines.joined(),
162-
imports: []
163-
)
164-
}
165-
}
166-

0 commit comments

Comments
 (0)