Merge remote-tracking branch 'origin/3.6'

Conflicts:
	src/plugins/projectexplorer/toolchainmanager.cpp
	src/plugins/qmlprofiler/qmlprofilerclientmanager.cpp

Change-Id: Id736c6922670c921c689219cb817b1541eaaf304
This commit is contained in:
Oswald Buddenhagen
2015-12-02 18:42:05 +01:00
185 changed files with 2327 additions and 7907 deletions

View File

@@ -1,43 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANG_GLOBAL_H
#define CLANG_GLOBAL_H
#include <qglobal.h>
#if defined(CLANGCODEMODEL_LIBRARY)
# define CLANG_EXPORT Q_DECL_EXPORT
#else
# define CLANG_EXPORT Q_DECL_IMPORT
#endif
#endif // CLANG_GLOBAL_H

View File

@@ -28,9 +28,9 @@
**
****************************************************************************/
#include "activationsequencecontextprocessor.h"
#include "clangactivationsequencecontextprocessor.h"
#include "activationsequenceprocessor.h"
#include "clangactivationsequenceprocessor.h"
#include <cplusplus/BackwardsScanner.h>
#include <cplusplus/ExpressionUnderCursor.h>

View File

@@ -28,7 +28,7 @@
**
****************************************************************************/
#include "activationsequenceprocessor.h"
#include "clangactivationsequenceprocessor.h"
namespace ClangCodeModel {
namespace Internal {

View File

@@ -42,7 +42,7 @@ ClangAssistProposal::ClangAssistProposal(int cursorPos, TextEditor::GenericPropo
bool ClangAssistProposal::isCorrective() const
{
return ClangAssistProposalModel::replaceDotForArrow(model());
return false;
}
void ClangAssistProposal::makeCorrection(TextEditor::TextEditorWidget *editorWidget)

View File

@@ -45,9 +45,6 @@ public:
virtual bool isCorrective() const;
virtual void makeCorrection(TextEditor::TextEditorWidget *editorWidget);
private:
bool m_replaceDotForArrow;
};
} // namespace Internal

View File

@@ -30,7 +30,7 @@
#include "clangassistproposalitem.h"
#include "completionchunkstotextconverter.h"
#include "clangcompletionchunkstotextconverter.h"
#include <cplusplus/MatchingText.h>
#include <cplusplus/Token.h>

View File

@@ -39,13 +39,6 @@
namespace ClangCodeModel {
namespace Internal {
bool ClangAssistProposalModel::replaceDotForArrow(TextEditor::IAssistProposalModel *model)
{
auto clangAssistProposalModel = static_cast<ClangAssistProposalModel*>(model);
return clangAssistProposalModel->m_replaceDotForArrow;
}
bool ClangAssistProposalModel::isSortable(const QString &/*prefix*/) const
{
return true;

View File

@@ -41,21 +41,8 @@ namespace Internal {
class ClangAssistProposalModel : public TextEditor::GenericProposalModel
{
public:
ClangAssistProposalModel()
: m_sortable(false)
, m_completionOperator(CPlusPlus::T_EOF_SYMBOL)
, m_replaceDotForArrow(false)
{}
bool isSortable(const QString &prefix) const override;
void sort(const QString &prefix) override;
static bool replaceDotForArrow(IAssistProposalModel *model);
private:
bool m_sortable;
unsigned m_completionOperator;
bool m_replaceDotForArrow;
};
} // namespace Internal

View File

@@ -34,7 +34,6 @@
#include "clangeditordocumentprocessor.h"
#include "clangmodelmanagersupport.h"
#include "clangutils.h"
#include "pchmanager.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
@@ -48,6 +47,7 @@
#include <texteditor/texteditor.h>
#include <clangbackendipc/diagnosticschangedmessage.h>
#include <clangbackendipc/highlightingchangedmessage.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
@@ -62,11 +62,13 @@
#include <clangbackendipc/cmbmessages.h>
#include <clangbackendipc/registerunsavedfilesforeditormessage.h>
#include <clangbackendipc/requestdiagnosticsmessage.h>
#include <clangbackendipc/requesthighlightingmessage.h>
#include <clangbackendipc/filecontainer.h>
#include <clangbackendipc/projectpartsdonotexistmessage.h>
#include <clangbackendipc/translationunitdoesnotexistmessage.h>
#include <clangbackendipc/unregisterunsavedfilesforeditormessage.h>
#include <clangbackendipc/updatetranslationunitsforeditormessage.h>
#include <clangbackendipc/updatevisibletranslationunitsmessage.h>
#include <cplusplus/Icons.h>
@@ -135,6 +137,11 @@ void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *t
}
}
bool IpcReceiver::isExpectingCodeCompletedMessage() const
{
return !m_assistProcessorsTable.isEmpty();
}
void IpcReceiver::alive()
{
qCDebug(log) << "<<< AliveMessage";
@@ -174,6 +181,24 @@ void IpcReceiver::diagnosticsChanged(const DiagnosticsChangedMessage &message)
}
}
void IpcReceiver::highlightingChanged(const HighlightingChangedMessage &message)
{
qCDebug(log) << "<<< HighlightingChangedMessage with"
<< message.highlightingMarks().size() << "items";
auto processor = ClangEditorDocumentProcessor::get(message.file().filePath());
if (processor && processor->projectPart()) {
const QString highlightingProjectPartId = message.file().projectPartId();
const QString documentProjectPartId = processor->projectPart()->id();
if (highlightingProjectPartId == documentProjectPartId) {
processor->updateHighlighting(message.highlightingMarks(),
message.skippedPreprocessorRanges(),
message.file().documentRevision());
}
}
}
void IpcReceiver::translationUnitDoesNotExist(const TranslationUnitDoesNotExistMessage &message)
{
QTC_CHECK(!"Got TranslationUnitDoesNotExistMessage");
@@ -203,6 +228,8 @@ public:
void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) override;
void completeCode(const ClangBackEnd::CompleteCodeMessage &message) override;
void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) override;
void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) override;
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override;
private:
ClangBackEnd::ConnectionClient &m_connection;
@@ -268,6 +295,18 @@ void IpcSender::requestDiagnostics(const RequestDiagnosticsMessage &message)
m_connection.serverProxy().requestDiagnostics(message);
}
void IpcSender::requestHighlighting(const RequestHighlightingMessage &message)
{
QTC_CHECK(m_connection.isConnected());
m_connection.serverProxy().requestHighlighting(message);
}
void IpcSender::updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message)
{
QTC_CHECK(m_connection.isConnected());
m_connection.serverProxy().updateVisibleTranslationUnits(message);
}
IpcCommunicator::IpcCommunicator()
: m_connection(&m_ipcReceiver)
, m_ipcSender(new IpcSender(m_connection))
@@ -308,10 +347,8 @@ void IpcCommunicator::initializeBackend()
static QStringList projectPartOptions(const CppTools::ProjectPart::Ptr &projectPart)
{
QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
const QStringList options = ClangCodeModel::Utils::createClangOptions(projectPart,
CppTools::ProjectFile::Unclassified); // No language option
if (PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(projectPart))
options += ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName());
return options;
}
@@ -346,6 +383,90 @@ void IpcCommunicator::registerFallbackProjectPart()
registerProjectPartsForEditor({projectPartContainer});
}
namespace {
Utf8String currentCppEditorDocumentFilePath()
{
Utf8String currentCppEditorDocumentFilePath;
const auto currentEditor = Core::EditorManager::currentEditor();
if (currentEditor && CppTools::CppModelManager::isCppEditor(currentEditor)) {
const auto currentDocument = currentEditor->document();
if (currentDocument)
currentCppEditorDocumentFilePath = currentDocument->filePath().toString();
}
return currentCppEditorDocumentFilePath;
}
void removeDuplicates(Utf8StringVector &visibleEditorDocumentsFilePaths)
{
std::sort(visibleEditorDocumentsFilePaths.begin(),
visibleEditorDocumentsFilePaths.end());
const auto end = std::unique(visibleEditorDocumentsFilePaths.begin(),
visibleEditorDocumentsFilePaths.end());
visibleEditorDocumentsFilePaths.erase(end,
visibleEditorDocumentsFilePaths.end());
}
void removeNonCppEditors(QList<Core::IEditor*> &visibleEditors)
{
const auto isNotCppEditor = [] (Core::IEditor *editor) {
return !CppTools::CppModelManager::isCppEditor(editor);
};
const auto end = std::remove_if(visibleEditors.begin(),
visibleEditors.end(),
isNotCppEditor);
visibleEditors.erase(end, visibleEditors.end());
}
Utf8StringVector visibleCppEditorDocumentsFilePaths()
{
auto visibleEditors = Core::EditorManager::visibleEditors();
removeNonCppEditors(visibleEditors);
Utf8StringVector visibleCppEditorDocumentsFilePaths;
visibleCppEditorDocumentsFilePaths.reserve(visibleEditors.size());
const auto editorFilePaths = [] (Core::IEditor *editor) {
return Utf8String(editor->document()->filePath().toString());
};
std::transform(visibleEditors.begin(),
visibleEditors.end(),
std::back_inserter(visibleCppEditorDocumentsFilePaths),
editorFilePaths);
removeDuplicates(visibleCppEditorDocumentsFilePaths);
return visibleCppEditorDocumentsFilePaths;
}
}
void IpcCommunicator::updateTranslationUnitVisiblity()
{
updateTranslationUnitVisiblity(currentCppEditorDocumentFilePath(), visibleCppEditorDocumentsFilePaths());
}
bool IpcCommunicator::isNotWaitingForCompletion() const
{
return !m_ipcReceiver.isExpectingCodeCompletedMessage();
}
void IpcCommunicator::updateTranslationUnitVisiblity(const Utf8String &currentEditorFilePath,
const Utf8StringVector &visibleEditorsFilePaths)
{
if (m_sendMode == IgnoreSendRequests)
return;
const UpdateVisibleTranslationUnitsMessage message(currentEditorFilePath, visibleEditorsFilePaths);
qCDebug(log) << ">>>" << message;
m_ipcSender->updateVisibleTranslationUnits(message);
}
void IpcCommunicator::registerCurrentProjectParts()
{
using namespace CppTools;
@@ -355,15 +476,24 @@ void IpcCommunicator::registerCurrentProjectParts()
registerProjectsParts(projectInfo.projectParts());
}
void IpcCommunicator::registerCurrentCppEditorDocuments()
void IpcCommunicator::restoreCppEditorDocuments()
{
resetCppEditorDocumentProcessors();
registerVisibleCppEditorDocumentAndMarkInvisibleDirty();
}
void IpcCommunicator::resetCppEditorDocumentProcessors()
{
using namespace CppTools;
const auto cppEditorDocuments = CppModelManager::instance()->cppEditorDocuments();
foreach (const CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments) {
if (cppEditorDocument->processor()->baseTextDocument()->isModified())
updateTranslationUnitFromCppEditorDocument(cppEditorDocument->filePath());
}
foreach (CppEditorDocumentHandle *cppEditorDocument, cppEditorDocuments)
cppEditorDocument->resetProcessor();
}
void IpcCommunicator::registerVisibleCppEditorDocumentAndMarkInvisibleDirty()
{
CppTools::CppModelManager::instance()->updateCppEditorDocuments();
}
void IpcCommunicator::registerCurrentCodeModelUiHeaders()
@@ -401,12 +531,13 @@ CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath)
return CppTools::CppModelManager::instance()->cppEditorDocument(filePath);
}
bool documentHasChanged(const QString &filePath)
bool documentHasChanged(const QString &filePath,
uint revision)
{
auto *document = cppDocument(filePath);
if (document)
return document->sendTracker().shouldSendRevision(document->revision());
return document->sendTracker().shouldSendRevision(revision);
return true;
}
@@ -446,33 +577,42 @@ void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArra
documentRevision}});
}
void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer)
void IpcCommunicator::updateTranslationUnitWithRevisionCheck(const FileContainer &fileContainer)
{
if (m_sendMode == IgnoreSendRequests)
return;
if (documentHasChanged(fileContainer.filePath())) {
if (documentHasChanged(fileContainer.filePath(), fileContainer.documentRevision())) {
updateTranslationUnitsForEditor({fileContainer});
const RequestDiagnosticsMessage message(fileContainer);
qCDebug(log) << ">>>" << message;
m_ipcSender->requestDiagnostics(message);
setLastSentDocumentRevision(fileContainer.filePath(),
fileContainer.documentRevision());
}
}
void IpcCommunicator::requestDiagnostics(Core::IDocument *document)
void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer)
{
const RequestDiagnosticsMessage message(fileContainer);
qCDebug(log) << ">>>" << message;
m_ipcSender->requestDiagnostics(message);
}
void IpcCommunicator::requestHighlighting(const FileContainer &fileContainer)
{
const RequestHighlightingMessage message(fileContainer);
qCDebug(log) << ">>>" << message;
m_ipcSender->requestHighlighting(message);
}
void IpcCommunicator::updateTranslationUnitWithRevisionCheck(Core::IDocument *document)
{
const auto textDocument = qobject_cast<TextDocument*>(document);
const auto filePath = textDocument->filePath().toString();
const QString projectPartId = Utils::projectPartIdForFile(filePath);
requestDiagnostics(FileContainer(filePath,
projectPartId,
Utf8StringVector(),
textDocument->document()->revision()));
updateTranslationUnitWithRevisionCheck(FileContainer(filePath,
projectPartId,
Utf8StringVector(),
textDocument->document()->revision()));
}
void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position)
@@ -526,8 +666,9 @@ void IpcCommunicator::initializeBackendWithCurrentData()
{
registerFallbackProjectPart();
registerCurrentProjectParts();
registerCurrentCppEditorDocuments();
registerCurrentCodeModelUiHeaders();
restoreCppEditorDocuments();
updateTranslationUnitVisiblity();
emit backendReinitialized();
}
@@ -549,7 +690,9 @@ void IpcCommunicator::registerTranslationUnitsForEditor(const FileContainers &fi
if (m_sendMode == IgnoreSendRequests)
return;
const RegisterTranslationUnitForEditorMessage message(fileContainers);
const RegisterTranslationUnitForEditorMessage message(fileContainers,
currentCppEditorDocumentFilePath(),
visibleCppEditorDocumentsFilePaths());
qCDebug(log) << ">>>" << message;
m_ipcSender->registerTranslationUnitsForEditor(message);
}

View File

@@ -76,11 +76,14 @@ public:
void deleteAndClearWaitingAssistProcessors();
void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget);
bool isExpectingCodeCompletedMessage() const;
private:
void alive() override;
void echo(const ClangBackEnd::EchoMessage &message) override;
void codeCompleted(const ClangBackEnd::CodeCompletedMessage &message) override;
void diagnosticsChanged(const ClangBackEnd::DiagnosticsChangedMessage &message) override;
void highlightingChanged(const ClangBackEnd::HighlightingChangedMessage &message) override;
void translationUnitDoesNotExist(const ClangBackEnd::TranslationUnitDoesNotExistMessage &message) override;
void projectPartsDoNotExist(const ClangBackEnd::ProjectPartsDoNotExistMessage &message) override;
@@ -105,6 +108,8 @@ public:
virtual void unregisterUnsavedFilesForEditor(const ClangBackEnd::UnregisterUnsavedFilesForEditorMessage &message) = 0;
virtual void completeCode(const ClangBackEnd::CompleteCodeMessage &message) = 0;
virtual void requestDiagnostics(const ClangBackEnd::RequestDiagnosticsMessage &message) = 0;
virtual void requestHighlighting(const ClangBackEnd::RequestHighlightingMessage &message) = 0;
virtual void updateVisibleTranslationUnits(const ClangBackEnd::UpdateVisibleTranslationUnitsMessage &message) = 0;
};
class IpcCommunicator : public QObject
@@ -126,6 +131,8 @@ public:
void unregisterProjectPartsForEditor(const QStringList &projectPartIds);
void registerUnsavedFilesForEditor(const FileContainers &fileContainers);
void unregisterUnsavedFilesForEditor(const FileContainers &fileContainers);
void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer);
void requestHighlighting(const ClangBackEnd::FileContainer &fileContainer);
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
quint32 line,
quint32 column,
@@ -140,11 +147,14 @@ public:
void updateUnsavedFileFromCppEditorDocument(const QString &filePath);
void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision);
void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision);
void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer);
void requestDiagnostics(Core::IDocument *document);
void updateTranslationUnitWithRevisionCheck(const ClangBackEnd::FileContainer &fileContainer);
void updateTranslationUnitWithRevisionCheck(Core::IDocument *document);
void updateChangeContentStartPosition(const QString &filePath, int position);
void registerFallbackProjectPart();
void updateTranslationUnitVisiblity();
bool isNotWaitingForCompletion() const;
public: // for tests
IpcSenderInterface *setIpcSender(IpcSenderInterface *ipcSender);
@@ -159,13 +169,19 @@ private:
void initializeBackend();
void initializeBackendWithCurrentData();
void registerCurrentProjectParts();
void registerCurrentCppEditorDocuments();
void restoreCppEditorDocuments();
void resetCppEditorDocumentProcessors();
void registerVisibleCppEditorDocumentAndMarkInvisibleDirty();
void registerCurrentCodeModelUiHeaders();
void onBackendRestarted();
void onEditorAboutToClose(Core::IEditor *editor);
void onCoreAboutToClose();
void updateTranslationUnitVisiblity(const Utf8String &currentEditorFilePath,
const Utf8StringVector &visibleEditorsFilePaths);
private:
IpcReceiver m_ipcReceiver;
ClangBackEnd::ConnectionClient m_connection;

View File

@@ -1,19 +1,13 @@
include(../../qtcreatorplugin.pri)
include(../../shared/clang/clang_installation.pri)
LIBS += $$LLVM_LIBS
INCLUDEPATH += $$LLVM_INCLUDEPATH
DEFINES += CLANGCODEMODEL_LIBRARY
# The following defines are used to determine the clang include path for intrinsics
# The following defines are used to determine the clang include path for intrinsics.
DEFINES += CLANG_VERSION=\\\"$${LLVM_VERSION}\\\"
DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/include\\\"\""
unix:QMAKE_LFLAGS += -Wl,-rpath,\'$$LLVM_LIBDIR\'
SOURCES += \
activationsequencecontextprocessor.cpp \
activationsequenceprocessor.cpp \
clangactivationsequencecontextprocessor.cpp \
clangactivationsequenceprocessor.cpp \
clangassistproposal.cpp \
clangassistproposalitem.cpp \
clangassistproposalmodel.cpp \
@@ -22,6 +16,7 @@ SOURCES += \
clangcompletionassistinterface.cpp \
clangcompletionassistprocessor.cpp \
clangcompletionassistprovider.cpp \
clangcompletionchunkstotextconverter.cpp \
clangcompletioncontextanalyzer.cpp \
clangdiagnosticfilter.cpp \
clangdiagnosticmanager.cpp \
@@ -30,32 +25,16 @@ SOURCES += \
clangfixitoperation.cpp \
clangfixitoperationsextractor.cpp \
clangfunctionhintmodel.cpp \
clanghighlightingmarksreporter.cpp \
clangmodelmanagersupport.cpp \
clangprojectsettings.cpp \
clangprojectsettingspropertiespage.cpp \
clangtextmark.cpp \
clangutils.cpp \
completionchunkstotextconverter.cpp \
cppcreatemarkers.cpp \
cxprettyprinter.cpp \
diagnostic.cpp \
fastindexer.cpp \
pchinfo.cpp \
pchmanager.cpp \
raii/scopedclangoptions.cpp \
semanticmarker.cpp \
sourcelocation.cpp \
sourcemarker.cpp \
symbol.cpp \
unit.cpp \
unsavedfiledata.cpp \
utils.cpp \
utils_p.cpp
clangutils.cpp
HEADERS += \
activationsequencecontextprocessor.h \
activationsequenceprocessor.h \
clangactivationsequencecontextprocessor.h \
clangactivationsequenceprocessor.h \
clangassistproposal.h \
clangassistproposalitem.h \
clangassistproposalmodel.h \
@@ -64,7 +43,9 @@ HEADERS += \
clangcompletionassistinterface.h \
clangcompletionassistprocessor.h \
clangcompletionassistprovider.h \
clangcompletionchunkstotextconverter.h \
clangcompletioncontextanalyzer.h \
clangconstants.h \
clangdiagnosticfilter.h \
clangdiagnosticmanager.h \
clangeditordocumentparser.h \
@@ -72,45 +53,12 @@ HEADERS += \
clangfixitoperation.h \
clangfixitoperationsextractor.h \
clangfunctionhintmodel.h \
clang_global.h \
clanghighlightingmarksreporter.h \
clangmodelmanagersupport.h \
clangprojectsettings.h \
clangprojectsettingspropertiespage.h \
clangtextmark.h \
clangutils.h \
completionchunkstotextconverter.h \
constants.h \
cppcreatemarkers.h \
cxprettyprinter.h \
cxraii.h \
diagnostic.h \
fastindexer.h \
pchinfo.h \
pchmanager.h \
raii/scopedclangoptions.h \
semanticmarker.h \
sourcelocation.h \
sourcemarker.h \
symbol.h \
unit.h \
unsavedfiledata.h \
utils.h \
utils_p.h
contains(DEFINES, CLANG_INDEXING) {
HEADERS += \
clangindexer.h \
index.h \
indexer.h
# dependencygraph.h \
SOURCES += \
clangindexer.cpp \
index.cpp \
indexer.cpp
# dependencygraph.cpp \
}
FORMS += clangprojectsettingspropertiespage.ui

View File

@@ -20,84 +20,75 @@ QtcPlugin {
"QmakeProjectManager",
]
property bool clangCompletion: true
property bool clangHighlighting: true
property bool clangIndexing: false
property string llvmConfig: Clang.llvmConfig(qbs, QtcFunctions, QtcProcessOutputReader)
property string llvmIncludeDir: Clang.includeDir(llvmConfig, QtcProcessOutputReader)
property string llvmLibDir: Clang.libDir(llvmConfig, QtcProcessOutputReader)
property string llvmLibs: Clang.libraries(qbs.targetOS)
property string llvmVersion: Clang.version(llvmConfig, QtcProcessOutputReader)
condition: llvmConfig && File.exists(llvmIncludeDir.concat("/clang-c/Index.h"))
cpp.includePaths: base.concat(llvmIncludeDir)
cpp.libraryPaths: base.concat(llvmLibDir)
cpp.rpaths: cpp.libraryPaths
cpp.dynamicLibraries: base.concat(llvmLibs)
cpp.defines: {
var defines = base;
// The following defines are used to determine the clang include path for intrinsics.
defines.push('CLANG_VERSION="' + llvmVersion + '"');
defines.push('CLANG_RESOURCE_DIR="' + llvmLibDir + '/clang/' + llvmVersion + '/include"');
if (clangCompletion)
defines.push("CLANG_COMPLETION");
if (clangHighlighting)
defines.push("CLANG_HIGHLIGHTING");
if (clangIndexing)
defines.push("CLANG_INDEXING");
return defines;
}
Group {
name: "Completion support"
condition: product.clangCompletion
files: [
"activationsequencecontextprocessor.cpp",
"activationsequencecontextprocessor.h",
"activationsequenceprocessor.cpp",
"activationsequenceprocessor.h",
"clangassistproposal.cpp",
"clangassistproposal.h",
"clangassistproposalitem.cpp",
"clangassistproposalitem.h",
"clangassistproposalmodel.cpp",
"clangassistproposalmodel.h",
"clangcompletionassistinterface.cpp",
"clangcompletionassistinterface.h",
"clangcompletionassistprocessor.cpp",
"clangcompletionassistprocessor.h",
"clangcompletionassistprovider.cpp",
"clangcompletionassistprovider.h",
"clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h",
]
}
Group {
name: "Highlighting support"
condition: product.clangHighlighting
files: [
"cppcreatemarkers.cpp",
"cppcreatemarkers.h",
]
}
Group {
name: "Indexing support"
condition: product.clangIndexing
files: [
"clangindexer.cpp",
"clangindexer.h",
"index.cpp",
"index.h",
"indexer.cpp",
"indexer.h",
// "dependencygraph.h",
// "dependencygraph.cpp"
]
}
files: [
"clangactivationsequencecontextprocessor.cpp",
"clangactivationsequencecontextprocessor.h",
"clangactivationsequenceprocessor.cpp",
"clangactivationsequenceprocessor.h",
"clangassistproposal.cpp",
"clangassistproposal.h",
"clangassistproposalitem.cpp",
"clangassistproposalitem.h",
"clangassistproposalmodel.cpp",
"clangassistproposalmodel.h",
"clangbackendipcintegration.cpp",
"clangbackendipcintegration.h",
"clangcodemodelplugin.cpp",
"clangcodemodelplugin.h",
"clangcompletionassistinterface.cpp",
"clangcompletionassistinterface.h",
"clangcompletionassistprocessor.cpp",
"clangcompletionassistprocessor.h",
"clangcompletionassistprovider.cpp",
"clangcompletionassistprovider.h",
"clangcompletionchunkstotextconverter.cpp",
"clangcompletionchunkstotextconverter.h",
"clangcompletioncontextanalyzer.cpp",
"clangcompletioncontextanalyzer.h",
"clangconstants.h",
"clangdiagnosticfilter.cpp",
"clangdiagnosticfilter.h",
"clangdiagnosticmanager.cpp",
"clangdiagnosticmanager.h",
"clangeditordocumentparser.cpp",
"clangeditordocumentparser.h",
"clangeditordocumentprocessor.cpp",
"clangeditordocumentprocessor.h",
"clangfixitoperation.cpp",
"clangfixitoperation.h",
"clangfixitoperationsextractor.cpp",
"clangfixitoperationsextractor.h",
"clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h",
"clanghighlightingmarksreporter.cpp",
"clanghighlightingmarksreporter.h",
"clangmodelmanagersupport.cpp",
"clangmodelmanagersupport.h",
"clangprojectsettings.cpp",
"clangprojectsettings.h",
"clangprojectsettingspropertiespage.cpp",
"clangprojectsettingspropertiespage.h",
"clangprojectsettingspropertiespage.ui",
"clangtextmark.cpp",
"clangtextmark.h",
"clangutils.cpp",
"clangutils.h",
]
Group {
name: "Tests"
@@ -117,69 +108,4 @@ QtcPlugin {
files: [ "*" ]
excludeFiles: "clangtestdata.qrc"
}
files: [
"clang_global.h",
"clangcompletioncontextanalyzer.cpp",
"clangcompletioncontextanalyzer.h",
"clangeditordocumentparser.cpp",
"clangeditordocumentparser.h",
"clangeditordocumentprocessor.cpp",
"clangeditordocumentprocessor.h",
"clangdiagnosticfilter.cpp",
"clangdiagnosticfilter.h",
"clangdiagnosticmanager.cpp",
"clangdiagnosticmanager.h",
"clangfixitoperation.cpp",
"clangfixitoperation.h",
"clangfixitoperationsextractor.cpp",
"clangfixitoperationsextractor.h",
"clangmodelmanagersupport.cpp",
"clangmodelmanagersupport.h",
"clangcodemodelplugin.cpp",
"clangcodemodelplugin.h",
"clangprojectsettings.cpp",
"clangprojectsettings.h",
"clangprojectsettingspropertiespage.cpp",
"clangprojectsettingspropertiespage.h",
"clangprojectsettingspropertiespage.ui",
"clangtextmark.cpp",
"clangtextmark.h",
"clangutils.cpp",
"clangutils.h",
"clangbackendipcintegration.cpp",
"clangbackendipcintegration.h",
"completionchunkstotextconverter.cpp",
"completionchunkstotextconverter.h",
"constants.h",
"cxprettyprinter.cpp",
"cxprettyprinter.h",
"cxraii.h",
"diagnostic.cpp",
"diagnostic.h",
"fastindexer.cpp",
"fastindexer.h",
"pchinfo.cpp",
"pchinfo.h",
"pchmanager.cpp",
"pchmanager.h",
"semanticmarker.cpp",
"semanticmarker.h",
"sourcelocation.cpp",
"sourcelocation.h",
"sourcemarker.cpp",
"sourcemarker.h",
"symbol.cpp",
"symbol.h",
"unit.cpp",
"unit.h",
"unsavedfiledata.cpp",
"unsavedfiledata.h",
"utils.cpp",
"utils.h",
"utils_p.cpp",
"utils_p.h",
"raii/scopedclangoptions.cpp",
"raii/scopedclangoptions.h",
]
}

