forked from qt-creator/qt-creator
Clang: Add clang query
Clang query is mechanism to use AST matcher to search for code. Think about regular expression but in the context of AST. So you get a semantic search tool for C++. Change-Id: I72e882c5b53a0c52f352a3664847c4c3e4f6fc2e Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <sourcelocationscontainer.h>
|
||||
#include <sourcerangescontainer.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
@@ -40,6 +41,8 @@
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include <cctype>
|
||||
|
||||
namespace ClangBackEnd {
|
||||
|
||||
inline
|
||||
@@ -65,6 +68,75 @@ Utils::SmallString fromNativePath(Container container)
|
||||
return path;
|
||||
}
|
||||
|
||||
inline Utils::SmallString getSourceText(const clang::FullSourceLoc &startFullSourceLocation,
|
||||
uint startOffset,
|
||||
uint endOffset)
|
||||
{
|
||||
auto startBuffer = startFullSourceLocation.getBufferData();
|
||||
const auto bufferSize = endOffset - startOffset;
|
||||
|
||||
return Utils::SmallString(startBuffer.data() + startOffset, bufferSize + 1);
|
||||
}
|
||||
|
||||
inline void makePrintable(Utils::SmallString &text)
|
||||
{
|
||||
text.replace("\n", " ");
|
||||
text.replace("\t", " ");
|
||||
|
||||
auto end = std::unique(text.begin(), text.end(), [](char l, char r){
|
||||
return std::isspace(l) && std::isspace(r) && l == r;
|
||||
});
|
||||
text.resize(std::distance(text.begin(), end));
|
||||
}
|
||||
|
||||
inline void appendSourceRangeToSourceRangesContainer(
|
||||
const clang::SourceRange &sourceRange,
|
||||
ClangBackEnd::SourceRangesContainer &sourceRangesContainer,
|
||||
const clang::SourceManager &sourceManager)
|
||||
{
|
||||
clang::FullSourceLoc startFullSourceLocation(sourceRange.getBegin(), sourceManager);
|
||||
clang::FullSourceLoc endFullSourceLocation(sourceRange.getEnd(), sourceManager);
|
||||
if (startFullSourceLocation.isFileID() && endFullSourceLocation.isFileID()) {
|
||||
const auto startDecomposedLoction = startFullSourceLocation.getDecomposedLoc();
|
||||
const auto endDecomposedLoction = endFullSourceLocation.getDecomposedLoc();
|
||||
const auto fileId = startDecomposedLoction.first;
|
||||
const auto startOffset = startDecomposedLoction.second;
|
||||
const auto endOffset = endDecomposedLoction.second;
|
||||
const auto fileEntry = sourceManager.getFileEntryForID(fileId);
|
||||
auto filePath = absolutePath(fileEntry->getName());
|
||||
const auto fileName = llvm::sys::path::filename(filePath);
|
||||
llvm::sys::path::remove_filename(filePath);
|
||||
Utils::SmallString content = getSourceText(startFullSourceLocation,
|
||||
startOffset,
|
||||
endOffset);
|
||||
makePrintable(content);
|
||||
|
||||
sourceRangesContainer.insertFilePath(fileId.getHashValue(),
|
||||
fromNativePath(filePath),
|
||||
fromNativePath(fileName));
|
||||
sourceRangesContainer.insertSourceRange(fileId.getHashValue(),
|
||||
startFullSourceLocation.getSpellingLineNumber(),
|
||||
startFullSourceLocation.getSpellingColumnNumber(),
|
||||
startOffset,
|
||||
endFullSourceLocation.getSpellingLineNumber(),
|
||||
endFullSourceLocation.getSpellingColumnNumber(),
|
||||
endOffset,
|
||||
std::move(content));
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
void appendSourceRangesToSourceRangesContainer(
|
||||
ClangBackEnd::SourceRangesContainer &sourceRangesContainer,
|
||||
const std::vector<clang::SourceRange> &sourceRanges,
|
||||
const clang::SourceManager &sourceManager)
|
||||
{
|
||||
sourceRangesContainer.reserve(sourceRanges.size());
|
||||
|
||||
for (const auto &sourceRange : sourceRanges)
|
||||
appendSourceRangeToSourceRangesContainer(sourceRange, sourceRangesContainer, sourceManager);
|
||||
}
|
||||
|
||||
inline
|
||||
void appendSourceLocationsToSourceLocationsContainer(
|
||||
ClangBackEnd::SourceLocationsContainer &sourceLocationsContainer,
|
||||
@@ -75,10 +147,12 @@ void appendSourceLocationsToSourceLocationsContainer(
|
||||
|
||||
for (const auto &sourceLocation : sourceLocations) {
|
||||
clang::FullSourceLoc fullSourceLocation(sourceLocation, sourceManager);
|
||||
auto fileId = fullSourceLocation.getFileID();
|
||||
auto fileEntry = sourceManager.getFileEntryForID(fileId);
|
||||
const auto decomposedLoction = fullSourceLocation.getDecomposedLoc();
|
||||
const auto fileId = decomposedLoction.first;
|
||||
const auto offset = decomposedLoction.second;
|
||||
const auto fileEntry = sourceManager.getFileEntryForID(fileId);
|
||||
auto filePath = absolutePath(fileEntry->getName());
|
||||
auto fileName = llvm::sys::path::filename(filePath);
|
||||
const auto fileName = llvm::sys::path::filename(filePath);
|
||||
llvm::sys::path::remove_filename(filePath);
|
||||
|
||||
sourceLocationsContainer.insertFilePath(fileId.getHashValue(),
|
||||
@@ -86,8 +160,11 @@ void appendSourceLocationsToSourceLocationsContainer(
|
||||
fromNativePath(fileName));
|
||||
sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(),
|
||||
fullSourceLocation.getSpellingLineNumber(),
|
||||
fullSourceLocation.getSpellingColumnNumber());
|
||||
fullSourceLocation.getSpellingColumnNumber(),
|
||||
offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
||||
Reference in New Issue
Block a user