From a099b9a41096744b95b1c89b4ef8c218b5847b11 Mon Sep 17 00:00:00 2001 From: Emily Chen Date: Mon, 20 May 2024 11:42:49 +0100 Subject: [PATCH] Cleanup GenerateChangeLog command, removing unnecessary functions. --- .../Model/Rendering/RenderNode.swift | 21 -- .../Subcommands/DiffDocCArchive.swift | 328 ------------------ .../Subcommands/GenerateChangeLog.swift | 52 +-- .../Subcommands/ProcessArchive.swift | 2 +- 4 files changed, 17 insertions(+), 386 deletions(-) delete mode 100644 Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/DiffDocCArchive.swift diff --git a/Sources/SwiftDocC/Model/Rendering/RenderNode.swift b/Sources/SwiftDocC/Model/Rendering/RenderNode.swift index 3e496adb3d..c3ef2d5515 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderNode.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderNode.swift @@ -275,26 +275,5 @@ public struct RenderNode: VariantContainer { throw DecodingError.dataCorruptedError(in: container, debugDescription: "Unknown RenderNode.Kind: '\(unknown)'.") } } - -// // Return the string representing this kind. -// // If the kind is a symbol, return the symbol kind. -// public func kindString() -> String { -// var kind = "" -// -// switch(self) { -// case .article: -// kind = "article" -// case .tutorial: -// kind = "tutorial" -// case .section: -// kind = "section" -// case .overview: -// kind = "overview" -// case .symbol: -// kind = "symbol" -// } -// -// return kind -// } } } diff --git a/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/DiffDocCArchive.swift b/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/DiffDocCArchive.swift deleted file mode 100644 index 7cf7a615a7..0000000000 --- a/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/DiffDocCArchive.swift +++ /dev/null @@ -1,328 +0,0 @@ -/* - This source file is part doccof the Swift.org open source project - - Copyright (c) 2024 Apple Inc. and the Swift project authors - Licensed under Apache License v2.0 with Runtime Library Exception - - See https://swift.org/LICENSE.txt for license information - See https://swift.org/CONTRIBUTORS.txt for Swift project authors -*/ - -import ArgumentParser -import Foundation -import SwiftDocC - -extension Docc.ProcessArchive { - - struct DiffDocCArchive: ParsableCommand { - - // MARK: - Content and Configuration - - /// Command line configuration. - static var configuration = CommandConfiguration( - commandName: "diff-docc-archive", - abstract: "Produce a markdown file saved as {FrameworkName}_ChangeLog.md containing the diff of added/removed symbols between the two provided DocC archives.", - shouldDisplay: true) - - /// Content of the 'changeLog' template. - static func changeLogTemplateFileContent( - frameworkName: String, - initialDocCArchiveVersion: String, - newerDocCArchiveVersion: String, - additionLinks: String, - removalLinks: String - ) -> [String : String] { - [ - "\(frameworkName.localizedCapitalized)_ChangeLog.md": """ - # \(frameworkName.localizedCapitalized) Updates - - @Metadata { - @PageColor(yellow) - } - - Learn about important changes to \(frameworkName.localizedCapitalized). - - ## Overview - - Browse notable changes in \(frameworkName.localizedCapitalized). - - ## Version: Diff between \(initialDocCArchiveVersion) and \(newerDocCArchiveVersion) - - - ### Change Log - - #### Additions - _New symbols added in \(newerDocCArchiveVersion) that did not previously exist in \(initialDocCArchiveVersion)._ - - \(additionLinks) - - - #### Removals - _Old symbols that existed in \(initialDocCArchiveVersion) that no longer exist in \(newerDocCArchiveVersion)._ - - \(removalLinks) - - """ - ] - } - - // MARK: - Command Line Options & Arguments - - @Argument( - help: ArgumentHelp( - "The version of the initial DocC Archive to be compared.", - valueName: "initialDocCArchiveVersion")) - var initialDocCArchiveVersion: String - - @Argument( - help: ArgumentHelp( - "The path to the initial DocC Archive to be compared.", - valueName: "initialDocCArchive"), - transform: URL.init(fileURLWithPath:)) - var initialDocCArchivePath: URL - - @Argument( - help: ArgumentHelp( - "The version of the newer DocC Archive to be compared.", - valueName: "newerDocCArchiveVersion")) - var newerDocCArchiveVersion: String - - @Argument( - help: ArgumentHelp( - "The path to the newer DocC Archive to be compared.", - valueName: "newerDocCArchive"), - transform: URL.init(fileURLWithPath:)) - var newerDocCArchivePath: URL - - // MARK: - Execution - - public mutating func run() throws { - let initialDocCArchiveAPIs: [URL] = try findAllSymbolLinks(initialPath: initialDocCArchivePath) - let newDocCArchiveAPIs: [URL] = try findAllSymbolLinks(initialPath: newerDocCArchivePath) - - let initialSet = Set(initialDocCArchiveAPIs.map { $0 }) - let newSet = Set(newDocCArchiveAPIs.map { $0 }) - - // Compute additions and removals to both sets - let additionsToNewSet = newSet.subtracting(initialSet) - let removedFromOldSet = initialSet.subtracting(newSet) - - // The framework name is the path component after "/documentation/". - var frameworkName: String = "No_Framework_Name" - var potentialFrameworkName = try findFrameworkName(initialPath: initialDocCArchivePath) - if potentialFrameworkName == nil { - potentialFrameworkName = try findFrameworkName(initialPath: newerDocCArchivePath) - } - - if potentialFrameworkName != nil { - frameworkName = potentialFrameworkName ?? "No_Framework_Name" - } - - let additionLinks = groupSymbols(symbolLinks: additionsToNewSet, frameworkName: frameworkName) - let removalLinks = groupSymbols(symbolLinks: removedFromOldSet, frameworkName: frameworkName) - - // Create markdown file with changes in the newer DocC Archive that do not exist in the initial DocC Archive. - for fileNameAndContent in Docc.ProcessArchive.DiffDocCArchive.changeLogTemplateFileContent(frameworkName: frameworkName, initialDocCArchiveVersion: initialDocCArchiveVersion, newerDocCArchiveVersion: newerDocCArchiveVersion, additionLinks: additionLinks, removalLinks: removalLinks) { - let fileName = fileNameAndContent.key - let content = fileNameAndContent.value - let filePath = initialDocCArchivePath.deletingLastPathComponent().appendingPathComponent(fileName) - try FileManager.default.createFile(at: filePath, contents: Data(content.utf8)) - print("\nOutput file path: \(filePath)") - } - } - - /// Pretty print all symbols' url identifiers into a pretty format, with a new line between each symbol. - func printAllSymbols(symbols: [URL]) { - for symbol in symbols { - print(symbol) - } - } - - /// The framework name is the path component after "/documentation/". - func findFrameworkName(initialPath: URL) throws -> String? { - guard let enumerator = FileManager.default.enumerator( - at: initialPath, - includingPropertiesForKeys: [], - options: .skipsHiddenFiles, - errorHandler: nil - ) else { - return nil - } - - var frameworkName: String? - for case let filePath as URL in enumerator { - let pathComponents = filePath.pathComponents - var isFrameworkName = false - for pathComponent in pathComponents { - if isFrameworkName { - frameworkName = pathComponent - return frameworkName - } - - if pathComponent == "documentation" { - isFrameworkName = true - } - } - } - - return frameworkName - } - - /// Given the identifier url, cut off everything preceding /documentation/ and append this resulting string to doc: - func findExternalLink(identifierURL: URL) -> String { - var resultantURL = identifierURL.absoluteString - var shouldAppend = false - for pathComponent in identifierURL.pathComponents { - if pathComponent == "documentation" { - resultantURL = "doc:" - shouldAppend = true - } - if shouldAppend { - resultantURL.append(pathComponent + "/") - } - } - return resultantURL - } - - /// Given a URL, return each of the symbols by their unique identifying links - func findAllSymbolLinks(initialPath: URL) throws -> [URL] { - guard let enumerator = FileManager.default.enumerator( - at: initialPath, - includingPropertiesForKeys: [], - options: .skipsHiddenFiles, - errorHandler: nil - ) else { - return [] - } - - var returnSymbolLinks: [URL] = [] - for case let filePath as URL in enumerator { - if filePath.lastPathComponent.hasSuffix(".json") { - let symbolLink = try findSymbolLink(symbolPath: filePath) - if symbolLink != nil { - returnSymbolLinks.append(symbolLink!) - } - } - } - - return returnSymbolLinks - } - - func findSymbolLink(symbolPath: URL) throws -> URL? { - struct ContainerWithTopicReferenceIdentifier: Codable { - var identifier: ResolvedTopicReference - } - - let renderJSONData = try Data(contentsOf: symbolPath) - let decoder = RenderJSONDecoder.makeDecoder() - - do { - let identifier = try decoder.decode(ContainerWithTopicReferenceIdentifier.self, from: renderJSONData).identifier - return identifier.url - } catch { - return nil - } - } - - // TODO: CONTINUE -// func findPageType(symbolPath: URL) throws -> URL? { -// struct ContainerWithPageType: Codable { -// var pageType: NavigatorIndex.PageType -// } -// -// let renderJSONData = try Data(contentsOf: symbolPath) -// let decoder = RenderJSONDecoder.makeDecoder() -// -// do { -// let identifier = try decoder.decode(NavigatorIndex.self, from: renderJSONData). -// return identifier.url -// } catch { -// return nil -// } -// } - - func findClassName(symbolPath: URL) -> String { - return symbolPath.lastPathComponent - } - -// func findClassName(symbolPath: URL) throws -> [[String]]? { -// struct ContainerWithRenderHierarchy: Codable { -// var hierarchy: RenderHierarchy -// } -// -// let renderJSONData = try Data(contentsOf: symbolPath) -// let decoder = RenderJSONDecoder.makeDecoder() -// -// do { -// let hierarchy = try decoder.decode(ContainerWithRenderHierarchy.self, from: renderJSONData).hierarchy -// -// if hierarchy != nil { -// return hierarchy.paths -// } -// -// return identifier.url -// } catch { -// return nil -// } -// } - - /// Process lists of symbols to group them according to the highest level path component, split by spaces. - func groupSymbols(symbolLinks: Set, frameworkName: String) -> String { - // Sort list alphabetically - let sortedSymbols: [URL] = symbolLinks.sorted { $0.absoluteString.localizedCompare($1.absoluteString) == .orderedAscending } - - var links: String = "" - - // find most similar path up until framework name by iterating over path components one at a time - guard var first = sortedSymbols.first else { - return links - } - - for symbol in sortedSymbols.dropFirst() { - let parent: String = first.absoluteString.commonPrefix(with: symbol.absoluteString) - - // If there are no common path components, add a space. Then reset the first to find the next parent. - if parent.localizedLowercase.hasSuffix(frameworkName + "/") { - links.append("\n \n") - first = symbol - } - - links.append("\n- <\(findExternalLink(identifierURL: symbol))>") - } - - return links - } - - func addClassNames(allSymbolsString: String) -> String { -// let processedString = "" - - // Split string into string array on a double newline - return longestCommonPrefix(of: allSymbolsString) - } - - func longestCommonPrefix(of string: String) -> String { - - let words = string.split(separator: " ") -// let words = string.split(separator: "\n\n") - guard let first = words.first else { - return "" - } - - var (minWord, maxWord) = (first, first) - for word in words.dropFirst() { - if word < minWord { - print(word) - print(maxWord) - minWord = word - } else if word > maxWord { - print(word) - print(maxWord) - maxWord = word - } - } - - return minWord.commonPrefix(with: maxWord) - } - - } -} diff --git a/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/GenerateChangeLog.swift b/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/GenerateChangeLog.swift index 781fffaa6f..266da55e3e 100644 --- a/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/GenerateChangeLog.swift +++ b/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/GenerateChangeLog.swift @@ -83,9 +83,21 @@ extension Docc { transform: URL.init(fileURLWithPath:)) var newerDocCArchivePath: URL + @Option( + name: [.customLong("initial-archive-name", withSingleDash: false)], + help: "The name of the initial DocC Archive version to be compared." + ) + var initialArchiveName: String = "Version 1" + + @Option( + name: [.customLong("newer-archive-name", withSingleDash: false)], + help: "The name of the newer DocC Archive version to be compared." + ) + var newerArchiveName: String = "Version 2" + @Option( name: [.customLong("show-all", withSingleDash: false)], - help: "Produces full symbol diff: including all properties, methods, and overrides" + help: "Boolean value to indicate whether to produce a full symbol diff, including all properties, methods, and overrides" ) var showAllSymbols: Bool = false @@ -96,11 +108,11 @@ extension Docc { var newDocCArchiveAPIs: [URL] = try findAllSymbolLinks(initialPath: newerDocCArchivePath) if showAllSymbols { - print("Showing ALL symbols") + print("Showing ALL symbols.") initialDocCArchiveAPIs = try findAllSymbolLinks_Full(initialPath: initialDocCArchivePath) newDocCArchiveAPIs = try findAllSymbolLinks_Full(initialPath: newerDocCArchivePath) } else { - print("Showing ONLY modules, classes, protocols, and structs.") + print("Showing ONLY high-level symbol diffs: modules, classes, protocols, and structs.") } let initialSet = Set(initialDocCArchiveAPIs.map { $0 }) @@ -125,7 +137,7 @@ extension Docc { let removalLinks = groupSymbols(symbolLinks: removedFromOldSet, frameworkName: frameworkName) // Create markdown file with changes in the newer DocC Archive that do not exist in the initial DocC Archive. - for fileNameAndContent in Docc.GenerateChangelog.changeLogTemplateFileContent(frameworkName: frameworkName, initialDocCArchiveVersion: "RainbowF RC", newerDocCArchiveVersion: "Geode Beta 1", additionLinks: additionLinks, removalLinks: removalLinks) { + for fileNameAndContent in Docc.GenerateChangelog.changeLogTemplateFileContent(frameworkName: frameworkName, initialDocCArchiveVersion: initialArchiveName, newerDocCArchiveVersion: newerArchiveName, additionLinks: additionLinks, removalLinks: removalLinks) { let fileName = fileNameAndContent.key let content = fileNameAndContent.value let filePath = initialDocCArchivePath.deletingLastPathComponent().appendingPathComponent(fileName) @@ -292,10 +304,6 @@ extension Docc { } } - func findClassName(symbolPath: URL) -> String { - return symbolPath.lastPathComponent - } - /// Process lists of symbols to group them according to the highest level path component, split by spaces. func groupSymbols(symbolLinks: Set, frameworkName: String) -> String { // Sort list alphabetically @@ -323,33 +331,5 @@ extension Docc { return links } - func addClassNames(allSymbolsString: String) -> String { - // Split string into string array on a double newline - return longestCommonPrefix(of: allSymbolsString) - } - - func longestCommonPrefix(of string: String) -> String { - - let words = string.split(separator: " ") - guard let first = words.first else { - return "" - } - - var (minWord, maxWord) = (first, first) - for word in words.dropFirst() { - if word < minWord { - print(word) - print(maxWord) - minWord = word - } else if word > maxWord { - print(word) - print(maxWord) - maxWord = word - } - } - - return minWord.commonPrefix(with: maxWord) - } - } } diff --git a/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/ProcessArchive.swift b/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/ProcessArchive.swift index 279c8b39f2..59da03fff5 100644 --- a/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/ProcessArchive.swift +++ b/Sources/SwiftDocCUtilities/ArgumentParsing/Subcommands/ProcessArchive.swift @@ -18,7 +18,7 @@ extension Docc { static var configuration = CommandConfiguration( commandName: "process-archive", abstract: "Perform operations on documentation archives ('.doccarchive' directories).", - subcommands: [TransformForStaticHosting.self, Index.self, DiffDocCArchive.self]) + subcommands: [TransformForStaticHosting.self, Index.self]) } }