View File

@@ -30,10 +30,8 @@
#include "clangcodemodelplugin.h"
#include "clangconstants.h"
#include "clangprojectsettingspropertiespage.h"
#include "constants.h"
#include "pchmanager.h"
#include "utils.h"
#ifdef WITH_TESTS
# include "test/clangcodecompletion_test.h"
@@ -50,7 +48,9 @@
namespace ClangCodeModel {
namespace Internal {
static void initializeTextMarks()
namespace {
void initializeTextMarks()
{
TextEditor::TextMark::setCategoryColor(Core::Id(Constants::CLANG_WARNING),
Utils::Theme::ClangCodeModel_Warning_TextMarkColor);
@@ -58,10 +58,7 @@ static void initializeTextMarks()
Utils::Theme::ClangCodeModel_Error_TextMarkColor);
}
ClangCodeModelPlugin::ClangCodeModelPlugin()
{
qRegisterMetaType<CppTools::ProjectPart::Ptr>();
}
} // anonymous namespace
bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
@@ -75,25 +72,8 @@ bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *err
panelFactory->setSimpleCreateWidgetFunction<ClangProjectSettingsWidget>(QIcon());
ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory);
// Initialize Clang
ClangCodeModel::Internal::initializeClang();
// Set up Indexer
auto cppModelManager = CppTools::CppModelManager::instance();
#ifdef CLANG_INDEXING
m_indexer.reset(new ClangIndexer);
cppModelManager->setIndexingSupport(m_indexer->indexingSupport());
#endif // CLANG_INDEXING
// Set up PchManager
PchManager *pchManager = new PchManager(this);
ProjectExplorer::SessionManager *sessionManager = ProjectExplorer::SessionManager::instance();
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
pchManager, &PchManager::onAboutToRemoveProject);
connect(cppModelManager, &CppTools::CppModelManager::projectPartsUpdated,
pchManager, &PchManager::onProjectPartsUpdated);
// Register ModelManagerSupportProvider
auto cppModelManager = CppTools::CppModelManager::instance();
cppModelManager->setClangModelManagerSupportProvider(&m_modelManagerSupportProvider);
initializeTextMarks();

View File

@@ -33,14 +33,8 @@
#include "clangmodelmanagersupport.h"
#ifdef CLANG_INDEXING
# include "clangindexer.h"
#endif // CLANG_INDEXING
#include <extensionsystem/iplugin.h>
#include <QScopedPointer>
namespace ClangCodeModel {
namespace Internal {
@@ -50,16 +44,11 @@ class ClangCodeModelPlugin: public ExtensionSystem::IPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ClangCodeModel.json")
public:
ClangCodeModelPlugin();
bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized();
private:
ModelManagerSupportProviderClang m_modelManagerSupportProvider;
#ifdef CLANG_INDEXING
QScopedPointer<ClangIndexer> m_indexer;
#endif // CLANG_INDEXING
#ifdef WITH_TESTS
QList<QObject *> createTestObjects() const;

View File

@@ -1,15 +1,19 @@
INCLUDEPATH += $$PWD
SOURCES += $$PWD/completionchunkstotextconverter.cpp \
$$PWD/activationsequenceprocessor.cpp \
$$PWD/activationsequencecontextprocessor.cpp \
$$PWD/clangcompletioncontextanalyzer.cpp \
$$PWD/clangdiagnosticfilter.cpp \
$$PWD/clangfixitoperation.cpp
SOURCES += \
$$PWD/clangactivationsequencecontextprocessor.cpp \
$$PWD/clangactivationsequenceprocessor.cpp \
$$PWD/clangcompletionchunkstotextconverter.cpp \
$$PWD/clangcompletioncontextanalyzer.cpp \
$$PWD/clangdiagnosticfilter.cpp \
$$PWD/clangfixitoperation.cpp \
$$PWD/clanghighlightingmarksreporter.cpp
HEADERS += $$PWD/completionchunkstotextconverter.h \
$$PWD/activationsequenceprocessor.h \
$$PWD/activationsequencecontextprocessor.h \
$$PWD/clangcompletioncontextanalyzer.h \
$$PWD/clangdiagnosticfilter.h \
$$PWD/clangfixitoperation.h
HEADERS += \
$$PWD/clangactivationsequencecontextprocessor.h \
$$PWD/clangactivationsequenceprocessor.h \
$$PWD/clangcompletionchunkstotextconverter.h \
$$PWD/clangcompletioncontextanalyzer.h \
$$PWD/clangdiagnosticfilter.h \
$$PWD/clangfixitoperation.h \
$$PWD/clanghighlightingmarksreporter.h

View File

@@ -32,14 +32,10 @@
#include "clangutils.h"
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsreuse.h>
#include <cpptools/cppworkingcopy.h>
#include <texteditor/texteditor.h>
#include <cplusplus/Token.h>
namespace ClangCodeModel {
namespace Internal {
@@ -50,18 +46,13 @@ ClangCompletionAssistInterface::ClangCompletionAssistInterface(
const QString &fileName,
TextEditor::AssistReason reason,
const CppTools::ProjectPart::HeaderPaths &headerPaths,
const PchInfo::Ptr &pchInfo,
const CPlusPlus::LanguageFeatures &features)
: AssistInterface(textEditorWidget->document(), position, fileName, reason)
, m_ipcCommunicator(ipcCommunicator)
, m_headerPaths(headerPaths)
, m_savedPchPointer(pchInfo)
, m_languageFeatures(features)
, m_textEditorWidget(textEditorWidget)
{
m_unsavedFiles = Utils::createUnsavedFiles(
CppTools::CppModelManager::instance()->workingCopy(),
CppTools::modifiedFiles());
}
bool ClangCompletionAssistInterface::objcEnabled() const
@@ -94,11 +85,6 @@ IpcCommunicator &ClangCompletionAssistInterface::ipcCommunicator() const
return m_ipcCommunicator;
}
const UnsavedFiles &ClangCompletionAssistInterface::unsavedFiles() const
{
return m_unsavedFiles;
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -32,8 +32,7 @@
#define CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTINTERFACE_H
#include "clangbackendipcintegration.h"
#include "pchinfo.h"
#include "utils.h"
#include "clangutils.h"
#include <cpptools/cppcompletionassistprovider.h>
@@ -51,11 +50,9 @@ public:
const QString &fileName,
TextEditor::AssistReason reason,
const CppTools::ProjectPart::HeaderPaths &headerPaths,
const PchInfo::Ptr &pchInfo,
const CPlusPlus::LanguageFeatures &features);
IpcCommunicator &ipcCommunicator() const;
const UnsavedFiles &unsavedFiles() const;
bool objcEnabled() const;
const CppTools::ProjectPart::HeaderPaths &headerPaths() const;
CPlusPlus::LanguageFeatures languageFeatures() const;
@@ -65,10 +62,8 @@ public:
private:
IpcCommunicator &m_ipcCommunicator;
UnsavedFiles m_unsavedFiles;
QStringList m_options;
CppTools::ProjectPart::HeaderPaths m_headerPaths;
Internal::PchInfo::Ptr m_savedPchPointer;
CPlusPlus::LanguageFeatures m_languageFeatures;
const TextEditor::TextEditorWidget *m_textEditorWidget;
};

View File

@@ -30,7 +30,7 @@
#include "clangassistproposalitem.h"
#include "activationsequenceprocessor.h"
#include "clangactivationsequenceprocessor.h"
#include "clangassistproposal.h"
#include "clangassistproposalmodel.h"
#include "clangcompletionassistprocessor.h"
@@ -38,7 +38,7 @@
#include "clangeditordocumentprocessor.h"
#include "clangfunctionhintmodel.h"
#include "clangutils.h"
#include "completionchunkstotextconverter.h"
#include "clangcompletionchunkstotextconverter.h"
#include <utils/qtcassert.h>
@@ -342,13 +342,16 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
case ClangCompletionContextAnalyzer::PassThroughToLibClang: {
m_addSnippets = m_completionOperator == T_EOF_SYMBOL;
m_sentRequestType = NormalCompletion;
sendCompletionRequest(analyzer.positionForClang(), modifiedFileContent);
const bool requestSent = sendCompletionRequest(analyzer.positionForClang(),
modifiedFileContent);
setPerformWasApplicable(requestSent);
break;
}
case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: {
m_sentRequestType = FunctionHintCompletion;
m_functionName = analyzer.functionName();
sendCompletionRequest(analyzer.positionForClang(), QByteArray());
const bool requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray());
setPerformWasApplicable(requestSent);
break;
}
default:
@@ -702,15 +705,34 @@ bool shouldSendDocumentForCompletion(const QString &filePath,
return true;
}
void setLastCompletionPositionAndDocumentRevision(const QString &filePath,
int completionPosition)
bool shouldSendCodeCompletion(const QString &filePath,
int completionPosition)
{
auto *document = cppDocument(filePath);
if (document) {
document->sendTracker().setLastCompletionPosition(completionPosition);
document->sendTracker().setLastSentRevision(document->revision());
auto &sendTracker = document->sendTracker();
return sendTracker.shouldSendCompletion(completionPosition);
}
return true;
}
void setLastDocumentRevision(const QString &filePath)
{
auto *document = cppDocument(filePath);
if (document)
document->sendTracker().setLastSentRevision(int(document->revision()));
}
void setLastCompletionPosition(const QString &filePath,
int completionPosition)
{
auto *document = cppDocument(filePath);
if (document)
document->sendTracker().setLastCompletionPosition(completionPosition);
}
QString projectPartIdForEditorDocument(const QString &filePath)
@@ -726,7 +748,7 @@ QString projectPartIdForEditorDocument(const QString &filePath)
}
}
void ClangCompletionAssistProcessor::sendCompletionRequest(int position,
bool ClangCompletionAssistProcessor::sendCompletionRequest(int position,
const QByteArray &customFileContent)
{
int line, column;
@@ -735,17 +757,22 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position,
const QString filePath = m_interface->fileName();
if (shouldSendDocumentForCompletion(filePath, position)) {
sendFileContent(customFileContent);
setLastCompletionPositionAndDocumentRevision(filePath, position);
auto &ipcCommunicator = m_interface->ipcCommunicator();
if (shouldSendCodeCompletion(filePath, position)
|| ipcCommunicator.isNotWaitingForCompletion()) {
if (shouldSendDocumentForCompletion(filePath, position)) {
sendFileContent(customFileContent);
setLastDocumentRevision(filePath);
}
const QString projectPartId = projectPartIdForEditorDocument(filePath);
ipcCommunicator.completeCode(this, filePath, uint(line), uint(column), projectPartId);
setLastCompletionPosition(filePath, position);
return true;
}
const QString projectPartId = projectPartIdForEditorDocument(filePath);
m_interface->ipcCommunicator().completeCode(this,
filePath,
uint(line),
uint(column),
projectPartId);
return false;
}
TextEditor::IAssistProposal *ClangCompletionAssistProcessor::createProposal() const

View File

@@ -84,7 +84,7 @@ private:
UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const;
void sendFileContent(const QByteArray &customFileContent);
void sendCompletionRequest(int position, const QByteArray &customFileContent);
bool sendCompletionRequest(int position, const QByteArray &customFileContent);
void handleAvailableCompletions(const CodeCompletions &completions);
bool handleAvailableFunctionHintCompletions(const CodeCompletions &completions);

View File

@@ -33,7 +33,6 @@
#include "clangcompletionassistprocessor.h"
#include "clangeditordocumentprocessor.h"
#include "clangutils.h"
#include "pchmanager.h"
#include <cplusplus/Token.h>
#include <cpptools/cppcompletionassistprocessor.h>
@@ -73,14 +72,12 @@ TextEditor::AssistInterface *ClangCompletionAssistProvider::createAssistInterfac
{
const CppTools::ProjectPart::Ptr projectPart = Utils::projectPartForFileBasedOnProcessor(filePath);
if (projectPart) {
const PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(projectPart);
return new ClangCompletionAssistInterface(m_ipcCommunicator,
textEditorWidget,
position,
filePath,
reason,
projectPart->headerPaths,
pchInfo,
projectPart->languageFeatures);
}

View File

@@ -28,7 +28,7 @@
**
****************************************************************************/
#include "completionchunkstotextconverter.h"
#include "clangcompletionchunkstotextconverter.h"
#include <algorithm>
#include <functional>

View File

@@ -31,8 +31,8 @@
#include "clangcompletioncontextanalyzer.h"
#include "activationsequenceprocessor.h"
#include "activationsequencecontextprocessor.h"
#include "clangactivationsequencecontextprocessor.h"
#include "clangactivationsequenceprocessor.h"
#include <texteditor/codeassist/assistinterface.h>

View File

@@ -28,23 +28,17 @@
**
****************************************************************************/
#ifndef FASTINDEXER_H
#define FASTINDEXER_H
#include "unit.h"
#ifndef CLANGCONSTANTS_H
#define CLANGCONSTANTS_H
namespace ClangCodeModel {
namespace Internal {
namespace Constants {
class FastIndexer
{
public:
virtual ~FastIndexer() = 0;
const char CLANG_MODELMANAGERSUPPORT_ID[] = "ClangCodeModel.ClangCodeModel";
const char CLANG_ERROR[] = "Clang.Error";
const char CLANG_WARNING[] = "Clang.Warning";
virtual void indexNow(Unit::Ptr unit) = 0;
};
} // namespace Constants
} // namespace ClangCodeModel
} // Internal namespace
} // ClangCodeModel namespace
#endif // FASTINDEXER_H
#endif // CLANGCONSTANTS_H

View File

@@ -31,7 +31,9 @@
#include "clangdiagnosticfilter.h"
#include "clangdiagnosticmanager.h"
#include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
@@ -53,7 +55,7 @@ QTextEdit::ExtraSelection createExtraSelections(const QTextCharFormat &mainforma
void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
QTextDocument *textDocument,
const QTextCharFormat &rangeFormat,
const QTextCharFormat &contextFormat,
const QString &diagnosticText,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
@@ -62,7 +64,7 @@ void addRangeSelections(const ClangBackEnd::DiagnosticContainer &diagnostic,
cursor.setPosition(int(range.start().offset()));
cursor.setPosition(int(range.end().offset()), QTextCursor::KeepAnchor);
auto extraSelection = createExtraSelections(rangeFormat, cursor, diagnosticText);
auto extraSelection = createExtraSelections(contextFormat, cursor, diagnosticText);
extraSelections.push_back(std::move(extraSelection));
}
@@ -116,7 +118,7 @@ QString diagnosticText(const ClangBackEnd::DiagnosticContainer &diagnostic)
void addSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
QTextDocument *textDocument,
const QTextCharFormat &mainFormat,
const QTextCharFormat &rangeFormat,
const QTextCharFormat &contextFormat,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
for (auto &&diagnostic : diagnostics) {
@@ -125,7 +127,7 @@ void addSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics
auto text = diagnosticText(diagnostic);
auto extraSelection = createExtraSelections(mainFormat, cursor, text);
addRangeSelections(diagnostic, textDocument, rangeFormat, text, extraSelections);
addRangeSelections(diagnostic, textDocument, contextFormat, text, extraSelections);
extraSelections.push_back(std::move(extraSelection));
}
@@ -135,30 +137,25 @@ void addWarningSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diag
QTextDocument *textDocument,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
QTextCharFormat warningFormat;
warningFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
warningFormat.setUnderlineColor(QColor(180, 180, 0, 255));
const auto fontSettings = TextEditor::TextEditorSettings::instance()->fontSettings();
QTextCharFormat warningRangeFormat;
warningRangeFormat.setUnderlineStyle(QTextCharFormat::DotLine);
warningRangeFormat.setUnderlineColor(QColor(180, 180, 0, 255));
QTextCharFormat warningFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING);
addSelections(diagnostics, textDocument, warningFormat, warningRangeFormat, extraSelections);
QTextCharFormat warningContextFormat = fontSettings.toTextCharFormat(TextEditor::C_WARNING_CONTEXT);
addSelections(diagnostics, textDocument, warningFormat, warningContextFormat, extraSelections);
}
void addErrorSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
QTextDocument *textDocument,
QList<QTextEdit::ExtraSelection> &extraSelections)
{
QTextCharFormat errorFormat;
errorFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline);
errorFormat.setUnderlineColor(QColor(255, 0, 0, 255));
const auto fontSettings = TextEditor::TextEditorSettings::instance()->fontSettings();
QTextCharFormat errorRangeFormat;
errorRangeFormat.setUnderlineStyle(QTextCharFormat::DotLine);
errorRangeFormat.setUnderlineColor(QColor(255, 0, 0, 255));
QTextCharFormat errorFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR);
QTextCharFormat errorContextFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR_CONTEXT);
addSelections(diagnostics, textDocument, errorFormat, errorRangeFormat, extraSelections);
addSelections(diagnostics, textDocument, errorFormat, errorContextFormat, extraSelections);
}
} // anonymous

View File

@@ -29,111 +29,22 @@
****************************************************************************/
#include "clangeditordocumentparser.h"
#include "clangutils.h"
#include "pchinfo.h"
#include "pchmanager.h"
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cppprojects.h>
#include <cpptools/cppworkingcopy.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <QLoggingCategory>
static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.clangeditordocumentparser")
namespace {
QStringList createOptions(const QString &filePath,
const CppTools::ProjectPart::Ptr &part,
bool includeSpellCheck = false)
{
using namespace ClangCodeModel;
QStringList options;
if (part.isNull())
return options;
if (includeSpellCheck)
options += QLatin1String("-fspell-checking");
options += ClangCodeModel::Utils::createClangOptions(part, filePath);
if (Internal::PchInfo::Ptr pchInfo = Internal::PchManager::instance()->pchInfo(part))
options.append(ClangCodeModel::Utils::createPCHInclusionOptions(pchInfo->fileName()));
return options;
}
QString messageLine(const QStringList &options, const QString &fileName)
{
const QStringList allOptions = QStringList(options)
<< QLatin1String("-fsyntax-only") << fileName;
QStringList allOptionsQuoted;
foreach (const QString &option, allOptions)
allOptionsQuoted.append(QLatin1Char('\'') + option + QLatin1Char('\''));
return ::Utils::HostOsInfo::withExecutableSuffix(QLatin1String("clang"))
+ QLatin1Char(' ') + allOptionsQuoted.join(QLatin1Char(' '));
}
} // anonymous namespace
namespace ClangCodeModel {
ClangEditorDocumentParser::ClangEditorDocumentParser(const QString &filePath)
: BaseEditorDocumentParser(filePath)
, m_marker(new ClangCodeModel::SemanticMarker)
{
BaseEditorDocumentParser::Configuration config = configuration();
config.stickToPreviousProjectPart = false;
setConfiguration(config);
}
void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info)
void ClangEditorDocumentParser::updateHelper(const BaseEditorDocumentParser::InMemoryInfo &)
{
QTC_ASSERT(m_marker, return);
// Determine project part
State state_ = state();
state_.projectPart = determineProjectPart(filePath(), configuration(), state_);
setState(state_);
emit projectPartDetermined(state_.projectPart);
// Determine message line arguments
const QStringList options = createOptions(filePath(), state_.projectPart, true);
qCDebug(log, "Reparse options (cmd line equivalent): %s",
messageLine(options, filePath()).toUtf8().constData());
// Run
QTime t; t.start();
QMutexLocker lock(m_marker->mutex());
m_marker->setFileName(filePath());
m_marker->setCompilationOptions(options);
const Internal::UnsavedFiles unsavedFiles = Utils::createUnsavedFiles(info.workingCopy,
info.modifiedFiles);
m_marker->reparse(unsavedFiles);
qCDebug(log) << "Reparse took" << t.elapsed() << "ms.";
}
QList<Diagnostic> ClangEditorDocumentParser::diagnostics() const
{
QTC_ASSERT(m_marker, return QList<Diagnostic>());
QMutexLocker(m_marker->mutex());
return m_marker->diagnostics();
}
QList<SemanticMarker::Range> ClangEditorDocumentParser::ifdefedOutBlocks() const
{
QTC_ASSERT(m_marker, return QList<SemanticMarker::Range>());
QMutexLocker(m_marker->mutex());
return m_marker->ifdefedOutBlocks();
}
SemanticMarker::Ptr ClangEditorDocumentParser::semanticMarker() const
{
return m_marker;
}
} // namespace ClangCodeModel

View File

@@ -31,12 +31,8 @@
#ifndef CLANGEDITORDOCUMENTPARSER_H
#define CLANGEDITORDOCUMENTPARSER_H
#include "semanticmarker.h"
#include <cpptools/baseeditordocumentparser.h>
namespace CppTools { class WorkingCopy; }
namespace ClangCodeModel {
class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser
@@ -46,17 +42,8 @@ class ClangEditorDocumentParser : public CppTools::BaseEditorDocumentParser
public:
ClangEditorDocumentParser(const QString &filePath);
QList<Diagnostic> diagnostics() const;
QList<SemanticMarker::Range> ifdefedOutBlocks() const;
SemanticMarker::Ptr semanticMarker() const;
signals:
void projectPartDetermined(CppTools::ProjectPart::Ptr projectPart);
private:
void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &info) override;
SemanticMarker::Ptr m_marker;
void updateHelper(const BaseEditorDocumentParser::InMemoryInfo &) override;
};
} // namespace ClangCodeModel

View File

