summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/cppprojectpartchooser.cpp
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2017-01-17 15:27:31 +0100
committerNikolai Kosjar <nikolai.kosjar@qt.io>2017-01-24 14:41:48 +0000
commit0b8df41387005156ea73b029f4d9d77f91ce5eb5 (patch)
tree6b44cb326108dff1c0b37322741aaa3da646fb2b /src/plugins/cpptools/cppprojectpartchooser.cpp
parent19eaf87ef95a510351557119a955223a4aeea7b3 (diff)
downloadqt-creator-0b8df41387005156ea73b029f4d9d77f91ce5eb5.tar.gz
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>
Diffstat (limited to 'src/plugins/cpptools/cppprojectpartchooser.cpp')
-rw-r--r--src/plugins/cpptools/cppprojectpartchooser.cpp152
1 files changed, 107 insertions, 45 deletions
diff --git a/src/plugins/cpptools/cppprojectpartchooser.cpp b/src/plugins/cpptools/cppprojectpartchooser.cpp
index 5f7d3de137..816bddb592 100644
--- a/src/plugins/cpptools/cppprojectpartchooser.cpp
+++ b/src/plugins/cpptools/cppprojectpartchooser.cpp
@@ -31,82 +31,144 @@
namespace CppTools {
namespace Internal {
-static bool isPreferredLanguage(const ProjectPart &projectPart, Language preference)
+class ProjectPartPrioritizer
{
- const bool isCProjectPart = projectPart.languageVersion <= ProjectPart::LatestCVersion;
- return (preference == Language::C && isCProjectPart)
- || (preference == Language::Cxx && !isCProjectPart);
-}
+public:
+ struct PrioritizedProjectPart
+ {
+ PrioritizedProjectPart(const ProjectPart::Ptr &projectPart, int priority)
+ : projectPart(projectPart) , priority(priority) {}
+
+ ProjectPart::Ptr projectPart;
+ int priority = 0;
+ };
-static int priority(const ProjectPart &projectPart,
- const ProjectExplorer::Project *activeProject,
- Language languagePreference)
-{
- int thePriority = 0;
+ ProjectPartPrioritizer(const QList<ProjectPart::Ptr> &projectParts,
+ const ProjectExplorer::Project *activeProject,
+ 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;
+ }
- if (projectPart.project == activeProject)
- thePriority += 100;
+ ProjectPart::Ptr projectPart()
+ {
+ return m_projectPart;
+ }
- if (projectPart.selectedForBuilding)
- thePriority += 10;
+ bool isAmbiguous() const
+ {
+ return m_isAmbiguous;
+ }
- if (isPreferredLanguage(projectPart, languagePreference))
- thePriority += 1;
+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;
+ }
- return thePriority;
-}
+ int priority(const ProjectPart &projectPart) const
+ {
+ int thePriority = 0;
-static ProjectPart::Ptr chooseFromMultiple(const QList<ProjectPart::Ptr> &projectParts,
- const ProjectExplorer::Project *activeProject,
- Language languagePreference)
-{
- QList<ProjectPart::Ptr> projectPartsPrioritized = projectParts;
- 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);
+ if (projectPart.project == m_activeProject)
+ thePriority += 100;
- return projectPartsPrioritized.first();
-}
+ if (projectPart.selectedForBuilding)
+ thePriority += 10;
+
+ if (isPreferredLanguage(projectPart))
+ thePriority += 1;
+
+ return thePriority;
+ }
+
+ bool isPreferredLanguage(const ProjectPart &projectPart) const
+ {
+ const bool isCProjectPart = projectPart.languageVersion <= ProjectPart::LatestCVersion;
+ return (m_languagePreference == Language::C && isCProjectPart)
+ || (m_languagePreference == Language::Cxx && !isCProjectPart);
+ }
-ProjectPart::Ptr ProjectPartChooser::choose(const QString &filePath,
- const ProjectPart::Ptr &currentProjectPart,
- const ProjectPart::Ptr &manuallySetProjectPart,
- bool stickToPreviousProjectPart,
- const ProjectExplorer::Project *activeProject,
- Language languagePreference,
- bool projectHasChanged) const
+private:
+ const QList<ProjectPart::Ptr> m_projectParts;
+ const ProjectExplorer::Project *m_activeProject = nullptr;
+ Language m_languagePreference = Language::Cxx;
+
+ // Results
+ ProjectPart::Ptr m_projectPart;
+ bool m_isAmbiguous = false;
+};
+
+ProjectPartInfo ProjectPartChooser::choose(
+ const QString &filePath,
+ const ProjectPart::Ptr &currentProjectPart,
+ const ProjectPart::Ptr &manuallySetProjectPart,
+ bool stickToPreviousProjectPart,
+ const ProjectExplorer::Project *activeProject,
+ Language languagePreference,
+ bool projectHasChanged) const
{
QTC_CHECK(m_projectPartsForFile);
QTC_CHECK(m_projectPartsFromDependenciesForFile);
QTC_CHECK(m_fallbackProjectPart);
if (manuallySetProjectPart)
- return manuallySetProjectPart;
+ return {manuallySetProjectPart, ProjectPartInfo::NoHint};
ProjectPart::Ptr projectPart = currentProjectPart;
+ ProjectPartInfo::Hint hint = ProjectPartInfo::NoHint;
QList<ProjectPart::Ptr> projectParts = m_projectPartsForFile(filePath);
if (projectParts.isEmpty()) {
if (projectPart && stickToPreviousProjectPart)
// 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.
- return projectPart;
+ return {projectPart, ProjectPartInfo::NoHint};
// Fall-back step 1: Get some parts through the dependency table:
projectParts = m_projectPartsFromDependenciesForFile(filePath);
- if (projectParts.isEmpty())
+ if (projectParts.isEmpty()) {
// Fall-back step 2: Use fall-back part from the model manager:
projectPart = m_fallbackProjectPart();
- else
- projectPart = chooseFromMultiple(projectParts, activeProject, languagePreference);
+ hint = ProjectPartInfo::IsFallbackMatch;
+ } else {
+ ProjectPartPrioritizer prioritizer(projectParts, activeProject, languagePreference);
+ projectPart = prioritizer.projectPart();
+ }
} else {
- if (projectHasChanged || !projectParts.contains(projectPart))
- projectPart = chooseFromMultiple(projectParts, activeProject, languagePreference);
+ 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)