diff --git a/share/qtcreator/cplusplus/examples/tidy_example.cpp b/share/qtcreator/cplusplus/examples/tidy_example.cpp index dc921114ea1..2b41a1e83b0 100644 --- a/share/qtcreator/cplusplus/examples/tidy_example.cpp +++ b/share/qtcreator/cplusplus/examples/tidy_example.cpp @@ -203,6 +203,8 @@ public: virtual bool check(bool enable = true); }; +bool Derived2:: + // performance-unnecessary-value-param void use(Base b) { diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index a2d97989eff..11c6b314f0e 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -2948,7 +2948,10 @@ class DumperBase: return self.detypedef().integer() elif self.type.code == TypeCodeBitfield: return self.lvalue - unsigned = self.type.name.startswith('unsigned') + # Could be something like 'short unsigned int' + unsigned = self.type.name == 'unsigned' \ + or self.type.name.startswith('unsigned ') \ + or self.type.name.find(' unsigned ') != -1 bitsize = self.type.bitsize() return self.extractInteger(bitsize, unsigned) diff --git a/src/libs/utils/textutils.cpp b/src/libs/utils/textutils.cpp index 840325dd975..9b653bafa69 100644 --- a/src/libs/utils/textutils.cpp +++ b/src/libs/utils/textutils.cpp @@ -39,8 +39,9 @@ bool convertPosition(const QTextDocument *document, int pos, int *line, int *col (*column) = -1; return false; } else { + // line and column are both 1-based (*line) = block.blockNumber() + 1; - (*column) = pos - block.position(); + (*column) = pos - block.position() + 1; return true; } } diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 3015f3f28d0..f117d70c82e 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -162,7 +162,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa { auto runConfig = runner->runControl()->runConfiguration(); - auto aspect = runConfig->extraAspect(); + auto aspect = runConfig->aspect(); Core::Id runMode = runner->runMode(); const bool debuggingMode = runMode == ProjectExplorer::Constants::DEBUG_RUN_MODE; m_useCppDebugger = debuggingMode && aspect->useCppDebugger(); @@ -194,23 +194,23 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunWorker *runner, const QString &packa m_deviceSerialNumber = AndroidManager::deviceSerialNumber(target); m_apiLevel = AndroidManager::deviceApiLevel(target); - m_extraEnvVars = runConfig->extraAspect()->environment(); + m_extraEnvVars = runConfig->aspect()->environment(); qCDebug(androidRunWorkerLog) << "Environment variables for the app" << m_extraEnvVars.toStringList(); m_extraAppParams = runConfig->runnable().commandLineArguments; - if (auto aspect = runConfig->extraAspect(Constants::ANDROID_AMSTARTARGS)) + if (auto aspect = runConfig->aspect(Constants::ANDROID_AMSTARTARGS)) m_amStartExtraArgs = static_cast(aspect)->value().split(' '); - if (auto aspect = runConfig->extraAspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) { + if (auto aspect = runConfig->aspect(Constants::ANDROID_PRESTARTSHELLCMDLIST)) { for (const QString &shellCmd : static_cast(aspect)->value()) m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd)); } for (const QString &shellCmd : runner->recordedData(Constants::ANDROID_PRESTARTSHELLCMDLIST).toStringList()) m_beforeStartAdbCommands.append(QString("shell %1").arg(shellCmd)); - if (auto aspect = runConfig->extraAspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) { + if (auto aspect = runConfig->aspect(Constants::ANDROID_POSTFINISHSHELLCMDLIST)) { for (const QString &shellCmd : static_cast(aspect)->value()) m_afterFinishAdbCommands.append(QString("shell %1").arg(shellCmd)); } diff --git a/src/plugins/autotest/testrunconfiguration.h b/src/plugins/autotest/testrunconfiguration.h index d625afa28b8..f9110a8ece9 100644 --- a/src/plugins/autotest/testrunconfiguration.h +++ b/src/plugins/autotest/testrunconfiguration.h @@ -57,7 +57,7 @@ public: if (auto debuggable = dynamic_cast(config)) enableQuick = debuggable->mixedDebugging(); - if (auto debugAspect = extraAspect()) { + if (auto debugAspect = aspect()) { debugAspect->setUseQmlDebugger(enableQuick); ProjectExplorer::ProjectExplorerPlugin::instance()->updateRunActions(); } diff --git a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp index 1239c9045b0..14b957d5e4a 100644 --- a/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp +++ b/src/plugins/baremetal/baremetalcustomrunconfiguration.cpp @@ -58,7 +58,7 @@ const char *BareMetalCustomRunConfiguration::Id = "BareMetal"; bool BareMetalCustomRunConfiguration::isConfigured() const { - return !extraAspect()->executable().isEmpty(); + return !aspect()->executable().isEmpty(); } RunConfiguration::ConfigurationState diff --git a/src/plugins/baremetal/baremetaldebugsupport.cpp b/src/plugins/baremetal/baremetaldebugsupport.cpp index fdab85540c8..ab8783a446e 100644 --- a/src/plugins/baremetal/baremetaldebugsupport.cpp +++ b/src/plugins/baremetal/baremetaldebugsupport.cpp @@ -85,7 +85,7 @@ void BareMetalDebugSupport::start() { const auto rc = runControl()->runConfiguration(); QTC_ASSERT(rc, reportFailure(); return); - const auto exeAspect = rc->extraAspect(); + const auto exeAspect = rc->aspect(); QTC_ASSERT(exeAspect, reportFailure(); return); const QString bin = exeAspect->executable().toString(); @@ -124,7 +124,7 @@ void BareMetalDebugSupport::start() Runnable inferior; inferior.executable = bin; - if (auto aspect = rc->extraAspect()) + if (auto aspect = rc->aspect()) inferior.commandLineArguments = aspect->arguments(rc->macroExpander()); setInferior(inferior); setSymbolFile(bin); diff --git a/src/plugins/baremetal/baremetalrunconfiguration.cpp b/src/plugins/baremetal/baremetalrunconfiguration.cpp index 8cb2aa3a8c4..cdfa2ddca65 100644 --- a/src/plugins/baremetal/baremetalrunconfiguration.cpp +++ b/src/plugins/baremetal/baremetalrunconfiguration.cpp @@ -63,7 +63,7 @@ BareMetalRunConfiguration::BareMetalRunConfiguration(Target *target, Core::Id id void BareMetalRunConfiguration::updateTargetInformation() { const BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(buildKey()); - extraAspect()->setExecutable(bti.targetFilePath); + aspect()->setExecutable(bti.targetFilePath); emit enabledChanged(); } diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp index 28e8401d8ff..6b4d0b81629 100644 --- a/src/plugins/clangcodemodel/clangassistproposalitem.cpp +++ b/src/plugins/clangcodemodel/clangassistproposalitem.cpp @@ -27,6 +27,7 @@ #include "clangcompletionchunkstotextconverter.h" #include "clangfixitoperation.h" +#include "clangutils.h" #include #include @@ -34,10 +35,13 @@ #include #include +#include #include #include +#include #include +#include #include #include @@ -45,6 +49,7 @@ using namespace CPlusPlus; using namespace ClangBackEnd; +using namespace TextEditor; namespace ClangCodeModel { namespace Internal { @@ -73,7 +78,7 @@ bool ClangAssistProposalItem::implicitlyApplies() const return true; } -static QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInterface &manipulator, +static QString textUntilPreviousStatement(TextDocumentManipulatorInterface &manipulator, int startPosition) { static const QString stopCharacters(";{}#"); @@ -90,7 +95,7 @@ static QString textUntilPreviousStatement(TextEditor::TextDocumentManipulatorInt } // 7.3.3: using typename(opt) nested-name-specifier unqualified-id ; -static bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &manipulator, +static bool isAtUsingDeclaration(TextDocumentManipulatorInterface &manipulator, int basePosition) { SimpleLexer lexer; @@ -105,7 +110,7 @@ static bool isAtUsingDeclaration(TextEditor::TextDocumentManipulatorInterface &m if (lastToken.kind() != T_COLON_COLON) return false; - return Utils::contains(tokens, [](const Token &token) { + return ::Utils::contains(tokens, [](const Token &token) { return token.kind() == T_USING; }); } @@ -135,17 +140,17 @@ static QString methodDefinitionParameters(const CodeCompletionChunks &chunks) return result; } -void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface &manipulator, +void ClangAssistProposalItem::apply(TextDocumentManipulatorInterface &manipulator, int basePosition) const { const CodeCompletion ccr = firstCodeCompletion(); if (!ccr.requiredFixIts.empty()) { + // Important: Calculate shift before changing the document. + basePosition += fixItsShift(manipulator); + ClangFixItOperation fixItOperation(Utf8String(), ccr.requiredFixIts); fixItOperation.perform(); - - const int shift = fixItsShift(manipulator); - basePosition += shift; } QString textToBeInserted = m_text; @@ -175,8 +180,8 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface textToBeInserted = converter.text(); } else if (!ccr.text.isEmpty()) { - const TextEditor::CompletionSettings &completionSettings = - TextEditor::TextEditorSettings::instance()->completionSettings(); + const CompletionSettings &completionSettings = + TextEditorSettings::instance()->completionSettings(); const bool autoInsertBrackets = completionSettings.m_autoInsertBrackets; if (autoInsertBrackets && @@ -193,9 +198,9 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface QTextCursor cursor = manipulator.textCursorAt(basePosition); bool abandonParen = false; - if (Utils::Text::matchPreviousWord(manipulator, cursor, "&")) { - Utils::Text::moveToPrevChar(manipulator, cursor); - Utils::Text::moveToPrevChar(manipulator, cursor); + if (::Utils::Text::matchPreviousWord(manipulator, cursor, "&")) { + ::Utils::Text::moveToPrevChar(manipulator, cursor); + ::Utils::Text::moveToPrevChar(manipulator, cursor); const QChar prevChar = manipulator.characterAt(cursor.position()); cursor.setPosition(basePosition); abandonParen = QString("(;,{}").contains(prevChar); @@ -206,7 +211,7 @@ void ClangAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface if (!abandonParen && ccr.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) { const CodeCompletionChunk resultType = ccr.chunks.first(); QTC_ASSERT(resultType.kind == CodeCompletionChunk::ResultType, return;); - if (Utils::Text::matchPreviousWord(manipulator, cursor, resultType.text.toString())) { + if (::Utils::Text::matchPreviousWord(manipulator, cursor, resultType.text.toString())) { extraCharacters += methodDefinitionParameters(ccr.chunks); // To skip the next block. abandonParen = true; @@ -306,7 +311,7 @@ void ClangAssistProposalItem::setText(const QString &text) QString ClangAssistProposalItem::text() const { - return m_text + (requiresFixIts() ? fixItText() : QString()); + return m_text; } const QVector &ClangAssistProposalItem::firstCompletionFixIts() const @@ -314,39 +319,53 @@ const QVector &ClangAssistProposalItem::firstCompl return firstCodeCompletion().requiredFixIts; } -// FIXME: Indicate required fix-it without adding extra text. +std::pair fixItPositionsRange(const FixItContainer &fixIt, const QTextCursor &cursor) +{ + const QTextBlock startLine = cursor.document()->findBlockByNumber(fixIt.range.start.line - 1); + const QTextBlock endLine = cursor.document()->findBlockByNumber(fixIt.range.end.line - 1); + + const int fixItStartPos = ::Utils::Text::positionInText( + cursor.document(), + static_cast(fixIt.range.start.line), + Utils::cppEditorColumn(startLine, static_cast(fixIt.range.start.column))); + const int fixItEndPos = ::Utils::Text::positionInText( + cursor.document(), + static_cast(fixIt.range.end.line), + Utils::cppEditorColumn(endLine, static_cast(fixIt.range.end.column))); + return std::make_pair(fixItStartPos, fixItEndPos); +} + +static QString textReplacedByFixit(const FixItContainer &fixIt) +{ + TextEditorWidget *textEditorWidget = TextEditorWidget::currentTextEditorWidget(); + if (!textEditorWidget) + return QString(); + const std::pair fixItPosRange = fixItPositionsRange(fixIt, + textEditorWidget->textCursor()); + return textEditorWidget->textAt(fixItPosRange.first, + fixItPosRange.second - fixItPosRange.first); +} + QString ClangAssistProposalItem::fixItText() const { const FixItContainer &fixIt = firstCompletionFixIts().first(); - const SourceRangeContainer &range = fixIt.range; return QCoreApplication::translate("ClangCodeModel::ClangAssistProposalItem", - " (requires to correct [%1:%2-%3:%4] to \"%5\")") - .arg(range.start.line) - .arg(range.start.column) - .arg(range.end.line) - .arg(range.end.column) + "Requires to correct \"%1\" to \"%2\"") + .arg(textReplacedByFixit(fixIt)) .arg(fixIt.text.toString()); } -int ClangAssistProposalItem::fixItsShift( - const TextEditor::TextDocumentManipulatorInterface &manipulator) const +int ClangAssistProposalItem::fixItsShift(const TextDocumentManipulatorInterface &manipulator) const { const QVector &requiredFixIts = firstCompletionFixIts(); if (requiredFixIts.empty()) return 0; int shift = 0; - QTextCursor cursor = manipulator.textCursorAt(0); + const QTextCursor cursor = manipulator.textCursorAt(0); for (const FixItContainer &fixIt : requiredFixIts) { - const int fixItStartPos = Utils::Text::positionInText( - cursor.document(), - static_cast(fixIt.range.start.line), - static_cast(fixIt.range.start.column)); - const int fixItEndPos = Utils::Text::positionInText( - cursor.document(), - static_cast(fixIt.range.end.line), - static_cast(fixIt.range.end.column)); - shift += fixIt.text.toString().length() - (fixItEndPos - fixItStartPos); + const std::pair fixItPosRange = fixItPositionsRange(fixIt, cursor); + shift += fixIt.text.toString().length() - (fixItPosRange.second - fixItPosRange.first); } return shift; } @@ -425,10 +444,14 @@ QString ClangAssistProposalItem::detail() const detail += "
"; detail += CompletionChunksToTextConverter::convertToToolTipWithHtml( codeCompletion.chunks, codeCompletion.completionKind); + if (!codeCompletion.briefComment.isEmpty()) detail += "
" + codeCompletion.briefComment.toString(); } + if (requiresFixIts()) + detail += "

