diff --git a/src/core/codedocument.cpp b/src/core/codedocument.cpp index f8e10f57..68ee1271 100644 --- a/src/core/codedocument.cpp +++ b/src/core/codedocument.cpp @@ -134,7 +134,10 @@ void CodeDocument::deleteSymbol(const Symbol &symbol) Core::SymbolList CodeDocument::symbols() const { LOG(); - return m_treeSitterHelper->symbols(); + RangeMark::temporaryDocumentText = text(); + const auto &symbols = m_treeSitterHelper->symbols(); + RangeMark::temporaryDocumentText.clear(); + return symbols; } struct RegexpTransform diff --git a/src/core/cppdocument.cpp b/src/core/cppdocument.cpp index 046dfe01..0e680109 100644 --- a/src/core/cppdocument.cpp +++ b/src/core/cppdocument.cpp @@ -1,4 +1,4 @@ -/* +/* This file is part of Knut. SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company @@ -1223,26 +1223,39 @@ void CppDocument::toggleSection() gotoLine(line + 3); } else { - // Check that we are in a function - auto isFunction = [](const Symbol &symbol) { - return symbol.isFunction(); + auto matches = query(QString(R"EOF( + (function_definition + (type_qualifier)? @return + type: (_)? @return + declarator: [ + (function_declarator + declarator: (_) @name) + (_ + (function_declarator + declarator: (_) @name)) @full_name + ] + body: (compound_statement) @body) + )EOF")); + auto cursorPos = cursor.position(); + auto isInBody = [cursorPos](const QueryMatch &match) { + return match.get("body").contains(cursorPos); }; - auto symbol = currentSymbol(isFunction); - if (!symbol) + const auto functionMatch = kdalgorithms::find_if(matches, isInBody); + if (!functionMatch) return; - auto cursorPos = cursor.position(); + const auto range = functionMatch->get("body"); cursor.beginEditBlock(); // Start from the end - cursor.setPosition(symbol->range().end()); + cursor.setPosition(range.end()); cursor.movePosition(QTextCursor::StartOfLine); cursor.movePosition(QTextCursor::Up, QTextCursor::KeepAnchor); if (cursor.selectedText().startsWith(endifString)) { // The function is already commented out, remove the comments int start = textEdit()->document()->find(elseString, cursor, QTextDocument::FindBackward).selectionStart(); - if (start > symbol->range().start()) + if (start > range.start()) cursor.setPosition(start, QTextCursor::KeepAnchor); cursor.removeSelectedText(); cursor.setPosition(moveBlock(cursor.position(), QTextCursor::PreviousCharacter)); @@ -1252,14 +1265,17 @@ void CppDocument::toggleSection() cursor.removeSelectedText(); cursorPos -= ifdefString.length() + 1; } else { + const auto name = functionMatch->get("name").text(); + const auto returnType = functionMatch->get("return").text() + + (functionMatch->get("full_name").text().startsWith("*") ? "*" : ""); + // Comment out the function with #if/#def, make sure to return something if needed - cursor.setPosition(symbol->range().end()); + cursor.setPosition(range.end()); cursor.movePosition(QTextCursor::PreviousCharacter); QString text = elseString + newLine; if (!sectionSettings.debug.isEmpty()) - text += tab() + sectionSettings.debug.arg(symbol->name()) + ";\n"; - const QString returnType = symbol->toFunction()->returnType(); + text += tab() + sectionSettings.debug.arg(name) + ";\n"; auto it = sectionSettings.return_values.find(returnType.toStdString()); if (it != sectionSettings.return_values.end()) text += tab() + QString("return %1;\n").arg(QString::fromStdString(it->second)); diff --git a/src/core/logger.h b/src/core/logger.h index c8d23c5a..901a1418 100644 --- a/src/core/logger.h +++ b/src/core/logger.h @@ -30,25 +30,31 @@ * Log a method, with all its parameters. */ #define LOG(...) \ - Core::LoggerObject __loggerObject(Core::formatToClassNameFunctionName(std::source_location::current()), false, \ - ##__VA_ARGS__) + Core::LoggerObject __loggerObject( \ + Core::LoggerObject::canLog() ? Core::formatToClassNameFunctionName(std::source_location::current()) : "", \ + false, ##__VA_ARGS__) /** * Log a method, with all its parameters. If the previous log is also the same method, it will be merged into one * operation */ #define LOG_AND_MERGE(...) \ - Core::LoggerObject __loggerObject(Core::formatToClassNameFunctionName(std::source_location::current()), true, \ - ##__VA_ARGS__) + Core::LoggerObject __loggerObject( \ + Core::LoggerObject::canLog() ? Core::formatToClassNameFunctionName(std::source_location::current()) : "", \ + true, ##__VA_ARGS__) /** * Macro to save the returned value in the historymodel */ #define LOG_RETURN(name, value) \ do { \ - const auto &__value = value; \ - __loggerObject.setReturnValue(name, __value); \ - return __value; \ + if (Core::LoggerObject::canLog()) { \ + const auto &__value = value; \ + __loggerObject.setReturnValue(name, __value); \ + return __value; \ + } else { \ + return value; \ + } \ } while (false) namespace Core { @@ -293,6 +299,8 @@ class LoggerObject m_model->setReturnValue(std::move(name), value); } + static bool canLog() { return m_canLog; } + private: friend HistoryModel; friend LoggerDisabler; diff --git a/src/core/rangemark.cpp b/src/core/rangemark.cpp index d238a4b2..27c2c1e3 100644 --- a/src/core/rangemark.cpp +++ b/src/core/rangemark.cpp @@ -1,4 +1,4 @@ -/* +/* This file is part of Knut. SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company @@ -134,9 +134,16 @@ TextDocument *RangeMark::document() const QString RangeMark::text() const { + if (!isValid()) + return {}; + + auto text = temporaryDocumentText.isEmpty() ? document()->text() : temporaryDocumentText; // <= here instead of < because m_end is exclusive - if (isValid() && end() <= document()->text().size()) - return document()->text().sliced(start(), end() - start()); + if (isValid() && end() <= text.size()) { + text = text.sliced(start(), end() - start()); + text.squeeze(); + return text; + } return {}; } diff --git a/src/core/rangemark.h b/src/core/rangemark.h index a5eb795b..0494d362 100644 --- a/src/core/rangemark.h +++ b/src/core/rangemark.h @@ -1,4 +1,4 @@ -/* +/* This file is part of Knut. SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company @@ -62,6 +62,11 @@ class RangeMark bool operator==(const RangeMark &other) const; +protected: + friend class CodeDocument; + // This is used to reduce memory allocations when extracting symbols + inline static QString temporaryDocumentText = {}; + private: std::shared_ptr d = nullptr; diff --git a/src/core/textdocument.cpp b/src/core/textdocument.cpp index 9b147ce3..92ce932c 100644 --- a/src/core/textdocument.cpp +++ b/src/core/textdocument.cpp @@ -1,4 +1,4 @@ -/* +/* This file is part of Knut. SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company @@ -428,7 +428,7 @@ int TextDocument::positionAt(int line, int column) QString TextDocument::text() const { LOG(); - LOG_RETURN("text", m_document->toPlainText()); + return m_document->toPlainText(); } void TextDocument::setText(const QString &newText) diff --git a/test_data/tst_cppdocument/toggleSection/section.cpp.expected b/test_data/tst_cppdocument/toggleSection/section.cpp.expected index 7cf523d7..2bbbb308 100644 --- a/test_data/tst_cppdocument/toggleSection/section.cpp.expected +++ b/test_data/tst_cppdocument/toggleSection/section.cpp.expected @@ -64,3 +64,14 @@ Section *Section::create() return nullptr; #endif // KDAB_TEMPORARILY_REMOVED } + +Section &Section::reference() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + computeText(); + return *m_pointer; +#else // KDAB_TEMPORARILY_REMOVED + qDebug("Section::reference is commented out"); + return {}; +#endif // KDAB_TEMPORARILY_REMOVED +} diff --git a/test_data/tst_cppdocument/toggleSection/section.cpp.original b/test_data/tst_cppdocument/toggleSection/section.cpp.original index 36567cab..84112e4d 100644 --- a/test_data/tst_cppdocument/toggleSection/section.cpp.original +++ b/test_data/tst_cppdocument/toggleSection/section.cpp.original @@ -44,3 +44,9 @@ Section *Section::create() computeText(); return new Section; } + +Section &Section::reference() +{ + computeText(); + return *m_pointer; +} diff --git a/test_data/tst_cppdocument/toggleSection/section.h b/test_data/tst_cppdocument/toggleSection/section.h index cc4655ca..0cd9a067 100644 --- a/test_data/tst_cppdocument/toggleSection/section.h +++ b/test_data/tst_cppdocument/toggleSection/section.h @@ -10,4 +10,7 @@ class Section { int bar(); static Section *create(); + Section &reference(); +private: + Section *m_pointer; }; diff --git a/tests/tst_cppdocument_clangd.cpp b/tests/tst_cppdocument_clangd.cpp index f06760cb..ce25a9c1 100644 --- a/tests/tst_cppdocument_clangd.cpp +++ b/tests/tst_cppdocument_clangd.cpp @@ -68,6 +68,8 @@ private slots: auto cppFile = qobject_cast(Core::Project::instance()->get(file.fileName())); // Comment out full methods (start from the end) + cppFile->gotoLine(50); + cppFile->toggleSection(); cppFile->gotoLine(42); cppFile->toggleSection(); cppFile->gotoLine(35);