ClangCodeModel: Prevent outdated fix-its from getting applied

The code locations might no longer be correct.

Fixes: QTCREATORBUG-21818
Change-Id: I866a29d2fd63ff65cf33168024f7788c5f6e3547
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2020-11-20 17:26:26 +01:00
parent 0d12c8cba8
commit bcf900e29b
6 changed files with 37 additions and 19 deletions

View File

@@ -455,7 +455,8 @@ void ClangDiagnosticManager::addClangTextMarks(
auto textMark = new ClangTextMark(::Utils::FilePath::fromString(filePath()), auto textMark = new ClangTextMark(::Utils::FilePath::fromString(filePath()),
diagnostic, diagnostic,
onMarkRemoved, onMarkRemoved,
m_fullVisualization); m_fullVisualization,
this);
m_clangTextMarks.push_back(textMark); m_clangTextMarks.push_back(textMark);
m_textDocument->addMark(textMark); m_textDocument->addMark(textMark);
} }

View File

@@ -58,6 +58,7 @@ public:
TextEditor::RefactorMarkers takeFixItAvailableMarkers(); TextEditor::RefactorMarkers takeFixItAvailableMarkers();
QList<TextEditor::TextMark *> diagnosticTextMarksAt(uint line, uint column) const; QList<TextEditor::TextMark *> diagnosticTextMarksAt(uint line, uint column) const;
bool diagnosticsInvalidated() const { return m_diagnosticsInvalidated; }
void invalidateDiagnostics(); void invalidateDiagnostics();
void clearDiagnosticsWithFixIts(); void clearDiagnosticsWithFixIts();

View File

