Clang: Use completion through backend process

This makes us independent of libclang crashes for completion.
Re-parsing for highlighting still happens in the Qt Creator process.

Run in verbose mode:
    qtc.clangcodemodel.ipc=true

Run tests:
    -test "ClangCodeModel"

Task-number: QTCREATORBUG-14108
Task-number: QTCREATORBUG-12819
Change-Id: Id3e95bd2afdb6508bbd1d35fddc69534a909b905
Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
This commit is contained in:
Nikolai Kosjar
2015-05-08 15:48:17 +02:00
parent 264132da27
commit 23b8a3b2e8
59 changed files with 3820 additions and 634 deletions

View File

@@ -28,43 +28,178 @@
**
****************************************************************************/
#include "clangmodelmanagersupport.h"
#include "constants.h"
#include "clangcompletion.h"
#include "clangeditordocumentprocessor.h"
#include "clangmodelmanagersupport.h"
#include "clangutils.h"
#include <coreplugin/editormanager/editormanager.h>
#include <cpptools/baseeditordocumentparser.h>
#include <cpptools/editordocumenthandle.h>
#include <projectexplorer/project.h>
#include <codemodelbackendipc/cmbregisterprojectsforcodecompletioncommand.h>
#include <codemodelbackendipc/filecontainer.h>
#include <codemodelbackendipc/projectpartcontainer.h>
#include <utils/qtcassert.h>
#include <QCoreApplication>
using namespace ClangCodeModel;
using namespace ClangCodeModel::Internal;
ModelManagerSupport::ModelManagerSupport()
: m_completionAssistProvider(new ClangCompletionAssistProvider)
static ModelManagerSupportClang *m_instance = 0;
static CppTools::CppModelManager *cppModelManager()
{
return CppTools::CppModelManager::instance();
}
ModelManagerSupport::~ModelManagerSupport()
ModelManagerSupportClang::ModelManagerSupportClang()
: m_ipcCommunicator(new IpcCommunicator)
, m_completionAssistProvider(new ClangCompletionAssistProvider(m_ipcCommunicator))
{
QTC_CHECK(!m_instance);
m_instance = this;
Core::EditorManager *editorManager = Core::EditorManager::instance();
connect(editorManager, &Core::EditorManager::currentEditorChanged,
this, &ModelManagerSupportClang::onCurrentEditorChanged);
connect(editorManager, &Core::EditorManager::editorOpened,
this, &ModelManagerSupportClang::onEditorOpened);
CppTools::CppModelManager *modelManager = cppModelManager();
connect(modelManager, &CppTools::CppModelManager::projectPartsUpdated,
this, &ModelManagerSupportClang::onProjectPartsUpdated);
connect(modelManager, &CppTools::CppModelManager::projectPartsRemoved,
this, &ModelManagerSupportClang::onProjectPartsRemoved);
}
QString ModelManagerSupport::id() const
ModelManagerSupportClang::~ModelManagerSupportClang()
{
return QLatin1String("ClangCodeMode.ClangCodeMode");
m_instance = 0;
}
QString ModelManagerSupport::displayName() const
CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssistProvider()
{
return m_completionAssistProvider.data();
}
CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument)
{
return new ClangEditorDocumentProcessor(this, baseTextDocument);
}
void ModelManagerSupportClang::onCurrentEditorChanged(Core::IEditor *newCurrent)
{
// 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->updateUnsavedFileFromCppEditorDocument(
m_previousCppEditor->document()->filePath().toString());
}
// Remember previous editor
if (newCurrent && cppModelManager()->isCppEditor(newCurrent))
m_previousCppEditor = newCurrent;
else
m_previousCppEditor.clear();
}
void ModelManagerSupportClang::onEditorOpened(Core::IEditor *editor)
{
QTC_ASSERT(editor, return);
Core::IDocument *document = editor->document();
QTC_ASSERT(document, return);
TextEditor::TextDocument *textDocument = qobject_cast<TextEditor::TextDocument *>(document);
QTC_ASSERT(textDocument, return);
if (cppModelManager()->isCppEditor(editor)) {
// Handle externally changed documents
connect(textDocument, &Core::IDocument::reloadFinished,
this, &ModelManagerSupportClang::onCppDocumentReloadFinished,
Qt::UniqueConnection);
// Handle changes from e.g. refactoring actions
connect(textDocument, &TextEditor::TextDocument::contentsChanged,
this, &ModelManagerSupportClang::onCppDocumentContentsChanged,
Qt::UniqueConnection);
// TODO: Ensure that not fully loaded documents are updated?
}
}
void ModelManagerSupportClang::onCppDocumentReloadFinished(bool success)
{
if (!success)
return;
Core::IDocument *document = qobject_cast<Core::IDocument *>(sender());
m_ipcCommunicator->updateUnsavedFileIfNotCurrentDocument(document);
}
void ModelManagerSupportClang::onCppDocumentContentsChanged()
{
Core::IDocument *document = qobject_cast<Core::IDocument *>(sender());
m_ipcCommunicator->updateUnsavedFileIfNotCurrentDocument(document);
}
void ModelManagerSupportClang::onAbstractEditorSupportContentsUpdated(const QString &filePath,
const QByteArray &content)
{
QTC_ASSERT(!filePath.isEmpty(), return);
m_ipcCommunicator->updateUnsavedFile(filePath, content);
}
void ModelManagerSupportClang::onAbstractEditorSupportRemoved(const QString &filePath)
{
QTC_ASSERT(!filePath.isEmpty(), return);
if (!cppModelManager()->cppEditorDocument(filePath)) {
const QString projectFilePath = Utils::projectFilePathForFile(filePath);
m_ipcCommunicator->unregisterFilesForCodeCompletion(
{CodeModelBackEnd::FileContainer(filePath, projectFilePath)});
}
}
void ModelManagerSupportClang::onProjectPartsUpdated(ProjectExplorer::Project *project)
{
QTC_ASSERT(project, return);
const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project);
QTC_ASSERT(projectInfo.isValid(), return);
m_ipcCommunicator->registerProjectsParts(projectInfo.projectParts());
}
void ModelManagerSupportClang::onProjectPartsRemoved(const QStringList &projectFiles)
{
m_ipcCommunicator->unregisterProjectPartsForCodeCompletion(projectFiles);
}
ModelManagerSupportClang *ModelManagerSupportClang::instance()
{
return m_instance;
}
IpcCommunicator::Ptr ModelManagerSupportClang::ipcCommunicator()
{
return m_ipcCommunicator;
}
QString ModelManagerSupportProviderClang::id() const
{
return QLatin1String(Constants::CLANG_MODELMANAGERSUPPORT_ID);
}
QString ModelManagerSupportProviderClang::displayName() const
{
//: Display name
return QCoreApplication::translate("ClangCodeModel::Internal::ModelManagerSupport",
"Clang");
}
CppTools::CppCompletionAssistProvider *ModelManagerSupport::completionAssistProvider()
CppTools::ModelManagerSupport::Ptr ModelManagerSupportProviderClang::createModelManagerSupport()
{
return m_completionAssistProvider.data();
}
CppTools::BaseEditorDocumentProcessor *ModelManagerSupport::editorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument)
{
return new ClangEditorDocumentProcessor(baseTextDocument);
return CppTools::ModelManagerSupport::Ptr(new ModelManagerSupportClang);
}