@@ -32,11 +32,9 @@
#include "clangfixitoperation.h"
#include "clangfixitoperationsextractor.h"
#include "clanghighlightingmarksreporter.h"
#include "clangmodelmanagersupport.h"
#include "clangutils.h"
#include "cppcreatemarkers.h"
#include "diagnostic.h"
#include "pchinfo.h"
#include <diagnosticcontainer.h>
#include <sourcelocationcontainer.h>
@@ -59,22 +57,6 @@
#include <QTextBlock>
namespace {
typedef CPlusPlus::Document::DiagnosticMessage CppToolsDiagnostic;
QList<TextEditor::BlockRange> toTextEditorBlocks(
const QList<ClangCodeModel::SemanticMarker::Range> &ranges)
{
QList<TextEditor::BlockRange> result;
result.reserve(ranges.size());
foreach (const ClangCodeModel::SemanticMarker::Range &range, ranges)
result.append(TextEditor::BlockRange(range.first, range.last));
return result;
}
} // anonymous namespace
namespace ClangCodeModel {
namespace Internal {
@@ -89,26 +71,12 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
, m_semanticHighlighter(document)
, m_builtinProcessor(document, /*enableSemanticHighlighter=*/ false)
{
connect(m_parser.data(), &ClangEditorDocumentParser::projectPartDetermined,
this, &ClangEditorDocumentProcessor::onParserDeterminedProjectPart);
// Forwarding the semantic info from the builtin processor enables us to provide all
// editor (widget) related features that are not yet implemented by the clang plugin.
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
this, &ClangEditorDocumentProcessor::cppDocumentUpdated);
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::semanticInfoUpdated,
this, &ClangEditorDocumentProcessor::semanticInfoUpdated);
m_semanticHighlighter.setHighlightingRunner(
[this]() -> QFuture<TextEditor::HighlightingResult> {
const int firstLine = 1;
const int lastLine = baseTextDocument()->document()->blockCount();
CreateMarkers *createMarkers = CreateMarkers::create(m_parser->semanticMarker(),
baseTextDocument()->filePath().toString(),
firstLine, lastLine);
return createMarkers->start();
});
}
ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
@@ -125,7 +93,7 @@ ClangEditorDocumentProcessor::~ClangEditorDocumentProcessor()
void ClangEditorDocumentProcessor::run()
{
requestDiagnostics();
updateTranslationUnitIfProjectPartExists();
// Run clang parser
disconnect(&m_parserWatcher, &QFutureWatcher<void>::finished,
@@ -153,7 +121,9 @@ void ClangEditorDocumentProcessor::recalculateSemanticInfoDetached(bool force)
void ClangEditorDocumentProcessor::semanticRehighlight()
{
m_semanticHighlighter.updateFormatMapFromFontSettings();
m_semanticHighlighter.run();
if (m_projectPart)
requestDocumentAnnotations(m_projectPart->id());
}
CppTools::SemanticInfo ClangEditorDocumentProcessor::recalculateSemanticInfo()
@@ -201,6 +171,36 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(const QVector<ClangBackEnd
}
}
static QList<TextEditor::BlockRange>
toTextEditorBlocks(const QVector<ClangBackEnd::SourceRangeContainer> &ifdefedOutRanges)
{
QList<TextEditor::BlockRange> blockRanges;
blockRanges.reserve(ifdefedOutRanges.size());
for (const auto &range : ifdefedOutRanges)
blockRanges.append(TextEditor::BlockRange(range.start().offset(),range.end().offset()));
return blockRanges;
}
void ClangEditorDocumentProcessor::updateHighlighting(
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
uint documentRevision)
{
if (documentRevision == revision()) {
const auto skippedPreprocessorBlocks = toTextEditorBlocks(skippedPreprocessorRanges);
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
m_semanticHighlighter.setHighlightingRunner(
[highlightingMarks]() {
auto *reporter = new HighlightingMarksReporter(highlightingMarks);
return reporter->start();
});
m_semanticHighlighter.run();
}
}
static int currentLine(const TextEditor::AssistInterface &assistInterface)
{
int line, column;
@@ -219,9 +219,9 @@ TextEditor::QuickFixOperations ClangEditorDocumentProcessor::extraRefactoringOpe
return extractor.extract(assistInterface.fileName(), currentLine(assistInterface));
}
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainer() const
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
{
return fileContainer(m_projectPart.data());
return fileContainerWithArguments(m_projectPart.data());
}
void ClangEditorDocumentProcessor::clearDiagnosticsWithFixIts()
@@ -240,75 +240,58 @@ static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPa
&& (projectPart->id().isEmpty() || ClangCodeModel::Utils::isProjectPartLoaded(projectPart));
}
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor(
CppTools::ProjectPart::Ptr projectPart)
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor()
{
QTC_ASSERT(projectPart, return);
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPart();
if (isProjectPartLoadedOrIsFallback(projectPart)) {
updateTranslationUnitForEditor(projectPart.data());
requestDiagnostics(projectPart.data());
registerTranslationUnitForEditor(projectPart.data());
m_projectPart = projectPart;
}
}
void ClangEditorDocumentProcessor::onParserDeterminedProjectPart(
CppTools::ProjectPart::Ptr projectPart)
{
updateProjectPartAndTranslationUnitForEditor(projectPart);
}
void ClangEditorDocumentProcessor::onParserFinished()
{
if (revision() != m_parserRevision)
return;
// Emit ifdefed out blocks
const auto ifdefoutBlocks = toTextEditorBlocks(m_parser->ifdefedOutBlocks());
emit ifdefedOutBlocksUpdated(revision(), ifdefoutBlocks);
// Run semantic highlighter
m_semanticHighlighter.run();
updateProjectPartAndTranslationUnitForEditor();
}
void ClangEditorDocumentProcessor::updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart)
void ClangEditorDocumentProcessor::registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart)
{
QTC_ASSERT(m_modelManagerSupport, return);
IpcCommunicator &ipcCommunicator = m_modelManagerSupport->ipcCommunicator();
if (m_projectPart) {
if (projectPart->id() != m_projectPart->id()) {
ipcCommunicator.unregisterTranslationUnitsForEditor({fileContainer()});
ipcCommunicator.registerTranslationUnitsForEditor({fileContainer(projectPart)});
ipcCommunicator.unregisterTranslationUnitsForEditor({fileContainerWithArguments()});
ipcCommunicator.registerTranslationUnitsForEditor({fileContainerWithArguments(projectPart)});
}
} else {
ipcCommunicator.registerTranslationUnitsForEditor({{fileContainer(projectPart)}});
ipcCommunicator.registerTranslationUnitsForEditor({{fileContainerWithArguments(projectPart)}});
}
}
void ClangEditorDocumentProcessor::requestDiagnostics(CppTools::ProjectPart *projectPart)
void ClangEditorDocumentProcessor::updateTranslationUnitIfProjectPartExists()
{
if (!m_projectPart || projectPart->id() != m_projectPart->id()) {
IpcCommunicator &ipcCommunicator = m_modelManagerSupport->ipcCommunicator();
ipcCommunicator.requestDiagnostics({fileContainer(projectPart)});
}
}
void ClangEditorDocumentProcessor::requestDiagnostics()
{
// Get diagnostics
if (m_projectPart) {
auto &ipcCommunicator = m_modelManagerSupport->ipcCommunicator();
ipcCommunicator.requestDiagnostics({filePath(),
m_projectPart->id(),
baseTextDocument()->plainText(),
true,
revision()});
const ClangBackEnd::FileContainer fileContainer = fileContainerWithDocumentContent(m_projectPart->id());
m_modelManagerSupport->ipcCommunicator().updateTranslationUnitWithRevisionCheck(fileContainer);
}
}
void ClangEditorDocumentProcessor::requestDocumentAnnotations(const QString &projectpartId)
{
const auto fileContainer = fileContainerWithDocumentContent(projectpartId);
auto &ipcCommunicator = m_modelManagerSupport->ipcCommunicator();
ipcCommunicator.requestDiagnostics(fileContainer);
ipcCommunicator.requestHighlighting(fileContainer);
}
static CppTools::ProjectPart projectPartForLanguageOption(CppTools::ProjectPart *projectPart)
{
if (projectPart)
@@ -332,7 +315,7 @@ static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart
}
ClangBackEnd::FileContainer
ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart) const
ClangEditorDocumentProcessor::fileContainerWithArguments(CppTools::ProjectPart *projectPart) const
{
const auto projectPartId = projectPart
? Utf8String::fromString(projectPart->id())
@@ -342,5 +325,15 @@ ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart)
return {filePath(), projectPartId, Utf8StringVector(theFileArguments), revision()};
}
ClangBackEnd::FileContainer
ClangEditorDocumentProcessor::fileContainerWithDocumentContent(const QString &projectpartId) const
{
return ClangBackEnd::FileContainer(filePath(),
projectpartId,
baseTextDocument()->plainText(),
true,
revision());
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -43,6 +43,7 @@
namespace ClangBackEnd {
class DiagnosticContainer;
class HighlightingMarkContainer;
class FileContainer;
}
@@ -75,11 +76,14 @@ public:
void updateCodeWarnings(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
uint documentRevision);
void updateHighlighting(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
uint documentRevision);
TextEditor::QuickFixOperations
extraRefactoringOperations(const TextEditor::AssistInterface &assistInterface) override;
ClangBackEnd::FileContainer fileContainer() const;
ClangBackEnd::FileContainer fileContainerWithArguments() const;
void clearDiagnosticsWithFixIts();
@@ -87,15 +91,15 @@ public:
static ClangEditorDocumentProcessor *get(const QString &filePath);
private slots:
void onParserDeterminedProjectPart(CppTools::ProjectPart::Ptr projectPart);
void onParserFinished();
private:
void updateProjectPartAndTranslationUnitForEditor(CppTools::ProjectPart::Ptr projectPart);
void updateTranslationUnitForEditor(CppTools::ProjectPart *projectPart);
void requestDiagnostics(CppTools::ProjectPart *projectPart);
void requestDiagnostics();
ClangBackEnd::FileContainer fileContainer(CppTools::ProjectPart *projectPart) const;
void updateProjectPartAndTranslationUnitForEditor();
void registerTranslationUnitForEditor(CppTools::ProjectPart *projectPart);
void updateTranslationUnitIfProjectPartExists();
void requestDocumentAnnotations(const QString &projectpartId);
ClangBackEnd::FileContainer fileContainerWithArguments(CppTools::ProjectPart *projectPart) const;
ClangBackEnd::FileContainer fileContainerWithDocumentContent(const QString &projectpartId) const;
private:
ClangDiagnosticManager m_diagnosticManager;

View File

@@ -30,7 +30,7 @@
#include "clangfunctionhintmodel.h"
#include "completionchunkstotextconverter.h"
#include "clangcompletionchunkstotextconverter.h"
#include <cplusplus/SimpleLexer.h>

View File

@@ -0,0 +1,155 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "clanghighlightingmarksreporter.h"
#include <cpptools/semantichighlighter.h>
#include <QFuture>
namespace {
CppTools::SemanticHighlighter::Kind toCppToolsSemanticHighlighterKind(
ClangBackEnd::HighlightingType type)
{
using ClangBackEnd::HighlightingType;
using CppTools::SemanticHighlighter;
switch (type) {
case HighlightingType::Keyword:
return SemanticHighlighter::PseudoKeywordUse;
case HighlightingType::Function:
return SemanticHighlighter::FunctionUse;
case HighlightingType::VirtualFunction:
return SemanticHighlighter::VirtualMethodUse;
case HighlightingType::Type:
return SemanticHighlighter::TypeUse;
case HighlightingType::LocalVariable:
return SemanticHighlighter::LocalUse;
case HighlightingType::Field:
return SemanticHighlighter::FieldUse;
case HighlightingType::GlobalVariable:
return SemanticHighlighter::Unknown;
case HighlightingType::Enumeration:
return SemanticHighlighter::EnumerationUse;
case HighlightingType::Label:
return SemanticHighlighter::LabelUse;
case HighlightingType::Preprocessor:
return SemanticHighlighter::MacroUse;
default:
return SemanticHighlighter::Unknown;
}
Q_UNREACHABLE();
}
TextEditor::HighlightingResult toHighlightingResult(
const ClangBackEnd::HighlightingMarkContainer &highlightingMark)
{
const auto highlighterKind = toCppToolsSemanticHighlighterKind(highlightingMark.type());
return TextEditor::HighlightingResult(highlightingMark.line(),
highlightingMark.column(),
highlightingMark.length(),
highlighterKind);
}
} // anonymous
namespace ClangCodeModel {
HighlightingMarksReporter::HighlightingMarksReporter(
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks)
: m_highlightingMarks(highlightingMarks)
{
m_chunksToReport.reserve(m_chunkSize + 1);
}
void HighlightingMarksReporter::reportChunkWise(
const TextEditor::HighlightingResult &highlightingResult)
{
if (m_chunksToReport.size() >= m_chunkSize) {
if (m_flushRequested && highlightingResult.line != m_flushLine) {
reportAndClearCurrentChunks();
} else if (!m_flushRequested) {
m_flushRequested = true;
m_flushLine = highlightingResult.line;
}
}
m_chunksToReport.append(highlightingResult);
}
void HighlightingMarksReporter::reportAndClearCurrentChunks()
{
m_flushRequested = false;
m_flushLine = 0;
if (!m_chunksToReport.isEmpty()) {
reportResults(m_chunksToReport);
m_chunksToReport.erase(m_chunksToReport.begin(), m_chunksToReport.end());
}
}
void HighlightingMarksReporter::setChunkSize(int chunkSize)
{
m_chunkSize = chunkSize;
}
void HighlightingMarksReporter::run()
{
run_internal();
reportFinished();
}
void HighlightingMarksReporter::run_internal()
{
if (isCanceled())
return;
for (const auto &highlightingMark : m_highlightingMarks)
reportChunkWise(toHighlightingResult(highlightingMark));
if (isCanceled())
return;
reportAndClearCurrentChunks();
}
QFuture<TextEditor::HighlightingResult> HighlightingMarksReporter::start()
{
this->setRunnable(this);
this->reportStarted();
QFuture<TextEditor::HighlightingResult> future = this->future();
QThreadPool::globalInstance()->start(this, QThread::LowestPriority);
return future;
}
} // namespace ClangCodeModel

View File

@@ -28,46 +28,51 @@
**
****************************************************************************/
#ifndef CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H
#define CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H
#ifndef CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H
#define CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H
#include "../clang_global.h"
#include <QStringList>
#include <QSharedPointer>
#include <QFutureInterface>
#include <QObject>
#include <QRunnable>
#include <QThreadPool>
#include <texteditor/semantichighlighter.h>
#include <clangbackendipc/highlightingmarkcontainer.h>
namespace ClangCodeModel {
class CLANG_EXPORT ScopedClangOptions
class HighlightingMarksReporter:
public QObject,
public QRunnable,
public QFutureInterface<TextEditor::HighlightingResult>
{
public:
ScopedClangOptions(const QStringList &options);
~ScopedClangOptions();
Q_OBJECT
const char **data() const;
int size() const;
public:
HighlightingMarksReporter(const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks);
void setChunkSize(int chunkSize);
QFuture<TextEditor::HighlightingResult> start();
private:
void release();
void run() override;
void run_internal();
int m_size;
const char **m_rawOptions;
};
class CLANG_EXPORT SharedClangOptions
{
public:
SharedClangOptions();
SharedClangOptions(const QStringList &options);
void reloadOptions(const QStringList &options);
const char **data() const;
int size() const;
void reportChunkWise(const TextEditor::HighlightingResult &highlightingResult);
void reportAndClearCurrentChunks();
private:
QSharedPointer<ScopedClangOptions> d;
QVector<ClangBackEnd::HighlightingMarkContainer> m_highlightingMarks;
QVector<TextEditor::HighlightingResult> m_chunksToReport;
int m_chunkSize = 100;
bool m_flushRequested = false;
unsigned m_flushLine = 0;
};
} // namespace ClangCodeModel
#endif // CLANGCODEMODEL_SCOPEDCLANGOPTIONS_H
#endif // CLANGCODEMODEL_HIGHLIGHTINGMARKSREPORTER_H

View File

@@ -1,172 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "clangindexer.h"
#include "clangutils.h"
#include "indexer.h"
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/session.h>
#include <QDir>
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
ClangIndexingSupport::ClangIndexingSupport(ClangIndexer *indexer)
: m_indexer(indexer)
{
}
ClangIndexingSupport::~ClangIndexingSupport()
{
}
QFuture<void> ClangIndexingSupport::refreshSourceFiles(
const QSet<QString> &sourceFiles,
CppTools::CppModelManager::ProgressNotificationMode mode)
{
Q_UNUSED(mode);
return m_indexer->refreshSourceFiles(sourceFiles);
}
CppTools::SymbolSearcher *ClangIndexingSupport::createSymbolSearcher(CppTools::SymbolSearcher::Parameters parameters, QSet<QString> fileNames)
{
Q_UNUSED(parameters);
Q_UNUSED(fileNames)
// return new ClangSymbolSearcher(m_indexer, parameters, fileNames);
return 0;
}
ClangIndexer::ClangIndexer()
: QObject(0)
, m_indexingSupport(new ClangIndexingSupport(this))
, m_isLoadingSession(false)
, m_clangIndexer(new Indexer(this))
{
connect(m_clangIndexer, SIGNAL(indexingStarted(QFuture<void>,Internal::ProgressNotificationMode)),
this, SLOT(onIndexingStarted(QFuture<void>,Internal::ProgressNotificationMode)));
QObject *session = ProjectExplorer::SessionManager::instance();
connect(session, SIGNAL(aboutToLoadSession(QString)),
this, SLOT(onAboutToLoadSession(QString)));
connect(session, SIGNAL(sessionLoaded(QString)),
this, SLOT(onSessionLoaded(QString)));
connect(session, SIGNAL(aboutToSaveSession()),
this, SLOT(onAboutToSaveSession()));
}
ClangIndexer::~ClangIndexer()
{
m_clangIndexer->cancel(true);
}
CppTools::CppIndexingSupport *ClangIndexer::indexingSupport()
{
return m_indexingSupport.data();
}
QFuture<void> ClangIndexer::refreshSourceFiles(const QSet<QString> &sourceFiles)
{
typedef CppTools::ProjectPart ProjectPart;
CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
if (m_clangIndexer->isBusy())
m_clangIndexer->cancel(true);
foreach (const QString &file, sourceFiles) {
if (m_clangIndexer->isTracking(file))
continue; // we get notified separately about open files.
const QList<ProjectPart::Ptr> &parts = modelManager->projectPart(file);
if (!parts.isEmpty())
m_clangIndexer->addFile(file, parts.at(0));
else
m_clangIndexer->addFile(file, ProjectPart::Ptr());
}
if (!m_isLoadingSession)
m_clangIndexer->regenerate();
return QFuture<void>();
}
void ClangIndexer::match(ClangSymbolSearcher *searcher) const
{
m_clangIndexer->match(searcher);
}
void ClangIndexer::onAboutToLoadSession(const QString &sessionName)
{
m_isLoadingSession = true;
if (sessionName == QLatin1String("default"))
return;
QString path = Core::ICore::instance()->userResourcePath() + QLatin1String("/codemodel/");
if (QFile::exists(path) || QDir().mkpath(path))
m_clangIndexer->initialize(path + sessionName + QLatin1String(".qci"));
}
void ClangIndexer::onSessionLoaded(QString)
{
m_isLoadingSession = false;
m_clangIndexer->regenerate();
}
void ClangIndexer::onAboutToSaveSession()
{
m_clangIndexer->finalize();
}
void ClangIndexer::indexNow(Unit::Ptr unit)
{
typedef CppTools::ProjectPart ProjectPart;
QString file = unit->fileName();
CppTools::CppModelManager *mmi = CppTools::CppModelManager::instance();
const QList<ProjectPart::Ptr> &parts = mmi->projectPart(file);
ProjectPart::Ptr part;
if (!parts.isEmpty())
part = parts.at(0);
if (!m_isLoadingSession)
m_clangIndexer->runQuickIndexing(unit, part);
}
void ClangIndexer::onIndexingStarted(QFuture<void> indexingFuture)
{
Core::ProgressManager::addTask(indexingFuture, QCoreApplication::translate(
"ClangCodeModel::Internal::ClangIndexer",
"Parsing C/C++/ObjC Files"),
"ClangCodeMode.Task.Indexing");
}

View File

@@ -1,99 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANGINDEXER_H
#define CLANGINDEXER_H
#include "fastindexer.h"
#include <cpptools/cppindexingsupport.h>
#include <QObject>
namespace ClangCodeModel {
class Indexer;
namespace Internal {
typedef CppTools::CppModelManager::ProgressNotificationMode ProgressNotificationMode;
class ClangIndexer;
class ClangSymbolSearcher;
class ClangIndexingSupport: public CppTools::CppIndexingSupport
{
public:
ClangIndexingSupport(ClangIndexer *indexer);
virtual ~ClangIndexingSupport();
virtual QFuture<void> refreshSourceFiles(
const QSet<QString> &sourceFiles,
ProgressNotificationMode mode);
virtual CppTools::SymbolSearcher *createSymbolSearcher(
CppTools::SymbolSearcher::Parameters parameters, QSet<QString> fileNames);
private:
ClangIndexer *m_indexer;
};
class ClangIndexer: public QObject, public FastIndexer
{
Q_OBJECT
public:
ClangIndexer();
~ClangIndexer();
CppTools::CppIndexingSupport *indexingSupport();
QFuture<void> refreshSourceFiles(const QSet<QString> &sourceFiles);
void match(ClangSymbolSearcher *searcher) const;
void indexNow(Unit::Ptr unit);
public slots:
void onAboutToLoadSession(const QString &sessionName);
void onSessionLoaded(QString);
void onAboutToSaveSession();
private slots:
void onIndexingStarted(QFuture<void> indexingFuture);
private:
QScopedPointer<ClangIndexingSupport> m_indexingSupport;
bool m_isLoadingSession;
Indexer *m_clangIndexer;
};
} // namespace Internal
} // namespace ClangCodeModel
#endif // CLANGINDEXER_H

View File

@@ -30,7 +30,7 @@
#include "clangmodelmanagersupport.h"
#include "constants.h"
#include "clangconstants.h"
#include "clangeditordocumentprocessor.h"
#include "clangutils.h"
@@ -66,9 +66,14 @@ ModelManagerSupportClang::ModelManagerSupportClang()
Core::EditorManager *editorManager = Core::EditorManager::instance();
connect(editorManager, &Core::EditorManager::currentEditorChanged,
this, &ModelManagerSupportClang::onCurrentEditorChanged);
this, &ModelManagerSupportClang::onCurrentEditorChanged,
Qt::QueuedConnection);
connect(editorManager, &Core::EditorManager::editorOpened,
this, &ModelManagerSupportClang::onEditorOpened);
this, &ModelManagerSupportClang::onEditorOpened,
Qt::QueuedConnection);
connect(editorManager, &Core::EditorManager::editorsClosed,
this, &ModelManagerSupportClang::onEditorClosed,
Qt::QueuedConnection);
CppTools::CppModelManager *modelManager = cppModelManager();
connect(modelManager, &CppTools::CppModelManager::abstractEditorSupportContentsUpdated,
@@ -97,20 +102,9 @@ CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentP
return new ClangEditorDocumentProcessor(this, baseTextDocument);
}
void ModelManagerSupportClang::onCurrentEditorChanged(Core::IEditor *newCurrent)
void ModelManagerSupportClang::onCurrentEditorChanged(Core::IEditor *)
{
// If we switch away from a cpp editor, update the backend about
// the document's unsaved content.
if (m_previousCppEditor && m_previousCppEditor->document()->isModified()) {
m_ipcCommunicator.updateTranslationUnitFromCppEditorDocument(
m_previousCppEditor->document()->filePath().toString());
}
// Remember previous editor
if (newCurrent && cppModelManager()->isCppEditor(newCurrent))
m_previousCppEditor = newCurrent;
else
m_previousCppEditor.clear();
m_ipcCommunicator.updateTranslationUnitVisiblity();
}
void ModelManagerSupportClang::connectTextDocumentToTranslationUnit(TextEditor::TextDocument *textDocument)
@@ -181,6 +175,11 @@ void ModelManagerSupportClang::onEditorOpened(Core::IEditor *editor)
}
}
void ModelManagerSupportClang::onEditorClosed(const QList<Core::IEditor *> &)
{
m_ipcCommunicator.updateTranslationUnitVisiblity();
}
void ModelManagerSupportClang::onCppDocumentAboutToReloadOnTranslationUnit()
{
TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
@@ -193,7 +192,7 @@ void ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool
if (success) {
TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(sender());
connectToTextDocumentContentsChangedForTranslationUnit(textDocument);
m_ipcCommunicator.requestDiagnostics(textDocument);
m_ipcCommunicator.updateTranslationUnitWithRevisionCheck(textDocument);
}
}
@@ -342,7 +341,7 @@ void ModelManagerSupportClang::unregisterTranslationUnitsWithProjectParts(
{
const auto processors = clangProcessorsWithProjectParts(projectPartIds);
foreach (ClangEditorDocumentProcessor *processor, processors) {
m_ipcCommunicator.unregisterTranslationUnitsForEditor({processor->fileContainer()});
m_ipcCommunicator.unregisterTranslationUnitsForEditor({processor->fileContainerWithArguments()});
processor->clearProjectPart();
processor->run();
}

View File

@@ -71,6 +71,7 @@ public:
private:
void onEditorOpened(Core::IEditor *editor);
void onEditorClosed(const QList<Core::IEditor *> &editors);
void onCurrentEditorChanged(Core::IEditor *newCurrent);
void onCppDocumentAboutToReloadOnTranslationUnit();
void onCppDocumentReloadFinishedOnTranslationUnit(bool success);
@@ -103,7 +104,6 @@ private:
private:
IpcCommunicator m_ipcCommunicator;
ClangCompletionAssistProvider m_completionAssistProvider;
QPointer<Core::IEditor> m_previousCppEditor;
};
class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider

View File

@@ -31,8 +31,6 @@
#ifndef CLANGPROJECTSETTINGS_H
#define CLANGPROJECTSETTINGS_H
#include "clang_global.h"
#include <projectexplorer/project.h>
#include <QObject>
@@ -40,7 +38,7 @@
namespace ClangCodeModel {
class CLANG_EXPORT ClangProjectSettings: public QObject
class ClangProjectSettings: public QObject
{
Q_OBJECT

View File

@@ -30,11 +30,6 @@
#include "clangprojectsettings.h"
#include "clangprojectsettingspropertiespage.h"
#include "pchmanager.h"
#include <QButtonGroup>
#include <QCoreApplication>
#include <QFileDialog>
using namespace ProjectExplorer;
using namespace ClangCodeModel::Internal;
@@ -43,88 +38,4 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(Project *project)
: m_project(project)
{
m_ui.setupUi(this);
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(project);
Q_ASSERT(cps);
QButtonGroup *pchGroup = new QButtonGroup(this);
pchGroup->addButton(m_ui.noneButton, ClangProjectSettings::PchUse_None);
pchGroup->addButton(m_ui.exactButton, ClangProjectSettings::PchUse_BuildSystem_Exact);
pchGroup->addButton(m_ui.fuzzyButton, ClangProjectSettings::PchUse_BuildSystem_Fuzzy);
pchGroup->addButton(m_ui.customButton, ClangProjectSettings::PchUse_Custom);
switch (cps->pchUsage()) {
case ClangProjectSettings::PchUse_None:
case ClangProjectSettings::PchUse_BuildSystem_Exact:
case ClangProjectSettings::PchUse_BuildSystem_Fuzzy:
case ClangProjectSettings::PchUse_Custom:
pchGroup->button(cps->pchUsage())->setChecked(true);
break;
default: break;
}
pchUsageChanged(cps->pchUsage());
connect(pchGroup, SIGNAL(buttonClicked(int)),
this, SLOT(pchUsageChanged(int)));
m_ui.customField->setText(cps->customPchFile());
connect(m_ui.customField, SIGNAL(editingFinished()),
this, SLOT(customPchFileChanged()));
connect(m_ui.customButton, SIGNAL(clicked()),
this, SLOT(customPchButtonClicked()));
}
void ClangProjectSettingsWidget::pchUsageChanged(int id)
{
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(m_project);
Q_ASSERT(cps);
cps->setPchUsage(static_cast<ClangProjectSettings::PchUsage>(id));
switch (id) {
case ClangProjectSettings::PchUse_None:
case ClangProjectSettings::PchUse_BuildSystem_Fuzzy:
case ClangProjectSettings::PchUse_BuildSystem_Exact:
m_ui.customField->setEnabled(false);
m_ui.chooseButton->setEnabled(false);
break;
case ClangProjectSettings::PchUse_Custom:
m_ui.customField->setEnabled(true);
m_ui.chooseButton->setEnabled(true);
break;
default:
break;
}
}
void ClangProjectSettingsWidget::customPchFileChanged()
{
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(m_project);
Q_ASSERT(cps);
if (cps->pchUsage() != ClangProjectSettings::PchUse_Custom)
return;
QString fileName = m_ui.customField->text();
if (!QFile(fileName).exists())
return;
cps->setCustomPchFile(fileName);
}
void ClangProjectSettingsWidget::customPchButtonClicked()
{
ClangProjectSettings *cps = PchManager::instance()->settingsForProject(m_project);
Q_ASSERT(cps);
QFileDialog d(this);
d.setNameFilters(QStringList() << tr("Header Files (*.h)")
<< tr("All Files (*)"));
d.setFileMode(QFileDialog::ExistingFile);
d.setDirectory(m_project->projectDirectory().toString());
if (!d.exec())
return;
const QStringList fileNames = d.selectedFiles();
if (fileNames.isEmpty() || fileNames.first().isEmpty())
return;
m_ui.customField->setText(fileNames.first());
cps->setCustomPchFile(fileNames.first());
}

View File

@@ -33,10 +33,8 @@
#include "ui_clangprojectsettingspropertiespage.h"
#include <QString>
namespace ProjectExplorer {
class Project;
class Project;
}
namespace ClangCodeModel {
@@ -49,11 +47,6 @@ class ClangProjectSettingsWidget: public QWidget
public:
ClangProjectSettingsWidget(ProjectExplorer::Project *project);
protected slots:
void pchUsageChanged(int id);
void customPchFileChanged();
void customPchButtonClicked();
private:
Ui::ClangProjectSettingsPropertiesPage m_ui;
ProjectExplorer::Project *m_project;

View File

@@ -2,6 +2,9 @@
<ui version="4.0">
<class>ClangCodeModel::Internal::ClangProjectSettingsPropertiesPage</class>
<widget class="QWidget" name="ClangCodeModel::Internal::ClangProjectSettingsPropertiesPage">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>

View File

@@ -30,7 +30,7 @@
#include "clangtextmark.h"
#include "constants.h"
#include "clangconstants.h"
#include <coreplugin/coreicons.h>

View File

@@ -32,25 +32,18 @@
#include "clangeditordocumentprocessor.h"
#include <clang-c/Index.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <cpptools/baseeditordocumentparser.h>
#include <cpptools/cppprojects.h>
#include <cpptools/cppworkingcopy.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
#include <QDir>
#include <QFile>
#include <QLoggingCategory>
#include <QRegularExpression>
#include <QSet>
#include <QString>
#include <QStringList>
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
@@ -62,21 +55,6 @@ namespace Utils {
Q_LOGGING_CATEGORY(verboseRunLog, "qtc.clangcodemodel.verboserun")
UnsavedFiles createUnsavedFiles(const WorkingCopy &workingCopy,
const ::Utils::FileNameList &modifiedFiles)
{
UnsavedFiles result;
QHashIterator< ::Utils::FileName, QPair<QByteArray, unsigned> > wcIter = workingCopy.iterator();
while (wcIter.hasNext()) {
wcIter.next();
const ::Utils::FileName &fileName = wcIter.key();
if (modifiedFiles.contains(fileName) && QFile(fileName.toString()).exists())
result.insert(fileName.toString(), wcIter.value().first);
}
return result;
}
/**
* @brief Creates list of message-line arguments required for correct parsing
* @param pPart Null if file isn't part of any project

View File

@@ -31,10 +31,7 @@
#ifndef CPPTOOLS_CLANGUTILS_H
#define CPPTOOLS_CLANGUTILS_H
#include "clang_global.h"
#include "utils.h"
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cppprojects.h>
#include <QLoggingCategory>
@@ -43,10 +40,6 @@ namespace Utils {
Q_DECLARE_LOGGING_CATEGORY(verboseRunLog)
ClangCodeModel::Internal::UnsavedFiles createUnsavedFiles(
const CppTools::WorkingCopy &workingCopy,
const ::Utils::FileNameList &modifiedFiles);
QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart,
CppTools::ProjectFile::Kind fileKind);
QStringList createClangOptions(const CppTools::ProjectPart::Ptr &pPart,

View File

@@ -1,65 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <QtCore/QLatin1Char>
namespace ClangCodeModel {
namespace Constants {
static const QLatin1Char kLParen('(');
static const QLatin1Char kRParen(')');
static const QLatin1Char kLBrace('{');
static const QLatin1Char kRBrace('}');
static const QLatin1Char kLBracket('[');
static const QLatin1Char kRBracket(']');
static const QLatin1Char kLABracket('<');
static const QLatin1Char kRABracket('>');
static const QLatin1Char kSemiColon(';');
static const QLatin1Char kPound('#');
static const QLatin1Char kColon(':');
static const QLatin1Char kExclamation('!');
static const QLatin1Char kSpace(' ');
static const QLatin1Char kSlash('/');
static const QLatin1Char kStar('*');
static const QLatin1Char kDoubleQuote('"');
static const QLatin1Char kNewLine('\n');
static const QLatin1Char kHorizontalTab('\t');
const char CLANG_MODELMANAGERSUPPORT_ID[] = "ClangCodeModel.ClangCodeModel";
const char CLANG_ERROR[] = "Clang.Error";
const char CLANG_WARNING[] = "Clang.Warning";
}
}
#endif // CONSTANTS_H

View File

@@ -1,135 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "clangutils.h"
#include "cppcreatemarkers.h"
#include <cplusplus/CppDocument.h>
#include <utils/executeondestruction.h>
#include <utils/runextensions.h>
#include <QCoreApplication>
#include <QLoggingCategory>
#include <QMutexLocker>
#include <QThreadPool>
#include <QDebug>
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
using namespace CppTools;
static Q_LOGGING_CATEGORY(log, "qtc.clangcodemodel.createmarkers")
CreateMarkers *CreateMarkers::create(SemanticMarker::Ptr semanticMarker,
const QString &fileName,
unsigned firstLine, unsigned lastLine)
{
if (semanticMarker.isNull())
return 0;
else
return new CreateMarkers(semanticMarker, fileName, firstLine, lastLine);
}
CreateMarkers::CreateMarkers(SemanticMarker::Ptr semanticMarker,
const QString &fileName,
unsigned firstLine, unsigned lastLine)
: m_marker(semanticMarker)
, m_fileName(fileName)
, m_firstLine(firstLine)
, m_lastLine(lastLine)
{
Q_ASSERT(!semanticMarker.isNull());
m_flushRequested = false;
m_flushLine = 0;
}
CreateMarkers::~CreateMarkers()
{ }
void CreateMarkers::run()
{
QMutexLocker lock(m_marker->mutex());
::Utils::ExecuteOnDestruction reportFinishedOnDestruction([this]() { reportFinished(); });
if (isCanceled())
return;
qCDebug(log) << "Creating markers from" << m_firstLine << "to" << m_lastLine
<< "of" << m_fileName;
QTime t; t.start();
m_usages.clear();
if (isCanceled())
return;
const QList<ClangCodeModel::SourceMarker> markers
= m_marker->sourceMarkersInRange(m_firstLine, m_lastLine);
foreach (const ClangCodeModel::SourceMarker &m, markers)
addUse(SourceMarker(m.location().line(), m.location().column(), m.length(), m.kind()));
if (isCanceled())
return;
flush();
qCDebug(log) << "Creating markers took" << t.elapsed() << "ms in total.";
}
void CreateMarkers::addUse(const SourceMarker &marker)
{
// if (! enclosingFunctionDefinition()) {
if (m_usages.size() >= 100) {
if (m_flushRequested && marker.line != m_flushLine)
flush();
else if (! m_flushRequested) {
m_flushRequested = true;
m_flushLine = marker.line;
}
}
// }
m_usages.append(marker);
}
void CreateMarkers::flush()
{
m_flushRequested = false;
m_flushLine = 0;
if (m_usages.isEmpty())
return;
reportResults(m_usages);
m_usages.clear();
}

View File

@@ -1,94 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CPPCREATEMARKERS_H
#define CPPCREATEMARKERS_H
#include "fastindexer.h"
#include "sourcemarker.h"
#include "semanticmarker.h"
#include "pchinfo.h"
#include <texteditor/semantichighlighter.h>
#include <QFuture>
#include <QtConcurrentRun>
namespace ClangCodeModel {
class CreateMarkers:
public QObject,
public QRunnable,
public QFutureInterface<TextEditor::HighlightingResult>
{
Q_OBJECT
Q_DISABLE_COPY(CreateMarkers)
public:
virtual ~CreateMarkers();
virtual void run();
typedef TextEditor::HighlightingResult SourceMarker;
typedef QFuture<SourceMarker> Future;
Future start()
{
this->setRunnable(this);
this->reportStarted();
Future future = this->future();
QThreadPool::globalInstance()->start(this, QThread::LowestPriority);
return future;
}
static CreateMarkers *create(ClangCodeModel::SemanticMarker::Ptr semanticMarker,
const QString &fileName, unsigned firstLine, unsigned lastLine);
void addUse(const SourceMarker &marker);
void flush();
protected:
CreateMarkers(ClangCodeModel::SemanticMarker::Ptr semanticMarker,
const QString &fileName, unsigned firstLine, unsigned lastLine);
private:
ClangCodeModel::SemanticMarker::Ptr m_marker;
QString m_fileName;
unsigned m_firstLine;
unsigned m_lastLine;
QVector<SourceMarker> m_usages;
bool m_flushRequested;
unsigned m_flushLine;
};
} // namespace ClangCodeModel
#endif // CPPCREATEMARKERS_H

View File

@@ -1,551 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "cxprettyprinter.h"
#include "utils_p.h"
#include "cxraii.h"
#include <QStringList>
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
CXPrettyPrinter::CXPrettyPrinter()
: m_indent(0)
{
}
QString CXPrettyPrinter::toString(CXCompletionChunkKind kind) const
{
switch (kind) {
case CXCompletionChunk_Optional:
return QLatin1String("Optional");
case CXCompletionChunk_TypedText:
return QLatin1String("TypedText");
case CXCompletionChunk_Text:
return QLatin1String("Text");
case CXCompletionChunk_Placeholder:
return QLatin1String("Placeholder");
case CXCompletionChunk_Informative:
return QLatin1String("Informative");
case CXCompletionChunk_CurrentParameter:
return QLatin1String("CurrentParameter");
case CXCompletionChunk_LeftParen:
return QLatin1String("LeftParen");
case CXCompletionChunk_RightParen:
return QLatin1String("RightParen");
case CXCompletionChunk_LeftBracket:
return QLatin1String("LeftBracket");
case CXCompletionChunk_RightBracket:
return QLatin1String("RightBracket");
case CXCompletionChunk_LeftBrace:
return QLatin1String("LeftBrace");
case CXCompletionChunk_RightBrace:
return QLatin1String("RightBrace");
case CXCompletionChunk_LeftAngle:
return QLatin1String("LeftAngle");
case CXCompletionChunk_RightAngle:
return QLatin1String("RightAngle");
case CXCompletionChunk_Comma:
return QLatin1String("Comma");
case CXCompletionChunk_ResultType:
return QLatin1String("ResultType");
case CXCompletionChunk_Colon:
return QLatin1String("Colon");
case CXCompletionChunk_SemiColon:
return QLatin1String("SemiColon");
case CXCompletionChunk_Equal:
return QLatin1String("Equal");
case CXCompletionChunk_HorizontalSpace:
return QLatin1String("HorizontalSpace");
case CXCompletionChunk_VerticalSpace:
return QLatin1String("VerticalSpace");
default:
return QLatin1String("<UNKNOWN>");
}
}
QString CXPrettyPrinter::toString(CXAvailabilityKind kind) const
{
switch (kind) {
case CXAvailability_Available:
return QLatin1String("Available");
case CXAvailability_Deprecated:
return QLatin1String("Deprecated");
case CXAvailability_NotAccessible:
return QLatin1String("NotAccessible");
case CXAvailability_NotAvailable:
return QLatin1String("NotAvailable");
default:
return QLatin1String("<UNKNOWN>");
}
}
QString CXPrettyPrinter::toString(CXCursorKind kind) const
{
return getQString(clang_getCursorKindSpelling(kind));
}
QString CXPrettyPrinter::toString(CXDiagnosticSeverity severity) const
{
switch (severity)
{
case CXDiagnostic_Ignored:
return QLatin1String("Ignored");
case CXDiagnostic_Note:
return QLatin1String("Note");
case CXDiagnostic_Warning:
return QLatin1String("Warning");
case CXDiagnostic_Error:
return QLatin1String("Error");
case CXDiagnostic_Fatal:
return QLatin1String("Fatal");
default:
return QLatin1String("<UNKNOWN>");
}
}
QString CXPrettyPrinter::jsonForCompletionMeta(CXCodeCompleteResults *results)
{
QString json;
m_printed.swap(json);
m_indent = 0;
m_printed += QLatin1String("CXCodeCompleteResults {");
m_indent += 4;
CXCursorKind containerKind = clang_codeCompleteGetContainerKind(results, NULL);
writeLineEnd();
m_printed += QLatin1String("'container CursorKind': ");
m_printed += toString(containerKind);
m_printed += QLatin1Char(',');
QString containerUSR(Internal::getQString(clang_codeCompleteGetContainerUSR(results)));
if (!containerUSR.isEmpty()) {
writeLineEnd();
m_printed += QLatin1String("'container USR': ");
m_printed += containerUSR;
m_printed += QLatin1Char(',');
}
QString objCSelector(Internal::getQString(clang_codeCompleteGetObjCSelector(results)));
if (!objCSelector.isEmpty()) {
writeLineEnd();
m_printed += QLatin1String("'Objective-C selector': ");
m_printed += objCSelector;
m_printed += QLatin1Char(',');
}
writeLineEnd();
m_printed += QLatin1String("'contexts': [");
m_indent += 4;
writeCompletionContexts(results);
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char(']');
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char('}');
m_printed.swap(json);
return json;
}
QString CXPrettyPrinter::jsonForCompletionString(const CXCompletionString &string)
{
QString json;
m_printed.swap(json);
m_indent = 0;
m_printed += QLatin1String("CXCompletionString: ");
writeCompletionStringJson(string);
m_printed.swap(json);
return json;
}
QString CXPrettyPrinter::jsonForCompletion(const CXCompletionResult &result)
{
QString json;
m_printed.swap(json);
m_indent = 4;
m_printed += QLatin1String("CXCompletionResult: {\n"
" CompletionString: ");
writeCompletionStringJson(result.CompletionString);
m_printed += QLatin1Char('\n');
m_printed += QLatin1String(" CursorKind: ");
m_printed += toString(result.CursorKind);
m_printed += QLatin1String(";\n}");
m_printed.swap(json);
return json;
}
/**
* @brief CXPrettyPrinter::jsonForDiagnsotic
* @param diagnostic
* @return
*
* List of used clang-c API calls:
* CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
* CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
* CXString clang_getDiagnosticOption(CXDiagnostic Diag,
* CXString *Disable);
* unsigned clang_getDiagnosticCategory(CXDiagnostic);
* CXString clang_getDiagnosticCategoryText(CXDiagnostic);
* unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
* CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
* unsigned Range);
* unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
* CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
* unsigned FixIt,
* CXSourceRange *ReplacementRange);
*/
QString CXPrettyPrinter::jsonForDiagnsotic(const CXDiagnostic &diagnostic)
{
QString json;
m_printed.swap(json);
m_indent = 0;
m_printed += QLatin1String("CXDiagnostic: ");
writeDiagnosticJson(diagnostic);
m_printed.swap(json);
return json;
}
void CXPrettyPrinter::writeCompletionContexts(CXCodeCompleteResults *results)
{
quint64 contexts = clang_codeCompleteGetContexts(results);
QStringList lines;
if (contexts & CXCompletionContext_AnyType)
lines << QLatin1String("'any type'");
if (contexts & CXCompletionContext_AnyValue)
lines << QLatin1String("'any value'");
if (contexts & CXCompletionContext_ObjCObjectValue)
lines << QLatin1String("'Objective-C object'");
if (contexts & CXCompletionContext_ObjCSelectorValue)
lines << QLatin1String("'Objective-C selector'");
if (contexts & CXCompletionContext_CXXClassTypeValue)
lines << QLatin1String("'C++ class'");
if (contexts & CXCompletionContext_DotMemberAccess)
lines << QLatin1String("'. member access'");
if (contexts & CXCompletionContext_ArrowMemberAccess)
lines << QLatin1String("'-> member access'");
if (contexts & CXCompletionContext_ObjCPropertyAccess)
lines << QLatin1String("'. Objective-C property access'");
if (contexts & CXCompletionContext_EnumTag)
lines << QLatin1String("'enum tag'");
if (contexts & CXCompletionContext_UnionTag)
lines << QLatin1String("'union tag'");
if (contexts & CXCompletionContext_StructTag)
lines << QLatin1String("'struct tag'");
if (contexts & CXCompletionContext_ClassTag)
lines << QLatin1String("'C++ class tag'");
if (contexts & CXCompletionContext_Namespace)
lines << QLatin1String("'namespace tag'");
if (contexts & CXCompletionContext_NestedNameSpecifier)
lines << QLatin1String("'C++ nested name specifier'");
if (contexts & CXCompletionContext_ObjCInterface)
lines << QLatin1String("'Objective-C interface'");
if (contexts & CXCompletionContext_ObjCProtocol)
lines << QLatin1String("'Objective-C protocol'");
if (contexts & CXCompletionContext_ObjCCategory)
lines << QLatin1String("'Objective-C category'");
if (contexts & CXCompletionContext_ObjCInstanceMessage)
lines << QLatin1String("'Objective-C instance message'");
if (contexts & CXCompletionContext_ObjCClassMessage)
lines << QLatin1String("'Objective-C class message'");
if (contexts & CXCompletionContext_ObjCSelectorName)
lines << QLatin1String("'Objective-C selector name'");
if (contexts & CXCompletionContext_MacroName)
lines << QLatin1String("'macro name'");
if (contexts & CXCompletionContext_NaturalLanguage)
lines << QLatin1String("'natural language'");
foreach (const QString &line, lines) {
writeLineEnd();
m_printed += line + QLatin1Char(',');
}
}
void CXPrettyPrinter::writeCompletionStringJson(const CXCompletionString &string)
{
m_printed += QLatin1Char('{');
writeLineEnd();
// availability
m_printed += QLatin1String("availability: ");
m_printed += toString(clang_getCompletionAvailability(string));
m_printed += QLatin1Char(';');
writeLineEnd();
// priority
m_printed += QLatin1String("priority: ");
m_printed += QString::number(clang_getCompletionPriority(string));
m_printed += QLatin1Char(';');
writeLineEnd();
// parent
m_printed += QLatin1String("parent: \'");
m_printed += getQString(clang_getCompletionParent(string, NULL));
m_printed += QLatin1String("\';");
writeLineEnd();
// chunks
m_printed += QLatin1String("chunks: [");
m_indent += 4;
unsigned numChunks = clang_getNumCompletionChunks(string);
for (unsigned i = 0; i < numChunks; ++i) {
writeLineEnd();
writeCompletionChunkJson(string, i);
}
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char(']');
writeLineEnd();
// annotation
m_printed += QLatin1String("annotations: [");
m_indent += 4;
unsigned numAnns = clang_getCompletionNumAnnotations(string);
for (unsigned i = 0; i < numAnns; ++i) {
writeLineEnd();
writeCompletionAnnotationJson(string, i);
}
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char(']');
writeLineEnd();
m_printed += QLatin1Char('}');
}
void CXPrettyPrinter::writeCompletionChunkJson(const CXCompletionString &string, unsigned i)
{
QString text = getQString(clang_getCompletionChunkText(string, i));
QString kind = toString(clang_getCompletionChunkKind(string, i));
CXCompletionString optional = clang_getCompletionChunkCompletionString(string, i);
m_printed += kind;
m_printed += QLatin1String(": ");
if (!text.isEmpty()) {
m_printed += QLatin1Char('\'');
m_printed += text;
m_printed += QLatin1Char('\'');
}
if (optional != NULL) {
if (!text.isEmpty())
m_printed += QLatin1String(", ");
m_indent += 4;
writeCompletionStringJson(optional);
m_indent -= 4;
}
}
void CXPrettyPrinter::writeCompletionAnnotationJson(const CXCompletionString &string, unsigned i)
{
m_printed += QLatin1Char('\'');
m_printed += getQString(clang_getCompletionAnnotation(string, i));
m_printed += QLatin1Char('\'');
}
void CXPrettyPrinter::writeDiagnosticJson(const CXDiagnostic &diag)
{
m_printed += QLatin1Char('{');
m_indent += 4;
writeLineEnd();
// message
m_printed += QLatin1Char('\'');
m_printed += getQString(clang_formatDiagnostic(diag, /*options*/ 0));
m_printed += QLatin1Char('\'');
writeLineEnd();
// severity
m_printed += QLatin1String("severity: ");
m_printed += toString(clang_getDiagnosticSeverity(diag));
writeLineEnd();
// location
m_printed += QLatin1String("location: ");
writeLocationJson(clang_getDiagnosticLocation(diag));
writeLineEnd();
// fix-its
unsigned numFixIts = clang_getDiagnosticNumFixIts(diag);
if (numFixIts > 0) {
m_printed += QLatin1String("FixIts: [");
writeLineEnd();
for (unsigned i = 0; i < numFixIts; ++i) {
writeFixItJson(diag, i);
writeLineEnd();
}
m_printed += QLatin1Char(']');
writeLineEnd();
}
// clang CLI options
CXString cxDisabler;
QString enabler = getQString(clang_getDiagnosticOption(diag, &cxDisabler));
QString disabler = getQString(cxDisabler);
if (!enabler.isEmpty()) {
m_printed += QLatin1String("enabledBy: \'");
m_printed += enabler;
m_printed += QLatin1String("';");
writeLineEnd();
}
if (!disabler.isEmpty()) {
m_printed += QLatin1String("disabledBy: \'");
m_printed += disabler;
m_printed += QLatin1String("';");
writeLineEnd();
}
// diagnostic category
m_printed += QLatin1String("category: \'");
m_printed += getQString(clang_getDiagnosticCategoryText(diag));
m_printed += QLatin1String("';");
// ranges
unsigned numRanges = clang_getDiagnosticNumRanges(diag);
if (numRanges > 0) {
writeLineEnd();
m_printed += QLatin1String("ranges: [");
m_indent += 4;
for (unsigned i = 0; i < numRanges; ++i) {
writeLineEnd();
writeRangeJson(clang_getDiagnosticRange(diag, i));
}
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char(']');
}
// children
CXDiagnosticSet set(clang_getChildDiagnostics(diag));
unsigned numChildren = clang_getNumDiagnosticsInSet(set);
if (numChildren > 0) {
writeLineEnd();
m_printed += QLatin1String("children: [");
m_indent += 4;
for (unsigned i = 0; i < numChildren; ++i) {
writeLineEnd();
ScopedCXDiagnostic child(clang_getDiagnosticInSet(set, i));
writeDiagnosticJson(child);
}
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char(']');
}
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char('}');
}
void CXPrettyPrinter::writeFixItJson(const CXDiagnostic &diag, unsigned i)
{
CXSourceRange range; // half-open range [a, b)
QString text = getQString(clang_getDiagnosticFixIt(diag, i, &range));
m_printed += QLatin1String("{ newText: ");
m_printed += QLatin1String("\'");
m_printed += text;
m_printed += QLatin1String("\', range: ");
writeRangeJson(range);
m_printed += QLatin1Char('}');
}
void CXPrettyPrinter::writeRangeJson(const CXSourceRange &range)
{
SourceLocation start = getSpellingLocation(clang_getRangeStart(range));
SourceLocation end = getSpellingLocation(clang_getRangeEnd(range));
m_printed += QLatin1Char('{');
m_indent += 4;
writeLineEnd();
m_printed += QLatin1String("file: \'");
m_printed += start.fileName();
m_printed += QLatin1String("\',");
writeLineEnd();
m_printed += QLatin1String("from: {");
m_printed += QString::number(start.line());
m_printed += QLatin1String(", ");
m_printed += QString::number(start.column());
m_printed += QLatin1String("},");
m_printed += QLatin1String("to: {");
m_printed += QString::number(end.line());
m_printed += QLatin1String(", ");
m_printed += QString::number(end.column());
m_printed += QLatin1Char('}');
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char('}');
}
void CXPrettyPrinter::writeLocationJson(const CXSourceLocation &location)
{
SourceLocation loc = getSpellingLocation(location);
m_printed += QLatin1Char('{');
m_indent += 4;
writeLineEnd();
m_printed += QLatin1String("file: \'");
m_printed += loc.fileName();
m_printed += QLatin1String("\',");
writeLineEnd();
m_printed += QLatin1String("line: ");
m_printed += QString::number(loc.line());
m_printed += QLatin1Char(',');
writeLineEnd();
m_printed += QLatin1String("column: ");
m_printed += QString::number(loc.column());
m_indent -= 4;
writeLineEnd();
m_printed += QLatin1Char('}');
}
void CXPrettyPrinter::writeLineEnd()
{
m_printed += QLatin1Char('\n');
for (int i = 0; i < m_indent; ++i)
m_printed += QLatin1Char(' ');
}

View File

@@ -1,76 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CXPRETTYPRINTER_H
#define CXPRETTYPRINTER_H
#include <clang-c/Index.h>
#include <QString>
namespace ClangCodeModel {
namespace Internal {
class CXPrettyPrinter
{
public:
CXPrettyPrinter();
QString toString(CXCompletionChunkKind kind) const;
QString toString(CXAvailabilityKind kind) const;
QString toString(CXCursorKind kind) const;
QString toString(CXDiagnosticSeverity severity) const;
QString jsonForCompletionMeta(CXCodeCompleteResults *results);
QString jsonForCompletionString(const CXCompletionString &string);
QString jsonForCompletion(const CXCompletionResult &result);
QString jsonForDiagnsotic(const CXDiagnostic &diagnostic);
private:
int m_indent;
QString m_printed;
void writeCompletionContexts(CXCodeCompleteResults *results);
void writeCompletionStringJson(const CXCompletionString &string);
void writeCompletionChunkJson(const CXCompletionString &string, unsigned i);
void writeCompletionAnnotationJson(const CXCompletionString &string, unsigned i);
void writeDiagnosticJson(const CXDiagnostic &diag);
void writeFixItJson(const CXDiagnostic &diag, unsigned i);
void writeRangeJson(const CXSourceRange &range);
void writeLocationJson(const CXSourceLocation &location);
void writeLineEnd();
};
} // namespace Internal
} // namespace ClangCodeModel
#endif // CXPRETTYPRINTER_H

View File

@@ -1,146 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CXRAII_H
#define CXRAII_H
#include <clang-c/Index.h>
// Simple RAII types for their CX correspondings
namespace ClangCodeModel {
namespace Internal {
template <class CXType_T>
struct ScopedCXType
{
protected:
typedef void (*DisposeFunction)(CXType_T);
ScopedCXType(DisposeFunction f)
: m_cx(0), m_disposeFunction(f)
{}
ScopedCXType(const CXType_T &cx, DisposeFunction f)
: m_cx(cx) , m_disposeFunction(f)
{}
public:
~ScopedCXType()
{
dispose();
}
operator CXType_T() const { return m_cx; }
bool operator!() const { return !m_cx; }
bool isNull() const { return !m_cx; }
void reset(const CXType_T &cx)
{
dispose();
m_cx = cx;
}
private:
ScopedCXType(const ScopedCXType &);
const ScopedCXType &operator=(const ScopedCXType &);
void dispose()
{
if (m_cx)
m_disposeFunction(m_cx);
}
CXType_T m_cx;
DisposeFunction m_disposeFunction;
};
struct ScopedCXIndex : ScopedCXType<CXIndex>
{
ScopedCXIndex()
: ScopedCXType<CXIndex>(&clang_disposeIndex)
{}
ScopedCXIndex(const CXIndex &index)
: ScopedCXType<CXIndex>(index, &clang_disposeIndex)
{}
};
struct ScopedCXTranslationUnit : ScopedCXType<CXTranslationUnit>
{
ScopedCXTranslationUnit()
: ScopedCXType<CXTranslationUnit>(&clang_disposeTranslationUnit)
{}
ScopedCXTranslationUnit(const CXTranslationUnit &unit)
: ScopedCXType<CXTranslationUnit>(unit, &clang_disposeTranslationUnit)
{}
};
struct ScopedCXDiagnostic : ScopedCXType<CXDiagnostic>
{
ScopedCXDiagnostic()
: ScopedCXType<CXDiagnostic>(&clang_disposeDiagnostic)
{}
ScopedCXDiagnostic(const CXDiagnostic &diagnostic)
: ScopedCXType<CXDiagnostic>(diagnostic, &clang_disposeDiagnostic)
{}
};
struct ScopedCXDiagnosticSet : ScopedCXType<CXDiagnostic>
{
ScopedCXDiagnosticSet()
: ScopedCXType<CXDiagnosticSet>(&clang_disposeDiagnosticSet)
{}
ScopedCXDiagnosticSet(const CXDiagnostic &diagnostic)
: ScopedCXType<CXDiagnosticSet>(diagnostic, &clang_disposeDiagnosticSet)
{}
};
struct ScopedCXCodeCompleteResults : ScopedCXType<CXCodeCompleteResults*>
{
ScopedCXCodeCompleteResults()
: ScopedCXType<CXCodeCompleteResults*>(&clang_disposeCodeCompleteResults)
{}
ScopedCXCodeCompleteResults(CXCodeCompleteResults *results)
: ScopedCXType<CXCodeCompleteResults*>(results, &clang_disposeCodeCompleteResults)
{}
unsigned size() const
{
return static_cast<CXCodeCompleteResults *>(*this)->NumResults;
}
const CXCompletionResult &completionAt(unsigned i)
{
return static_cast<CXCodeCompleteResults *>(*this)->Results[i];
}
};
} // Internal
} // ClangCodeModel
#endif // CXRAII_H

View File

@@ -1,209 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "dependencygraph.h"
#include <QtCore/QtConcurrentRun>
using namespace ClangCodeModel;
using namespace Internal;
DependencyGraph::DependencyGraph()
{
m_includeTracker.setResolutionMode(IncludeTracker::EveryMatchResolution);
}
DependencyGraph::~DependencyGraph()
{
discard();
}
void DependencyGraph::cancel()
{
if (m_computeWatcher.isRunning()) {
m_computeWatcher.cancel();
m_computeWatcher.waitForFinished();
}
}
void DependencyGraph::addFile(const QString &fileName, const QStringList &compilationOptions)
{
cancel();
m_files.append(qMakePair(fileName, compilationOptions));
}
QFuture<void> DependencyGraph::compute()
{
QFuture<void> future = QtConcurrent::run(this, &DependencyGraph::computeCore);
m_computeWatcher.setFuture(future);
return future;
}
void DependencyGraph::computeCore()
{
for (int i = 0; i < m_files.size(); ++i) {
if (m_computeWatcher.isCanceled())
break;
const QPair<QString, QStringList> &p = m_files.at(i);
const QString &currentFile = p.first;
const QStringList &options = p.second;
const QPair<bool, NodeRefSetIt> &v = findVertex(currentFile);
if (!v.first)
processIncludes(insertVertex(currentFile), options);
}
emit dependencyGraphAvailable();
}
void DependencyGraph::processIncludes(NodeRefSetIt currentIt,
const QStringList &compilationOptions)
{
const QString &currentFile = currentIt.key();
const QStringList &includes = m_includeTracker.directIncludes(currentFile, compilationOptions);
foreach (const QString &include, includes) {
if (m_computeWatcher.isCanceled())
return;
QPair<bool, NodeRefSetIt> v = findVertex(include);
if (!v.first) {
v.second = insertVertex(include);
processIncludes(v.second, compilationOptions);
}
insertEdge(currentIt, v.second);
}
}
namespace {
struct SimpleVisitor
{
bool acceptFile(const QString &fileName)
{
m_allFiles.append(fileName);
return false;
}
QStringList m_allFiles;
};
}
QStringList DependencyGraph::collectDependencies(const QString &referenceFile,
DependencyRole role) const
{
SimpleVisitor visitor;
collectDependencies(referenceFile, role, &visitor);
return visitor.m_allFiles;
}
bool DependencyGraph::hasDependency(const QString &referenceFile, DependencyRole role) const
{
QPair<bool, NodeRefSetIt> v = findVertex(referenceFile);
if (!v.first)
return false;
NodeListIt nodeIt = v.second.value();
if (role == FilesDirectlyIncludedBy || role == FilesIncludedBy)
return nodeIt->m_out != 0;
return nodeIt->m_in != 0;
}
void DependencyGraph::discard()
{
cancel();
for (NodeListIt it = m_nodes.begin(); it != m_nodes.end(); ++it) {
deleteAdjacencies(it->m_out);
deleteAdjacencies(it->m_in);
}
m_nodes.clear();
m_nodesRefs.clear();
m_files.clear();
}
DependencyGraph::Node::Node(const QString &fileName)
: m_fileName(fileName)
, m_out(0)
, m_in(0)
{}
DependencyGraph::AdjacencyNode::AdjacencyNode(NodeListIt it)
: m_next(0)
, m_nodeIt(it)
{}
QPair<bool, DependencyGraph::NodeRefSetIt> DependencyGraph::findVertex(const QString &s) const
{
bool found = false;
NodeRefSetIt it = const_cast<NodeRefSet &>(m_nodesRefs).find(s);
if (it != m_nodesRefs.end())
found = true;
return qMakePair(found, it);
}
DependencyGraph::NodeRefSetIt DependencyGraph::insertVertex(const QString &s)
{
Q_ASSERT(m_nodesRefs.find(s) == m_nodesRefs.end());
m_nodes.append(Node(s));
return m_nodesRefs.insert(s, m_nodes.end() - 1);
}
void DependencyGraph::insertEdge(DependencyGraph::NodeRefSetIt fromIt,
DependencyGraph::NodeRefSetIt toIt)
{
NodeListIt nodeFromIt = fromIt.value();
NodeListIt nodeToIt = toIt.value();
createAdjacency(&nodeFromIt->m_out, new AdjacencyNode(nodeToIt));
createAdjacency(&nodeToIt->m_in, new AdjacencyNode(nodeFromIt));
}
void DependencyGraph::deleteAdjacencies(AdjacencyNode *node)
{
while (node) {
AdjacencyNode *next = node->m_next;
delete node;
node = next;
}
}
void DependencyGraph::createAdjacency(AdjacencyNode **node, AdjacencyNode *newNode)
{
if (*node)
newNode->m_next = *node;
*node = newNode;
}

View File

@@ -1,236 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef DEPENDENCYGRAPH_H
#define DEPENDENCYGRAPH_H
#include "includetracker.h"
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QLinkedList>
#include <QtCore/QHash>
#include <QtCore/QPair>
#include <QtCore/QQueue>
#include <QtCore/QFuture>
#include <QtCore/QFutureWatcher>
#include <QtCore/QDebug>
namespace ClangCodeModel {
namespace Internal {
class DependencyGraph : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(DependencyGraph)
public:
DependencyGraph();
~DependencyGraph();
void addFile(const QString &fileName, const QStringList &compilationOptions);
QFuture<void> compute();
enum DependencyRole
{
FilesDirectlyIncludedBy, // Only direct inclusions
FilesIncludedBy, // Both direct and indirect inclusions
FilesWhichDirectlyInclude, // This one is directly included from...
FilesWhichInclude // This one is directly or indirectly included from...
};
/*
* You should use this version if you simply want all the dependencies, no matter what.
*/
QStringList collectDependencies(const QString &referenceFile, DependencyRole role) const;
/*
* You should use this version if you might be interested on a particular dependency
* and don't want to continue the search once you have found it. In this case you need
* supply a visitor. Currently the visitor concept simply requires that a type Visitor_T
* models a function that will receive a file string s and indicate whether or not to
* continue:
*
* Visitor_T().acceptFile(s) must be a valid expression.
*
*/
template <class Visitor_T>
void collectDependencies(const QString &referenceFile,
DependencyRole role,
Visitor_T *visitor) const;
bool hasDependency(const QString &referenceFile, DependencyRole role) const;
void discard();
signals:
void dependencyGraphAvailable();
private:
QList<QPair<QString, QStringList> > m_files;
IncludeTracker m_includeTracker;
QFutureWatcher<void> m_computeWatcher;
void cancel();
void computeCore();
// The dependency graph is represent as an adjacency list. The vertices contains
// a list of *out* edges and a list of *in* edges. Each vertex corresponds to a file.
// Its out edges correspond to the files which get directly included by this one, while
// its in edges correspond to files that directly include this one.
//
// For better space efficiency, the adjacency nodes doen't explicitly store the file
// names themselves, but rather an iterator to the corresponding vertex. In addition,
// for speed efficiency we keep track of a hash table that contains iterators to the
// actual vertex storage container, which actually contains the strings for the file
// names. The vertex container itself is a linked list, it has the semantics we need,
// in particular regarding iterator invalidation.
struct AdjacencyNode;
struct Node
{
Node(const QString &fileName);
QString m_fileName;
AdjacencyNode *m_out;
AdjacencyNode *m_in;
};
typedef QLinkedList<Node> NodeList;
typedef NodeList::iterator NodeListIt;
typedef QHash<QString, NodeListIt> NodeRefSet;
typedef NodeRefSet::iterator NodeRefSetIt;
struct AdjacencyNode
{
AdjacencyNode(NodeListIt it);
AdjacencyNode *m_next;
NodeListIt m_nodeIt;
};
void processIncludes(NodeRefSetIt currentFileIt,
const QStringList &compilationOptions);
template <class Visitor_T>
void collectFilesBFS(NodeListIt nodeIt, DependencyRole role, Visitor_T *visitor) const;
// Core graph operations and data
QPair<bool, NodeRefSetIt> findVertex(const QString &s) const;
NodeRefSetIt insertVertex(const QString &s);
void insertEdge(NodeRefSetIt fromIt, NodeRefSetIt toIt);
void deleteAdjacencies(AdjacencyNode *node);
void createAdjacency(AdjacencyNode **node, AdjacencyNode *newNode);
NodeList m_nodes;
NodeRefSet m_nodesRefs;
};
template <class Visitor_T>
void DependencyGraph::collectDependencies(const QString &referenceFile,
DependencyRole role,
Visitor_T *visitor) const
{
if (m_computeWatcher.isRunning())
return;
QPair<bool, NodeRefSetIt> v = findVertex(referenceFile);
if (!v.first)
return;
NodeListIt nodeIt = v.second.value();
if (role == FilesDirectlyIncludedBy || role == FilesWhichDirectlyInclude) {
AdjacencyNode *adj;
if (role == FilesDirectlyIncludedBy)
adj = nodeIt->m_out;
else
adj = nodeIt->m_in;
for (; adj; adj = adj->m_next) {
NodeListIt dependentIt = adj->m_nodeIt;
if (visitor->acceptFile(dependentIt->m_fileName))
return;
}
} else {
collectFilesBFS(nodeIt, role, visitor);
}
}
template <class Visitor_T>
void DependencyGraph::collectFilesBFS(NodeListIt nodeIt,
DependencyRole role,
Visitor_T *visitor) const
{
Q_ASSERT(role == FilesIncludedBy || role == FilesWhichInclude);
if (m_computeWatcher.isRunning())
return;
QQueue<NodeListIt> q;
q.enqueue(nodeIt);
QSet<QString> visited;
visited.insert(nodeIt->m_fileName);
while (!q.isEmpty()) {
NodeListIt currentIt = q.dequeue();
AdjacencyNode *adj;
if (role == FilesIncludedBy)
adj = currentIt->m_out;
else
adj = currentIt->m_in;
while (adj) {
NodeListIt adjNodeIt = adj->m_nodeIt;
adj = adj->m_next;
const QString &adjFileName = adjNodeIt->m_fileName;
if (visited.contains(adjFileName))
continue;
if (visitor->acceptFile(adjFileName))
return;
visited.insert(adjFileName);
q.enqueue(adjNodeIt);
}
}
}
} // Internal
} // ClangCodeModel
#endif // DEPENDENCYGRAPH_H

View File

@@ -1,64 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "diagnostic.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
using namespace ClangCodeModel;
Diagnostic::Diagnostic()
: m_severity(Unknown)
, m_length(0)
{}
Diagnostic::Diagnostic(Severity severity, const SourceLocation &location, unsigned length, const QString &spelling)
: m_severity(severity)
, m_loc(location)
, m_length(length)
, m_spelling(spelling)
{}
const QString Diagnostic::severityAsString() const
{
if (m_severity == Unknown)
return QString();
static QStringList strs = QStringList()
<< QCoreApplication::translate("ClangCodeModel::Diagnostic", "ignored")
<< QCoreApplication::translate("ClangCodeModel::Diagnostic", "note")
<< QCoreApplication::translate("ClangCodeModel::Diagnostic", "warning")
<< QCoreApplication::translate("ClangCodeModel::Diagnostic", "error")
<< QCoreApplication::translate("ClangCodeModel::Diagnostic", "fatal")
;
return strs.at(m_severity);
}

View File

@@ -1,83 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANG_DIAGNOSTIC_H
#define CLANG_DIAGNOSTIC_H
#include "clang_global.h"
#include "sourcelocation.h"
#include <QMetaType>
namespace ClangCodeModel {
class CLANG_EXPORT Diagnostic
{
public:
enum Severity {
Unknown = -1,
Ignored = 0,
Note = 1,
Warning = 2,
Error = 3,
Fatal = 4
};
public:
Diagnostic();
Diagnostic(Severity severity, const SourceLocation &location, unsigned length, const QString &spelling);
Severity severity() const
{ return m_severity; }
const QString severityAsString() const;
const SourceLocation &location() const
{ return m_loc; }
unsigned length() const
{ return m_length; }
const QString &spelling() const
{ return m_spelling; }
private:
Severity m_severity;
SourceLocation m_loc;
unsigned m_length;
QString m_spelling;
};
} // namespace ClangCodeModel
Q_DECLARE_METATYPE(ClangCodeModel::Diagnostic)
Q_DECLARE_METATYPE(QList<ClangCodeModel::Diagnostic>)
#endif // CLANG_DIAGNOSTIC_H

View File

@@ -1,37 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "fastindexer.h"
using namespace ClangCodeModel::Internal;
FastIndexer::~FastIndexer()
{
}

View File

@@ -1,491 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "index.h"
#include <QStringList>
#include <QLinkedList>
#include <QHash>
#include <QDataStream>
#include <QPair>
#include <QFileInfo>
#include <QMutex>
#include <QMutexLocker>
namespace ClangCodeModel {
namespace Internal {
class ClangSymbolSearcher;
class IndexPrivate
{
public:
IndexPrivate();
void insertSymbol(const Symbol &symbol, const QDateTime &timeStamp);
QList<Symbol> symbols(const QString &fileName) const;
QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind) const;
QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind, const QString &uqName) const;
QList<Symbol> symbols(const QString &fileName, const QString &uqName) const;
QList<Symbol> symbols(Symbol::Kind kind) const;
void match(ClangSymbolSearcher *searcher) const;
void insertFile(const QString &fileName, const QDateTime &timeStamp);
void removeFile(const QString &fileName);
void removeFiles(const QStringList &fileNames);
bool containsFile(const QString &fileName) const;
QStringList files() const;
void clear();
bool isEmpty() const;
void trackTimeStamp(const Symbol &symbol, const QDateTime &timeStamp);
void trackTimeStamp(const QString &fileName, const QDateTime &timeStamp);
bool validate(const QString &fileName) const;
QByteArray serialize() const;
void deserialize(const QByteArray &data);
private:
typedef QLinkedList<Symbol> SymbolCont;
typedef SymbolCont::iterator SymbolIt;
typedef QHash<QString, QList<SymbolIt> > NameIndex;
typedef QHash<Symbol::Kind, NameIndex> KindIndex;
typedef QHash<QString, KindIndex> FileIndex;
typedef QList<SymbolIt>::iterator SymbolIndexIt;
typedef NameIndex::iterator NameIndexIt;
typedef KindIndex::iterator KindIndexIt;
typedef FileIndex::iterator FileIndexIt;
typedef FileIndex::const_iterator FileIndexCIt;
void insertSymbol(const Symbol &symbol);
void removeSymbol(SymbolIndexIt it);
QPair<bool, SymbolIndexIt> findEquivalentSymbol(const Symbol &symbol);
void updateEquivalentSymbol(SymbolIndexIt it, const Symbol &symbol);
void createIndexes(SymbolIt it);
QList<SymbolIt> removeIndexes(const QString &fileName);
static QList<Symbol> symbolsFromIterators(const QList<SymbolIt> &symbolList);
// @TODO: Sharing of compilation options...
mutable QMutex m_mutex;
SymbolCont m_container;
FileIndex m_files;
QHash<QString, QDateTime> m_timeStamps;
};
} // namespace Internal
} // namespace ClangCodeModel
using namespace ClangCodeModel;
using namespace Internal;
IndexPrivate::IndexPrivate()
: m_mutex(QMutex::Recursive)
{
}
void IndexPrivate::createIndexes(SymbolIt it)
{
m_files[it->m_location.fileName()][it->m_kind][it->m_name].append(it);
}
QList<QLinkedList<Symbol>::iterator> IndexPrivate::removeIndexes(const QString &fileName)
{
QList<SymbolIt> iterators;
KindIndex kindIndex = m_files.take(fileName);
KindIndexIt it = kindIndex.begin();
KindIndexIt eit = kindIndex.end();
for (; it != eit; ++it) {
NameIndex nameIndex = *it;
NameIndexIt nit = nameIndex.begin();
NameIndexIt neit = nameIndex.end();
for (; nit != neit; ++nit)
iterators.append(*nit);
}
return iterators;
}
void IndexPrivate::insertSymbol(const Symbol &symbol)
{
QMutexLocker locker(&m_mutex);
SymbolIt it = m_container.insert(m_container.begin(), symbol);
createIndexes(it);
}
void IndexPrivate::insertSymbol(const Symbol &symbol, const QDateTime &timeStamp)
{
const QPair<bool, SymbolIndexIt> &find = findEquivalentSymbol(symbol);
if (find.first)
updateEquivalentSymbol(find.second, symbol);
else
insertSymbol(symbol);
trackTimeStamp(symbol, timeStamp);
}
QPair<bool, IndexPrivate::SymbolIndexIt> IndexPrivate::findEquivalentSymbol(const Symbol &symbol)
{
// Despite the loop below finding a symbol should be efficient, since we already filter
// the file name, the kind, and the qualified name through the indexing mechanism. In many
// cases it will iterate only once.
QList<SymbolIt> &byName = m_files[symbol.m_location.fileName()][symbol.m_kind][symbol.m_name];
for (SymbolIndexIt it = byName.begin(); it != byName.end(); ++it) {
const Symbol &candidateSymbol = *(*it);
// @TODO: Overloads, template specializations
if (candidateSymbol.m_qualification == symbol.m_qualification)
return qMakePair(true, it);
}
return qMakePair(false, QList<SymbolIt>::iterator());
}
void IndexPrivate::updateEquivalentSymbol(SymbolIndexIt it, const Symbol &symbol)
{
SymbolIt symbolIt = *it;
Q_ASSERT(symbolIt->m_kind == symbol.m_kind);
Q_ASSERT(symbolIt->m_qualification == symbol.m_qualification);
Q_ASSERT(symbolIt->m_name == symbol.m_name);
Q_ASSERT(symbolIt->m_location.fileName() == symbol.m_location.fileName());
symbolIt->m_location = symbol.m_location;
}
void IndexPrivate::removeSymbol(SymbolIndexIt it)
{
SymbolIt symbolIt = *it;
m_container.erase(symbolIt);
KindIndex &kindIndex = m_files[symbolIt->m_location.fileName()];
NameIndex &nameIndex = kindIndex[symbolIt->m_kind];
QList<SymbolIt> &byName = nameIndex[symbolIt->m_name];
byName.erase(it);
if (byName.isEmpty()) {
nameIndex.remove(symbolIt->m_name);
if (nameIndex.isEmpty()) {
kindIndex.remove(symbolIt->m_kind);
if (kindIndex.isEmpty())
m_files.remove(symbolIt->m_location.fileName());
}
}
}
QList<Symbol> IndexPrivate::symbols(const QString &fileName) const
{
QMutexLocker locker(&m_mutex);
QList<Symbol> all;
const QList<NameIndex> &byKind = m_files.value(fileName).values();
foreach (const NameIndex &nameIndex, byKind) {
const QList<QList<SymbolIt> > &byName = nameIndex.values();
foreach (const QList<SymbolIt> &symbols, byName)
all.append(symbolsFromIterators(symbols));
}
return all;
}
QList<Symbol> IndexPrivate::symbols(const QString &fileName, Symbol::Kind kind) const
{
QMutexLocker locker(&m_mutex);
QList<Symbol> all;
const QList<QList<SymbolIt> > &byName = m_files.value(fileName).value(kind).values();
foreach (const QList<SymbolIt> &symbols, byName)
all.append(symbolsFromIterators(symbols));
return all;
}
QList<Symbol> IndexPrivate::symbols(const QString &fileName,
Symbol::Kind kind,
const QString &uqName) const
{
QMutexLocker locker(&m_mutex);
return symbolsFromIterators(m_files.value(fileName).value(kind).value(uqName));
}
QList<Symbol> IndexPrivate::symbols(Symbol::Kind kind) const
{
QMutexLocker locker(&m_mutex);
QList<Symbol> all;
FileIndexCIt it = m_files.begin();
FileIndexCIt eit = m_files.end();
for (; it != eit; ++it)
all.append(symbols(it.key(), kind));
return all;
}
void IndexPrivate::match(ClangSymbolSearcher *searcher) const
{
QMutexLocker locker(&m_mutex);
Q_UNUSED(searcher);
// searcher->search(m_container);
}
QList<Symbol> IndexPrivate::symbolsFromIterators(const QList<SymbolIt> &symbolList)
{
QList<Symbol> all;
foreach (SymbolIt symbolIt, symbolList)
all.append(*symbolIt);
return all;
}
void IndexPrivate::trackTimeStamp(const Symbol &symbol, const QDateTime &timeStamp)
{
QMutexLocker locker(&m_mutex);
trackTimeStamp(symbol.m_location.fileName(), timeStamp);
}
void IndexPrivate::trackTimeStamp(const QString &fileName, const QDateTime &timeStamp)
{
QMutexLocker locker(&m_mutex);
// We keep track of time stamps on a per file basis (most recent one).
m_timeStamps[fileName] = timeStamp;
}
bool IndexPrivate::validate(const QString &fileName) const
{
QMutexLocker locker(&m_mutex);
const QDateTime &timeStamp = m_timeStamps.value(fileName);
if (!timeStamp.isValid())
return false;
QFileInfo fileInfo(fileName);
if (fileInfo.lastModified() > timeStamp)
return false;
return true;
}
void IndexPrivate::insertFile(const QString &fileName, const QDateTime &timeStamp)
{
QMutexLocker locker(&m_mutex);
trackTimeStamp(fileName, timeStamp);
}
QStringList IndexPrivate::files() const
{
QMutexLocker locker(&m_mutex);
return m_timeStamps.keys();
}
bool IndexPrivate::containsFile(const QString &fileName) const
{
QMutexLocker locker(&m_mutex);
return m_timeStamps.contains(fileName);
}
void IndexPrivate::removeFile(const QString &fileName)
{
QMutexLocker locker(&m_mutex);
const QList<SymbolIt> &iterators = removeIndexes(fileName);
foreach (SymbolIt it, iterators)
m_container.erase(it);
m_timeStamps.remove(fileName);
}
void IndexPrivate::removeFiles(const QStringList &fileNames)
{
QMutexLocker locker(&m_mutex);
foreach (const QString &fileName, fileNames)
removeFile(fileName);
}
void IndexPrivate::clear()
{
QMutexLocker locker(&m_mutex);
m_container.clear();
m_files.clear();
m_timeStamps.clear();
}
bool IndexPrivate::isEmpty() const
{
QMutexLocker locker(&m_mutex);
return m_timeStamps.isEmpty();
}
QByteArray IndexPrivate::serialize() const
{
QMutexLocker locker(&m_mutex);
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << (quint32)0x0A0BFFEE;
stream << (quint16)1;
stream.setVersion(QDataStream::Qt_4_7);
stream << m_container;
stream << m_timeStamps;
return data;
}
void IndexPrivate::deserialize(const QByteArray &data)
{
QMutexLocker locker(&m_mutex);
clear();
// @TODO: Version compatibility handling.
QDataStream stream(data);
quint32 header;
stream >> header;
if (header != 0x0A0BFFEE)
return;
quint16 indexVersion;
stream >> indexVersion;
if (indexVersion != 1)
return;
stream.setVersion(QDataStream::Qt_4_7);
SymbolCont symbols;
stream >> symbols;
stream >> m_timeStamps;
// @TODO: Overload the related functions with batch versions.
foreach (const Symbol &symbol, symbols)
insertSymbol(symbol);
}
Index::Index()
: d(new IndexPrivate)
{}
Index::~Index()
{}
void Index::insertSymbol(const Symbol &symbol, const QDateTime &timeStamp)
{
d->insertSymbol(symbol, timeStamp);
}
QList<Symbol> Index::symbols(const QString &fileName) const
{
return d->symbols(fileName);
}
QList<Symbol> Index::symbols(const QString &fileName, Symbol::Kind kind) const
{
return d->symbols(fileName, kind);
}
QList<Symbol> Index::symbols(const QString &fileName, Symbol::Kind kind, const QString &uqName) const
{
return d->symbols(fileName, kind, uqName);
}
QList<Symbol> Index::symbols(Symbol::Kind kind) const
{
return d->symbols(kind);
}
void Index::match(ClangSymbolSearcher *searcher) const
{
d->match(searcher);
}
void Index::insertFile(const QString &fileName, const QDateTime &timeStamp)
{
d->insertFile(fileName, timeStamp);
}
QStringList Index::files() const
{
return d->files();
}
bool Index::containsFile(const QString &fileName) const
{
return d->containsFile(fileName);
}
void Index::removeFile(const QString &fileName)
{
d->removeFile(fileName);
}
void Index::removeFiles(const QStringList &fileNames)
{
d->removeFiles(fileNames);
}
void Index::clear()
{
d->clear();
}
bool Index::isEmpty() const
{
return d->isEmpty();
}
bool Index::validate(const QString &fileName) const
{
return d->validate(fileName);
}
QByteArray Index::serialize() const
{
return d->serialize();
}
void Index::deserialize(const QByteArray &data)
{
d->deserialize(data);
}

View File

@@ -1,88 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef INDEX_H
#define INDEX_H
#include "symbol.h"
#include <QtCore/QByteArray>
#include <QtCore/QString>
#include <QtCore/QList>
#include <QtCore/QScopedPointer>
#include <QtCore/QDateTime>
#include <QStringList>
namespace ClangCodeModel {
class Symbol;
namespace Internal {
class ClangSymbolSearcher;
class IndexPrivate;
class Index
{
public:
Index();
~Index();
void insertSymbol(const Symbol &symbol, const QDateTime &timeStamp);
QList<Symbol> symbols(const QString &fileName) const;
QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind) const;
QList<Symbol> symbols(const QString &fileName, Symbol::Kind kind, const QString &uqName) const;
QList<Symbol> symbols(Symbol::Kind kind) const;
void match(ClangSymbolSearcher *searcher) const;
void insertFile(const QString &fileName, const QDateTime &timeStamp);
void removeFile(const QString &fileName);
void removeFiles(const QStringList &fileNames);
bool containsFile(const QString &fileName) const;
QStringList files() const;
bool validate(const QString &fileName) const;
void clear();
bool isEmpty() const;
QByteArray serialize() const;
void deserialize(const QByteArray &data);
private:
QScopedPointer<IndexPrivate> d;
};
} // Internal
} // ClangCodeModel
#endif // INDEX_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,104 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef INDEXER_H
#define INDEXER_H
#include "clang_global.h"
#include "symbol.h"
#include "unit.h"
#include <cpptools/cppmodelmanager.h>
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QScopedPointer>
#include <QtCore/QFuture>
namespace ClangCodeModel {
namespace Internal { class ClangSymbolSearcher; }
class IndexerPrivate;
class CLANG_EXPORT Indexer : public QObject
{
Q_OBJECT
public:
typedef CppTools::ProjectPart ProjectPart;
public:
Indexer(QObject *parent = 0);
~Indexer();
void initialize(const QString &storagePath);
void finalize();
void regenerate();
void evaluateFile(const QString &fileName);
bool isBusy() const;
void cancel(bool waitForFinished);
bool addFile(const QString &fileName, ProjectPart::Ptr projectPart);
QStringList allFiles() const;
QStringList compilationOptions(const QString &fileName) const;
QList<Symbol> allFunctions() const;
QList<Symbol> allClasses() const;
QList<Symbol> allMethods() const;
QList<Symbol> allConstructors() const;
QList<Symbol> allDestructors() const;
QList<Symbol> functionsFromFile(const QString &fileName) const;
QList<Symbol> classesFromFile(const QString &fileName) const;
QList<Symbol> methodsFromFile(const QString &fileName) const;
QList<Symbol> constructorsFromFile(const QString &fileName) const;
QList<Symbol> destructorsFromFile(const QString &fileName) const;
QList<Symbol> allFromFile(const QString &fileName) const;
void match(Internal::ClangSymbolSearcher *searcher) const;
void runQuickIndexing(Internal::Unit::Ptr unit, const ProjectPart::Ptr &part);
bool isTracking(const QString &fileName) const;
signals:
void indexingStarted(QFuture<void> future);
void indexingFinished();
private:
friend class IndexerPrivate;
QScopedPointer<IndexerPrivate> m_d;
};
} // ClangCodeModel
#endif // INDEXER_H

View File

@@ -1,63 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "pchinfo.h"
#include <QDir>
using namespace ClangCodeModel::Internal;
PchInfo::PchInfo()
{
}
PchInfo::~PchInfo()
{
}
PchInfo::Ptr PchInfo::createEmpty()
{
return Ptr(new PchInfo);
}
PchInfo::Ptr PchInfo::createWithFileName(const QString &inputFileName,
const QStringList &options,
bool objcEnabled)
{
Ptr result(new PchInfo);
result->m_inputFileName = inputFileName;
result->m_options = options;
result->m_objcEnabled = objcEnabled;
// The next 2 lines are just here to generate the file name....
result->m_file.open();
result->m_file.close();
return result;
}

View File

@@ -1,81 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef PCHINFO_H
#define PCHINFO_H
#include <QString>
#include <QStringList>
#include <QSharedPointer>
#include <QTemporaryFile>
namespace ClangCodeModel {
namespace Internal {
class PchInfo
{
PchInfo();
public:
typedef QSharedPointer<PchInfo> Ptr;
public:
~PchInfo();
static Ptr createEmpty();
static Ptr createWithFileName(const QString &inputFileName,
const QStringList &options, bool objcEnabled);
/// \return the (temporary) file name for the PCH file.
QString fileName() const
{ return m_file.fileName(); }
/// \return the input file for the PCH compilation.
QString inputFileName() const
{ return m_inputFileName; }
/// \return the options used to generate this PCH file.
QStringList options() const
{ return m_options; }
bool objcWasEnabled() const
{ return m_objcEnabled; }
private:
QString m_inputFileName;
QStringList m_options;
bool m_objcEnabled;
QTemporaryFile m_file;
};
} // Internal namespace
} // ClangCodeModel namespace
#endif // PCHINFO_H

View File

@@ -1,448 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "pchmanager.h"
#include "utils.h"
#include "clangutils.h"
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
#include <QFile>
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
using namespace CPlusPlus;
PchManager *PchManager::m_instance = 0;
PchManager::PchManager(QObject *parent)
: QObject(parent)
{
Q_ASSERT(!m_instance);
m_instance = this;
QObject *msgMgr = Core::MessageManager::instance();
connect(this, SIGNAL(pchMessage(QString,Core::MessageManager::PrintToOutputPaneFlags)),
msgMgr, SLOT(write(QString,Core::MessageManager::PrintToOutputPaneFlags)));
connect(&m_pchGenerationWatcher, SIGNAL(finished()),
this, SLOT(updateActivePchFiles()));
}
PchManager::~PchManager()
{
Q_ASSERT(m_instance);
m_instance = 0;
qDeleteAll(m_projectSettings.values());
m_projectSettings.clear();
}
PchManager *PchManager::instance()
{
return m_instance;
}
PchInfo::Ptr PchManager::pchInfo(const ProjectPart::Ptr &projectPart) const
{
QMutexLocker locker(&m_mutex);
return m_activePchFiles[projectPart];
}
ClangProjectSettings *PchManager::settingsForProject(ProjectExplorer::Project *project)
{
QMutexLocker locker(&m_mutex);
ClangProjectSettings *cps = m_projectSettings.value(project);
if (!cps) {
cps = new ClangProjectSettings(project);
m_projectSettings.insert(project, cps);
cps->pullSettings();
connect(cps, SIGNAL(pchSettingsChanged()),
this, SLOT(clangProjectSettingsChanged()));
}
return cps;
}
void PchManager::setPCHInfo(const QList<ProjectPart::Ptr> &projectParts,
const PchInfo::Ptr &pchInfo,
const QPair<bool, QStringList> &msgs)
{
QMutexLocker locker(&m_mutex);
foreach (ProjectPart::Ptr pPart, projectParts)
m_activePchFiles[pPart] = pchInfo;
if (pchInfo) {
if (msgs.first) {
if (!pchInfo->fileName().isEmpty())
emit pchMessage(tr("Successfully generated PCH file \"%1\".").arg(
pchInfo->fileName()), Core::MessageManager::Silent);
} else {
emit pchMessage(tr("Failed to generate PCH file \"%1\".").arg(
pchInfo->fileName()), Core::MessageManager::Silent);
}
if (!msgs.second.isEmpty())
emit pchMessage(msgs.second.join(QLatin1Char('\n')), Core::MessageManager::Flash);
}
}
void PchManager::clangProjectSettingsChanged()
{
ClangProjectSettings *cps = qobject_cast<ClangProjectSettings *>(sender());
if (!cps)
return;
onProjectPartsUpdated(cps->project());
}
void PchManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
{
Q_UNUSED(project);
// we cannot ask the ModelManager for the parts, because, depending on
// the order of signal delivery, it might already have wiped any information
// about the project.
updateActivePchFiles();
}
void PchManager::onProjectPartsUpdated(ProjectExplorer::Project *project)
{
ClangProjectSettings *cps = settingsForProject(project);
Q_ASSERT(cps);
CppTools::CppModelManager *mmi = CppTools::CppModelManager::instance();
const QList<ProjectPart::Ptr> projectParts = mmi->projectInfo(
cps->project()).projectParts();
updatePchInfo(cps, projectParts);
}
void PchManager::updatePchInfo(ClangProjectSettings *cps,
const QList<ProjectPart::Ptr> &projectParts)
{
if (m_pchGenerationWatcher.isRunning()) {
m_pchGenerationWatcher.waitForFinished();
}
const QString customPchFile = cps->customPchFile();
const ClangProjectSettings::PchUsage pchUsage = cps->pchUsage();
void (*updateFunction)(QFutureInterface<void> &future,
const PchManager::UpdateParams params) = 0;
QString message;
if (pchUsage == ClangProjectSettings::PchUse_None
|| (pchUsage == ClangProjectSettings::PchUse_Custom && customPchFile.isEmpty())) {
updateFunction = &PchManager::doPchInfoUpdateNone;
message = QLatin1String("updatePchInfo: switching to none");
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Fuzzy) {
updateFunction = &PchManager::doPchInfoUpdateFuzzy;
message = QLatin1String("updatePchInfo: switching to build system (fuzzy)");
} else if (pchUsage == ClangProjectSettings::PchUse_BuildSystem_Exact) {
updateFunction = &PchManager::doPchInfoUpdateExact;
message = QLatin1String("updatePchInfo: switching to build system (exact)");
} else if (pchUsage == ClangProjectSettings::PchUse_Custom) {
updateFunction = &PchManager::doPchInfoUpdateCustom;
message = QLatin1String("updatePchInfo: switching to custom") + customPchFile;
}
QTC_ASSERT(updateFunction && !message.isEmpty(), return);
Core::MessageManager::write(message, Core::MessageManager::Silent);
QFuture<void> future = QtConcurrent::run(updateFunction,
UpdateParams(customPchFile, projectParts));
m_pchGenerationWatcher.setFuture(future);
Core::ProgressManager::addTask(future, tr("Precompiling"), "Key.Tmp.Precompiling");
}
namespace {
bool hasObjCFiles(const CppTools::ProjectPart::Ptr &projectPart)
{
foreach (const CppTools::ProjectFile &file, projectPart->files) {
switch (file.kind) {
case CppTools::ProjectFile::ObjCHeader:
case CppTools::ProjectFile::ObjCSource:
case CppTools::ProjectFile::ObjCXXHeader:
case CppTools::ProjectFile::ObjCXXSource:
return true;
default:
break;
}
}
return false;
}
bool hasCppFiles(const CppTools::ProjectPart::Ptr &projectPart)
{
foreach (const CppTools::ProjectFile &file, projectPart->files) {
switch (file.kind) {
case CppTools::ProjectFile::CudaSource:
case CppTools::ProjectFile::CXXHeader:
case CppTools::ProjectFile::CXXSource:
case CppTools::ProjectFile::OpenCLSource:
case CppTools::ProjectFile::ObjCXXHeader:
case CppTools::ProjectFile::ObjCXXSource:
return true;
default:
break;
}
}
return false;
}
CppTools::ProjectFile::Kind getPrefixFileKind(bool hasObjectiveC, bool hasCPlusPlus)
{
if (hasObjectiveC && hasCPlusPlus)
return CppTools::ProjectFile::ObjCXXHeader;
else if (hasObjectiveC)
return CppTools::ProjectFile::ObjCHeader;
else if (hasCPlusPlus)
return CppTools::ProjectFile::CXXHeader;
return CppTools::ProjectFile::CHeader;
}
}
void PchManager::doPchInfoUpdateNone(QFutureInterface<void> &future,
const PchManager::UpdateParams params)
{
future.setProgressRange(0, 1);
PchInfo::Ptr emptyPch = PchInfo::createEmpty();
PchManager::instance()->setPCHInfo(params.projectParts, emptyPch,
qMakePair(true, QStringList()));
future.setProgressValue(1);
}
void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
const PchManager::UpdateParams params)
{
typedef ProjectPart::HeaderPath HeaderPath;
QHash<QString, QSet<HeaderPath>> headers;
QHash<QString, QSet<QByteArray> > definesPerPCH;
QHash<QString, bool> objc;
QHash<QString, bool> cplusplus;
QHash<QString, ProjectPart::QtVersion> qtVersions;
QHash<QString, ProjectPart::LanguageVersion> languageVersions;
QHash<QString, ProjectPart::LanguageExtensions> languageExtensionsMap;
QHash<QString, QList<ProjectPart::Ptr> > inputToParts;
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
if (projectPart->precompiledHeaders.isEmpty())
continue;
const QString &pch = projectPart->precompiledHeaders.first(); // TODO: support more than 1 PCH file.
if (!QFile(pch).exists())
continue;
inputToParts[pch].append(projectPart);
headers[pch].unite(QSet<HeaderPath>::fromList(projectPart->headerPaths));
languageVersions[pch] = std::max(languageVersions.value(pch, ProjectPart::C89),
projectPart->languageVersion);
languageExtensionsMap[pch] = languageExtensionsMap[pch] | projectPart->languageExtensions;
if (hasObjCFiles(projectPart))
objc[pch] = true;
if (hasCppFiles(projectPart))
cplusplus[pch] = true;
QSet<QByteArray> projectDefines = QSet<QByteArray>::fromList(projectPart->toolchainDefines.split('\n'));
QMutableSetIterator<QByteArray> iter(projectDefines);
while (iter.hasNext()){
QByteArray v = iter.next();
if (v.startsWith("#define _") || v.isEmpty()) // TODO: see ProjectPart::createClangOptions
iter.remove();
}
projectDefines.unite(QSet<QByteArray>::fromList(projectPart->projectDefines.split('\n')));
if (definesPerPCH.contains(pch)) {
definesPerPCH[pch].intersect(projectDefines);
} else {
definesPerPCH[pch] = projectDefines;
}
qtVersions[pch] = projectPart->qtVersion;
}
future.setProgressRange(0, definesPerPCH.size() + 1);
future.setProgressValue(0);
foreach (const QString &pch, inputToParts.keys()) {
if (future.isCanceled())
return;
ProjectPart::Ptr projectPart(new ProjectPart);
projectPart->qtVersion = qtVersions[pch];
projectPart->languageVersion = languageVersions[pch];
projectPart->languageExtensions = languageExtensionsMap[pch];
projectPart->headerPaths = headers[pch].toList();
projectPart->updateLanguageFeatures();
QList<QByteArray> defines = definesPerPCH[pch].toList();
if (!defines.isEmpty()) {
projectPart->projectDefines = defines[0];
for (int i = 1; i < defines.size(); ++i) {
projectPart->projectDefines += '\n';
projectPart->projectDefines += defines[i];
}
}
CppTools::ProjectFile::Kind prefixFileKind =
getPrefixFileKind(objc.value(pch, false), cplusplus.value(pch, false));
QStringList options = Utils::createClangOptions(projectPart, prefixFileKind);
projectPart.clear();
PchManager *pchManager = PchManager::instance();
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, true);
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
if (pchInfo.isNull()) {
pchInfo = PchInfo::createWithFileName(pch, options, objc[pch]);
msgs = precompile(pchInfo);
}
pchManager->setPCHInfo(inputToParts[pch], pchInfo, msgs);
future.setProgressValue(future.progressValue() + 1);
}
future.setProgressValue(future.progressValue() + 1);
}
void PchManager::doPchInfoUpdateExact(QFutureInterface<void> &future,
const PchManager::UpdateParams params)
{
future.setProgressRange(0, params.projectParts.size() + 1);
future.setProgressValue(0);
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
if (future.isCanceled())
return;
if (projectPart->precompiledHeaders.isEmpty())
continue;
const QString &pch = projectPart->precompiledHeaders.first(); // TODO: support more than 1 PCH file.
if (!QFile(pch).exists())
continue;
const bool hasObjC = hasObjCFiles(projectPart);
QStringList options = Utils::createClangOptions(
projectPart, getPrefixFileKind(hasObjC, hasCppFiles(projectPart)));
PchManager *pchManager = PchManager::instance();
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(pch, options, false);
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());
if (pchInfo.isNull()) {
pchInfo = PchInfo::createWithFileName(pch, options, hasObjC);
msgs = precompile(pchInfo);
}
pchManager->setPCHInfo(QList<ProjectPart::Ptr>() << projectPart,
pchInfo, msgs);
future.setProgressValue(future.progressValue() + 1);
}
future.setProgressValue(future.progressValue() + 1);
}
void PchManager::doPchInfoUpdateCustom(QFutureInterface<void> &future,
const PchManager::UpdateParams params)
{
future.setProgressRange(0, 1);
future.setProgressValue(0);
ProjectPart::HeaderPaths headers;
bool objc = false;
bool cplusplus = false;
ProjectPart::Ptr united(new ProjectPart());
united->languageVersion = ProjectPart::C89;
foreach (const ProjectPart::Ptr &projectPart, params.projectParts) {
headers += projectPart->headerPaths;
united->languageVersion = std::max(united->languageVersion, projectPart->languageVersion);
united->qtVersion = std::max(united->qtVersion, projectPart->qtVersion);
objc |= hasObjCFiles(projectPart);
cplusplus |= hasCppFiles(projectPart);
}
united->updateLanguageFeatures();
united->headerPaths = headers;
QStringList opts = Utils::createClangOptions(
united, getPrefixFileKind(objc, cplusplus));
united.clear();
PchManager *pchManager = PchManager::instance();
PchInfo::Ptr pchInfo = pchManager->findMatchingPCH(params.customPchFile, opts, true);
QPair<bool, QStringList> msgs = qMakePair(true, QStringList());;
if (future.isCanceled())
return;
if (pchInfo.isNull()) {
pchInfo = PchInfo::createWithFileName(params.customPchFile, opts, objc);
msgs = precompile(pchInfo);
}
pchManager->setPCHInfo(params.projectParts, pchInfo, msgs);
future.setProgressValue(1);
}
PchInfo::Ptr PchManager::findMatchingPCH(const QString &inputFileName,
const QStringList &options,
bool fuzzyMatching) const
{
QMutexLocker locker(&m_mutex);
if (fuzzyMatching) {
QStringList opts = options;
opts.sort();
foreach (PchInfo::Ptr pchInfo, m_activePchFiles.values()) {
if (pchInfo->inputFileName() != inputFileName)
continue;
QStringList pchOpts = pchInfo->options();
pchOpts.sort();
if (pchOpts == opts)
return pchInfo;
}
} else {
foreach (PchInfo::Ptr pchInfo, m_activePchFiles.values())
if (pchInfo->inputFileName() == inputFileName
&& pchInfo->options() == options)
return pchInfo;
}
return PchInfo::Ptr();
}
void PchManager::updateActivePchFiles()
{
QMutexLocker locker(&m_mutex);
QSet<ProjectPart::Ptr> activeParts;
CppTools::CppModelManager *mmi = CppTools::CppModelManager::instance();
foreach (const CppTools::ProjectInfo &pi, mmi->projectInfos())
activeParts.unite(QSet<ProjectPart::Ptr>::fromList(pi.projectParts()));
QList<ProjectPart::Ptr> partsWithPCHFiles = m_activePchFiles.keys();
foreach (ProjectPart::Ptr pPart, partsWithPCHFiles)
if (!activeParts.contains(pPart))
m_activePchFiles.remove(pPart);
}

