reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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
//===--- URI.h - File URIs with schemes --------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATHURI_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATHURI_H

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Registry.h"

namespace clang {
namespace clangd {

/// A URI describes the location of a source file.
/// In the simplest case, this is a "file" URI that directly encodes the
/// absolute path to a file. More abstract cases are possible: a shared index
/// service might expose repo:// URIs that are relative to the source control
/// root.
///
/// Clangd handles URIs of the form <scheme>:[//<authority>]<body>. It doesn't
/// further split the authority or body into constituent parts (e.g. query
/// strings is included in the body).
class URI {
public:
  URI(llvm::StringRef Scheme, llvm::StringRef Authority, llvm::StringRef Body);

  /// Returns decoded scheme e.g. "https"
  llvm::StringRef scheme() const { return Scheme; }
  /// Returns decoded authority e.g. "reviews.lvm.org"
  llvm::StringRef authority() const { return Authority; }
  /// Returns decoded body e.g. "/D41946"
  llvm::StringRef body() const { return Body; }

  /// Returns a string URI with all components percent-encoded.
  std::string toString() const;

  /// Creates a URI for a file in the given scheme. \p Scheme must be
  /// registered. The URI is percent-encoded.
  static llvm::Expected<URI> create(llvm::StringRef AbsolutePath,
                                    llvm::StringRef Scheme);

  // Similar to above except this picks a registered scheme that works. If none
  // works, this falls back to "file" scheme.
  static URI create(llvm::StringRef AbsolutePath);

  /// This creates a file:// URI for \p AbsolutePath. The path must be absolute.
  static URI createFile(llvm::StringRef AbsolutePath);

  /// Parse a URI string "<scheme>:[//<authority>/]<path>". Percent-encoded
  /// characters in the URI will be decoded.
  static llvm::Expected<URI> parse(llvm::StringRef Uri);

  /// Resolves the absolute path of \p U. If there is no matching scheme, or the
  /// URI is invalid in the scheme, this returns an error.
  ///
  /// \p HintPath A related path, such as the current file or working directory,
  /// which can help disambiguate when the same file exists in many workspaces.
  static llvm::Expected<std::string> resolve(const URI &U,
                                             llvm::StringRef HintPath = "");

  /// Same as above, in addition it parses the \p FileURI using URI::parse.
  static llvm::Expected<std::string> resolve(llvm::StringRef FileURI,
                                             llvm::StringRef HintPath = "");

  /// Resolves \p AbsPath into a canonical path of its URI, by converting
  /// \p AbsPath to URI and resolving the URI to get th canonical path.
  /// This ensures that paths with the same URI are resolved into consistent
  /// file path.
  static llvm::Expected<std::string> resolvePath(llvm::StringRef AbsPath,
                                                 llvm::StringRef HintPath = "");

  /// Gets the preferred spelling of this file for #include, if there is one,
  /// e.g. <system_header.h>, "path/to/x.h".
  ///
  /// This allows URI schemas to provide their customized include paths.
  ///
  /// Returns an empty string if normal include-shortening based on the absolute
  /// path should be used.
  /// Fails if the URI is not valid in the schema.
  static llvm::Expected<std::string> includeSpelling(const URI &U);

  friend bool operator==(const URI &LHS, const URI &RHS) {
    return std::tie(LHS.Scheme, LHS.Authority, LHS.Body) ==
           std::tie(RHS.Scheme, RHS.Authority, RHS.Body);
  }

  friend bool operator<(const URI &LHS, const URI &RHS) {
    return std::tie(LHS.Scheme, LHS.Authority, LHS.Body) <
           std::tie(RHS.Scheme, RHS.Authority, RHS.Body);
  }

private:
  URI() = default;

  std::string Scheme;
  std::string Authority;
  std::string Body;
};

/// URIScheme is an extension point for teaching clangd to recognize a custom
/// URI scheme. This is expected to be implemented and exposed via the
/// URISchemeRegistry.
class URIScheme {
public:
  virtual ~URIScheme() = default;

  /// Returns the absolute path of the file corresponding to the URI
  /// authority+body in the file system. See URI::resolve for semantics of
  /// \p HintPath.
  virtual llvm::Expected<std::string>
  getAbsolutePath(llvm::StringRef Authority, llvm::StringRef Body,
                  llvm::StringRef HintPath) const = 0;

  virtual llvm::Expected<URI>
  uriFromAbsolutePath(llvm::StringRef AbsolutePath) const = 0;

  /// Returns the include path of the file (e.g. <path>, "path"), which can be
  /// #included directly. See URI::includeSpelling for details.
  virtual llvm::Expected<std::string> getIncludeSpelling(const URI &U) const {
    return ""; // no customized include path for this scheme.
  }
};

/// By default, a "file" scheme is supported where URI paths are always absolute
/// in the file system.
typedef llvm::Registry<URIScheme> URISchemeRegistry;

} // namespace clangd
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATHURI_H