diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index 5bfdd54765d..cfc0db24d6a 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -27,12 +27,18 @@ #include "clangdiagnosticmanager.h" #include "clangisdiagnosticrelatedtolocation.h" +#include +#include + +#include + #include #include #include #include #include +#include #include #include @@ -193,6 +199,40 @@ bool editorDocumentProcessorHasDiagnosticAt( return false; } +QTextCursor cursorAtLastPositionOfLine(QTextDocument *textDocument, int lineNumber) +{ + const QTextBlock textBlock = textDocument->findBlockByNumber(lineNumber - 1); + QTC_ASSERT(textBlock.isValid(), return QTextCursor()); + + const int lastPositionOfLine = textBlock.position() + textBlock.length() - 1; + + QTextCursor textCursor(textDocument); + textCursor.setPosition(lastPositionOfLine); + + return textCursor; +} + +QString tooltipForFixItAvailableMarker() +{ + QString text = QObject::tr("Inspect available fixits"); + + Core::Command *command = Core::ActionManager::command(TextEditor::Constants::QUICKFIX_THIS); + if (command) + text = Utils::ProxyAction::stringWithAppendedShortcut(text, command->keySequence()); + + return text; +} + +TextEditor::RefactorMarker createFixItAvailableMarker(QTextDocument *textDocument, int lineNumber) +{ + TextEditor::RefactorMarker marker; + marker.tooltip = tooltipForFixItAvailableMarker(); + marker.cursor = cursorAtLastPositionOfLine(textDocument, lineNumber); + marker.data = QLatin1String(CppTools::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID); + + return marker; +} + } // anonymous namespace ClangCodeModel { @@ -212,6 +252,15 @@ void ClangDiagnosticManager::generateTextMarks() addClangTextMarks(m_errorDiagnostics); } +void ClangDiagnosticManager::generateFixItAvailableMarkers() +{ + m_fixItAvailableMarkers.clear(); + + QSet lineNumbersWithFixItMarker; + addFixItAvailableMarker(m_warningDiagnostics, lineNumbersWithFixItMarker); + addFixItAvailableMarker(m_errorDiagnostics, lineNumbersWithFixItMarker); +} + QList ClangDiagnosticManager::takeExtraSelections() { auto extraSelections = m_extraSelections; @@ -221,6 +270,15 @@ QList ClangDiagnosticManager::takeExtraSelections() return extraSelections; } +TextEditor::RefactorMarkers ClangDiagnosticManager::takeFixItAvailableMarkers() +{ + TextEditor::RefactorMarkers fixItAvailableMarkers = m_fixItAvailableMarkers; + + m_fixItAvailableMarkers.clear(); + + return fixItAvailableMarkers; +} + bool ClangDiagnosticManager::hasDiagnosticsAt(uint line, uint column) const { QTextDocument *textDocument = m_textDocument->document(); @@ -262,6 +320,7 @@ void ClangDiagnosticManager::processNewDiagnostics( generateTextMarks(); generateEditorSelections(); + generateFixItAvailableMarkers(); } const QVector & @@ -288,6 +347,24 @@ void ClangDiagnosticManager::addClangTextMarks( } } +void ClangDiagnosticManager::addFixItAvailableMarker( + const QVector &diagnostics, + QSet &lineNumbersWithFixItMarker) +{ + for (auto &&diagnostic : diagnostics) { + const int line = int(diagnostic.location().line()); + if (!diagnostic.fixIts().isEmpty() && !lineNumbersWithFixItMarker.contains(line)) { + const TextEditor::RefactorMarker marker + = createFixItAvailableMarker(m_textDocument->document(), line); + + lineNumbersWithFixItMarker.insert(line); + m_fixItAvailableMarkers.append(marker); + } + + addFixItAvailableMarker(diagnostic.children(), lineNumbersWithFixItMarker); + } +} + QString ClangDiagnosticManager::filePath() const { return m_textDocument->filePath().toString(); diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.h b/src/plugins/clangcodemodel/clangdiagnosticmanager.h index 5e7eb0561aa..dbfd72ec041 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.h +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.h @@ -28,9 +28,12 @@ #include "clangtextmark.h" +#include + #include #include +#include #include #include @@ -50,6 +53,7 @@ public: const QVector &diagnosticsWithFixIts() const; QList takeExtraSelections(); + TextEditor::RefactorMarkers takeFixItAvailableMarkers(); bool hasDiagnosticsAt(uint line, uint column) const; QVector diagnosticsAt(uint line, uint column) const; @@ -61,7 +65,10 @@ private: void filterDiagnostics(const QVector &diagnostics); void generateEditorSelections(); void generateTextMarks(); + void generateFixItAvailableMarkers(); void addClangTextMarks(const QVector &diagnostics); + void addFixItAvailableMarker(const QVector &diagnostics, + QSet &lineNumbersWithFixItMarker); private: TextEditor::TextDocument *m_textDocument; @@ -70,6 +77,7 @@ private: QVector m_errorDiagnostics; QVector m_fixItdiagnostics; QList m_extraSelections; + TextEditor::RefactorMarkers m_fixItAvailableMarkers; std::vector m_clangTextMarks; }; diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp index 59650d7ea0a..8cdd19d436a 100644 --- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp +++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp @@ -164,7 +164,8 @@ void ClangEditorDocumentProcessor::updateCodeWarnings(const QVector #include +#include #include #include #include @@ -271,11 +272,14 @@ void CppEditorWidget::onCppDocumentUpdated() } void CppEditorWidget::onCodeWarningsUpdated(unsigned revision, - const QList selections) + const QList selections, + const TextEditor::RefactorMarkers &refactorMarkers) { if (revision != documentRevision()) return; + setExtraSelections(TextEditorWidget::CodeWarningsSelection, selections); + setRefactorMarkers(refactorMarkersWithoutClangMarkers() + refactorMarkers); } void CppEditorWidget::onIfdefedOutBlocksUpdated(unsigned revision, @@ -428,6 +432,26 @@ unsigned CppEditorWidget::documentRevision() const return document()->revision(); } +static bool isClangFixItAvailableMarker(const RefactorMarker &marker) +{ + return marker.data.toString() + == QLatin1String(CppTools::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID); +} + +RefactorMarkers CppEditorWidget::refactorMarkersWithoutClangMarkers() const +{ + RefactorMarkers clearedRefactorMarkers; + + foreach (const RefactorMarker &marker, refactorMarkers()) { + if (isClangFixItAvailableMarker(marker)) + continue; + + clearedRefactorMarkers.append(marker); + } + + return clearedRefactorMarkers; +} + bool CppEditorWidget::isSemanticInfoValidExceptLocalUses() const { return d->m_lastSemanticInfo.doc @@ -631,8 +655,15 @@ QSharedPointer CppEditorWidget::declDefLink() const void CppEditorWidget::onRefactorMarkerClicked(const RefactorMarker &marker) { - if (marker.data.canConvert()) + if (marker.data.canConvert()) { applyDeclDefLinkChanges(true); + } else if (isClangFixItAvailableMarker(marker)) { + int line, column; + if (Convenience::convertPosition(document(), marker.cursor.position(), &line, &column)) { + setTextCursor(marker.cursor); + invokeAssist(TextEditor::QuickFix); + } + } } void CppEditorWidget::updateFunctionDeclDefLink() diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h index 01ec0a81074..62c50ccc10d 100644 --- a/src/plugins/cppeditor/cppeditor.h +++ b/src/plugins/cppeditor/cppeditor.h @@ -115,7 +115,8 @@ private slots: void onCppDocumentUpdated(); void onCodeWarningsUpdated(unsigned revision, - const QList selections); + const QList selections, + const TextEditor::RefactorMarkers &refactorMarkers); void onIfdefedOutBlocksUpdated(unsigned revision, const QList ifdefedOutBlocks); @@ -133,6 +134,8 @@ private: unsigned documentRevision() const; + TextEditor::RefactorMarkers refactorMarkersWithoutClangMarkers() const; + private: QScopedPointer d; }; diff --git a/src/plugins/cppeditor/cppeditordocument.h b/src/plugins/cppeditor/cppeditordocument.h index 0d4a192300e..c932aa13890 100644 --- a/src/plugins/cppeditor/cppeditordocument.h +++ b/src/plugins/cppeditor/cppeditordocument.h @@ -60,7 +60,8 @@ public: signals: void codeWarningsUpdated(unsigned contentsRevision, - const QList selections); + const QList selections, + const TextEditor::RefactorMarkers &refactorMarkers); void ifdefedOutBlocksUpdated(unsigned contentsRevision, const QList ifdefedOutBlocks); diff --git a/src/plugins/cpptools/baseeditordocumentprocessor.h b/src/plugins/cpptools/baseeditordocumentprocessor.h index 886e6bc98c2..5f8e9a73535 100644 --- a/src/plugins/cpptools/baseeditordocumentprocessor.h +++ b/src/plugins/cpptools/baseeditordocumentprocessor.h @@ -74,7 +74,8 @@ public: signals: // Signal interface to implement void codeWarningsUpdated(unsigned revision, - const QList selections); + const QList selections, + const TextEditor::RefactorMarkers &refactorMarkers); void ifdefedOutBlocksUpdated(unsigned revision, const QList ifdefedOutBlocks); diff --git a/src/plugins/cpptools/builtineditordocumentprocessor.cpp b/src/plugins/cpptools/builtineditordocumentprocessor.cpp index 272fd9f1287..b3a184139db 100644 --- a/src/plugins/cpptools/builtineditordocumentprocessor.cpp +++ b/src/plugins/cpptools/builtineditordocumentprocessor.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -307,7 +308,7 @@ void BuiltinEditorDocumentProcessor::onCodeWarningsUpdated( m_codeWarnings += toTextEditorSelections(codeWarnings, textDocument()); m_codeWarningsUpdated = true; - emit codeWarningsUpdated(revision(), m_codeWarnings); + emit codeWarningsUpdated(revision(), m_codeWarnings, TextEditor::RefactorMarkers()); } SemanticInfo::Source BuiltinEditorDocumentProcessor::createSemanticInfoSource(bool force) const diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h index 5fad1669357..37e8acb601a 100644 --- a/src/plugins/cpptools/cpptoolsconstants.h +++ b/src/plugins/cpptools/cpptoolsconstants.h @@ -61,6 +61,8 @@ const char CPP_SETTINGS_CATEGORY[] = "I.C++"; const char CPP_SETTINGS_TR_CATEGORY[] = QT_TRANSLATE_NOOP("CppTools", "C++"); const char SETTINGS_CATEGORY_CPP_ICON[] = ":/cpptools/images/category_cpp.png"; +const char CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID[] = "ClangFixItAvailableMarker"; + const char CPP_SETTINGS_ID[] = "Cpp"; const char CPP_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("CppTools", "C++");