Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds support to correctly identify snippet symbolgraphs #89

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions Sources/SymbolKit/UnifiedSymbolGraph/GraphCollector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ extension GraphCollector {
/// - inputGraph: The symbol graph to merge in.
/// - url: The file name where the given symbol graph is located. Used to determine whether a symbol graph
/// contains primary symbols or extensions.
/// - forceLoading: A Boolean value, that defaults to `false`, that indicates whether the graph is merged
heckj marked this conversation as resolved.
Show resolved Hide resolved
/// even though it is a `primary` symbol graph.
///
/// If the symbol graph is the `primary` graph, this method ignore merging the graph if it isn't already
/// registered in the graph collector. To force the loading into the collector, set `forceLoading` to `true`.
public func mergeSymbolGraph(_ inputGraph: SymbolGraph, at url: URL, forceLoading: Bool = false) {
let (extendedModuleName, isMainSymbolGraph) = Self.moduleNameFor(inputGraph, at: url)

Expand Down Expand Up @@ -126,13 +131,25 @@ extension GraphCollector {
/// - url: The file name where the symbol graph is located.
/// - Returns: The name of the module described by `graph`, and whether the symbol graph is a "primary" symbol graph.
public static func moduleNameFor(_ graph: SymbolGraph, at url: URL) -> (String, Bool) {
let isMainSymbolGraph = !url.lastPathComponent.contains("@")
// The Swift compiler generates symbol graph URLs that contain an `@` symbol to denote an
// extension to another modules.
// The snippet extractor generates symbol graph files without an `@` symbol and with the
// the metadata that indicates the module `isVirtual`.
heckj marked this conversation as resolved.
Show resolved Hide resolved
let isMainSymbolGraph = !url.lastPathComponent.contains("@") && !graph.module.isVirtual

let moduleName: String
if isMainSymbolGraph {
// For main symbol graphs, get the module name from the symbol graph's data
moduleName = graph.module.name
return (moduleName, isMainSymbolGraph)
} else {
// Non-main symbol graphs are not only extensions, but also snippets. The correct module name
// for snippets **is** in the graph itself - so in the case where the URl is referencing symbol graph
// generated from snippets, return the name from within the graph.
if url.lastPathComponent.contains("-snippets.symbols.json") {
return (graph.module.name, isMainSymbolGraph)
}

// For extension symbol graphs, derive the extended module's name from the file name.
//
// The per-symbol `extendedModule` value is the same as the main module for most symbols, so it's not a good way to find the name
Expand All @@ -147,7 +164,7 @@ extension GraphCollector {
} else {
moduleName = fileName.split(separator: "@", maxSplits: 1).last.map({ String($0) })!
}
return (moduleName, isMainSymbolGraph)
}
return (moduleName, isMainSymbolGraph)
}
}
58 changes: 58 additions & 0 deletions Tests/SymbolKitTests/UnifiedGraph/GraphCollectorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,62 @@ class GraphCollectorTests: XCTestCase {
XCTAssertEqual(graphB.symbols.count, 1)
XCTAssert(graphB.symbols.keys.contains("s:BB"))
}

func testModuleNameForSymbolGraph() throws {
// aligned with the name "A.symbols.json"
let a = SymbolGraph(metadata: .init(formatVersion: .init(major: 1, minor: 0, patch: 0), generator: "unit-test"),
module: .init(name: "A", platform: .init()),
symbols: [
.init(identifier: .init(precise: "s:AA", interfaceLanguage: "swift"),
names: .init(title: "A", navigator: nil, subHeading: nil, prose: nil),
pathComponents: ["A"],
docComment: nil,
accessLevel: .init(rawValue: "public"),
kind: .init(parsedIdentifier: .class, displayName: "Class"),
mixins: [:])
],
relationships: [])

let (name, isMain) = GraphCollector.moduleNameFor(a, at: .init(fileURLWithPath: "A.symbols.json"))
XCTAssertTrue(isMain)
XCTAssertEqual("A", name)

// aligned with the name "[email protected]"
let a_At_B = SymbolGraph(metadata: .init(formatVersion: .init(major: 1, minor: 0, patch: 0), generator: "unit-test"),
module: .init(name: "A", platform: .init()),
symbols: [
.init(identifier: .init(precise: "s:BBAatB", interfaceLanguage: "swift"),
names: .init(title: "AatB", navigator: nil, subHeading: nil, prose: nil),
pathComponents: ["B", "AatB"],
docComment: nil,
accessLevel: .init(rawValue: "public"),
kind: .init(parsedIdentifier: .class, displayName: "Class"),
mixins: [:])
],
relationships: [])

let (extensionName, extensionIsMain) = GraphCollector.moduleNameFor(a_At_B, at: .init(fileURLWithPath: "[email protected]"))
XCTAssertFalse(extensionIsMain)
XCTAssertEqual("B", extensionName)

// "A-snippets.symbols.json"
let a_snippet = SymbolGraph(metadata: .init(formatVersion: .init(major: 0, minor: 0, patch: 1), generator: "snippet-extract-unit-test-example"),
module: .init(name: "A", platform: .init(), isVirtual: true),
symbols: [
.init(identifier: .init(precise: "Snippet__A.example", interfaceLanguage: "swift"),
names: .init(title: "example", navigator: nil, subHeading: nil, prose: nil),
pathComponents: ["A", "exmaple"],
docComment: nil,
accessLevel: .init(rawValue: "public"),
kind: .init(parsedIdentifier: .snippet, displayName: "example"),
mixins: [:],
isVirtual: true)

],
relationships: [])

let (snippetName, snippetIsMain) = GraphCollector.moduleNameFor(a_snippet, at: .init(fileURLWithPath: "A-snippets.symbols.json"))
XCTAssertFalse(snippetIsMain)
XCTAssertEqual("A", snippetName)
}
}