aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/cppeditor/cppquickfixes.cpp
diff options
context:
space:
mode:
authorhjk <hjk@qt.io>2017-12-18 16:56:50 +0100
committerhjk <hjk@qt.io>2018-01-03 07:36:11 +0000
commit0e687d6a4f8ccbacdeefc43c7ecdbbc3d7814a82 (patch)
treeefb8116e3f9e3e783bb91471a0025a8749c9d63b /src/plugins/cppeditor/cppquickfixes.cpp
parent915d5cf259fd8e03a30af5f72e92ddfed58930ea (diff)
CppEditor: Normalize WrapStringLiteral and RewriteLogicalAnd interface
Slims down publicly visible interface and could be one step towards replacing the CppQuickFixFactory derived classes by plain stand-alone functions. Change-Id: I9c6a8bcbd8481e14fb21dd41b11a1e6153a35e4b Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
Diffstat (limited to 'src/plugins/cppeditor/cppquickfixes.cpp')
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp191
1 files changed, 106 insertions, 85 deletions
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 8a2a2ad3263..ee12f960b7f 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -608,6 +608,8 @@ void RewriteLogicalAnd::match(const CppQuickFixInterface &interface, QuickFixOpe
QSharedPointer<RewriteLogicalAndOp> op(new RewriteLogicalAndOp(interface));
+ ASTMatcher matcher;
+
if (expression->match(op->pattern, &matcher) &&
file->tokenAt(op->pattern->binary_op_token).is(T_AMPER_AMPER) &&
file->tokenAt(op->left->unary_op_token).is(T_EXCLAIM) &&
@@ -619,7 +621,7 @@ void RewriteLogicalAnd::match(const CppQuickFixInterface &interface, QuickFixOpe
}
}
-bool SplitSimpleDeclaration::checkDeclaration(SimpleDeclarationAST *declaration)
+static bool checkDeclarationForSplit(SimpleDeclarationAST *declaration)
{
if (!declaration->semicolon_token)
return false;
@@ -714,7 +716,7 @@ void SplitSimpleDeclaration::match(const CppQuickFixInterface &interface,
if (CoreDeclaratorAST *coreDecl = node->asCoreDeclarator()) {
core_declarator = coreDecl;
} else if (SimpleDeclarationAST *simpleDecl = node->asSimpleDeclaration()) {
- if (checkDeclaration(simpleDecl)) {
+ if (checkDeclarationForSplit(simpleDecl)) {
SimpleDeclarationAST *declaration = simpleDecl;
const int startOfDeclSpecifier = file->startOf(declaration->decl_specifier_list->firstToken());
@@ -1091,10 +1093,82 @@ void SplitIfStatement::match(const CppQuickFixInterface &interface, QuickFixOper
/* Analze a string/character literal like "x", QLatin1String("x") and return the literal
* (StringLiteral or NumericLiteral for characters) and its type
* and the enclosing function (QLatin1String, tr...) */
-ExpressionAST *WrapStringLiteral::analyze(const QList<AST *> &path,
- const CppRefactoringFilePtr &file, Type *type,
- QByteArray *enclosingFunction /* = 0 */,
- CallAST **enclosingFunctionCall /* = 0 */)
+
+enum StringLiteralType { TypeString, TypeObjCString, TypeChar, TypeNone };
+
+enum ActionFlags {
+ EncloseInQLatin1CharAction = 0x1,
+ EncloseInQLatin1StringAction = 0x2,
+ EncloseInQStringLiteralAction = 0x4,
+ EncloseActionMask = EncloseInQLatin1CharAction
+ | EncloseInQLatin1StringAction | EncloseInQStringLiteralAction,
+ TranslateTrAction = 0x8,
+ TranslateQCoreApplicationAction = 0x10,
+ TranslateNoopAction = 0x20,
+ TranslationMask = TranslateTrAction
+ | TranslateQCoreApplicationAction | TranslateNoopAction,
+ RemoveObjectiveCAction = 0x40,
+ ConvertEscapeSequencesToCharAction = 0x100,
+ ConvertEscapeSequencesToStringAction = 0x200,
+ SingleQuoteAction = 0x400,
+ DoubleQuoteAction = 0x800
+};
+
+
+/* Convert single-character string literals into character literals with some
+ * special cases "a" --> 'a', "'" --> '\'', "\n" --> '\n', "\"" --> '"'. */
+static QByteArray stringToCharEscapeSequences(const QByteArray &content)
+{
+ if (content.size() == 1)
+ return content.at(0) == '\'' ? QByteArray("\\'") : content;
+ if (content.size() == 2 && content.at(0) == '\\')
+ return content == "\\\"" ? QByteArray(1, '"') : content;
+ return QByteArray();
+}
+
+/* Convert character literal into a string literal with some special cases
+ * 'a' -> "a", '\n' -> "\n", '\'' --> "'", '"' --> "\"". */
+static QByteArray charToStringEscapeSequences(const QByteArray &content)
+{
+ if (content.size() == 1)
+ return content.at(0) == '"' ? QByteArray("\\\"") : content;
+ if (content.size() == 2)
+ return content == "\\'" ? QByteArray("'") : content;
+ return QByteArray();
+}
+
+static QString msgQtStringLiteralDescription(const QString &replacement, int qtVersion)
+{
+ return QApplication::translate("CppTools::QuickFix", "Enclose in %1(...) (Qt %2)")
+ .arg(replacement).arg(qtVersion);
+}
+
+static QString msgQtStringLiteralDescription(const QString &replacement)
+{
+ return QApplication::translate("CppTools::QuickFix", "Enclose in %1(...)").arg(replacement);
+}
+
+static QString stringLiteralReplacement(unsigned actions)
+{
+ if (actions & EncloseInQLatin1CharAction)
+ return QLatin1String("QLatin1Char");
+ if (actions & EncloseInQLatin1StringAction)
+ return QLatin1String("QLatin1String");
+ if (actions & EncloseInQStringLiteralAction)
+ return QLatin1String("QStringLiteral");
+ if (actions & TranslateTrAction)
+ return QLatin1String("tr");
+ if (actions & TranslateQCoreApplicationAction)
+ return QLatin1String("QCoreApplication::translate");
+ if (actions & TranslateNoopAction)
+ return QLatin1String("QT_TRANSLATE_NOOP");
+ return QString();
+}
+
+static ExpressionAST *analyzeStringLiteral(const QList<AST *> &path,
+ const CppRefactoringFilePtr &file, StringLiteralType *type,
+ QByteArray *enclosingFunction = nullptr,
+ CallAST **enclosingFunctionCall = nullptr)
{
*type = TypeNone;
if (enclosingFunction)
@@ -1140,8 +1214,6 @@ namespace {
class WrapStringLiteralOp : public CppQuickFixOperation
{
public:
- typedef WrapStringLiteral Factory;
-
WrapStringLiteralOp(const CppQuickFixInterface &interface, int priority,
unsigned actions, const QString &description, ExpressionAST *literal,
const QString &translationContext = QString())
@@ -1162,46 +1234,46 @@ public:
const int endPos = currentFile->endOf(m_literal);
// kill leading '@'. No need to adapt endPos, that is done by ChangeSet
- if (m_actions & Factory::RemoveObjectiveCAction)
+ if (m_actions & RemoveObjectiveCAction)
changes.remove(startPos, startPos + 1);
// Fix quotes
- if (m_actions & (Factory::SingleQuoteAction | Factory::DoubleQuoteAction)) {
- const QString newQuote((m_actions & Factory::SingleQuoteAction)
+ if (m_actions & (SingleQuoteAction | DoubleQuoteAction)) {
+ const QString newQuote((m_actions & SingleQuoteAction)
? QLatin1Char('\'') : QLatin1Char('"'));
changes.replace(startPos, startPos + 1, newQuote);
changes.replace(endPos - 1, endPos, newQuote);
}
// Convert single character strings into character constants
- if (m_actions & Factory::ConvertEscapeSequencesToCharAction) {
+ if (m_actions & ConvertEscapeSequencesToCharAction) {
StringLiteralAST *stringLiteral = m_literal->asStringLiteral();
QTC_ASSERT(stringLiteral, return ;);
const QByteArray oldContents(currentFile->tokenAt(stringLiteral->literal_token).identifier->chars());
- const QByteArray newContents = Factory::stringToCharEscapeSequences(oldContents);
+ const QByteArray newContents = stringToCharEscapeSequences(oldContents);
QTC_ASSERT(!newContents.isEmpty(), return ;);
if (oldContents != newContents)
changes.replace(startPos + 1, endPos -1, QString::fromLatin1(newContents));
}
// Convert character constants into strings constants
- if (m_actions & Factory::ConvertEscapeSequencesToStringAction) {
+ if (m_actions & ConvertEscapeSequencesToStringAction) {
NumericLiteralAST *charLiteral = m_literal->asNumericLiteral(); // char 'c' constants are numerical.
QTC_ASSERT(charLiteral, return ;);
const QByteArray oldContents(currentFile->tokenAt(charLiteral->literal_token).identifier->chars());
- const QByteArray newContents = Factory::charToStringEscapeSequences(oldContents);
+ const QByteArray newContents = charToStringEscapeSequences(oldContents);
QTC_ASSERT(!newContents.isEmpty(), return ;);
if (oldContents != newContents)
changes.replace(startPos + 1, endPos -1, QString::fromLatin1(newContents));
}
// Enclose in literal or translation function, macro.
- if (m_actions & (Factory::EncloseActionMask | Factory::TranslationMask)) {
+ if (m_actions & (EncloseActionMask | TranslationMask)) {
changes.insert(endPos, QString(QLatin1Char(')')));
- QString leading = Factory::replacement(m_actions);
+ QString leading = stringLiteralReplacement(m_actions);
leading += QLatin1Char('(');
if (m_actions
- & (Factory::TranslateQCoreApplicationAction | Factory::TranslateNoopAction)) {
+ & (TranslateQCoreApplicationAction | TranslateNoopAction)) {
leading += QLatin1Char('"');
leading += m_translationContext;
leading += QLatin1String("\", ");
@@ -1223,11 +1295,11 @@ private:
void WrapStringLiteral::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
{
- Type type = TypeNone;
+ StringLiteralType type = TypeNone;
QByteArray enclosingFunction;
const QList<AST *> &path = interface.path();
CppRefactoringFilePtr file = interface.currentFile();
- ExpressionAST *literal = analyze(path, file, &type, &enclosingFunction);
+ ExpressionAST *literal = analyzeStringLiteral(path, file, &type, &enclosingFunction);
if (!literal || type == TypeNone)
return;
if ((type == TypeChar && enclosingFunction == "QLatin1Char")
@@ -1238,7 +1310,7 @@ void WrapStringLiteral::match(const CppQuickFixInterface &interface, QuickFixOpe
const int priority = path.size() - 1; // very high priority
if (type == TypeChar) {
unsigned actions = EncloseInQLatin1CharAction;
- QString description = msgQtStringLiteralDescription(replacement(actions));
+ QString description = msgQtStringLiteralDescription(stringLiteralReplacement(actions));
result << new WrapStringLiteralOp(interface, priority, actions, description, literal);
if (NumericLiteralAST *charLiteral = literal->asNumericLiteral()) {
const QByteArray contents(file->tokenAt(charLiteral->literal_token).identifier->chars());
@@ -1272,74 +1344,23 @@ void WrapStringLiteral::match(const CppQuickFixInterface &interface, QuickFixOpe
}
actions = EncloseInQLatin1StringAction | objectiveCActions;
result << new WrapStringLiteralOp(interface, priority, actions,
- msgQtStringLiteralDescription(replacement(actions), 4), literal);
+ msgQtStringLiteralDescription(stringLiteralReplacement(actions), 4), literal);
actions = EncloseInQStringLiteralAction | objectiveCActions;
result << new WrapStringLiteralOp(interface, priority, actions,
- msgQtStringLiteralDescription(replacement(actions), 5), literal);
+ msgQtStringLiteralDescription(stringLiteralReplacement(actions), 5), literal);
}
}
-QString WrapStringLiteral::replacement(unsigned actions)
-{
- if (actions & EncloseInQLatin1CharAction)
- return QLatin1String("QLatin1Char");
- if (actions & EncloseInQLatin1StringAction)
- return QLatin1String("QLatin1String");
- if (actions & EncloseInQStringLiteralAction)
- return QLatin1String("QStringLiteral");
- if (actions & TranslateTrAction)
- return QLatin1String("tr");
- if (actions & TranslateQCoreApplicationAction)
- return QLatin1String("QCoreApplication::translate");
- if (actions & TranslateNoopAction)
- return QLatin1String("QT_TRANSLATE_NOOP");
- return QString();
-}
-
-/* Convert single-character string literals into character literals with some
- * special cases "a" --> 'a', "'" --> '\'', "\n" --> '\n', "\"" --> '"'. */
-QByteArray WrapStringLiteral::stringToCharEscapeSequences(const QByteArray &content)
-{
- if (content.size() == 1)
- return content.at(0) == '\'' ? QByteArray("\\'") : content;
- if (content.size() == 2 && content.at(0) == '\\')
- return content == "\\\"" ? QByteArray(1, '"') : content;
- return QByteArray();
-}
-
-/* Convert character literal into a string literal with some special cases
- * 'a' -> "a", '\n' -> "\n", '\'' --> "'", '"' --> "\"". */
-QByteArray WrapStringLiteral::charToStringEscapeSequences(const QByteArray &content)
-{
- if (content.size() == 1)
- return content.at(0) == '"' ? QByteArray("\\\"") : content;
- if (content.size() == 2)
- return content == "\\'" ? QByteArray("'") : content;
- return QByteArray();
-}
-
-inline QString WrapStringLiteral::msgQtStringLiteralDescription(const QString &replacement,
- int qtVersion)
-{
- return QApplication::translate("CppTools::QuickFix", "Enclose in %1(...) (Qt %2)")
- .arg(replacement).arg(qtVersion);
-}
-
-inline QString WrapStringLiteral::msgQtStringLiteralDescription(const QString &replacement)
-{
- return QApplication::translate("CppTools::QuickFix", "Enclose in %1(...)").arg(replacement);
-}
-
void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
QuickFixOperations &result)
{
// Initialize
- WrapStringLiteral::Type type = WrapStringLiteral::TypeNone;
+ StringLiteralType type = TypeNone;
QByteArray enclosingFunction;
const QList<AST *> &path = interface.path();
CppRefactoringFilePtr file = interface.currentFile();
- ExpressionAST *literal = WrapStringLiteral::analyze(path, file, &type, &enclosingFunction);
- if (!literal || type != WrapStringLiteral::TypeString
+ ExpressionAST *literal = analyzeStringLiteral(path, file, &type, &enclosingFunction);
+ if (!literal || type != TypeString
|| isQtStringLiteral(enclosingFunction) || isQtStringTranslation(enclosingFunction))
return;
@@ -1361,7 +1382,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
if (s->type()->isFunctionType()) {
// no context required for tr
result << new WrapStringLiteralOp(interface, path.size() - 1,
- WrapStringLiteral::TranslateTrAction,
+ TranslateTrAction,
description, literal);
return;
}
@@ -1379,7 +1400,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
if (trContext.isEmpty())
trContext = QLatin1String("GLOBAL");
result << new WrapStringLiteralOp(interface, path.size() - 1,
- WrapStringLiteral::TranslateQCoreApplicationAction,
+ TranslateQCoreApplicationAction,
description, literal, trContext);
return;
}
@@ -1387,7 +1408,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
// We need to use Q_TRANSLATE_NOOP
result << new WrapStringLiteralOp(interface, path.size() - 1,
- WrapStringLiteral::TranslateNoopAction,
+ TranslateNoopAction,
description, literal, trContext);
}
@@ -1440,13 +1461,13 @@ void ConvertCStringToNSString::match(const CppQuickFixInterface &interface,
if (!interface.editor()->cppEditorDocument()->isObjCEnabled())
return;
- WrapStringLiteral::Type type = WrapStringLiteral::TypeNone;
+ StringLiteralType type = TypeNone;
QByteArray enclosingFunction;
CallAST *qlatin1Call;
const QList<AST *> &path = interface.path();
- ExpressionAST *literal = WrapStringLiteral::analyze(path, file, &type, &enclosingFunction,
- &qlatin1Call);
- if (!literal || type != WrapStringLiteral::TypeString)
+ ExpressionAST *literal = analyzeStringLiteral(path, file, &type, &enclosingFunction,
+ &qlatin1Call);
+ if (!literal || type != TypeString)
return;
if (!isQtStringLiteral(enclosingFunction))
qlatin1Call = 0;
@@ -2310,7 +2331,7 @@ public:
QStringList values;
};
-Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctxt)
+static Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctxt)
{
foreach (const LookupItem &result, results) {
const FullySpecifiedType fst = result.type();