Skip to content

Commit

Permalink
Decode the new docComment module and file information (#42)
Browse files Browse the repository at this point in the history
* Decode the new docComment module and file information

* Add new function that takes the symbol module's name as an argument
  • Loading branch information
d-ronnqvist committed Jun 21, 2022
1 parent f88800d commit d46f688
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 15 deletions.
20 changes: 17 additions & 3 deletions Sources/SymbolKit/SymbolGraph/LineList/LineList.swift
Original file line number Diff line number Diff line change
@@ -1,13 +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

extension SymbolGraph {
/**
A `LineList` is a logical grouping of text ranges in a document making up a block of textual content.
Expand Down Expand Up @@ -91,9 +93,21 @@ extension SymbolGraph {
public struct LineList: Codable, Equatable {
/// The lines making up this line list.
public var lines: [Line]

public init(_ lines: [Line]) {
/// The file URL of the source file where the documentation comment originated.
public var url: URL?
/// The name of the source module where the documentation comment originated.
public var moduleName: String?

enum CodingKeys: String, CodingKey {
case lines
case url = "uri"
case moduleName = "module"
}

public init(_ lines: [Line], url: URL? = nil, moduleName: String? = nil) {
self.lines = lines
self.url = url
self.moduleName = moduleName
}

/**
Expand Down
28 changes: 27 additions & 1 deletion Sources/SymbolKit/SymbolGraph/Symbol/Symbol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,43 @@ extension SymbolGraph {
/// the same module as the symbol or not.
///
/// An inherited documentation comment is from the same module when the symbol that the documentation is inherited from is in the same module as this symbol.
@available(*, deprecated, message: "Use 'isDocCommentFromSameModule(symbolModuleName:)' instead.")
public var isDocCommentFromSameModule: Bool? {
_isDocCommentFromSameModule
}
// To avoid deprecation warnings in SymbolKit test until the deprecated property is removed.
internal var _isDocCommentFromSameModule: Bool? {
guard let docComment = docComment, !docComment.lines.isEmpty else {
return nil
}

// As a current implementation detail, documentation comments from within the current module has range information but
// documentation comments that are inherited from other modules don't have any range information.
//
// It would be better for correctness and accuracy to determine this when extracting the symbol information (rdar://81190369)
// This isn't always correct and is only used as a fallback logic for symbol information before the source module was
// included in the symbol graph file.
return docComment.lines.contains(where: { $0.range != nil })
}

/// If the symbol has a documentation comment, checks whether the documentation comment is from the same module as the symbol.
///
/// A documentation comment is from the same module as the symbol when the source of the documentation comment is the symbol itself or another symbol in the same module.
///
/// - Parameter symbolModuleName: The name of the module where the symbol is defined.
/// - Returns: `true`if the source of the documentation comment is from the same module as this symbol.
public func isDocCommentFromSameModule(symbolModuleName: String) -> Bool? {
guard let docComment = docComment, !docComment.lines.isEmpty else {
return nil
}

if let moduleName = docComment.moduleName {
// If the new source module information is available, rely on that.
return moduleName == symbolModuleName
} else {
// Otherwise, fallback to the previous implementation.
return _isDocCommentFromSameModule
}
}

/// The access level of the symbol.
public var accessLevel: AccessControl
Expand Down
39 changes: 28 additions & 11 deletions Tests/SymbolKitTests/SymbolGraph/SymbolTests.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 @@ -19,39 +19,57 @@ class SymbolTests: XCTestCase {
let jsonData = encodedSymbol(withDocComment: nil).data(using: .utf8)!
let symbol = try JSONDecoder().decode(SymbolGraph.Symbol.self, from: jsonData)

XCTAssertNil(symbol.isDocCommentFromSameModule)
XCTAssertNil(symbol._isDocCommentFromSameModule)
XCTAssertNil(symbol.isDocCommentFromSameModule(symbolModuleName: "Test"))
}

// without range information
do {
let jsonData = encodedSymbol(withDocComment:
(lines: ["First line", "Second line"], rangeStart: nil)
(lines: ["First line", "Second line"], rangeStart: nil, moduleName: nil, fileName: nil)
).data(using: .utf8)!
let symbol = try JSONDecoder().decode(SymbolGraph.Symbol.self, from: jsonData)

XCTAssertEqual(symbol.isDocCommentFromSameModule, false)
XCTAssertEqual(symbol._isDocCommentFromSameModule, false)
XCTAssertEqual(symbol.isDocCommentFromSameModule(symbolModuleName: "Test"), false)
}

// with range information
do {
let jsonData = encodedSymbol(withDocComment:
(lines: ["First line", "Second line"], rangeStart: (line: 2, character: 4))
(lines: ["First line", "Second line"], rangeStart: (line: 2, character: 4), moduleName: nil, fileName: nil)
).data(using: .utf8)!
let symbol = try JSONDecoder().decode(SymbolGraph.Symbol.self, from: jsonData)

XCTAssertEqual(symbol.isDocCommentFromSameModule, true)
XCTAssertEqual(symbol._isDocCommentFromSameModule, true)
XCTAssertEqual(symbol.isDocCommentFromSameModule(symbolModuleName: "Test"), true)
}

// empty doc comment
do {
let jsonData = encodedSymbol(withDocComment:
(lines: [], rangeStart: (line: 2, character: 4))
(lines: [], rangeStart: (line: 2, character: 4), moduleName: nil, fileName: nil)
).data(using: .utf8)!
let symbol = try JSONDecoder().decode(SymbolGraph.Symbol.self, from: jsonData)

XCTAssertNil(symbol.isDocCommentFromSameModule)
XCTAssertNil(symbol._isDocCommentFromSameModule)
XCTAssertNil(symbol.isDocCommentFromSameModule(symbolModuleName: "Test"))
}
}

func testDocCommentModuleInformation() throws {
let jsonData = encodedSymbol(withDocComment:
(lines: ["First line", "Second line"], rangeStart: nil, moduleName: "ModuleName", fileName: "file name")
).data(using: .utf8)!
let symbol = try JSONDecoder().decode(SymbolGraph.Symbol.self, from: jsonData)

XCTAssertEqual(symbol.docComment?.moduleName, "ModuleName")
XCTAssertEqual(symbol.docComment?.url?.isFileURL, true)
XCTAssertEqual(symbol.docComment?.url?.pathComponents.last, "file name")

XCTAssertEqual(symbol.isDocCommentFromSameModule(symbolModuleName: "ModuleName"), true)
XCTAssertEqual(symbol.isDocCommentFromSameModule(symbolModuleName: "Test"), false)
}

/// Check that a Location mixin without position information still decodes a symbol graph without throwing.
func testMalformedLocationDoesNotThrow() throws {
Expand Down Expand Up @@ -109,8 +127,7 @@ class SymbolTests: XCTestCase {

// MARK: Test Data

private func encodedSymbol(withDocComment: (lines: [String], rangeStart: (line: Int, character: Int)?)?) -> String {

private func encodedSymbol(withDocComment: (lines: [String], rangeStart: (line: Int, character: Int)?, moduleName: String?, fileName: String?)?) -> String {
let docCommentJSON: String
if let withDocComment = withDocComment {
let lineList = SymbolGraph.LineList(withDocComment.lines.enumerated().map { index, text in
Expand All @@ -121,7 +138,7 @@ private func encodedSymbol(withDocComment: (lines: [String], rangeStart: (line:
)
}
return SymbolGraph.LineList.Line(text: text, range: range)
})
}, url: withDocComment.fileName.map({ URL(fileURLWithPath: $0) }), moduleName: withDocComment.moduleName)
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try! encoder.encode(lineList)
Expand Down

0 comments on commit d46f688

Please sign in to comment.