diff options
author | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2017-01-17 15:27:31 +0100 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2017-01-24 14:41:48 +0000 |
commit | 0b8df41387005156ea73b029f4d9d77f91ce5eb5 (patch) | |
tree | 6b44cb326108dff1c0b37322741aaa3da646fb2b /src/plugins/cpptools/cppprojectpartchooser.cpp | |
parent | 19eaf87ef95a510351557119a955223a4aeea7b3 (diff) | |
download | qt-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.cpp | 152 |
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 ¤tProjectPart, - 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 ¤tProjectPart, + 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) |