630d69f02d
Automated-By: Claude Sonnet 4.6
97 lines
2.9 KiB
Swift
97 lines
2.9 KiB
Swift
import Foundation
|
|
|
|
enum SymbolKind: String {
|
|
case `class`, `struct`, `enum`, `protocol`, actor
|
|
case `extension` = "ext"
|
|
case function = "func"
|
|
case initializer = "init"
|
|
case property = "prop"
|
|
case unknown = "?"
|
|
}
|
|
|
|
struct SymbolInfo {
|
|
var qualifiedName: String // "Application.addWindow" or "Application"
|
|
var typeName: String // parent type ("Application"), empty for top-level types
|
|
var name: String // simple name
|
|
var kind: SymbolKind
|
|
var signature: String // sliced source text from decl start to `{`
|
|
var filePath: String
|
|
var targetName: String
|
|
var isExtensionDecl: Bool
|
|
var accessLevel: String // "pub", "priv", or "" (internal)
|
|
var isAsync: Bool
|
|
var isThrows: Bool
|
|
var returnType: String?
|
|
var superclass: String?
|
|
var conformances: [String]
|
|
var selectionLine: Int
|
|
var selectionChar: Int
|
|
}
|
|
|
|
struct CallEdge {
|
|
var callerQualified: String
|
|
var calleeQualified: String // "" if external
|
|
var calleeDisplay: String // "~name" prefix if external
|
|
var isExternal: Bool
|
|
}
|
|
|
|
struct ExtensionInfo {
|
|
var baseType: String
|
|
var conformances: [String]
|
|
}
|
|
|
|
class SymbolTable {
|
|
var symbols: [String: SymbolInfo] = [:]
|
|
var fileSymbols: [String: [SymbolInfo]] = [:]
|
|
var fileExtensions: [String: [ExtensionInfo]] = [:]
|
|
var fileTargets: [String: String] = [:]
|
|
var callEdges: [String: [CallEdge]] = [:]
|
|
var reverseEdges: [String: [String]] = [:]
|
|
var conformanceMap: [String: Set<String>] = [:]
|
|
var implementorMap: [String: [String]] = [:]
|
|
|
|
func registerSymbol(_ sym: SymbolInfo) {
|
|
if sym.kind != .extension {
|
|
symbols[sym.qualifiedName] = sym
|
|
}
|
|
fileSymbols[sym.filePath, default: []].append(sym)
|
|
|
|
let owner = sym.typeName.isEmpty ? sym.name : sym.typeName
|
|
for proto in sym.conformances {
|
|
conformanceMap[owner, default: []].insert(proto)
|
|
}
|
|
}
|
|
|
|
func registerExtension(_ ext: ExtensionInfo, filePath: String) {
|
|
fileExtensions[filePath, default: []].append(ext)
|
|
for proto in ext.conformances {
|
|
conformanceMap[ext.baseType, default: []].insert(proto)
|
|
}
|
|
}
|
|
|
|
func addCallEdge(_ edge: CallEdge) {
|
|
callEdges[edge.callerQualified, default: []].append(edge)
|
|
}
|
|
|
|
func buildReverseIndex() {
|
|
reverseEdges = [:]
|
|
for (caller, edges) in callEdges {
|
|
for edge in edges where !edge.isExternal {
|
|
reverseEdges[edge.calleeQualified, default: []].append(caller)
|
|
}
|
|
}
|
|
}
|
|
|
|
func buildImplementorMap() {
|
|
implementorMap = [:]
|
|
for (typeName, protos) in conformanceMap {
|
|
for proto in protos {
|
|
implementorMap[proto, default: []].append(typeName)
|
|
}
|
|
}
|
|
for key in implementorMap.keys {
|
|
implementorMap[key]?.sort()
|
|
}
|
|
}
|
|
}
|