View File

@@ -1,109 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef PCHMANAGER_H
#define PCHMANAGER_H
#include "clangprojectsettings.h"
#include "pchinfo.h"
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/project.h>
#include <coreplugin/messagemanager.h>
#include <QFutureWatcher>
#include <QHash>
#include <QMutex>
#include <QObject>
namespace ClangCodeModel {
namespace Internal {
class PchManager : public QObject
{
Q_OBJECT
typedef CppTools::ProjectPart ProjectPart;
static PchManager *m_instance;
public:
PchManager(QObject *parent = 0);
virtual ~PchManager();
static PchManager *instance();
PchInfo::Ptr pchInfo(const ProjectPart::Ptr &projectPart) const;
ClangProjectSettings *settingsForProject(ProjectExplorer::Project *project);
signals:
void pchMessage(const QString &message, Core::MessageManager::PrintToOutputPaneFlags flags);
public slots:
void clangProjectSettingsChanged();
void onAboutToRemoveProject(ProjectExplorer::Project *project);
void onProjectPartsUpdated(ProjectExplorer::Project *project);
private slots:
void updateActivePchFiles();
private:
struct UpdateParams {
UpdateParams(const QString &customPchFile, const QList<ProjectPart::Ptr> &projectParts)
: customPchFile(customPchFile) , projectParts(projectParts) {}
const QString customPchFile;
const QList<ProjectPart::Ptr> projectParts;
};
void updatePchInfo(ClangProjectSettings *cps,
const QList<ProjectPart::Ptr> &projectParts);
static void doPchInfoUpdateNone(QFutureInterface<void> &future, const UpdateParams params);
static void doPchInfoUpdateFuzzy(QFutureInterface<void> &future, const UpdateParams params);
static void doPchInfoUpdateExact(QFutureInterface<void> &future, const UpdateParams params);
static void doPchInfoUpdateCustom(QFutureInterface<void> &future, const UpdateParams params);
void setPCHInfo(const QList<ProjectPart::Ptr> &projectParts,
const PchInfo::Ptr &pchInfo,
const QPair<bool, QStringList> &msgs);
PchInfo::Ptr findMatchingPCH(const QString &inputFileName, const QStringList &options,
bool fuzzyMatching) const;
private:
mutable QMutex m_mutex;
QHash<ProjectPart::Ptr, PchInfo::Ptr> m_activePchFiles;
QHash<ProjectExplorer::Project *, ClangProjectSettings *> m_projectSettings;
QFutureWatcher<void> m_pchGenerationWatcher;
};
} // namespace Internal
} // namespace ClangCodeModel
#endif // PCHMANAGER_H

