Skip to content

add experimental Doxygen support #497

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

Merged
merged 4 commits into from
Mar 3, 2023
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
2 changes: 1 addition & 1 deletion Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Sources/SwiftDocC/Model/DocumentationNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,12 @@ public struct DocumentationNode {
]
} else if let symbol = documentedSymbol, let docComment = symbol.docComment {
let docCommentString = docComment.lines.map { $0.text }.joined(separator: "\n")
let docCommentMarkup = Document(parsing: docCommentString, options: [.parseBlockDirectives, .parseSymbolLinks])

var documentOptions: ParseOptions = [.parseBlockDirectives, .parseSymbolLinks]
if FeatureFlags.current.isExperimentalDoxygenSupportEnabled {
documentOptions.insert(.parseMinimalDoxygen)
}
let docCommentMarkup = Document(parsing: docCommentString, options: documentOptions)

let docCommentDirectives = docCommentMarkup.children.compactMap({ $0 as? BlockDirective })
if !docCommentDirectives.isEmpty {
Expand Down
8 changes: 8 additions & 0 deletions Sources/SwiftDocC/Model/Semantics/Parameter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,12 @@ public struct Parameter {
self.name = name
self.contents = contents
}

/// Initialize a value to describe documentation about a symbol's parameter via a Doxygen `\param` command.
///
/// - Parameter doxygenParameter: A parsed Doxygen `\param` command.
public init(_ doxygenParameter: DoxygenParameter) {
self.name = doxygenParameter.name
self.contents = Array(doxygenParameter.children)
}
}
7 changes: 7 additions & 0 deletions Sources/SwiftDocC/Model/Semantics/Return.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,11 @@ public struct Return {
public init(contents: [Markup]) {
self.contents = contents
}

/// Initialize a value to describe documentation about a symbol's return value.
///
/// - Parameter doxygenReturns: A parsed Doxygen `\returns` command.
public init(_ doxygenReturns: DoxygenReturns) {
self.contents = Array(doxygenReturns.children)
}
}
3 changes: 3 additions & 0 deletions Sources/SwiftDocC/Utility/FeatureFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public struct FeatureFlags: Codable {

/// Whether or not experimental support for device frames on images and video is enabled.
public var isExperimentalDeviceFrameSupportEnabled = false

/// Whether or not experimental support for parsing Doxygen commands is enabled.
public var isExperimentalDoxygenSupportEnabled = false

/// Creates a set of feature flags with the given values.
///
Expand Down
10 changes: 10 additions & 0 deletions Sources/SwiftDocC/Utility/MarkupExtensions/ListItemExtractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -407,4 +407,14 @@ struct TaggedListItemExtractor: MarkupRewriter {
// No match; leave this list item alone.
return listItem
}

mutating func visitDoxygenParameter(_ doxygenParam: DoxygenParameter) -> Markup? {
parameters.append(Parameter(doxygenParam))
return nil
}

mutating func visitDoxygenReturns(_ doxygenReturns: DoxygenReturns) -> Markup? {
returns.append(Return(doxygenReturns))
return nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ extension ConvertAction {
let outOfProcessResolver: OutOfProcessReferenceResolver?

FeatureFlags.current.isExperimentalDeviceFrameSupportEnabled = convert.enableExperimentalDeviceFrameSupport
FeatureFlags.current.isExperimentalDoxygenSupportEnabled = convert.experimentalParseDoxygenCommands

// If the user-provided a URL for an external link resolver, attempt to
// initialize an `OutOfProcessReferenceResolver` with the provided URL.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ extension Docc {
@OptionGroup()
public var sourceRepositoryArguments: SourceRepositoryArguments

/// A user-provided value that is true if experimental Doxygen support should be enabled.
///
/// Defaults to false.
@Flag(help: .hidden)
public var experimentalParseDoxygenCommands = false

// MARK: - Info.plist fallbacks

/// A user-provided fallback display name for the documentation bundle.
Expand Down
25 changes: 25 additions & 0 deletions Tests/SwiftDocCTests/Semantics/SymbolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,31 @@ class SymbolTests: XCTestCase {
XCTAssertEqual(problems.count, 0)
}

func testParseDoxygenWithFeatureFlag() throws {
enableFeatureFlag(\.isExperimentalDoxygenSupportEnabled)

let deckKitSymbolGraph = Bundle.module.url(
forResource: "DeckKit-Objective-C",
withExtension: "symbols.json",
subdirectory: "Test Resources"
)!
let (_, _, context) = try testBundleAndContext(copying: "TestBundle") { url in
try? FileManager.default.copyItem(at: deckKitSymbolGraph, to: url.appendingPathComponent("DeckKit.symbols.json"))
}
let symbol = try XCTUnwrap(context.symbolIndex["c:objc(cs)PlayingCard(cm)newWithRank:ofSuit:"]?.semantic as? Symbol)

XCTAssertEqual(symbol.abstract?.format(), "Allocate and initialize a new card with the given rank and suit.")

XCTAssertEqual(symbol.parametersSection?.parameters.count, 2)

let rankParameter = try XCTUnwrap(symbol.parametersSection?.parameters.first(where:{$0.name == "rank"}))
XCTAssertEqual(rankParameter.contents.map({$0.format()}), ["The rank of the card."])
let suitParameter = try XCTUnwrap(symbol.parametersSection?.parameters.first(where:{$0.name == "suit"}))
XCTAssertEqual(suitParameter.contents.map({$0.format()}), ["The suit of the card."])

XCTAssertEqual(symbol.returnsSection?.content.map({ $0.format() }), ["A new card with the given configuration."])
}

func testUnresolvedReferenceWarningsInDocumentationExtension() throws {
let (url, _, context) = try testBundleAndContext(copying: "TestBundle") { url in
let myKitDocumentationExtensionComment = """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1591,14 +1591,66 @@
"range" : {
"end" : {
"character" : 68,
"line" : 56
"line" : 46
},
"start" : {
"character" : 4,
"line" : 56
"line" : 46
}
},
"text" : "Allocate and initialize a new card with the given rank and suit."
},
{
"range" : {
"end" : {
"character" : 3,
"line" : 47
},
"start" : {
"character" : 3,
"line" : 47
}
},
"text" : ""
},
{
"range" : {
"end" : {
"character" : 37,
"line" : 48
},
"start" : {
"character" : 4,
"line" : 48
}
},
"text" : "\\param rank The rank of the card."
},
{
"range" : {
"end" : {
"character" : 37,
"line" : 49
},
"start" : {
"character" : 4,
"line" : 49
}
},
"text" : "@param suit The suit of the card."
},
{
"range" : {
"end" : {
"character" : 54,
"line" : 50
},
"start" : {
"character" : 4,
"line" : 50
}
},
"text" : "\\returns A new card with the given configuration. "
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class ConvertSubcommandTests: XCTestCase {
]), "Did not refuse target folder path '\(path)'")
}
}

func testAnalyzerIsTurnedOffByDefault() throws {
setenv(TemplateOption.environmentVariableKey, testTemplateURL.path, 1)
let convertOptions = try Docc.Convert.parse([
Expand Down Expand Up @@ -206,7 +206,7 @@ class ConvertSubcommandTests: XCTestCase {
XCTAssertEqual(convertOptions.defaultCodeListingLanguage, "swift")
}

// Are set when passed
// Are set when passed
do {
let convertOptions = try Docc.Convert.parse([
testBundleURL.path,
Expand Down Expand Up @@ -390,6 +390,27 @@ class ConvertSubcommandTests: XCTestCase {
XCTAssertTrue(commandWithFlag.enableExperimentalDeviceFrameSupport)
XCTAssertTrue(FeatureFlags.current.isExperimentalDeviceFrameSupportEnabled)
}

func testExperimentalParseDoxygenFlag() throws {
let originalFeatureFlagsState = FeatureFlags.current

defer {
FeatureFlags.current = originalFeatureFlagsState
}

let commandWithoutFlag = try Docc.Convert.parse([testBundleURL.path])
let _ = try ConvertAction(fromConvertCommand: commandWithoutFlag)
XCTAssertFalse(commandWithoutFlag.experimentalParseDoxygenCommands)
XCTAssertFalse(FeatureFlags.current.isExperimentalDoxygenSupportEnabled)

let commandWithFlag = try Docc.Convert.parse([
"--experimental-parse-doxygen-commands",
testBundleURL.path,
])
let _ = try ConvertAction(fromConvertCommand: commandWithFlag)
XCTAssertTrue(commandWithFlag.experimentalParseDoxygenCommands)
XCTAssertTrue(FeatureFlags.current.isExperimentalDoxygenSupportEnabled)
}

func testTransformForStaticHostingFlagWithoutHTMLTemplate() throws {
unsetenv(TemplateOption.environmentVariableKey)
Expand Down