1 //===--- SourceCode.h - Manipulating source code as strings -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Various code that examines C++ source code without using heavy AST machinery
11 // (and often not even the lexer). To be used sparingly!
12 //
13 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
15 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SOURCECODE_H
16 #include "Protocol.h"
17 #include "clang/Basic/Diagnostic.h"
18 #include "clang/Basic/SourceLocation.h"
19 #include "clang/Basic/SourceManager.h"
20 #include "clang/Tooling/Core/Replacement.h"
21 #include "llvm/Support/SHA1.h"
22 
23 namespace clang {
24 class SourceManager;
25 
26 namespace clangd {
27 
28 // We tend to generate digests for source codes in a lot of different places.
29 // This represents the type for those digests to prevent us hard coding details
30 // of hashing function at every place that needs to store this information.
31 using FileDigest = decltype(llvm::SHA1::hash({}));
32 FileDigest digest(StringRef Content);
33 Optional<FileDigest> digestFile(const SourceManager &SM, FileID FID);
34 
35 // Counts the number of UTF-16 code units needed to represent a string (LSP
36 // specifies string lengths in UTF-16 code units).
37 size_t lspLength(StringRef Code);
38 
39 /// Turn a [line, column] pair into an offset in Code.
40 ///
41 /// If P.character exceeds the line length, returns the offset at end-of-line.
42 /// (If !AllowColumnsBeyondLineLength, then returns an error instead).
43 /// If the line number is out of range, returns an error.
44 ///
45 /// The returned value is in the range [0, Code.size()].
46 llvm::Expected<size_t>
47 positionToOffset(llvm::StringRef Code, Position P,
48                  bool AllowColumnsBeyondLineLength = true);
49 
50 /// Turn an offset in Code into a [line, column] pair.
51 /// The offset must be in range [0, Code.size()].
52 Position offsetToPosition(llvm::StringRef Code, size_t Offset);
53 
54 /// Turn a SourceLocation into a [line, column] pair.
55 /// FIXME: This should return an error if the location is invalid.
56 Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc);
57 
58 // Converts a half-open clang source range to an LSP range.
59 // Note that clang also uses closed source ranges, which this can't handle!
60 Range halfOpenToRange(const SourceManager &SM, CharSourceRange R);
61 
62 // Converts an offset to a clang line/column (1-based, columns are bytes).
63 // The offset must be in range [0, Code.size()].
64 // Prefer to use SourceManager if one is available.
65 std::pair<size_t, size_t> offsetToClangLineColumn(llvm::StringRef Code,
66                                                   size_t Offset);
67 
68 /// From "a::b::c", return {"a::b::", "c"}. Scope is empty if there's no
69 /// qualifier.
70 std::pair<llvm::StringRef, llvm::StringRef>
71 splitQualifiedName(llvm::StringRef QName);
72 
73 TextEdit replacementToEdit(StringRef Code, const tooling::Replacement &R);
74 
75 std::vector<TextEdit> replacementsToEdits(StringRef Code,
76                                           const tooling::Replacements &Repls);
77 
78 TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M,
79                     const LangOptions &L);
80 
81 /// Get the canonical path of \p F.  This means:
82 ///
83 ///   - Absolute path
84 ///   - Symlinks resolved
85 ///   - No "." or ".." component
86 ///   - No duplicate or trailing directory separator
87 ///
88 /// This function should be used when paths needs to be used outside the
89 /// component that generate it, so that paths are normalized as much as
90 /// possible.
91 llvm::Optional<std::string> getCanonicalPath(const FileEntry *F,
92                                              const SourceManager &SourceMgr);
93 
94 bool IsRangeConsecutive(const Range &Left, const Range &Right);
95 } // namespace clangd
96 } // namespace clang
97 #endif
98