Skip to content
Merged
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
14 changes: 14 additions & 0 deletions Sources/SWBCore/Settings/BuiltinMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,7 @@ public final class BuiltinMacros {
public static let DOCC_ARCHIVE_PATH = BuiltinMacros.declareStringMacro("DOCC_ARCHIVE_PATH")
public static let DOCC_PRETTY_PRINT = BuiltinMacros.declareBooleanMacro("DOCC_PRETTY_PRINT")
public static let DOCC_EXTRACT_SPI_DOCUMENTATION = BuiltinMacros.declareBooleanMacro("DOCC_EXTRACT_SPI_DOCUMENTATION")
public static let DOCC_MINIMUM_ACCESS_LEVEL = BuiltinMacros.declareEnumMacro("DOCC_MINIMUM_ACCESS_LEVEL") as EnumMacroDeclaration<DoccMinimumAccessLevel>
public static let DOCC_SKIP_SYNTHESIZED_MEMBERS = BuiltinMacros.declareBooleanMacro("DOCC_SKIP_SYNTHESIZED_MEMBERS")
public static let DOCC_EXTRACT_EXTENSION_SYMBOLS = BuiltinMacros.declareBooleanMacro("DOCC_EXTRACT_EXTENSION_SYMBOLS")
public static let DOCC_EXTRACT_SWIFT_INFO_FOR_OBJC_SYMBOLS = BuiltinMacros.declareBooleanMacro("DOCC_EXTRACT_SWIFT_INFO_FOR_OBJC_SYMBOLS")
Expand Down Expand Up @@ -1650,6 +1651,7 @@ public final class BuiltinMacros {
DOCC_ARCHIVE_PATH,
DOCC_PRETTY_PRINT,
DOCC_SKIP_SYNTHESIZED_MEMBERS,
DOCC_MINIMUM_ACCESS_LEVEL,
DOCC_EXTRACT_SPI_DOCUMENTATION,
DOCC_EXTRACT_EXTENSION_SYMBOLS,
DOCC_EXTRACT_SWIFT_INFO_FOR_OBJC_SYMBOLS,
Expand Down Expand Up @@ -2757,6 +2759,18 @@ public enum LinkerDriverChoice: String, Equatable, Hashable, EnumerationMacroTyp
case auto
}

public enum DoccMinimumAccessLevel: String, Equatable, Hashable, EnumerationMacroType {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may need to add a case to the switch in EnumBuildOptionType.declareMacro for this enum type too. It might be nice to have a test in DocumentationTaskConstructionTests that the flag is being passed through correctly

public static let defaultValue = DoccMinimumAccessLevel.none

case none = ""
case `private` = "private"
case `fileprivate` = "fileprivate"
case `internal` = "internal"
case `package` = "package"
case `public` = "public"
case `open` = "open"
}

/// Enumeration macro type for the value of the `INFOPLIST_KEY_LSApplicationCategoryType` build setting.
public enum ApplicationCategory: String, Equatable, Hashable, EnumerationMacroType {
public static let defaultValue = ApplicationCategory.none
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ private final class EnumBuildOptionType : BuildOptionType {
return try namespace.declareEnumMacro(name) as EnumMacroDeclaration<SwiftAPIDigesterMode>
case "LINKER_FILE_LIST_FORMAT":
return try namespace.declareEnumMacro(name) as EnumMacroDeclaration<LinkerFileListFormat>
case "DOCC_MINIMUM_ACCESS_LEVEL":
return try namespace.declareEnumMacro(name) as EnumMacroDeclaration<DoccMinimumAccessLevel>
default:
return try namespace.declareStringMacro(name)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ final public class DocumentationCompilerSpec: GenericCompilerSpec, SpecIdentifie
var additionalFlags = [String]()

// Check if pretty print is requested
if cbc.scope.evaluate(BuiltinMacros.DOCC_PRETTY_PRINT) && swiftCompilerInfo.toolFeatures.has(.emitExtensionBlockSymbols) {
if cbc.scope.evaluate(BuiltinMacros.DOCC_PRETTY_PRINT) {
additionalFlags.append("-symbol-graph-pretty-print")
}

Expand All @@ -88,19 +88,34 @@ final public class DocumentationCompilerSpec: GenericCompilerSpec, SpecIdentifie
}

// Check if synthesized members should be skipped
if cbc.scope.evaluate(BuiltinMacros.DOCC_SKIP_SYNTHESIZED_MEMBERS) && swiftCompilerInfo.toolFeatures.has(.emitExtensionBlockSymbols) {
if cbc.scope.evaluate(BuiltinMacros.DOCC_SKIP_SYNTHESIZED_MEMBERS) {
additionalFlags.append("-symbol-graph-skip-synthesized-members")
}

switch DocumentationType(from: cbc) {
case .executable:
// When building executable types (like applications and command-line tools), include
// internal symbols in the generated symbol graph.
switch cbc.scope.evaluate(BuiltinMacros.DOCC_MINIMUM_ACCESS_LEVEL) {
case .none:
switch DocumentationType(from: cbc) {
case .executable:
// When building executable types (like applications and command-line tools), include
// internal symbols in the generated symbol graph.
return additionalFlags.appending(contentsOf: ["-symbol-graph-minimum-access-level", "internal"])
case .framework, .none:
// For frameworks (and non-documentable types), just use the default behavior
// of the symbol graph tool.
return additionalFlags
}
case .private:
return additionalFlags.appending(contentsOf: ["-symbol-graph-minimum-access-level", "private"])
case .fileprivate:
return additionalFlags.appending(contentsOf: ["-symbol-graph-minimum-access-level", "fileprivate"])
case .internal:
return additionalFlags.appending(contentsOf: ["-symbol-graph-minimum-access-level", "internal"])
case .framework, .none:
// For frameworks (and non-documentable types), just use the default behavior
// of the symbol graph tool.
return additionalFlags
case .package:
return additionalFlags.appending(contentsOf: ["-symbol-graph-minimum-access-level", "package"])
case .public:
return additionalFlags.appending(contentsOf: ["-symbol-graph-minimum-access-level", "public"])
case .open:
return additionalFlags.appending(contentsOf: ["-symbol-graph-minimum-access-level", "open"])
}
}

Expand Down
16 changes: 16 additions & 0 deletions Sources/SWBUniversalPlatform/Specs/Documentation.xcspec
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,22 @@
DefaultValue = NO;
},

// The minimum access level for API for the symbol graph extractor to generate
{
Name = DOCC_MINIMUM_ACCESS_LEVEL;
Type = Enumeration;
Values = (
none,
private,
fileprivate,
internal,
package,
public,
open,
);
DefaultValue = none;
},

{
Name = DOCC_EXTRACT_SWIFT_INFO_FOR_OBJC_SYMBOLS;
Type = bool;
Expand Down
60 changes: 59 additions & 1 deletion Tests/SWBCoreTests/DocumentationCompilerSpecTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,57 @@ import SWBMacro
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(frameworkArgs == [])

let publicArgs = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, minimumAccessLevel: .public),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(publicArgs == ["-symbol-graph-minimum-access-level", "public"])

let privateArgs = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, minimumAccessLevel: .private),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(privateArgs == ["-symbol-graph-minimum-access-level", "private"])

let filePrivateArgs = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, minimumAccessLevel: .fileprivate),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(filePrivateArgs == ["-symbol-graph-minimum-access-level", "fileprivate"])

let internalArgs = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, minimumAccessLevel: .internal),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(internalArgs == ["-symbol-graph-minimum-access-level", "internal"])

