CppEditor: Squash three copies of the "is in comment or string" check

Change-Id: Id6c4e35ae2d3b3031e5c95ea04f5b971bef58389
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-10-13 17:18:07 +02:00
parent 9234bc369b
commit c4256a9a2b
5 changed files with 53 additions and 106 deletions

View File

@@ -36,6 +36,7 @@
#include <cppeditor/cppdoxygen.h> #include <cppeditor/cppdoxygen.h>
#include <cppeditor/cppmodelmanager.h> #include <cppeditor/cppmodelmanager.h>
#include <cppeditor/cpptoolsreuse.h>
#include <cppeditor/editordocumenthandle.h> #include <cppeditor/editordocumenthandle.h>
#include <texteditor/codeassist/assistproposalitem.h> #include <texteditor/codeassist/assistproposalitem.h>
@@ -44,10 +45,7 @@
#include <texteditor/codeassist/ifunctionhintproposalmodel.h> #include <texteditor/codeassist/ifunctionhintproposalmodel.h>
#include <texteditor/texteditorsettings.h> #include <texteditor/texteditorsettings.h>
#include <cplusplus/BackwardsScanner.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/Icons.h> #include <cplusplus/Icons.h>
#include <cplusplus/SimpleLexer.h>
#include <clangsupport/filecontainer.h> #include <clangsupport/filecontainer.h>
@@ -431,37 +429,8 @@ bool ClangCompletionAssistProcessor::accepts() const
if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) { if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) {
const QChar firstCharacter = m_interface->characterAt(startOfName); const QChar firstCharacter = m_interface->characterAt(startOfName);
if (firstCharacter.isLetter() || firstCharacter == QLatin1Char('_')) { if (firstCharacter.isLetter() || firstCharacter == QLatin1Char('_')) {
// Finally check that we're not inside a comment or string (code copied from startOfOperator) return !CppEditor::isInCommentOrString(m_interface.data(),
QTextCursor tc(m_interface->textDocument()); m_interface->languageFeatures());
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;
}
}
} }
} }
} }

View File

@@ -35,11 +35,9 @@
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/find/searchresultitem.h> #include <coreplugin/find/searchresultitem.h>
#include <coreplugin/find/searchresultwindow.h> #include <coreplugin/find/searchresultwindow.h>
#include <cplusplus/BackwardsScanner.h>
#include <cplusplus/FindUsages.h> #include <cplusplus/FindUsages.h>
#include <cplusplus/Icons.h> #include <cplusplus/Icons.h>
#include <cplusplus/MatchingText.h> #include <cplusplus/MatchingText.h>
#include <cplusplus/SimpleLexer.h>
#include <cppeditor/cppeditorconstants.h> #include <cppeditor/cppeditorconstants.h>
#include <cppeditor/cppcodemodelsettings.h> #include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cppcompletionassistprocessor.h> #include <cppeditor/cppcompletionassistprocessor.h>
@@ -98,13 +96,6 @@ static Q_LOGGING_CATEGORY(clangdLogHighlight, "qtc.clangcodemodel.clangd.highlig
static Q_LOGGING_CATEGORY(clangdLogTiming, "qtc.clangcodemodel.clangd.timing", QtWarningMsg); static Q_LOGGING_CATEGORY(clangdLogTiming, "qtc.clangcodemodel.clangd.timing", QtWarningMsg);
static QString indexingToken() { return "backgroundIndexProgress"; } 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) static QStringView subViewLen(const QString &s, qsizetype start, qsizetype length)
{ {
if (start < 0 || length < 0 || start + length > s.length()) if (start < 0 || length < 0 || start + length > s.length())
@@ -2646,36 +2637,9 @@ bool ClangdClient::ClangdCompletionAssistProvider::isContinuationChar(const QCha
bool ClangdClient::ClangdCompletionAssistProvider::isInCommentOrString( bool ClangdClient::ClangdCompletionAssistProvider::isInCommentOrString(
const AssistInterface *interface) const const AssistInterface *interface) const
{ {
QTextCursor tc(interface->textDocument()); LanguageFeatures features = LanguageFeatures::defaultFeatures();
tc.setPosition(interface->position()); features.objCEnabled = CppEditor::ProjectFile::isObjC(interface->filePath().toString());
return CppEditor::isInCommentOrString(interface, features);
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;
} }
void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator, void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,

View File

@@ -858,38 +858,8 @@ bool InternalCppCompletionAssistProcessor::accepts() const
if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) { if (pos - startOfName >= TextEditorSettings::completionSettings().m_characterThreshold) {
const QChar firstCharacter = m_interface->characterAt(startOfName); const QChar firstCharacter = m_interface->characterAt(startOfName);
if (isValidFirstIdentifierChar(firstCharacter)) { if (isValidFirstIdentifierChar(firstCharacter)) {
// Finally check that we're not inside a comment or string (code copied from startOfOperator) return !isInCommentOrString(m_interface.data(),
QTextCursor tc(m_interface->textDocument()); m_interface->languageFeatures());
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;
}
}
} }
} }
} }

View File

@@ -39,11 +39,15 @@
#include <coreplugin/idocument.h> #include <coreplugin/idocument.h>
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <projectexplorer/session.h> #include <projectexplorer/session.h>
#include <texteditor/codeassist/assistinterface.h>
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
#include <cplusplus/Overview.h> #include <cplusplus/BackwardsScanner.h>
#include <cplusplus/LookupContext.h> #include <cplusplus/LookupContext.h>
#include <cplusplus/Overview.h>
#include <cplusplus/SimpleLexer.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/porting.h>
#include <utils/textutils.h> #include <utils/textutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -300,6 +304,40 @@ const Macro *findCanonicalMacro(const QTextCursor &cursor, Document::Ptr documen
return nullptr; 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() CppCodeModelSettings *codeModelSettings()
{ {
return Internal::CppEditorPlugin::instance()->codeModelSettings(); return Internal::CppEditorPlugin::instance()->codeModelSettings();

View File

@@ -35,6 +35,7 @@
#include <cplusplus/ASTVisitor.h> #include <cplusplus/ASTVisitor.h>
#include <cplusplus/CppDocument.h> #include <cplusplus/CppDocument.h>
#include <cplusplus/Token.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QChar; class QChar;
@@ -48,6 +49,8 @@ class Symbol;
class LookupContext; class LookupContext;
} // namespace CPlusPlus } // namespace CPlusPlus
namespace TextEditor { class AssistInterface; }
namespace CppEditor { namespace CppEditor {
class CppRefactoringFile; class CppRefactoringFile;
class ProjectInfo; class ProjectInfo;
@@ -71,6 +74,9 @@ bool CPPEDITOR_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,
const CPlusPlus::Macro CPPEDITOR_EXPORT *findCanonicalMacro(const QTextCursor &cursor, const CPlusPlus::Macro CPPEDITOR_EXPORT *findCanonicalMacro(const QTextCursor &cursor,
CPlusPlus::Document::Ptr document); CPlusPlus::Document::Ptr document);
bool CPPEDITOR_EXPORT isInCommentOrString(const TextEditor::AssistInterface *interface,
CPlusPlus::LanguageFeatures features);
enum class CacheUsage { ReadWrite, ReadOnly }; enum class CacheUsage { ReadWrite, ReadOnly };
QString CPPEDITOR_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = nullptr, QString CPPEDITOR_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = nullptr,