diff --git a/Sources/Commands/PackageTools/DumpCommands.swift b/Sources/Commands/PackageTools/DumpCommands.swift index 6a13f186bc4..541cac5ae23 100644 --- a/Sources/Commands/PackageTools/DumpCommands.swift +++ b/Sources/Commands/PackageTools/DumpCommands.swift @@ -39,6 +39,9 @@ struct DumpSymbolGraph: SwiftCommand { @Flag(help: "Add symbols with SPI information to the symbol graph.") var includeSPISymbols = false + + @Flag(help: "Emit extension block symbols for extensions to external types or directly associate members and conformances with the extended nominal.") + var extensionBlockSymbolBehavior: ExtensionBlockSymbolBehavior = .omitExtensionBlockSymbols func run(_ swiftTool: SwiftTool) throws { // Build the current package. @@ -51,10 +54,12 @@ struct DumpSymbolGraph: SwiftCommand { let symbolGraphExtractor = try SymbolGraphExtract( fileSystem: swiftTool.fileSystem, tool: swiftTool.getDestinationToolchain().getSymbolGraphExtract(), + observabilityScope: swiftTool.observabilityScope, skipSynthesizedMembers: skipSynthesizedMembers, minimumAccessLevel: minimumAccessLevel, skipInheritedDocs: skipInheritedDocs, includeSPISymbols: includeSPISymbols, + emitExtensionBlockSymbols: extensionBlockSymbolBehavior == .emitExtensionBlockSymbols, outputFormat: .json(pretty: prettyPrint) ) @@ -76,6 +81,11 @@ struct DumpSymbolGraph: SwiftCommand { } } +enum ExtensionBlockSymbolBehavior: String, EnumerableFlag { + case emitExtensionBlockSymbols + case omitExtensionBlockSymbols +} + struct DumpPackage: SwiftCommand { static let configuration = CommandConfiguration( abstract: "Print parsed Package.swift as JSON") diff --git a/Sources/Commands/Utilities/PluginDelegate.swift b/Sources/Commands/Utilities/PluginDelegate.swift index 819f5b88c4c..532d5799fb1 100644 --- a/Sources/Commands/Utilities/PluginDelegate.swift +++ b/Sources/Commands/Utilities/PluginDelegate.swift @@ -338,7 +338,8 @@ final class PluginDelegate: PluginInvocationDelegate { // Configure the symbol graph extractor. var symbolGraphExtractor = try SymbolGraphExtract( fileSystem: swiftTool.fileSystem, - tool: swiftTool.getDestinationToolchain().getSymbolGraphExtract() + tool: swiftTool.getDestinationToolchain().getSymbolGraphExtract(), + observabilityScope: swiftTool.observabilityScope ) symbolGraphExtractor.skipSynthesizedMembers = !options.includeSynthesized switch options.minimumAccessLevel { @@ -355,6 +356,7 @@ final class PluginDelegate: PluginInvocationDelegate { } symbolGraphExtractor.skipInheritedDocs = true symbolGraphExtractor.includeSPISymbols = options.includeSPI + symbolGraphExtractor.emitExtensionBlockSymbols = options.emitExtensionBlocks // Determine the output directory, and remove any old version if it already exists. guard let package = packageGraph.package(for: target) else { diff --git a/Sources/Commands/Utilities/SymbolGraphExtract.swift b/Sources/Commands/Utilities/SymbolGraphExtract.swift index 5f04de12b33..340b579528e 100644 --- a/Sources/Commands/Utilities/SymbolGraphExtract.swift +++ b/Sources/Commands/Utilities/SymbolGraphExtract.swift @@ -16,16 +16,19 @@ import PackageGraph import PackageModel import SPMBuildCore import TSCBasic +@_implementationOnly import DriverSupport /// A wrapper for swift-symbolgraph-extract tool. public struct SymbolGraphExtract { let fileSystem: FileSystem let tool: AbsolutePath + let observabilityScope: ObservabilityScope var skipSynthesizedMembers = false var minimumAccessLevel = AccessLevel.public var skipInheritedDocs = false var includeSPISymbols = false + var emitExtensionBlockSymbols = false var outputFormat = OutputFormat.json(pretty: false) /// Access control levels. @@ -70,6 +73,14 @@ public struct SymbolGraphExtract { if includeSPISymbols { commandLine += ["-include-spi-symbols"] } + + let extensionBlockSymbolsFlag = emitExtensionBlockSymbols ? "-emit-extension-block-symbols" : "-omit-extension-block-symbols" + if DriverSupport.checkSupportedFrontendFlags(flags: [extensionBlockSymbolsFlag.trimmingCharacters(in: ["-"])], fileSystem: fileSystem) { + commandLine += [extensionBlockSymbolsFlag] + } else { + observabilityScope.emit(warning: "dropped \(extensionBlockSymbolsFlag) flag because it is not supported by this compiler version") + } + switch outputFormat { case .json(let pretty): if pretty { diff --git a/Sources/PackagePlugin/PackageManagerProxy.swift b/Sources/PackagePlugin/PackageManagerProxy.swift index d4970a4a59d..01289cfa2c7 100644 --- a/Sources/PackagePlugin/PackageManagerProxy.swift +++ b/Sources/PackagePlugin/PackageManagerProxy.swift @@ -229,11 +229,15 @@ public struct PackageManager { /// Whether to include symbols marked as SPI. public var includeSPI: Bool + + /// Whether to emit symbols for extensions to external types. + public var emitExtensionBlocks: Bool - public init(minimumAccessLevel: AccessLevel = .public, includeSynthesized: Bool = false, includeSPI: Bool = false) { + public init(minimumAccessLevel: AccessLevel = .public, includeSynthesized: Bool = false, includeSPI: Bool = false, emitExtensionBlocks: Bool = false) { self.minimumAccessLevel = minimumAccessLevel self.includeSynthesized = includeSynthesized self.includeSPI = includeSPI + self.emitExtensionBlocks = emitExtensionBlocks } } @@ -410,6 +414,7 @@ fileprivate extension PluginToHostMessage.SymbolGraphOptions { self.minimumAccessLevel = .init(options.minimumAccessLevel) self.includeSynthesized = options.includeSynthesized self.includeSPI = options.includeSPI + self.emitExtensionBlocks = options.emitExtensionBlocks } } diff --git a/Sources/PackagePlugin/PluginMessages.swift b/Sources/PackagePlugin/PluginMessages.swift index 58ed4900e85..52078421d1d 100644 --- a/Sources/PackagePlugin/PluginMessages.swift +++ b/Sources/PackagePlugin/PluginMessages.swift @@ -316,5 +316,6 @@ enum PluginToHostMessage: Codable { } var includeSynthesized: Bool var includeSPI: Bool + var emitExtensionBlocks: Bool } } diff --git a/Sources/SPMBuildCore/PluginInvocation.swift b/Sources/SPMBuildCore/PluginInvocation.swift index 1608e0d7f49..e724d1409e8 100644 --- a/Sources/SPMBuildCore/PluginInvocation.swift +++ b/Sources/SPMBuildCore/PluginInvocation.swift @@ -697,6 +697,7 @@ public struct PluginInvocationSymbolGraphOptions { } public var includeSynthesized: Bool public var includeSPI: Bool + public var emitExtensionBlocks: Bool } public struct PluginInvocationSymbolGraphResult { @@ -957,6 +958,7 @@ fileprivate extension PluginInvocationSymbolGraphOptions { self.minimumAccessLevel = .init(options.minimumAccessLevel) self.includeSynthesized = options.includeSynthesized self.includeSPI = options.includeSPI + self.emitExtensionBlocks = options.emitExtensionBlocks } }