diff options
author | Nikolai Kosjar <nikolai.kosjar@theqtcompany.com> | 2015-10-08 13:32:36 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@theqtcompany.com> | 2015-10-12 15:08:24 +0000 |
commit | 6b6ad446ebdff5709278e299f525dba6173f3427 (patch) | |
tree | 719a643bff78fb2522326ea0c2102cdba1db5d67 /src/plugins/cpptools/cppfileiterationorder.cpp | |
parent | eccc5676516f2ee22884cd9cbf15e6dba76fc632 (diff) | |
download | qt-creator-6b6ad446ebdff5709278e299f525dba6173f3427.tar.gz |
CppTools: Make FollowSymbol respect projects
Finding the class definition for a forward declaration or finding the
function definition from its declaration is mostly determined by the
file iteration order. Documents with the most common path prefix are
checked first.
This works fine as long as the files of your project have a common
ancestor. If that's not the case, FollowSymbol might take you to the
definition within another project.
Fix that issue by considering the project part id when constructing the
file iteration order. Since the cached file iteration order now depends
on the projects, ensure to clear it if projects are added, changed or
removed.
Task-number: QTCREATORBUG-15116
Change-Id: I529166bac363959c9fee0b946747fd0370a88809
Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
Diffstat (limited to 'src/plugins/cpptools/cppfileiterationorder.cpp')
-rw-r--r-- | src/plugins/cpptools/cppfileiterationorder.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/plugins/cpptools/cppfileiterationorder.cpp b/src/plugins/cpptools/cppfileiterationorder.cpp new file mode 100644 index 0000000000..807e26f8ff --- /dev/null +++ b/src/plugins/cpptools/cppfileiterationorder.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "cppfileiterationorder.h" + +#include <utils/qtcassert.h> + +namespace CppTools { + +FileIterationOrder::Entry::Entry(const QString &filePath, + const QString &projectPartId, + int commonPrefixLength, + int commonProjectPartPrefixLength) + : filePath(filePath) + , projectPartId(projectPartId) + , commonFilePathPrefixLength(commonPrefixLength) + , commonProjectPartPrefixLength(commonProjectPartPrefixLength) +{} + +namespace { + +bool cmpPrefixLengthAndText(int prefixLength1, int prefixLength2) +{ + return prefixLength1 > prefixLength2; +} + +bool cmpLessFilePath(const FileIterationOrder::Entry &first, + const FileIterationOrder::Entry &second) +{ + return cmpPrefixLengthAndText(first.commonFilePathPrefixLength, + second.commonFilePathPrefixLength); +} + +bool cmpLessProjectPartId(const FileIterationOrder::Entry &first, + const FileIterationOrder::Entry &second) +{ + return cmpPrefixLengthAndText(first.commonProjectPartPrefixLength, + second.commonProjectPartPrefixLength); +} + +bool hasProjectPart(const FileIterationOrder::Entry &entry) +{ + return !entry.projectPartId.isEmpty(); +} + +} // anonymous namespace + +bool operator<(const FileIterationOrder::Entry &first, const FileIterationOrder::Entry &second) +{ + if (hasProjectPart(first)) { + if (hasProjectPart(second)) { + if (first.projectPartId == second.projectPartId) + return cmpLessFilePath(first, second); + else + return cmpLessProjectPartId(first, second); + } else { + return true; + } + } else { + if (hasProjectPart(second)) + return false; + else + return cmpLessFilePath(first, second); + } +} + +FileIterationOrder::FileIterationOrder() +{ +} + +FileIterationOrder::FileIterationOrder(const QString &referenceFilePath, + const QString &referenceProjectPartId) +{ + setReference(referenceFilePath, referenceProjectPartId); +} + +void FileIterationOrder::setReference(const QString &filePath, + const QString &projectPartId) +{ + m_referenceFilePath = filePath; + m_referenceProjectPartId = projectPartId; +} + +bool FileIterationOrder::isValid() const +{ + return !m_referenceFilePath.isEmpty(); +} + +static int commonPrefixLength(const QString &filePath1, const QString &filePath2) +{ + const auto mismatches = std::mismatch(filePath1.begin(), + filePath1.end(), + filePath2.begin()); + return mismatches.first - filePath1.begin(); +} + +FileIterationOrder::Entry FileIterationOrder::createEntryFromFilePath( + const QString &filePath, + const QString &projectPartId) const +{ + const int filePrefixLength = commonPrefixLength(m_referenceFilePath, filePath); + const int projectPartPrefixLength = commonPrefixLength(m_referenceProjectPartId, projectPartId); + return Entry(filePath, projectPartId, filePrefixLength, projectPartPrefixLength); +} + +void FileIterationOrder::insert(const QString &filePath, const QString &projectPartId) +{ + const Entry entry = createEntryFromFilePath(filePath, projectPartId); + m_set.insert(entry); +} + +void FileIterationOrder::remove(const QString &filePath, const QString &projectPartId) +{ + const auto needleElement = createEntryFromFilePath(filePath, projectPartId); + const auto range = m_set.equal_range(needleElement); + + const auto toRemove = std::find_if(range.first, range.second, [filePath] (const Entry &entry) { + return entry.filePath == filePath; + }); + QTC_ASSERT(toRemove != range.second, return); + m_set.erase(toRemove); +} + +QStringList FileIterationOrder::toStringList() const +{ + QStringList result; + + for (const auto &entry : m_set) + result.append(entry.filePath); + + return result; +} + +} // namespace CppTools |