diff --git a/Sources/SwiftDocC/Model/Rendering/RenderSectionTranslator/DeclarationsSectionTranslator.swift b/Sources/SwiftDocC/Model/Rendering/RenderSectionTranslator/DeclarationsSectionTranslator.swift index b65ddc9d29..f360cd881d 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderSectionTranslator/DeclarationsSectionTranslator.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderSectionTranslator/DeclarationsSectionTranslator.swift @@ -23,10 +23,17 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator { return nil } - func translateFragment(_ fragment: SymbolGraph.Symbol.DeclarationFragments.Fragment) -> DeclarationRenderSection.Token { + /// Convert a ``SymbolGraph`` declaration fragment into a ``DeclarationRenderSection/Token`` + /// by resolving any symbol USRs to the appropriate reference link. + func translateFragment( + _ fragment: SymbolGraph.Symbol.DeclarationFragments.Fragment, + highlight: Bool + ) -> DeclarationRenderSection.Token { let reference: ResolvedTopicReference? if let preciseIdentifier = fragment.preciseIdentifier, - let resolved = renderNodeTranslator.context.localOrExternalReference(symbolID: preciseIdentifier) + let resolved = renderNodeTranslator.context.localOrExternalReference( + symbolID: preciseIdentifier + ) { reference = resolved renderNodeTranslator.collectedTopicReferences.append(resolved) @@ -35,54 +42,149 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator { } // Add the declaration token - return DeclarationRenderSection.Token(fragment: fragment, identifier: reference?.absoluteString) + return DeclarationRenderSection.Token( + fragment: fragment, + identifier: reference?.absoluteString, + highlight: highlight + ) } - func renderOtherDeclarationsTokens(from overloads: Symbol.Overloads) -> DeclarationRenderSection.OtherDeclarations { - var otherDeclarations = [DeclarationRenderSection.OtherDeclarations.Declaration]() - for overloadReference in overloads.references { - guard let overload = try? renderNodeTranslator.context.entity(with: overloadReference).semantic as? Symbol else { - continue + /// Convenience wrapper for `translateFragment(_:highlight:)` that can be used in + /// an iterator mapping. + func translateFragment( + _ fragment: SymbolGraph.Symbol.DeclarationFragments.Fragment + ) -> DeclarationRenderSection.Token { + return translateFragment(fragment, highlight: false) + } + + /// Translate a whole ``SymbolGraph`` declaration to a ``DeclarationRenderSection`` + /// declaration and highlight any tokens that aren't shared with a sequence of common tokens. + func translateDeclaration( + _ declaration: [SymbolGraph.Symbol.DeclarationFragments.Fragment], + commonFragments: [SymbolGraph.Symbol.DeclarationFragments.Fragment] + ) -> [DeclarationRenderSection.Token] { + var translatedDeclaration: [DeclarationRenderSection.Token] = [] + var commonIndex = 0 + for fragment in declaration { + if commonIndex < commonFragments.count, fragment == commonFragments[commonIndex] { + // fragment is common to all declarations, render plain + translatedDeclaration.append(translateFragment(fragment)) + commonIndex += 1 + } else { + // fragment is unique to this declaration, render highlighted + translatedDeclaration.append(translateFragment(fragment, highlight: true)) } + } - let declarationFragments = overload.declarationVariants[trait]?.values.first?.declarationFragments - assert(declarationFragments != nil, "Overloaded symbols must have declaration fragments.") - guard let declarationFragments else { continue } + return postProcessTokens(translatedDeclaration) + } - let declarationTokens = declarationFragments.map(translateFragment) - otherDeclarations.append( - .init( - tokens: declarationTokens, - identifier: overloadReference.absoluteString - ) - ) + typealias OverloadDeclaration = ( + declaration: [SymbolGraph.Symbol.DeclarationFragments.Fragment], + reference: ResolvedTopicReference + ) + + func renderOtherDeclarationsTokens( + from overloadDeclarations: [OverloadDeclaration], + displayIndex: Int, + commonFragments: [SymbolGraph.Symbol.DeclarationFragments.Fragment] + ) -> DeclarationRenderSection.OtherDeclarations { + var otherDeclarations: [DeclarationRenderSection.OtherDeclarations.Declaration] = [] + + for overloadDeclaration in overloadDeclarations { + let translatedDeclaration = translateDeclaration( + overloadDeclaration.declaration, + commonFragments: commonFragments) + otherDeclarations.append(.init( + tokens: translatedDeclaration, + identifier: overloadDeclaration.reference.absoluteString)) // Add a topic reference to the overload - renderNodeTranslator.collectedTopicReferences.append(overloadReference) + renderNodeTranslator.collectedTopicReferences.append( + overloadDeclaration.reference + ) } - return .init(declarations: otherDeclarations, displayIndex: overloads.displayIndex) + + return .init(declarations: otherDeclarations, displayIndex: displayIndex) } - var declarations = [DeclarationRenderSection]() - for pair in declaration { - let (platforms, declaration) = pair + func collectOverloadDeclarations(from overloads: Symbol.Overloads) -> [OverloadDeclaration]? { + let declarations = overloads.references.compactMap { overloadReference -> OverloadDeclaration? in + guard let overload = try? renderNodeTranslator.context + .entity(with: overloadReference).semantic as? Symbol + else { + return nil + } - let renderedTokens = declaration.declarationFragments.map(translateFragment) + let declarationFragments = overload.declarationVariants[trait]?.values + .first? + .declarationFragments + precondition( + declarationFragments != nil, + "Overloaded symbols must have declaration fragments." + ) + return declarationFragments.map({ + (declaration: $0, reference: overloadReference) + }) + } + + guard !declarations.isEmpty else { + return nil + } + return declarations + } - let platformNames = platforms.sorted { (lhs, rhs) -> Bool in + func sortPlatformNames(_ platforms: [PlatformName?]) -> [PlatformName?] { + platforms.sorted { (lhs, rhs) -> Bool in guard let lhsValue = lhs, let rhsValue = rhs else { return lhs == nil } return lhsValue.rawValue < rhsValue.rawValue } + } + + var declarations: [DeclarationRenderSection] = [] + let languages = [ + trait.interfaceLanguage ?? renderNodeTranslator.identifier.sourceLanguage.id + ] + for pair in declaration { + let (platforms, declaration) = pair + + let renderedTokens: [DeclarationRenderSection.Token] + let otherDeclarations: DeclarationRenderSection.OtherDeclarations? // If this symbol has overloads, render their declarations as well. - let otherDeclarations = symbol.overloadsVariants[trait].map({ renderOtherDeclarationsTokens(from: $0) }) + if let overloads = symbol.overloadsVariants[trait], + let overloadDeclarations = collectOverloadDeclarations(from: overloads) + { + // Pre-process the declarations by splitting text fragments apart to increase legibility + let mainDeclaration = declaration.declarationFragments.flatMap(preProcessFragment(_:)) + let processedOverloadDeclarations = overloadDeclarations.map({ + OverloadDeclaration($0.declaration.flatMap(preProcessFragment(_:)), $0.reference) + }) + let preProcessedDeclarations = [mainDeclaration] + processedOverloadDeclarations.map(\.declaration) + + // Collect the "common fragments" so we can highlight the ones that are different + // in each declaration + let commonFragments = longestCommonSubsequence(preProcessedDeclarations) + + renderedTokens = translateDeclaration( + mainDeclaration, + commonFragments: commonFragments + ) + otherDeclarations = renderOtherDeclarationsTokens( + from: processedOverloadDeclarations, + displayIndex: overloads.displayIndex, + commonFragments: commonFragments) + } else { + renderedTokens = declaration.declarationFragments.map(translateFragment) + otherDeclarations = nil + } declarations.append( DeclarationRenderSection( - languages: [trait.interfaceLanguage ?? renderNodeTranslator.identifier.sourceLanguage.id], - platforms: platformNames, + languages: languages, + platforms: sortPlatformNames(platforms), tokens: renderedTokens, otherDeclarations: otherDeclarations ) @@ -92,16 +194,13 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator { if let alternateDeclarations = symbol.alternateDeclarationVariants[trait] { for pair in alternateDeclarations { let (platforms, decls) = pair + let platformNames = sortPlatformNames(platforms) for alternateDeclaration in decls { let renderedTokens = alternateDeclaration.declarationFragments.map(translateFragment) - let platformNames = platforms - .compactMap { $0 } - .sorted(by: \.rawValue) - declarations.append( DeclarationRenderSection( - languages: [trait.interfaceLanguage ?? renderNodeTranslator.identifier.sourceLanguage.id], + languages: languages, platforms: platformNames, tokens: renderedTokens ) @@ -114,3 +213,220 @@ struct DeclarationsSectionTranslator: RenderSectionTranslator { } } } + +fileprivate extension DeclarationRenderSection.Token { + /// Whether this token is a text token with a changed highlight. + var isHighlightedText: Bool { + self.highlight == .changed && self.kind == .text + } + + /// Whether this token has any highlight applied to it. + var isHighlighted: Bool { + self.highlight != nil + } + + /// Create a new ``Kind/text`` token with the given text and highlight. + init(plainText text: String, highlight: Highlight? = nil) { + self.init(text: text, kind: .text, highlight: highlight) + } +} + +/// "Post-process" a sequence of declaration tokens by recombining text tokens and cleaning up +/// highlighted spans of tokens. +/// +/// The output of `preProcessFragment` is suitable for differencing, but causes unexpected results +/// when handed directly to Swift-DocC-Render and applied to its declaration formatter. This +/// function recombines adjacent tokens so that the declaration formatter can correctly see the +/// structure of a declaration and format it accordingly. +/// +/// In addition, this function takes the opportunity to trim whitespace at the beginning and end of +/// highlighted spans of tokens, to beautify the resulting declaration. +fileprivate func postProcessTokens( + _ tokens: [DeclarationRenderSection.Token] +) -> [DeclarationRenderSection.Token] { + var processedTokens: [DeclarationRenderSection.Token] = [] + + // This function iterates a list of tokens, keeping track of a "previous token" and comparing it + // against the "current token" to perform the following transformations: + // + // 1. Trim whitespace from the end of a highlighted token if the following token is not + // highlighted. + // 2. Trim whitespace from the beginning of a highlighted token if the previous token was not + // highlighted. + // 3. Concatenate plain-text tokens if they are both highlighted or both not highlighted. + + /// If the given tokens are both plain-text tokens with the same highlight, return a token with + /// both tokens' texts. + func concatenateTokens( + _ lhs: DeclarationRenderSection.Token, + _ rhs: DeclarationRenderSection.Token + ) -> DeclarationRenderSection.Token? { + guard lhs.kind == .text, rhs.kind == .text, lhs.highlight == rhs.highlight else { + return nil + } + var result = lhs + result.text += rhs.text + return result + } + + guard var previousToken = tokens.first else { return [] } + for var currentToken in tokens.dropFirst() { + // First, check whether the tokens we have start or end a highlighted span, and whether + // that span started or ended (respectively) with whitespace. If so, break off that + // whitespace into a new, unhighlighted token, and save any excess tokens accordingly. + // This is complicated by the fact that the whitespace token could be all whitespace, + // removing the need to create a new token. Both of these branches also "fall through" + // to the concatenation check below, in case the creation of a new unhighlighted token + // allows it to be combined with the current token. + + // If the previous token was a highlighted plain-text token that ended with whitespace, + // and the current token is not highlighted, then remove the highlighting for the + // whitespace. + if previousToken.isHighlightedText, + !currentToken.isHighlighted, + previousToken.text.last?.isWhitespace == true + { + if previousToken.text.allSatisfy(\.isWhitespace) { + // if the last token was all whitespace, just convert it to be unhighlighted + previousToken.highlight = nil + } else { + // otherwise, split the trailing whitespace into a new token + let trimmedText = previousToken.text.removingTrailingWhitespace() + let trailingWhitespace = previousToken.text.suffix( + previousToken.text.count - trimmedText.count + ) + previousToken.text = trimmedText + processedTokens.append(previousToken) + + previousToken = .init(plainText: String(trailingWhitespace)) + } + } else if !previousToken.isHighlighted, + currentToken.isHighlightedText, + currentToken.text.first?.isWhitespace == true + { + // Vice versa: If the current token is a highlighted plain-text token that begins + // with whitespace, and the previous token is not highlighted, then remove the + // highlighting for that whitespace. + + if currentToken.text.allSatisfy(\.isWhitespace) { + // if this token is all whitespace, just convert it to be unhighlighted + currentToken.highlight = nil + } else { + // otherwise, split the leading whitespace into a new token + let trimmedText = currentToken.text.removingLeadingWhitespace() + let leadingWhitespace = currentToken.text.prefix( + currentToken.text.count - trimmedText.count + ) + currentToken.text = trimmedText + + // if we can combine the whitespace with the previous token, do that + let whitespaceToken = DeclarationRenderSection.Token(plainText: String(leadingWhitespace)) + if let combinedToken = concatenateTokens(previousToken, whitespaceToken) { + previousToken = combinedToken + } else { + processedTokens.append(previousToken) + previousToken = whitespaceToken + } + } + } + + if let combinedToken = concatenateTokens(previousToken, currentToken) { + // if we could combine the tokens, save it to the current token so it becomes the + // "previous" token at the end of the loop + currentToken = combinedToken + } else { + // otherwise, just save off the previous token so we can store the next + // one for the next iteration + processedTokens.append(previousToken) + } + previousToken = currentToken + } + processedTokens.append(previousToken) + + return processedTokens +} + +/// "Pre-process" a declaration fragment by eagerly splitting apart text fragments into chunks that +/// are more likely to be held in common with other declarations. +/// +/// This method exists to clean up the diff visualization in circumstances where parts of a text +/// fragment are shared in common, but have been combined with other text that is not shared. For +/// example, a declaration such as `myFunc(param: T)` will have a text fragment `>(` before the +/// parameter list, which is technically not shared with a similar declaration `myFunc(param: Int)` +/// which only has a `(` fragment. +/// +/// Text should be broken up in three scenarios: +/// 1. Before a parenthesis or comma, as in the previous example, +/// 2. Before and after whitespace, to increase the chances of matching non-whitespace tokens with +/// each other, and +/// 3. After a `?` character, to eagerly separate optional parameter types from their surrounding +/// syntax. +/// +/// > Note: Any adjacent text fragments that are both shared or highlighted should be recombined +/// > after translation, to allow Swift-DocC-Render to correctly format Swift declarations into +/// > multiple lines. This is performed as part of `translateDeclaration(_:commonFragments:)` above. +fileprivate func preProcessFragment( + _ fragment: SymbolGraph.Symbol.DeclarationFragments.Fragment +) -> [SymbolGraph.Symbol.DeclarationFragments.Fragment] { + guard fragment.kind == .text, !fragment.spelling.isEmpty else { + return [fragment] + } + var textPartitions: [Substring] = [] + var substringIndex = fragment.spelling.startIndex + var currentElement = fragment.spelling[substringIndex] + + func areInSameChunk(_ currentElement: Character, _ nextElement: Character) -> Bool { + if "(),".contains(nextElement) { + // an open paren means we have a token like `>(` which should be split + // a close paren means we have a token like ` = nil)` which should be split + // a comma is similar to the close paren situation + return false + } else if currentElement.isWhitespace != nextElement.isWhitespace { + // break whitespace into their own blocks + return false + } else if currentElement == "?" { + // if we have a token like `?>` or similar we should break the fragment + return false + } else { + return true + } + } + + // FIXME: replace this with `chunked(by:)` if we add swift-algorithms as a dependency + for (nextIndex, nextElement) in fragment.spelling.indexed().dropFirst() { + if !areInSameChunk(currentElement, nextElement) { + textPartitions.append(fragment.spelling[substringIndex..(_ sequences: [[Element]]) -> [Element] { + guard var result = sequences.first else { return [] } + + for other in sequences.dropFirst() { + // This implementation uses the Swift standard library's `CollectionDifference` API to + // calculate the difference between two sequences, then back-computes the LCS by applying + // just the calculated "removals" to the first sequence. Then, in the next loop iteration, + // recalculate the LCS between the result and the next input sequence. By the time all the + // input sequences have been iterated, we have a common subsequence from all the inputs. + for case .remove(let offset, _, _) in other.difference(from: result).removals.reversed() { + result.remove(at: result.startIndex + offset) + } + } + + return result +} diff --git a/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationRenderSection+SymbolGraph.swift b/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationRenderSection+SymbolGraph.swift index 0c55b1deed..e1b49d3377 100644 --- a/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationRenderSection+SymbolGraph.swift +++ b/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationRenderSection+SymbolGraph.swift @@ -16,10 +16,19 @@ extension DeclarationRenderSection.Token { /// - Parameters: /// - fragment: The symbol-graph declaration fragment to render. /// - identifier: An optional reference to a symbol. - init(fragment: SymbolKit.SymbolGraph.Symbol.DeclarationFragments.Fragment, identifier: String?) { + init( + fragment: SymbolKit.SymbolGraph.Symbol.DeclarationFragments.Fragment, + identifier: String?, + highlight: Bool = false + ) { self.text = fragment.spelling self.kind = Kind(rawValue: fragment.kind.rawValue) ?? .text self.identifier = identifier self.preciseIdentifier = fragment.preciseIdentifier + if highlight { + self.highlight = .changed + } else { + self.highlight = nil + } } } diff --git a/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationsRenderSection.swift b/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationsRenderSection.swift index 4cb3d26599..bf7ab620ca 100644 --- a/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationsRenderSection.swift +++ b/Sources/SwiftDocC/Model/Rendering/Symbol/DeclarationsRenderSection.swift @@ -77,7 +77,7 @@ public struct DeclarationRenderSection: Codable, Equatable { /// For example, `123` is represented as a single token of kind "number". public struct Token: Codable, Hashable, Equatable { /// The token text content. - public let text: String + public var text: String /// The token programming kind. public let kind: Kind @@ -114,24 +114,40 @@ public struct DeclarationRenderSection: Codable, Equatable { /// If the token is a known symbol, its precise identifier as vended in the symbol graph. public let preciseIdentifier: String? - + + /// The kind of highlight the token should be rendered with. + public var highlight: Highlight? + + /// The kinds of highlights that can be applied to a token. + public enum Highlight: String, Codable, RawRepresentable { + /// A highlight representing generalized change, not specifically added or removed. + case changed + } + /// Creates a new declaration token with optional identifier and precise identifier. /// - Parameters: /// - text: The text content of the token. /// - kind: The kind of the token. /// - identifier: If the token refers to a known symbol, its identifier. /// - preciseIdentifier: If the refers to a symbol, its precise identifier. - public init(text: String, kind: Kind, identifier: String? = nil, preciseIdentifier: String? = nil) { + public init( + text: String, + kind: Kind, + identifier: String? = nil, + preciseIdentifier: String? = nil, + highlight: Highlight? = nil + ) { self.text = text self.kind = kind self.identifier = identifier self.preciseIdentifier = preciseIdentifier + self.highlight = highlight } // MARK: - Codable private enum CodingKeys: CodingKey { - case text, kind, identifier, preciseIdentifier, otherDeclarations + case text, kind, identifier, preciseIdentifier, highlight, otherDeclarations } public func encode(to encoder: Encoder) throws { @@ -141,6 +157,7 @@ public struct DeclarationRenderSection: Codable, Equatable { try container.encode(kind, forKey: .kind) try container.encodeIfPresent(identifier, forKey: .identifier) try container.encodeIfPresent(preciseIdentifier, forKey: .preciseIdentifier) + try container.encodeIfPresent(highlight, forKey: .highlight) } public init(from decoder: Decoder) throws { @@ -150,6 +167,7 @@ public struct DeclarationRenderSection: Codable, Equatable { kind = try container.decode(Kind.self, forKey: .kind) preciseIdentifier = try container.decodeIfPresent(String.self, forKey: .preciseIdentifier) identifier = try container.decodeIfPresent(String.self, forKey: .identifier) + highlight = try container.decodeIfPresent(Highlight.self, forKey: .highlight) if let reference = identifier { decoder.registerReferences([reference]) diff --git a/Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json b/Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json index 62f3fe07f3..c93a09de13 100644 --- a/Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json +++ b/Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json @@ -2616,6 +2616,12 @@ }, "preciseIdentifier": { "type": "string" + }, + "highlight": { + "type": "string", + "enum": [ + "changed" + ] } } }, diff --git a/Tests/SwiftDocCTests/Rendering/DeclarationsRenderSectionTests.swift b/Tests/SwiftDocCTests/Rendering/DeclarationsRenderSectionTests.swift index a6a24be589..5289df2b95 100644 --- a/Tests/SwiftDocCTests/Rendering/DeclarationsRenderSectionTests.swift +++ b/Tests/SwiftDocCTests/Rendering/DeclarationsRenderSectionTests.swift @@ -11,6 +11,7 @@ import Foundation import XCTest @testable import SwiftDocC +import SwiftDocCTestUtilities class DeclarationsRenderSectionTests: XCTestCase { func testDecodingTokens() throws { @@ -76,7 +77,7 @@ class DeclarationsRenderSectionTests: XCTestCase { ) } } - + func testDoNotEmitOtherDeclarationsIfEmpty() throws { let encoder = RenderJSONEncoder.makeEncoder(prettyPrint: true) @@ -151,4 +152,230 @@ class DeclarationsRenderSectionTests: XCTestCase { XCTAssertEqual(declarationsSection.declarations.count, 2) XCTAssert(declarationsSection.declarations.allSatisfy({ $0.platforms == [.iOS, .macOS] })) } + + func testHighlightDiff() throws { + enableFeatureFlag(\.isExperimentalOverloadedSymbolPresentationEnabled) + + let symbolGraphFile = Bundle.module.url( + forResource: "FancyOverloads", + withExtension: "symbols.json", + subdirectory: "Test Resources" + )! + + let tempURL = try createTempFolder(content: [ + Folder(name: "unit-test.docc", content: [ + InfoPlist(displayName: "FancyOverloads", identifier: "com.test.example"), + CopyOfFile(original: symbolGraphFile), + ]) + ]) + + let (_, bundle, context) = try loadBundle(from: tempURL) + + // Make sure that type decorators like arrays, dictionaries, and optionals are correctly highlighted. + do { + // func overload1(param: Int) {} // <- overload group + // func overload1(param: Int?) {} + // func overload1(param: [Int]) {} + // func overload1(param: [Int]?) {} + // func overload1(param: Set) {} + // func overload1(param: [Int: Int]) {} + let reference = ResolvedTopicReference( + bundleIdentifier: bundle.identifier, + path: "/documentation/FancyOverloads/overload1(param:)-8nk5z", + sourceLanguage: .swift + ) + let symbol = try XCTUnwrap(context.entity(with: reference).semantic as? Symbol) + var translator = RenderNodeTranslator( + context: context, + bundle: bundle, + identifier: reference, + source: nil + ) + let renderNode = try XCTUnwrap(translator.visitSymbol(symbol) as? RenderNode) + let declarationsSection = try XCTUnwrap(renderNode.primaryContentSections.compactMap({ $0 as? DeclarationsRenderSection }).first) + XCTAssertEqual(declarationsSection.declarations.count, 1) + let declarations = try XCTUnwrap(declarationsSection.declarations.first) + + XCTAssertEqual( + declarationAndHighlights(for: declarations.tokens), + [ + "func overload1(param: Int)", + " ", + ] + ) + + XCTAssertEqual( + declarations.otherDeclarations?.declarations.flatMap({ declarationAndHighlights(for: $0.tokens) }), + [ + "func overload1(param: Int?)", + " ~ ", + + "func overload1(param: Set)", + " ~~~~ ~ ", + + "func overload1(param: [Int : Int])", + " ~ ~~~~~~ ", + + "func overload1(param: [Int])", + " ~ ~ ", + + "func overload1(param: [Int]?)", + " ~ ~~ ", + ] + ) + } + + // Verify the behavior of the highlighter in the face of tuples and closures, which can + // confuse the differencing code with excess parentheses and commas. + do { + // func overload2(p1: Int, p2: Int) {} + // func overload2(p1: (Int, Int), p2: Int) {} + // func overload2(p1: Int, p2: (Int, Int)) {} + // func overload2(p1: (Int) -> (), p2: Int) {} + // func overload2(p1: (Int) -> Int, p2: Int) {} + // func overload2(p1: (Int) -> Int?, p2: Int) {} + // func overload2(p1: ((Int) -> Int)?, p2: Int) {} // <- overload group + let reference = ResolvedTopicReference( + bundleIdentifier: bundle.identifier, + path: "/documentation/FancyOverloads/overload2(p1:p2:)-4p1sq", + sourceLanguage: .swift + ) + let symbol = try XCTUnwrap(context.entity(with: reference).semantic as? Symbol) + var translator = RenderNodeTranslator( + context: context, + bundle: bundle, + identifier: reference, + source: nil + ) + let renderNode = try XCTUnwrap(translator.visitSymbol(symbol) as? RenderNode) + let declarationsSection = try XCTUnwrap(renderNode.primaryContentSections.compactMap({ $0 as? DeclarationsRenderSection }).first) + XCTAssertEqual(declarationsSection.declarations.count, 1) + let declarations = try XCTUnwrap(declarationsSection.declarations.first) + + XCTAssertEqual( + declarationAndHighlights(for: declarations.tokens), + [ + "func overload2(p1: ((Int) -> Int)?, p2: Int)", + " ~~ ~~~~~~~~~~ " + ] + ) + + XCTAssertEqual( + declarations.otherDeclarations?.declarations.flatMap({ declarationAndHighlights(for: $0.tokens) }), + [ + "func overload2(p1: (Int) -> (), p2: Int)", + " ~ ~~~~~~~ ", + + "func overload2(p1: (Int) -> Int, p2: Int)", + " ~ ~~~~~~~~ ", + + "func overload2(p1: (Int) -> Int?, p2: Int)", + " ~ ~~~~~~~~~ ", + + // FIXME: adjust the token processing so that the comma inside the tuple isn't treated as common? + // (it breaks the declaration pretty-printer in Swift-DocC-Render and causes it to skip pretty-printing) + "func overload2(p1: (Int, Int), p2: Int)", + " ~ ~~~~~ ", + + // FIXME: adjust the token processing so that the common parenthesis is always the final one + "func overload2(p1: Int, p2: (Int, Int))", + " ~ ~~~~~ ~", + + "func overload2(p1: Int, p2: Int)", + " ", + ] + ) + } + + // Verify that the presence of type parameters doesn't cause the opening parenthesis of an + // argument list to also be highlighted, since it is combined into the same token as the + // closing angle bracket in the symbol graph. Also ensure that the leading space of the + // rendered where clause is not highlighted. + do { + // func overload3(_ p: [Int: Int]) {} // <- overload group + // func overload3(_ p: [T: T]) {} + // func overload3(_ p: [K: V]) {} + let reference = ResolvedTopicReference( + bundleIdentifier: bundle.identifier, + path: "/documentation/FancyOverloads/overload3(_:)-xql2", + sourceLanguage: .swift + ) + let symbol = try XCTUnwrap(context.entity(with: reference).semantic as? Symbol) + var translator = RenderNodeTranslator( + context: context, + bundle: bundle, + identifier: reference, + source: nil + ) + let renderNode = try XCTUnwrap(translator.visitSymbol(symbol) as? RenderNode) + let declarationsSection = try XCTUnwrap(renderNode.primaryContentSections.compactMap({ $0 as? DeclarationsRenderSection }).first) + XCTAssertEqual(declarationsSection.declarations.count, 1) + let declarations = try XCTUnwrap(declarationsSection.declarations.first) + + XCTAssertEqual( + declarationAndHighlights(for: declarations.tokens), + [ + "func overload3(_ p: [Int : Int])", + " ~~~ ~~~ ", + ] + ) + + XCTAssertEqual( + declarations.otherDeclarations?.declarations.flatMap({ declarationAndHighlights(for: $0.tokens) }), + [ + "func overload3(_ p: [K : V]) where K : Hashable", + " ~~~~~~ ~ ~ ~~~~~~~~~~~~~~~~~~", + + "func overload3(_ p: [T : T]) where T : Hashable", + " ~~~ ~ ~ ~~~~~~~~~~~~~~~~~~", + ] + ) + } + } + + func testDontHighlightWhenOverloadsAreDisabled() throws { + let symbolGraphFile = Bundle.module.url( + forResource: "FancyOverloads", + withExtension: "symbols.json", + subdirectory: "Test Resources" + )! + + let tempURL = try createTempFolder(content: [ + Folder(name: "unit-test.docc", content: [ + InfoPlist(displayName: "FancyOverloads", identifier: "com.test.example"), + CopyOfFile(original: symbolGraphFile), + ]) + ]) + + let (_, bundle, context) = try loadBundle(from: tempURL) + + for hash in ["7eht8", "8p1lo", "858ja"] { + let reference = ResolvedTopicReference( + bundleIdentifier: bundle.identifier, + path: "/documentation/FancyOverloads/overload3(_:)-\(hash)", + sourceLanguage: .swift + ) + let symbol = try XCTUnwrap(context.entity(with: reference).semantic as? Symbol) + var translator = RenderNodeTranslator( + context: context, + bundle: bundle, + identifier: reference, + source: nil + ) + let renderNode = try XCTUnwrap(translator.visitSymbol(symbol) as? RenderNode) + let declarationsSection = try XCTUnwrap(renderNode.primaryContentSections.compactMap({ $0 as? DeclarationsRenderSection }).first) + XCTAssertEqual(declarationsSection.declarations.count, 1) + let declarations = try XCTUnwrap(declarationsSection.declarations.first) + + XCTAssert(declarations.tokens.allSatisfy({ $0.highlight == nil })) + } + } +} + +/// Render a list of declaration tokens as a plain-text decoration and as a plain-text rendering of which characters are highlighted. +func declarationAndHighlights(for tokens: [DeclarationRenderSection.Token]) -> [String] { + [ + tokens.map({ $0.text }).joined(), + tokens.map({ String(repeating: $0.highlight == .changed ? "~" : " ", count: $0.text.count) }).joined() + ] } diff --git a/Tests/SwiftDocCTests/Test Resources/FancyOverloads.symbols.json b/Tests/SwiftDocCTests/Test Resources/FancyOverloads.symbols.json new file mode 100644 index 0000000000..bbcf6b46fc --- /dev/null +++ b/Tests/SwiftDocCTests/Test Resources/FancyOverloads.symbols.json @@ -0,0 +1,2682 @@ +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 6, + "patch": 0 + }, + "generator": "Apple Swift version 6.0 (swiftlang-6.0.0.3.300 clang-1600.0.20.10)" + }, + "module": { + "name": "FancyOverloads", + "platform": { + "architecture": "arm64", + "vendor": "apple", + "operatingSystem": { + "name": "macosx", + "minimumVersion": { + "major": 12, + "minor": 4 + } + } + } + }, + "symbols": [ + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload3yySDyS2iGF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload3(_:)" + ], + "names": { + "title": "overload3(_:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload3" + }, + { + "kind": "text", + "spelling": "([" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "])" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "]" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload3" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "_" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "internalParam", + "spelling": "p" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "])" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload22p12p2ySi_Sit_SitF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload2(p1:p2:)" + ], + "names": { + "title": "overload2(p1:p2:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "), " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p1", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + { + "name": "p2", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "), " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload3yySDyxxGSHRzlF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload3(_:)" + ], + "names": { + "title": "overload3(_:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload3" + }, + { + "kind": "text", + "spelling": "<" + }, + { + "kind": "genericParameter", + "spelling": "T" + }, + { + "kind": "text", + "spelling": ">([" + }, + { + "kind": "typeIdentifier", + "spelling": "T", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxxGSHRzlF1TL_xmfp" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "T", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxxGSHRzlF1TL_xmfp" + }, + { + "kind": "text", + "spelling": "])" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "T", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxxGSHRzlF1TL_xmfp" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "T", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxxGSHRzlF1TL_xmfp" + }, + { + "kind": "text", + "spelling": "]" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "swiftGenerics": { + "parameters": [ + { + "name": "T", + "index": 0, + "depth": 0 + } + ], + "constraints": [ + { + "kind": "conformance", + "lhs": "T", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload3" + }, + { + "kind": "text", + "spelling": "<" + }, + { + "kind": "genericParameter", + "spelling": "T" + }, + { + "kind": "text", + "spelling": ">(" + }, + { + "kind": "externalParam", + "spelling": "_" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "internalParam", + "spelling": "p" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "T", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxxGSHRzlF1TL_xmfp" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "T", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxxGSHRzlF1TL_xmfp" + }, + { + "kind": "text", + "spelling": "]) " + }, + { + "kind": "keyword", + "spelling": "where" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "T" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Hashable", + "preciseIdentifier": "s:SH" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload3yySDyxq_GSHRzr0_lF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload3(_:)" + ], + "names": { + "title": "overload3(_:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload3" + }, + { + "kind": "text", + "spelling": "<" + }, + { + "kind": "genericParameter", + "spelling": "K" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "genericParameter", + "spelling": "V" + }, + { + "kind": "text", + "spelling": ">([" + }, + { + "kind": "typeIdentifier", + "spelling": "K", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxq_GSHRzr0_lF1KL_xmfp" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "V", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxq_GSHRzr0_lF1VL_q_mfp" + }, + { + "kind": "text", + "spelling": "])" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "K", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxq_GSHRzr0_lF1KL_xmfp" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "V", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxq_GSHRzr0_lF1VL_q_mfp" + }, + { + "kind": "text", + "spelling": "]" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "swiftGenerics": { + "parameters": [ + { + "name": "K", + "index": 0, + "depth": 0 + }, + { + "name": "V", + "index": 1, + "depth": 0 + } + ], + "constraints": [ + { + "kind": "conformance", + "lhs": "K", + "rhs": "Hashable", + "rhsPrecise": "s:SH" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload3" + }, + { + "kind": "text", + "spelling": "<" + }, + { + "kind": "genericParameter", + "spelling": "K" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "genericParameter", + "spelling": "V" + }, + { + "kind": "text", + "spelling": ">(" + }, + { + "kind": "externalParam", + "spelling": "_" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "internalParam", + "spelling": "p" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "K", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxq_GSHRzr0_lF1KL_xmfp" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "V", + "preciseIdentifier": "s:9FancyOverloads9overload3yySDyxq_GSHRzr0_lF1VL_q_mfp" + }, + { + "kind": "text", + "spelling": "]) " + }, + { + "kind": "keyword", + "spelling": "where" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "typeIdentifier", + "spelling": "K" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Hashable", + "preciseIdentifier": "s:SH" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload22p12p2ySi_SitF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload2(p1:p2:)" + ], + "names": { + "title": "overload2(p1:p2:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p1", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + }, + { + "name": "p2", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload15paramySDyS2iG_tF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload1(param:)" + ], + "names": { + "title": "overload1(param:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "])" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "param", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "]" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "])" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload15paramySaySiGSg_tF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload1(param:)" + ], + "names": { + "title": "overload1(param:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "]?)" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "param", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "]?" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "]?)" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload15paramySiSg_tF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload1(param:)" + ], + "names": { + "title": "overload1(param:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "?)" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "param", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "?" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "?)" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload22p12p2yS2icSg_SitF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload2(p1:p2:)" + ], + "names": { + "title": "overload2(p1:p2:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": ((" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")?, " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p1", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": ((" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")?" + } + ] + }, + { + "name": "p2", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": ((" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")?, " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload22p12p2yS2iXE_SitF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload2(p1:p2:)" + ], + "names": { + "title": "overload2(p1:p2:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p1", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + }, + { + "name": "p2", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload22p12p2ySiSgSiXE_SitF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload2(p1:p2:)" + ], + "names": { + "title": "overload2(p1:p2:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "?, " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p1", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "?" + } + ] + }, + { + "name": "p2", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "?, " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload15paramySi_tF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload1(param:)" + ], + "names": { + "title": "overload1(param:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "param", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload15paramyShySiG_tF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload1(param:)" + ], + "names": { + "title": "overload1(param:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Set", + "preciseIdentifier": "s:Sh" + }, + { + "kind": "text", + "spelling": "<" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ">)" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "param", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Set", + "preciseIdentifier": "s:Sh" + }, + { + "kind": "text", + "spelling": "<" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ">" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Set", + "preciseIdentifier": "s:Sh" + }, + { + "kind": "text", + "spelling": "<" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ">)" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload22p12p2yySiXE_SitF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload2(p1:p2:)" + ], + "names": { + "title": "overload2(p1:p2:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> (), " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p1", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> ()" + } + ] + }, + { + "name": "p2", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ") -> (), " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload22p12p2ySi_Si_SittF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload2(p1:p2:)" + ], + "names": { + "title": "overload2(p1:p2:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "))" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "p1", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + } + ] + }, + { + "name": "p2", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ")" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload2" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "p1" + }, + { + "kind": "text", + "spelling": ": " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "externalParam", + "spelling": "p2" + }, + { + "kind": "text", + "spelling": ": (" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": ", " + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "))" + } + ], + "accessLevel": "public" + }, + { + "kind": { + "identifier": "swift.func", + "displayName": "Function" + }, + "identifier": { + "precise": "s:9FancyOverloads9overload15paramySaySiG_tF", + "interfaceLanguage": "swift" + }, + "pathComponents": [ + "overload1(param:)" + ], + "names": { + "title": "overload1(param:)", + "subHeading": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "])" + } + ] + }, + "functionSignature": { + "parameters": [ + { + "name": "param", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "]" + } + ] + } + ], + "returns": [ + { + "kind": "text", + "spelling": "()" + } + ] + }, + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "func" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "overload1" + }, + { + "kind": "text", + "spelling": "(" + }, + { + "kind": "externalParam", + "spelling": "param" + }, + { + "kind": "text", + "spelling": ": [" + }, + { + "kind": "typeIdentifier", + "spelling": "Int", + "preciseIdentifier": "s:Si" + }, + { + "kind": "text", + "spelling": "])" + } + ], + "accessLevel": "public" + } + ], + "relationships": [] +}