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 #include "SourceCode.h"
10 
11 #include "clang/Basic/SourceManager.h"
12 
13 namespace clang {
14 namespace clangd {
15 using namespace llvm;
16 
17 size_t positionToOffset(StringRef Code, Position P) {
18   if (P.line < 0)
19     return 0;
20   size_t StartOfLine = 0;
21   for (int I = 0; I != P.line; ++I) {
22     size_t NextNL = Code.find('\n', StartOfLine);
23     if (NextNL == StringRef::npos)
24       return Code.size();
25     StartOfLine = NextNL + 1;
26   }
27   // FIXME: officially P.character counts UTF-16 code units, not UTF-8 bytes!
28   return std::min(Code.size(), StartOfLine + std::max(0, P.character));
29 }
30 
31 Position offsetToPosition(StringRef Code, size_t Offset) {
32   Offset = std::min(Code.size(), Offset);
33   StringRef Before = Code.substr(0, Offset);
34   int Lines = Before.count('\n');
35   size_t PrevNL = Before.rfind('\n');
36   size_t StartOfLine = (PrevNL == StringRef::npos) ? 0 : (PrevNL + 1);
37   // FIXME: officially character counts UTF-16 code units, not UTF-8 bytes!
38   Position Pos;
39   Pos.line = Lines;
40   Pos.character = static_cast<int>(Offset - StartOfLine);
41   return Pos;
42 }
43 
44 Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc) {
45   Position P;
46   P.line = static_cast<int>(SM.getSpellingLineNumber(Loc)) - 1;
47   P.character = static_cast<int>(SM.getSpellingColumnNumber(Loc)) - 1;
48   return P;
49 }
50 
51 Range halfOpenToRange(const SourceManager &SM, CharSourceRange R) {
52   // Clang is 1-based, LSP uses 0-based indexes.
53   Position Begin = sourceLocToPosition(SM, R.getBegin());
54   Position End = sourceLocToPosition(SM, R.getEnd());
55 
56   return {Begin, End};
57 }
58 
59 } // namespace clangd
60 } // namespace clang
61