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:
Nikolai Kosjar
2017-01-18 15:05:46 +01:00
parent 9ac96339ff
commit 38ba61ec4f
18 changed files with 538 additions and 208 deletions

View File

@@ -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,