Skip to content

Commit

Permalink
Accept more Objective-C symbol graph identifiers
Browse files Browse the repository at this point in the history
Accept "objective-c" and "c" as interface language identifiers in symbol
graph files emitted by clang.

rdar://90361614
  • Loading branch information
franklinsch committed Mar 31, 2022
1 parent 5258679 commit 326d234
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 18 deletions.
31 changes: 24 additions & 7 deletions Sources/SwiftDocC/Model/SourceLanguage.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021 Apple Inc. and the Swift project authors
Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
Expand All @@ -14,14 +14,18 @@ public struct SourceLanguage: Hashable, Codable {
public var name: String
/// A globally unique identifier for the language.
public var id: String
/// Aliases for the language's identifier.
public var idAliases: [String] = []

/// Creates a new language with a given name and identifier.
/// - Parameters:
/// - name: The display name of the programming language.
/// - id: A globally unique identifier for the language.
public init(name: String, id: String) {
/// - idAliases: Aliases for the language's identifier.
public init(name: String, id: String, idAliases: [String] = []) {
self.name = name
self.id = id
self.idAliases = idAliases
}

/// Finds the programming language that matches a given query identifier.
Expand All @@ -34,7 +38,7 @@ public struct SourceLanguage: Hashable, Codable {
switch queryID {
case "swift":
self = .swift
case "occ":
case "occ", "objective-c", "c":
self = .objectiveC
case "javascript":
self = .javaScript
Expand All @@ -52,7 +56,7 @@ public struct SourceLanguage: Hashable, Codable {
public init(id: String) {
switch id {
case "swift": self = .swift
case "occ": self = .objectiveC
case "occ", "objective-c", "c": self = .objectiveC
case "javascript": self = .javaScript
case "data": self = .data
case "metal": self = .metal
Expand Down Expand Up @@ -101,17 +105,30 @@ public struct SourceLanguage: Hashable, Codable {
}

private static func firstKnownLanguage(withName name: String) -> SourceLanguage? {
return SourceLanguage.knownLanguages.first { $0.name.lowercased() == name.lowercased() }
SourceLanguage.knownLanguages.first { $0.name.lowercased() == name.lowercased() }
}

private static func firstKnownLanguage(withIdentifier id: String) -> SourceLanguage? {
return SourceLanguage.knownLanguages.first { $0.id.lowercased() == id.lowercased() }
SourceLanguage.knownLanguages.first { knownLanguage in
([knownLanguage.id] + knownLanguage.idAliases)
.map { $0.lowercased() }
.contains(id)
}
}

/// The Swift programming language.
public static let swift = SourceLanguage(name: "Swift", id: "swift")

/// The Objective-C programming language.
public static let objectiveC = SourceLanguage(name: "Objective-C", id: "occ")
public static let objectiveC = SourceLanguage(
name: "Objective-C",
id: "occ",
idAliases: [
"objective-c",
"c", // FIXME: DocC should display C as its own language (SR-16050).
]
)

/// The JavaScript programming language or another language that conforms to the ECMAScript specification.
public static let javaScript = SourceLanguage(name: "JavaScript", id: "javascript")
/// Miscellaneous data, that's not a programming language.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021 Apple Inc. and the Swift project authors
Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
Expand All @@ -23,7 +23,7 @@ extension DocumentationDataVariants {
guard selector.platform == platformName else { return nil }

return (
DocumentationDataVariantsTrait(interfaceLanguage: selector.interfaceLanguage),
DocumentationDataVariantsTrait(for: selector),
transform(value)
)
}
Expand All @@ -44,7 +44,7 @@ extension DocumentationDataVariants {
else { return nil }

return (
DocumentationDataVariantsTrait(interfaceLanguage: selector.interfaceLanguage),
DocumentationDataVariantsTrait(for: selector),
value
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021 Apple Inc. and the Swift project authors
Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation
import SymbolKit

/// A model type that encapsulates variants of documentation node data.
///
Expand Down Expand Up @@ -141,4 +142,14 @@ public struct DocumentationDataVariantsTrait: Hashable {
public init(interfaceLanguage: String? = nil) {
self.interfaceLanguage = interfaceLanguage
}

/// Creates a new trait given a symbol graph selector.
///
/// - Parameter selector: The symbol graph selector to use when creating the trait.
public init(for selector: UnifiedSymbolGraph.Selector) {
self.init(
interfaceLanguage: SourceLanguage(knownLanguageIdentifier: selector.interfaceLanguage)?.id
?? selector.interfaceLanguage
)
}
}
2 changes: 1 addition & 1 deletion Sources/SwiftDocC/Semantics/Symbol/Symbol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ extension Symbol {
/// depending on variances in their implementation across platforms (e.g. use `NSPoint` vs `CGPoint` parameter in a method).
/// This method finds matching symbols between graphs and merges their declarations in case there are differences.
func mergeDeclaration(mergingDeclaration: SymbolGraph.Symbol.DeclarationFragments, identifier: String, symbolAvailability: SymbolGraph.Symbol.Availability?, selector: UnifiedSymbolGraph.Selector) throws {
let trait = DocumentationDataVariantsTrait(interfaceLanguage: selector.interfaceLanguage)
let trait = DocumentationDataVariantsTrait(for: selector)
let platformName = selector.platform

if let platformName = platformName,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2021 Apple Inc. and the Swift project authors
Copyright (c) 2021-2022 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
Expand Down Expand Up @@ -76,9 +76,26 @@ class SemaToRenderNodeMixedLanguageTests: XCTestCase {
)
}
}

func testOutputsMultiLanguageRenderNodes() throws {
let outputConsumer = try mixedLanguageFrameworkConsumer()

func assertOutputsMultiLanguageRenderNodes(variantInterfaceLanguage: String) throws {
let outputConsumer = try mixedLanguageFrameworkConsumer { bundleURL in
// Update the clang symbol graph with the Objective-C identifier given in variantInterfaceLanguage.

let clangSymbolGraphLocation = bundleURL
.appendingPathComponent("symbol-graphs")
.appendingPathComponent("clang")
.appendingPathComponent("MixedLanguageFramework.symbols.json")

var clangSymbolGraph = try JSONDecoder().decode(SymbolGraph.self, from: Data(contentsOf: clangSymbolGraphLocation))

clangSymbolGraph.symbols = clangSymbolGraph.symbols.mapValues { symbol in
var symbol = symbol
symbol.identifier.interfaceLanguage = variantInterfaceLanguage
return symbol
}

try JSONEncoder().encode(clangSymbolGraph).write(to: clangSymbolGraphLocation)
}

XCTAssertEqual(
Set(
Expand Down Expand Up @@ -136,7 +153,7 @@ class SemaToRenderNodeMixedLanguageTests: XCTestCase {
"c:@M@TestFramework@objc(pl)MixedLanguageProtocol(im)mixedLanguageMethod",
"c:@M@TestFramework@objc(cs)MixedLanguageClassConformingToProtocol(im)init",
"c:@CM@TestFramework@objc(cs)MixedLanguageClassConformingToProtocol(im)mixedLanguageMethod",

"MixedLanguageProtocol Implementations",
"Article",
"APICollection",
Expand All @@ -146,7 +163,19 @@ class SemaToRenderNodeMixedLanguageTests: XCTestCase {
]
)
}


func testOutputsMultiLanguageRenderNodesWithOccIdentifier() throws {
try assertOutputsMultiLanguageRenderNodes(variantInterfaceLanguage: "occ")
}

func testOutputsMultiLanguageRenderNodesWithObjectiveCIdentifier() throws {
try assertOutputsMultiLanguageRenderNodes(variantInterfaceLanguage: "objective-c")
}

func testOutputsMultiLanguageRenderNodesWithCIdentifier() throws {
try assertOutputsMultiLanguageRenderNodes(variantInterfaceLanguage: "c")
}

func testFrameworkRenderNodeHasExpectedContentAcrossLanguages() throws {
let outputConsumer = try mixedLanguageFrameworkConsumer()
let mixedLanguageFrameworkRenderNode = try outputConsumer.renderNode(
Expand Down
19 changes: 19 additions & 0 deletions Tests/SwiftDocCTests/Model/SourceLanguageTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2022 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

@testable import SwiftDocC
import XCTest

class SourceLanguageTests: XCTestCase {
func testUsesIDAliasesWhenQueryingFirstKnownLanguage() {
XCTAssertEqual(SourceLanguage(knownLanguageIdentifier: "objective-c"), .objectiveC)
XCTAssertEqual(SourceLanguage(knownLanguageIdentifier: "c"), .objectiveC)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import Foundation
import XCTest
import SymbolKit
@testable import SwiftDocC

class DocumentationDataVariantsTests: XCTestCase {
Expand Down Expand Up @@ -84,4 +85,16 @@ class DocumentationDataVariantsTests: XCTestCase {
variants[objectiveCTrait] = "Objective-C"
XCTAssertEqual(variants.firstValue, "Swift") // Swift is still treated as the default value.
}

func testInitializesUsingSelectorLanguage() {
XCTAssertEqual(
DocumentationDataVariantsTrait(
for: UnifiedSymbolGraph.Selector(
interfaceLanguage: "MyLanguage",
platform: nil
)
).interfaceLanguage,
"MyLanguage"
)
}
}

0 comments on commit 326d234

Please sign in to comment.