summaryrefslogtreecommitdiff
path: root/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp
diff options
context:
space:
mode:
authorTim Jenssen <tim.jenssen@qt.io>2016-11-23 13:13:38 +0100
committerTim Jenssen <tim.jenssen@qt.io>2016-11-23 12:16:04 +0000
commit7f757884c5a04484820a97e592afae74beff95a9 (patch)
treed5066d8a24965523b5024ba37d210c74cd68446c /src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp
parent52fc4a4ebdc840cc351a0ed465a6523d5bc53ac2 (diff)
downloadqt-creator-7f757884c5a04484820a97e592afae74beff95a9.tar.gz
Clang: Extend clang query
It's a first step to introduce clang query. Change-Id: I4d001a8883f56066765ce6bc561fa3f49611c0a4 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp')
-rw-r--r--src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp
new file mode 100644
index 0000000000..2a79260349
--- /dev/null
+++ b/src/tools/clangrefactoringbackend/source/sourcerangeextractor.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sourcerangeextractor.h"
+
+#include "sourcelocationsutils.h"
+
+#include <sourcerangescontainer.h>
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+#include <clang/Basic/SourceManager.h>
+#include <clang/Lex/Lexer.h>
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/FileUtilities.h>
+#include <llvm/ADT/SmallVector.h>
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+namespace ClangBackEnd {
+
+SourceRangeExtractor::SourceRangeExtractor(const clang::SourceManager &sourceManager,
+ const clang::LangOptions &languageOptions,
+ SourceRangesContainer &sourceRangesContainer)
+ : sourceManager(sourceManager),
+ languageOptions(languageOptions),
+ sourceRangesContainer(sourceRangesContainer)
+{
+}
+
+const char *SourceRangeExtractor::findStartOfLineInBuffer(llvm::StringRef buffer, uint startOffset)
+{
+ auto beginText = buffer.begin() + startOffset;
+ auto reverseEnd = std::make_reverse_iterator(buffer.begin());
+
+ auto found = std::find_if(std::make_reverse_iterator(beginText),
+ reverseEnd,
+ [] (const char character) {
+ return character == '\n' || character == '\r';
+ });
+
+ if (found != reverseEnd)
+ return found.base();
+
+ return buffer.begin();
+}
+
+const char *SourceRangeExtractor::findEndOfLineInBuffer(llvm::StringRef buffer, uint endOffset)
+{
+ auto beginText = buffer.begin() + endOffset;
+
+ auto found = std::find_if(beginText,
+ buffer.end(),
+ [] (const char character) {
+ return character == '\n' || character == '\r';
+ });
+
+ if (found != buffer.end())
+ return found;
+
+ return buffer.end();
+}
+
+Utils::SmallString SourceRangeExtractor::getExpandedText(llvm::StringRef buffer,
+ uint startOffset,
+ uint endOffset)
+{
+ auto startBuffer = findStartOfLineInBuffer(buffer, startOffset);
+ auto endBuffer = findEndOfLineInBuffer(buffer, endOffset);
+
+ return Utils::SmallString(startBuffer, endBuffer);
+}
+
+const clang::SourceRange SourceRangeExtractor::extendSourceRangeToLastTokenEnd(const clang::SourceRange sourceRange)
+{
+ auto endLocation = sourceRange.getEnd();
+ uint length = clang::Lexer::MeasureTokenLength(sourceManager.getSpellingLoc(endLocation),
+ sourceManager,
+ languageOptions);
+ endLocation = endLocation.getLocWithOffset(length);
+
+ return {sourceRange.getBegin(), endLocation};
+}
+
+void SourceRangeExtractor::insertSourceRange(uint fileHash,
+ Utils::SmallString &&directoryPath,
+ Utils::SmallString &&fileName,
+ const clang::FullSourceLoc &startLocation,
+ uint startOffset,
+ const clang::FullSourceLoc &endLocation,
+ uint endOffset,
+ Utils::SmallString &&lineSnippet)
+{
+ sourceRangesContainer.insertFilePath(fileHash,
+ std::move(directoryPath),
+ std::move(fileName));
+ sourceRangesContainer.insertSourceRange(fileHash,
+ startLocation.getSpellingLineNumber(),
+ startLocation.getSpellingColumnNumber(),
+ startOffset,
+ endLocation.getSpellingLineNumber(),
+ endLocation.getSpellingColumnNumber(),
+ endOffset,
+ std::move(lineSnippet));
+}
+
+void SourceRangeExtractor::addSourceRange(const clang::SourceRange &sourceRange)
+{
+ auto extendedSourceRange = extendSourceRangeToLastTokenEnd(sourceRange);
+
+ clang::FullSourceLoc startSourceLocation(extendedSourceRange.getBegin(), sourceManager);
+ clang::FullSourceLoc endSourceLocation(extendedSourceRange.getEnd(), sourceManager);
+ if (startSourceLocation.isFileID() && endSourceLocation.isFileID()) {
+ const auto startDecomposedLoction = startSourceLocation.getDecomposedLoc();
+ const auto endDecomposedLoction = endSourceLocation.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 lineSnippet = getExpandedText(startSourceLocation.getBufferData(),
+ startOffset,
+ endOffset);
+ insertSourceRange(fileId.getHashValue(),
+ fromNativePath(filePath),
+ {fileName.data(), fileName.size()},
+ startSourceLocation,
+ startOffset,
+ endSourceLocation,
+ endOffset,
+ std::move(lineSnippet));
+
+ }
+}
+
+void SourceRangeExtractor::addSourceRanges(const std::vector<clang::SourceRange> &sourceRanges)
+{
+ sourceRangesContainer.reserve(sourceRanges.size() + sourceRangeWithTextContainers().size());
+
+ for (const clang::SourceRange &sourceRange : sourceRanges)
+ addSourceRange(sourceRange);
+}
+
+const std::vector<SourceRangeWithTextContainer> &SourceRangeExtractor::sourceRangeWithTextContainers() const
+{
+ return sourceRangesContainer.sourceRangeWithTextContainers();
+}
+
+} // namespace ClangBackEnd