1 /*
2  * SourceLocation.cpp
3  *
4  * Copyright (C) 2021 by RStudio, PBC
5  *
6  * Unless you have received this program directly from RStudio pursuant
7  * to the terms of a commercial license agreement with RStudio, then
8  * this program is licensed to you under the terms of version 3 of the
9  * GNU Affero General Public License. This program is distributed WITHOUT
10  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
11  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
12  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
13  *
14  */
15 
16 #include <core/libclang/SourceLocation.hpp>
17 
18 #include <core/libclang/LibClang.hpp>
19 
20 namespace rstudio {
21 namespace core {
22 namespace libclang {
23 
operator <<(std::ostream & stream,const FileLocation & loc)24 std::ostream& operator << (std::ostream& stream, const FileLocation& loc)
25 {
26    stream << loc.filePath << " [" << loc.line << ", " << loc.column << "]";
27    return stream;
28 }
29 
SourceLocation()30 SourceLocation::SourceLocation()
31    : location_(clang().getNullLocation())
32 {
33 }
34 
empty() const35 bool SourceLocation::empty() const
36 {
37    return clang().equalLocations(location_, clang().getNullLocation());
38 }
39 
isFromMainFile() const40 bool SourceLocation::isFromMainFile() const
41 {
42    return clang().Location_isFromMainFile(location_);
43 }
44 
isInSystemHeader() const45 bool SourceLocation::isInSystemHeader() const
46 {
47    return clang().Location_isInSystemHeader(location_);
48 }
49 
getExpansionLocation(std::string * pFile,unsigned * pLine,unsigned * pColumn,unsigned * pOffset) const50 void SourceLocation::getExpansionLocation(std::string* pFile,
51                                           unsigned* pLine,
52                                           unsigned* pColumn,
53                                           unsigned* pOffset) const
54 {
55    CXFile file;
56    clang().getExpansionLocation(location_, &file, pLine, pColumn, pOffset);
57 
58    CXString filename = clang().getFileName(file);
59    *pFile = toStdString(filename);
60 }
61 
printExpansionLocation(std::ostream & ostr)62 void SourceLocation::printExpansionLocation(std::ostream& ostr)
63 {
64    std::string file;
65    unsigned line, offset;
66    getExpansionLocation(&file, &line, &offset, nullptr);
67    ostr << file << " [line: " << line << ", col: " << offset << "]";
68 }
69 
70 
getSpellingLocation(std::string * pFile,unsigned * pLine,unsigned * pColumn,unsigned * pOffset) const71 bool SourceLocation::getSpellingLocation(std::string* pFile,
72                                          unsigned* pLine,
73                                          unsigned* pColumn,
74                                          unsigned* pOffset) const
75 {
76    if (!empty())
77    {
78       CXFile file;
79       clang().getSpellingLocation(location_, &file, pLine, pColumn, pOffset);
80 
81       CXString filename = clang().getFileName(file);
82       *pFile = toStdString(filename);
83       return true;
84    }
85    else
86    {
87       return false;
88    }
89 }
90 
getSpellingLocation() const91 FileLocation SourceLocation::getSpellingLocation() const
92 {
93    std::string file;
94    unsigned line, column;
95    if (getSpellingLocation(&file, &line, &column))
96       return FileLocation(FilePath(file), line, column);
97    else
98       return FileLocation();
99 }
100 
printSpellingLocation(std::ostream & ostr)101 void SourceLocation::printSpellingLocation(std::ostream& ostr)
102 {
103    std::string file;
104    unsigned line, offset;
105    if (getSpellingLocation(&file, &line, &offset, nullptr))
106       ostr << file << " [line: " << line << ", col: " << offset << "]";
107 }
108 
operator ==(const SourceLocation & other) const109 bool SourceLocation::operator==(const SourceLocation& other) const
110 {
111    return clang().equalLocations(location_, other.location_) != 0;
112 }
113 
operator !=(const SourceLocation & other) const114 bool SourceLocation::operator!=(const SourceLocation& other) const
115 {
116    return clang().equalLocations(location_, other.location_) == 0;
117 }
118 
119 } // namespace libclang
120 } // namespace core
121 } // namespace rstudio
122