summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2019-02-15 13:42:44 +0200
committerOrgad Shaneh <orgad.shaneh@audiocodes.com>2019-02-15 13:42:44 +0200
commit6fc532f812f62b7206ec5e958d251f7389cd6ecf (patch)
tree285bab3ac533c84a77dc173b195e8af4d8435869 /src/plugins
parent72d962e949564fc963f91e1b48350a091aea1bb2 (diff)
parent603191ba77852b64e5438c339bc39fcdc608cfb8 (diff)
downloadqt-creator-6fc532f812f62b7206ec5e958d251f7389cd6ecf.tar.gz
Merge remote-tracking branch 'origin/4.9'
Change-Id: If4e8f52fc94c4e5fd9ec69c9000436d4ded913ff
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/clangcodemodel/clanghoverhandler.cpp77
-rw-r--r--src/plugins/clangformat/clangformatbaseindenter.cpp96
-rw-r--r--src/plugins/clangformat/clangformatbaseindenter.h8
-rw-r--r--src/plugins/clangtools/clangselectablefilesdialog.ui4
-rw-r--r--src/plugins/clangtools/clangtidyclazytool.cpp14
-rw-r--r--src/plugins/clangtools/clangtool.cpp6
-rw-r--r--src/plugins/clangtools/clangtoolruncontrol.cpp4
-rw-r--r--src/plugins/clangtools/clangtoolsbasicsettings.cpp2
-rw-r--r--src/plugins/clangtools/clangtoolsbasicsettings.h2
-rw-r--r--src/plugins/clangtools/clangtoolsbasicsettings.ui4
-rw-r--r--src/plugins/clangtools/clangtoolsconfigwidget.ui4
-rw-r--r--src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp109
-rw-r--r--src/plugins/clangtools/clangtoolsdiagnosticmodel.h6
-rw-r--r--src/plugins/clangtools/clangtoolsdiagnosticview.cpp156
-rw-r--r--src/plugins/clangtools/clangtoolsdiagnosticview.h12
-rw-r--r--src/plugins/clangtools/clangtoolslogfilereader.cpp2
-rw-r--r--src/plugins/coreplugin/helpitem.cpp9
-rw-r--r--src/plugins/coreplugin/helpitem.h2
-rw-r--r--src/plugins/coreplugin/images/logo/128/QtProject-qtcreator.pngbin3799 -> 5303 bytes
-rw-r--r--src/plugins/coreplugin/images/logo/16/QtProject-qtcreator.pngbin487 -> 515 bytes
-rw-r--r--src/plugins/coreplugin/images/logo/24/QtProject-qtcreator.pngbin650 -> 557 bytes
-rw-r--r--src/plugins/coreplugin/images/logo/256/QtProject-qtcreator.pngbin8195 -> 10500 bytes
-rw-r--r--src/plugins/coreplugin/images/logo/32/QtProject-qtcreator.pngbin976 -> 790 bytes
-rw-r--r--src/plugins/coreplugin/images/logo/48/QtProject-qtcreator.pngbin1386 -> 1985 bytes
-rw-r--r--src/plugins/coreplugin/images/logo/512/QtProject-qtcreator.pngbin18951 -> 25277 bytes
-rw-r--r--src/plugins/coreplugin/images/logo/64/QtProject-qtcreator.pngbin1873 -> 2571 bytes
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.cpp8
-rw-r--r--src/plugins/cpptools/cpphoverhandler.cpp9
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.cpp87
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.h1
-rw-r--r--src/plugins/languageclient/client.cpp77
-rw-r--r--src/plugins/languageclient/client.h11
-rw-r--r--src/plugins/languageclient/languageclient.pro6
-rw-r--r--src/plugins/languageclient/languageclient.qbs6
-rw-r--r--src/plugins/languageclient/languageclientcompletionassist.cpp (renamed from src/plugins/languageclient/languageclientcodeassist.cpp)2
-rw-r--r--src/plugins/languageclient/languageclientcompletionassist.h (renamed from src/plugins/languageclient/languageclientcodeassist.h)2
-rw-r--r--src/plugins/languageclient/languageclientquickfix.cpp166
-rw-r--r--src/plugins/languageclient/languageclientquickfix.h45
-rw-r--r--src/plugins/languageclient/languageclientsettings.cpp46
-rw-r--r--src/plugins/languageclient/languageclientutils.cpp18
-rw-r--r--src/plugins/languageclient/languageclientutils.h1
-rw-r--r--src/plugins/perfprofiler/perfdatareader.cpp10
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.cpp43
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.pro2
-rw-r--r--src/plugins/qbsprojectmanager/qbsprojectmanager.qbs6
-rw-r--r--src/plugins/qmljseditor/qmljsfindreferences.cpp10
-rw-r--r--src/plugins/remotelinux/linuxdeviceprocess.cpp5
-rw-r--r--src/plugins/texteditor/textdocument.cpp13
-rw-r--r--src/plugins/texteditor/textdocument.h2
-rw-r--r--src/plugins/texteditor/textmark.cpp7
-rw-r--r--src/plugins/welcome/introductionwidget.cpp14
51 files changed, 737 insertions, 377 deletions
diff --git a/src/plugins/clangcodemodel/clanghoverhandler.cpp b/src/plugins/clangcodemodel/clanghoverhandler.cpp
index 58f414d9f1..c8e87c2577 100644
--- a/src/plugins/clangcodemodel/clanghoverhandler.cpp
+++ b/src/plugins/clangcodemodel/clanghoverhandler.cpp
@@ -93,79 +93,6 @@ ClangHoverHandler::~ClangHoverHandler()
abort();
}
-static int skipChars(QTextCursor *tc,
- QTextCursor::MoveOperation op,
- int offset,
- std::function<bool(const QChar &)> skip)
-{
- const QTextDocument *doc = tc->document();
- QChar ch = doc->characterAt(tc->position() + offset);
- if (ch.isNull())
- return 0;
- int count = 0;
- while (skip(ch)) {
- if (tc->movePosition(op))
- ++count;
- else
- break;
- ch = doc->characterAt(tc->position() + offset);
- }
- return count;
-}
-
-static int skipCharsForward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
-{
- return skipChars(tc, QTextCursor::NextCharacter, 0, skip);
-}
-
-static int skipCharsBackward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
-{
- return skipChars(tc, QTextCursor::PreviousCharacter, -1, skip);
-}
-
-static QStringList fallbackWords(QTextDocument *document, int pos)
-{
- const auto isSpace = [](const QChar &c) { return c.isSpace(); };
- const auto isColon = [](const QChar &c) { return c == ':'; };
- const auto isValidIdentifierChar = [document](const QTextCursor &tc) {
- return CppTools::isValidIdentifierChar(document->characterAt(tc.position()));
- };
- // move to the end
- QTextCursor endCursor(document);
- endCursor.setPosition(pos);
- do {
- CppTools::moveCursorToEndOfIdentifier(&endCursor);
- // possibly skip ::
- QTextCursor temp(endCursor);
- skipCharsForward(&temp, isSpace);
- const int colons = skipCharsForward(&temp, isColon);
- skipCharsForward(&temp, isSpace);
- if (colons == 2 && isValidIdentifierChar(temp))
- endCursor = temp;
- } while (isValidIdentifierChar(endCursor));
-
- QStringList results;
- QTextCursor startCursor(endCursor);
- do {
- CppTools::moveCursorToStartOfIdentifier(&startCursor);
- if (startCursor.position() == endCursor.position())
- break;
- QTextCursor temp(endCursor);
- temp.setPosition(startCursor.position(), QTextCursor::KeepAnchor);
- results.append(temp.selectedText().remove(QRegularExpression("\\s")));
- // possibly skip ::
- temp = startCursor;
- skipCharsBackward(&temp, isSpace);
- const int colons = skipCharsBackward(&temp, isColon);
- skipCharsBackward(&temp, isSpace);
- if (colons == 2
- && CppTools::isValidIdentifierChar(document->characterAt(temp.position() - 1))) {
- startCursor = temp;
- }
- } while (!isValidIdentifierChar(startCursor));
- return results;
-}
-
void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
int pos,
BaseHoverHandler::ReportPriority report)
@@ -187,7 +114,9 @@ void ClangHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
qCDebug(hoverLog) << "Requesting tooltip info at" << pos;
m_reportPriority = report;
m_futureWatcher.reset(new QFutureWatcher<CppTools::ToolTipInfo>());
- const QStringList fallback = fallbackWords(editorWidget->document(), pos);
+ QTextCursor tc(editorWidget->document());
+ tc.setPosition(pos);
+ const QStringList fallback = CppTools::identifierWordsUnderCursor(tc);
QObject::connect(m_futureWatcher.data(),
&QFutureWatcherBase::finished,
[this, fallback]() {
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp
index e8c6b5e902..1b316bea55 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.cpp
+++ b/src/plugins/clangformat/clangformatbaseindenter.cpp
@@ -36,16 +36,27 @@
namespace ClangFormat {
-static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style)
+static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
+ ReplacementsToKeep replacementsToKeep)
{
+ if (replacementsToKeep == ReplacementsToKeep::All)
+ return;
+
+ style.MaxEmptyLinesToKeep = 2;
+ style.SortIncludes = false;
+ style.SortUsingDeclarations = false;
+
+ // This is a separate pass, don't do it unless it's the full formatting.
+ style.FixNamespaceComments = false;
+
+ if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
+ return;
+
style.DisableFormat = false;
style.ColumnLimit = 0;
#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
style.KeepLineBreaksForNonEmptyLines = true;
#endif
- style.MaxEmptyLinesToKeep = 2;
- style.SortIncludes = false;
- style.SortUsingDeclarations = false;
}
static llvm::StringRef clearExtraNewline(llvm::StringRef text)
@@ -59,7 +70,6 @@ static clang::tooling::Replacements filteredReplacements(
const clang::tooling::Replacements &replacements,
int offset,
int utf8LineLengthBeforeCursor,
- int extraOffsetFromStartOfFile,
int extraEmptySpaceOffset,
ReplacementsToKeep replacementsToKeep)
{
@@ -69,14 +79,13 @@ static clang::tooling::Replacements filteredReplacements(
const bool replacementDoesNotMatchRestriction
= (replacementsToKeep == ReplacementsToKeep::OnlyIndent
&& replacementOffset != offset - 1)
- || (replacementsToKeep == ReplacementsToKeep::OnlyBeforeIndent
- && replacementOffset >= offset + utf8LineLengthBeforeCursor - 1);
+ || (replacementsToKeep == ReplacementsToKeep::IndentAndBefore
+ && replacementOffset > offset + utf8LineLengthBeforeCursor - 1);
if (replacementDoesNotMatchRestriction)
continue;
if (replacementOffset >= offset - 1)
replacementOffset += extraEmptySpaceOffset;
- replacementOffset += extraOffsetFromStartOfFile;
llvm::StringRef text = replacementsToKeep == ReplacementsToKeep::OnlyIndent
? clearExtraNewline(replacement.getReplacementText())
@@ -128,18 +137,6 @@ static void trimFirstNonEmptyBlock(const QTextBlock &currentBlock)
cursor.endEditBlock();
}
-static void trimCurrentBlock(const QTextBlock &currentBlock)
-{
- if (currentBlock.text().trimmed().isEmpty()) {
- // Clear the block containing only spaces
- QTextCursor cursor(currentBlock);
- cursor.beginEditBlock();
- cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
- cursor.removeSelectedText();
- cursor.endEditBlock();
- }
-}
-
// Returns the total langth of previous lines with pure whitespace.
static int previousEmptyLinesLength(const QTextBlock &currentBlock)
{
@@ -167,7 +164,7 @@ static void modifyToIndentEmptyLines(
if (firstNonWhitespace < 0 || closingParenBlock) {
//This extra text works for the most cases.
- QByteArray dummyText("a;");
+ QByteArray dummyText("a;a;");
// Search for previous character
QTextBlock prevBlock = block.previous();
@@ -198,8 +195,6 @@ static void modifyToIndentEmptyLines(
}
}
-static const int kMaxLinesFromCurrentBlock = 200;
-
static Utils::LineColumn utf16LineColumn(const QTextBlock &block,
int blockOffsetUtf8,
const QByteArray &utf8Buffer,
@@ -388,24 +383,21 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(
return format(cursor, cursorPositionInEditor);
}
-int ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
- const QChar &typedChar,
- int cursorPositionInEditor)
+void ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
+ const QChar &typedChar,
+ int cursorPositionInEditor)
{
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
- QTC_ASSERT(utf8Offset >= 0, return cursorPositionInEditor;);
+ QTC_ASSERT(utf8Offset >= 0, return;);
const TextEditor::Replacements toReplace = replacements(buffer,
utf8Offset,
0,
block,
cursorPositionInEditor,
- ReplacementsToKeep::OnlyBeforeIndent,
+ ReplacementsToKeep::IndentAndBefore,
typedChar);
applyReplacements(block, toReplace);
- for (const TextEditor::Replacement &replacement : toReplace)
- cursorPositionInEditor += replacement.text.length() - replacement.length;
- return cursorPositionInEditor;
}
static bool doNotIndentInContext(QTextDocument *doc, int pos)
@@ -466,11 +458,10 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
else
cursorPositionInEditor = currentBlock.position();
- cursorPositionInEditor = indentBeforeCursor(currentBlock, typedChar, cursorPositionInEditor);
- currentBlock = m_doc->findBlock(cursorPositionInEditor);
+ indentBeforeCursor(currentBlock, typedChar, cursorPositionInEditor);
+ return;
}
- trimCurrentBlock(currentBlock);
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return;);
@@ -496,7 +487,6 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositionInEditor)
{
trimFirstNonEmptyBlock(block);
- trimCurrentBlock(block);
const QByteArray buffer = m_doc->toPlainText().toUtf8();
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
QTC_ASSERT(utf8Offset >= 0, return 0;);
@@ -571,8 +561,7 @@ static int formattingRangeStart(const QTextBlock &currentBlock,
{
QTextBlock prevBlock = currentBlock.previous();
while ((prevBlock.position() > 0 || prevBlock.length() > 0)
- && prevBlock.revision() != documentRevision
- && (currentBlock.blockNumber() - prevBlock.blockNumber() < kMaxLinesFromCurrentBlock)) {
+ && prevBlock.revision() != documentRevision) {
// Find the first block with not matching revision.
prevBlock = prevBlock.previous();
}
@@ -604,41 +593,27 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
= block.text().left(cursorPositionInEditor - block.position()).toUtf8().size();
}
- int extraOffsetFromStartOfFile = 0;
int extraEmptySpaceOffset = 0;
int rangeStart = 0;
if (replacementsToKeep != ReplacementsToKeep::All) {
- if (block.blockNumber() > kMaxLinesFromCurrentBlock) {
- extraOffsetFromStartOfFile
- = Utils::Text::utf8NthLineOffset(block.document(),
- buffer,
- block.blockNumber() - kMaxLinesFromCurrentBlock);
- }
- int endOffset = Utils::Text::utf8NthLineOffset(block.document(),
- buffer,
- block.blockNumber()
- + kMaxLinesFromCurrentBlock);
- if (endOffset == -1)
- endOffset = buffer.size();
-
-
- if (replacementsToKeep == ReplacementsToKeep::OnlyBeforeIndent)
+ if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
rangeStart = formattingRangeStart(block, buffer, lastSaveRevision());
- buffer = buffer.mid(extraOffsetFromStartOfFile, endOffset - extraOffsetFromStartOfFile);
- utf8Offset -= extraOffsetFromStartOfFile;
- rangeStart -= extraOffsetFromStartOfFile;
-
extraEmptySpaceOffset = previousEmptyLinesLength(block);
utf8Offset -= extraEmptySpaceOffset;
buffer.remove(utf8Offset, extraEmptySpaceOffset);
- if (replacementsToKeep == ReplacementsToKeep::OnlyIndent)
- adjustFormatStyleForLineBreak(style);
+ adjustFormatStyleForLineBreak(style, replacementsToKeep);
modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
+
+ if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) {
+ buffer.insert(utf8Offset - 1, " //");
+ extraEmptySpaceOffset -= 3;
+ utf8Offset += 3;
+ }
}
- if (replacementsToKeep != ReplacementsToKeep::OnlyBeforeIndent || utf8Offset < rangeStart)
+ if (replacementsToKeep != ReplacementsToKeep::IndentAndBefore || utf8Offset < rangeStart)
rangeStart = utf8Offset;
unsigned int rangeLength = static_cast<unsigned int>(utf8Offset + utf8Length - rangeStart);
@@ -658,7 +633,6 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
filtered = filteredReplacements(clangReplacements,
utf8Offset,
utf8LineLengthBeforeCursor,
- extraOffsetFromStartOfFile,
extraEmptySpaceOffset,
replacementsToKeep);
}
diff --git a/src/plugins/clangformat/clangformatbaseindenter.h b/src/plugins/clangformat/clangformatbaseindenter.h
index 1a73d9bfbc..2017f8ba64 100644
--- a/src/plugins/clangformat/clangformatbaseindenter.h
+++ b/src/plugins/clangformat/clangformatbaseindenter.h
@@ -31,7 +31,7 @@
namespace ClangFormat {
-enum class ReplacementsToKeep { OnlyIndent, OnlyBeforeIndent, All };
+enum class ReplacementsToKeep { OnlyIndent, IndentAndBefore, All };
class ClangFormatBaseIndenter : public TextEditor::Indenter
{
@@ -79,9 +79,9 @@ private:
void indent(const QTextCursor &cursor, const QChar &typedChar, int cursorPositionInEditor);
void indentBlock(const QTextBlock &block, const QChar &typedChar, int cursorPositionInEditor);
int indentFor(const QTextBlock &block, int cursorPositionInEditor);
- int indentBeforeCursor(const QTextBlock &block,
- const QChar &typedChar,
- int cursorPositionInEditor);
+ void indentBeforeCursor(const QTextBlock &block,
+ const QChar &typedChar,
+ int cursorPositionInEditor);
TextEditor::Replacements replacements(QByteArray buffer,
int utf8Offset,
int utf8Length,
diff --git a/src/plugins/clangtools/clangselectablefilesdialog.ui b/src/plugins/clangtools/clangselectablefilesdialog.ui
index 316b9946fb..2fe10139a3 100644
--- a/src/plugins/clangtools/clangselectablefilesdialog.ui
+++ b/src/plugins/clangtools/clangselectablefilesdialog.ui
@@ -52,7 +52,7 @@
</layout>
</item>
<item>
- <widget class="ClangTools::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
+ <widget class="ClangTools::Internal::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
</item>
</layout>
</widget>
@@ -87,7 +87,7 @@
</widget>
<customwidgets>
<customwidget>
- <class>ClangTools::ClangToolsBasicSettings</class>
+ <class>ClangTools::Internal::ClangToolsBasicSettings</class>
<extends>QWidget</extends>
<header>clangtools/clangtoolsbasicsettings.h</header>
</customwidget>
diff --git a/src/plugins/clangtools/clangtidyclazytool.cpp b/src/plugins/clangtools/clangtidyclazytool.cpp
index 9056b64367..0583a3aa0f 100644
--- a/src/plugins/clangtools/clangtidyclazytool.cpp
+++ b/src/plugins/clangtools/clangtidyclazytool.cpp
@@ -219,7 +219,7 @@ ClangTidyClazyTool::ClangTidyClazyTool()
m_diagnosticView->sortByColumn(Debugger::DetailedErrorView::DiagnosticColumn,
Qt::AscendingOrder);
m_diagnosticView->setObjectName(QLatin1String("ClangTidyClazyIssuesView"));
- m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Issues"));
+ m_diagnosticView->setWindowTitle(tr("Clang-Tidy and Clazy Diagnostics"));
foreach (auto * const model,
QList<QAbstractItemModel *>({m_diagnosticModel, m_diagnosticFilterModel})) {
@@ -281,7 +281,7 @@ ClangTidyClazyTool::ClangTidyClazyTool()
// Filter line edit
m_filterLineEdit = new Utils::FancyLineEdit();
m_filterLineEdit->setFiltering(true);
- m_filterLineEdit->setPlaceholderText(tr("Filter Issues"));
+ m_filterLineEdit->setPlaceholderText(tr("Filter Diagnostics"));
m_filterLineEdit->setHistoryCompleter("CppTools.ClangTidyClazyIssueFilter", true);
connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, [this](const QString &filter) {
m_diagnosticFilterModel->setFilterRegExp(
@@ -309,7 +309,7 @@ ClangTidyClazyTool::ClangTidyClazyTool()
ActionContainer *menu = ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
const QString toolTip = tr("Clang-Tidy and Clazy use a customized Clang executable from the "
- "Clang project to search for errors and warnings.");
+ "Clang project to search for diagnostics.");
m_perspective.addWindow(m_diagnosticView, Perspective::SplitVertical, nullptr);
@@ -450,14 +450,14 @@ void ClangTidyClazyTool::handleStateUpdate()
QString message;
if (m_running) {
if (issuesFound)
- message = tr("Running - %n issues found", nullptr, issuesFound);
+ message = tr("Running - %n diagnostics", nullptr, issuesFound);
else
- message = tr("Running - No issues found", nullptr, issuesFound);
+ message = tr("Running - No diagnostics", nullptr, issuesFound);
} else {
if (issuesFound)
- message = tr("Finished - %n issues found", nullptr, issuesFound);
+ message = tr("Finished - %n diagnostics", nullptr, issuesFound);
else
- message = tr("Finished - No issues found", nullptr, issuesFound);
+ message = tr("Finished - No diagnostics", nullptr, issuesFound);
}
Debugger::showPermanentStatusMessage(message);
diff --git a/src/plugins/clangtools/clangtool.cpp b/src/plugins/clangtools/clangtool.cpp
index b02868cb5d..52746080c1 100644
--- a/src/plugins/clangtools/clangtool.cpp
+++ b/src/plugins/clangtools/clangtool.cpp
@@ -46,6 +46,7 @@
#include <projectexplorer/target.h>
#include <projectexplorer/session.h>
+#include <utils/algorithm.h>
#include <utils/fancymainwindow.h>
#include <utils/utilsicons.h>
@@ -137,7 +138,10 @@ void ClangTool::initDiagnosticView()
QSet<Diagnostic> ClangTool::diagnostics() const
{
- return m_diagnosticModel->diagnostics();
+ return Utils::filtered(m_diagnosticModel->diagnostics(), [](const Diagnostic &diagnostic) {
+ using CppTools::ProjectFile;
+ return ProjectFile::isSource(ProjectFile::classify(diagnostic.location.filePath));
+ });
}
void ClangTool::onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics)
diff --git a/src/plugins/clangtools/clangtoolruncontrol.cpp b/src/plugins/clangtools/clangtoolruncontrol.cpp
index c92a446484..2f994c3a8f 100644
--- a/src/plugins/clangtools/clangtoolruncontrol.cpp
+++ b/src/plugins/clangtools/clangtoolruncontrol.cpp
@@ -267,6 +267,8 @@ void ClangToolRunControl::init()
void ClangToolRunControl::start()
{
+ TaskHub::clearTasks(Debugger::Constants::ANALYZERTASK_ID);
+
if (ClangToolsSettings::instance()->savedBuildBeforeAnalysis()) {
QTC_ASSERT(m_projectBuilder, return;);
if (!m_projectBuilder->success()) {
@@ -441,7 +443,7 @@ void ClangToolRunControl::onRunnerFinishedWithFailure(const QString &errorMessag
m_success = false;
appendMessage(message, Utils::StdErrFormat);
appendMessage(errorDetails, Utils::StdErrFormat);
- TaskHub::addTask(Task::Warning, message, Debugger::Constants::ANALYZERTASK_ID);
+ TaskHub::addTask(Task::Error, message, Debugger::Constants::ANALYZERTASK_ID);
handleFinished();
}
diff --git a/src/plugins/clangtools/clangtoolsbasicsettings.cpp b/src/plugins/clangtools/clangtoolsbasicsettings.cpp
index 7fe56e9193..bf1d533700 100644
--- a/src/plugins/clangtools/clangtoolsbasicsettings.cpp
+++ b/src/plugins/clangtools/clangtoolsbasicsettings.cpp
@@ -29,6 +29,7 @@
#include "clangtoolsutils.h"
namespace ClangTools {
+namespace Internal {
ClangToolsBasicSettings::ClangToolsBasicSettings(QWidget *parent)
: QWidget(parent)
@@ -47,4 +48,5 @@ Ui::ClangToolsBasicSettings *ClangToolsBasicSettings::ui()
return m_ui;
}
+} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/clangtools/clangtoolsbasicsettings.h b/src/plugins/clangtools/clangtoolsbasicsettings.h
index fb896e830d..b9ecb0285e 100644
--- a/src/plugins/clangtools/clangtoolsbasicsettings.h
+++ b/src/plugins/clangtools/clangtoolsbasicsettings.h
@@ -28,6 +28,7 @@
#include <QWidget>
namespace ClangTools {
+namespace Internal {
namespace Ui { class ClangToolsBasicSettings; }
@@ -46,4 +47,5 @@ private:
Ui::ClangToolsBasicSettings *m_ui;
};
+} // namespace Internal
} // namespace ClangTools
diff --git a/src/plugins/clangtools/clangtoolsbasicsettings.ui b/src/plugins/clangtools/clangtoolsbasicsettings.ui
index 4b6f14111e..ccdba126bd 100644
--- a/src/plugins/clangtools/clangtoolsbasicsettings.ui
+++ b/src/plugins/clangtools/clangtoolsbasicsettings.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>ClangTools::ClangToolsBasicSettings</class>
- <widget class="QWidget" name="ClangTools::ClangToolsBasicSettings">
+ <class>ClangTools::Internal::ClangToolsBasicSettings</class>
+ <widget class="QWidget" name="ClangTools::Internal::ClangToolsBasicSettings">
<property name="geometry">
<rect>
<x>0</x>
diff --git a/src/plugins/clangtools/clangtoolsconfigwidget.ui b/src/plugins/clangtools/clangtoolsconfigwidget.ui
index ea8dafb92b..b2d5aa9875 100644
--- a/src/plugins/clangtools/clangtoolsconfigwidget.ui
+++ b/src/plugins/clangtools/clangtoolsconfigwidget.ui
@@ -21,7 +21,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <widget class="ClangTools::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
+ <widget class="ClangTools::Internal::ClangToolsBasicSettings" name="clangToolsBasicSettings" native="true"/>
</item>
<item>
<layout class="QHBoxLayout" name="processesLayout">
@@ -77,7 +77,7 @@
</widget>
<customwidgets>
<customwidget>
- <class>ClangTools::ClangToolsBasicSettings</class>
+ <class>ClangTools::Internal::ClangToolsBasicSettings</class>
<extends>QWidget</extends>
<header>clangtools/clangtoolsbasicsettings.h</header>
</customwidget>
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
index 6e16cc6eec..4225970221 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
+++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp
@@ -84,7 +84,7 @@ ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
: Utils::TreeModel<>(parent)
, m_filesWatcher(std::make_unique<QFileSystemWatcher>())
{
- setHeader({tr("Issue"), tr("Fixit Status")});
+ setHeader({tr("Diagnostic")});
connectFileWatcher();
}
@@ -192,7 +192,26 @@ void ClangToolsDiagnosticModel::addWatchedPath(const QString &path)
m_filesWatcher->addPath(path);
}
-static QString createDiagnosticToolTipString(const Diagnostic &diagnostic)
+static QString fixitStatus(FixitStatus status)
+{
+ switch (status) {
+ case FixitStatus::NotAvailable:
+ return ClangToolsDiagnosticModel::tr("No Fixits");
+ case FixitStatus::NotScheduled:
+ return ClangToolsDiagnosticModel::tr("Not Scheduled");
+ case FixitStatus::Invalidated:
+ return ClangToolsDiagnosticModel::tr("Invalidated");
+ case FixitStatus::Scheduled:
+ return ClangToolsDiagnosticModel::tr("Scheduled");
+ case FixitStatus::FailedToApply:
+ return ClangToolsDiagnosticModel::tr("Failed to Apply");
+ case FixitStatus::Applied:
+ return ClangToolsDiagnosticModel::tr("Applied");
+ }
+ return QString();
+}
+
+static QString createDiagnosticToolTipString(const Diagnostic &diagnostic, FixitStatus fixItStatus)
{
using StringPair = QPair<QString, QString>;
QList<StringPair> lines;
@@ -226,6 +245,10 @@ static QString createDiagnosticToolTipString(const Diagnostic &diagnostic)
QCoreApplication::translate("ClangTools::Diagnostic", "Location:"),
createFullLocationString(diagnostic.location));
+ lines << qMakePair(
+ QCoreApplication::translate("ClangTools::Diagnostic", "Fixit Status:"),
+ fixitStatus(fixItStatus));
+
QString html = QLatin1String("<html>"
"<head>"
"<style>dt { font-weight:bold; } dd { font-family: monospace; }</style>\n"
@@ -364,19 +387,8 @@ DiagnosticItem::~DiagnosticItem()
Qt::ItemFlags DiagnosticItem::flags(int column) const
{
const Qt::ItemFlags itemFlags = TreeItem::flags(column);
- if (column == DiagnosticView::FixItColumn) {
- switch (m_fixitStatus) {
- case FixitStatus::NotAvailable:
- case FixitStatus::Applied:
- case FixitStatus::FailedToApply:
- case FixitStatus::Invalidated:
- return itemFlags & ~Qt::ItemIsEnabled;
- case FixitStatus::Scheduled:
- case FixitStatus::NotScheduled:
- return itemFlags | Qt::ItemIsUserCheckable;
- }
- }
-
+ if (column == DiagnosticView::DiagnosticColumn)
+ return itemFlags | Qt::ItemIsUserCheckable;
return itemFlags;
}
@@ -395,49 +407,46 @@ static QVariant iconData(const QString &type)
QVariant DiagnosticItem::data(int column, int role) const
{
- if (column == DiagnosticView::FixItColumn) {
- if (role == Qt::CheckStateRole) {
+ if (column == DiagnosticView::DiagnosticColumn) {
+ switch (role) {
+ case Debugger::DetailedErrorView::LocationRole:
+ return QVariant::fromValue(m_diagnostic.location);
+ case Debugger::DetailedErrorView::FullTextRole:
+ return fullText(m_diagnostic);
+ case ClangToolsDiagnosticModel::DiagnosticRole:
+ return QVariant::fromValue(m_diagnostic);
+ case ClangToolsDiagnosticModel::TextRole:
+ return m_diagnostic.description;
+ case ClangToolsDiagnosticModel::CheckBoxEnabledRole:
switch (m_fixitStatus) {
case FixitStatus::NotAvailable:
- case FixitStatus::NotScheduled:
- case FixitStatus::Invalidated:
case FixitStatus::Applied:
case FixitStatus::FailedToApply:
- return Qt::Unchecked;
+ case FixitStatus::Invalidated:
+ return false;
case FixitStatus::Scheduled:
- return Qt::Checked;
+ case FixitStatus::NotScheduled:
+ return true;
}
- } else if (role == Qt::DisplayRole) {
+ break;
+ case Qt::CheckStateRole: {
switch (m_fixitStatus) {
case FixitStatus::NotAvailable:
- return ClangToolsDiagnosticModel::tr("No Fixits");
- case FixitStatus::NotScheduled:
- return ClangToolsDiagnosticModel::tr("Not Scheduled");
case FixitStatus::Invalidated:
- return ClangToolsDiagnosticModel::tr("Invalidated");
- case FixitStatus::Scheduled:
- return ClangToolsDiagnosticModel::tr("Scheduled");
- case FixitStatus::FailedToApply:
- return ClangToolsDiagnosticModel::tr("Failed to Apply");
case FixitStatus::Applied:
- return ClangToolsDiagnosticModel::tr("Applied");
+ case FixitStatus::FailedToApply:
+ case FixitStatus::NotScheduled:
+ return Qt::Unchecked;
+ case FixitStatus::Scheduled:
+ return Qt::Checked;
}
+ break;
}
- } else if (column == DiagnosticView::DiagnosticColumn) {
- switch (role) {
- case Debugger::DetailedErrorView::LocationRole:
- return QVariant::fromValue(m_diagnostic.location);
- case Debugger::DetailedErrorView::FullTextRole:
- return fullText(m_diagnostic);
- case ClangToolsDiagnosticModel::DiagnosticRole:
- return QVariant::fromValue(m_diagnostic);
- case ClangToolsDiagnosticModel::TextRole:
- return m_diagnostic.description;
case Qt::DisplayRole:
return QString("%1: %2").arg(lineColumnString(m_diagnostic.location),
m_diagnostic.description);
case Qt::ToolTipRole:
- return createDiagnosticToolTipString(m_diagnostic);
+ return createDiagnosticToolTipString(m_diagnostic, m_fixitStatus);
case Qt::DecorationRole:
return iconData(m_diagnostic.type);
default:
@@ -450,7 +459,7 @@ QVariant DiagnosticItem::data(int column, int role) const
bool DiagnosticItem::setData(int column, const QVariant &data, int role)
{
- if (column == DiagnosticView::FixItColumn && role == Qt::CheckStateRole) {
+ if (column == DiagnosticView::DiagnosticColumn && role == Qt::CheckStateRole) {
if (m_fixitStatus != FixitStatus::Scheduled && m_fixitStatus != FixitStatus::NotScheduled)
return false;
@@ -494,15 +503,6 @@ ExplainingStepItem::ExplainingStepItem(const ExplainingStep &step, int index)
, m_index(index)
{}
-// We expect something like "note: ..."
-static QVariant iconForExplainingStepMessage(const QString &message)
-{
- const int index = message.indexOf(':');
- if (index == -1)
- return QVariant();
- return iconData(message.mid(0, index));
-}
-
static QString rangeString(const QVector<Debugger::DiagnosticLocation> &ranges)
{
return QString("%1-%2").arg(lineColumnString(ranges[0]), lineColumnString(ranges[1]));
@@ -510,9 +510,6 @@ static QString rangeString(const QVector<Debugger::DiagnosticLocation> &ranges)
QVariant ExplainingStepItem::data(int column, int role) const
{
- if (column == DiagnosticView::FixItColumn)
- return QVariant();
-
if (column == DiagnosticView::DiagnosticColumn) {
// DiagnosticColumn
switch (role) {
@@ -555,7 +552,7 @@ QVariant ExplainingStepItem::data(int column, int role) const
case Qt::DecorationRole:
if (m_step.isFixIt)
return Utils::Icons::CODEMODEL_FIXIT.icon();
- return iconForExplainingStepMessage(m_step.message);
+ return Utils::Icons::INFO.icon();
default:
return QVariant();
}
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
index 22d0699201..a8c4dcd011 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
+++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h
@@ -112,7 +112,11 @@ public:
void addDiagnostics(const QList<Diagnostic> &diagnostics);
QSet<Diagnostic> diagnostics() const;
- enum ItemRole { DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1, TextRole };
+ enum ItemRole {
+ DiagnosticRole = Debugger::DetailedErrorView::FullTextRole + 1,
+ TextRole,
+ CheckBoxEnabledRole
+ };
void clear();
void removeWatchedPath(const QString &path);
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticview.cpp b/src/plugins/clangtools/clangtoolsdiagnosticview.cpp
index 07bc7f397f..33b002ced2 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticview.cpp
+++ b/src/plugins/clangtools/clangtoolsdiagnosticview.cpp
@@ -30,11 +30,13 @@
#include "clangtoolsutils.h"
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/manhattanstyle.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <QAction>
+#include <QApplication>
#include <QDebug>
#include <QHeaderView>
#include <QPainter>
@@ -44,21 +46,22 @@ using namespace Debugger;
namespace ClangTools {
namespace Internal {
-class ClickableFixItHeader : public QHeaderView
+// A header view that puts a check box in front of a given column.
+class HeaderWithCheckBoxInColumn : public QHeaderView
{
Q_OBJECT
public:
- ClickableFixItHeader(Qt::Orientation orientation, QWidget *parent = nullptr)
+ HeaderWithCheckBoxInColumn(Qt::Orientation orientation,
+ int column = 0,
+ QWidget *parent = nullptr)
: QHeaderView(orientation, parent)
+ , m_column(column)
{
setDefaultAlignment(Qt::AlignLeft);
}
- void setState(QFlags<QStyle::StateFlag> newState)
- {
- state = newState;
- }
+ void setState(QFlags<QStyle::StateFlag> newState) { state = newState; }
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override
@@ -66,7 +69,7 @@ protected:
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
- if (logicalIndex == DiagnosticView::FixItColumn) {
+ if (logicalIndex == m_column) {
QStyleOptionButton option;
const int side = sizeHint().height();
option.rect = QRect(rect.left() + 1, 1, side - 3, side - 3);
@@ -83,34 +86,111 @@ protected:
void mouseReleaseEvent(QMouseEvent *event) override
{
const int x = event->localPos().x();
- const int fixItColumnX = sectionPosition(DiagnosticView::FixItColumn);
- const bool isWithinFixitCheckBox = x > fixItColumnX
- && x < fixItColumnX + sizeHint().height() - 3;
- if (isWithinFixitCheckBox) {
+ const int columnX = sectionPosition(m_column);
+ const bool isWithinCheckBox = x > columnX && x < columnX + sizeHint().height() - 3;
+ if (isWithinCheckBox) {
state = (state != QStyle::State_On) ? QStyle::State_On : QStyle::State_Off;
viewport()->update();
- emit fixItColumnClicked(state == QStyle::State_On);
+ emit checkBoxClicked(state == QStyle::State_On);
return; // Avoid changing sort order
}
QHeaderView::mouseReleaseEvent(event);
}
signals:
- void fixItColumnClicked(bool checked);
+ void checkBoxClicked(bool checked);
private:
+ const int m_column = 0;
QFlags<QStyle::StateFlag> state = QStyle::State_Off;
};
+static QString getBaseStyleName()
+{
+ QStyle *style = QApplication::style();
+ if (auto proxyStyle = qobject_cast<QProxyStyle *>(style))
+ style = proxyStyle->baseStyle();
+ return style->objectName();
+}
+
+// Paints the check box indicator disabled if requested by client.
+class DiagnosticViewStyle : public ManhattanStyle
+{
+public:
+ DiagnosticViewStyle(const QString &baseStyleName = getBaseStyleName())
+ : ManhattanStyle(baseStyleName)
+ {}
+
+ void setPaintCheckBoxDisabled(bool paintDisabledCheckbox)
+ {
+ m_paintCheckBoxDisabled = paintDisabledCheckbox;
+ }
+
+ void drawPrimitive(PrimitiveElement element,
+ const QStyleOption *option,
+ QPainter *painter,
+ const QWidget *widget = nullptr) const final
+ {
+ if (element == QStyle::PE_IndicatorCheckBox && m_paintCheckBoxDisabled) {
+ if (const QStyleOptionButton *o = qstyleoption_cast<const QStyleOptionButton *>(
+ option)) {
+ QStyleOptionButton myOption = *o;
+ myOption.palette.setCurrentColorGroup(QPalette::Disabled);
+ ManhattanStyle::drawPrimitive(element, &myOption, painter, widget);
+ return;
+ }
+ }
+ ManhattanStyle::drawPrimitive(element, option, painter, widget);
+ }
+
+private:
+ bool m_paintCheckBoxDisabled = false;
+};
+
+// A delegate that allows to paint a disabled check box (indicator).
+// This is useful if the rest of the item should not be disabled.
+class DiagnosticViewDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+
+public:
+ DiagnosticViewDelegate(DiagnosticViewStyle *style)
+ : m_style(style)
+ {}
+
+ void paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const final
+ {
+ const bool paintDisabled = !index.data(ClangToolsDiagnosticModel::CheckBoxEnabledRole)
+ .toBool();
+ if (paintDisabled)
+ m_style->setPaintCheckBoxDisabled(true);
+ QStyledItemDelegate::paint(painter, option, index);
+ if (paintDisabled)
+ m_style->setPaintCheckBoxDisabled(false);
+ }
+
+private:
+ DiagnosticViewStyle *m_style = nullptr;
+};
+
DiagnosticView::DiagnosticView(QWidget *parent)
: Debugger::DetailedErrorView(parent)
+ , m_style(new DiagnosticViewStyle)
+ , m_delegate(new DiagnosticViewDelegate(m_style.get()))
{
m_suppressAction = new QAction(tr("Suppress This Diagnostic"), this);
connect(m_suppressAction, &QAction::triggered,
this, &DiagnosticView::suppressCurrentDiagnostic);
installEventFilter(this);
+
+ setStyle(m_style.get());
+ setItemDelegate(m_delegate.get());
}
+DiagnosticView::~DiagnosticView() = default;
+
void DiagnosticView::suppressCurrentDiagnostic()
{
const QModelIndexList indexes = selectionModel()->selectedRows();
@@ -199,7 +279,6 @@ bool DiagnosticView::eventFilter(QObject *watched, QEvent *event)
switch (key) {
case Qt::Key_Return:
case Qt::Key_Enter:
- case Qt::Key_Space:
openEditorForCurrentIndex();
}
return true;
@@ -219,11 +298,11 @@ void DiagnosticView::setSelectedFixItsCount(int fixItsCount)
{
if (m_ignoreSetSelectedFixItsCount)
return;
- auto *clickableFixItHeader = static_cast<ClickableFixItHeader *>(header());
- clickableFixItHeader->setState(fixItsCount
- ? (QStyle::State_NoChange | QStyle::State_On | QStyle::State_Off)
- : QStyle::State_Off);
- clickableFixItHeader->viewport()->update();
+ auto checkBoxHeader = static_cast<HeaderWithCheckBoxInColumn *>(header());
+ checkBoxHeader->setState(fixItsCount
+ ? (QStyle::State_NoChange | QStyle::State_On | QStyle::State_Off)
+ : QStyle::State_Off);
+ checkBoxHeader->viewport()->update();
}
void DiagnosticView::openEditorForCurrentIndex()
@@ -237,28 +316,31 @@ void DiagnosticView::openEditorForCurrentIndex()
void DiagnosticView::setModel(QAbstractItemModel *theProxyModel)
{
const auto proxyModel = static_cast<QSortFilterProxyModel *>(theProxyModel);
- const auto sourceModel = static_cast<ClangToolsDiagnosticModel *>(proxyModel->sourceModel());
-
Debugger::DetailedErrorView::setModel(proxyModel);
- auto *clickableFixItHeader = new ClickableFixItHeader(Qt::Horizontal, this);
- connect(clickableFixItHeader, &ClickableFixItHeader::fixItColumnClicked, this, [=](bool checked) {
+
+ auto *header = new HeaderWithCheckBoxInColumn(Qt::Horizontal,
+ DiagnosticView::DiagnosticColumn,
+ this);
+ connect(header, &HeaderWithCheckBoxInColumn::checkBoxClicked, this, [=](bool checked) {
m_ignoreSetSelectedFixItsCount = true;
- sourceModel->rootItem()->forChildrenAtLevel(2, [&](::Utils::TreeItem *item) {
- auto diagnosticItem = static_cast<DiagnosticItem *>(item);
- diagnosticItem->setData(FixItColumn,
- checked ? Qt::Checked : Qt::Unchecked,
- Qt::CheckStateRole);
- });
+ for (int i = 0, count = proxyModel->rowCount(); i < count; ++i) {
+ const QModelIndex filePathItemIndex = proxyModel->index(i, 0);
+ for (int j = 0, count = proxyModel->rowCount(filePathItemIndex); j < count; ++j) {
+ const QModelIndex proxyIndex = proxyModel->index(j, 0, filePathItemIndex);
+ const QModelIndex diagnosticItemIndex = proxyModel->mapToSource(proxyIndex);
+ auto item = static_cast<DiagnosticItem *>(diagnosticItemIndex.internalPointer());
+ item->setData(DiagnosticView::DiagnosticColumn,
+ checked ? Qt::Checked : Qt::Unchecked,
+ Qt::CheckStateRole);
+ }
+ }
m_ignoreSetSelectedFixItsCount = false;
});
- setHeader(clickableFixItHeader);
- clickableFixItHeader->setStretchLastSection(false);
- clickableFixItHeader->setSectionResizeMode(0, QHeaderView::Stretch);
- clickableFixItHeader->setSectionResizeMode(1, QHeaderView::ResizeToContents);
-
- const int fixitColumnWidth = clickableFixItHeader->sectionSizeHint(DiagnosticView::FixItColumn);
- const int checkboxWidth = clickableFixItHeader->height();
- clickableFixItHeader->setMinimumSectionSize(fixitColumnWidth + 1.2 * checkboxWidth);
+ setHeader(header);
+ header->setSectionResizeMode(DiagnosticView::DiagnosticColumn, QHeaderView::Stretch);
+ const int columnWidth = header->sectionSizeHint(DiagnosticView::DiagnosticColumn);
+ const int checkboxWidth = header->height();
+ header->setMinimumSectionSize(columnWidth + 1.2 * checkboxWidth);
}
} // namespace Internal
diff --git a/src/plugins/clangtools/clangtoolsdiagnosticview.h b/src/plugins/clangtools/clangtoolsdiagnosticview.h
index 7cb287ab39..6bc6135101 100644
--- a/src/plugins/clangtools/clangtoolsdiagnosticview.h
+++ b/src/plugins/clangtools/clangtoolsdiagnosticview.h
@@ -27,19 +27,21 @@
#include <debugger/analyzer/detailederrorview.h>
+#include <memory>
+
namespace ClangTools {
namespace Internal {
+class DiagnosticViewStyle;
+class DiagnosticViewDelegate;
+
class DiagnosticView : public Debugger::DetailedErrorView
{
Q_OBJECT
public:
DiagnosticView(QWidget *parent = nullptr);
-
- enum ExtraColumn {
- FixItColumn = DiagnosticColumn + 1,
- };
+ ~DiagnosticView() override;
void setSelectedFixItsCount(int fixItsCount);
@@ -59,6 +61,8 @@ private:
void setModel(QAbstractItemModel *theProxyModel) override;
QAction *m_suppressAction;
+ std::unique_ptr<DiagnosticViewStyle> m_style;
+ std::unique_ptr<DiagnosticViewDelegate> m_delegate;
bool m_ignoreSetSelectedFixItsCount = false;
};
diff --git a/src/plugins/clangtools/clangtoolslogfilereader.cpp b/src/plugins/clangtools/clangtoolslogfilereader.cpp
index d2213d3304..e8a6fbcc96 100644
--- a/src/plugins/clangtools/clangtoolslogfilereader.cpp
+++ b/src/plugins/clangtools/clangtoolslogfilereader.cpp
@@ -94,7 +94,7 @@ static ExplainingStep buildChildDiagnostic(const CXDiagnostic cxDiagnostic)
const CXSourceLocation cxLocation = clang_getDiagnosticLocation(cxDiagnostic);
diagnosticStep.location = diagLocationFromSourceLocation(cxLocation);
- diagnosticStep.message = type + ": " + fromCXString(clang_getDiagnosticSpelling(cxDiagnostic));
+ diagnosticStep.message = fromCXString(clang_getDiagnosticSpelling(cxDiagnostic));
return diagnosticStep;
}
diff --git a/src/plugins/coreplugin/helpitem.cpp b/src/plugins/coreplugin/helpitem.cpp
index b8794481cf..d63bd883de 100644
--- a/src/plugins/coreplugin/helpitem.cpp
+++ b/src/plugins/coreplugin/helpitem.cpp
@@ -270,7 +270,7 @@ static const HelpItem::Links getBestLink(const HelpItem::Links &links)
const HelpItem::Links HelpItem::bestLinks() const
{
- if (m_isFuzzyMatch)
+ if (isFuzzyMatch())
return getBestLinks(links());
return getBestLink(links());
}
@@ -279,3 +279,10 @@ const QString HelpItem::keyword() const
{
return m_keyword;
}
+
+bool HelpItem::isFuzzyMatch() const
+{
+ // make sure m_isFuzzyMatch is correct
+ links();
+ return m_isFuzzyMatch;
+}
diff --git a/src/plugins/coreplugin/helpitem.h b/src/plugins/coreplugin/helpitem.h
index 4d9ab153fb..15ff585ca8 100644
--- a/src/plugins/coreplugin/helpitem.h
+++ b/src/plugins/coreplugin/helpitem.h
@@ -86,6 +86,8 @@ public:
const QString keyword() const;
private:
+ bool isFuzzyMatch() const;
+
QUrl m_helpUrl;
QStringList m_helpIds;
QString m_docMark;
diff --git a/src/plugins/coreplugin/images/logo/128/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/128/QtProject-qtcreator.png
index 3dc3b0a74e..53a42c20fe 100644
--- a/src/plugins/coreplugin/images/logo/128/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/128/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/logo/16/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/16/QtProject-qtcreator.png
index 2adcdb5f49..d48df57e63 100644
--- a/src/plugins/coreplugin/images/logo/16/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/16/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/logo/24/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/24/QtProject-qtcreator.png
index 3ec47c9175..449c740a11 100644
--- a/src/plugins/coreplugin/images/logo/24/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/24/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/logo/256/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/256/QtProject-qtcreator.png
index 68667830c1..3a9cf292bc 100644
--- a/src/plugins/coreplugin/images/logo/256/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/256/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/logo/32/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/32/QtProject-qtcreator.png
index 8173281abf..87ab1ba5cb 100644
--- a/src/plugins/coreplugin/images/logo/32/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/32/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/logo/48/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/48/QtProject-qtcreator.png
index 9d218b36d8..43a6834a14 100644
--- a/src/plugins/coreplugin/images/logo/48/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/48/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/logo/512/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/512/QtProject-qtcreator.png
index 45aa2008d1..acbb5a5134 100644
--- a/src/plugins/coreplugin/images/logo/512/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/512/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/coreplugin/images/logo/64/QtProject-qtcreator.png b/src/plugins/coreplugin/images/logo/64/QtProject-qtcreator.png
index 778da34776..1a89d932f5 100644
--- a/src/plugins/coreplugin/images/logo/64/QtProject-qtcreator.png
+++ b/src/plugins/coreplugin/images/logo/64/QtProject-qtcreator.png
Binary files differ
diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp
index 3f44a977c9..e5685dc5e0 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.cpp
+++ b/src/plugins/cpptools/compileroptionsbuilder.cpp
@@ -41,6 +41,7 @@
#include <QDir>
#include <QRegularExpression>
+#include <QtGlobal>
namespace CppTools {
@@ -701,6 +702,10 @@ void CompilerOptionsBuilder::reset()
// QMakeProject: -pipe -Whello -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC
void CompilerOptionsBuilder::evaluateCompilerFlags()
{
+ static QStringList userBlackList = QString::fromLocal8Bit(
+ qgetenv("QTC_CLANG_CMD_OPTIONS_BLACKLIST"))
+ .split(';', QString::SkipEmptyParts);
+
bool containsDriverMode = false;
bool skipNext = false;
for (const QString &option : m_projectPart.compilerFlags) {
@@ -709,6 +714,9 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
continue;
}
+ if (userBlackList.contains(option))
+ continue;
+
// Ignore warning flags as these interfere with our user-configured diagnostics.
// Note that once "-w" is provided, no warnings will be emitted, even if "-Wall" follows.
if (m_useBuildSystemWarnings == UseBuildSystemWarnings::No
diff --git a/src/plugins/cpptools/cpphoverhandler.cpp b/src/plugins/cpptools/cpphoverhandler.cpp
index f65e701c03..07617a411f 100644
--- a/src/plugins/cpptools/cpphoverhandler.cpp
+++ b/src/plugins/cpptools/cpphoverhandler.cpp
@@ -26,6 +26,7 @@
#include "cpphoverhandler.h"
#include "cppelementevaluator.h"
+#include "cpptoolsreuse.h"
#include <coreplugin/helpmanager.h>
#include <texteditor/texteditor.h>
@@ -56,14 +57,16 @@ void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos, Rep
tip += evaluator.diagnosis();
setPriority(Priority_Diagnostic);
}
+ const QStringList fallback = identifierWordsUnderCursor(tc);
if (evaluator.identifiedCppElement()) {
const QSharedPointer<CppElement> &cppElement = evaluator.cppElement();
- QStringList candidates = cppElement->helpIdCandidates;
- candidates.removeDuplicates();
- const HelpItem helpItem(candidates, cppElement->helpMark, cppElement->helpCategory);
+ const QStringList candidates = cppElement->helpIdCandidates;
+ const HelpItem helpItem(candidates + fallback, cppElement->helpMark, cppElement->helpCategory);
setLastHelpItemIdentified(helpItem); // tool tip appended by decorateToolTip
if (!helpItem.isValid())
tip += cppElement->tooltip;
+ } else {
+ setLastHelpItemIdentified({fallback, {}, HelpItem::Unknown});
}
setToolTip(tip);
}
diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp
index c56bfb9160..9bcf806b7d 100644
--- a/src/plugins/cpptools/cpptoolsreuse.cpp
+++ b/src/plugins/cpptools/cpptoolsreuse.cpp
@@ -41,6 +41,7 @@
#include <utils/qtcassert.h>
#include <QDebug>
+#include <QRegularExpression>
#include <QSet>
#include <QStringRef>
#include <QTextCursor>
@@ -50,29 +51,91 @@ using namespace CPlusPlus;
namespace CppTools {
-static void moveCursorToStartOrEndOfIdentifier(QTextCursor *tc,
- QTextCursor::MoveOperation op,
- int posDiff = 0)
+static int skipChars(QTextCursor *tc,
+ QTextCursor::MoveOperation op,
+ int offset,
+ std::function<bool(const QChar &)> skip)
{
- QTextDocument *doc = tc->document();
+ const QTextDocument *doc = tc->document();
if (!doc)
- return;
-
- QChar ch = doc->characterAt(tc->position() - posDiff);
- while (isValidIdentifierChar(ch)) {
- tc->movePosition(op);
- ch = doc->characterAt(tc->position() - posDiff);
+ return 0;
+ QChar ch = doc->characterAt(tc->position() + offset);
+ if (ch.isNull())
+ return 0;
+ int count = 0;
+ while (skip(ch)) {
+ if (tc->movePosition(op))
+ ++count;
+ else
+ break;
+ ch = doc->characterAt(tc->position() + offset);
}
+ return count;
+}
+
+static int skipCharsForward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
+{
+ return skipChars(tc, QTextCursor::NextCharacter, 0, skip);
+}
+
+static int skipCharsBackward(QTextCursor *tc, std::function<bool(const QChar &)> skip)
+{
+ return skipChars(tc, QTextCursor::PreviousCharacter, -1, skip);
+}
+
+QStringList identifierWordsUnderCursor(const QTextCursor &tc)
+{
+ const QTextDocument *document = tc.document();
+ if (!document)
+ return {};
+ const auto isSpace = [](const QChar &c) { return c.isSpace(); };
+ const auto isColon = [](const QChar &c) { return c == ':'; };
+ const auto isValidIdentifierCharAt = [document](const QTextCursor &tc) {
+ return isValidIdentifierChar(document->characterAt(tc.position()));
+ };
+ // move to the end
+ QTextCursor endCursor(tc);
+ do {
+ moveCursorToEndOfIdentifier(&endCursor);
+ // possibly skip ::
+ QTextCursor temp(endCursor);
+ skipCharsForward(&temp, isSpace);
+ const int colons = skipCharsForward(&temp, isColon);
+ skipCharsForward(&temp, isSpace);
+ if (colons == 2 && isValidIdentifierCharAt(temp))
+ endCursor = temp;
+ } while (isValidIdentifierCharAt(endCursor));
+
+ QStringList results;
+ QTextCursor startCursor(endCursor);
+ do {
+ moveCursorToStartOfIdentifier(&startCursor);
+ if (startCursor.position() == endCursor.position())
+ break;
+ QTextCursor temp(endCursor);
+ temp.setPosition(startCursor.position(), QTextCursor::KeepAnchor);
+ results.append(temp.selectedText().remove(QRegularExpression("\\s")));
+ // possibly skip ::
+ temp = startCursor;
+ skipCharsBackward(&temp, isSpace);
+ const int colons = skipCharsBackward(&temp, isColon);
+ skipCharsBackward(&temp, isSpace);
+ if (colons == 2
+ && isValidIdentifierChar(document->characterAt(temp.position() - 1))) {
+ startCursor = temp;
+ }
+ } while (!isValidIdentifierCharAt(startCursor));
+ return results;
}
void moveCursorToEndOfIdentifier(QTextCursor *tc)
{
- moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::NextCharacter);
+ skipCharsForward(tc, isValidIdentifierChar);
}
void moveCursorToStartOfIdentifier(QTextCursor *tc)
{
- moveCursorToStartOrEndOfIdentifier(tc, QTextCursor::PreviousCharacter, 1);
+ skipCharsBackward(tc, isValidIdentifierChar);
}
static bool isOwnershipRAIIName(const QString &name)
diff --git a/src/plugins/cpptools/cpptoolsreuse.h b/src/plugins/cpptools/cpptoolsreuse.h
index d1a1956be3..92e1365d15 100644
--- a/src/plugins/cpptools/cpptoolsreuse.h
+++ b/src/plugins/cpptools/cpptoolsreuse.h
@@ -58,6 +58,7 @@ bool CPPTOOLS_EXPORT isValidFirstIdentifierChar(const QChar &ch);
bool CPPTOOLS_EXPORT isValidIdentifierChar(const QChar &ch);
bool CPPTOOLS_EXPORT isValidIdentifier(const QString &s);
+QStringList CPPTOOLS_EXPORT identifierWordsUnderCursor(const QTextCursor &tc);
QString CPPTOOLS_EXPORT identifierUnderCursor(QTextCursor *cursor);
bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp
index d401f452ac..dde08c6794 100644
--- a/src/plugins/languageclient/client.cpp
+++ b/src/plugins/languageclient/client.cpp
@@ -69,6 +69,7 @@ class TextMark : public TextEditor::TextMark
public:
TextMark(const Utils::FileName &fileName, const Diagnostic &diag)
: TextEditor::TextMark(fileName, diag.range().start().line() + 1, "lspmark")
+ , m_diagnostic(diag)
{
using namespace Utils;
setLineAnnotation(diag.message());
@@ -81,11 +82,17 @@ public:
setIcon(isError ? Icons::CODEMODEL_ERROR.icon()
: Icons::CODEMODEL_WARNING.icon());
}
+
+ const Diagnostic &diagnostic() const { return m_diagnostic; }
+
+private:
+ const Diagnostic m_diagnostic;
};
Client::Client(BaseClientInterface *clientInterface)
: m_id(Core::Id::fromString(QUuid::createUuid().toString()))
, m_completionProvider(this)
+ , m_quickFixProvider(this)
, m_clientInterface(clientInterface)
{
m_contentHandler.insert(JsonRpcMessageHandler::jsonRpcMimeType(),
@@ -101,8 +108,10 @@ Client::~Client()
using namespace TextEditor;
// FIXME: instead of replacing the completion provider in the text document store the
// completion provider as a prioritised list in the text document
- for (TextDocument *document : m_resetCompletionProvider)
+ for (TextDocument *document : m_resetAssistProvider) {
document->setCompletionAssistProvider(nullptr);
+ document->setQuickFixAssistProvider(nullptr);
+ }
for (Core::IEditor * editor : Core::DocumentModel::editorsForOpenedDocuments()) {
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) {
TextEditorWidget *widget = textEditor->editorWidget();
@@ -192,10 +201,12 @@ void Client::openDocument(Core::IDocument *document)
documentContentsChanged(document);
});
if (textDocument) {
- m_resetCompletionProvider << textDocument;
+ textDocument->completionAssistProvider();
+ m_resetAssistProvider << textDocument;
textDocument->setCompletionAssistProvider(&m_completionProvider);
+ textDocument->setQuickFixAssistProvider(&m_quickFixProvider);
connect(textDocument, &QObject::destroyed, this, [this, textDocument]{
- m_resetCompletionProvider.remove(textDocument);
+ m_resetAssistProvider.remove(textDocument);
});
if (BaseTextEditor *editor = BaseTextEditor::textEditorForDocument(textDocument)) {
if (QPointer<TextEditorWidget> widget = editor->editorWidget()) {
@@ -543,25 +554,10 @@ void Client::cursorPositionChanged(TextEditor::TextEditorWidget *widget)
void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic> &diagnostics)
{
const Utils::FileName fileName = uri.toFileName();
- TextEditor::TextDocument *doc = textDocumentForFileName(fileName);
+ TextEditor::TextDocument *doc = TextEditor::TextDocument::textDocumentForFileName(fileName);
if (!doc)
return;
- const QString method(CodeActionRequest::methodName);
- if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
- if (!registered.value())
- return;
- const TextDocumentRegistrationOptions option(
- m_dynamicCapabilities.option(method).toObject());
- if (option.isValid(nullptr) && !option.filterApplies(fileName))
- return;
- } else {
- Utils::variant<bool, CodeActionOptions> provider
- = m_serverCapabilities.codeActionProvider().value_or(false);
- if (!(Utils::holds_alternative<CodeActionOptions>(provider) || Utils::get<bool>(provider)))
- return;
- }
-
CodeActionParams codeActionParams;
CodeActionParams::CodeActionContext context;
context.setDiagnostics(diagnostics);
@@ -577,6 +573,32 @@ void Client::requestCodeActions(const DocumentUri &uri, const QList<Diagnostic>
if (self)
self->handleCodeActionResponse(response, uri);
});
+ requestCodeActions(request);
+}
+
+void Client::requestCodeActions(const CodeActionRequest &request)
+{
+ if (!request.isValid(nullptr))
+ return;
+
+ const Utils::FileName fileName
+ = request.params().value_or(CodeActionParams()).textDocument().uri().toFileName();
+
+ const QString method(CodeActionRequest::methodName);
+ if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
+ if (!registered.value())
+ return;
+ const TextDocumentRegistrationOptions option(
+ m_dynamicCapabilities.option(method).toObject());
+ if (option.isValid(nullptr) && !option.filterApplies(fileName))
+ return;
+ } else {
+ Utils::variant<bool, CodeActionOptions> provider
+ = m_serverCapabilities.codeActionProvider().value_or(false);
+ if (!(Utils::holds_alternative<CodeActionOptions>(provider) || Utils::get<bool>(provider)))
+ return;
+ }
+
sendContent(request);
}
@@ -682,6 +704,17 @@ bool Client::needsRestart(const BaseSettings *settings) const
|| m_languagFilter.filePattern != settings->m_languageFilter.filePattern;
}
+QList<Diagnostic> Client::diagnosticsAt(const DocumentUri &uri, const Range &range) const
+{
+ QList<Diagnostic> diagnostics;
+ for (const TextMark *mark : m_diagnostics[uri]) {
+ const Diagnostic diagnostic = mark->diagnostic();
+ if (diagnostic.range().overlaps(range))
+ diagnostics << diagnostic;
+ }
+ return diagnostics;
+}
+
bool Client::start()
{
return m_clientInterface->start();
@@ -778,7 +811,8 @@ void Client::showMessageBox(const ShowMessageRequestParams &message, const Messa
void Client::showDiagnostics(const DocumentUri &uri)
{
- if (TextEditor::TextDocument *doc = textDocumentForFileName(uri.toFileName())) {
+ if (TextEditor::TextDocument *doc
+ = TextEditor::TextDocument::textDocumentForFileName(uri.toFileName())) {
for (TextMark *mark : m_diagnostics.value(uri))
doc->addMark(mark);
}
@@ -786,7 +820,8 @@ void Client::showDiagnostics(const DocumentUri &uri)
void Client::removeDiagnostics(const DocumentUri &uri)
{
- TextEditor::TextDocument *doc = textDocumentForFileName(uri.toFileName());
+ TextEditor::TextDocument *doc
+ = TextEditor::TextDocument::textDocumentForFileName(uri.toFileName());
for (TextMark *mark : m_diagnostics.take(uri)) {
if (doc)
diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h
index 3d691f2bd2..2d92424f42 100644
--- a/src/plugins/languageclient/client.h
+++ b/src/plugins/languageclient/client.h
@@ -26,7 +26,8 @@
#pragma once
#include "dynamiccapabilities.h"
-#include "languageclientcodeassist.h"
+#include "languageclientcompletionassist.h"
+#include "languageclientquickfix.h"
#include "languageclientsettings.h"
#include <coreplugin/id.h>
@@ -104,6 +105,7 @@ public:
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::Diagnostic> &diagnostics);
+ void requestCodeActions(const LanguageServerProtocol::CodeActionRequest &request);
void handleCodeActionResponse(const LanguageServerProtocol::CodeActionRequest::Response &response,
const LanguageServerProtocol::DocumentUri &uri);
void executeCommand(const LanguageServerProtocol::Command &command);
@@ -129,6 +131,10 @@ public:
bool needsRestart(const BaseSettings *) const;
+ QList<LanguageServerProtocol::Diagnostic> diagnosticsAt(
+ const LanguageServerProtocol::DocumentUri &uri,
+ const LanguageServerProtocol::Range &range) const;
+
bool start();
bool reset();
@@ -184,7 +190,8 @@ private:
LanguageServerProtocol::ServerCapabilities m_serverCapabilities;
DynamicCapabilities m_dynamicCapabilities;
LanguageClientCompletionAssistProvider m_completionProvider;
- QSet<TextEditor::TextDocument *> m_resetCompletionProvider;
+ LanguageClientQuickFixProvider m_quickFixProvider;
+ QSet<TextEditor::TextDocument *> m_resetAssistProvider;
QHash<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::MessageId> m_highlightRequests;
int m_restartsLeft = 5;
QScopedPointer<BaseClientInterface> m_clientInterface;
diff --git a/src/plugins/languageclient/languageclient.pro b/src/plugins/languageclient/languageclient.pro
index 59c568a75b..dbae20e109 100644
--- a/src/plugins/languageclient/languageclient.pro
+++ b/src/plugins/languageclient/languageclient.pro
@@ -6,11 +6,12 @@ HEADERS += \
client.h \
dynamiccapabilities.h \
languageclient_global.h \
- languageclientcodeassist.h \
+ languageclientcompletionassist.h \
languageclientinterface.h \
languageclientmanager.h \
languageclientoutline.h \
languageclientplugin.h \
+ languageclientquickfix.h \
languageclientsettings.h \
languageclientutils.h
@@ -18,11 +19,12 @@ HEADERS += \
SOURCES += \
client.cpp \
dynamiccapabilities.cpp \
- languageclientcodeassist.cpp \
+ languageclientcompletionassist.cpp \
languageclientinterface.cpp \
languageclientmanager.cpp \
languageclientoutline.cpp \
languageclientplugin.cpp \
+ languageclientquickfix.cpp \
languageclientsettings.cpp \
languageclientutils.cpp
diff --git a/src/plugins/languageclient/languageclient.qbs b/src/plugins/languageclient/languageclient.qbs
index 0da6a58076..0c2752ef5e 100644
--- a/src/plugins/languageclient/languageclient.qbs
+++ b/src/plugins/languageclient/languageclient.qbs
@@ -20,16 +20,18 @@ QtcPlugin {
"dynamiccapabilities.h",
"languageclient.qrc",
"languageclient_global.h",
- "languageclientcodeassist.cpp",
- "languageclientcodeassist.h",
"languageclientinterface.cpp",
"languageclientinterface.h",
+ "languageclientcompletionassist.cpp",
+ "languageclientcompletionassist.h",
"languageclientmanager.cpp",
"languageclientmanager.h",
"languageclientoutline.cpp",
"languageclientoutline.h",
"languageclientplugin.cpp",
"languageclientplugin.h",
+ "languageclientquickfix.cpp",
+ "languageclientquickfix.h",
"languageclientsettings.cpp",
"languageclientsettings.h",
"languageclientutils.cpp",
diff --git a/src/plugins/languageclient/languageclientcodeassist.cpp b/src/plugins/languageclient/languageclientcompletionassist.cpp
index af0e9ce892..1d9a10f6e4 100644
--- a/src/plugins/languageclient/languageclientcodeassist.cpp
+++ b/src/plugins/languageclient/languageclientcompletionassist.cpp
@@ -23,7 +23,7 @@
**
****************************************************************************/
-#include "languageclientcodeassist.h"
+#include "languageclientcompletionassist.h"
#include "client.h"
#include "languageclientutils.h"
diff --git a/src/plugins/languageclient/languageclientcodeassist.h b/src/plugins/languageclient/languageclientcompletionassist.h
index 1410e67f82..f0ad95bc88 100644
--- a/src/plugins/languageclient/languageclientcodeassist.h
+++ b/src/plugins/languageclient/languageclientcompletionassist.h
@@ -48,7 +48,7 @@ public:
private:
QList<QString> m_triggerChars;
int m_activationCharSequenceLength = 0;
- Client *m_client;
+ Client *m_client = nullptr; // not owned
};
} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientquickfix.cpp b/src/plugins/languageclient/languageclientquickfix.cpp
new file mode 100644
index 0000000000..def01b17d8
--- /dev/null
+++ b/src/plugins/languageclient/languageclientquickfix.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "languageclientquickfix.h"
+
+#include "client.h"
+#include "languageclientutils.h"
+
+#include <texteditor/codeassist/assistinterface.h>
+#include <texteditor/codeassist/genericproposal.h>
+#include <texteditor/codeassist/iassistprocessor.h>
+#include <texteditor/quickfix.h>
+
+
+using namespace LanguageServerProtocol;
+using namespace TextEditor;
+
+namespace LanguageClient {
+
+class CodeActionQuickFixOperation : public QuickFixOperation
+{
+public:
+ CodeActionQuickFixOperation(const CodeAction &action, Client *client)
+ : m_action(action)
+ , m_client(client)
+ { setDescription(action.title()); }
+
+ void perform() override
+ {
+ if (Utils::optional<WorkspaceEdit> edit = m_action.edit()) {
+ applyWorkspaceEdit(*edit);
+ } else if (Utils::optional<Command> command = m_action.command()) {
+ if (m_client)
+ m_client->executeCommand(*command);
+ }
+ }
+
+private:
+ CodeAction m_action;
+ QPointer<Client> m_client;
+};
+
+class CommandQuickFixOperation : public QuickFixOperation
+{
+public:
+ CommandQuickFixOperation(const Command &command, Client *client)
+ : m_command(command)
+ , m_client(client)
+ { setDescription(command.title()); }
+ void perform() override
+ {
+ if (m_client)
+ m_client->executeCommand(m_command);
+ }
+
+private:
+ Command m_command;
+ QPointer<Client> m_client;
+};
+
+class LanguageClientQuickFixAssistProcessor : public IAssistProcessor
+{
+public:
+ explicit LanguageClientQuickFixAssistProcessor(Client *client) : m_client(client) {}
+ bool running() override { return m_running; }
+ IAssistProposal *perform(const AssistInterface *interface) override;
+
+private:
+ void handleCodeActionResponse(const CodeActionRequest::Response &response);
+
+ QSharedPointer<const AssistInterface> m_assistInterface;
+ Client *m_client = nullptr; // not owned
+ bool m_running = false;
+};
+
+IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInterface *interface)
+{
+ m_assistInterface = QSharedPointer<const AssistInterface>(interface);
+
+ CodeActionParams params;
+ params.setContext({});
+ QTextCursor cursor(interface->textDocument());
+ cursor.setPosition(interface->position());
+ if (cursor.atBlockEnd() || cursor.atBlockStart())
+ cursor.select(QTextCursor::LineUnderCursor);
+ else
+ cursor.select(QTextCursor::WordUnderCursor);
+ if (!cursor.hasSelection())
+ cursor.select(QTextCursor::LineUnderCursor);
+ Range range(cursor);
+ params.setRange(range);
+ auto uri = DocumentUri::fromFileName(Utils::FileName::fromString(interface->fileName()));
+ params.setTextDocument(uri);
+ CodeActionParams::CodeActionContext context;
+ context.setDiagnostics(m_client->diagnosticsAt(uri, range));
+ params.setContext(context);
+
+ CodeActionRequest request(params);
+ request.setResponseCallback([this](const CodeActionRequest::Response &response){
+ handleCodeActionResponse(response);
+ });
+
+ m_client->requestCodeActions(request);
+ m_running = true;
+ return nullptr;
+}
+
+void LanguageClientQuickFixAssistProcessor::handleCodeActionResponse(
+ const CodeActionRequest::Response &response)
+{
+ m_running = false;
+ if (const Utils::optional<CodeActionRequest::Response::Error> &error = response.error())
+ m_client->log(*error);
+ QuickFixOperations ops;
+ if (const Utils::optional<CodeActionResult> &_result = response.result()) {
+ const CodeActionResult &result = _result.value();
+ if (auto list = Utils::get_if<QList<Utils::variant<Command, CodeAction>>>(&result)) {
+ for (const Utils::variant<Command, CodeAction> &item : *list) {
+ if (auto action = Utils::get_if<CodeAction>(&item))
+ ops << new CodeActionQuickFixOperation(*action, m_client);
+ else if (auto command = Utils::get_if<Command>(&item))
+ ops << new CommandQuickFixOperation(*command, m_client);
+ }
+ }
+ }
+ setAsyncProposalAvailable(GenericProposal::createProposal(m_assistInterface.data(), ops));
+}
+
+LanguageClientQuickFixProvider::LanguageClientQuickFixProvider(Client *client) : m_client(client)
+{
+ QTC_CHECK(client);
+}
+
+IAssistProvider::RunType LanguageClientQuickFixProvider::runType() const
+{
+ return Asynchronous;
+}
+
+IAssistProcessor *LanguageClientQuickFixProvider::createProcessor() const
+{
+ return new LanguageClientQuickFixAssistProcessor(m_client);
+}
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientquickfix.h b/src/plugins/languageclient/languageclientquickfix.h
new file mode 100644
index 0000000000..d9b322769f
--- /dev/null
+++ b/src/plugins/languageclient/languageclientquickfix.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <texteditor/codeassist/iassistprovider.h>
+
+namespace LanguageClient {
+
+class Client;
+
+class LanguageClientQuickFixProvider : public TextEditor::IAssistProvider
+{
+public:
+ explicit LanguageClientQuickFixProvider(Client *client);
+ IAssistProvider::RunType runType() const override;
+ TextEditor::IAssistProcessor *createProcessor() const override;
+
+private:
+ Client *m_client = nullptr; // not owned
+};
+
+} // namespace LanguageClient
diff --git a/src/plugins/languageclient/languageclientsettings.cpp b/src/plugins/languageclient/languageclientsettings.cpp
index e101db412c..17ea39f80e 100644
--- a/src/plugins/languageclient/languageclientsettings.cpp
+++ b/src/plugins/languageclient/languageclientsettings.cpp
@@ -34,9 +34,8 @@
#include <utils/algorithm.h>
#include <utils/delegates.h>
#include <utils/fancylineedit.h>
-#include <utils/qtcprocess.h>
#include <utils/mimetypes/mimedatabase.h>
-#include <languageserverprotocol/lsptypes.h>
+#include <utils/jsontreeitem.h>
#include <QBoxLayout>
#include <QCheckBox>
@@ -150,7 +149,6 @@ LanguageClientSettingsPageWidget::LanguageClientSettingsPageWidget(LanguageClien
connect(addButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::addItem);
auto deleteButton = new QPushButton(LanguageClientSettingsPage::tr("&Delete"));
connect(deleteButton, &QPushButton::pressed, this, &LanguageClientSettingsPageWidget::deleteItem);
-
mainLayout->addLayout(layout);
setLayout(mainLayout);
layout->addWidget(m_view);
@@ -505,6 +503,24 @@ BaseClientInterface *StdIOSettings::createInterface() const
return new StdIOClientInterface(m_executable, m_arguments);
}
+static QWidget *createCapabilitiesView(
+ const LanguageServerProtocol::ServerCapabilities &capabilities)
+{
+ auto root = new Utils::JsonTreeItem("Capabilities", QJsonValue(capabilities));
+ if (root->canFetchMore())
+ root->fetchMore();
+
+ auto capabilitiesModel = new Utils::TreeModel<Utils::JsonTreeItem>(root);
+ capabilitiesModel->setHeader({BaseSettingsWidget::tr("Name"),
+ BaseSettingsWidget::tr("Value"),
+ BaseSettingsWidget::tr("Type")});
+ auto capabilitiesView = new QTreeView();
+ capabilitiesView->setModel(capabilitiesModel);
+ capabilitiesView->setAlternatingRowColors(true);
+ capabilitiesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+ return capabilitiesView;
+}
+
BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *parent)
: QWidget(parent)
, m_name(new QLineEdit(settings->m_name, this))
@@ -528,6 +544,30 @@ BaseSettingsWidget::BaseSettingsWidget(const BaseSettings *settings, QWidget *pa
connect(addMimeTypeButton, &QPushButton::pressed,
this, &BaseSettingsWidget::showAddMimeTypeDialog);
+ auto createInfoLabel = []() {
+ return new QLabel(tr("Available after server was initialized"));
+ };
+
+ mainLayout->addWidget(new QLabel(tr("Capabilities:")), ++row, 0, Qt::AlignTop);
+ if (Client *client = settings->m_client.data()) {
+ if (client->state() == Client::Initialized)
+ mainLayout->addWidget(createCapabilitiesView(client->capabilities()));
+ else
+ mainLayout->addWidget(createInfoLabel(), row, 1);
+ connect(client, &Client::finished, mainLayout, [mainLayout, row, createInfoLabel]() {
+ delete mainLayout->itemAtPosition(row, 1)->widget();
+ mainLayout->addWidget(createInfoLabel(), row, 1);
+ });
+ connect(client, &Client::initialized, mainLayout,
+ [mainLayout, row](
+ const LanguageServerProtocol::ServerCapabilities &capabilities) {
+ delete mainLayout->itemAtPosition(row, 1)->widget();
+ mainLayout->addWidget(createCapabilitiesView(capabilities), row, 1);
+ });
+ } else {
+ mainLayout->addWidget(createInfoLabel());
+ }
+
setLayout(mainLayout);
}
diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp
index 5f3f8e0672..f81be2427c 100644
--- a/src/plugins/languageclient/languageclientutils.cpp
+++ b/src/plugins/languageclient/languageclientutils.cpp
@@ -40,6 +40,7 @@
using namespace LanguageServerProtocol;
using namespace Utils;
+using namespace TextEditor;
namespace LanguageClient {
@@ -72,7 +73,7 @@ bool applyTextDocumentEdit(const TextDocumentEdit &edit)
if (edits.isEmpty())
return true;
const DocumentUri &uri = edit.id().uri();
- if (TextEditor::TextDocument* doc = textDocumentForFileName(uri.toFileName())) {
+ if (TextDocument* doc = TextDocument::textDocumentForFileName(uri.toFileName())) {
LanguageClientValue<int> version = edit.id().version();
if (!version.isNull() && version.value(0) < doc->document()->revision())
return false;
@@ -84,14 +85,14 @@ bool applyTextEdits(const DocumentUri &uri, const QList<TextEdit> &edits)
{
if (edits.isEmpty())
return true;
- TextEditor::RefactoringChanges changes;
- TextEditor::RefactoringFilePtr file;
+ RefactoringChanges changes;
+ RefactoringFilePtr file;
file = changes.file(uri.toFileName().toString());
file->setChangeSet(editsToChangeSet(edits, file->document()));
return file->apply();
}
-void applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator, const TextEdit &edit)
+void applyTextEdit(TextDocumentManipulatorInterface &manipulator, const TextEdit &edit)
{
using namespace Utils::Text;
const Range range = edit.range();
@@ -118,12 +119,6 @@ bool applyWorkspaceEdit(const WorkspaceEdit &edit)
return result;
}
-TextEditor::TextDocument *textDocumentForFileName(const FileName &fileName)
-{
- return qobject_cast<TextEditor::TextDocument *>(
- Core::DocumentModel::documentForFilePath(fileName.toString()));
-}
-
QTextCursor endOfLineCursor(const QTextCursor &cursor)
{
QTextCursor ret = cursor;
@@ -135,8 +130,7 @@ void updateCodeActionRefactoringMarker(Client *client,
const CodeAction &action,
const DocumentUri &uri)
{
- using namespace TextEditor;
- TextDocument* doc = textDocumentForFileName(uri.toFileName());
+ TextDocument* doc = TextDocument::textDocumentForFileName(uri.toFileName());
if (!doc)
return;
BaseTextEditor *editor = BaseTextEditor::textEditorForDocument(doc);
diff --git a/src/plugins/languageclient/languageclientutils.h b/src/plugins/languageclient/languageclientutils.h
index 2891c2d303..f07b6e18bf 100644
--- a/src/plugins/languageclient/languageclientutils.h
+++ b/src/plugins/languageclient/languageclientutils.h
@@ -45,7 +45,6 @@ bool applyTextEdits(const LanguageServerProtocol::DocumentUri &uri,
const QList<LanguageServerProtocol::TextEdit> &edits);
void applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator,
const LanguageServerProtocol::TextEdit &edit);
-TextEditor::TextDocument *textDocumentForFileName(const Utils::FileName &fileName);
void updateCodeActionRefactoringMarker(Client *client,
const LanguageServerProtocol::CodeAction &action,
const LanguageServerProtocol::DocumentUri &uri);
diff --git a/src/plugins/perfprofiler/perfdatareader.cpp b/src/plugins/perfprofiler/perfdatareader.cpp
index 3fec773bad..c137e87b8c 100644
--- a/src/plugins/perfprofiler/perfdatareader.cpp
+++ b/src/plugins/perfprofiler/perfdatareader.cpp
@@ -77,7 +77,8 @@ PerfDataReader::PerfDataReader(QObject *parent) :
QMessageBox::warning(Core::ICore::mainWindow(),
tr("Perf data parser failed"),
tr("The perf data parser failed to process all the samples. "
- "Your trace is incomplete."));
+ "Your trace is incomplete. The exit code was %1.")
+ .arg(exitCode));
}
});
@@ -120,6 +121,7 @@ PerfDataReader::PerfDataReader(QObject *parent) :
qWarning() << "Cannot send data to perfparser";
break;
case QProcess::Timedout:
+ qWarning() << "QProcess::Timedout";
default:
break;
}
@@ -349,8 +351,10 @@ void PerfDataReader::writeChunk()
"Your trace is incomplete."));
}
}
- } else if (m_dataFinished) {
- m_input.closeWriteChannel();
+ } else if (m_dataFinished && m_input.isWritable()) {
+ // Delay closing of the write channel. Closing the channel from within a handler
+ // for bytesWritten() is dangerous on windows.
+ QTimer::singleShot(0, &m_input, &QProcess::closeWriteChannel);
}
}
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp b/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
index 8e384b2036..41cbe1763b 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.cpp
@@ -46,7 +46,6 @@
#include <QVariantMap>
#include <qbs.h>
-#include <qtprofilesetup.h>
const QChar sep = QLatin1Char('.');
@@ -166,45 +165,9 @@ void QbsManager::addProfile(const QString &name, const QVariantMap &data)
void QbsManager::addQtProfileFromKit(const QString &profileName, const ProjectExplorer::Kit *k)
{
- const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitAspect::qtVersion(k);
- if (!qt)
- return;
-
- qbs::QtEnvironment qtEnv;
- const QList<ProjectExplorer::Abi> abi = qt->qtAbis();
- if (!abi.empty()) {
- qtEnv.architecture = ProjectExplorer::Abi::toString(abi.first().architecture());
- if (abi.first().wordWidth() == 64)
- qtEnv.architecture.append(QLatin1String("_64"));
- }
- qtEnv.binaryPath = qt->binPath().toString();
- qtEnv.documentationPath = qt->docsPath().toString();
- qtEnv.includePath = qt->headerPath().toString();
- qtEnv.libraryPath = qt->libraryPath().toString();
- qtEnv.pluginPath = qt->pluginPath().toString();
- qtEnv.mkspecBasePath = qt->mkspecsPath().toString();
- qtEnv.mkspecName = qt->mkspec().toString();
- qtEnv.mkspecPath = qt->mkspecPath().toString();
- qtEnv.qtNameSpace = qt->qtNamespace();
- qtEnv.qtLibInfix = qt->qtLibInfix();
- qtEnv.qtVersion = qt->qtVersionString();
- qtEnv.qtMajorVersion = qt->qtVersion().majorVersion;
- qtEnv.qtMinorVersion = qt->qtVersion().minorVersion;
- qtEnv.qtPatchVersion = qt->qtVersion().patchVersion;
- qtEnv.frameworkBuild = qt->isFrameworkBuild();
- qtEnv.configItems = qt->configValues();
- qtEnv.qtConfigItems = qt->qtConfigValues();
- foreach (const QString &buildVariant,
- QStringList() << QLatin1String("debug") << QLatin1String("release")) {
- if (qtEnv.qtConfigItems.contains(buildVariant))
- qtEnv.buildVariant << buildVariant;
- }
- qtEnv.qmlPath = qt->qmlPath().toString();
- qtEnv.qmlImportPath = qt->qmakeProperty("QT_INSTALL_IMPORTS");
- const qbs::ErrorInfo errorInfo = qbs::setupQtProfile(profileName, settings(), qtEnv);
- if (errorInfo.hasError()) {
- Core::MessageManager::write(tr("Failed to set up kit for Qbs: %1")
- .arg(errorInfo.toString()), Core::MessageManager::ModeSwitch);
+ if (const QtSupport::BaseQtVersion * const qt = QtSupport::QtKitAspect::qtVersion(k)) {
+ qbs::Profile(profileName, settings()).setValue("moduleProviders.Qt.qmakeFilePaths",
+ qt->qmakeCommand().toString());
}
}
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
index d5d0b1b79a..bef7cd2a05 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.pro
@@ -5,11 +5,9 @@ isEmpty(QBS_INSTALL_DIR): QBS_INSTALL_DIR = $$(QBS_INSTALL_DIR)
isEmpty(QBS_INSTALL_DIR) {
QBS_SOURCE_DIR = $$PWD/../../shared/qbs
include($$QBS_SOURCE_DIR/src/lib/corelib/use_corelib.pri)
- include($$QBS_SOURCE_DIR/src/lib/qtprofilesetup/use_qtprofilesetup.pri)
osx:QMAKE_LFLAGS += -Wl,-rpath,@loader_path/../Frameworks # OS X: fix rpath for qbscore soname
} else {
include($${QBS_INSTALL_DIR}/include/qbs/use_installed_corelib.pri)
- include($${QBS_INSTALL_DIR}/include/qbs/use_installed_qtprofilesetup.pri)
}
QBS_INSTALL_DIR_FWD_SLASHES = $$replace(QBS_INSTALL_DIR, \\\\, /)
DEFINES += QBS_INSTALL_DIR=\\\"$$QBS_INSTALL_DIR_FWD_SLASHES\\\"
diff --git a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
index 6c7793db55..45e5d1f3a4 100644
--- a/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
+++ b/src/plugins/qbsprojectmanager/qbsprojectmanager.qbs
@@ -20,7 +20,7 @@ QtcPlugin {
if (qbs.enableDebugCode)
suffix = "d";
}
- libs.push("qbscore" + suffix, "qbsqtprofilesetup" + suffix);
+ libs.push("qbscore" + suffix);
return libs
}
@@ -33,10 +33,6 @@ QtcPlugin {
name: "qbscore"
condition: product.useInternalQbsProducts
}
- Depends {
- name: "qbsqtprofilesetup"
- condition: product.useInternalQbsProducts
- }
Depends { name: "QmlJS" }
Depends { name: "Utils" }
diff --git a/src/plugins/qmljseditor/qmljsfindreferences.cpp b/src/plugins/qmljseditor/qmljsfindreferences.cpp
index 67abdece26..8b790c3351 100644
--- a/src/plugins/qmljseditor/qmljsfindreferences.cpp
+++ b/src/plugins/qmljseditor/qmljsfindreferences.cpp
@@ -322,10 +322,12 @@ protected:
bool visit(AST::UiPublicMember *node) override
{
- if (node->memberType->name == _name){
- const ObjectValue * tVal = _context->lookupType(_doc.data(), QStringList(_name));
- if (tVal == _typeValue)
- _usages.append(node->typeToken);
+ if (UiQualifiedId *memberType = node->memberType) {
+ if (memberType->name == _name) {
+ const ObjectValue * tVal = _context->lookupType(_doc.data(), QStringList(_name));
+ if (tVal == _typeValue)
+ _usages.append(node->typeToken);
+ }
}
if (AST::cast<Block *>(node->statement)) {
_builder.push(node);
diff --git a/src/plugins/remotelinux/linuxdeviceprocess.cpp b/src/plugins/remotelinux/linuxdeviceprocess.cpp
index 1dac2e4408..004ca63d2a 100644
--- a/src/plugins/remotelinux/linuxdeviceprocess.cpp
+++ b/src/plugins/remotelinux/linuxdeviceprocess.cpp
@@ -42,6 +42,9 @@ LinuxDeviceProcess::LinuxDeviceProcess(const QSharedPointer<const ProjectExplore
: ProjectExplorer::SshDeviceProcess(device, parent), m_processId(0)
{
connect(this, &DeviceProcess::finished, this, [this]() {
+ m_processId = -1;
+ });
+ connect(this, &DeviceProcess::started, this, [this]() {
m_processId = 0;
});
}
@@ -70,7 +73,7 @@ QByteArray LinuxDeviceProcess::readAllStandardOutput()
qint64 LinuxDeviceProcess::processId() const
{
- return m_processId;
+ return m_processId < 0 ? 0 : m_processId;
}
QString LinuxDeviceProcess::fullCommandLine(const Runnable &runnable) const
diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp
index 98096daee9..2bfb51439a 100644
--- a/src/plugins/texteditor/textdocument.cpp
+++ b/src/plugins/texteditor/textdocument.cpp
@@ -100,6 +100,7 @@ public:
QTextDocument m_document;
SyntaxHighlighter *m_highlighter = nullptr;
CompletionAssistProvider *m_completionAssistProvider = nullptr;
+ IAssistProvider *m_quickFixProvider = nullptr;
QScopedPointer<Indenter> m_indenter;
bool m_fileIsReadOnly = false;
@@ -298,6 +299,11 @@ TextDocument *TextDocument::currentTextDocument()
return qobject_cast<TextDocument *>(EditorManager::currentDocument());
}
+TextDocument *TextDocument::textDocumentForFileName(const Utils::FileName &fileName)
+{
+ return qobject_cast<TextDocument *>(DocumentModel::documentForFilePath(fileName.toString()));
+}
+
QString TextDocument::plainText() const
{
return document()->toPlainText();
@@ -388,9 +394,14 @@ CompletionAssistProvider *TextDocument::completionAssistProvider() const
return d->m_completionAssistProvider;
}
+void TextDocument::setQuickFixAssistProvider(IAssistProvider *provider) const
+{
+ d->m_quickFixProvider = provider;
+}
+
IAssistProvider *TextDocument::quickFixAssistProvider() const
{
- return nullptr;
+ return d->m_quickFixProvider;
}
void TextDocument::applyFontSettings()
diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h
index b7c771e748..9ea1751b11 100644
--- a/src/plugins/texteditor/textdocument.h
+++ b/src/plugins/texteditor/textdocument.h
@@ -70,6 +70,7 @@ public:
static QMap<QString, QString> openedTextDocumentContents();
static QMap<QString, QTextCodec *> openedTextDocumentEncodings();
static TextDocument *currentTextDocument();
+ static TextDocument *textDocumentForFileName(const Utils::FileName &fileName);
virtual QString plainText() const;
virtual QString textAt(int pos, int length) const;
@@ -140,6 +141,7 @@ public:
void setCompletionAssistProvider(CompletionAssistProvider *provider);
virtual CompletionAssistProvider *completionAssistProvider() const;
+ void setQuickFixAssistProvider(IAssistProvider *provider) const;
virtual IAssistProvider *quickFixAssistProvider() const;
void setTabSettings(const TextEditor::TabSettings &tabSettings);
diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp
index 8995167564..22ddbbec03 100644
--- a/src/plugins/texteditor/textmark.cpp
+++ b/src/plugins/texteditor/textmark.cpp
@@ -361,11 +361,8 @@ TextMarkRegistry::TextMarkRegistry(QObject *parent)
void TextMarkRegistry::add(TextMark *mark)
{
instance()->m_marks[mark->fileName()].insert(mark);
- auto document = qobject_cast<TextDocument *>(
- DocumentModel::documentForFilePath(mark->fileName().toString()));
- if (!document)
- return;
- document->addMark(mark);
+ if (TextDocument *document = TextDocument::textDocumentForFileName(mark->fileName()))
+ document->addMark(mark);
}
bool TextMarkRegistry::remove(TextMark *mark)
diff --git a/src/plugins/welcome/introductionwidget.cpp b/src/plugins/welcome/introductionwidget.cpp
index d0c993b6e8..d10cb76be2 100644
--- a/src/plugins/welcome/introductionwidget.cpp
+++ b/src/plugins/welcome/introductionwidget.cpp
@@ -31,6 +31,7 @@
#include <utils/stylehelper.h>
#include <QEvent>
+#include <QGuiApplication>
#include <QKeyEvent>
#include <QLabel>
#include <QPainter>
@@ -349,8 +350,17 @@ void IntroductionWidget::keyPressEvent(QKeyEvent *ke)
{
if (ke->key() == Qt::Key_Escape)
finish();
- else if (ke->modifiers() == Qt::NoModifier)
- step();
+ else if ((ke->modifiers()
+ & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::MetaModifier))
+ == Qt::NoModifier) {
+ const Qt::Key backKey = QGuiApplication::isLeftToRight() ? Qt::Key_Left : Qt::Key_Right;
+ if (ke->key() == backKey) {
+ if (m_step > 0)
+ setStep(m_step - 1);
+ } else {
+ step();
+ }
+ }
}
void IntroductionWidget::mouseReleaseEvent(QMouseEvent *me)