From 057cf4138488befd8521562b53dda2f215e60b5e Mon Sep 17 00:00:00 2001 From: Ashley Garland Date: Mon, 9 Jan 2023 14:01:52 -0800 Subject: [PATCH 1/2] Prevent adding extra `Snippets` path component when converting to symbol graph symbols rdar://104044227 --- .../snippet-extract/Utility/SymbolGraph+Snippet.swift | 10 +++++++--- .../Snippets/SnippetSymbolTests.swift | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Sources/snippet-extract/Utility/SymbolGraph+Snippet.swift b/Sources/snippet-extract/Utility/SymbolGraph+Snippet.swift index 4e5560a..e122d79 100644 --- a/Sources/snippet-extract/Utility/SymbolGraph+Snippet.swift +++ b/Sources/snippet-extract/Utility/SymbolGraph+Snippet.swift @@ -19,14 +19,18 @@ extension SymbolGraph.Symbol { let identifier = SymbolGraph.Symbol.Identifier(precise: "$snippet__\(moduleName).\(basename)", interfaceLanguage: "swift") let names = SymbolGraph.Symbol.Names.init(title: basename, navigator: nil, subHeading: nil, prose: nil) - var pathComponents = snippet.sourceFile.absoluteURL.deletingPathExtension().pathComponents[...] + var pathComponents = Array(snippet.sourceFile.absoluteURL.deletingPathExtension().pathComponents[...]) guard let snippetsPathComponentIndex = pathComponents.firstIndex(where: { $0 == "Snippets" }) else { throw SnippetExtractCommand.ArgumentError.snippetNotContainedInSnippetsDirectory(snippet.sourceFile) } - pathComponents = pathComponents[snippetsPathComponentIndex...] + + // In theory, there may be differently named snippet root directories in the future. + // Replace that path component with the standardized `Snippets`. + pathComponents.replaceSubrange(pathComponents.startIndex...snippetsPathComponentIndex, + with: CollectionOfOne("Snippets")) let docComment = SymbolGraph.LineList(snippet.explanation .split(separator: "\n", maxSplits: Int.max, omittingEmptySubsequences: false) @@ -39,7 +43,7 @@ extension SymbolGraph.Symbol { self.init(identifier: identifier, names: names, - pathComponents: ["Snippets"] + Array(pathComponents), + pathComponents: pathComponents, docComment: docComment, accessLevel: accessLevel, kind: kind, diff --git a/Tests/SwiftDocCPluginUtilitiesTests/Snippets/SnippetSymbolTests.swift b/Tests/SwiftDocCPluginUtilitiesTests/Snippets/SnippetSymbolTests.swift index d6eb2b1..1fe9877 100644 --- a/Tests/SwiftDocCPluginUtilitiesTests/Snippets/SnippetSymbolTests.swift +++ b/Tests/SwiftDocCPluginUtilitiesTests/Snippets/SnippetSymbolTests.swift @@ -30,4 +30,15 @@ class SnippetSymbolTests: XCTestCase { } }) } + + func testPathComponentsForSnippetSymbol() throws { + let source = """ + // A snippet. + foo() {} + """ + let snippet = Snippets.Snippet(parsing: source, + sourceFile: URL(fileURLWithPath: "/path/to/my-package/Snippets/ASnippet.swift")) + let symbol = try SymbolGraph.Symbol(snippet, moduleName: "my-package") + XCTAssertEqual(["Snippets", "ASnippet"], symbol.pathComponents) + } } From a458deafe5c3e4c52a1b81819fa19bd147307494 Mon Sep 17 00:00:00 2001 From: Ashley Garland Date: Mon, 9 Jan 2023 14:32:01 -0800 Subject: [PATCH 2/2] Copy snippet symbol graphs to the correct final destination The snippet symbol graph is currently being generated with the changes in e013865138b, however they are not being copied to the correct final destination. The `snippet-extract` tool now takes input and output *files* instead of directories, however there is still one place in the plugin where we are still treating the output like a directory, so the snippet symbol graph basename path component looks like a directory, and needs additional basenames to put it in the right place with the correct file extension. rdar://104045850 --- .../SnippetDocumentationGenerationTests.swift | 16 +++++++++++++- ...ackageManager+getSymbolGraphsForDocC.swift | 22 +++++++++---------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/IntegrationTests/Tests/SnippetDocumentationGenerationTests.swift b/IntegrationTests/Tests/SnippetDocumentationGenerationTests.swift index 33c3b9d..3e537ad 100644 --- a/IntegrationTests/Tests/SnippetDocumentationGenerationTests.swift +++ b/IntegrationTests/Tests/SnippetDocumentationGenerationTests.swift @@ -10,10 +10,11 @@ import XCTest final class SnippetDocumentationGenerationTests: ConcurrencyRequiringTestCase { func testGenerateDocumentationForPackageWithSnippets() throws { + let packageName = "PackageWithSnippets" let result = try swiftPackage( "generate-documentation", "--target", "Library", - workingDirectory: try setupTemporaryDirectoryForFixture(named: "PackageWithSnippets") + workingDirectory: try setupTemporaryDirectoryForFixture(named: packageName) ) result.assertExitStatusEquals(0) @@ -45,6 +46,19 @@ final class SnippetDocumentationGenerationTests: ConcurrencyRequiringTestCase { "symbol-graphs/unified-symbol-graphs", ] ) + + let unifiedSymbolGraphDirectory = subDirectoriesOfSymbolGraphDirectory.first { + $0.pathComponents.last == "unified-symbol-graphs" + }! + + let symbolGraphEnumerator = FileManager.default.enumerator(at: unifiedSymbolGraphDirectory, + includingPropertiesForKeys: [.isRegularFileKey])! + let symbolGraphPaths = try (symbolGraphEnumerator.allObjects as! [URL]).filter { + try $0.resourceValues(forKeys: [.isRegularFileKey]).isRegularFile! + } + XCTAssertNotNil(symbolGraphPaths.first { + $0.pathComponents.last == "\(packageName)-snippets.symbols.json" + }) } func testPreviewDocumentationWithSnippets() throws { diff --git a/Plugins/SharedPackagePluginExtensions/PackageManager+getSymbolGraphsForDocC.swift b/Plugins/SharedPackagePluginExtensions/PackageManager+getSymbolGraphsForDocC.swift index 2b12ff3..24c59d1 100644 --- a/Plugins/SharedPackagePluginExtensions/PackageManager+getSymbolGraphsForDocC.swift +++ b/Plugins/SharedPackagePluginExtensions/PackageManager+getSymbolGraphsForDocC.swift @@ -13,22 +13,22 @@ extension PackageManager { struct DocCSymbolGraphResult { let unifiedSymbolGraphsDirectory: URL let targetSymbolGraphsDirectory: URL - let snippetSymbolGraphsDirectory: URL? + let snippetSymbolGraphFile: URL? init( unifiedSymbolGraphsDirectory: URL, targetSymbolGraphsDirectory: URL, - snippetSymbolGraphsDirectory: URL? + snippetSymbolGraphFile: URL? ) { self.unifiedSymbolGraphsDirectory = unifiedSymbolGraphsDirectory self.targetSymbolGraphsDirectory = targetSymbolGraphsDirectory - self.snippetSymbolGraphsDirectory = snippetSymbolGraphsDirectory + self.snippetSymbolGraphFile = snippetSymbolGraphFile } init(targetSymbolGraphsDirectory: URL) { self.unifiedSymbolGraphsDirectory = targetSymbolGraphsDirectory self.targetSymbolGraphsDirectory = targetSymbolGraphsDirectory - self.snippetSymbolGraphsDirectory = nil + self.snippetSymbolGraphFile = nil } } @@ -70,7 +70,7 @@ extension PackageManager { print("snippet extractor provided, attempting to generate snippet symbol graph") } - guard let snippetSymbolGraphsDirectory = try snippetExtractor.generateSnippets( + guard let snippetSymbolGraphFile = try snippetExtractor.generateSnippets( for: target, context: context ) else { @@ -82,7 +82,7 @@ extension PackageManager { } if verbose { - print("snippet symbol graph directory path: '\(snippetSymbolGraphsDirectory.path)'") + print("snippet symbol graph file: '\(snippetSymbolGraphFile.path)'") } // Since we successfully produced symbol graphs for snippets contained in the @@ -125,20 +125,20 @@ extension PackageManager { toPath: targetSymbolGraphsUnifiedDirectory.path ) - let snippetSymbolGraphsUnifiedDirectory = unifiedSymbolGraphsDirectory.appendingPathComponent( - "snippet-symbol-graphs", isDirectory: true + let snippetSymbolGraphFileInUnifiedDirectory = unifiedSymbolGraphsDirectory.appendingPathComponent( + snippetSymbolGraphFile.lastPathComponent, isDirectory: false ) // Copy the snippet symbol graphs into the unified directory try FileManager.default.copyItem( - atPath: snippetSymbolGraphsDirectory.path, - toPath: snippetSymbolGraphsUnifiedDirectory.path + atPath: snippetSymbolGraphFile.path, + toPath: snippetSymbolGraphFileInUnifiedDirectory.path ) return DocCSymbolGraphResult( unifiedSymbolGraphsDirectory: unifiedSymbolGraphsDirectory, targetSymbolGraphsDirectory: targetSymbolGraphsUnifiedDirectory, - snippetSymbolGraphsDirectory: snippetSymbolGraphsUnifiedDirectory + snippetSymbolGraphFile: snippetSymbolGraphFileInUnifiedDirectory ) } }