diff options
author | Nikolai Kosjar <nikolai.kosjar@digia.com> | 2013-06-06 09:27:28 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@digia.com> | 2013-06-11 15:57:10 +0200 |
commit | f3186690bd39020c85cdee5a5ea6996011ad7158 (patch) | |
tree | ec2deefbf528556f6c3052d7e4200bd229957ebd /src/plugins/cppeditor/cppquickfixes.cpp | |
parent | e3bc84c4143498b20f702c0d3b4b0b75a99ffe0e (diff) | |
download | qt-creator-f3186690bd39020c85cdee5a5ea6996011ad7158.tar.gz |
CppEditor: Improve finding position for new includes
...by detecting include groups (separated by new lines, include types
and same dir prefix).
Task-number: QTCREATORBUG-9317
Change-Id: I73e80fdc715104901cb2d4f5b15b4cab5d04d305
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
Diffstat (limited to 'src/plugins/cppeditor/cppquickfixes.cpp')
-rw-r--r-- | src/plugins/cppeditor/cppquickfixes.cpp | 163 |
1 files changed, 46 insertions, 117 deletions
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 1d2a38a9c3..d157767609 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -40,6 +40,7 @@ #include <cpptools/cpppointerdeclarationformatter.h> #include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsreuse.h> +#include <cpptools/includeutils.h> #include <cpptools/insertionpointlocator.h> #include <cpptools/symbolfinder.h> @@ -182,6 +183,37 @@ Class *isMemberFunction(const LookupContext &context, Function *function) return 0; } +// Given include is e.g. "afile.h" or <afile.h> (quotes/angle brackets included!). +void insertNewIncludeDirective(const QString &include, CppRefactoringFilePtr file) +{ + // Find optimal position + using namespace IncludeUtils; + LineForNewIncludeDirective finder(file->document(), file->cppDocument()->includes(), + LineForNewIncludeDirective::IgnoreMocIncludes, + LineForNewIncludeDirective::AutoDetect); + unsigned newLinesToPrepend = 0; + unsigned newLinesToAppend = 0; + const int insertLine = finder(include, &newLinesToPrepend, &newLinesToAppend); + QTC_ASSERT(insertLine >= 1, return); + const int insertPosition = file->position(insertLine, 1); + QTC_ASSERT(insertPosition >= 0, return); + + // Construct text to insert + const QString includeLine = QLatin1String("#include ") + include + QLatin1Char('\n'); + QString prependedNewLines, appendedNewLines; + while (newLinesToAppend--) + appendedNewLines += QLatin1String("\n"); + while (newLinesToPrepend--) + prependedNewLines += QLatin1String("\n"); + const QString textToInsert = prependedNewLines + includeLine + appendedNewLines; + + // Insert + ChangeSet changes; + changes.insert(insertPosition, textToInsert); + file->setChangeSet(changes); + file->apply(); +} + } // anonymous namespace namespace { @@ -1479,24 +1511,8 @@ public: if (best.isEmpty()) best = headerFile; - int pos = currentFile->startOf(1); - - unsigned currentLine = currentFile->cursor().blockNumber() + 1; - unsigned bestLine = 0; - foreach (const Document::Include &incl, - assistInterface()->semanticInfo().doc->includes()) { - if (incl.line() < currentLine) - bestLine = incl.line(); - } - - if (bestLine) - pos = currentFile->document()->findBlockByNumber(bestLine).position(); - - ChangeSet changes; - changes.insert(pos, QLatin1String("#include <") - + QFileInfo(best).fileName() + QLatin1String(">\n")); - currentFile->setChangeSet(changes); - currentFile->apply(); + const QString include = QString::fromLatin1("<%1>").arg(QFileInfo(best).fileName()); + insertNewIncludeDirective(include, currentFile); } } @@ -1731,108 +1747,21 @@ void ConvertToCamelCase::match(const CppQuickFixInterface &interface, QuickFixOp } } -namespace { - -class AddIncludeForUndefinedIdentifierOp: public CppQuickFixOperation +AddIncludeForUndefinedIdentifierOp::AddIncludeForUndefinedIdentifierOp( + const CppQuickFixInterface &interface, int priority, const QString &include) + : CppQuickFixOperation(interface, priority) + , m_include(include) { -public: - AddIncludeForUndefinedIdentifierOp(const CppQuickFixInterface &interface, int priority, - const QString &include) - : CppQuickFixOperation(interface, priority) - , m_include(include) - { - setDescription(QApplication::translate("CppTools::QuickFix", - "Add #include %1").arg(m_include)); - } - - void perform() - { - CppRefactoringChanges refactoring(snapshot()); - CppRefactoringFilePtr file = refactoring.file(fileName()); - - QList<Document::Include> includes = file->cppDocument()->includes(); - if (!includes.isEmpty()) { - QHash<QString, unsigned> includePositions; - foreach (const Document::Include &include, includes) { - const QString fileName = include.unresolvedFileName(); - if (fileName.endsWith(QLatin1String(".moc"))) - continue; - includePositions.insert(fileName, include.line()); - } - - if (!includePositions.isEmpty()) { - const QString include = m_include.mid(1, m_include.length() - 2); - QList<QString> keys = includePositions.keys(); - keys << include; - qSort(keys); - const int pos = keys.indexOf(include); - - ChangeSet changes; - if (pos + 1 != keys.count()) { - const int insertPos = qMax(0, file->position( - includePositions.value(keys.at(pos + 1)), 1)); - changes.insert(insertPos, - QLatin1String("#include ") + m_include + QLatin1String("\n")); - - } else { - const int insertPos = qMax(0, file->position(includePositions.value( - keys.at(pos - 1)) + 1, 1) - 1); - changes.insert(insertPos, QLatin1String("\n#include ") + m_include); - } - file->setChangeSet(changes); - file->apply(); - return; - } - } - - // No includes or no matching include, find possible first/multi line comment - int insertPos = 0; - QTextBlock block = file->document()->firstBlock(); - while (block.isValid()) { - const QString trimmedText = block.text().trimmed(); - - // Only skip the first comment! - if (trimmedText.startsWith(QLatin1String("/*"))) { - do { - const int pos = block.text().indexOf(QLatin1String("*/")); - if (pos > -1) { - insertPos = block.position() + pos + 2; - break; - } - block = block.next(); - } while (block.isValid()); - break; - } else if (trimmedText.startsWith(QLatin1String("//"))) { - block = block.next(); - while (block.isValid()) { - if (!block.text().trimmed().startsWith(QLatin1String("//"))) { - insertPos = block.position() - 1; - break; - } - block = block.next(); - } - break; - } - - if (!trimmedText.isEmpty()) - break; - block = block.next(); - } - - ChangeSet changes; - if (insertPos != 0) - changes.insert(insertPos, QLatin1String("\n\n#include ") + m_include); - else - changes.insert(insertPos, QString::fromLatin1("#include %1\n\n").arg(m_include)); - file->setChangeSet(changes); - file->apply(); - } + setDescription(QApplication::translate("CppTools::QuickFix", "Add #include %1").arg(m_include)); +} -private: - QString m_include; -}; +void AddIncludeForUndefinedIdentifierOp::perform() +{ + CppRefactoringChanges refactoring(snapshot()); + CppRefactoringFilePtr file = refactoring.file(fileName()); -} // anonymous namespace + insertNewIncludeDirective(m_include, file); +} void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interface, QuickFixOperations &result) |