View File

@@ -1,104 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "scopedclangoptions.h"
namespace ClangCodeModel {
/**
* @class ClangCodeModel::ScopedClangOptions
* @brief Converts QStringList to raw options, acceptable by clang-c parsing and indexing API
*/
ScopedClangOptions::ScopedClangOptions(const QStringList &options)
: m_size(options.size())
, m_rawOptions(new const char*[options.size()])
{
for (int i = 0 ; i < m_size; ++i)
m_rawOptions[i] = qstrdup(options[i].toUtf8());
}
ScopedClangOptions::~ScopedClangOptions()
{
for (int i = 0; i < m_size; ++i)
delete[] m_rawOptions[i];
delete[] m_rawOptions;
}
const char **ScopedClangOptions::data() const
{
return m_rawOptions;
}
int ScopedClangOptions::size() const
{
return m_size;
}
/**
* @class ClangCodeModel::SharedClangOptions
* @brief Shared wrapper around \a {ClangCodeModel::ScopedClangOptions} ScopedClangOptions
*/
SharedClangOptions::SharedClangOptions()
: d(0)
{
}
SharedClangOptions::SharedClangOptions(const QStringList &options)
: d(new ScopedClangOptions(options))
{
}
/**
* @return Replaces options with new options list
*/
void SharedClangOptions::reloadOptions(const QStringList &options)
{
d = QSharedPointer<ScopedClangOptions>(new ScopedClangOptions(options));
}
/**
* @return Pointer to clang raw options or NULL if uninitialized
*/
const char **SharedClangOptions::data() const
{
return d ? d->data() : 0;
}
/**
* @return Options count or 0 if uninitialized
*/
int SharedClangOptions::size() const
{
return d ? d->size() : 0;
}
} // namespace ClangCodeModel