" + fixItText() + ""; + return detail; } diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp index 148ebb0ad48..6e535fb04a7 100644 --- a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp +++ b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp @@ -56,11 +56,7 @@ void ClangAssistProposalModel::sort(const QString &/*prefix*/) return static_cast(first->prefixMatch()) < static_cast(second->prefixMatch()); } - if (first->requiresFixIts() != second->requiresFixIts()) - return first->requiresFixIts() < second->requiresFixIts(); - return (first->order() > 0 - && (first->order() < second->order() - || (first->order() == second->order() && first->text() < second->text()))); + return false; }; // Keep the order for the items with the same priority and name. diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 843778e4bbe..e87135351db 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -51,8 +51,9 @@ #include #include -#include #include +#include +#include #include #include @@ -76,20 +77,18 @@ static void addAssistProposalItem(QList &items, item->appendCodeCompletion(codeCompletion); } +// Add the next CXXMethod or CXXConstructor which is the overload for another existing item. static void addFunctionOverloadAssistProposalItem(QList &items, AssistProposalItemInterface *sameItem, const ClangCompletionAssistInterface *interface, const CodeCompletion &codeCompletion, const QString &name) { - ClangBackEnd::CodeCompletionChunk resultType = codeCompletion.chunks.first(); auto *item = static_cast(sameItem); item->setHasOverloadsWithParameters(true); - if (resultType.kind != ClangBackEnd::CodeCompletionChunk::ResultType) { - // It's the constructor. + if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind) { + // It's the constructor, currently constructor definitions do not lead here. // CLANG-UPGRADE-CHECK: Can we get here with constructor definition? - if (!item->firstCodeCompletion().hasParameters) - item->removeFirstCodeCompletion(); item->appendCodeCompletion(codeCompletion); return; } @@ -98,15 +97,27 @@ static void addFunctionOverloadAssistProposalItem(QListposition()); cursor.movePosition(QTextCursor::StartOfWord); + const ClangBackEnd::CodeCompletionChunk resultType = codeCompletion.chunks.first(); if (::Utils::Text::matchPreviousWord(*interface->textEditorWidget(), cursor, resultType.text.toString())) { + // Function definition completion - do not merge completions together. addAssistProposalItem(items, codeCompletion, name); } else { item->appendCodeCompletion(codeCompletion); } } +// Check if they are both CXXMethod or CXXConstructor. +static bool isTheSameFunctionOverload(const CodeCompletion &completion, + const QString &name, + ClangAssistProposalItem *lastItem) +{ + return completion.hasParameters + && completion.completionKind == lastItem->firstCodeCompletion().completionKind + && lastItem->text() == name; +} + static QList toAssistProposalItems( const CodeCompletions &completions, const ClangCompletionAssistInterface *interface) @@ -117,8 +128,9 @@ static QList toAssistProposalItems( QList items; items.reserve(completions.size()); for (const CodeCompletion &codeCompletion : completions) { - if (codeCompletion.text.isEmpty()) // TODO: Make isValid()? - continue; + if (codeCompletion.text.isEmpty()) + continue; // It's an OverloadCandidate which has text but no typedText. + if (signalCompletion && codeCompletion.completionKind != CodeCompletion::SignalCompletionKind) continue; if (slotCompletion && codeCompletion.completionKind != CodeCompletion::SlotCompletionKind) @@ -128,34 +140,16 @@ static QList toAssistProposalItems( ? CompletionChunksToTextConverter::convertToName(codeCompletion.chunks) : codeCompletion.text.toString(); - if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind - || codeCompletion.completionKind == CodeCompletion::ClassCompletionKind) { - auto samePreviousConstructor - = std::find_if(items.begin(), - items.end(), - [&](const AssistProposalItemInterface *item) { - return item->text() == name - && static_cast(item)->firstCodeCompletion() - .completionKind == codeCompletion.completionKind; - }); - if (samePreviousConstructor == items.end()) { - addAssistProposalItem(items, codeCompletion, name); - } else if (codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind){ - addFunctionOverloadAssistProposalItem(items, *samePreviousConstructor, interface, - codeCompletion, name); - } - continue; - } - - if (!items.empty() && items.last()->text() == name) { - if ((codeCompletion.completionKind == CodeCompletion::FunctionCompletionKind - || codeCompletion.completionKind == CodeCompletion::FunctionDefinitionCompletionKind) - && codeCompletion.hasParameters) { + if (items.empty()) { + addAssistProposalItem(items, codeCompletion, name); + } else { + auto *lastItem = static_cast(items.last()); + if (isTheSameFunctionOverload(codeCompletion, name, lastItem)) { addFunctionOverloadAssistProposalItem(items, items.back(), interface, codeCompletion, name); + } else { + addAssistProposalItem(items, codeCompletion, name); } - } else { - addAssistProposalItem(items, codeCompletion, name); } } @@ -187,48 +181,14 @@ IAssistProposal *ClangCompletionAssistProcessor::perform(const AssistInterface * return startCompletionHelper(); // == 0 if results are calculated asynchronously } -static CodeCompletions filterFunctionSignatures(const CodeCompletions &completions) -{ - return ::Utils::filtered(completions, [](const CodeCompletion &completion) { - return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind; - }); -} - -static CodeCompletions filterConstructorSignatures(Utf8String textBefore, - const CodeCompletions &completions) -{ - const int prevStatementEnd = textBefore.lastIndexOf(";"); - if (prevStatementEnd != -1) - textBefore = textBefore.mid(prevStatementEnd + 1); - - return ::Utils::filtered(completions, [&textBefore](const CodeCompletion &completion) { - if (completion.completionKind != CodeCompletion::ConstructorCompletionKind) - return false; - const Utf8String type = completion.chunks.at(0).text; - return textBefore.indexOf(type) != -1; - }); -} - -void ClangCompletionAssistProcessor::handleAvailableCompletions( - const CodeCompletions &completions) +void ClangCompletionAssistProcessor::handleAvailableCompletions(const CodeCompletions &completions) { QTC_CHECK(m_completions.isEmpty()); - if (m_sentRequestType == FunctionHintCompletion){ - CodeCompletions functionSignatures; - if (m_completionOperator == T_LPAREN) { - functionSignatures = filterFunctionSignatures(completions); - } else { - const QTextBlock block = m_interface->textDocument()->findBlock( - m_interface->position()); - const QString textBefore = block.text().left( - m_interface->position() - block.position()); - - functionSignatures = filterConstructorSignatures(textBefore, completions); - } - - if (!functionSignatures.isEmpty()) { - setAsyncProposalAvailable(createFunctionHintProposal(functionSignatures)); + if (m_sentRequestType == FunctionHintCompletion) { + const CodeCompletion &firstCompletion = completions.front(); + if (firstCompletion.completionKind == CodeCompletion::FunctionOverloadCompletionKind) { + setAsyncProposalAvailable(createFunctionHintProposal(completions)); return; } // else: Proceed with a normal completion in case: diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp index 2d74d7f4ef1..971c0551749 100644 --- a/src/plugins/clangcodemodel/clangutils.cpp +++ b/src/plugins/clangcodemodel/clangutils.cpp @@ -155,8 +155,18 @@ int clangColumn(const QTextBlock &line, int cppEditorColumn) // (2) The return value is the column in Clang which is the utf8 byte offset from the beginning // of the line. // Here we convert column from (1) to (2). - // '+ 1' is for 1-based columns - return line.text().left(cppEditorColumn).toUtf8().size() + 1; + // '- 1' and '+ 1' are because of 1-based columns + return line.text().left(cppEditorColumn - 1).toUtf8().size() + 1; +} + +int cppEditorColumn(const QTextBlock &line, int clangColumn) +{ + // (1) clangColumn is the column in Clang which is the utf8 byte offset from the beginning + // of the line. + // (2) The return value is the actual column shown by CppEditor. + // Here we convert column from (1) to (2). + // '- 1' and '+ 1' are because of 1-based columns + return QString::fromUtf8(line.text().toUtf8().left(clangColumn - 1)).size() + 1; } ::Utils::CodeModelIcon::Type iconTypeForToken(const ClangBackEnd::TokenInfoContainer &token) diff --git a/src/plugins/clangcodemodel/clangutils.h b/src/plugins/clangcodemodel/clangutils.h index 883dfcdf29e..956f1dee4aa 100644 --- a/src/plugins/clangcodemodel/clangutils.h +++ b/src/plugins/clangcodemodel/clangutils.h @@ -57,7 +57,8 @@ CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath); CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &filePath); bool isProjectPartLoaded(const CppTools::ProjectPart::Ptr projectPart); QString projectPartIdForFile(const QString &filePath); -int clangColumn(const QTextBlock &lineText, int cppEditorColumn); +int clangColumn(const QTextBlock &line, int cppEditorColumn); +int cppEditorColumn(const QTextBlock &line, int clangColumn); QString diagnosticCategoryPrefixRemoved(const QString &text); diff --git a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp index cb618e06579..3872fe90f4e 100644 --- a/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp @@ -98,11 +98,11 @@ QString CMakeRunConfiguration::disabledReason() const void CMakeRunConfiguration::updateTargetInformation() { BuildTargetInfo bti = target()->applicationTargets().buildTargetInfo(buildKey()); - extraAspect()->setExecutable(bti.targetFilePath); - extraAspect()->setDefaultWorkingDirectory(bti.workingDirectory); - extraAspect()->buildEnvironmentHasChanged(); + aspect()->setExecutable(bti.targetFilePath); + aspect()->setDefaultWorkingDirectory(bti.workingDirectory); + aspect()->buildEnvironmentHasChanged(); - auto terminalAspect = extraAspect(); + auto terminalAspect = aspect(); if (!terminalAspect->isUserSet()) terminalAspect->setUseTerminal(bti.usesTerminal); } diff --git a/src/plugins/cmakeprojectmanager/treescanner.cpp b/src/plugins/cmakeprojectmanager/treescanner.cpp index 877491a9de7..7a25e9e2668 100644 --- a/src/plugins/cmakeprojectmanager/treescanner.cpp +++ b/src/plugins/cmakeprojectmanager/treescanner.cpp @@ -69,10 +69,7 @@ bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory) m_scanFuture = fi->future(); m_futureWatcher.setFuture(m_scanFuture); - if (m_versionControls.isEmpty()) - m_versionControls = Core::VcsManager::versionControls(); - - Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory, m_versionControls); }); + Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); }); return true; } @@ -150,14 +147,12 @@ FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Uti } void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory, - const FileFilter &filter, const FileTypeFactory &factory, - QList &versionControls) + const FileFilter &filter, const FileTypeFactory &factory) { std::unique_ptr fip(fi); fip->reportStarted(); - Result nodes - = FileNode::scanForFilesWithVersionControls( + Result nodes = FileNode::scanForFiles( directory, [&filter, &factory](const Utils::FileName &fn) -> FileNode * { const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString()); @@ -172,7 +167,7 @@ void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& direc type = factory(mimeType, fn); return new FileNode(fn, type, false); - }, versionControls, fip.get()); + }, fip.get()); Utils::sort(nodes, ProjectExplorer::Node::sortByPath); diff --git a/src/plugins/cmakeprojectmanager/treescanner.h b/src/plugins/cmakeprojectmanager/treescanner.h index 146076f1f2a..b377ec63a49 100644 --- a/src/plugins/cmakeprojectmanager/treescanner.h +++ b/src/plugins/cmakeprojectmanager/treescanner.h @@ -88,8 +88,7 @@ signals: private: static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory, - const FileFilter &filter, const FileTypeFactory &factory, - QList &versionControls); + const FileFilter &filter, const FileTypeFactory &factory); private: FileFilter m_filter; @@ -97,7 +96,6 @@ private: FutureWatcher m_futureWatcher; Future m_scanFuture; - QList m_versionControls; }; } // namespace Internal diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index c5004b80242..afc777be1a8 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -1682,9 +1682,8 @@ namespace { class ConvertToCamelCaseOp: public CppQuickFixOperation { public: - ConvertToCamelCaseOp(const CppQuickFixInterface &interface, int priority, - const QString &newName) - : CppQuickFixOperation(interface, priority) + ConvertToCamelCaseOp(const CppQuickFixInterface &interface, const QString &newName) + : CppQuickFixOperation(interface, -1) , m_name(newName) { setDescription(QApplication::translate("CppTools::QuickFix", "Convert to Camel Case")); @@ -1744,7 +1743,7 @@ void ConvertToCamelCase::match(const CppQuickFixInterface &interface, QuickFixOp return; for (int i = 1; i < newName.length() - 1; ++i) { if (ConvertToCamelCaseOp::isConvertibleUnderscore(newName, i)) { - result << new ConvertToCamelCaseOp(interface, path.size() - 1, newName); + result << new ConvertToCamelCaseOp(interface, newName); return; } } @@ -3303,9 +3302,17 @@ public: // Write class qualification, if any. if (matchingClass) { - const Name *name = rewriteName(matchingClass->name(), &env, control); - funcDef.append(printer.prettyName(name)); - funcDef.append(QLatin1String("::")); + Class *current = matchingClass; + QVector classes{matchingClass->name()}; + while (current->enclosingScope()->asClass()) { + current = current->enclosingScope()->asClass(); + classes.prepend(current->name()); + } + for (const Name *n : classes) { + const Name *name = rewriteName(n, &env, control); + funcDef.append(printer.prettyName(name)); + funcDef.append(QLatin1String("::")); + } } // Write the extracted function itself and its call. diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index 29339121fa3..7acf8550b38 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -906,9 +906,9 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer if (runConfig) { m_runParameters.displayName = runConfig->displayName(); - if (auto symbolsAspect = runConfig->extraAspect()) + if (auto symbolsAspect = runConfig->aspect()) m_runParameters.symbolFile = symbolsAspect->value(); - if (auto terminalAspect = runConfig->extraAspect()) + if (auto terminalAspect = runConfig->aspect()) m_runParameters.useTerminal = terminalAspect->useTerminal(); } @@ -924,7 +924,7 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit)) m_runParameters.qtPackageSourceLocation = qtVersion->qtPackageSourcePath().toString(); - if (auto aspect = runConfig ? runConfig->extraAspect() : nullptr) { + if (auto aspect = runConfig ? runConfig->aspect() : nullptr) { if (!aspect->useCppDebugger()) m_runParameters.cppEngineType = NoEngineType; m_runParameters.isQmlDebugging = aspect->useQmlDebugger(); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index fe370f45235..dbbb45a16a4 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -3385,8 +3385,14 @@ GitRemote::GitRemote(const QString &url) // Check for local remotes (refer to the root or relative path) // On Windows, local paths typically starts with : + auto startsWithWindowsDrive = [](const QString &url) { + if (!HostOsInfo::isWindowsHost() || url.size() < 2) + return false; + const QChar drive = url.at(0).toLower(); + return drive >= 'a' && drive <= 'z' && url.at(1) == ':'; + }; if (url.startsWith("file://") || url.startsWith('/') || url.startsWith('.') - || (HostOsInfo::isWindowsHost() && url[1] == ':')) { + || startsWithWindowsDrive(url)) { protocol = "file"; path = QDir::fromNativeSeparators(url.startsWith("file://") ? url.mid(7) : url); isValid = QDir(path).exists() || QDir(path + ".git").exists(); diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp index dc0607cbb73..e36a22239e7 100644 --- a/src/plugins/git/gitversioncontrol.cpp +++ b/src/plugins/git/gitversioncontrol.cpp @@ -82,7 +82,10 @@ bool GitVersionControl::isVcsFileOrDirectory(const Utils::FileName &fileName) co return false; if (fileName.toFileInfo().isDir()) return true; - return QFile(fileName.toString()).readLine().startsWith("gitdir: "); + QFile file(fileName.toString()); + if (!file.open(QFile::ReadOnly)) + return false; + return file.read(8) == "gitdir: "; } bool GitVersionControl::isConfigured() const diff --git a/src/plugins/help/helpmanager.cpp b/src/plugins/help/helpmanager.cpp index 34be168bcb0..3dbbbd65c72 100644 --- a/src/plugins/help/helpmanager.cpp +++ b/src/plugins/help/helpmanager.cpp @@ -84,11 +84,6 @@ struct HelpManagerPrivate static HelpManager *m_instance = nullptr; static HelpManagerPrivate *d = nullptr; -static const char linksForKeyQuery[] = "SELECT d.Title, f.Name, e.Name, " - "d.Name, a.Anchor FROM IndexTable a, FileNameTable d, FolderTable e, " - "NamespaceTable f WHERE a.FileId=d.FileId AND d.FolderId=e.Id AND " - "a.NamespaceId=f.Id AND a.Name='%1'"; - // -- DbCleaner struct DbCleaner @@ -227,66 +222,29 @@ QSet HelpManager::userDocumentationPaths() return d->m_userRegisteredFiles; } -static QUrl buildQUrl(const QString &ns, const QString &folder, - const QString &relFileName, const QString &anchor) -{ - QUrl url; - url.setScheme(QLatin1String("qthelp")); - url.setAuthority(ns); - url.setPath(QLatin1Char('/') + folder + QLatin1Char('/') + relFileName); - url.setFragment(anchor); - return url; -} - // This should go into Qt 4.8 once we start using it for Qt Creator QMap HelpManager::linksForKeyword(const QString &key) { - QMap links; - QTC_ASSERT(!d->m_needsSetup, return links); - - const QLatin1String sqlite("QSQLITE"); - const QLatin1String name("HelpManager::linksForKeyword"); - - DbCleaner cleaner(name); - QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); - if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { - const QStringList ®isteredDocs = d->m_helpEngine->registeredDocumentations(); - for (const QString &nameSpace : registeredDocs) { - db.setDatabaseName(d->m_helpEngine->documentationFileName(nameSpace)); - if (db.open()) { - QSqlQuery query = QSqlQuery(db); - query.setForwardOnly(true); - query.exec(QString::fromLatin1(linksForKeyQuery).arg(key)); - while (query.next()) { - QString title = query.value(0).toString(); - if (title.isEmpty()) // generate a title + corresponding path - title = key + QLatin1String(" : ") + query.value(3).toString(); - links.insertMulti(title, buildQUrl(query.value(1).toString(), - query.value(2).toString(), query.value(3).toString(), - query.value(4).toString())); - } - } - } - } - return links; + QTC_ASSERT(!d->m_needsSetup, return {}); + return d->m_helpEngine->linksForKeyword(key); } QMap HelpManager::linksForIdentifier(const QString &id) { QMap empty; - QTC_ASSERT(!d->m_needsSetup, return empty); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->linksForIdentifier(id); } QUrl HelpManager::findFile(const QUrl &url) { - QTC_ASSERT(!d->m_needsSetup, return QUrl()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->findFile(url); } QByteArray HelpManager::fileData(const QUrl &url) { - QTC_ASSERT(!d->m_needsSetup, return QByteArray()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->fileData(url); } @@ -297,19 +255,19 @@ void HelpManager::handleHelpRequest(const QUrl &url, Core::HelpManager::HelpView QStringList HelpManager::registeredNamespaces() { - QTC_ASSERT(!d->m_needsSetup, return QStringList()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->registeredDocumentations(); } QString HelpManager::namespaceFromFile(const QString &file) { - QTC_ASSERT(!d->m_needsSetup, return QString()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->namespaceName(file); } QString HelpManager::fileFromNamespace(const QString &nameSpace) { - QTC_ASSERT(!d->m_needsSetup, return QString()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->documentationFileName(nameSpace); } @@ -325,13 +283,13 @@ void HelpManager::setCustomValue(const QString &key, const QVariant &value) QVariant HelpManager::customValue(const QString &key, const QVariant &value) { - QTC_ASSERT(!d->m_needsSetup, return QVariant()); + QTC_ASSERT(!d->m_needsSetup, return {}); return d->m_helpEngine->customValue(key, value); } HelpManager::Filters HelpManager::filters() { - QTC_ASSERT(!d->m_needsSetup, return Filters()); + QTC_ASSERT(!d->m_needsSetup, return {}); Filters filters; const QStringList &customFilters = d->m_helpEngine->customFilters(); @@ -342,12 +300,12 @@ HelpManager::Filters HelpManager::filters() HelpManager::Filters HelpManager::fixedFilters() { - Filters fixedFilters; - QTC_ASSERT(!d->m_needsSetup, return fixedFilters); + QTC_ASSERT(!d->m_needsSetup, return {}); const QLatin1String sqlite("QSQLITE"); const QLatin1String name("HelpManager::fixedCustomFilters"); + Filters fixedFilters; DbCleaner cleaner(name); QSqlDatabase db = QSqlDatabase::addDatabase(sqlite, name); if (db.driver() && db.driver()->lastError().type() == QSqlError::NoError) { @@ -370,7 +328,7 @@ HelpManager::Filters HelpManager::fixedFilters() HelpManager::Filters HelpManager::userDefinedFilters() { - QTC_ASSERT(!d->m_needsSetup, return Filters()); + QTC_ASSERT(!d->m_needsSetup, return {}); Filters all = filters(); const Filters &fixed = fixedFilters(); diff --git a/src/plugins/ios/iosrunconfiguration.cpp b/src/plugins/ios/iosrunconfiguration.cpp index 182a1dea713..8fd19bdbd5f 100644 --- a/src/plugins/ios/iosrunconfiguration.cpp +++ b/src/plugins/ios/iosrunconfiguration.cpp @@ -139,7 +139,7 @@ void IosRunConfiguration::updateDisplayNames() setDefaultDisplayName(tr("Run on %1").arg(devName)); setDisplayName(tr("Run %1 on %2").arg(applicationName()).arg(devName)); - extraAspect()->setExecutable(localExecutable()); + aspect()->setExecutable(localExecutable()); } void IosRunConfiguration::updateEnabledState() diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index 07918f787e4..dc6d222e0f8 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -100,7 +100,7 @@ IosRunner::IosRunner(RunControl *runControl) stopRunningRunControl(runControl); auto runConfig = qobject_cast(runControl->runConfiguration()); m_bundleDir = runConfig->bundleDirectory().toString(); - m_arguments = runConfig->extraAspect()->arguments(runConfig->macroExpander()); + m_arguments = runConfig->aspect()->arguments(runConfig->macroExpander()); m_device = DeviceKitInformation::device(runConfig->target()->kit()); m_deviceType = runConfig->deviceType(); } @@ -387,7 +387,7 @@ IosQmlProfilerSupport::IosQmlProfilerSupport(RunControl *runControl) Runnable runnable; runnable.executable = iosRunConfig->localExecutable().toUserOutput(); runnable.commandLineArguments = - iosRunConfig->extraAspect()->arguments(iosRunConfig->macroExpander()); + iosRunConfig->aspect()->arguments(iosRunConfig->macroExpander()); runControl->setDisplayName(iosRunConfig->applicationName()); runControl->setRunnable(runnable); diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index 99fd84afa2d..50a903044f3 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -113,11 +113,9 @@ void NimProject::collectProjectFiles() m_lastProjectScan.start(); QTC_ASSERT(!m_futureWatcher.future().isRunning(), return); FileName prjDir = projectDirectory(); - const QList versionControls = Core::VcsManager::versionControls(); - QFuture> future = Utils::runAsync([prjDir, versionControls] { - return FileNode::scanForFilesWithVersionControls( - prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); }, - versionControls); + QFuture> future = Utils::runAsync([prjDir] { + return FileNode::scanForFiles( + prjDir, [](const FileName &fn) { return new FileNode(fn, FileType::Source, false); }); }); m_futureWatcher.setFuture(future); Core::ProgressManager::addTask(future, tr("Scanning for Nim files"), "Nim.Project.Scan"); @@ -144,7 +142,7 @@ void NimProject::updateProject() m_files = transform(fileNodes, [](const std::unique_ptr &fn) { return fn->filePath().toString(); }); - Utils::sort(m_files, [](const QString &a, const QString &b) { return a < b; }); + Utils::sort(m_files); if (oldFiles == m_files) return; diff --git a/src/plugins/nim/project/nimrunconfiguration.cpp b/src/plugins/nim/project/nimrunconfiguration.cpp index 21c6d50779f..c27cb75b542 100644 --- a/src/plugins/nim/project/nimrunconfiguration.cpp +++ b/src/plugins/nim/project/nimrunconfiguration.cpp @@ -67,9 +67,9 @@ void NimRunConfiguration::updateConfiguration() QTC_ASSERT(buildConfiguration, return); setActiveBuildConfiguration(buildConfiguration); const QFileInfo outFileInfo = buildConfiguration->outFilePath().toFileInfo(); - extraAspect()->setExecutable(FileName::fromString(outFileInfo.absoluteFilePath())); + aspect()->setExecutable(FileName::fromString(outFileInfo.absoluteFilePath())); const QString workingDirectory = outFileInfo.absoluteDir().absolutePath(); - extraAspect()->setDefaultWorkingDirectory(FileName::fromString(workingDirectory)); + aspect()->setDefaultWorkingDirectory(FileName::fromString(workingDirectory)); } void NimRunConfiguration::setActiveBuildConfiguration(NimBuildConfiguration *activeBuildConfiguration) diff --git a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp index 3689deb50c6..1c2b315095c 100644 --- a/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp +++ b/src/plugins/projectexplorer/customexecutablerunconfiguration.cpp @@ -94,7 +94,7 @@ private: CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc) : QDialog(Core::ICore::dialogParent()), m_rc(rc), - m_workingDirectory(rc->extraAspect()) + m_workingDirectory(rc->aspect()) { auto vbox = new QVBoxLayout(this); vbox->addWidget(new QLabel(tr("Could not find the executable, please specify one."))); @@ -121,21 +121,21 @@ CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc) m_executableChooser = new PathChooser(this); m_executableChooser->setHistoryCompleter("Qt.CustomExecutable.History"); m_executableChooser->setExpectedKind(PathChooser::ExistingCommand); - m_executableChooser->setPath(rc->extraAspect()->executable().toString()); + m_executableChooser->setPath(rc->aspect()->executable().toString()); layout->addRow(tr("Executable:"), m_executableChooser); connect(m_executableChooser, &PathChooser::rawPathChanged, this, &CustomExecutableDialog::changed); - copyAspect(rc->extraAspect(), &m_arguments); + copyAspect(rc->aspect(), &m_arguments); m_arguments.addToConfigurationLayout(layout); - copyAspect(rc->extraAspect(), &m_workingDirectory); + copyAspect(rc->aspect(), &m_workingDirectory); m_workingDirectory.addToConfigurationLayout(layout); - copyAspect(rc->extraAspect(), &m_terminal); + copyAspect(rc->aspect(), &m_terminal); m_terminal.addToConfigurationLayout(layout); - auto enviromentAspect = rc->extraAspect(); + auto enviromentAspect = rc->aspect(); connect(enviromentAspect, &EnvironmentAspect::environmentChanged, this, &CustomExecutableDialog::environmentWasChanged); environmentWasChanged(); @@ -146,10 +146,10 @@ CustomExecutableDialog::CustomExecutableDialog(RunConfiguration *rc) void CustomExecutableDialog::accept() { auto executable = FileName::fromString(m_executableChooser->path()); - m_rc->extraAspect()->setExecutable(executable); - copyAspect(&m_arguments, m_rc->extraAspect()); - copyAspect(&m_workingDirectory, m_rc->extraAspect()); - copyAspect(&m_terminal, m_rc->extraAspect()); + m_rc->aspect()->setExecutable(executable); + copyAspect(&m_arguments, m_rc->aspect()); + copyAspect(&m_workingDirectory, m_rc->aspect()); + copyAspect(&m_terminal, m_rc->aspect()); QDialog::accept(); } @@ -168,7 +168,7 @@ bool CustomExecutableDialog::event(QEvent *event) void CustomExecutableDialog::environmentWasChanged() { - auto aspect = m_rc->extraAspect(); + auto aspect = m_rc->aspect(); QTC_ASSERT(aspect, return); m_executableChooser->setEnvironment(aspect->environment()); } @@ -242,7 +242,7 @@ void CustomExecutableRunConfiguration::configurationDialogFinished() QString CustomExecutableRunConfiguration::rawExecutable() const { - return extraAspect()->executable().toString(); + return aspect()->executable().toString(); } bool CustomExecutableRunConfiguration::isConfigured() const @@ -253,12 +253,12 @@ bool CustomExecutableRunConfiguration::isConfigured() const Runnable CustomExecutableRunConfiguration::runnable() const { FileName workingDirectory = - extraAspect()->workingDirectory(macroExpander()); + aspect()->workingDirectory(macroExpander()); Runnable r; - r.executable = extraAspect()->executable().toString(); - r.commandLineArguments = extraAspect()->arguments(macroExpander()); - r.environment = extraAspect()->environment(); + r.executable = aspect()->executable().toString(); + r.commandLineArguments = aspect()->arguments(macroExpander()); + r.environment = aspect()->environment(); r.workingDirectory = workingDirectory.toString(); r.device = DeviceManager::instance()->defaultDevice(Constants::DESKTOP_DEVICE_TYPE); diff --git a/src/plugins/projectexplorer/projectconfiguration.cpp b/src/plugins/projectexplorer/projectconfiguration.cpp index a78f5624f39..fafa53af3e2 100644 --- a/src/plugins/projectexplorer/projectconfiguration.cpp +++ b/src/plugins/projectexplorer/projectconfiguration.cpp @@ -154,7 +154,7 @@ bool ProjectConfiguration::fromMap(const QVariantMap &map) return true; } -ProjectConfigurationAspect *ProjectConfiguration::extraAspect(Core::Id id) const +ProjectConfigurationAspect *ProjectConfiguration::aspect(Core::Id id) const { return Utils::findOrDefault(m_aspects, Utils::equal(&ProjectConfigurationAspect::id, id)); } diff --git a/src/plugins/projectexplorer/projectconfiguration.h b/src/plugins/projectexplorer/projectconfiguration.h index 9e72ce0cb8d..492f19467c6 100644 --- a/src/plugins/projectexplorer/projectconfiguration.h +++ b/src/plugins/projectexplorer/projectconfiguration.h @@ -126,9 +126,9 @@ public: const QList aspects() const { return m_aspects; } - ProjectConfigurationAspect *extraAspect(Core::Id id) const; + ProjectConfigurationAspect *aspect(Core::Id id) const; - template T *extraAspect() const + template T *aspect() const { for (ProjectConfigurationAspect *aspect : m_aspects) if (T *result = qobject_cast(aspect)) diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index b2fc067de8c..8d0a9dd7459 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -390,15 +390,15 @@ static QList scanForFilesRecursively(const Utils::FileName &director } QList -FileNode::scanForFilesWithVersionControls(const Utils::FileName &directory, - const std::function factory, - const QList &versionControls, - QFutureInterface> *future) +FileNode::scanForFiles(const Utils::FileName &directory, + const std::function factory, + QFutureInterface> *future) { QSet visited; if (future) future->setProgressRange(0, 1000000); - return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, versionControls); + return scanForFilesRecursively(directory, factory, visited, future, 0.0, 1000000.0, + Core::VcsManager::versionControls()); } bool FileNode::supportsAction(ProjectAction action, const Node *node) const diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index 909be008d9e..8f8f9fd1bf0 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -36,7 +36,6 @@ #include namespace Utils { class MimeType; } -namespace Core { class IVersionControl; } namespace ProjectExplorer { @@ -191,10 +190,9 @@ public: const FileNode *asFileNode() const final { return this; } static QList - scanForFilesWithVersionControls(const Utils::FileName &directory, - const std::function factory, - const QList &versionControls, - QFutureInterface> *future = nullptr); + scanForFiles(const Utils::FileName &directory, + const std::function factory, + QFutureInterface> *future = nullptr); bool supportsAction(ProjectAction action, const Node *node) const override; private: diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index afb4b6d9819..32dd8e460b5 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -193,7 +193,7 @@ RunConfiguration::RunConfiguration(Target *target, Core::Id id) }); expander->registerPrefix("CurrentRun:Env", tr("Variables in the current run environment"), [this](const QString &var) { - const auto envAspect = extraAspect(); + const auto envAspect = aspect(); return envAspect ? envAspect->environment().value(var) : QString(); }); expander->registerVariable(Constants::VAR_CURRENTRUN_NAME, @@ -224,6 +224,8 @@ QWidget *RunConfiguration::createConfigurationWidget() { auto widget = new QWidget; auto formLayout = new QFormLayout(widget); + formLayout->setMargin(0); + formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); for (ProjectConfigurationAspect *aspect : m_aspects) { if (aspect->isVisible()) @@ -232,7 +234,10 @@ QWidget *RunConfiguration::createConfigurationWidget() Core::VariableChooser::addSupportForChildWidgets(widget, macroExpander()); - return wrapWidget(widget); + auto detailsWidget = new Utils::DetailsWidget; + detailsWidget->setState(DetailsWidget::NoSummary); + detailsWidget->setWidget(widget); + return detailsWidget; } void RunConfiguration::updateEnabledState() @@ -282,18 +287,6 @@ BuildConfiguration *RunConfiguration::activeBuildConfiguration() const return target()->activeBuildConfiguration(); } -QWidget *RunConfiguration::wrapWidget(QWidget *inner) const -{ - auto detailsWidget = new Utils::DetailsWidget; - detailsWidget->setState(DetailsWidget::NoSummary); - detailsWidget->setWidget(inner); - if (auto fl = qobject_cast(inner->layout())){ - fl->setMargin(0); - fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); - } - return detailsWidget; -} - Target *RunConfiguration::target() const { return static_cast(parent()); @@ -383,14 +376,14 @@ bool RunConfiguration::fromMap(const QVariantMap &map) Runnable RunConfiguration::runnable() const { Runnable r; - if (auto aspect = extraAspect()) - r.executable = aspect->executable().toString(); - if (auto aspect = extraAspect()) - r.commandLineArguments = aspect->arguments(macroExpander()); - if (auto aspect = extraAspect()) - r.workingDirectory = aspect->workingDirectory(macroExpander()).toString(); - if (auto aspect = extraAspect()) - r.environment = aspect->environment(); + if (auto executableAspect = aspect()) + r.executable = executableAspect->executable().toString(); + if (auto argumentsAspect = aspect()) + r.commandLineArguments = argumentsAspect->arguments(macroExpander()); + if (auto workingDirectoryAspect = aspect()) + r.workingDirectory = workingDirectoryAspect->workingDirectory(macroExpander()).toString(); + if (auto environmentAspect = aspect()) + r.environment = environmentAspect->environment(); return r; } @@ -1563,7 +1556,7 @@ SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl) m_runnable = runControl->runnable(); // Default value. Can be overridden using setRunnable. m_device = runControl->device(); // Default value. Can be overridden using setDevice. if (auto runConfig = runControl->runConfiguration()) { - if (auto terminalAspect = runConfig->extraAspect()) + if (auto terminalAspect = runConfig->aspect()) m_useTerminal = terminalAspect->useTerminal(); } } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 33c72a9654c..9a973b42ebb 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -185,8 +185,8 @@ public: template T *currentSettings(Core::Id id) const { - if (auto aspect = qobject_cast(extraAspect(id))) - return qobject_cast(aspect->currentSettings()); + if (auto a = qobject_cast(aspect(id))) + return qobject_cast(a->currentSettings()); return nullptr; } @@ -205,7 +205,6 @@ protected: /// convenience function to get current build configuration. BuildConfiguration *activeBuildConfiguration() const; - QWidget *wrapWidget(QWidget *inner) const; template void setOutputFormatter() { diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index f728f6bbc65..5dd91d7067c 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -113,6 +113,10 @@ public: bool showInSimpleTree() const override; QString addFileFilter() const override; + bool supportsAction(ProjectAction action, const Node *node) const override; + bool addFiles(const QStringList &filePaths, QStringList *) override; + bool removeFiles(const QStringList &filePaths, QStringList *) override; + bool deleteFiles(const QStringList &) override; bool renameFile(const QString &filePath, const QString &newFilePath) override; private: @@ -237,9 +241,9 @@ private: Runnable runnable() const final; bool supportsDebugger() const { return true; } - QString mainScript() const { return extraAspect()->value(); } - QString arguments() const { return extraAspect()->arguments(macroExpander()); } - QString interpreter() const { return extraAspect()->value(); } + QString mainScript() const { return aspect()->value(); } + QString arguments() const { return aspect()->arguments(macroExpander()); } + QString interpreter() const { return aspect()->value(); } void updateTargetInformation(); }; @@ -279,7 +283,7 @@ void PythonRunConfiguration::updateTargetInformation() const BuildTargetInfo bti = buildTargetInfo(); const QString script = bti.targetFilePath.toString(); setDefaultDisplayName(tr("Run %1").arg(script)); - extraAspect()->setValue(script); + aspect()->setValue(script); } Runnable PythonRunConfiguration::runnable() const @@ -287,9 +291,9 @@ Runnable PythonRunConfiguration::runnable() const Runnable r; QtcProcess::addArg(&r.commandLineArguments, mainScript()); QtcProcess::addArgs(&r.commandLineArguments, - extraAspect()->arguments(macroExpander())); - r.executable = extraAspect()->value(); - r.environment = extraAspect()->environment(); + aspect()->arguments(macroExpander())); + r.executable = aspect()->value(); + r.environment = aspect()->environment(); return r; } @@ -312,11 +316,13 @@ PythonProject::PythonProject(const FileName &fileName) : setDisplayName(fileName.toFileInfo().completeBaseName()); } -static QStringList readLines(const QString &absoluteFileName) +static QStringList readLines(const Utils::FileName &projectFile) { - QStringList lines; + const QString projectFileName = projectFile.fileName(); + QSet visited = { projectFileName }; + QStringList lines = { projectFileName }; - QFile file(absoluteFileName); + QFile file(projectFile.toString()); if (file.open(QFile::ReadOnly)) { QTextStream stream(&file); @@ -324,8 +330,10 @@ static QStringList readLines(const QString &absoluteFileName) QString line = stream.readLine(); if (line.isNull()) break; - + if (visited.contains(line)) + continue; lines.append(line); + visited.insert(line); } } @@ -362,14 +370,6 @@ bool PythonProject::addFiles(const QStringList &filePaths) foreach (const QString &filePath, filePaths) newList.append(baseDir.relativeFilePath(filePath)); - QSet toAdd; - - foreach (const QString &filePath, filePaths) { - QString directory = QFileInfo(filePath).absolutePath(); - if (!toAdd.contains(directory)) - toAdd << directory; - } - bool result = saveRawList(newList, projectFilePath().toString()); refresh(); @@ -392,7 +392,7 @@ bool PythonProject::removeFiles(const QStringList &filePaths) bool PythonProject::setFiles(const QStringList &filePaths) { QStringList newList; - QDir baseDir(projectFilePath().toString()); + QDir baseDir(projectDirectory().toString()); foreach (const QString &filePath, filePaths) newList.append(baseDir.relativeFilePath(filePath)); @@ -407,7 +407,7 @@ bool PythonProject::renameFile(const QString &filePath, const QString &newFilePa if (i != m_rawListEntries.end()) { int index = newList.indexOf(i.value()); if (index != -1) { - QDir baseDir(projectFilePath().toString()); + QDir baseDir(projectDirectory().toString()); newList.replace(index, baseDir.relativeFilePath(newFilePath)); } } @@ -418,8 +418,7 @@ bool PythonProject::renameFile(const QString &filePath, const QString &newFilePa void PythonProject::parseProject() { m_rawListEntries.clear(); - m_rawFileList = readLines(projectFilePath().toString()); - m_rawFileList << projectFilePath().fileName(); + m_rawFileList = readLines(projectFilePath()); m_files = processEntries(m_rawFileList, &m_rawListEntries); } @@ -581,6 +580,37 @@ QString PythonProjectNode::addFileFilter() const return QLatin1String("*.py"); } +bool PythonProjectNode::supportsAction(ProjectAction action, const Node *node) const +{ + switch (node->nodeType()) { + case NodeType::File: + return action == ProjectAction::Rename + || action == ProjectAction::RemoveFile; + case NodeType::Folder: + case NodeType::Project: + return action == ProjectAction::AddNewFile + || action == ProjectAction::RemoveFile + || action == ProjectAction::AddExistingFile; + default: + return ProjectNode::supportsAction(action, node); + } +} + +bool PythonProjectNode::addFiles(const QStringList &filePaths, QStringList *) +{ + return m_project->addFiles(filePaths); +} + +bool PythonProjectNode::removeFiles(const QStringList &filePaths, QStringList *) +{ + return m_project->removeFiles(filePaths); +} + +bool PythonProjectNode::deleteFiles(const QStringList &) +{ + return true; +} + bool PythonProjectNode::renameFile(const QString &filePath, const QString &newFilePath) { return m_project->renameFile(filePath, newFilePath); diff --git a/src/plugins/qbsprojectmanager/qbskitinformation.cpp b/src/plugins/qbsprojectmanager/qbskitinformation.cpp index 6d78c09d090..95242e5e37a 100644 --- a/src/plugins/qbsprojectmanager/qbskitinformation.cpp +++ b/src/plugins/qbsprojectmanager/qbskitinformation.cpp @@ -30,11 +30,11 @@ #include #include +#include #include #include -#include #include using namespace ProjectExplorer; @@ -48,7 +48,7 @@ class ConfigWidget final : public KitConfigWidget public: ConfigWidget(Kit *kit, const KitInformation *kitInfo) : KitConfigWidget(kit, kitInfo), - m_contentLabel(new QLabel), + m_contentLabel(new Utils::ElidingLabel), m_changeButton(new QPushButton(tr("Change..."))) { connect(m_changeButton, &QPushButton::clicked, this, &ConfigWidget::changeProperties); diff --git a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp index a28257d36fe..e48c7a2037a 100644 --- a/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsrunconfiguration.cpp @@ -110,11 +110,11 @@ void QbsRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo & void QbsRunConfiguration::addToBaseEnvironment(Utils::Environment &env) const { - if (auto dyldAspect = extraAspect()) { + if (auto dyldAspect = aspect()) { if (dyldAspect->value()) env.set("DYLD_IMAGE_SUFFIX", "_debug"); } - bool usingLibraryPaths = extraAspect()->value(); + bool usingLibraryPaths = aspect()->value(); const auto key = qMakePair(env.toStringList(), usingLibraryPaths); const auto it = m_envCache.constFind(key); @@ -146,16 +146,16 @@ void QbsRunConfiguration::updateTargetInformation() { BuildTargetInfo bti = buildTargetInfo(); const FileName executable = executableToRun(bti); - auto terminalAspect = extraAspect(); + auto terminalAspect = aspect(); if (!terminalAspect->isUserSet()) terminalAspect->setUseTerminal(bti.usesTerminal); - extraAspect()->setExecutable(executable); + aspect()->setExecutable(executable); if (!executable.isEmpty()) { QString defaultWorkingDir = QFileInfo(executable.toString()).absolutePath(); if (!defaultWorkingDir.isEmpty()) { - auto wdAspect = extraAspect(); + auto wdAspect = aspect(); wdAspect->setDefaultWorkingDirectory(FileName::fromString(defaultWorkingDir)); } } diff --git a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp index b58807d5bf5..f25b77a65fc 100644 --- a/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/desktopqmakerunconfiguration.cpp @@ -91,20 +91,20 @@ DesktopQmakeRunConfiguration::DesktopQmakeRunConfiguration(Target *target, Core: void DesktopQmakeRunConfiguration::updateTargetInformation() { setDefaultDisplayName(defaultDisplayName()); - extraAspect()->buildEnvironmentHasChanged(); + aspect()->buildEnvironmentHasChanged(); BuildTargetInfo bti = buildTargetInfo(); - auto wda = extraAspect(); + auto wda = aspect(); wda->setDefaultWorkingDirectory(bti.workingDirectory); if (wda->pathChooser()) wda->pathChooser()->setBaseFileName(target()->project()->projectDirectory()); - auto terminalAspect = extraAspect(); + auto terminalAspect = aspect(); if (!terminalAspect->isUserSet()) terminalAspect->setUseTerminal(bti.usesTerminal); - extraAspect()->setExecutable(bti.targetFilePath); + aspect()->setExecutable(bti.targetFilePath); } QVariantMap DesktopQmakeRunConfiguration::toMap() const @@ -135,9 +135,9 @@ void DesktopQmakeRunConfiguration::addToBaseEnvironment(Environment &env) const { BuildTargetInfo bti = buildTargetInfo(); if (bti.runEnvModifier) - bti.runEnvModifier(env, extraAspect()->value()); + bti.runEnvModifier(env, aspect()->value()); - if (auto dyldAspect = extraAspect()) { + if (auto dyldAspect = aspect()) { if (dyldAspect->value()) env.set(QLatin1String("DYLD_IMAGE_SUFFIX"), QLatin1String("_debug")); } diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index d42416a4a98..220d959d030 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -302,7 +302,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker) auto runConfiguration = runControl->runConfiguration(); if (runConfiguration) { auto aspect = static_cast( - runConfiguration->extraAspect(Constants::SETTINGS)); + runConfiguration->aspect(Constants::SETTINGS)); if (aspect) { if (QmlProfilerSettings *settings = static_cast(aspect->currentSettings())) { d->m_profilerConnections->setFlushInterval(settings->flushEnabled() ? diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 8d99294c673..55e32ec508e 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -305,7 +305,7 @@ Runnable QmlProjectRunConfiguration::runnable() const Runnable r; r.executable = executable(); r.commandLineArguments = commandLineArguments(); - r.environment = extraAspect()->environment(); + r.environment = aspect()->environment(); r.workingDirectory = static_cast(project())->targetDirectory(target()).toString(); return r; } @@ -354,7 +354,7 @@ QString QmlProjectRunConfiguration::executable() const QString QmlProjectRunConfiguration::commandLineArguments() const { // arguments in .user file - QString args = extraAspect()->arguments(macroExpander()); + QString args = aspect()->arguments(macroExpander()); const Target *currentTarget = target(); const IDevice::ConstPtr device = DeviceKitInformation::device(currentTarget->kit()); const Utils::OsType osType = device ? device->osType() : Utils::HostOsInfo::hostOs(); diff --git a/src/plugins/qnx/qnxdebugsupport.cpp b/src/plugins/qnx/qnxdebugsupport.cpp index bb69ba46472..f53b27df368 100644 --- a/src/plugins/qnx/qnxdebugsupport.cpp +++ b/src/plugins/qnx/qnxdebugsupport.cpp @@ -265,7 +265,7 @@ void QnxAttachDebugSupport::showProcessesDialog() // QString projectSourceDirectory = dlg.projectSource(); QString localExecutable = dlg.localExecutable(); if (localExecutable.isEmpty()) { - if (auto aspect = runConfig->extraAspect()) + if (auto aspect = runConfig->aspect()) localExecutable = aspect->fileName().toString(); } diff --git a/src/plugins/qnx/qnxrunconfiguration.cpp b/src/plugins/qnx/qnxrunconfiguration.cpp index 73e619dbad4..f9aa3b93fc6 100644 --- a/src/plugins/qnx/qnxrunconfiguration.cpp +++ b/src/plugins/qnx/qnxrunconfiguration.cpp @@ -45,7 +45,7 @@ QnxRunConfiguration::QnxRunConfiguration(Target *target, Core::Id id) Runnable QnxRunConfiguration::runnable() const { Runnable r = RemoteLinuxRunConfiguration::runnable(); - QString libPath = extraAspect()->value(); + QString libPath = aspect()->value(); if (!libPath.isEmpty()) { r.environment.appendOrSet("LD_LIBRARY_PATH", libPath + "/lib:$LD_LIBRARY_PATH"); r.environment.appendOrSet("QML_IMPORT_PATH", libPath + "/imports:$QML_IMPORT_PATH"); diff --git a/src/plugins/qnx/slog2inforunner.cpp b/src/plugins/qnx/slog2inforunner.cpp index e7648899a49..113d589a3c9 100644 --- a/src/plugins/qnx/slog2inforunner.cpp +++ b/src/plugins/qnx/slog2inforunner.cpp @@ -45,7 +45,7 @@ Slog2InfoRunner::Slog2InfoRunner(RunControl *runControl) : RunWorker(runControl) { setId("Slog2InfoRunner"); - m_applicationId = runControl->runConfiguration()->extraAspect()->executable().fileName(); + m_applicationId = runControl->runConfiguration()->aspect()->executable().fileName(); // See QTCREATORBUG-10712 for details. // We need to limit length of ApplicationId to 63 otherwise it would not match one in slog2info. diff --git a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp index 83f378ab8e2..b8ed968a9b9 100644 --- a/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxcustomrunconfiguration.cpp @@ -65,7 +65,7 @@ RemoteLinuxCustomRunConfiguration::RemoteLinuxCustomRunConfiguration(Target *tar bool RemoteLinuxCustomRunConfiguration::isConfigured() const { - return !extraAspect()->executable().isEmpty(); + return !aspect()->executable().isEmpty(); } RunConfiguration::ConfigurationState @@ -88,7 +88,7 @@ Core::Id RemoteLinuxCustomRunConfiguration::runConfigId() QString RemoteLinuxCustomRunConfiguration::runConfigDefaultDisplayName() { - QString remoteExecutable = extraAspect()->executable().toString(); + QString remoteExecutable = aspect()->executable().toString(); QString display = remoteExecutable.isEmpty() ? tr("Custom Executable") : tr("Run \"%1\"").arg(remoteExecutable); return RunConfigurationFactory::decoratedTargetName(display, target()); diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp index 7a799bf4298..cbd02d72fd6 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp +++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.cpp @@ -73,24 +73,14 @@ RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Target *target, Core::I this, &RemoteLinuxRunConfiguration::updateTargetInformation); } -void RemoteLinuxRunConfiguration::doAdditionalSetup(const RunConfigurationCreationInfo &) -{ - setDefaultDisplayName(defaultDisplayName()); -} - -QString RemoteLinuxRunConfiguration::defaultDisplayName() const -{ - return RunConfigurationFactory::decoratedTargetName(buildKey(), target()); -} - void RemoteLinuxRunConfiguration::updateTargetInformation() { BuildTargetInfo bti = buildTargetInfo(); QString localExecutable = bti.targetFilePath.toString(); DeployableFile depFile = target()->deploymentData().deployableForLocalFile(localExecutable); - extraAspect()->setExecutable(FileName::fromString(depFile.remoteFilePath())); - extraAspect()->setValue(localExecutable); + aspect()->setExecutable(FileName::fromString(depFile.remoteFilePath())); + aspect()->setValue(localExecutable); emit enabledChanged(); } @@ -103,6 +93,7 @@ const char *RemoteLinuxRunConfiguration::IdPrefix = "RemoteLinuxRunConfiguration RemoteLinuxRunConfigurationFactory::RemoteLinuxRunConfigurationFactory() { registerRunConfiguration(RemoteLinuxRunConfiguration::IdPrefix); + setDecorateDisplayNames(true); addSupportedTargetDeviceType(RemoteLinux::Constants::GenericLinuxOsType); } diff --git a/src/plugins/remotelinux/remotelinuxrunconfiguration.h b/src/plugins/remotelinux/remotelinuxrunconfiguration.h index c3d263dcb71..839da13ae5d 100644 --- a/src/plugins/remotelinux/remotelinuxrunconfiguration.h +++ b/src/plugins/remotelinux/remotelinuxrunconfiguration.h @@ -40,9 +40,6 @@ public: static const char *IdPrefix; private: - void doAdditionalSetup(const ProjectExplorer::RunConfigurationCreationInfo &) override; - - QString defaultDisplayName() const; void updateTargetInformation(); }; diff --git a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp index 8f5d7291482..079b7b2db1d 100644 --- a/src/plugins/texteditor/codeassist/genericproposalwidget.cpp +++ b/src/plugins/texteditor/codeassist/genericproposalwidget.cpp @@ -31,9 +31,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -49,6 +51,7 @@ #include #include #include +#include using namespace Utils; @@ -92,6 +95,8 @@ QVariant ModelAdapter::data(const QModelIndex &index, int role) const return m_completionModel->icon(index.row()); else if (role == Qt::WhatsThisRole) return m_completionModel->detail(index.row()); + else if (role == Qt::UserRole) + return m_completionModel->proposalItem(index.row())->requiresFixIts(); return QVariant(); } @@ -146,6 +151,7 @@ private: // ----------------------- class GenericProposalListView : public QListView { + friend class ProposalItemDelegate; public: GenericProposalListView(QWidget *parent); @@ -160,10 +166,53 @@ public: void selectLastRow() { selectRow(model()->rowCount() - 1); } }; +class ProposalItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit ProposalItemDelegate(GenericProposalListView *parent = nullptr) + : QStyledItemDelegate(parent) + , m_parent(parent) + { + } + + void paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { + static const QIcon fixItIcon = ::Utils::Icons::CODEMODEL_FIXIT.icon(); + + QStyledItemDelegate::paint(painter, option, index); + + if (m_parent->model()->data(index, Qt::UserRole).toBool()) { + const QRect itemRect = m_parent->rectForIndex(index); + const QScrollBar *verticalScrollBar = m_parent->verticalScrollBar(); + + const int x = m_parent->width() - itemRect.height() - (verticalScrollBar->isVisible() + ? verticalScrollBar->width() + : 0); + const int iconSize = itemRect.height() - 5; + fixItIcon.paint(painter, QRect(x, itemRect.y() - m_parent->verticalOffset(), + iconSize, iconSize)); + } + } + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override + { + QSize size(QStyledItemDelegate::sizeHint(option, index)); + if (m_parent->model()->data(index, Qt::UserRole).toBool()) + size.setWidth(size.width() + m_parent->rectForIndex(index).height() - 5); + return size; + } +private: + GenericProposalListView *m_parent; +}; + GenericProposalListView::GenericProposalListView(QWidget *parent) : QListView(parent) { setVerticalScrollMode(QAbstractItemView::ScrollPerItem); + setItemDelegate(new ProposalItemDelegate(this)); } QSize GenericProposalListView::calculateSize() const diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp index 6f2a6f75cef..15a882adf8f 100644 --- a/src/plugins/valgrind/valgrindengine.cpp +++ b/src/plugins/valgrind/valgrindengine.cpp @@ -86,7 +86,7 @@ void ValgrindToolRunner::start() m_runner.setDevice(device()); m_runner.setDebuggee(runnable()); - if (auto aspect = runControl()->runConfiguration()->extraAspect()) + if (auto aspect = runControl()->runConfiguration()->aspect()) m_runner.setUseTerminal(aspect->useTerminal()); connect(&m_runner, &ValgrindRunner::processOutputReceived, diff --git a/src/plugins/winrt/winrtrunnerhelper.cpp b/src/plugins/winrt/winrtrunnerhelper.cpp index be9ddfa25fa..efd0e62506b 100644 --- a/src/plugins/winrt/winrtrunnerhelper.cpp +++ b/src/plugins/winrt/winrtrunnerhelper.cpp @@ -84,13 +84,13 @@ WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunWorker *runWorker, QStr bool loopbackExemptClient = false; bool loopbackExemptServer = false; - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) m_arguments = aspect->arguments(runConfiguration->macroExpander()); - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) m_uninstallAfterStop = aspect->value(); - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) loopbackExemptClient = aspect->value(); - if (auto aspect = runConfiguration->extraAspect()) + if (auto aspect = runConfiguration->aspect()) loopbackExemptServer = aspect->value(); if (loopbackExemptClient && loopbackExemptServer) m_loopbackArguments = "--loopbackexempt clientserver"; diff --git a/src/tools/clangbackend/source/codecompleter.cpp b/src/tools/clangbackend/source/codecompleter.cpp index 7a11ff02d8e..5520b5b3a9d 100644 --- a/src/tools/clangbackend/source/codecompleter.cpp +++ b/src/tools/clangbackend/source/codecompleter.cpp @@ -40,6 +40,8 @@ #include "unsavedfile.h" #include "unsavedfiles.h" +#include + #include namespace ClangBackEnd { @@ -47,13 +49,14 @@ namespace ClangBackEnd { namespace { CodeCompletions toCodeCompletions(const TranslationUnit &translationUnit, - const ClangCodeCompleteResults &results) + const ClangCodeCompleteResults &results, + bool onlyFunctionOverloads) { if (results.isNull()) return CodeCompletions(); CodeCompletionsExtractor extractor(translationUnit.cxTranslationUnit(), results.data()); - CodeCompletions codeCompletions = extractor.extractAll(); + CodeCompletions codeCompletions = extractor.extractAll(onlyFunctionOverloads); return codeCompletions; } @@ -83,33 +86,49 @@ CodeCompleter::CodeCompleter(const TranslationUnit &translationUnit, { } +static void replaceWithOpeningParen(UnsavedFile &file, uint line, uint column) +{ + bool ok; + const uint pos = file.toUtf8Position(line, column, &ok); + QTC_ASSERT(ok, return;); + file.replaceAt(pos, 1, Utf8String("(", 1)); +} + CodeCompletions CodeCompleter::complete(uint line, uint column, int funcNameStartLine, int funcNameStartColumn) { + if (funcNameStartLine >= 0) { + UnsavedFile &file = unsavedFiles.unsavedFile(translationUnit.filePath()); + // Replace '{' by '(' to get proper FunctionOverloadCompletionKind for constructor. + if (file.hasCharacterAt(line, column - 1, '{')) + replaceWithOpeningParen(file, line, column - 1); + } + // Check if we have a smart pointer completion and get proper constructor signatures in results. // Results are empty when it's not a smart pointer or this completion failed. - ClangCodeCompleteResults results = completeSmartPointerCreation(line, - column, - funcNameStartLine, - funcNameStartColumn); + ClangCodeCompleteResults clangCompletions = completeSmartPointerCreation(line, + column, + funcNameStartLine, + funcNameStartColumn); - if (results.isNull() || results.isEmpty()) - results = completeHelper(line, column); + // Default completion. + if (clangCompletions.isNull() || clangCompletions.isEmpty()) + clangCompletions = completeHelper(line, column); - filterUnknownContextResults(results, unsavedFile(), line, column); + filterUnknownContextResults(clangCompletions, unsavedFile(), line, column); - return toCodeCompletions(translationUnit, results); + return toCodeCompletions(translationUnit, clangCompletions, funcNameStartLine >= 0); } // For given "make_unique" / "make_shared" / "QSharedPointer::create" return "new T(" // Otherwize return empty QString -static QString tweakName(const QString &oldName) +static QString tweakName(const Utf8String &oldName) { - QString fullName = oldName.trimmed(); - if (!fullName.contains('>')) + if (!oldName.contains('>')) return QString(); + QString fullName = QString(oldName).trimmed(); if (!fullName.endsWith('>')) { // This is the class::method case - remove ::method part if (!fullName.endsWith("create") || !fullName.contains("QSharedPointer")) @@ -138,10 +157,12 @@ ClangCodeCompleteResults CodeCompleter::completeSmartPointerCreation(uint line, bool ok; const uint startPos = file.toUtf8Position(funcNameStartLine, funcNameStartColumn, &ok); + QTC_ASSERT(ok, return ClangCodeCompleteResults();); const uint endPos = file.toUtf8Position(line, column - 1, &ok); + QTC_ASSERT(ok, return ClangCodeCompleteResults();); - Utf8String content = file.fileContent(); - const QString oldName = content.mid(startPos, endPos - startPos); + const Utf8String content = file.fileContent(); + const Utf8String oldName = content.mid(startPos, endPos - startPos); const QString updatedName = tweakName(oldName); if (updatedName.isEmpty()) return ClangCodeCompleteResults(); diff --git a/src/tools/clangbackend/source/codecompletionsextractor.cpp b/src/tools/clangbackend/source/codecompletionsextractor.cpp index bd961dc4aa5..25be6bddcf3 100644 --- a/src/tools/clangbackend/source/codecompletionsextractor.cpp +++ b/src/tools/clangbackend/source/codecompletionsextractor.cpp @@ -27,9 +27,13 @@ #include "clangbackend_global.h" #include "clangstring.h" +#include "clangtranslationunit.h" #include "codecompletionchunkconverter.h" +#include "sourcelocation.h" #include "sourcerange.h" +#include + #include namespace ClangBackEnd { @@ -85,7 +89,7 @@ bool CodeCompletionsExtractor::peek(const Utf8String &name) return false; } -CodeCompletions CodeCompletionsExtractor::extractAll() +CodeCompletions CodeCompletionsExtractor::extractAll(bool onlyFunctionOverloads) { CodeCompletions codeCompletions; codeCompletions.reserve(int(cxCodeCompleteResults->NumResults)); @@ -93,9 +97,75 @@ CodeCompletions CodeCompletionsExtractor::extractAll() while (next()) codeCompletions.append(currentCodeCompletion_); + handleCompletions(codeCompletions, onlyFunctionOverloads); + return codeCompletions; } +static CodeCompletions filterFunctionOverloads(const CodeCompletions &completions) +{ + return ::Utils::filtered(completions, [](const CodeCompletion &completion) { + return completion.completionKind == CodeCompletion::FunctionOverloadCompletionKind; + }); +} + +static ::Utils::optional classBeforeCXXConstructor(const CodeCompletion &first, + const CodeCompletion &second) +{ + // Put ClassCompletionKind elements before ConstructorCompletionKind elements + // when they have the same name. + if (first.completionKind == CodeCompletion::ClassCompletionKind + && second.completionKind == CodeCompletion::ConstructorCompletionKind + && first.text == second.text) { + return true; + } + + if (first.completionKind == CodeCompletion::ConstructorCompletionKind + && second.completionKind == CodeCompletion::ClassCompletionKind + && first.text == second.text) { + return false; + } + + return ::Utils::optional(); +} + +static void sortCodeCompletions(CodeCompletions &codeCompletions) +{ + auto currentItemsCompare = [](const CodeCompletion &first, + const CodeCompletion &second) { + // Items without fix-its come first. + if (first.requiredFixIts.empty() != second.requiredFixIts.empty()) + return first.requiredFixIts.empty() > second.requiredFixIts.empty(); + + const ::Utils::optional classBeforeConstructorWithTheSameName + = classBeforeCXXConstructor(first, second); + if (classBeforeConstructorWithTheSameName) + return classBeforeConstructorWithTheSameName.value(); + + return (first.priority > 0 + && (first.priority < second.priority + || (first.priority == second.priority && first.text < second.text))); + }; + + // Keep the order for the items with the same priority and name. + std::stable_sort(codeCompletions.begin(), codeCompletions.end(), currentItemsCompare); +} + +void CodeCompletionsExtractor::handleCompletions(CodeCompletions &codeCompletions, + bool onlyFunctionOverloads) +{ + if (onlyFunctionOverloads) { + const CodeCompletions overloadCompletions = filterFunctionOverloads(codeCompletions); + + // If filtered completions are empty the assumption we need function overloads is wrong + // therefore we do not use filtered results in that case. + if (!overloadCompletions.isEmpty()) + codeCompletions = overloadCompletions; + } + + sortCodeCompletions(codeCompletions); +} + void CodeCompletionsExtractor::extractCompletionKind() { switch (currentCxCodeCompleteResult.CursorKind) { diff --git a/src/tools/clangbackend/source/codecompletionsextractor.h b/src/tools/clangbackend/source/codecompletionsextractor.h index 1c5f963c14b..928dabd25d3 100644 --- a/src/tools/clangbackend/source/codecompletionsextractor.h +++ b/src/tools/clangbackend/source/codecompletionsextractor.h @@ -50,7 +50,7 @@ public: bool next(); bool peek(const Utf8String &name); - CodeCompletions extractAll(); + CodeCompletions extractAll(bool onlyFunctionOverloads); const CodeCompletion ¤tCodeCompletion() const; @@ -73,6 +73,8 @@ private: void decreasePriorityForQObjectInternals(); void decreasePriorityForOperators(); + void handleCompletions(CodeCompletions &codeCompletions, bool onlyFunctionOverloads); + bool hasText(const Utf8String &text, CXCompletionString cxCompletionString) const; private: diff --git a/tests/unit/unittest/codecompleter-test.cpp b/tests/unit/unittest/codecompleter-test.cpp index 0a20849bb8f..f72a9eb8281 100644 --- a/tests/unit/unittest/codecompleter-test.cpp +++ b/tests/unit/unittest/codecompleter-test.cpp @@ -43,6 +43,7 @@ using ::testing::Not; using ::testing::PrintToString; using ClangBackEnd::CodeCompletion; +using ClangBackEnd::CodeCompletionChunk; using ClangBackEnd::CodeCompleter; namespace { @@ -65,6 +66,29 @@ MATCHER_P2(IsCodeCompletion, text, completionKind, return true; } +MATCHER_P(IsOverloadCompletion, text, + std::string(negation ? "isn't" : "is") + " overload completion with text " + PrintToString(text)) +{ + Utf8String overloadName; + for (auto &chunk : arg.chunks) { + if (chunk.kind == CodeCompletionChunk::Text) { + overloadName = chunk.text; + break; + } + } + if (overloadName != text) { + *result_listener << "text is " + PrintToString(overloadName) + " and not " + PrintToString(text); + return false; + } + + if (arg.completionKind != CodeCompletion::FunctionOverloadCompletionKind) { + *result_listener << "kind is " + PrintToString(arg.completionKind) + " and not " + PrintToString(CodeCompletion::FunctionOverloadCompletionKind); + return false; + } + + return true; +} + MATCHER(HasFixIts, "") { return !arg.requiredFixIts.empty(); @@ -195,6 +219,12 @@ protected: readFileContent("/complete_smartpointer.cpp"), true }; + ClangBackEnd::FileContainer completionsOrder{ + Utf8StringLiteral(TESTDATA_DIR"/completions_order.cpp"), + {includePathArgument}, + readFileContent("/completions_order.cpp"), + true + }; }; using CodeCompleterSlowTest = CodeCompleter; @@ -306,27 +336,24 @@ TEST_F(CodeCompleterSlowTest, UniquePointerCompletion) { auto myCompleter = setupCompleter(smartPointerCompletion); - ASSERT_THAT(myCompleter.complete(55, 54, 55, 32), - Contains(IsCodeCompletion(Utf8StringLiteral("Bar"), - CodeCompletion::ConstructorCompletionKind))); + ASSERT_THAT(myCompleter.complete(59, 54, 59, 32), + Contains(IsOverloadCompletion(Utf8StringLiteral("Bar")))); } TEST_F(CodeCompleterSlowTest, SharedPointerCompletion) { auto myCompleter = setupCompleter(smartPointerCompletion); - ASSERT_THAT(myCompleter.complete(56, 55, 56, 33), - Contains(IsCodeCompletion(Utf8StringLiteral("Bar"), - CodeCompletion::ConstructorCompletionKind))); + ASSERT_THAT(myCompleter.complete(60, 55, 60, 33), + Contains(IsOverloadCompletion(Utf8StringLiteral("Bar")))); } TEST_F(CodeCompleterSlowTest, QSharedPointerCompletion) { auto myCompleter = setupCompleter(smartPointerCompletion); - ASSERT_THAT(myCompleter.complete(57, 60, 57, 32), - Contains(IsCodeCompletion(Utf8StringLiteral("Bar"), - CodeCompletion::ConstructorCompletionKind))); + ASSERT_THAT(myCompleter.complete(61, 60, 61, 32), + Contains(IsOverloadCompletion(Utf8StringLiteral("Bar")))); } TEST_F(CodeCompleterSlowTest, FunctionInUnsavedIncludedHeader) @@ -499,6 +526,60 @@ TEST_F(CodeCompleterSlowTest, GlobalCompletionAfterForwardDeclaredClassPointer) ASSERT_TRUE(!completions.isEmpty()); } +TEST_F(CodeCompleterSlowTest, ConstructorCompletionExists) +{ + auto myCompleter = setupCompleter(completionsOrder); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1); + + int constructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind; + }); + + ASSERT_THAT(constructorIndex != -1, true); +} + +TEST_F(CodeCompleterSlowTest, ClassConstructorCompletionsOrder) +{ + auto myCompleter = setupCompleter(completionsOrder); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1); + + int classIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ClassCompletionKind; + }); + int constructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind; + }); + + ASSERT_THAT(classIndex < constructorIndex, true); +} + +TEST_F(CodeCompleterSlowTest, SharedPointerCompletionsOrder) +{ + auto myCompleter = setupCompleter(smartPointerCompletion); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(62, 11); + + int resetIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "reset"; + }); + int barDestructorIndex = Utils::indexOf(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "~Bar"; + }); + + ASSERT_THAT(barDestructorIndex < resetIndex, true); +} + +TEST_F(CodeCompleterSlowTest, ConstructorHasOverloadCompletions) +{ + auto myCompleter = setupCompleter(completionsOrder); + const ClangBackEnd::CodeCompletions completions = myCompleter.complete(8, 1); + + int constructorsCount = Utils::count(completions, [](const CodeCompletion &codeCompletion) { + return codeCompletion.text == "Constructor" && codeCompletion.completionKind == CodeCompletion::ConstructorCompletionKind; + }); + + ASSERT_THAT(constructorsCount, 2); +} + ClangBackEnd::CodeCompleter CodeCompleter::setupCompleter( const ClangBackEnd::FileContainer &fileContainer) { diff --git a/tests/unit/unittest/codecompletionsextractor-test.cpp b/tests/unit/unittest/codecompletionsextractor-test.cpp index 3f4ca8f0df3..b7c44f2cca0 100644 --- a/tests/unit/unittest/codecompletionsextractor-test.cpp +++ b/tests/unit/unittest/codecompletionsextractor-test.cpp @@ -794,6 +794,18 @@ TEST_F(CodeCompletionsExtractorSlowTest, OverloadCandidate) }))); } +TEST_F(CodeCompletionsExtractorSlowTest, ExtractAll) +{ + ClangCodeCompleteResults completeResults(getResults(constructorDocument, 25)); + ::CodeCompletionsExtractor extractor( + constructorDocument.translationUnit().cxTranslationUnit(), + completeResults.data()); + + auto codeCompletions = extractor.extractAll(false); + + ASSERT_THAT(codeCompletions.empty(), false); +} + ClangCodeCompleteResults CodeCompletionsExtractor::getResults(const Document &document, uint line, uint column, diff --git a/tests/unit/unittest/data/complete_smartpointer.cpp b/tests/unit/unittest/data/complete_smartpointer.cpp index 1a9bbaf9788..a6e7d73a58a 100644 --- a/tests/unit/unittest/data/complete_smartpointer.cpp +++ b/tests/unit/unittest/data/complete_smartpointer.cpp @@ -27,7 +27,11 @@ template class unique_ptr {}; template -class shared_ptr {}; +class shared_ptr { +public: + void reset(); + Type *operator->(); +}; template unique_ptr make_unique(Args&&... args); @@ -55,4 +59,5 @@ void f2() std::unique_ptr bar = std::make_unique(); std::shared_ptr bar2 = std::make_shared(); QSharedPointer bar3 = QSharedPointer::create(); + bar2-> } diff --git a/tests/unit/unittest/data/completions_order.cpp b/tests/unit/unittest/data/completions_order.cpp new file mode 100644 index 00000000000..6ede7573d85 --- /dev/null +++ b/tests/unit/unittest/data/completions_order.cpp @@ -0,0 +1,9 @@ +class Constructor { +public: + Constructor() = default; + Constructor(int) {} +}; + +void testConstructor() { + +}