forked from qt-creator/qt-creator
CppTools: Provide hints about chosen project part for editor document
Parse issues can have multiple reasons (invalid kit, not a project file, actual parse issue) and we should be able to tell them apart. With this change, we can distinguish between the fallback project part and a ambiguous project part. Follow up changes will use this to display more accurate diagnostics. Change-Id: Icc8767607cc17dc14d6227b07f34e81ba5525a96 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -39,12 +39,13 @@ void ClangEditorDocumentParser::updateImpl(const QFutureInterface<void> &,
|
|||||||
const UpdateParams &updateParams)
|
const UpdateParams &updateParams)
|
||||||
{
|
{
|
||||||
State state_ = state();
|
State state_ = state();
|
||||||
state_.projectPart = determineProjectPart(filePath(),
|
state_.projectPartInfo = determineProjectPart(filePath(),
|
||||||
configuration(),
|
configuration(),
|
||||||
state_,
|
state_,
|
||||||
updateParams.activeProject,
|
updateParams.activeProject,
|
||||||
updateParams.languagePreference,
|
updateParams.languagePreference,
|
||||||
updateParams.hasActiveProjectChanged);
|
updateParams.hasActiveProjectChanged);
|
||||||
|
emit projectPartInfoUpdated(state_.projectPartInfo);
|
||||||
setState(state_);
|
setState(state_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
|||||||
connect(&m_updateTranslationUnitTimer, &QTimer::timeout,
|
connect(&m_updateTranslationUnitTimer, &QTimer::timeout,
|
||||||
this, &ClangEditorDocumentProcessor::updateTranslationUnitIfProjectPartExists);
|
this, &ClangEditorDocumentProcessor::updateTranslationUnitIfProjectPartExists);
|
||||||
|
|
||||||
|
connect(m_parser.data(), &ClangEditorDocumentParser::projectPartInfoUpdated,
|
||||||
|
this, &BaseEditorDocumentProcessor::projectPartInfoUpdated);
|
||||||
|
|
||||||
// Forwarding the semantic info from the builtin processor enables us to provide all
|
// 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.
|
// editor (widget) related features that are not yet implemented by the clang plugin.
|
||||||
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
|
connect(&m_builtinProcessor, &CppTools::BuiltinEditorDocumentProcessor::cppDocumentUpdated,
|
||||||
@@ -302,7 +305,7 @@ static bool isProjectPartLoadedOrIsFallback(CppTools::ProjectPart::Ptr projectPa
|
|||||||
|
|
||||||
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor()
|
void ClangEditorDocumentProcessor::updateProjectPartAndTranslationUnitForEditor()
|
||||||
{
|
{
|
||||||
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPart();
|
const CppTools::ProjectPart::Ptr projectPart = m_parser->projectPartInfo().projectPart;
|
||||||
|
|
||||||
if (isProjectPartLoadedOrIsFallback(projectPart)) {
|
if (isProjectPartLoadedOrIsFallback(projectPart)) {
|
||||||
registerTranslationUnitForEditor(projectPart.data());
|
registerTranslationUnitForEditor(projectPart.data());
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind
|
|||||||
ProjectPart::Ptr projectPartForFile(const QString &filePath)
|
ProjectPart::Ptr projectPartForFile(const QString &filePath)
|
||||||
{
|
{
|
||||||
if (const auto parser = CppTools::BaseEditorDocumentParser::get(filePath))
|
if (const auto parser = CppTools::BaseEditorDocumentParser::get(filePath))
|
||||||
return parser->projectPart();
|
return parser->projectPartInfo().projectPart;
|
||||||
return ProjectPart::Ptr();
|
return ProjectPart::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1580,7 +1580,7 @@ void CppCodeModelInspectorDialog::refresh()
|
|||||||
|
|
||||||
// Project Parts
|
// Project Parts
|
||||||
const ProjectPart::Ptr editorsProjectPart = cppEditorDocument
|
const ProjectPart::Ptr editorsProjectPart = cppEditorDocument
|
||||||
? cppEditorDocument->processor()->parser()->projectPart()
|
? cppEditorDocument->processor()->parser()->projectPartInfo().projectPart
|
||||||
: ProjectPart::Ptr();
|
: ProjectPart::Ptr();
|
||||||
|
|
||||||
const QList<ProjectInfo> projectInfos = cmmi->projectInfos();
|
const QList<ProjectInfo> projectInfos = cmmi->projectInfos();
|
||||||
|
|||||||
@@ -274,7 +274,8 @@ void CppEditorDocument::setPreprocessorSettings(const CppTools::ProjectPart::Ptr
|
|||||||
{
|
{
|
||||||
const auto parser = processor()->parser();
|
const auto parser = processor()->parser();
|
||||||
QTC_ASSERT(parser, return);
|
QTC_ASSERT(parser, return);
|
||||||
if (parser->projectPart() != projectPart || parser->configuration().editorDefines != defines) {
|
if (parser->projectPartInfo().projectPart != projectPart
|
||||||
|
|| parser->configuration().editorDefines != defines) {
|
||||||
CppTools::BaseEditorDocumentParser::Configuration config = parser->configuration();
|
CppTools::BaseEditorDocumentParser::Configuration config = parser->configuration();
|
||||||
config.manuallySetProjectPart = projectPart;
|
config.manuallySetProjectPart = projectPart;
|
||||||
config.editorDefines = defines;
|
config.editorDefines = defines;
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ namespace CppTools {
|
|||||||
BaseEditorDocumentParser::BaseEditorDocumentParser(const QString &filePath)
|
BaseEditorDocumentParser::BaseEditorDocumentParser(const QString &filePath)
|
||||||
: m_filePath(filePath)
|
: m_filePath(filePath)
|
||||||
{
|
{
|
||||||
|
static int meta = qRegisterMetaType<ProjectPartInfo>("CppTools::ProjectPartInfo");
|
||||||
|
Q_UNUSED(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseEditorDocumentParser::~BaseEditorDocumentParser()
|
BaseEditorDocumentParser::~BaseEditorDocumentParser()
|
||||||
@@ -102,9 +104,9 @@ void BaseEditorDocumentParser::setState(const State &state)
|
|||||||
m_state = state;
|
m_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectPart::Ptr BaseEditorDocumentParser::projectPart() const
|
ProjectPartInfo BaseEditorDocumentParser::projectPartInfo() const
|
||||||
{
|
{
|
||||||
return state().projectPart;
|
return state().projectPartInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseEditorDocumentParser::Ptr BaseEditorDocumentParser::get(const QString &filePath)
|
BaseEditorDocumentParser::Ptr BaseEditorDocumentParser::get(const QString &filePath)
|
||||||
@@ -117,7 +119,7 @@ BaseEditorDocumentParser::Ptr BaseEditorDocumentParser::get(const QString &fileP
|
|||||||
return BaseEditorDocumentParser::Ptr();
|
return BaseEditorDocumentParser::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart(
|
ProjectPartInfo BaseEditorDocumentParser::determineProjectPart(
|
||||||
const QString &filePath,
|
const QString &filePath,
|
||||||
const Configuration &config,
|
const Configuration &config,
|
||||||
const State &state,
|
const State &state,
|
||||||
@@ -125,7 +127,9 @@ ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart(
|
|||||||
Language languagePreference,
|
Language languagePreference,
|
||||||
bool hasActiveProjectChanged)
|
bool hasActiveProjectChanged)
|
||||||
{
|
{
|
||||||
Internal::ProjectPartChooser chooser;
|
using Internal::ProjectPartChooser;
|
||||||
|
|
||||||
|
ProjectPartChooser chooser;
|
||||||
chooser.setFallbackProjectPart([](){
|
chooser.setFallbackProjectPart([](){
|
||||||
return CppModelManager::instance()->fallbackProjectPart();
|
return CppModelManager::instance()->fallbackProjectPart();
|
||||||
});
|
});
|
||||||
@@ -137,13 +141,16 @@ ProjectPart::Ptr BaseEditorDocumentParser::determineProjectPart(
|
|||||||
return CppModelManager::instance()->projectPartFromDependencies(fileName);
|
return CppModelManager::instance()->projectPartFromDependencies(fileName);
|
||||||
});
|
});
|
||||||
|
|
||||||
return chooser.choose(filePath,
|
const ProjectPartInfo chooserResult
|
||||||
state.projectPart,
|
= chooser.choose(filePath,
|
||||||
|
state.projectPartInfo.projectPart,
|
||||||
config.manuallySetProjectPart,
|
config.manuallySetProjectPart,
|
||||||
config.stickToPreviousProjectPart,
|
config.stickToPreviousProjectPart,
|
||||||
activeProject,
|
activeProject,
|
||||||
languagePreference,
|
languagePreference,
|
||||||
hasActiveProjectChanged);
|
hasActiveProjectChanged);
|
||||||
|
|
||||||
|
return chooserResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cpplanguage.h"
|
|
||||||
#include "cpptools_global.h"
|
#include "cpptools_global.h"
|
||||||
|
#include "cpptools_utils.h"
|
||||||
#include "cppworkingcopy.h"
|
#include "cppworkingcopy.h"
|
||||||
#include "projectpart.h"
|
#include "projectpart.h"
|
||||||
|
|
||||||
@@ -82,17 +82,21 @@ public:
|
|||||||
void update(const UpdateParams &updateParams);
|
void update(const UpdateParams &updateParams);
|
||||||
void update(const QFutureInterface<void> &future, const UpdateParams &updateParams);
|
void update(const QFutureInterface<void> &future, const UpdateParams &updateParams);
|
||||||
|
|
||||||
ProjectPart::Ptr projectPart() const;
|
ProjectPartInfo projectPartInfo() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void projectPartInfoUpdated(const CppTools::ProjectPartInfo &projectPartInfo);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct State {
|
struct State {
|
||||||
QByteArray editorDefines;
|
QByteArray editorDefines;
|
||||||
ProjectPart::Ptr projectPart;
|
ProjectPartInfo projectPartInfo;
|
||||||
};
|
};
|
||||||
State state() const;
|
State state() const;
|
||||||
void setState(const State &state);
|
void setState(const State &state);
|
||||||
|
|
||||||
static ProjectPart::Ptr determineProjectPart(const QString &filePath,
|
static ProjectPartInfo determineProjectPart(
|
||||||
|
const QString &filePath,
|
||||||
const Configuration &config,
|
const Configuration &config,
|
||||||
const State &state,
|
const State &state,
|
||||||
const ProjectExplorer::Project *activeProject,
|
const ProjectExplorer::Project *activeProject,
|
||||||
|
|||||||
@@ -26,10 +26,10 @@
|
|||||||
#include "baseeditordocumentprocessor.h"
|
#include "baseeditordocumentprocessor.h"
|
||||||
|
|
||||||
#include "cppcodemodelsettings.h"
|
#include "cppcodemodelsettings.h"
|
||||||
#include "cpplanguage.h"
|
|
||||||
#include "cppmodelmanager.h"
|
#include "cppmodelmanager.h"
|
||||||
#include "cpptoolsbridge.h"
|
#include "cpptoolsbridge.h"
|
||||||
#include "cpptoolsreuse.h"
|
#include "cpptoolsreuse.h"
|
||||||
|
#include "cpptools_utils.h"
|
||||||
#include "editordocumenthandle.h"
|
#include "editordocumenthandle.h"
|
||||||
|
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
|||||||
@@ -74,8 +74,9 @@ public:
|
|||||||
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
|
using HeaderErrorDiagnosticWidgetCreator = std::function<QWidget*()>;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
// Signal interface to implement
|
// Signal interface to implement
|
||||||
|
void projectPartInfoUpdated(const CppTools::ProjectPartInfo &projectPartInfo);
|
||||||
|
|
||||||
void codeWarningsUpdated(unsigned revision,
|
void codeWarningsUpdated(unsigned revision,
|
||||||
const QList<QTextEdit::ExtraSelection> selections,
|
const QList<QTextEdit::ExtraSelection> selections,
|
||||||
const HeaderErrorDiagnosticWidgetCreator &creator,
|
const HeaderErrorDiagnosticWidgetCreator &creator,
|
||||||
|
|||||||
@@ -77,19 +77,20 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
|
|||||||
QString projectConfigFile;
|
QString projectConfigFile;
|
||||||
LanguageFeatures features = LanguageFeatures::defaultFeatures();
|
LanguageFeatures features = LanguageFeatures::defaultFeatures();
|
||||||
|
|
||||||
baseState.projectPart = determineProjectPart(filePath(),
|
baseState.projectPartInfo = determineProjectPart(filePath(),
|
||||||
baseConfig,
|
baseConfig,
|
||||||
baseState,
|
baseState,
|
||||||
updateParams.activeProject,
|
updateParams.activeProject,
|
||||||
updateParams.languagePreference,
|
updateParams.languagePreference,
|
||||||
updateParams.hasActiveProjectChanged);
|
updateParams.hasActiveProjectChanged);
|
||||||
|
emit projectPartInfoUpdated(baseState.projectPartInfo);
|
||||||
|
|
||||||
if (state.forceSnapshotInvalidation) {
|
if (state.forceSnapshotInvalidation) {
|
||||||
invalidateSnapshot = true;
|
invalidateSnapshot = true;
|
||||||
state.forceSnapshotInvalidation = false;
|
state.forceSnapshotInvalidation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const ProjectPart::Ptr part = baseState.projectPart) {
|
if (const ProjectPart::Ptr part = baseState.projectPartInfo.projectPart) {
|
||||||
configFile += part->toolchainDefines;
|
configFile += part->toolchainDefines;
|
||||||
configFile += overwrittenToolchainDefines(*part.data());
|
configFile += overwrittenToolchainDefines(*part.data());
|
||||||
configFile += part->projectDefines;
|
configFile += part->projectDefines;
|
||||||
|
|||||||
@@ -190,6 +190,8 @@ BuiltinEditorDocumentProcessor::BuiltinEditorDocumentProcessor(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(m_parser.data(), &BuiltinEditorDocumentParser::projectPartInfoUpdated,
|
||||||
|
this, &BaseEditorDocumentProcessor::projectPartInfoUpdated);
|
||||||
connect(m_parser.data(), &BuiltinEditorDocumentParser::finished,
|
connect(m_parser.data(), &BuiltinEditorDocumentParser::finished,
|
||||||
this, &BuiltinEditorDocumentProcessor::onParserFinished);
|
this, &BuiltinEditorDocumentProcessor::onParserFinished);
|
||||||
connect(&m_semanticInfoUpdater, &SemanticInfoUpdater::updated,
|
connect(&m_semanticInfoUpdater, &SemanticInfoUpdater::updated,
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ ProjectPart::Ptr projectPartOfEditorDocument(const QString &filePath)
|
|||||||
{
|
{
|
||||||
auto *editorDocument = CppModelManager::instance()->cppEditorDocument(filePath);
|
auto *editorDocument = CppModelManager::instance()->cppEditorDocument(filePath);
|
||||||
QTC_ASSERT(editorDocument, return ProjectPart::Ptr());
|
QTC_ASSERT(editorDocument, return ProjectPart::Ptr());
|
||||||
return editorDocument->processor()->parser()->projectPart();
|
return editorDocument->processor()->parser()->projectPartInfo().projectPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|||||||
@@ -31,46 +31,99 @@
|
|||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
static bool isPreferredLanguage(const ProjectPart &projectPart, Language preference)
|
class ProjectPartPrioritizer
|
||||||
{
|
{
|
||||||
const bool isCProjectPart = projectPart.languageVersion <= ProjectPart::LatestCVersion;
|
public:
|
||||||
return (preference == Language::C && isCProjectPart)
|
struct PrioritizedProjectPart
|
||||||
|| (preference == Language::Cxx && !isCProjectPart);
|
{
|
||||||
}
|
PrioritizedProjectPart(const ProjectPart::Ptr &projectPart, int priority)
|
||||||
|
: projectPart(projectPart) , priority(priority) {}
|
||||||
|
|
||||||
static int priority(const ProjectPart &projectPart,
|
ProjectPart::Ptr projectPart;
|
||||||
|
int priority = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ProjectPartPrioritizer(const QList<ProjectPart::Ptr> &projectParts,
|
||||||
const ProjectExplorer::Project *activeProject,
|
const ProjectExplorer::Project *activeProject,
|
||||||
Language languagePreference)
|
Language languagePreference)
|
||||||
{
|
: m_projectParts(projectParts)
|
||||||
|
, m_activeProject(activeProject)
|
||||||
|
, m_languagePreference(languagePreference)
|
||||||
|
{
|
||||||
|
// Determine best project part
|
||||||
|
const QList<PrioritizedProjectPart> prioritized = prioritize();
|
||||||
|
m_projectPart = prioritized.first().projectPart;
|
||||||
|
|
||||||
|
// Determine ambiguity
|
||||||
|
m_isAmbiguous = prioritized.size() > 1
|
||||||
|
? prioritized[0].priority == prioritized[1].priority
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectPart::Ptr projectPart()
|
||||||
|
{
|
||||||
|
return m_projectPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAmbiguous() const
|
||||||
|
{
|
||||||
|
return m_isAmbiguous;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<PrioritizedProjectPart> prioritize()
|
||||||
|
{
|
||||||
|
// Prioritize
|
||||||
|
QList<PrioritizedProjectPart> prioritized = Utils::transform(m_projectParts,
|
||||||
|
[&](const ProjectPart::Ptr &projectPart) {
|
||||||
|
return PrioritizedProjectPart{projectPart, priority(*projectPart)};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort according to priority
|
||||||
|
const auto lessThan = [&] (const PrioritizedProjectPart &p1,
|
||||||
|
const PrioritizedProjectPart &p2) {
|
||||||
|
return p1.priority > p2.priority;
|
||||||
|
};
|
||||||
|
std::stable_sort(prioritized.begin(), prioritized.end(), lessThan);
|
||||||
|
|
||||||
|
return prioritized;
|
||||||
|
}
|
||||||
|
|
||||||
|
int priority(const ProjectPart &projectPart) const
|
||||||
|
{
|
||||||
int thePriority = 0;
|
int thePriority = 0;
|
||||||
|
|
||||||
if (projectPart.project == activeProject)
|
if (projectPart.project == m_activeProject)
|
||||||
thePriority += 100;
|
thePriority += 100;
|
||||||
|
|
||||||
if (projectPart.selectedForBuilding)
|
if (projectPart.selectedForBuilding)
|
||||||
thePriority += 10;
|
thePriority += 10;
|
||||||
|
|
||||||
if (isPreferredLanguage(projectPart, languagePreference))
|
if (isPreferredLanguage(projectPart))
|
||||||
thePriority += 1;
|
thePriority += 1;
|
||||||
|
|
||||||
return thePriority;
|
return thePriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ProjectPart::Ptr chooseFromMultiple(const QList<ProjectPart::Ptr> &projectParts,
|
bool isPreferredLanguage(const ProjectPart &projectPart) const
|
||||||
const ProjectExplorer::Project *activeProject,
|
{
|
||||||
Language languagePreference)
|
const bool isCProjectPart = projectPart.languageVersion <= ProjectPart::LatestCVersion;
|
||||||
{
|
return (m_languagePreference == Language::C && isCProjectPart)
|
||||||
QList<ProjectPart::Ptr> projectPartsPrioritized = projectParts;
|
|| (m_languagePreference == Language::Cxx && !isCProjectPart);
|
||||||
const auto lessThan = [&] (const ProjectPart::Ptr &p1, const ProjectPart::Ptr &p2) {
|
}
|
||||||
return priority(*p1, activeProject, languagePreference)
|
|
||||||
> priority(*p2, activeProject, languagePreference);
|
|
||||||
};
|
|
||||||
std::stable_sort(projectPartsPrioritized.begin(), projectPartsPrioritized.end(), lessThan);
|
|
||||||
|
|
||||||
return projectPartsPrioritized.first();
|
private:
|
||||||
}
|
const QList<ProjectPart::Ptr> m_projectParts;
|
||||||
|
const ProjectExplorer::Project *m_activeProject = nullptr;
|
||||||
|
Language m_languagePreference = Language::Cxx;
|
||||||
|
|
||||||
ProjectPart::Ptr ProjectPartChooser::choose(const QString &filePath,
|
// Results
|
||||||
|
ProjectPart::Ptr m_projectPart;
|
||||||
|
bool m_isAmbiguous = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
ProjectPartInfo ProjectPartChooser::choose(
|
||||||
|
const QString &filePath,
|
||||||
const ProjectPart::Ptr ¤tProjectPart,
|
const ProjectPart::Ptr ¤tProjectPart,
|
||||||
const ProjectPart::Ptr &manuallySetProjectPart,
|
const ProjectPart::Ptr &manuallySetProjectPart,
|
||||||
bool stickToPreviousProjectPart,
|
bool stickToPreviousProjectPart,
|
||||||
@@ -83,30 +136,39 @@ ProjectPart::Ptr ProjectPartChooser::choose(const QString &filePath,
|
|||||||
QTC_CHECK(m_fallbackProjectPart);
|
QTC_CHECK(m_fallbackProjectPart);
|
||||||
|
|
||||||
if (manuallySetProjectPart)
|
if (manuallySetProjectPart)
|
||||||
return manuallySetProjectPart;
|
return {manuallySetProjectPart, ProjectPartInfo::NoHint};
|
||||||
|
|
||||||
ProjectPart::Ptr projectPart = currentProjectPart;
|
ProjectPart::Ptr projectPart = currentProjectPart;
|
||||||
|
ProjectPartInfo::Hint hint = ProjectPartInfo::NoHint;
|
||||||
|
|
||||||
QList<ProjectPart::Ptr> projectParts = m_projectPartsForFile(filePath);
|
QList<ProjectPart::Ptr> projectParts = m_projectPartsForFile(filePath);
|
||||||
if (projectParts.isEmpty()) {
|
if (projectParts.isEmpty()) {
|
||||||
if (projectPart && stickToPreviousProjectPart)
|
if (projectPart && stickToPreviousProjectPart)
|
||||||
// File is not directly part of any project, but we got one before. We will re-use it,
|
// File is not directly part of any project, but we got one before. We will re-use it,
|
||||||
// because re-calculating this can be expensive when the dependency table is big.
|
// because re-calculating this can be expensive when the dependency table is big.
|
||||||
return projectPart;
|
return {projectPart, ProjectPartInfo::NoHint};
|
||||||
|
|
||||||
// Fall-back step 1: Get some parts through the dependency table:
|
// Fall-back step 1: Get some parts through the dependency table:
|
||||||
projectParts = m_projectPartsFromDependenciesForFile(filePath);
|
projectParts = m_projectPartsFromDependenciesForFile(filePath);
|
||||||
if (projectParts.isEmpty())
|
if (projectParts.isEmpty()) {
|
||||||
// Fall-back step 2: Use fall-back part from the model manager:
|
// Fall-back step 2: Use fall-back part from the model manager:
|
||||||
projectPart = m_fallbackProjectPart();
|
projectPart = m_fallbackProjectPart();
|
||||||
else
|
hint = ProjectPartInfo::IsFallbackMatch;
|
||||||
projectPart = chooseFromMultiple(projectParts, activeProject, languagePreference);
|
|
||||||
} else {
|
} else {
|
||||||
if (projectHasChanged || !projectParts.contains(projectPart))
|
ProjectPartPrioritizer prioritizer(projectParts, activeProject, languagePreference);
|
||||||
projectPart = chooseFromMultiple(projectParts, activeProject, languagePreference);
|
projectPart = prioritizer.projectPart();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (projectHasChanged || !projectParts.contains(projectPart)) {
|
||||||
|
ProjectPartPrioritizer prioritizer(projectParts, activeProject, languagePreference);
|
||||||
|
projectPart = prioritizer.projectPart();
|
||||||
|
hint = prioritizer.isAmbiguous()
|
||||||
|
? ProjectPartInfo::IsAmbiguousMatch
|
||||||
|
: ProjectPartInfo::NoHint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return projectPart;
|
return {projectPart, hint};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectPartChooser::setFallbackProjectPart(const FallBackProjectPart &getter)
|
void ProjectPartChooser::setFallbackProjectPart(const FallBackProjectPart &getter)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cpplanguage.h"
|
#include "cpptools_utils.h"
|
||||||
#include "projectpart.h"
|
#include "projectpart.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -48,7 +48,8 @@ public:
|
|||||||
void setProjectPartsForFile(const ProjectPartsForFile &getter);
|
void setProjectPartsForFile(const ProjectPartsForFile &getter);
|
||||||
void setProjectPartsFromDependenciesForFile(const ProjectPartsFromDependenciesForFile &getter);
|
void setProjectPartsFromDependenciesForFile(const ProjectPartsFromDependenciesForFile &getter);
|
||||||
|
|
||||||
ProjectPart::Ptr choose(const QString &filePath,
|
ProjectPartInfo choose(
|
||||||
|
const QString &filePath,
|
||||||
const ProjectPart::Ptr ¤tProjectPart,
|
const ProjectPart::Ptr ¤tProjectPart,
|
||||||
const ProjectPart::Ptr &manuallySetProjectPart,
|
const ProjectPart::Ptr &manuallySetProjectPart,
|
||||||
bool stickToPreviousProjectPart,
|
bool stickToPreviousProjectPart,
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ HEADERS += \
|
|||||||
cppfunctionsfilter.h \
|
cppfunctionsfilter.h \
|
||||||
cppincludesfilter.h \
|
cppincludesfilter.h \
|
||||||
cppindexingsupport.h \
|
cppindexingsupport.h \
|
||||||
cpplanguage.h \
|
|
||||||
cpplocalsymbols.h \
|
cpplocalsymbols.h \
|
||||||
cpplocatordata.h \
|
cpplocatordata.h \
|
||||||
cpplocatorfilter.h \
|
cpplocatorfilter.h \
|
||||||
@@ -50,6 +49,7 @@ HEADERS += \
|
|||||||
cppsemanticinfoupdater.h \
|
cppsemanticinfoupdater.h \
|
||||||
cppsourceprocessor.h \
|
cppsourceprocessor.h \
|
||||||
cpptools_global.h \
|
cpptools_global.h \
|
||||||
|
cpptools_utils.h \
|
||||||
cpptoolsconstants.h \
|
cpptoolsconstants.h \
|
||||||
cpptoolsjsextension.h \
|
cpptoolsjsextension.h \
|
||||||
cpptoolsplugin.h \
|
cpptoolsplugin.h \
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ Project {
|
|||||||
"cppfunctionsfilter.cpp", "cppfunctionsfilter.h",
|
"cppfunctionsfilter.cpp", "cppfunctionsfilter.h",
|
||||||
"cppincludesfilter.cpp", "cppincludesfilter.h",
|
"cppincludesfilter.cpp", "cppincludesfilter.h",
|
||||||
"cppindexingsupport.cpp", "cppindexingsupport.h",
|
"cppindexingsupport.cpp", "cppindexingsupport.h",
|
||||||
"cpplanguage.h",
|
|
||||||
"cpplocalsymbols.cpp", "cpplocalsymbols.h",
|
"cpplocalsymbols.cpp", "cpplocalsymbols.h",
|
||||||
"cpplocatordata.cpp", "cpplocatordata.h",
|
"cpplocatordata.cpp", "cpplocatordata.h",
|
||||||
"cpplocatorfilter.cpp", "cpplocatorfilter.h",
|
"cpplocatorfilter.cpp", "cpplocatorfilter.h",
|
||||||
@@ -81,6 +80,7 @@ Project {
|
|||||||
"cpptoolsbridgeqtcreatorimplementation.cpp", "cpptoolsbridgeqtcreatorimplementation.h",
|
"cpptoolsbridgeqtcreatorimplementation.cpp", "cpptoolsbridgeqtcreatorimplementation.h",
|
||||||
"cpptools.qrc",
|
"cpptools.qrc",
|
||||||
"cpptools_global.h",
|
"cpptools_global.h",
|
||||||
|
"cpptools_utils.h",
|
||||||
"cpptoolsconstants.h",
|
"cpptoolsconstants.h",
|
||||||
"cpptoolsjsextension.cpp", "cpptoolsjsextension.h",
|
"cpptoolsjsextension.cpp", "cpptoolsjsextension.h",
|
||||||
"cpptoolsplugin.cpp", "cpptoolsplugin.h",
|
"cpptoolsplugin.cpp", "cpptoolsplugin.h",
|
||||||
|
|||||||
@@ -25,8 +25,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "projectpart.h"
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
|
|
||||||
enum class Language { C, Cxx };
|
enum class Language { C, Cxx };
|
||||||
|
|
||||||
|
class ProjectPartInfo {
|
||||||
|
public:
|
||||||
|
enum Hint {
|
||||||
|
NoHint,
|
||||||
|
IsFallbackMatch,
|
||||||
|
IsAmbiguousMatch
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProjectPart::Ptr projectPart;
|
||||||
|
Hint hint;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
@@ -47,7 +47,7 @@ namespace {
|
|||||||
CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath)
|
CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath)
|
||||||
{
|
{
|
||||||
if (const auto parser = BaseEditorDocumentParser::get(filePath))
|
if (const auto parser = BaseEditorDocumentParser::get(filePath))
|
||||||
return parser->projectPart();
|
return parser->projectPartInfo().projectPart;
|
||||||
|
|
||||||
return CppTools::ProjectPart::Ptr();
|
return CppTools::ProjectPart::Ptr();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,13 @@
|
|||||||
|
|
||||||
#include "googletest.h"
|
#include "googletest.h"
|
||||||
|
|
||||||
#include <cpptools/cpplanguage.h>
|
|
||||||
#include <cpptools/cppprojectpartchooser.h>
|
#include <cpptools/cppprojectpartchooser.h>
|
||||||
|
#include <cpptools/cpptools_utils.h>
|
||||||
#include <cpptools/projectpart.h>
|
#include <cpptools/projectpart.h>
|
||||||
|
|
||||||
using CppTools::Internal::ProjectPartChooser;
|
using CppTools::Internal::ProjectPartChooser;
|
||||||
using CppTools::ProjectPart;
|
using CppTools::ProjectPart;
|
||||||
|
using CppTools::ProjectPartInfo;
|
||||||
using CppTools::Language;
|
using CppTools::Language;
|
||||||
|
|
||||||
using testing::Eq;
|
using testing::Eq;
|
||||||
@@ -41,7 +42,7 @@ class ProjectPartChooser : public ::testing::Test
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void SetUp() override;
|
void SetUp() override;
|
||||||
const ProjectPart::Ptr choose() const;
|
const ProjectPartInfo choose() const;
|
||||||
|
|
||||||
static QList<ProjectPart::Ptr> createProjectPartsWithDifferentProjects();
|
static QList<ProjectPart::Ptr> createProjectPartsWithDifferentProjects();
|
||||||
static QList<ProjectPart::Ptr> createCAndCxxProjectParts();
|
static QList<ProjectPart::Ptr> createCAndCxxProjectParts();
|
||||||
@@ -65,7 +66,7 @@ TEST_F(ProjectPartChooser, ChooseManuallySet)
|
|||||||
{
|
{
|
||||||
manuallySetProjectPart.reset(new ProjectPart);
|
manuallySetProjectPart.reset(new ProjectPart);
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(manuallySetProjectPart));
|
ASSERT_THAT(chosen, Eq(manuallySetProjectPart));
|
||||||
}
|
}
|
||||||
@@ -76,7 +77,7 @@ TEST_F(ProjectPartChooser, ForMultipleChoosePrevious)
|
|||||||
projectPartsForFile += otherProjectPart;
|
projectPartsForFile += otherProjectPart;
|
||||||
projectPartsForFile += currentProjectPart;
|
projectPartsForFile += currentProjectPart;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(currentProjectPart));
|
ASSERT_THAT(chosen, Eq(currentProjectPart));
|
||||||
}
|
}
|
||||||
@@ -88,7 +89,7 @@ TEST_F(ProjectPartChooser, ForMultipleChooseFromActiveProject)
|
|||||||
projectPartsForFile += projectParts;
|
projectPartsForFile += projectParts;
|
||||||
activeProject = secondProjectPart->project;
|
activeProject = secondProjectPart->project;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
||||||
}
|
}
|
||||||
@@ -102,7 +103,7 @@ TEST_F(ProjectPartChooser, ForMultiplePreferSelectedForBuilding)
|
|||||||
projectPartsForFile += firstProjectPart;
|
projectPartsForFile += firstProjectPart;
|
||||||
projectPartsForFile += secondProjectPart;
|
projectPartsForFile += secondProjectPart;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
||||||
}
|
}
|
||||||
@@ -114,7 +115,7 @@ TEST_F(ProjectPartChooser, ForMultipleFromDependenciesChooseFromActiveProject)
|
|||||||
projectPartsFromDependenciesForFile += projectParts;
|
projectPartsFromDependenciesForFile += projectParts;
|
||||||
activeProject = secondProjectPart->project;
|
activeProject = secondProjectPart->project;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
||||||
}
|
}
|
||||||
@@ -129,7 +130,7 @@ TEST_F(ProjectPartChooser, ForMultipleCheckIfActiveProjectChanged)
|
|||||||
activeProject = secondProjectPart->project;
|
activeProject = secondProjectPart->project;
|
||||||
projectHasChanged = true;
|
projectHasChanged = true;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
ASSERT_THAT(chosen, Eq(secondProjectPart));
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ TEST_F(ProjectPartChooser, ForMultipleAndAmbigiousHeaderPreferCProjectPart)
|
|||||||
projectPartsForFile = createCAndCxxProjectParts();
|
projectPartsForFile = createCAndCxxProjectParts();
|
||||||
const ProjectPart::Ptr cProjectPart = projectPartsForFile.at(0);
|
const ProjectPart::Ptr cProjectPart = projectPartsForFile.at(0);
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(cProjectPart));
|
ASSERT_THAT(chosen, Eq(cProjectPart));
|
||||||
}
|
}
|
||||||
@@ -151,16 +152,27 @@ TEST_F(ProjectPartChooser, ForMultipleAndAmbigiousHeaderPreferCxxProjectPart)
|
|||||||
projectPartsForFile = createCAndCxxProjectParts();
|
projectPartsForFile = createCAndCxxProjectParts();
|
||||||
const ProjectPart::Ptr cxxProjectPart = projectPartsForFile.at(1);
|
const ProjectPart::Ptr cxxProjectPart = projectPartsForFile.at(1);
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(cxxProjectPart));
|
ASSERT_THAT(chosen, Eq(cxxProjectPart));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectPartChooser, IndicateMultiple)
|
||||||
|
{
|
||||||
|
const ProjectPart::Ptr p1{new ProjectPart};
|
||||||
|
const ProjectPart::Ptr p2{new ProjectPart};
|
||||||
|
projectPartsForFile += { p1, p2 };
|
||||||
|
|
||||||
|
const ProjectPartInfo::Hint hint = choose().hint;
|
||||||
|
|
||||||
|
ASSERT_THAT(hint, Eq(ProjectPartInfo::Hint::IsAmbiguousMatch));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ProjectPartChooser, IfProjectIsGoneStickToPrevious) // Built-in Code Model
|
TEST_F(ProjectPartChooser, IfProjectIsGoneStickToPrevious) // Built-in Code Model
|
||||||
{
|
{
|
||||||
stickToPreviousProjectPart = true;
|
stickToPreviousProjectPart = true;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(currentProjectPart));
|
ASSERT_THAT(chosen, Eq(currentProjectPart));
|
||||||
}
|
}
|
||||||
@@ -170,7 +182,7 @@ TEST_F(ProjectPartChooser, IfProjectIsGoneDoNotStickToPrevious) // Clang Code Mo
|
|||||||
currentProjectPart.clear();
|
currentProjectPart.clear();
|
||||||
stickToPreviousProjectPart = true;
|
stickToPreviousProjectPart = true;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(ProjectPart::Ptr()));
|
ASSERT_THAT(chosen, Eq(ProjectPart::Ptr()));
|
||||||
}
|
}
|
||||||
@@ -180,7 +192,7 @@ TEST_F(ProjectPartChooser, ForMultipleChooseNewIfPreviousIsGone)
|
|||||||
const ProjectPart::Ptr newProjectPart{new ProjectPart};
|
const ProjectPart::Ptr newProjectPart{new ProjectPart};
|
||||||
projectPartsForFile += newProjectPart;
|
projectPartsForFile += newProjectPart;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(newProjectPart));
|
ASSERT_THAT(chosen, Eq(newProjectPart));
|
||||||
}
|
}
|
||||||
@@ -190,7 +202,7 @@ TEST_F(ProjectPartChooser, FallbackToProjectPartFromDependencies)
|
|||||||
const ProjectPart::Ptr fromDependencies{new ProjectPart};
|
const ProjectPart::Ptr fromDependencies{new ProjectPart};
|
||||||
projectPartsFromDependenciesForFile += fromDependencies;
|
projectPartsFromDependenciesForFile += fromDependencies;
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(fromDependencies));
|
ASSERT_THAT(chosen, Eq(fromDependencies));
|
||||||
}
|
}
|
||||||
@@ -199,11 +211,20 @@ TEST_F(ProjectPartChooser, FallbackToProjectPartFromModelManager)
|
|||||||
{
|
{
|
||||||
fallbackProjectPart.reset(new ProjectPart);
|
fallbackProjectPart.reset(new ProjectPart);
|
||||||
|
|
||||||
const ProjectPart::Ptr chosen = choose();
|
const ProjectPart::Ptr chosen = choose().projectPart;
|
||||||
|
|
||||||
ASSERT_THAT(chosen, Eq(fallbackProjectPart));
|
ASSERT_THAT(chosen, Eq(fallbackProjectPart));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ProjectPartChooser, IndicateFallbacktoProjectPartFromModelManager)
|
||||||
|
{
|
||||||
|
fallbackProjectPart.reset(new ProjectPart);
|
||||||
|
|
||||||
|
const ProjectPartInfo::Hint hint = choose().hint;
|
||||||
|
|
||||||
|
ASSERT_THAT(hint, Eq(ProjectPartInfo::Hint::IsFallbackMatch));
|
||||||
|
}
|
||||||
|
|
||||||
void ProjectPartChooser::SetUp()
|
void ProjectPartChooser::SetUp()
|
||||||
{
|
{
|
||||||
chooser.setFallbackProjectPart([&](){
|
chooser.setFallbackProjectPart([&](){
|
||||||
@@ -217,7 +238,7 @@ void ProjectPartChooser::SetUp()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProjectPart::Ptr ProjectPartChooser::choose() const
|
const ProjectPartInfo ProjectPartChooser::choose() const
|
||||||
{
|
{
|
||||||
return chooser.choose(filePath,
|
return chooser.choose(filePath,
|
||||||
currentProjectPart,
|
currentProjectPart,
|
||||||
|
|||||||
Reference in New Issue
Block a user