forked from qt-creator/qt-creator
CppEditor: Rework showing/switching parse configurations
* Move the combox box for switching the parse configurations out of the "Additional Preprocessor Directives" dialog ('#'-button) to make it better visible/accessible. Also, decouple the extra preprocessor directives from the concrete parse context since this is not anymore in same dialog. * The combo box appears only if multiple parse configurations are available for a file. * The first time multiple parse configurations are detected, an info bar is shown that points the user to the combox box. A "Do Not Show Again" button is provided. * Upon selecting an entry, the preferred parse configuration is saved as part of the session. The setting can be cleared with the context menu entry on the combo box. Follow-up changes need to ensure that the display name and/or tooltip is unambiguous, e.g. for qbs and cmake projects. Change-Id: I9e9773704187291524ad7b605bfdddd83ef5b19d Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -280,6 +280,13 @@ void ClangEditorDocumentProcessor::editorDocumentTimerRestarted()
|
||||
m_updateTranslationUnitTimer.stop(); // Wait for the next call to run().
|
||||
}
|
||||
|
||||
void ClangEditorDocumentProcessor::setParserConfig(
|
||||
const CppTools::BaseEditorDocumentParser::Configuration config)
|
||||
{
|
||||
m_parser->setConfiguration(config);
|
||||
m_builtinProcessor.parser()->setConfiguration(config);
|
||||
}
|
||||
|
||||
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const
|
||||
{
|
||||
return fileContainerWithArguments(m_projectPart.data());
|
||||
|
@@ -82,6 +82,8 @@ public:
|
||||
|
||||
void editorDocumentTimerRestarted() override;
|
||||
|
||||
void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override;
|
||||
|
||||
ClangBackEnd::FileContainer fileContainerWithArguments() const;
|
||||
|
||||
void clearDiagnosticsWithFixIts();
|
||||
|
@@ -131,6 +131,8 @@ public:
|
||||
|
||||
QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
|
||||
|
||||
QAction *m_parseContextAction = nullptr;
|
||||
ParseContextWidget *m_parseContextWidget = nullptr;
|
||||
QToolButton *m_preprocessorButton = nullptr;
|
||||
MinimizableInfoBars::Actions m_showInfoBarActions;
|
||||
|
||||
@@ -222,7 +224,7 @@ void CppEditorWidget::finalizeInitialization()
|
||||
d->m_cppSelectionChanger.onCursorPositionChanged(textCursor());
|
||||
});
|
||||
|
||||
// Tool bar creation
|
||||
// Toolbar: '#' Button
|
||||
d->m_preprocessorButton = new QToolButton(this);
|
||||
d->m_preprocessorButton->setText(QLatin1String("#"));
|
||||
Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
|
||||
@@ -231,13 +233,25 @@ void CppEditorWidget::finalizeInitialization()
|
||||
connect(d->m_preprocessorButton, &QAbstractButton::clicked, this, &CppEditorWidget::showPreProcessorWidget);
|
||||
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton);
|
||||
|
||||
// Actions to show minimized info bars
|
||||
// Toolbar: Actions to show minimized info bars
|
||||
d->m_showInfoBarActions = MinimizableInfoBars::createShowInfoBarActions([this](QWidget *w) {
|
||||
return this->insertExtraToolBarWidget(TextEditorWidget::Left, w);
|
||||
});
|
||||
connect(&cppEditorDocument()->minimizableInfoBars(), &MinimizableInfoBars::showAction,
|
||||
this, &CppEditorWidget::onShowInfoBarAction);
|
||||
|
||||
// Toolbar: Parse context
|
||||
ParseContextModel &parseContextModel = cppEditorDocument()->parseContextModel();
|
||||
d->m_parseContextWidget = new ParseContextWidget(parseContextModel, this);
|
||||
d->m_parseContextAction = insertExtraToolBarWidget(TextEditorWidget::Left,
|
||||
d->m_parseContextWidget);
|
||||
d->m_parseContextAction->setVisible(false);
|
||||
connect(&parseContextModel, &ParseContextModel::updated,
|
||||
this, [this](bool areMultipleAvailable) {
|
||||
d->m_parseContextAction->setVisible(areMultipleAvailable);
|
||||
});
|
||||
|
||||
// Toolbar: Outline/Overview combo box
|
||||
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget());
|
||||
}
|
||||
|
||||
@@ -252,6 +266,10 @@ void CppEditorWidget::finalizeInitializationAfterDuplication(TextEditorWidget *o
|
||||
d->m_cppEditorOutline->update();
|
||||
const Id selectionKind = CodeWarningsSelection;
|
||||
setExtraSelections(selectionKind, cppEditorWidget->extraSelections(selectionKind));
|
||||
|
||||
d->m_parseContextWidget->syncToModel();
|
||||
d->m_parseContextAction->setVisible(
|
||||
d->m_cppEditorDocument->parseContextModel().areMultipleAvailable());
|
||||
}
|
||||
|
||||
CppEditorWidget::~CppEditorWidget()
|
||||
@@ -972,20 +990,12 @@ void CppEditorWidget::abortDeclDefLink()
|
||||
|
||||
void CppEditorWidget::showPreProcessorWidget()
|
||||
{
|
||||
const Utils::FileName fileName = textDocument()->filePath();
|
||||
const QString filePath = textDocument()->filePath().toString();
|
||||
|
||||
// Check if this editor belongs to a project
|
||||
QList<ProjectPart::Ptr> projectParts = d->m_modelManager->projectPart(fileName);
|
||||
if (projectParts.isEmpty())
|
||||
projectParts = d->m_modelManager->projectPartFromDependencies(fileName);
|
||||
if (projectParts.isEmpty())
|
||||
projectParts << d->m_modelManager->fallbackProjectPart();
|
||||
|
||||
CppPreProcessorDialog preProcessorDialog(this, textDocument()->filePath().toString(), projectParts);
|
||||
if (preProcessorDialog.exec() == QDialog::Accepted) {
|
||||
cppEditorDocument()->setPreprocessorSettings(
|
||||
preProcessorDialog.projectPart(),
|
||||
preProcessorDialog.additionalPreProcessorDirectives().toUtf8());
|
||||
CppPreProcessorDialog dialog(filePath, this);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
const QByteArray extraDirectives = dialog.extraPreprocessorDirectives().toUtf8();
|
||||
cppEditorDocument()->setExtraPreprocessorDirectives(extraDirectives);
|
||||
cppEditorDocument()->scheduleProcessDocument();
|
||||
}
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ HEADERS += \
|
||||
cppfunctiondecldeflink.h \
|
||||
cpphighlighter.h \
|
||||
cpphoverhandler.h \
|
||||
cppparsecontext.h \
|
||||
cppincludehierarchy.h \
|
||||
cppinsertvirtualmethods.h \
|
||||
cpplocalrenaming.h \
|
||||
@@ -46,6 +47,7 @@ SOURCES += \
|
||||
cppfunctiondecldeflink.cpp \
|
||||
cpphighlighter.cpp \
|
||||
cpphoverhandler.cpp \
|
||||
cppparsecontext.cpp \
|
||||
cppincludehierarchy.cpp \
|
||||
cppinsertvirtualmethods.cpp \
|
||||
cpplocalrenaming.cpp \
|
||||
|
@@ -43,6 +43,7 @@ QtcPlugin {
|
||||
"cppminimizableinfobars.cpp", "cppminimizableinfobars.h",
|
||||
"cppoutline.cpp", "cppoutline.h",
|
||||
"cpppreprocessordialog.cpp", "cpppreprocessordialog.h", "cpppreprocessordialog.ui",
|
||||
"cppparsecontext.cpp", "cppparsecontext.h",
|
||||
"cppquickfix.cpp", "cppquickfix.h",
|
||||
"cppquickfixassistant.cpp", "cppquickfixassistant.h",
|
||||
"cppquickfixes.cpp", "cppquickfixes.h",
|
||||
|
@@ -37,6 +37,7 @@ const char RENAME_SYMBOL_UNDER_CURSOR[] = "CppEditor.RenameSymbolUnderCursor";
|
||||
const char FIND_USAGES[] = "CppEditor.FindUsages";
|
||||
const char OPEN_PREPROCESSOR_DIALOG[] = "CppEditor.OpenPreprocessorDialog";
|
||||
const char ERRORS_IN_HEADER_FILES[] = "CppEditor.ErrorsInHeaderFiles";
|
||||
const char MULTIPLE_PARSE_CONTEXTS_AVAILABLE[] = "CppEditor.MultipleParseContextsAvailable";
|
||||
const char NO_PROJECT_CONFIGURATION[] = "CppEditor.NoProjectConfiguration";
|
||||
const char M_REFACTORING_MENU_INSERTION_POINT[] = "CppEditor.RefactorGroup";
|
||||
const char UPDATE_CODEMODEL[] = "CppEditor.UpdateCodeModel";
|
||||
@@ -50,7 +51,8 @@ const char OPEN_INCLUDE_HIERARCHY[] = "CppEditor.OpenIncludeHierarchy";
|
||||
|
||||
const char CPP_SNIPPETS_GROUP_ID[] = "C++";
|
||||
|
||||
const char CPP_PREPROCESSOR_PROJECT_PREFIX[] = "CppPreprocessorProject-";
|
||||
const char EXTRA_PREPROCESSOR_DIRECTIVES[] = "CppEditor.ExtraPreprocessorDirectives-";
|
||||
const char PREFERRED_PARSE_CONTEXT[] = "CppEditor.PreferredParseContext-";
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace CppEditor
|
||||
|
@@ -30,6 +30,8 @@
|
||||
#include "cpphighlighter.h"
|
||||
#include "cppquickfixassistant.h"
|
||||
|
||||
#include <coreplugin/infobar.h>
|
||||
|
||||
#include <cpptools/baseeditordocumentparser.h>
|
||||
#include <cpptools/builtineditordocumentprocessor.h>
|
||||
#include <cpptools/cppcodeformatter.h>
|
||||
@@ -115,6 +117,9 @@ CppEditorDocument::CppEditorDocument()
|
||||
connect(this, &IDocument::filePathChanged,
|
||||
this, &CppEditorDocument::onFilePathChanged);
|
||||
|
||||
connect(&m_parseContextModel, &ParseContextModel::preferredParseContextChanged,
|
||||
this, &CppEditorDocument::reparseWithPreferredParseContext);
|
||||
|
||||
// See also onFilePathChanged() for more initialization
|
||||
}
|
||||
|
||||
@@ -204,6 +209,21 @@ void CppEditorDocument::onReloadFinished()
|
||||
m_fileIsBeingReloaded = false;
|
||||
}
|
||||
|
||||
void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseContextId)
|
||||
{
|
||||
using namespace CppTools;
|
||||
|
||||
// Update parser
|
||||
setPreferredParseContext(parseContextId);
|
||||
|
||||
// Remember the setting
|
||||
const QString key = Constants::PREFERRED_PARSE_CONTEXT + filePath().toString();
|
||||
ProjectExplorer::SessionManager::setValue(key, parseContextId);
|
||||
|
||||
// Reprocess
|
||||
scheduleProcessDocument();
|
||||
}
|
||||
|
||||
void CppEditorDocument::onFilePathChanged(const Utils::FileName &oldPath,
|
||||
const Utils::FileName &newPath)
|
||||
{
|
||||
@@ -222,7 +242,8 @@ void CppEditorDocument::onFilePathChanged(const Utils::FileName &oldPath,
|
||||
m_editorDocumentHandle.reset(new CppEditorDocumentHandleImpl(this));
|
||||
|
||||
resetProcessor();
|
||||
updatePreprocessorSettings();
|
||||
applyPreferredParseContextFromSettings();
|
||||
applyExtraPreprocessorDirectivesFromSettings();
|
||||
m_processorRevision = document()->revision();
|
||||
processDocument();
|
||||
}
|
||||
@@ -256,34 +277,51 @@ void CppEditorDocument::resetProcessor()
|
||||
processor(); // creates a new processor
|
||||
}
|
||||
|
||||
void CppEditorDocument::updatePreprocessorSettings()
|
||||
void CppEditorDocument::applyPreferredParseContextFromSettings()
|
||||
{
|
||||
if (filePath().isEmpty())
|
||||
return;
|
||||
|
||||
const QString prefix = QLatin1String(Constants::CPP_PREPROCESSOR_PROJECT_PREFIX);
|
||||
const QString &projectPartId = ProjectExplorer::SessionManager::value(
|
||||
prefix + filePath().toString()).toString();
|
||||
const QString directivesKey = projectPartId + QLatin1Char(',') + filePath().toString();
|
||||
const QByteArray additionalDirectives = ProjectExplorer::SessionManager::value(
|
||||
directivesKey).toString().toUtf8();
|
||||
const QString key = Constants::PREFERRED_PARSE_CONTEXT + filePath().toString();
|
||||
const QString parseContextId = ProjectExplorer::SessionManager::value(key).toString();
|
||||
|
||||
setPreprocessorSettings(mm()->projectPartForId(projectPartId), additionalDirectives);
|
||||
setPreferredParseContext(parseContextId);
|
||||
}
|
||||
|
||||
void CppEditorDocument::setPreprocessorSettings(const CppTools::ProjectPart::Ptr &projectPart,
|
||||
const QByteArray &defines)
|
||||
void CppEditorDocument::applyExtraPreprocessorDirectivesFromSettings()
|
||||
{
|
||||
if (filePath().isEmpty())
|
||||
return;
|
||||
|
||||
const QString key = Constants::EXTRA_PREPROCESSOR_DIRECTIVES + filePath().toString();
|
||||
const QByteArray directives = ProjectExplorer::SessionManager::value(key).toString().toUtf8();
|
||||
|
||||
setExtraPreprocessorDirectives(directives);
|
||||
}
|
||||
|
||||
void CppEditorDocument::setExtraPreprocessorDirectives(const QByteArray &directives)
|
||||
{
|
||||
const auto parser = processor()->parser();
|
||||
QTC_ASSERT(parser, return);
|
||||
if (parser->projectPartInfo().projectPart != projectPart
|
||||
|| parser->configuration().editorDefines != defines) {
|
||||
CppTools::BaseEditorDocumentParser::Configuration config = parser->configuration();
|
||||
config.preferredProjectPartId = projectPart->id();
|
||||
config.editorDefines = defines;
|
||||
parser->setConfiguration(config);
|
||||
|
||||
emit preprocessorSettingsChanged(!defines.trimmed().isEmpty());
|
||||
CppTools::BaseEditorDocumentParser::Configuration config = parser->configuration();
|
||||
if (config.editorDefines != directives) {
|
||||
config.editorDefines = directives;
|
||||
processor()->setParserConfig(config);
|
||||
|
||||
emit preprocessorSettingsChanged(!directives.trimmed().isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
void CppEditorDocument::setPreferredParseContext(const QString &parseContextId)
|
||||
{
|
||||
const CppTools::BaseEditorDocumentParser::Ptr parser = processor()->parser();
|
||||
QTC_ASSERT(parser, return);
|
||||
|
||||
CppTools::BaseEditorDocumentParser::Configuration config = parser->configuration();
|
||||
if (config.preferredProjectPartId != parseContextId) {
|
||||
config.preferredProjectPartId = parseContextId;
|
||||
processor()->setParserConfig(config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +337,23 @@ void CppEditorDocument::releaseResources()
|
||||
m_processor.reset();
|
||||
}
|
||||
|
||||
void CppEditorDocument::showHideInfoBarAboutMultipleParseContexts(bool show)
|
||||
{
|
||||
const Core::Id id = Constants::MULTIPLE_PARSE_CONTEXTS_AVAILABLE;
|
||||
|
||||
if (show) {
|
||||
Core::InfoBarEntry info(id,
|
||||
tr("Note: Multiple parse contexts are available for this file. "
|
||||
"Choose the preferred one from the editor toolbar."),
|
||||
Core::InfoBarEntry::GlobalSuppressionEnabled);
|
||||
info.removeCancelButton();
|
||||
if (infoBar()->canInfoBeAdded(id))
|
||||
infoBar()->addInfo(info);
|
||||
} else {
|
||||
infoBar()->removeInfo(id);
|
||||
}
|
||||
}
|
||||
|
||||
void CppEditorDocument::initializeTimer()
|
||||
{
|
||||
m_processorTimer.setSingleShot(true);
|
||||
@@ -311,6 +366,11 @@ void CppEditorDocument::initializeTimer()
|
||||
Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
ParseContextModel &CppEditorDocument::parseContextModel()
|
||||
{
|
||||
return m_parseContextModel;
|
||||
}
|
||||
|
||||
const MinimizableInfoBars &CppEditorDocument::minimizableInfoBars() const
|
||||
{
|
||||
return m_minimizableInfoBars;
|
||||
@@ -321,11 +381,15 @@ CppTools::BaseEditorDocumentProcessor *CppEditorDocument::processor()
|
||||
if (!m_processor) {
|
||||
m_processor.reset(mm()->editorDocumentProcessor(this));
|
||||
connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::projectPartInfoUpdated,
|
||||
[this] (const CppTools::ProjectPartInfo &projectPartInfo)
|
||||
[this] (const CppTools::ProjectPartInfo &info)
|
||||
{
|
||||
const bool hasProjectPart
|
||||
= projectPartInfo.hint != CppTools::ProjectPartInfo::IsFallbackMatch;
|
||||
using namespace CppTools;
|
||||
const bool hasProjectPart = !(info.hints & ProjectPartInfo::IsFallbackMatch);
|
||||
m_minimizableInfoBars.processHasProjectPart(hasProjectPart);
|
||||
m_parseContextModel.update(info);
|
||||
const bool isAmbiguous = info.hints & ProjectPartInfo::IsAmbiguousMatch;
|
||||
const bool isProjectFile = info.hints & ProjectPartInfo::IsFromProjectMatch;
|
||||
showHideInfoBarAboutMultipleParseContexts(isAmbiguous && isProjectFile);
|
||||
});
|
||||
connect(m_processor.data(), &CppTools::BaseEditorDocumentProcessor::codeWarningsUpdated,
|
||||
[this] (unsigned revision,
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "cppminimizableinfobars.h"
|
||||
#include "cppparsecontext.h"
|
||||
|
||||
#include <cpptools/baseeditordocumentprocessor.h>
|
||||
#include <cpptools/cppcompletionassistprovider.h>
|
||||
@@ -57,11 +58,13 @@ public:
|
||||
void recalculateSemanticInfoDetached();
|
||||
CppTools::SemanticInfo recalculateSemanticInfo(); // TODO: Remove me
|
||||
|
||||
void setPreprocessorSettings(const CppTools::ProjectPart::Ptr &projectPart,
|
||||
const QByteArray &defines);
|
||||
void setPreferredParseContext(const QString &parseContextId);
|
||||
void setExtraPreprocessorDirectives(const QByteArray &directives);
|
||||
|
||||
void scheduleProcessDocument();
|
||||
|
||||
const MinimizableInfoBars &minimizableInfoBars() const;
|
||||
ParseContextModel &parseContextModel();
|
||||
|
||||
signals:
|
||||
void codeWarningsUpdated(unsigned contentsRevision,
|
||||
@@ -87,6 +90,8 @@ private:
|
||||
void onAboutToReload();
|
||||
void onReloadFinished();
|
||||
|
||||
void reparseWithPreferredParseContext(const QString &id);
|
||||
|
||||
void processDocument();
|
||||
|
||||
QByteArray contentsText() const;
|
||||
@@ -94,9 +99,12 @@ private:
|
||||
|
||||
CppTools::BaseEditorDocumentProcessor *processor();
|
||||
void resetProcessor();
|
||||
void updatePreprocessorSettings();
|
||||
void applyPreferredParseContextFromSettings();
|
||||
void applyExtraPreprocessorDirectivesFromSettings();
|
||||
void releaseResources();
|
||||
|
||||
void showHideInfoBarAboutMultipleParseContexts(bool show);
|
||||
|
||||
void initializeTimer();
|
||||
|
||||
private:
|
||||
@@ -118,6 +126,7 @@ private:
|
||||
QScopedPointer<CppTools::CppEditorDocumentHandle> m_editorDocumentHandle;
|
||||
|
||||
MinimizableInfoBars m_minimizableInfoBars;
|
||||
ParseContextModel m_parseContextModel;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
172
src/plugins/cppeditor/cppparsecontext.cpp
Normal file
172
src/plugins/cppeditor/cppparsecontext.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "cppparsecontext.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
void ParseContextModel::update(const CppTools::ProjectPartInfo &projectPartInfo)
|
||||
{
|
||||
beginResetModel();
|
||||
reset(projectPartInfo);
|
||||
endResetModel();
|
||||
|
||||
emit updated(areMultipleAvailable());
|
||||
}
|
||||
|
||||
QString ParseContextModel::currentToolTip() const
|
||||
{
|
||||
const QModelIndex index = createIndex(m_currentIndex, 0);
|
||||
if (!index.isValid())
|
||||
return QString();
|
||||
|
||||
return tr("<p><b>Active Parse Context</b>:<br/>%1</p>"
|
||||
"<p>Multiple parse contexts (set of defines, include paths, and so on) "
|
||||
"are available for this file.</p>"
|
||||
"<p>Choose a parse context to set it as the preferred one. "
|
||||
"Clear the preference from the context menu.</p>")
|
||||
.arg(data(index, Qt::ToolTipRole).toString());
|
||||
}
|
||||
|
||||
void ParseContextModel::setPreferred(int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
emit preferredParseContextChanged(m_projectParts[index]->id());
|
||||
}
|
||||
|
||||
void ParseContextModel::clearPreferred()
|
||||
{
|
||||
emit preferredParseContextChanged(QString());
|
||||
}
|
||||
|
||||
bool ParseContextModel::areMultipleAvailable() const
|
||||
{
|
||||
return m_projectParts.size() >= 2;
|
||||
}
|
||||
|
||||
void ParseContextModel::reset(const CppTools::ProjectPartInfo &projectPartInfo)
|
||||
{
|
||||
// Sort
|
||||
m_hints = projectPartInfo.hints;
|
||||
m_projectParts = projectPartInfo.projectParts;
|
||||
Utils::sort(m_projectParts, &CppTools::ProjectPart::displayName);
|
||||
|
||||
// Determine index for current
|
||||
const QString id = projectPartInfo.projectPart->id();
|
||||
m_currentIndex = Utils::indexOf(m_projectParts, [id](const CppTools::ProjectPart::Ptr &pp) {
|
||||
return pp->id() == id;
|
||||
});
|
||||
QTC_CHECK(m_currentIndex >= 0);
|
||||
}
|
||||
|
||||
int ParseContextModel::currentIndex() const
|
||||
{
|
||||
return m_currentIndex;
|
||||
}
|
||||
|
||||
bool ParseContextModel::isCurrentPreferred() const
|
||||
{
|
||||
return m_hints & CppTools::ProjectPartInfo::IsPreferredMatch;
|
||||
}
|
||||
|
||||
QString ParseContextModel::currentId() const
|
||||
{
|
||||
if (m_currentIndex < 0)
|
||||
return QString();
|
||||
|
||||
return m_projectParts[m_currentIndex]->id();
|
||||
}
|
||||
|
||||
int ParseContextModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_projectParts.size();
|
||||
}
|
||||
|
||||
QVariant ParseContextModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (m_projectParts.isEmpty())
|
||||
return QVariant();
|
||||
|
||||
const int row = index.row();
|
||||
if (role == Qt::DisplayRole)
|
||||
return m_projectParts[row]->displayName;
|
||||
else if (role == Qt::ToolTipRole)
|
||||
return QDir::toNativeSeparators(m_projectParts[row]->projectFile);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
ParseContextWidget::ParseContextWidget(ParseContextModel &parseContextModel, QWidget *parent)
|
||||
: QComboBox(parent)
|
||||
, m_parseContextModel(parseContextModel)
|
||||
{
|
||||
// Set up context menu with a clear action
|
||||
setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
m_clearPreferredAction = new QAction(tr("Clear Preferred Parse Context"), this);
|
||||
connect(m_clearPreferredAction, &QAction::triggered,[&]() {
|
||||
m_parseContextModel.clearPreferred();
|
||||
});
|
||||
addAction(m_clearPreferredAction);
|
||||
|
||||
// Set up sync of this widget and model in both directions
|
||||
connect(this,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
|
||||
&m_parseContextModel,
|
||||
&ParseContextModel::setPreferred);
|
||||
connect(&m_parseContextModel, &ParseContextModel::updated,
|
||||
this, &ParseContextWidget::syncToModel);
|
||||
|
||||
// Set up model
|
||||
setModel(&m_parseContextModel);
|
||||
}
|
||||
|
||||
void ParseContextWidget::syncToModel()
|
||||
{
|
||||
const int index = m_parseContextModel.currentIndex();
|
||||
if (index < 0)
|
||||
return; // E.g. editor was duplicated but no project context was determined yet.
|
||||
|
||||
if (currentIndex() != index)
|
||||
setCurrentIndex(index);
|
||||
|
||||
setToolTip(m_parseContextModel.currentToolTip());
|
||||
|
||||
const bool isPreferred = m_parseContextModel.isCurrentPreferred();
|
||||
m_clearPreferredAction->setEnabled(isPreferred);
|
||||
QComboBox::setProperty("highlightWidget", isPreferred);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CppEditor
|
83
src/plugins/cppeditor/cppparsecontext.h
Normal file
83
src/plugins/cppeditor/cppparsecontext.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cpptools/cpptools_utils.h>
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QComboBox>
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
|
||||
class ParseContextModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void update(const CppTools::ProjectPartInfo &projectPartInfo);
|
||||
|
||||
void setPreferred(int index);
|
||||
void clearPreferred();
|
||||
|
||||
int currentIndex() const;
|
||||
bool isCurrentPreferred() const;
|
||||
|
||||
QString currentId() const;
|
||||
QString currentToolTip() const;
|
||||
|
||||
bool areMultipleAvailable() const;
|
||||
|
||||
signals:
|
||||
void updated(bool areMultipleAvailable);
|
||||
void preferredParseContextChanged(const QString &id);
|
||||
|
||||
private:
|
||||
void reset(const CppTools::ProjectPartInfo &projectPartInfo);
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
private:
|
||||
CppTools::ProjectPartInfo::Hints m_hints;
|
||||
QList<CppTools::ProjectPart::Ptr> m_projectParts;
|
||||
int m_currentIndex = -1;
|
||||
};
|
||||
|
||||
class ParseContextWidget : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ParseContextWidget(ParseContextModel &parseContextModel, QWidget *parent);
|
||||
void syncToModel();
|
||||
|
||||
private:
|
||||
ParseContextModel &m_parseContextModel;
|
||||
QAction *m_clearPreferredAction = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CppEditor
|
@@ -31,18 +31,9 @@
|
||||
|
||||
#include <projectexplorer/session.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace CppEditor::Internal;
|
||||
|
||||
static bool projectPartLessThan(const CppTools::ProjectPart::Ptr &projectPart1,
|
||||
const CppTools::ProjectPart::Ptr &projectPart2)
|
||||
{
|
||||
return projectPart1->displayName < projectPart2->displayName;
|
||||
}
|
||||
|
||||
CppPreProcessorDialog::CppPreProcessorDialog(QWidget *parent, const QString &filePath,
|
||||
const QList<CppTools::ProjectPart::Ptr> &projectParts)
|
||||
CppPreProcessorDialog::CppPreProcessorDialog(const QString &filePath, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::CppPreProcessorDialog())
|
||||
, m_filePath(filePath)
|
||||
@@ -55,32 +46,9 @@ CppPreProcessorDialog::CppPreProcessorDialog(QWidget *parent, const QString &fil
|
||||
|
||||
CppSnippetProvider().decorateEditor(m_ui->editWidget);
|
||||
|
||||
const QString &projectPartIdToUse = ProjectExplorer::SessionManager::value(
|
||||
QLatin1String(Constants::CPP_PREPROCESSOR_PROJECT_PREFIX) + m_filePath).toString();
|
||||
int currentIndex = 0;
|
||||
|
||||
QList<CppTools::ProjectPart::Ptr> sortedProjectParts(projectParts);
|
||||
std::stable_sort(sortedProjectParts.begin(), sortedProjectParts.end(), projectPartLessThan);
|
||||
|
||||
foreach (CppTools::ProjectPart::Ptr projectPart, sortedProjectParts) {
|
||||
m_ui->projectComboBox->addItem(projectPart->displayName);
|
||||
ProjectPartAddition addition;
|
||||
addition.projectPart = projectPart;
|
||||
addition.additionalDirectives = ProjectExplorer::SessionManager::value(
|
||||
projectPart->id() + QLatin1Char(',') + m_filePath).toString();
|
||||
if (projectPart->id() == projectPartIdToUse)
|
||||
currentIndex = m_ui->projectComboBox->count() - 1;
|
||||
m_partAdditions << addition;
|
||||
}
|
||||
if (m_ui->projectComboBox->count() <= 1)
|
||||
m_ui->projectComboBox->setEnabled(false);
|
||||
m_ui->projectComboBox->setCurrentIndex(currentIndex);
|
||||
m_ui->editWidget->setPlainText(m_partAdditions.value(currentIndex).additionalDirectives);
|
||||
|
||||
connect(m_ui->projectComboBox,
|
||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, &CppPreProcessorDialog::projectChanged);
|
||||
connect(m_ui->editWidget, &QPlainTextEdit::textChanged, this, &CppPreProcessorDialog::textChanged);
|
||||
const QString key = Constants::EXTRA_PREPROCESSOR_DIRECTIVES + m_filePath;
|
||||
const QString directives = ProjectExplorer::SessionManager::value(key).toString();
|
||||
m_ui->editWidget->setPlainText(directives);
|
||||
}
|
||||
|
||||
CppPreProcessorDialog::~CppPreProcessorDialog()
|
||||
@@ -93,41 +61,13 @@ int CppPreProcessorDialog::exec()
|
||||
if (QDialog::exec() == Rejected)
|
||||
return Rejected;
|
||||
|
||||
ProjectExplorer::SessionManager::setValue(
|
||||
QLatin1String(Constants::CPP_PREPROCESSOR_PROJECT_PREFIX) + m_filePath,
|
||||
m_partAdditions[m_ui->projectComboBox->currentIndex()].projectPart->id());
|
||||
const QString key = Constants::EXTRA_PREPROCESSOR_DIRECTIVES + m_filePath;
|
||||
ProjectExplorer::SessionManager::setValue(key, extraPreprocessorDirectives());
|
||||
|
||||
foreach (ProjectPartAddition partAddition, m_partAdditions) {
|
||||
const QString &previousDirectives = ProjectExplorer::SessionManager::value(
|
||||
partAddition.projectPart->id()
|
||||
+ QLatin1Char(',')
|
||||
+ m_filePath).toString();
|
||||
if (previousDirectives != partAddition.additionalDirectives) {
|
||||
ProjectExplorer::SessionManager::setValue(
|
||||
partAddition.projectPart->id() + QLatin1Char(',') + m_filePath,
|
||||
partAddition.additionalDirectives);
|
||||
}
|
||||
}
|
||||
return Accepted;
|
||||
}
|
||||
|
||||
CppTools::ProjectPart::Ptr CppPreProcessorDialog::projectPart() const
|
||||
{
|
||||
return m_partAdditions[m_ui->projectComboBox->currentIndex()].projectPart;
|
||||
}
|
||||
|
||||
QString CppPreProcessorDialog::additionalPreProcessorDirectives() const
|
||||
QString CppPreProcessorDialog::extraPreprocessorDirectives() const
|
||||
{
|
||||
return m_ui->editWidget->toPlainText();
|
||||
}
|
||||
|
||||
void CppPreProcessorDialog::projectChanged(int index)
|
||||
{
|
||||
m_ui->editWidget->setPlainText(m_partAdditions[index].additionalDirectives);
|
||||
}
|
||||
|
||||
void CppPreProcessorDialog::textChanged()
|
||||
{
|
||||
m_partAdditions[m_ui->projectComboBox->currentIndex()].additionalDirectives
|
||||
= m_ui->editWidget->toPlainText();
|
||||
}
|
||||
|
@@ -25,9 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
|
||||
namespace CppEditor {
|
||||
namespace Internal {
|
||||
@@ -38,27 +37,17 @@ class CppPreProcessorDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CppPreProcessorDialog(QWidget *parent, const QString &filePath,
|
||||
const QList<CppTools::ProjectPart::Ptr> &projectParts);
|
||||
explicit CppPreProcessorDialog(const QString &filePath, QWidget *parent);
|
||||
~CppPreProcessorDialog();
|
||||
|
||||
int exec();
|
||||
|
||||
CppTools::ProjectPart::Ptr projectPart() const;
|
||||
QString additionalPreProcessorDirectives() const;
|
||||
QString extraPreprocessorDirectives() const;
|
||||
|
||||
private:
|
||||
void projectChanged(int index);
|
||||
void textChanged();
|
||||
|
||||
struct ProjectPartAddition {
|
||||
CppTools::ProjectPart::Ptr projectPart;
|
||||
QString additionalDirectives;
|
||||
};
|
||||
|
||||
Ui::CppPreProcessorDialog *m_ui;
|
||||
QList<ProjectPartAddition> m_partAdditions;
|
||||
QString m_filePath;
|
||||
const QString m_filePath;
|
||||
const QString m_projectPartId;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -14,34 +14,6 @@
|
||||
<string>Additional C++ Preprocessor Directives</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="projectLabel">
|
||||
<property name="text">
|
||||
<string>Project:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="projectComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="separator">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="editorLabel">
|
||||
<property name="text">
|
||||
|
@@ -87,6 +87,12 @@ void BaseEditorDocumentProcessor::editorDocumentTimerRestarted()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseEditorDocumentProcessor::setParserConfig(
|
||||
const BaseEditorDocumentParser::Configuration config)
|
||||
{
|
||||
parser()->setConfiguration(config);
|
||||
}
|
||||
|
||||
void BaseEditorDocumentProcessor::runParser(QFutureInterface<void> &future,
|
||||
BaseEditorDocumentParser::Ptr parser,
|
||||
BaseEditorDocumentParser::UpdateParams updateParams)
|
||||
|
@@ -70,6 +70,8 @@ public:
|
||||
|
||||
virtual void editorDocumentTimerRestarted();
|
||||
|
||||
virtual void setParserConfig(const BaseEditorDocumentParser::Configuration config);
|
||||
|
||||
public:
|
||||
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
|
||||
|
||||
|
@@ -37,7 +37,7 @@ public:
|
||||
struct PrioritizedProjectPart
|
||||
{
|
||||
PrioritizedProjectPart(const ProjectPart::Ptr &projectPart, int priority)
|
||||
: projectPart(projectPart) , priority(priority) {}
|
||||
: projectPart(projectPart), priority(priority) {}
|
||||
|
||||
ProjectPart::Ptr projectPart;
|
||||
int priority = 0;
|
||||
@@ -46,37 +46,41 @@ public:
|
||||
ProjectPartPrioritizer(const QList<ProjectPart::Ptr> &projectParts,
|
||||
const QString &preferredProjectPartId,
|
||||
const ProjectExplorer::Project *activeProject,
|
||||
Language languagePreference)
|
||||
: m_projectParts(projectParts)
|
||||
, m_preferredProjectPartId(preferredProjectPartId)
|
||||
Language languagePreference,
|
||||
bool areProjectPartsFromDependencies)
|
||||
: m_preferredProjectPartId(preferredProjectPartId)
|
||||
, m_activeProject(activeProject)
|
||||
, m_languagePreference(languagePreference)
|
||||
{
|
||||
// Determine best project part
|
||||
const QList<PrioritizedProjectPart> prioritized = prioritize();
|
||||
m_projectPart = prioritized.first().projectPart;
|
||||
// Prioritize
|
||||
const QList<PrioritizedProjectPart> prioritized = prioritize(projectParts);
|
||||
for (const PrioritizedProjectPart &ppp : prioritized)
|
||||
m_info.projectParts << ppp.projectPart;
|
||||
|
||||
// Determine ambiguity
|
||||
m_isAmbiguous = prioritized.size() > 1
|
||||
? prioritized[0].priority == prioritized[1].priority
|
||||
: false;
|
||||
// Best project part
|
||||
m_info.projectPart = m_info.projectParts.first();
|
||||
|
||||
// Hints
|
||||
if (m_info.projectParts.size() > 1)
|
||||
m_info.hints |= ProjectPartInfo::IsAmbiguousMatch;
|
||||
if (prioritized.first().priority > 1000)
|
||||
m_info.hints |= ProjectPartInfo::IsPreferredMatch;
|
||||
if (areProjectPartsFromDependencies)
|
||||
m_info.hints |= ProjectPartInfo::IsFromDependenciesMatch;
|
||||
else
|
||||
m_info.hints |= ProjectPartInfo::IsFromProjectMatch;
|
||||
}
|
||||
|
||||
ProjectPart::Ptr projectPart()
|
||||
ProjectPartInfo info() const
|
||||
{
|
||||
return m_projectPart;
|
||||
}
|
||||
|
||||
bool isAmbiguous() const
|
||||
{
|
||||
return m_isAmbiguous;
|
||||
return m_info;
|
||||
}
|
||||
|
||||
private:
|
||||
QList<PrioritizedProjectPart> prioritize()
|
||||
QList<PrioritizedProjectPart> prioritize(const QList<ProjectPart::Ptr> &projectParts)
|
||||
{
|
||||
// Prioritize
|
||||
QList<PrioritizedProjectPart> prioritized = Utils::transform(m_projectParts,
|
||||
QList<PrioritizedProjectPart> prioritized = Utils::transform(projectParts,
|
||||
[&](const ProjectPart::Ptr &projectPart) {
|
||||
return PrioritizedProjectPart{projectPart, priority(*projectPart)};
|
||||
});
|
||||
@@ -118,14 +122,12 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
const QList<ProjectPart::Ptr> m_projectParts;
|
||||
const QString m_preferredProjectPartId;
|
||||
const ProjectExplorer::Project *m_activeProject = nullptr;
|
||||
Language m_languagePreference = Language::Cxx;
|
||||
|
||||
// Results
|
||||
ProjectPart::Ptr m_projectPart;
|
||||
bool m_isAmbiguous = false;
|
||||
ProjectPartInfo m_info;
|
||||
};
|
||||
|
||||
ProjectPartInfo ProjectPartChooser::choose(
|
||||
@@ -141,40 +143,30 @@ ProjectPartInfo ProjectPartChooser::choose(
|
||||
QTC_CHECK(m_fallbackProjectPart);
|
||||
|
||||
ProjectPart::Ptr projectPart = currentProjectPartInfo.projectPart;
|
||||
ProjectPartInfo::Hint hint = ProjectPartInfo::NoHint;
|
||||
|
||||
QList<ProjectPart::Ptr> projectParts = m_projectPartsForFile(filePath);
|
||||
bool areProjectPartsFromDependencies = false;
|
||||
|
||||
if (projectParts.isEmpty()) {
|
||||
if (!projectsUpdated && projectPart
|
||||
&& currentProjectPartInfo.hint == ProjectPartInfo::IsFallbackMatch)
|
||||
&& currentProjectPartInfo.hints & ProjectPartInfo::IsFallbackMatch)
|
||||
// Avoid re-calculating the expensive dependency table for non-project files.
|
||||
return {projectPart, ProjectPartInfo::IsFallbackMatch};
|
||||
return ProjectPartInfo(projectPart, {projectPart}, ProjectPartInfo::IsFallbackMatch);
|
||||
|
||||
// Fall-back step 1: Get some parts through the dependency table:
|
||||
projectParts = m_projectPartsFromDependenciesForFile(filePath);
|
||||
if (projectParts.isEmpty()) {
|
||||
// Fall-back step 2: Use fall-back part from the model manager:
|
||||
projectPart = m_fallbackProjectPart();
|
||||
hint = ProjectPartInfo::IsFallbackMatch;
|
||||
} else {
|
||||
ProjectPartPrioritizer prioritizer(projectParts,
|
||||
preferredProjectPartId,
|
||||
activeProject,
|
||||
languagePreference);
|
||||
projectPart = prioritizer.projectPart();
|
||||
return ProjectPartInfo(projectPart, {projectPart}, ProjectPartInfo::IsFallbackMatch);
|
||||
}
|
||||
} else {
|
||||
ProjectPartPrioritizer prioritizer(projectParts,
|
||||
preferredProjectPartId,
|
||||
activeProject,
|
||||
languagePreference);
|
||||
projectPart = prioritizer.projectPart();
|
||||
hint = prioritizer.isAmbiguous()
|
||||
? ProjectPartInfo::IsAmbiguousMatch
|
||||
: ProjectPartInfo::NoHint;
|
||||
areProjectPartsFromDependencies = true;
|
||||
}
|
||||
|
||||
return {projectPart, hint};
|
||||
return ProjectPartPrioritizer(projectParts,
|
||||
preferredProjectPartId,
|
||||
activeProject,
|
||||
languagePreference,
|
||||
areProjectPartsFromDependencies).info();
|
||||
}
|
||||
|
||||
void ProjectPartChooser::setFallbackProjectPart(const FallBackProjectPart &getter)
|
||||
|
@@ -34,14 +34,29 @@ enum class Language { C, Cxx };
|
||||
class ProjectPartInfo {
|
||||
public:
|
||||
enum Hint {
|
||||
NoHint,
|
||||
IsFallbackMatch,
|
||||
IsAmbiguousMatch
|
||||
NoHint = 0,
|
||||
IsFallbackMatch = 1 << 0,
|
||||
IsAmbiguousMatch = 1 << 1,
|
||||
IsPreferredMatch = 1 << 2,
|
||||
IsFromProjectMatch = 1 << 3,
|
||||
IsFromDependenciesMatch = 1 << 4,
|
||||
};
|
||||
Q_DECLARE_FLAGS(Hints, Hint)
|
||||
|
||||
ProjectPartInfo() = default;
|
||||
ProjectPartInfo(const ProjectPart::Ptr &projectPart,
|
||||
const QList<ProjectPart::Ptr> &projectParts,
|
||||
Hints hints)
|
||||
: projectPart(projectPart)
|
||||
, projectParts(projectParts)
|
||||
, hints(hints)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
ProjectPart::Ptr projectPart;
|
||||
Hint hint;
|
||||
QList<ProjectPart::Ptr> projectParts; // The one above as first plus alternatives.
|
||||
Hints hints = NoHint;
|
||||
};
|
||||
|
||||
} // namespace CppTools
|
||||
|
@@ -49,7 +49,9 @@ protected:
|
||||
|
||||
protected:
|
||||
QString filePath;
|
||||
ProjectPartInfo currentProjectPartInfo{ProjectPart::Ptr(new ProjectPart),
|
||||
ProjectPart::Ptr currentProjectPart{new ProjectPart};
|
||||
ProjectPartInfo currentProjectPartInfo{currentProjectPart,
|
||||
{currentProjectPart},
|
||||
ProjectPartInfo::NoHint};
|
||||
QString preferredProjectPartId;
|
||||
const ProjectExplorer::Project *activeProject = nullptr;
|
||||
@@ -74,6 +76,37 @@ TEST_F(ProjectPartChooser, ChooseManuallySet)
|
||||
ASSERT_THAT(chosen, Eq(p2));
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, IndicateManuallySet)
|
||||
{
|
||||
ProjectPart::Ptr p1(new ProjectPart);
|
||||
ProjectPart::Ptr p2(new ProjectPart);
|
||||
p2->projectFile = preferredProjectPartId = "someId";
|
||||
projectPartsForFile += {p1, p2};
|
||||
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_TRUE(hints & ProjectPartInfo::IsPreferredMatch);
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, IndicateManuallySetForFallbackToProjectPartFromDependencies)
|
||||
{
|
||||
ProjectPart::Ptr p1(new ProjectPart);
|
||||
ProjectPart::Ptr p2(new ProjectPart);
|
||||
p2->projectFile = preferredProjectPartId = "someId";
|
||||
projectPartsFromDependenciesForFile += {p1, p2};
|
||||
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_TRUE(hints & ProjectPartInfo::IsPreferredMatch);
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, DoNotIndicateNotManuallySet)
|
||||
{
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_FALSE(hints & ProjectPartInfo::IsPreferredMatch);
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, ForMultipleChooseFromActiveProject)
|
||||
{
|
||||
const QList<ProjectPart::Ptr> projectParts = createProjectPartsWithDifferentProjects();
|
||||
@@ -154,9 +187,20 @@ TEST_F(ProjectPartChooser, IndicateMultiple)
|
||||
const ProjectPart::Ptr p2{new ProjectPart};
|
||||
projectPartsForFile += { p1, p2 };
|
||||
|
||||
const ProjectPartInfo::Hint hint = choose().hint;
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_THAT(hint, Eq(ProjectPartInfo::Hint::IsAmbiguousMatch));
|
||||
ASSERT_TRUE(hints & ProjectPartInfo::IsAmbiguousMatch);
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, IndicateMultipleForFallbackToProjectPartFromDependencies)
|
||||
{
|
||||
const ProjectPart::Ptr p1{new ProjectPart};
|
||||
const ProjectPart::Ptr p2{new ProjectPart};
|
||||
projectPartsFromDependenciesForFile += { p1, p2 };
|
||||
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_TRUE(hints & ProjectPartInfo::IsAmbiguousMatch);
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, ForMultipleChooseNewIfPreviousIsGone)
|
||||
@@ -193,7 +237,7 @@ TEST_F(ProjectPartChooser, ContinueUsingFallbackFromModelManagerIfProjectDoesNot
|
||||
// ...without re-calculating the dependency table.
|
||||
fallbackProjectPart.reset(new ProjectPart);
|
||||
currentProjectPartInfo.projectPart = fallbackProjectPart;
|
||||
currentProjectPartInfo.hint = ProjectPartInfo::IsFallbackMatch;
|
||||
currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch;
|
||||
projectPartsFromDependenciesForFile += ProjectPart::Ptr(new ProjectPart);
|
||||
|
||||
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||
@@ -205,7 +249,7 @@ TEST_F(ProjectPartChooser, StopUsingFallbackFromModelManagerIfProjectChanges1)
|
||||
{
|
||||
fallbackProjectPart.reset(new ProjectPart);
|
||||
currentProjectPartInfo.projectPart = fallbackProjectPart;
|
||||
currentProjectPartInfo.hint = ProjectPartInfo::IsFallbackMatch;
|
||||
currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch;
|
||||
const ProjectPart::Ptr addedProject(new ProjectPart);
|
||||
projectPartsForFile += addedProject;
|
||||
|
||||
@@ -218,7 +262,7 @@ TEST_F(ProjectPartChooser, StopUsingFallbackFromModelManagerIfProjectChanges2)
|
||||
{
|
||||
fallbackProjectPart.reset(new ProjectPart);
|
||||
currentProjectPartInfo.projectPart = fallbackProjectPart;
|
||||
currentProjectPartInfo.hint = ProjectPartInfo::IsFallbackMatch;
|
||||
currentProjectPartInfo.hints |= ProjectPartInfo::IsFallbackMatch;
|
||||
const ProjectPart::Ptr addedProject(new ProjectPart);
|
||||
projectPartsFromDependenciesForFile += addedProject;
|
||||
projectsChanged = true;
|
||||
@@ -232,9 +276,27 @@ TEST_F(ProjectPartChooser, IndicateFallbacktoProjectPartFromModelManager)
|
||||
{
|
||||
fallbackProjectPart.reset(new ProjectPart);
|
||||
|
||||
const ProjectPartInfo::Hint hint = choose().hint;
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_THAT(hint, Eq(ProjectPartInfo::Hint::IsFallbackMatch));
|
||||
ASSERT_TRUE(hints & ProjectPartInfo::IsFallbackMatch);
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, IndicateFromDependencies)
|
||||
{
|
||||
projectPartsFromDependenciesForFile += ProjectPart::Ptr(new ProjectPart);
|
||||
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_TRUE(hints & ProjectPartInfo::IsFromDependenciesMatch);
|
||||
}
|
||||
|
||||
TEST_F(ProjectPartChooser, DoNotIndicateFromDependencies)
|
||||
{
|
||||
projectPartsForFile += ProjectPart::Ptr(new ProjectPart);
|
||||
|
||||
const ProjectPartInfo::Hints hints = choose().hints;
|
||||
|
||||
ASSERT_FALSE(hints & ProjectPartInfo::IsFromDependenciesMatch);
|
||||
}
|
||||
|
||||
void ProjectPartChooser::SetUp()
|
||||
|
Reference in New Issue
Block a user