View File

@@ -1,531 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "semanticmarker.h"
#include "unit.h"
#include "utils_p.h"
#include "cxraii.h"
#include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h>
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
static const unsigned ATTACHED_NOTES_LIMIT = 10;
SemanticMarker::SemanticMarker()
{
}
SemanticMarker::~SemanticMarker()
{
}
QString SemanticMarker::fileName() const
{
if (!m_unit)
return QString();
return m_unit->fileName();
}
void SemanticMarker::setFileName(const QString &fileName)
{
if (this->fileName() == fileName)
return;
QStringList oldOptions;
if (m_unit)
oldOptions = m_unit->compilationOptions();
m_unit = Unit::create(fileName);
if (!oldOptions.isEmpty())
m_unit->setCompilationOptions(oldOptions);
unsigned clangOpts = clang_defaultEditingTranslationUnitOptions();
clangOpts |= CXTranslationUnit_DetailedPreprocessingRecord;
clangOpts |= CXTranslationUnit_Incomplete;
clangOpts &= ~CXTranslationUnit_CacheCompletionResults;
m_unit->setManagementOptions(clangOpts);
}
void SemanticMarker::setCompilationOptions(const QStringList &options)
{
QTC_ASSERT(m_unit, return);
if (m_unit->compilationOptions() == options)
return;
m_unit->setCompilationOptions(options);
m_unit->unload();
}
void SemanticMarker::reparse(const UnsavedFiles &unsavedFiles)
{
QTC_ASSERT(m_unit, return);
m_unit->setUnsavedFiles(unsavedFiles);
if (m_unit->isLoaded())
m_unit->reparse();
else
m_unit->parse();
}
/**
* \brief Calculate one or several ranges and append diagnostic for each range
* Extracted from SemanticMarker::diagnostics() to reuse code
*/
static void appendDiagnostic(const CXDiagnostic &diag,
const CXSourceLocation &cxLocation,
Diagnostic::Severity severity,
const QString &spelling,
QList<Diagnostic> &diagnostics)
{
const unsigned rangeCount = clang_getDiagnosticNumRanges(diag);
bool expandLocation = true;
for (unsigned i = 0; i < rangeCount; ++i) {
CXSourceRange r = clang_getDiagnosticRange(diag, i);
const SourceLocation &spellBegin = Internal::getSpellingLocation(clang_getRangeStart(r));
const SourceLocation &spellEnd = Internal::getSpellingLocation(clang_getRangeEnd(r));
unsigned length = spellEnd.offset() - spellBegin.offset();
// File name can be empty due clang bug
if (!spellBegin.fileName().isEmpty()) {
Diagnostic d(severity, spellBegin, length, spelling);
diagnostics.append(d);
expandLocation = false;
}
}
if (expandLocation) {
const SourceLocation &location = Internal::getExpansionLocation(cxLocation);
Diagnostic d(severity, location, 0, spelling);
diagnostics.append(d);
}
}
static bool isBlackListedDiagnostic(const Utils::MimeType &mimeType, const QString &diagnostic)
{
static const QStringList blackList {
QLatin1String("#pragma once in main file"),
QLatin1String("#include_next in primary source file")
};
return mimeType.inherits(QLatin1String("text/x-chdr")) && blackList.contains(diagnostic);
}
QList<Diagnostic> SemanticMarker::diagnostics() const
{
QList<Diagnostic> diagnostics;
if (!m_unit || !m_unit->isLoaded())
return diagnostics;
Utils::MimeDatabase mimeDatabase;
const Utils::MimeType mimeType = mimeDatabase.mimeTypeForFile(fileName());
const unsigned diagCount = m_unit->getNumDiagnostics();
for (unsigned i = 0; i < diagCount; ++i) {
ScopedCXDiagnostic diag(m_unit->getDiagnostic(i));
Diagnostic::Severity severity = static_cast<Diagnostic::Severity>(clang_getDiagnosticSeverity(diag));
if (severity == Diagnostic::Ignored || severity == Diagnostic::Note)
continue;
CXSourceLocation cxLocation = clang_getDiagnosticLocation(diag);
QString spelling = Internal::getQString(clang_getDiagnosticSpelling(diag));
if (isBlackListedDiagnostic(mimeType, spelling))
continue;
// Attach messages with Diagnostic::Note severity
ScopedCXDiagnosticSet cxChildren(clang_getChildDiagnostics(diag));
const unsigned numChildren = clang_getNumDiagnosticsInSet(cxChildren);
const unsigned size = qMin(ATTACHED_NOTES_LIMIT, numChildren);
for (unsigned di = 0; di < size; ++di) {
ScopedCXDiagnostic child(clang_getDiagnosticInSet(cxChildren, di));
const Diagnostic::Severity severity
= static_cast<Diagnostic::Severity>(clang_getDiagnosticSeverity(child));
if (severity == Diagnostic::Ignored || severity == Diagnostic::Note)
continue;
spelling.append(QLatin1String("\n "));
spelling.append(Internal::getQString(clang_getDiagnosticSpelling(child)));
}
// Fatal error may occur in another file, but it breaks whole parsing
// Typical fatal error is unresolved #include
if (severity == Diagnostic::Fatal) {
for (unsigned di = 0; di < numChildren; ++di) {
ScopedCXDiagnostic child(clang_getDiagnosticInSet(cxChildren, di));
appendDiagnostic(child, clang_getDiagnosticLocation(child), Diagnostic::Warning, spelling, diagnostics);
}
}
appendDiagnostic(diag, cxLocation, severity, spelling, diagnostics);
}
return diagnostics;
}
QList<SemanticMarker::Range> SemanticMarker::ifdefedOutBlocks() const
{
QList<Range> blocks;
if (!m_unit || !m_unit->isLoaded())
return blocks;
#if CINDEX_VERSION_MINOR >= 21
CXSourceRangeList *skippedRanges = clang_getSkippedRanges(m_unit->clangTranslationUnit(),
m_unit->getFile());
blocks.reserve(skippedRanges->count);
for (unsigned i = 0; i < skippedRanges->count; ++i) {
const CXSourceRange &r = skippedRanges->ranges[i];
const SourceLocation &spellBegin = Internal::getSpellingLocation(clang_getRangeStart(r));
if (spellBegin.fileName() != fileName())
continue;
const SourceLocation &spellEnd = Internal::getSpellingLocation(clang_getRangeEnd(r));
const int begin = spellBegin.offset() + 1;
const int end = spellEnd.offset() - spellEnd.column();
blocks.append(Range(begin, end));
}
clang_disposeSourceRangeList(skippedRanges);
#endif
return blocks;
}
namespace {
static void add(QList<SourceMarker> &markers,
const CXSourceRange &extent,
SourceMarker::Kind kind)
{
CXSourceLocation start = clang_getRangeStart(extent);
CXSourceLocation end = clang_getRangeEnd(extent);
const SourceLocation &location = Internal::getExpansionLocation(start);
const SourceLocation &locationEnd = Internal::getExpansionLocation(end);
if (location.offset() < locationEnd.offset()) {
const unsigned length = locationEnd.offset() - location.offset();
markers.append(SourceMarker(location, length, kind));
}
}
/**
* @brief Selects correct highlighting for cursor that is reference
* @return SourceMarker::Unknown if cannot select highlighting
*/
static SourceMarker::Kind getKindByReferencedCursor(const CXCursor &cursor)
{
const CXCursor referenced = clang_getCursorReferenced(cursor);
switch (clang_getCursorKind(referenced)) {
case CXCursor_EnumConstantDecl:
return SourceMarker::Enumeration;
case CXCursor_FieldDecl:
case CXCursor_ObjCIvarDecl:
case CXCursor_ObjCPropertyDecl:
return SourceMarker::Field;
case CXCursor_FunctionDecl:
case CXCursor_FunctionTemplate:
case CXCursor_Constructor:
return SourceMarker::Function;
case CXCursor_VarDecl:
case CXCursor_ParmDecl:
case CXCursor_NonTypeTemplateParameter:
return SourceMarker::Local;
case CXCursor_CXXMethod:
if (clang_CXXMethod_isVirtual(referenced))
return SourceMarker::VirtualMethod;
else
return SourceMarker::Function;
case CXCursor_ObjCClassMethodDecl:
case CXCursor_ObjCInstanceMethodDecl:
// calling method as property, e.h. "layer.shouldRasterize = YES"
return SourceMarker::Field;
case CXCursor_UnexposedDecl:
// NSObject "self" method which is a pseudo keyword
if (clang_getCursorLanguage(referenced) == CXLanguage_ObjC)
return SourceMarker::PseudoKeyword;
break;
default:
break;
}
return SourceMarker::Unknown;
}
static const QSet<QString> ObjcPseudoKeywords = QSet<QString>()
<< QLatin1String("end")
<< QLatin1String("try")
<< QLatin1String("defs")
<< QLatin1String("throw")
<< QLatin1String("class")
<< QLatin1String("catch")
<< QLatin1String("encode")
<< QLatin1String("public")
<< QLatin1String("dynamic")
<< QLatin1String("finally")
<< QLatin1String("package")
<< QLatin1String("private")
<< QLatin1String("optional")
<< QLatin1String("property")
<< QLatin1String("protocol")
<< QLatin1String("required")
<< QLatin1String("selector")
<< QLatin1String("interface")
<< QLatin1String("protected")
<< QLatin1String("synthesize")
<< QLatin1String("not_keyword")
<< QLatin1String("synchronized")
<< QLatin1String("implementation")
<< QLatin1String("compatibility_alias")
;
} // Anonymous namespace
/**
* @brief SemanticMarker::sourceMarkersInRange
* @param firstLine - first line where to generate highlighting markers
* @param lastLine - last line where to generate highlighting markers
*
* There still two kinds of problems:
* - clang_annotateTokens() can return wrong cursor, and it's normal behavior
* - some cases no handled
*
* Problems caused by wrong cursors:
* - range-based for from C++ 2011
* - identifiers in some compound statements have type DeclStmt
* or CompoundStmt which refers to top-level construction.
* - CXCursor_ObjCIvarDecl mapped to field, but instance variable have
* incorrect cursor kind if it declared in private interface
* @interface MyApplication() {
* NSArray* _items;
* }
*
* Missed cases:
* - global variables highlighted as locals
* - appropriate marker had not been selected for listed cursors:
* CXCursor_ObjCProtocolExpr, CXCursor_ObjCEncodeExpr,
* CXCursor_ObjCDynamicDecl, CXCursor_ObjCBridgedCastExpr,
* CXCursor_ObjCSuperClassRef
* - template members of template classes&functions always highlighted
* as members, even if they are functions - no way to differ found.
* - @1, @{}, @[]
*/
QList<SourceMarker> SemanticMarker::sourceMarkersInRange(unsigned firstLine,
unsigned lastLine)
{
QList<SourceMarker> result;
if (!m_unit || !m_unit->isLoaded())
return result;
// Highlighting called asynchronously, and a few lines at the end can be deleted for this time.
CXSourceRange unitRange = clang_getCursorExtent(m_unit->getTranslationUnitCursor());
SourceLocation unitEnd = getExpansionLocation(clang_getRangeEnd(unitRange));
if (lastLine > unitEnd.line())
lastLine = unitEnd.line();
if (firstLine > lastLine)
return result;
IdentifierTokens idTokens(*m_unit, firstLine, lastLine);
const CXSourceRange *atTokenExtent = 0;
for (unsigned i = 0; i < idTokens.count(); ++i) {
const CXToken &tok = idTokens.token(i);
CXTokenKind kind = clang_getTokenKind(tok);
if (atTokenExtent) {
if (CXToken_Literal == kind) {
if (m_unit->getTokenSpelling(tok).startsWith(QLatin1Char('"')))
add(result, *atTokenExtent, SourceMarker::ObjCString);
atTokenExtent = 0;
continue;
} else {
add(result, *atTokenExtent, SourceMarker::PseudoKeyword);
atTokenExtent = 0;
}
}
const CXSourceRange &tokenExtent = idTokens.extent(i);
if (CXToken_Keyword == kind) {
QString spell = m_unit->getTokenSpelling(tok);
if (ObjcPseudoKeywords.contains(spell))
add(result, tokenExtent, SourceMarker::PseudoKeyword);
continue;
}
if (CXToken_Punctuation == kind) {
static const QLatin1String at("@");
if (m_unit->getTokenSpelling(tok) == at)
atTokenExtent = &tokenExtent;
continue;
}
if (CXToken_Identifier != kind)
continue;
const CXCursor &cursor = idTokens.cursor(i);
const CXCursorKind cursorKind = clang_getCursorKind(cursor);
if (clang_isInvalid(cursorKind))
continue;
switch (cursorKind) {
case CXCursor_EnumConstantDecl:
add(result, tokenExtent, SourceMarker::Enumeration);
break;
case CXCursor_ClassDecl:
case CXCursor_UnionDecl:
case CXCursor_ClassTemplate:
case CXCursor_ClassTemplatePartialSpecialization:
case CXCursor_EnumDecl:
case CXCursor_Namespace:
case CXCursor_NamespaceRef:
case CXCursor_NamespaceAlias:
case CXCursor_StructDecl:
case CXCursor_TemplateRef:
case CXCursor_TypeRef:
case CXCursor_TypedefDecl:
case CXCursor_Constructor:
case CXCursor_TemplateTypeParameter:
case CXCursor_TemplateTemplateParameter:
case CXCursor_UnexposedDecl: /* friend class MyClass; */
add(result, tokenExtent, SourceMarker::Type);
break;
case CXCursor_ParmDecl:
case CXCursor_VariableRef:
case CXCursor_VarDecl:
case CXCursor_NonTypeTemplateParameter:
add(result, tokenExtent, SourceMarker::Local);
break;
case CXCursor_MemberRefExpr:
case CXCursor_MemberRef:
case CXCursor_DeclRefExpr:
case CXCursor_CallExpr: {
SourceMarker::Kind kind = getKindByReferencedCursor(cursor);
if (kind == SourceMarker::Unknown && cursorKind == CXCursor_MemberRefExpr) {
/* template class member in template function */
kind = SourceMarker::Field;
}
if (kind != SourceMarker::Unknown)
add(result, tokenExtent, kind);
} break;
case CXCursor_FieldDecl:
add(result, tokenExtent, SourceMarker::Field);
break;
case CXCursor_Destructor:
case CXCursor_CXXMethod: {
if (clang_CXXMethod_isVirtual(cursor))
add(result, tokenExtent, SourceMarker::VirtualMethod);
else
add(result, tokenExtent, SourceMarker::Function);
} break;
case CXCursor_CXXOverrideAttr:
case CXCursor_CXXFinalAttr:
case CXCursor_AnnotateAttr: // 'annotate' in '__attribute__((annotate("AnyComment")))'
case CXCursor_UnexposedAttr: // 'align' in '__declspec(align(8))'
add(result, tokenExtent, SourceMarker::PseudoKeyword);
break;
case CXCursor_FunctionDecl:
case CXCursor_FunctionTemplate:
case CXCursor_OverloadedDeclRef:
add(result, tokenExtent, SourceMarker::Function);
break;
case CXCursor_ObjCInstanceMethodDecl:
case CXCursor_ObjCClassMethodDecl:
case CXCursor_ObjCSelectorExpr:
add(result, tokenExtent, SourceMarker::ObjectiveCMessage);
break;
case CXCursor_ObjCMessageExpr: {
static const QLatin1String super("super");
if (m_unit->getTokenSpelling(tok) == super)
add(result, tokenExtent, SourceMarker::PseudoKeyword);
else
add(result, tokenExtent, SourceMarker::ObjectiveCMessage);
} break;
case CXCursor_ObjCCategoryDecl:
case CXCursor_ObjCCategoryImplDecl:
case CXCursor_ObjCImplementationDecl:
case CXCursor_ObjCInterfaceDecl:
case CXCursor_ObjCProtocolDecl:
case CXCursor_ObjCProtocolRef:
case CXCursor_ObjCClassRef:
case CXCursor_ObjCSuperClassRef:
case CXCursor_TypeAliasDecl: // C++11 type alias: 'using value_t = T'
add(result, tokenExtent, SourceMarker::Type);
break;
case CXCursor_ObjCSynthesizeDecl:
case CXCursor_ObjCDynamicDecl:
case CXCursor_ObjCPropertyDecl:
case CXCursor_ObjCIvarDecl:
add(result, tokenExtent, SourceMarker::Field);
break;
case CXCursor_MacroDefinition:
case CXCursor_MacroExpansion:
add(result, tokenExtent, SourceMarker::Macro);
break;
case CXCursor_LabelRef:
case CXCursor_LabelStmt:
add(result, tokenExtent, SourceMarker::Label);
break;
default:
break;
}
}
return result;
}
Unit::Ptr SemanticMarker::unit() const
{
return m_unit;
}

