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