let openArgs = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, minimumAccessLevel: .open),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(openArgs == ["-symbol-graph-minimum-access-level", "open"])

let packageArgs = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, minimumAccessLevel: .package),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(packageArgs == ["-symbol-graph-minimum-access-level", "package"])

let prettyPrintArgs = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, prettyPrint: true),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(prettyPrintArgs == ["-symbol-graph-pretty-print"])

let skipSynthesizedMembers = await DocumentationCompilerSpec.additionalSymbolGraphGenerationArgs(
try mockApplicationBuildContext(application: false, skipSynthesizedMembers: true),
swiftCompilerInfo: try mockSwiftCompilerSpec(swiftVersion: "5.6", swiftTag: "swiftlang-5.6.0.0")
)
#expect(skipSynthesizedMembers == ["-symbol-graph-skip-synthesized-members"])
}

private func mockApplicationBuildContext(application: Bool) async throws -> CommandBuildContext {
private func mockApplicationBuildContext(application: Bool, minimumAccessLevel: DoccMinimumAccessLevel = .none, prettyPrint: Bool = false, skipSynthesizedMembers: Bool = false) async throws -> CommandBuildContext {
let core = try await getCore()

let producer = try MockCommandProducer(
Expand All @@ -49,6 +97,16 @@ import SWBMacro
mockTable.push(BuiltinMacros.MACH_O_TYPE, literal: "mh_execute")
}

mockTable.push(BuiltinMacros.DOCC_MINIMUM_ACCESS_LEVEL, literal: minimumAccessLevel)

if prettyPrint {
mockTable.push(BuiltinMacros.DOCC_PRETTY_PRINT, literal: true)
}

if skipSynthesizedMembers {
mockTable.push(BuiltinMacros.DOCC_SKIP_SYNTHESIZED_MEMBERS, literal: skipSynthesizedMembers)
}

let mockScope = MacroEvaluationScope(table: mockTable)

return CommandBuildContext(producer: producer, scope: mockScope, inputs: [])
Expand Down