From c4256a9a2b4bf92f84baea0435d414373493af46 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 13 Oct 2021 17:18:07 +0200 Subject: [PATCH] CppEditor: Squash three copies of the "is in comment or string" check Change-Id: Id6c4e35ae2d3b3031e5c95ea04f5b971bef58389 Reviewed-by: David Schulz --- .../clangcompletionassistprocessor.cpp | 37 ++-------------- src/plugins/clangcodemodel/clangdclient.cpp | 42 ++----------------- src/plugins/cppeditor/cppcompletionassist.cpp | 34 +-------------- src/plugins/cppeditor/cpptoolsreuse.cpp | 40 +++++++++++++++++- src/plugins/cppeditor/cpptoolsreuse.h | 6 +++ 5 files changed, 53 insertions(+), 106 deletions(-) diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index af964f5be95..1d924f8b2da 100644 --- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include @@ -44,10 +45,7 @@ #include #include -#include -#include #include -#include #include @@ -431,37 +429,8 @@ bool ClangCompletionAssistProcessor::accepts() const if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) { const QChar firstCharacter = m_interface->characterAt(startOfName); if (firstCharacter.isLetter() || firstCharacter == QLatin1Char('_')) { - // Finally check that we're not inside a comment or string (code copied from startOfOperator) - QTextCursor tc(m_interface->textDocument()); - tc.setPosition(pos); - - SimpleLexer tokenize; - LanguageFeatures lf = tokenize.languageFeatures(); - lf.qtMocRunEnabled = true; - lf.objCEnabled = true; - tokenize.setLanguageFeatures(lf); - tokenize.setSkipComments(false); - const Tokens &tokens = tokenize(tc.block().text(), BackwardsScanner::previousBlockState(tc.block())); - const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, tc.positionInBlock() - 1)); - const Token tk = (tokenIdx == -1) ? Token() : tokens.at(tokenIdx); - - if (!tk.isComment() && !tk.isLiteral()) { - return true; - } else if (tk.isLiteral() - && tokens.size() == 3 - && tokens.at(0).kind() == T_POUND - && tokens.at(1).kind() == T_IDENTIFIER) { - const QString &line = tc.block().text(); - const Token &idToken = tokens.at(1); - QStringView identifier = Utils::midView(line, - idToken.utf16charsBegin(), - idToken.utf16chars()); - if (identifier == QLatin1String("include") - || identifier == QLatin1String("include_next") - || (m_interface->objcEnabled() && identifier == QLatin1String("import"))) { - return true; - } - } + return !CppEditor::isInCommentOrString(m_interface.data(), + m_interface->languageFeatures()); } } } diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 20cb497095f..d5b63ec1e8f 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -35,11 +35,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -98,13 +96,6 @@ static Q_LOGGING_CATEGORY(clangdLogHighlight, "qtc.clangcodemodel.clangd.highlig static Q_LOGGING_CATEGORY(clangdLogTiming, "qtc.clangcodemodel.clangd.timing", QtWarningMsg); static QString indexingToken() { return "backgroundIndexProgress"; } -static QStringView subView(const QString &s, qsizetype start) -{ - if (start < 0 || start > s.length()) - return {}; - return QStringView(s).mid(start); -} - static QStringView subViewLen(const QString &s, qsizetype start, qsizetype length) { if (start < 0 || length < 0 || start + length > s.length()) @@ -2646,36 +2637,9 @@ bool ClangdClient::ClangdCompletionAssistProvider::isContinuationChar(const QCha bool ClangdClient::ClangdCompletionAssistProvider::isInCommentOrString( const AssistInterface *interface) const { - QTextCursor tc(interface->textDocument()); - tc.setPosition(interface->position()); - - SimpleLexer tokenize; - tokenize.setSkipComments(false); - const Tokens &tokens = tokenize(tc.block().text(), - BackwardsScanner::previousBlockState(tc.block())); - const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, tc.positionInBlock() - 1)); - const Token tk = (tokenIdx == -1) ? Token() : tokens.at(tokenIdx); - - if (tk.isComment()) - return true; - if (!tk.isLiteral()) - return false; - if (tokens.size() == 3 && tokens.at(0).kind() == T_POUND - && tokens.at(1).kind() == T_IDENTIFIER) { - const QString &line = tc.block().text(); - const Token &idToken = tokens.at(1); - QStringView identifier = idToken.utf16charsEnd() > line.size() - ? subView(line, idToken.utf16charsBegin()) - : subViewLen(line, idToken.utf16charsBegin(), - idToken.utf16chars()); - if (identifier == QLatin1String("include") - || identifier == QLatin1String("include_next") - || (CppEditor::ProjectFile::isObjC(interface->filePath().toString()) - && identifier == QLatin1String("import"))) { - return false; - } - } - return true; + LanguageFeatures features = LanguageFeatures::defaultFeatures(); + features.objCEnabled = CppEditor::ProjectFile::isObjC(interface->filePath().toString()); + return CppEditor::isInCommentOrString(interface, features); } void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator, diff --git a/src/plugins/cppeditor/cppcompletionassist.cpp b/src/plugins/cppeditor/cppcompletionassist.cpp index cd2c70b78c3..ee04a159570 100644 --- a/src/plugins/cppeditor/cppcompletionassist.cpp +++ b/src/plugins/cppeditor/cppcompletionassist.cpp @@ -858,38 +858,8 @@ bool InternalCppCompletionAssistProcessor::accepts() const if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) { const QChar firstCharacter = m_interface->characterAt(startOfName); if (isValidFirstIdentifierChar(firstCharacter)) { - // Finally check that we're not inside a comment or string (code copied from startOfOperator) - QTextCursor tc(m_interface->textDocument()); - tc.setPosition(pos); - - SimpleLexer tokenize; - tokenize.setLanguageFeatures(m_interface->languageFeatures()); - tokenize.setSkipComments(false); - - const Tokens &tokens = tokenize(tc.block().text(), BackwardsScanner::previousBlockState(tc.block())); - const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, tc.positionInBlock() - 1)); - const Token tk = (tokenIdx == -1) ? Token() : tokens.at(tokenIdx); - - if (!tk.isComment() && !tk.isLiteral()) { - return true; - } else if (tk.isLiteral() - && tokens.size() == 3 - && tokens.at(0).kind() == T_POUND - && tokens.at(1).kind() == T_IDENTIFIER) { - const QString &line = tc.block().text(); - const Token &idToken = tokens.at(1); - QStringView identifier = idToken.utf16charsEnd() > line.size() - ? QStringView(line).mid( - idToken.utf16charsBegin()) - : QStringView(line) - .mid(idToken.utf16charsBegin(), - idToken.utf16chars()); - if (identifier == QLatin1String("include") - || identifier == QLatin1String("include_next") - || (m_interface->languageFeatures().objCEnabled && identifier == QLatin1String("import"))) { - return true; - } - } + return !isInCommentOrString(m_interface.data(), + m_interface->languageFeatures()); } } } diff --git a/src/plugins/cppeditor/cpptoolsreuse.cpp b/src/plugins/cppeditor/cpptoolsreuse.cpp index 15a1bea88a1..04f679824ae 100644 --- a/src/plugins/cppeditor/cpptoolsreuse.cpp +++ b/src/plugins/cppeditor/cpptoolsreuse.cpp @@ -39,11 +39,15 @@ #include #include #include +#include #include -#include +#include #include +#include +#include #include +#include #include #include @@ -300,6 +304,40 @@ const Macro *findCanonicalMacro(const QTextCursor &cursor, Document::Ptr documen return nullptr; } +bool isInCommentOrString(const TextEditor::AssistInterface *interface, + CPlusPlus::LanguageFeatures features) +{ + QTextCursor tc(interface->textDocument()); + tc.setPosition(interface->position()); + + SimpleLexer tokenize; + features.qtMocRunEnabled = true; + tokenize.setLanguageFeatures(features); + tokenize.setSkipComments(false); + const Tokens &tokens = tokenize(tc.block().text(), + BackwardsScanner::previousBlockState(tc.block())); + const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, tc.positionInBlock() - 1)); + const Token tk = (tokenIdx == -1) ? Token() : tokens.at(tokenIdx); + + if (tk.isComment()) + return true; + if (!tk.isLiteral()) + return false; + if (tokens.size() == 3 && tokens.at(0).kind() == T_POUND + && tokens.at(1).kind() == T_IDENTIFIER) { + const QString &line = tc.block().text(); + const Token &idToken = tokens.at(1); + QStringView identifier = Utils::midView(line, idToken.utf16charsBegin(), + idToken.utf16chars()); + if (identifier == QLatin1String("include") + || identifier == QLatin1String("include_next") + || (features.objCEnabled && identifier == QLatin1String("import"))) { + return false; + } + } + return true; +} + CppCodeModelSettings *codeModelSettings() { return Internal::CppEditorPlugin::instance()->codeModelSettings(); diff --git a/src/plugins/cppeditor/cpptoolsreuse.h b/src/plugins/cppeditor/cpptoolsreuse.h index b3fd7a274b4..e7023b7be78 100644 --- a/src/plugins/cppeditor/cpptoolsreuse.h +++ b/src/plugins/cppeditor/cpptoolsreuse.h @@ -35,6 +35,7 @@ #include #include +#include QT_BEGIN_NAMESPACE class QChar; @@ -48,6 +49,8 @@ class Symbol; class LookupContext; } // namespace CPlusPlus +namespace TextEditor { class AssistInterface; } + namespace CppEditor { class CppRefactoringFile; class ProjectInfo; @@ -71,6 +74,9 @@ bool CPPEDITOR_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol, const CPlusPlus::Macro CPPEDITOR_EXPORT *findCanonicalMacro(const QTextCursor &cursor, CPlusPlus::Document::Ptr document); +bool CPPEDITOR_EXPORT isInCommentOrString(const TextEditor::AssistInterface *interface, + CPlusPlus::LanguageFeatures features); + enum class CacheUsage { ReadWrite, ReadOnly }; QString CPPEDITOR_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = nullptr,