@@ -24,6 +24,8 @@
****************************************************************************/ ****************************************************************************/
#include "clangdiagnostictooltipwidget.h" #include "clangdiagnostictooltipwidget.h"
#include "clangdiagnosticmanager.h"
#include "clangfixitoperation.h" #include "clangfixitoperation.h"
#include "clangutils.h" #include "clangutils.h"
@@ -101,7 +103,8 @@ public:
{ {
} }
QWidget *createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics) QWidget *createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const ClangDiagnosticManager *diagMgr)
{ {
const QString text = htmlText(diagnostics); const QString text = htmlText(diagnostics);
@@ -129,18 +132,22 @@ public:
const TargetIdToDiagnosticTable table = m_targetIdsToDiagnostics; const TargetIdToDiagnosticTable table = m_targetIdsToDiagnostics;
const bool hideToolTipAfterLinkActivation = m_displayHints.hideTooltipAfterLinkActivation; const bool hideToolTipAfterLinkActivation = m_displayHints.hideTooltipAfterLinkActivation;
QObject::connect(label, &QLabel::linkActivated, [table, hideToolTipAfterLinkActivation] QObject::connect(label, &QLabel::linkActivated, [table, hideToolTipAfterLinkActivation,
(const QString &action) { diagMgr](const QString &action) {
const ClangBackEnd::DiagnosticContainer diagnostic = table.value(action); const ClangBackEnd::DiagnosticContainer diagnostic = table.value(action);
if (diagnostic == ClangBackEnd::DiagnosticContainer()) if (diagnostic == ClangBackEnd::DiagnosticContainer())
QDesktopServices::openUrl(QUrl(action)); QDesktopServices::openUrl(QUrl(action));
else if (action.startsWith(LINK_ACTION_GOTO_LOCATION)) else if (action.startsWith(LINK_ACTION_GOTO_LOCATION)) {
openEditorAt(diagnostic); openEditorAt(diagnostic);
else if (action.startsWith(LINK_ACTION_APPLY_FIX)) } else if (action.startsWith(LINK_ACTION_APPLY_FIX)) {
applyFixit(diagnostic); if (diagMgr && !diagMgr->diagnosticsInvalidated()
else && diagMgr->diagnosticsWithFixIts().contains(diagnostic)) {
applyFixit(diagnostic);
}
} else {
QTC_CHECK(!"Link target cannot be handled."); QTC_CHECK(!"Link target cannot be handled.");
}
if (hideToolTipAfterLinkActivation) if (hideToolTipAfterLinkActivation)
::Utils::ToolTip::hideImmediately(); ::Utils::ToolTip::hideImmediately();
@@ -394,14 +401,15 @@ private:
QString m_mainFilePath; QString m_mainFilePath;
}; };
WidgetFromDiagnostics::DisplayHints toHints(const ClangDiagnosticWidget::Destination &destination) WidgetFromDiagnostics::DisplayHints toHints(const ClangDiagnosticWidget::Destination &destination,
const ClangDiagnosticManager *diagMgr = nullptr)
{ {
WidgetFromDiagnostics::DisplayHints hints; WidgetFromDiagnostics::DisplayHints hints;
if (destination == ClangDiagnosticWidget::ToolTip) { if (destination == ClangDiagnosticWidget::ToolTip) {
hints.showCategoryAndEnableOption = true; hints.showCategoryAndEnableOption = true;
hints.showFileNameInMainDiagnostic = false; hints.showFileNameInMainDiagnostic = false;
hints.enableClickableFixits = true; hints.enableClickableFixits = diagMgr && !diagMgr->diagnosticsInvalidated();
hints.limitWidth = true; hints.limitWidth = true;
hints.hideTooltipAfterLinkActivation = true; hints.hideTooltipAfterLinkActivation = true;
hints.allowTextSelection = false; hints.allowTextSelection = false;
@@ -438,10 +446,10 @@ QString ClangDiagnosticWidget::createText(
return text; return text;
} }
QWidget *ClangDiagnosticWidget::createWidget( QWidget *ClangDiagnosticWidget::createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, const Destination &destination) const Destination &destination, const ClangDiagnosticManager *diagMgr)
{ {
return WidgetFromDiagnostics(toHints(destination)).createWidget(diagnostics); return WidgetFromDiagnostics(toHints(destination, diagMgr)).createWidget(diagnostics, diagMgr);
} }
} // namespace Internal } // namespace Internal

View File

@@ -34,6 +34,7 @@ QT_END_NAMESPACE
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
class ClangDiagnosticManager;
class ClangDiagnosticWidget { class ClangDiagnosticWidget {
public: public:
@@ -41,8 +42,10 @@ public:
static QString createText(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, static QString createText(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const Destination &destination); const Destination &destination);
static QWidget *createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics, static QWidget *createWidget(const QVector<ClangBackEnd::DiagnosticContainer> &diagnostics,
const Destination &destination); const Destination &destination,
const ClangDiagnosticManager *diagMgr = nullptr);
}; };
} // namespace Internal } // namespace Internal

View File

@@ -210,12 +210,13 @@ void disableDiagnosticInCurrentProjectConfig(const ClangBackEnd::DiagnosticConta
ClangTextMark::ClangTextMark(const FilePath &fileName, ClangTextMark::ClangTextMark(const FilePath &fileName,
const ClangBackEnd::DiagnosticContainer &diagnostic, const ClangBackEnd::DiagnosticContainer &diagnostic,
const RemovedFromEditorHandler &removedHandler, const RemovedFromEditorHandler &removedHandler,
bool fullVisualization) bool fullVisualization, const ClangDiagnosticManager *diagMgr)
: TextEditor::TextMark(fileName, : TextEditor::TextMark(fileName,
int(diagnostic.location.line), int(diagnostic.location.line),
categoryForSeverity(diagnostic.severity)) categoryForSeverity(diagnostic.severity))
, m_diagnostic(diagnostic) , m_diagnostic(diagnostic)
, m_removedFromEditorHandler(removedHandler) , m_removedFromEditorHandler(removedHandler)
, m_diagMgr(diagMgr)
{ {
const bool warning = isWarningOrNote(diagnostic.severity); const bool warning = isWarningOrNote(diagnostic.severity);
setDefaultToolTip(warning ? QApplication::translate("Clang Code Model Marks", "Code Model Warning") setDefaultToolTip(warning ? QApplication::translate("Clang Code Model Marks", "Code Model Warning")
@@ -265,8 +266,10 @@ void ClangTextMark::updateIcon(bool valid)
bool ClangTextMark::addToolTipContent(QLayout *target) const bool ClangTextMark::addToolTipContent(QLayout *target) const
{ {
QWidget *widget = ClangDiagnosticWidget::createWidget({m_diagnostic},
ClangDiagnosticWidget::ToolTip); QWidget *widget = ClangDiagnosticWidget::createWidget(
{m_diagnostic}, ClangDiagnosticWidget::ToolTip,
color() == Utils::Theme::Color::IconsDisabledColor ? nullptr : m_diagMgr);
target->addWidget(widget); target->addWidget(widget);
return true; return true;
@@ -280,4 +283,3 @@ void ClangTextMark::removedFromEditor()
} // namespace Internal } // namespace Internal
} // namespace ClangCodeModel } // namespace ClangCodeModel

View File

@@ -34,6 +34,7 @@
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
class ClangDiagnosticManager;
class ClangTextMark : public TextEditor::TextMark class ClangTextMark : public TextEditor::TextMark
{ {
@@ -43,7 +44,8 @@ public:
ClangTextMark(const ::Utils::FilePath &fileName, ClangTextMark(const ::Utils::FilePath &fileName,
const ClangBackEnd::DiagnosticContainer &diagnostic, const ClangBackEnd::DiagnosticContainer &diagnostic,
const RemovedFromEditorHandler &removedHandler, const RemovedFromEditorHandler &removedHandler,
bool fullVisualization); bool fullVisualization,
const ClangDiagnosticManager *diagMgr);
ClangBackEnd::DiagnosticContainer diagnostic() const { return m_diagnostic; } ClangBackEnd::DiagnosticContainer diagnostic() const { return m_diagnostic; }
void updateIcon(bool valid = true); void updateIcon(bool valid = true);
@@ -55,6 +57,7 @@ private:
private: private:
ClangBackEnd::DiagnosticContainer m_diagnostic; ClangBackEnd::DiagnosticContainer m_diagnostic;
RemovedFromEditorHandler m_removedFromEditorHandler; RemovedFromEditorHandler m_removedFromEditorHandler;
const ClangDiagnosticManager * const m_diagMgr;
}; };
} // namespace Internal } // namespace Internal