File: ReferenceDocumentURL.swift

package info (click to toggle)
swiftlang 6.1.3-4
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 2,791,644 kB
  • sloc: cpp: 9,901,738; ansic: 2,201,433; asm: 1,091,827; python: 308,252; objc: 82,166; f90: 80,126; lisp: 38,358; pascal: 25,559; sh: 20,429; ml: 5,058; perl: 4,745; makefile: 4,484; awk: 3,535; javascript: 3,018; xml: 918; fortran: 664; cs: 573; ruby: 396
file content (137 lines) | stat: -rw-r--r-- 4,897 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 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 the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import Foundation
import LanguageServerProtocol

/// A Reference Document is a document whose url scheme is `sourcekit-lsp:` and whose content can only be retrieved
/// using `GetReferenceDocumentRequest`. The enum represents a specific type of reference document and its
/// associated value represents the data necessary to generate the document's contents and its url
///
/// The `url` will be of the form: `sourcekit-lsp://<document-type>/<display-name>?<parameters>`
/// Here,
///  - The `<document-type>` denotes the kind of the content present in the reference document
///  - The `<parameters>` denotes the parameter-value pairs such as "p1=v1&p2=v2&..." needed to generate
/// the content of the reference document.
///  - The `<display-name>` is the displayed file name of the reference document. It doesn't involve in generating
/// the content of the reference document.
package enum ReferenceDocumentURL {
  package static let scheme = "sourcekit-lsp"

  case macroExpansion(MacroExpansionReferenceDocumentURLData)

  var url: URL {
    get throws {
      switch self {
      case let .macroExpansion(data):
        var components = URLComponents()
        components.scheme = Self.scheme
        components.host = MacroExpansionReferenceDocumentURLData.documentType
        components.path = "/\(data.displayName)"
        components.queryItems = data.queryItems

        guard let url = components.url else {
          throw ReferenceDocumentURLError(
            description: "Unable to create URL for macro expansion reference document"
          )
        }

        return url
      }
    }
  }

  init(from uri: DocumentURI) throws {
    try self.init(from: uri.arbitrarySchemeURL)
  }

  init(from url: URL) throws {
    guard url.scheme == Self.scheme else {
      throw ReferenceDocumentURLError(description: "Invalid Scheme for reference document")
    }

    let documentType = url.host

    switch documentType {
    case MacroExpansionReferenceDocumentURLData.documentType:
      guard let queryItems = URLComponents(string: url.absoluteString)?.queryItems else {
        throw ReferenceDocumentURLError(
          description: "No queryItems passed for macro expansion reference document: \(url)"
        )
      }

      let macroExpansionURLData = try MacroExpansionReferenceDocumentURLData(
        displayName: url.lastPathComponent,
        queryItems: queryItems
      )
      self = .macroExpansion(macroExpansionURLData)
    case nil:
      throw ReferenceDocumentURLError(
        description: "Bad URL for reference document: \(url)"
      )
    case let documentType?:
      throw ReferenceDocumentURLError(
        description: "Invalid document type in URL for reference document: \(documentType)"
      )
    }
  }

  /// The path that should be passed as `keys.sourcefile` to sourcekitd in conjunction with a `keys.primaryFile`.
  ///
  /// For macro expansions, this is the buffer name that the URI references.
  var sourcekitdSourceFile: String {
    switch self {
    case let .macroExpansion(data): data.bufferName
    }
  }

  var primaryFile: DocumentURI {
    switch self {
    case let .macroExpansion(data):
      return data.primaryFile
    }
  }
}

extension DocumentURI {
  /// The path that should be passed as `keys.sourcefile` to sourcekitd in conjunction with a `keys.primaryFile`.
  ///
  /// For normal document URIs, this is the pseudo path of this URI. For macro expansions, this is the buffer name
  /// that the URI references.
  var sourcekitdSourceFile: String {
    if let referenceDocument = try? ReferenceDocumentURL(from: self) {
      referenceDocument.sourcekitdSourceFile
    } else {
      self.pseudoPath
    }
  }

  /// If this is a URI to a reference document, the URI of the source file from which this reference document was
  /// derived.
  ///
  /// The primary file is used to determine the workspace and language service that is used to generate the reference
  /// document as well as getting the reference document's build settings.
  var primaryFile: DocumentURI? {
    if let referenceDocument = try? ReferenceDocumentURL(from: self) {
      return referenceDocument.primaryFile
    }
    return nil
  }
}

package struct ReferenceDocumentURLError: Error, CustomStringConvertible {
  package var description: String

  init(description: String) {
    self.description = description
  }
}