Skip to content
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

add a "references" relationship kind and referenceLocation mixin #59

Merged
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
39 changes: 39 additions & 0 deletions Sources/SymbolKit/SymbolGraph/Relationship/ReferenceLocation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2023 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

extension SymbolGraph.Relationship {
/// A mixin for `references` relationships that indicates the source location of the reference.
public struct ReferenceLocation: Mixin, Codable, Equatable {
public static var mixinKey = "referenceLocation"

/// The source locations where the reference occurs.
public var range: SymbolGraph.LineList.SourceRange

/// The URI of the source file where the reference occurs.
public var uri: String

/// The file URL of the source file where the reference occurs.
@available(macOS 10.11, *)
public var url: URL? {
// The URI string provided in the symbol graph file may be an invalid URL (rdar://69242070)
//
// Using `URL.init(dataRepresentation:relativeTo:)` here handles URI strings with unescaped
// characters without trying to escape or otherwise process the URI string in SymbolKit.
return URL(dataRepresentation: Data(uri.utf8), relativeTo: nil)
}

public init(range: SymbolGraph.LineList.SourceRange, uri: String) {
self.range = range
self.uri = uri
}
}
}
2 changes: 2 additions & 0 deletions Sources/SymbolKit/SymbolGraph/Relationship/Relationship.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ extension SymbolGraph.Relationship {
// Mixins
static let swiftConstraints = Swift.GenericConstraints.relationshipCodingInfo
static let sourceOrigin = SourceOrigin.relationshipCodingInfo
static let referenceLocation = ReferenceLocation.relationshipCodingInfo

static let mixinKeys: [String: RelationshipMixinCodingInfo] = [
CodingKeys.swiftConstraints.codingKey.stringValue: Self.swiftConstraints,
CodingKeys.sourceOrigin.codingKey.stringValue: Self.sourceOrigin,
CodingKeys.referenceLocation.codingKey.stringValue: Self.referenceLocation,
]

static func == (lhs: SymbolGraph.Relationship.CodingKeys, rhs: SymbolGraph.Relationship.CodingKeys) -> Bool {
Expand Down
11 changes: 11 additions & 0 deletions Sources/SymbolKit/SymbolGraph/Relationship/RelationshipKind.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,16 @@ extension SymbolGraph.Relationship {
by an extension block symbol `A`.
*/
public static let extensionTo = Kind(rawValue: "extensionTo")

/**
A symbol `A` references a symbol `B` in its implementation.

This relationship can be used to describe implementation details of functions or
properties, by noting which symbols are used in its implementation.

The implied inverse of this relationship is that the symbol `B` is referenced by the
symbol `A`.
*/
public static let references = Kind(rawValue: "references")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
This source file is part of the Swift.org open source project

Copyright (c) 2023 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 XCTest
@testable import SymbolKit

class ReferenceLocationTests: XCTestCase {
typealias ReferenceLocation = SymbolGraph.Relationship.ReferenceLocation

func testRoundTrip() throws {
let referenceLocation = ReferenceLocation(
range: .init(
start: .init(line: 14, character: 0),
end: .init(line: 14, character: 6)),
uri: "file://file.swift"
)
var source = SymbolGraph.Relationship(source: "source", target: "target", kind: .references, targetFallback: nil)
source[mixin: ReferenceLocation.self] = referenceLocation

let encoder = JSONEncoder()
let decoder = JSONDecoder()

let encodedRelationship = try encoder.encode(source)
let decoded = try decoder.decode(SymbolGraph.Relationship.self, from: encodedRelationship)

XCTAssertEqual(source, decoded)
XCTAssertEqual(decoded[mixin: ReferenceLocation.self], referenceLocation)
}
}