summaryrefslogtreecommitdiff
path: root/src/plugins/cppeditor/cppquickfixes.cpp
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@digia.com>2013-06-06 09:27:28 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2013-06-11 15:57:10 +0200
commitf3186690bd39020c85cdee5a5ea6996011ad7158 (patch)
treeec2deefbf528556f6c3052d7e4200bd229957ebd /src/plugins/cppeditor/cppquickfixes.cpp
parente3bc84c4143498b20f702c0d3b4b0b75a99ffe0e (diff)
downloadqt-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.cpp163
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)