Skip to content

Commit 4e60dac

Browse files
committed
Factor out function for querying document symbols for URI
1 parent fd0b803 commit 4e60dac

File tree

1 file changed

+87
-68
lines changed

1 file changed

+87
-68
lines changed

Sources/SourceKitLSP/Swift/SwiftLanguageServer.swift

Lines changed: 87 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -507,86 +507,105 @@ extension SwiftLanguageServer {
507507
}
508508
}
509509

510-
public func documentSymbol(_ req: Request<DocumentSymbolRequest>) {
511-
let keys = self.keys
510+
// Must be called on self.queue
511+
private func _documentSymbols(
512+
_ uri: DocumentURI,
513+
_ completion: @escaping (Result<[DocumentSymbol], ResponseError>) -> Void
514+
) {
515+
if #available(macOS 10.12, *) {
516+
dispatchPrecondition(condition: .onQueue(queue))
517+
}
512518

513-
queue.async {
514-
guard let snapshot = self.documentManager.latestSnapshot(req.params.textDocument.uri) else {
515-
log("failed to find snapshot for url \(req.params.textDocument.uri)")
516-
req.reply(nil)
517-
return
519+
guard let snapshot = self.documentManager.latestSnapshot(uri) else {
520+
let msg = "failed to find snapshot for url \(uri)"
521+
log(msg)
522+
return completion(.failure(.unknown(msg)))
523+
}
524+
525+
let skreq = SKDRequestDictionary(sourcekitd: self.sourcekitd)
526+
skreq[keys.request] = self.requests.editor_open
527+
skreq[keys.name] = "DocumentSymbols:" + snapshot.document.uri.pseudoPath
528+
skreq[keys.sourcetext] = snapshot.text
529+
skreq[keys.syntactic_only] = 1
530+
531+
let handle = self.sourcekitd.send(skreq, self.queue) { [weak self] result in
532+
guard let self = self else { return }
533+
guard let dict = result.success else {
534+
return completion(.failure(ResponseError(result.failure!)))
535+
}
536+
guard let results: SKDResponseArray = dict[self.keys.substructure] else {
537+
return completion(.success([]))
518538
}
519539

520-
let skreq = SKDRequestDictionary(sourcekitd: self.sourcekitd)
521-
skreq[keys.request] = self.requests.editor_open
522-
skreq[keys.name] = "DocumentSymbols:" + snapshot.document.uri.pseudoPath
523-
skreq[keys.sourcetext] = snapshot.text
524-
skreq[keys.syntactic_only] = 1
540+
func documentSymbol(value: SKDResponseDictionary) -> DocumentSymbol? {
541+
guard let name: String = value[self.keys.name],
542+
let uid: sourcekitd_uid_t = value[self.keys.kind],
543+
let kind: SymbolKind = uid.asSymbolKind(self.values),
544+
let offset: Int = value[self.keys.offset],
545+
let start: Position = snapshot.positionOf(utf8Offset: offset),
546+
let length: Int = value[self.keys.length],
547+
let end: Position = snapshot.positionOf(utf8Offset: offset + length) else {
548+
return nil
549+
}
525550

526-
let handle = self.sourcekitd.send(skreq, self.queue) { [weak self] result in
527-
guard let self = self else { return }
528-
guard let dict = result.success else {
529-
req.reply(.failure(ResponseError(result.failure!)))
530-
return
551+
let range = start..<end
552+
let selectionRange: Range<Position>
553+
if let nameOffset: Int = value[self.keys.nameoffset],
554+
let nameStart: Position = snapshot.positionOf(utf8Offset: nameOffset),
555+
let nameLength: Int = value[self.keys.namelength],
556+
let nameEnd: Position = snapshot.positionOf(utf8Offset: nameOffset + nameLength) {
557+
selectionRange = nameStart..<nameEnd
558+
} else {
559+
selectionRange = range
531560
}
532-
guard let results: SKDResponseArray = dict[self.keys.substructure] else {
533-
return req.reply(.documentSymbols([]))
561+
562+
let children: [DocumentSymbol]?
563+
if let substructure: SKDResponseArray = value[self.keys.substructure] {
564+
children = documentSymbols(array: substructure)
565+
} else {
566+
children = nil
534567
}
568+
return DocumentSymbol(name: name,
569+
detail: nil,
570+
kind: kind,
571+
deprecated: nil,
572+
range: range,
573+
selectionRange: selectionRange,
574+
children: children)
575+
}
535576

536-
func documentSymbol(value: SKDResponseDictionary) -> DocumentSymbol? {
537-
guard let name: String = value[self.keys.name],
538-
let uid: sourcekitd_uid_t = value[self.keys.kind],
539-
let kind: SymbolKind = uid.asSymbolKind(self.values),
540-
let offset: Int = value[self.keys.offset],
541-
let start: Position = snapshot.positionOf(utf8Offset: offset),
542-
let length: Int = value[self.keys.length],
543-
let end: Position = snapshot.positionOf(utf8Offset: offset + length) else {
544-
return nil
577+
func documentSymbols(array: SKDResponseArray) -> [DocumentSymbol] {
578+
var result: [DocumentSymbol] = []
579+
array.forEach { (i: Int, value: SKDResponseDictionary) in
580+
if let documentSymbol = documentSymbol(value: value) {
581+
result.append(documentSymbol)
582+
} else if let substructure: SKDResponseArray = value[self.keys.substructure] {
583+
result += documentSymbols(array: substructure)
545584
}
585+
return true
586+
}
587+
return result
588+
}
546589

547-
let range = start..<end
548-
let selectionRange: Range<Position>
549-
if let nameOffset: Int = value[self.keys.nameoffset],
550-
let nameStart: Position = snapshot.positionOf(utf8Offset: nameOffset),
551-
let nameLength: Int = value[self.keys.namelength],
552-
let nameEnd: Position = snapshot.positionOf(utf8Offset: nameOffset + nameLength) {
553-
selectionRange = nameStart..<nameEnd
554-
} else {
555-
selectionRange = range
556-
}
590+
completion(.success(documentSymbols(array: results)))
591+
}
557592

558-
let children: [DocumentSymbol]?
559-
if let substructure: SKDResponseArray = value[self.keys.substructure] {
560-
children = documentSymbols(array: substructure)
561-
} else {
562-
children = nil
563-
}
564-
return DocumentSymbol(name: name,
565-
detail: nil,
566-
kind: kind,
567-
deprecated: nil,
568-
range: range,
569-
selectionRange: selectionRange,
570-
children: children)
571-
}
593+
// FIXME: cancellation
594+
_ = handle
595+
}
572596

573-
func documentSymbols(array: SKDResponseArray) -> [DocumentSymbol] {
574-
var result: [DocumentSymbol] = []
575-
array.forEach { (i: Int, value: SKDResponseDictionary) in
576-
if let documentSymbol = documentSymbol(value: value) {
577-
result.append(documentSymbol)
578-
} else if let substructure: SKDResponseArray = value[self.keys.substructure] {
579-
result += documentSymbols(array: substructure)
580-
}
581-
return true
582-
}
583-
return result
584-
}
597+
public func documentSymbols(
598+
_ uri: DocumentURI,
599+
_ completion: @escaping (Result<[DocumentSymbol], ResponseError>) -> Void
600+
) {
601+
queue.async {
602+
self._documentSymbols(uri, completion)
603+
}
604+
}
585605

586-
req.reply(.documentSymbols(documentSymbols(array: results)))
587-
}
588-
// FIXME: cancellation
589-
_ = handle
606+
public func documentSymbol(_ req: Request<DocumentSymbolRequest>) {
607+
documentSymbols(req.params.textDocument.uri) { result in
608+
req.reply(result.map { .documentSymbols($0) })
590609
}
591610
}
592611

0 commit comments

Comments
 (0)