View File

@@ -1,95 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANG_SEMANTICMARKER_H
#define CLANG_SEMANTICMARKER_H
#include "clang_global.h"
#include "diagnostic.h"
#include "fastindexer.h"
#include "sourcemarker.h"
#include "utils.h"
#include <QMutex>
#include <QScopedPointer>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
namespace ClangCodeModel {
class CLANG_EXPORT SemanticMarker
{
Q_DISABLE_COPY(SemanticMarker)
public:
typedef QSharedPointer<SemanticMarker> Ptr;
class Range
{
Range();
public:
Range(int first, int last) : first(first), last(last) {}
int first;
int last;
};
public:
SemanticMarker();
~SemanticMarker();
QMutex *mutex() const
{ return &m_mutex; }
QString fileName() const;
void setFileName(const QString &fileName);
void setCompilationOptions(const QStringList &options);
void reparse(const Internal::UnsavedFiles &unsavedFiles);
QList<Diagnostic> diagnostics() const;
QList<Range> ifdefedOutBlocks() const;
QList<SourceMarker> sourceMarkersInRange(unsigned firstLine,
unsigned lastLine);
Internal::Unit::Ptr unit() const;
private:
mutable QMutex m_mutex;
Internal::Unit::Ptr m_unit;
};
} // namespace ClangCodeModel
#endif // CLANG_SEMANTICMARKER_H

View File

@@ -1,80 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "sourcelocation.h"
using namespace ClangCodeModel;
SourceLocation::SourceLocation()
: m_line(0)
, m_column(0)
, m_offset(0)
{}
SourceLocation::SourceLocation(const QString &fileName,
unsigned line,
unsigned column,
unsigned offset)
: m_fileName(fileName)
, m_line(line)
, m_column(column)
, m_offset(offset)
{}
namespace ClangCodeModel {
bool operator==(const SourceLocation &a, const SourceLocation &b)
{
return a.line() == b.line()
&& a.column() == b.column()
&& a.offset() == b.offset()
&& a.fileName() == b.fileName()
;
}
bool operator!=(const SourceLocation &a, const SourceLocation &b)
{
return !(a == b);
}
QDebug operator<<(QDebug dbg, const SourceLocation &location)
{
dbg.nospace() << location.fileName()
<< " ["
<< location.line()
<< ":"
<< location.column()
<< "("
<< location.offset()
<< ")]";
return dbg.space();
}
} // ClangCodeModel

View File

@@ -1,70 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef SOURCELOCATION_H
#define SOURCELOCATION_H
#include "clang_global.h"
#include <QtCore/QString>
#include <QtCore/QDebug>
namespace ClangCodeModel {
class CLANG_EXPORT SourceLocation
{
public:
SourceLocation();
SourceLocation(const QString &fileName,
unsigned line = 0,
unsigned column = 0,
unsigned offset = 0);
bool isNull() const { return m_fileName.isEmpty(); }
const QString &fileName() const { return m_fileName; }
unsigned line() const { return m_line; }
unsigned column() const { return m_column; }
unsigned offset() const { return m_offset; }
private:
QString m_fileName;
unsigned m_line;
unsigned m_column;
unsigned m_offset;
};
bool operator==(const SourceLocation &a, const SourceLocation &b);
bool operator!=(const SourceLocation &a, const SourceLocation &b);
QDebug operator<<(QDebug dbg, const SourceLocation &location);
} // ClangCodeModel
#endif // SOURCELOCATION_H

View File

@@ -1,42 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "sourcemarker.h"
using namespace ClangCodeModel;
SourceMarker::SourceMarker()
: m_length(0), m_kind(Unknown)
{}
SourceMarker::SourceMarker(const SourceLocation &location, unsigned length, Kind kind)
: m_loc(location), m_length(length), m_kind(kind)
{
}

View File

@@ -1,98 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANG_SOURCEMARKER_H
#define CLANG_SOURCEMARKER_H
#include "clang_global.h"
#include "sourcelocation.h"
namespace ClangCodeModel {
class CLANG_EXPORT SourceMarker
{
public: // TODO: remove this, it's about the same as the TextEditor::SemanticHighlighter::Result
enum Kind {
Unknown = 0,
Type = 1,
Local,
Field,
Enumeration,
VirtualMethod,
Label,
Macro,
Function,
PseudoKeyword,
ObjCString,
ObjectiveCMessage = VirtualMethod
};
SourceMarker();
SourceMarker(const SourceLocation &location,
unsigned length,
Kind kind);
bool isValid() const
{ return m_loc.line() != 0; }
bool isInvalid() const
{ return m_loc.line() == 0; }
const SourceLocation &location() const
{ return m_loc; }
unsigned length() const
{ return m_length; }
Kind kind() const
{ return m_kind; }
bool lessThan(const SourceMarker &other) const
{
if (m_loc.line() != other.m_loc.line())
return m_loc.line() < other.m_loc.line();
if (m_loc.column() != other.m_loc.column())
return m_loc.column() < other.m_loc.column();
return m_length < other.m_length;
}
private:
SourceLocation m_loc;
unsigned m_length;
Kind m_kind;
};
CLANG_EXPORT inline bool operator<(const SourceMarker &one, const SourceMarker &two)
{ return one.lessThan(two); }
} // namespace Clang
#endif // CLANG_SOURCEMARKER_H

View File

@@ -1,118 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "symbol.h"
#include <cplusplus/Icons.h>
using namespace ClangCodeModel;
Symbol::Symbol()
: m_kind(Unknown)
{}
Symbol::Symbol(const QString &name,
const QString &qualification,
Kind type,
const SourceLocation &location)
: m_name(name)
, m_qualification(qualification)
, m_location(location)
, m_kind(type)
{}
QIcon Symbol::iconForSymbol() const
{
CPlusPlus::Icons icons;
switch (m_kind) {
case Enum:
return icons.iconForType(CPlusPlus::Icons::EnumIconType);
case Class:
return icons.iconForType(CPlusPlus::Icons::ClassIconType);
case Method:
case Function:
case Declaration:
case Constructor:
case Destructor:
return icons.iconForType(CPlusPlus::Icons::FuncPublicIconType);
default:
return icons.iconForType(CPlusPlus::Icons::UnknownIconType);
}
}
namespace ClangCodeModel {
QDataStream &operator<<(QDataStream &stream, const Symbol &symbol)
{
stream << symbol.m_name
<< symbol.m_qualification
<< symbol.m_location.fileName()
<< (quint32)symbol.m_location.line()
<< (quint16)symbol.m_location.column()
<< (quint32)symbol.m_location.offset()
<< (qint8)symbol.m_kind;
return stream;
}
QDataStream &operator>>(QDataStream &stream, Symbol &symbol)
{
QString fileName;
quint32 line;
quint16 column;
quint32 offset;
quint8 kind;
stream >> symbol.m_name
>> symbol.m_qualification
>> fileName
>> line
>> column
>> offset
>> kind;
symbol.m_location = SourceLocation(fileName, line, column, offset);
symbol.m_kind = Symbol::Kind(kind);
return stream;
}
bool operator==(const Symbol &a, const Symbol &b)
{
return a.m_name == b.m_name
&& a.m_qualification == b.m_qualification
&& a.m_location == b.m_location
&& a.m_kind == b.m_kind;
}
bool operator!=(const Symbol &a, const Symbol &b)
{
return !(a == b);
}
} // ClangCodeModel

View File

@@ -1,78 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef INDEXEDSYMBOLINFO_H
#define INDEXEDSYMBOLINFO_H
#include "sourcelocation.h"
#include <QString>
#include <QDataStream>
#include <QIcon>
namespace ClangCodeModel {
class Symbol
{
public:
enum Kind {
Enum,
Class,
Method, // A member-function.
Function, // A free-function (global or within a namespace).
Declaration,
Constructor,
Destructor,
Unknown
};
Symbol();
Symbol(const QString &name,
const QString &qualification,
Kind type,
const SourceLocation &location);
QString m_name;
QString m_qualification;
SourceLocation m_location;
Kind m_kind;
QIcon iconForSymbol() const;
};
QDataStream &operator<<(QDataStream &stream, const Symbol &symbol);
QDataStream &operator>>(QDataStream &stream, Symbol &symbol);
bool operator==(const Symbol &a, const Symbol &b);
bool operator!=(const Symbol &a, const Symbol &b);
} // Clang
#endif // INDEXEDSYMBOLINFO_H

View File

@@ -179,7 +179,7 @@ bool writeFile(const QString &filePath, const QByteArray &contents)
void insertTextAtTopOfEditor(TextEditor::BaseTextEditor *editor, const QByteArray &text)
{
QTC_ASSERT(editor, return);
Utils::ChangeSet cs;
::Utils::ChangeSet cs;
cs.insert(0, QString::fromUtf8(text));
QTextCursor textCursor = editor->textCursor();
cs.apply(&textCursor);
@@ -380,6 +380,16 @@ QString toString(const RequestDiagnosticsMessage &)
return QStringLiteral("RequestDiagnosticsMessage\n");
}
QString toString(const RequestHighlightingMessage &)
{
return QStringLiteral("RequestHighlightingMessage\n");
}
QString toString(const UpdateVisibleTranslationUnitsMessage &)
{
return QStringLiteral("UpdateVisibleTranslationUnitsMessage\n");
}
class IpcSenderSpy : public IpcSenderInterface
{
public:
@@ -413,6 +423,11 @@ public:
void requestDiagnostics(const RequestDiagnosticsMessage &message) override
{ senderLog.append(toString(message)); }
void requestHighlighting(const RequestHighlightingMessage &message) override
{ senderLog.append(toString(message)); }
void updateVisibleTranslationUnits(const UpdateVisibleTranslationUnitsMessage &message) override
{ senderLog.append(toString(message)); }
public:
QString senderLog;
@@ -1048,6 +1063,8 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeInGeneratedUiFile(
void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderInOtherEditor()
{
QSKIP("We don't reparse anymore before a code completion so we get wrong completion results.");
CppTools::Tests::TemporaryDir temporaryDir;
const TestDocument sourceDocument("mysource.cpp", &temporaryDir);
QVERIFY(sourceDocument.isCreatedAndHasValidCursorPosition());
@@ -1067,6 +1084,7 @@ void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderInOtherEdi
// Switch back to source file and check if modified header is reflected in completions.
Core::EditorManager::activateEditor(openSource.editor());
QCoreApplication::processEvents(); // connections are queued
proposal = completionResults(openSource.editor());
QVERIFY(hasItem(proposal, "globalFromHeader"));
QVERIFY(hasItem(proposal, "globalFromHeaderUnsaved"));
@@ -1074,6 +1092,8 @@ void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderInOtherEdi
void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderByRefactoringActions()
{
QSKIP("We don't reparse anymore before a code completion so we get wrong completion results.");
CppTools::Tests::TemporaryDir temporaryDir;
const TestDocument sourceDocument("mysource.cpp", &temporaryDir);
QVERIFY(sourceDocument.isCreatedAndHasValidCursorPosition());
@@ -1092,7 +1112,7 @@ void ClangCodeCompletionTest::testCompleteAfterModifyingIncludedHeaderByRefactor
// Modify header document without switching to its editor.
// This simulates e.g. changes from refactoring actions.
Utils::ChangeSet cs;
::Utils::ChangeSet cs;
cs.insert(0, QLatin1String("int globalFromHeaderUnsaved;\n"));
QTextCursor textCursor = openHeader.editor()->textCursor();
cs.apply(&textCursor);

View File

@@ -1,357 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "unit.h"
#include "clangutils.h"
#include "unsavedfiledata.h"
#include "utils_p.h"
#include <clang-c/Index.h>
#include <QtCore/QByteArray>
#include <QtCore/QVector>
#include <QtCore/QSharedData>
#ifdef DEBUG_UNIT_COUNT
# include <QAtomicInt>
# include <QDebug>
static QBasicAtomicInt unitDataCount = Q_BASIC_ATOMIC_INITIALIZER(0);
#endif // DEBUG_UNIT_COUNT
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
Unit::Unit()
: m_index(0)
, m_tu(0)
, m_managementOptions(0)
{}
Unit::Unit(const QString &fileName)
: m_index(clang_createIndex(/*excludeDeclsFromPCH*/ 1, Utils::verboseRunLog().isDebugEnabled()))
, m_tu(0)
, m_fileName(fileName.toUtf8())
, m_managementOptions(0)
{}
Unit::~Unit()
{
unload();
clang_disposeIndex(m_index);
m_index = 0;
}
Unit::Ptr Unit::create()
{
return Unit::Ptr(new Unit);
}
Unit::Ptr Unit::create(const QString &fileName)
{
return Unit::Ptr(new Unit(fileName));
}
const QString Unit::fileName() const
{
return QString::fromUtf8(m_fileName.data(), m_fileName.size());
}
bool Unit::isLoaded() const
{
return m_tu && m_index;
}
const QDateTime &Unit::timeStamp() const
{
return m_timeStamp;
}
QStringList Unit::compilationOptions() const
{
return m_compOptions;
}
void Unit::setCompilationOptions(const QStringList &compOptions)
{
m_compOptions = compOptions;
m_sharedCompOptions.reloadOptions(compOptions);
}
UnsavedFiles Unit::unsavedFiles() const
{
return m_unsaved;
}
void Unit::setUnsavedFiles(const UnsavedFiles &unsavedFiles)
{
m_unsaved = unsavedFiles;
}
unsigned Unit::managementOptions() const
{
return m_managementOptions;
}
void Unit::setManagementOptions(unsigned managementOptions)
{
m_managementOptions = managementOptions;
}
void Unit::parse()
{
unload();
updateTimeStamp();
UnsavedFileData unsaved(m_unsaved);
m_tu = clang_parseTranslationUnit(m_index, m_fileName.constData(),
m_sharedCompOptions.data(), m_sharedCompOptions.size(),
unsaved.files(), unsaved.count(),
m_managementOptions);
}
void Unit::reparse()
{
Q_ASSERT(isLoaded());
UnsavedFileData unsaved(m_unsaved);
const unsigned opts = clang_defaultReparseOptions(m_tu);
if (clang_reparseTranslationUnit(m_tu, unsaved.count(), unsaved.files(), opts) != 0)
unload();
}
int Unit::save(const QString &unitFileName)
{
Q_ASSERT(isLoaded());
return clang_saveTranslationUnit(m_tu, unitFileName.toUtf8().constData(),
clang_defaultSaveOptions(m_tu));
}
void Unit::unload()
{
if (m_tu) {
clang_disposeTranslationUnit(m_tu);
m_tu = 0;
#ifdef DEBUG_UNIT_COUNT
qDebug() << "# translation units:" << (unitDataCount.fetchAndAddOrdered(-1) - 1);
#endif // DEBUG_UNIT_COUNT
}
}
CXFile Unit::getFile() const
{
Q_ASSERT(isLoaded());
return clang_getFile(m_tu, m_fileName.constData());
}
CXCursor Unit::getCursor(const CXSourceLocation &location) const
{
Q_ASSERT(isLoaded());
return clang_getCursor(m_tu, location);
}
CXSourceLocation Unit::getLocation(const CXFile &file, unsigned line, unsigned column) const
{
Q_ASSERT(isLoaded());
return clang_getLocation(m_tu, file, line, column);
}
void Unit::codeCompleteAt(unsigned line, unsigned column, ScopedCXCodeCompleteResults &results)
{
unsigned flags = clang_defaultCodeCompleteOptions();
#if defined(CINDEX_VERSION) && (CINDEX_VERSION > 5)
flags |= CXCodeComplete_IncludeBriefComments;
#endif
UnsavedFileData unsaved(m_unsaved);
results.reset(clang_codeCompleteAt(m_tu, m_fileName.constData(),
line, column,
unsaved.files(), unsaved.count(),
flags));
}
void Unit::tokenize(CXSourceRange range, CXToken **tokens, unsigned *tokenCount) const
{
Q_ASSERT(isLoaded());
Q_ASSERT(tokens);
Q_ASSERT(tokenCount);
Q_ASSERT(!clang_Range_isNull(range));
clang_tokenize(m_tu, range, tokens, tokenCount);
}
void Unit::disposeTokens(CXToken *tokens, unsigned tokenCount) const
{
Q_ASSERT(isLoaded());
clang_disposeTokens(m_tu, tokens, tokenCount);
}
CXSourceRange Unit::getTokenExtent(const CXToken &token) const
{
Q_ASSERT(isLoaded());
return clang_getTokenExtent(m_tu, token);
}
void Unit::annotateTokens(CXToken *tokens, unsigned tokenCount, CXCursor *cursors) const
{
Q_ASSERT(isLoaded());
Q_ASSERT(tokens);
Q_ASSERT(cursors);
clang_annotateTokens(m_tu, tokens, tokenCount, cursors);
}
CXTranslationUnit Unit::clangTranslationUnit() const
{
Q_ASSERT(isLoaded());
return m_tu;
}
CXIndex Unit::clangIndex() const
{
Q_ASSERT(isLoaded());
return m_index;
}
QString Unit::getTokenSpelling(const CXToken &tok) const
{
Q_ASSERT(isLoaded());
return getQString(clang_getTokenSpelling(m_tu, tok));
}
CXCursor Unit::getTranslationUnitCursor() const
{
Q_ASSERT(isLoaded());
return clang_getTranslationUnitCursor(m_tu);
}
CXString Unit::getTranslationUnitSpelling() const
{
Q_ASSERT(isLoaded());
return clang_getTranslationUnitSpelling(m_tu);
}
void Unit::getInclusions(CXInclusionVisitor visitor, CXClientData clientData) const
{
Q_ASSERT(isLoaded());
clang_getInclusions(m_tu, visitor, clientData);
}
unsigned Unit::getNumDiagnostics() const
{
Q_ASSERT(isLoaded());
return clang_getNumDiagnostics(m_tu);
}
CXDiagnostic Unit::getDiagnostic(unsigned index) const
{
Q_ASSERT(isLoaded());
return clang_getDiagnostic(m_tu, index);
}
void Unit::updateTimeStamp()
{
m_timeStamp = QDateTime::currentDateTime();
}
IdentifierTokens::IdentifierTokens(const Unit &unit, unsigned firstLine, unsigned lastLine)
: m_unit(unit)
, m_tokenCount(0)
, m_tokens(0)
, m_cursors(0)
, m_extents(0)
{
Q_ASSERT(unit.isLoaded());
// Calculate the range:
CXFile file = unit.getFile();
CXSourceLocation startLocation = unit.getLocation(file, firstLine, 1);
CXSourceLocation endLocation = unit.getLocation(file, lastLine, 1);
CXSourceRange range = clang_getRange(startLocation, endLocation);
// Retrieve all identifier tokens:
unit.tokenize(range, &m_tokens, &m_tokenCount);
if (m_tokenCount == 0)
return;
// Get the cursors for the tokens:
m_cursors = new CXCursor[m_tokenCount];
unit.annotateTokens(m_tokens,
m_tokenCount,
m_cursors);
m_extents = new CXSourceRange[m_tokenCount];
// Create the markers using the cursor to check the types:
for (unsigned i = 0; i < m_tokenCount; ++i)
m_extents[i] = unit.getTokenExtent(m_tokens[i]);
}
IdentifierTokens::~IdentifierTokens()
{
dispose();
}
void IdentifierTokens::dispose()
{
if (!m_unit.isLoaded())
return;
if (m_tokenCount && m_tokens) {
m_unit.disposeTokens(m_tokens, m_tokenCount);
m_tokens = 0;
m_tokenCount = 0;
}
if (m_cursors) {
delete[] m_cursors;
m_cursors = 0;
}
if (m_extents) {
delete[] m_extents;
m_extents = 0;
}
}

View File

@@ -1,200 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef UNIT_H
#define UNIT_H
#include "utils.h"
#include "raii/scopedclangoptions.h"
#include "cxraii.h"
#include <QtCore/QDateTime>
#include <QSharedPointer>
#include <QMetaType>
#include <QString>
#include <QStringList>
#include <QVarLengthArray>
QT_BEGIN_NAMESPACE
class QDateTime;
QT_END_NAMESPACE
namespace ClangCodeModel {
namespace Internal {
class UnitData;
/*
* This is a minimal wrapper around clang's translation unit functionality.
* It should should contain only the very basic primitives which allow other
* components such as code completion, code navigation, and others to access
* data which directly depends on the translation unit.
*
* In other words, what's wrapped here is only the functions that receive a
* CXTranslationUnit as a parameter. And this class itself is then the corresponding
* abstraction of the CXTranslationUnit.
*
* Notes:
* - This class is not thread-safe.
* - It's responsibility of the client to make sure that the wrapped translation
* unit is consistent with the other data such as cursor and locations being used.
*
* @TODO: This is similar but not exactly the same as the current ClangWrapper class.
* That class is now tuned to specific features, so it's not generic enough to be used
* an underlying component and aslo don't provide the data in a fine granularity as
* needed here. At some point we should split ClangWrapper into its different logical
* components and use this is the underlying structure.
*/
class Unit
{
Q_DISABLE_COPY(Unit)
Unit();
explicit Unit(const QString &fileName);
public:
~Unit();
typedef QSharedPointer<Unit> Ptr;
static Ptr create();
static Ptr create(const QString &fileName);
bool isLoaded() const;
const QString fileName() const;
const QDateTime &timeStamp() const;
QStringList compilationOptions() const;
void setCompilationOptions(const QStringList &compOptions);
UnsavedFiles unsavedFiles() const;
void setUnsavedFiles(const UnsavedFiles &unsavedFiles);
unsigned managementOptions() const;
void setManagementOptions(unsigned managementOptions);
// Methods for generating the TU. Name mappings are direct, for example:
// - parse corresponds to clang_parseTranslationUnit
// - createFromSourceFile corresponds to clang_createTranslationUnitFromSourceFile
void parse();
void reparse();
int save(const QString &unitFileName);
void unload();
// Simple forwarding methods, separated by clang categories for convenience.
// As above, the names are directly mapped. Separated by categories as clang for convenience.
// Note that only methods that take the TU as a parameter should be wrapped.
// - Diagnostic reporting
unsigned getNumDiagnostics() const;
CXDiagnostic getDiagnostic(unsigned index) const;
// - Translation unit manipulation
CXString getTranslationUnitSpelling() const;
// - File manipulation routines
CXFile getFile() const;
// - Mapping between cursors and source code
CXCursor getCursor(const CXSourceLocation &location) const;
// - Miscellaneous utility functions
void getInclusions(CXInclusionVisitor visitor, CXClientData clientData) const;
// - Cursor manipulations
CXCursor getTranslationUnitCursor() const;
// - Physical source locations
CXSourceLocation getLocation(const CXFile &file, unsigned line, unsigned column) const;
void codeCompleteAt(unsigned line, unsigned column, ScopedCXCodeCompleteResults &results);
void tokenize(CXSourceRange range, CXToken **tokens, unsigned *tokenCount) const;
void disposeTokens(CXToken *tokens, unsigned tokenCount) const;
CXSourceRange getTokenExtent(const CXToken &token) const;
void annotateTokens(CXToken *tokens, unsigned tokenCount, CXCursor *cursors) const;
CXTranslationUnit clangTranslationUnit() const;
CXIndex clangIndex() const;
QString getTokenSpelling(const CXToken &tok) const;
private:
void updateTimeStamp();
CXIndex m_index;
CXTranslationUnit m_tu;
QByteArray m_fileName;
QStringList m_compOptions;
SharedClangOptions m_sharedCompOptions;
unsigned m_managementOptions;
UnsavedFiles m_unsaved;
QDateTime m_timeStamp;
};
class IdentifierTokens
{
Q_DISABLE_COPY(IdentifierTokens)
public:
IdentifierTokens(const Unit &m_unit, unsigned firstLine, unsigned lastLine);
~IdentifierTokens();
unsigned count() const
{ return m_tokenCount; }
const CXToken &token(unsigned nr) const
{ Q_ASSERT(nr < count()); return m_tokens[nr]; }
const CXCursor &cursor(unsigned nr) const
{ Q_ASSERT(nr < count()); return m_cursors[nr]; }
const CXSourceRange &extent(unsigned nr) const
{ Q_ASSERT(nr < count()); return m_extents[nr]; }
private:
void dispose();
private:
const Unit &m_unit;
unsigned m_tokenCount;
CXToken *m_tokens;
CXCursor *m_cursors;
CXSourceRange *m_extents;
};
} // Internal
} // Clang
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Unit::Ptr)
#endif // UNIT_H

View File

@@ -1,62 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "unsavedfiledata.h"
using namespace ClangCodeModel::Internal;
UnsavedFileData::UnsavedFileData(const UnsavedFiles &unsavedFiles)
: m_count(unsavedFiles.count())
, m_files(0)
{
if (m_count) {
m_files = new CXUnsavedFile[m_count];
unsigned idx = 0;
for (UnsavedFiles::const_iterator it = unsavedFiles.begin(); it != unsavedFiles.end(); ++it, ++idx) {
QByteArray contents = it.value();
const char *contentChars = qstrdup(contents.constData());
m_files[idx].Contents = contentChars;
m_files[idx].Length = contents.size();
const char *fileName = qstrdup(it.key().toUtf8().constData());
m_files[idx].Filename = fileName;
}
}
}
UnsavedFileData::~UnsavedFileData()
{
for (unsigned i = 0; i < m_count; ++i) {
delete[] m_files[i].Contents;
delete[] m_files[i].Filename;
}
delete[] m_files;
}

View File

@@ -1,66 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANG_INTERNAL_UNSAVEDFILEDATA_H
#define CLANG_INTERNAL_UNSAVEDFILEDATA_H
#include "utils.h"
#include <clang-c/Index.h>
namespace ClangCodeModel {
namespace Internal {
class UnsavedFileData
{
UnsavedFileData(const UnsavedFileData &);
UnsavedFileData &operator=(const UnsavedFileData &);
typedef ClangCodeModel::Internal::UnsavedFiles UnsavedFiles;
public:
UnsavedFileData(const UnsavedFiles &unsavedFiles);
~UnsavedFileData();
unsigned count() const
{ return m_count; }
CXUnsavedFile *files() const
{ return m_files; }
private:
unsigned m_count;
CXUnsavedFile *m_files;
};
} // namespace Internal
} // namespace ClangCodeModel
#endif // CLANG_INTERNAL_UNSAVEDFILEDATA_H

View File

@@ -1,90 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "diagnostic.h"
#include "unit.h"
#include "utils.h"
#include "utils_p.h"
#include <clang-c/Index.h>
#include <QMutex>
#include <QMutexLocker>
namespace ClangCodeModel {
namespace Internal {
QPair<bool, QStringList> precompile(const PchInfo::Ptr &pchInfo)
{
// qDebug() << "*** Precompiling" << pchInfo->inputFileName()
// << "into" << pchInfo->fileName()
// << "with options" << pchInfo->options();
bool ok = false;
Internal::Unit::Ptr unit = Internal::Unit::create(pchInfo->inputFileName());
unit->setCompilationOptions(pchInfo->options());
unsigned parseOpts = CXTranslationUnit_ForSerialization
| CXTranslationUnit_Incomplete;
unit->setManagementOptions(parseOpts);
unit->parse();
if (unit->isLoaded())
ok = CXSaveError_None == unit->save(pchInfo->fileName());
return qMakePair(ok, Internal::formattedDiagnostics(unit));
}
namespace {
static bool clangInitialised = false;
static QMutex initialisationMutex;
} // anonymous namespace
void initializeClang()
{
if (clangInitialised)
return;
QMutexLocker locker(&initialisationMutex);
if (clangInitialised)
return;
clang_toggleCrashRecovery(1);
clang_enableStackTraces();
clangInitialised = true;
qRegisterMetaType<ClangCodeModel::Diagnostic>();
qRegisterMetaType<QList<ClangCodeModel::Diagnostic> >();
}
} // Internal namespace
} // ClangCodeModel namespace

View File

@@ -1,66 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef UTILS_H
#define UTILS_H
#include "pchinfo.h"
#include <QString>
#include <QStringList>
#include <QByteArray>
#include <QMap>
#include <QPair>
/*
* A header for globally visible typedefs. This is particularly useful
* so we don't have to #include files simply because of a typedef. Still,
* not every typedef should go in here, only the minimal subset of the
* ones which are needed quite often.
*/
namespace ClangCodeModel {
namespace Internal {
typedef QMap<QString, QByteArray> UnsavedFiles;
/**
* Utility method to create a PCH file from a header file.
*
* \returns a boolean indicating success (true) or failure (false), and a
* list of diagnostic messages.
*/
QPair<bool, QStringList> precompile(const PchInfo::Ptr &pchInfo);
void initializeClang();
} // Internal namespace
} // ClangCodeModel namespace
#endif // UTILS_H

View File

@@ -1,125 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "unit.h"
#include "utils_p.h"
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
namespace ClangCodeModel {
namespace Internal {
QString getQString(const CXString &cxString, bool disposeCXString)
{
QString s = QString::fromUtf8(clang_getCString(cxString));
if (disposeCXString)
clang_disposeString(cxString);
return s;
}
namespace {
SourceLocation getLocation(const CXSourceLocation &loc,
void (*clangFunction)(CXSourceLocation,
CXFile *,
unsigned *,
unsigned *,
unsigned *))
{
CXFile file;
unsigned line, column, offset;
(*clangFunction)(loc, &file, &line, &column, &offset);
return SourceLocation(normalizeFileName(getQString(clang_getFileName(file))),
line,
column,
offset);
}
} // Anonymous
SourceLocation getInstantiationLocation(const CXSourceLocation &loc)
{
return getLocation(loc, &clang_getInstantiationLocation);
}
SourceLocation getSpellingLocation(const CXSourceLocation &loc)
{
return getLocation(loc, &clang_getSpellingLocation);
}
SourceLocation getExpansionLocation(const CXSourceLocation &loc)
{
// return getLocation(loc, &clang_getExpansionLocation);
return getLocation(loc, &clang_getInstantiationLocation);
}
QString normalizeFileName(const QString &fileName)
{
if (fileName.isEmpty())
return fileName;
return normalizeFileName(QFileInfo(fileName));
}
QString normalizeFileName(const QFileInfo &fileInfo)
{
if (!fileInfo.isFile())
return QString();
return QDir::cleanPath(fileInfo.absoluteFilePath());
}
QStringList formattedDiagnostics(const Unit::Ptr &unit)
{
QStringList diags;
if (!unit->isLoaded())
return diags;
const unsigned count = unit->getNumDiagnostics();
for (unsigned i = 0; i < count; ++i) {
CXDiagnostic diag = unit->getDiagnostic(i);
unsigned opt = CXDiagnostic_DisplaySourceLocation
| CXDiagnostic_DisplayColumn
| CXDiagnostic_DisplaySourceRanges
| CXDiagnostic_DisplayOption
| CXDiagnostic_DisplayCategoryId
| CXDiagnostic_DisplayCategoryName
;
diags << getQString(clang_formatDiagnostic(diag, opt));
clang_disposeDiagnostic(diag);
}
return diags;
}
} // Internal
} // ClangCodeModel

View File

@@ -1,66 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANG_REUSE_H
#define CLANG_REUSE_H
#include "sourcelocation.h"
#include "unit.h"
#include <clang-c/Index.h>
#include <QtCore/QString>
QT_BEGIN_NAMESPACE
class QFileInfo;
QT_END_NAMESPACE
namespace ClangCodeModel {
namespace Internal {
QString getQString(const CXString &cxString, bool disposeCXString = true);
SourceLocation getInstantiatonLocation(const CXSourceLocation &loc); // Deprecated
SourceLocation getSpellingLocation(const CXSourceLocation &loc);
SourceLocation getExpansionLocation(const CXSourceLocation &loc);
// There are slight differences of behavior from apparently similar Qt file processing functions.
// For instance, QFileInfo::absoluteFilePath will uppercase driver letters, while the corresponding
// QDir function will not do so. Besides, we need to keep paths clean. So in order to avoid
// inconsistencies the functions below should be used for any indexing related task.
QString normalizeFileName(const QString &fileName);
QString normalizeFileName(const QFileInfo &fileInfo);
QStringList formattedDiagnostics(const Unit::Ptr &unit);
} // Internal
} // ClangCodeModel
#endif // CLANG_REUSE_H