diff --git a/src/plugins/cppeditor/cppdeclfromdef.cpp b/src/plugins/cppeditor/cppdeclfromdef.cpp index 0730ed8d85ad7d71bd35c663d3b2372b50638755..2af9c94dc9dc64ac360ed1a14ff5fd251714ce9c 100644 --- a/src/plugins/cppeditor/cppdeclfromdef.cpp +++ b/src/plugins/cppeditor/cppdeclfromdef.cpp @@ -113,13 +113,14 @@ private: QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &state) { const QList<AST *> &path = state.path(); + const CppRefactoringFile &file = state.currentFile(); FunctionDefinitionAST *funDef = 0; int idx = 0; for (; idx < path.size(); ++idx) { AST *node = path.at(idx); if (FunctionDefinitionAST *candidate = node->asFunctionDefinition()) { - if (!funDef && state.isCursorOn(candidate) && !state.isCursorOn(candidate->function_body)) + if (!funDef && file.isCursorOn(candidate) && !file.isCursorOn(candidate->function_body)) funDef = candidate; } else if (node->asClassSpecifier()) { return noResult(); diff --git a/src/plugins/cppeditor/cppquickfix.cpp b/src/plugins/cppeditor/cppquickfix.cpp index c85e776f3a678eab3731234e122706b01aa10d0c..49d56dc93674dce23b994530711aac13e7628aa2 100644 --- a/src/plugins/cppeditor/cppquickfix.cpp +++ b/src/plugins/cppeditor/cppquickfix.cpp @@ -86,100 +86,11 @@ const LookupContext &CppQuickFixState::context() const return _context; } -Scope *CppQuickFixState::scopeAt(unsigned index) const +const CppRefactoringFile CppQuickFixState::currentFile() const { - unsigned line, column; - document()->translationUnit()->getTokenStartPosition(index, &line, &column); - return document()->scopeAt(line, column); + return CppRefactoringFile(editor(), document()); } -bool CppQuickFixState::isCursorOn(unsigned tokenIndex) const -{ - QTextCursor tc = textCursor(); - int cursorBegin = tc.selectionStart(); - - int start = startOf(tokenIndex); - int end = endOf(tokenIndex); - - if (cursorBegin >= start && cursorBegin <= end) - return true; - - return false; -} - -bool CppQuickFixState::isCursorOn(const AST *ast) const -{ - QTextCursor tc = textCursor(); - int cursorBegin = tc.selectionStart(); - - int start = startOf(ast); - int end = endOf(ast); - - if (cursorBegin >= start && cursorBegin <= end) - return true; - - return false; -} - -ChangeSet::Range CppQuickFixState::range(unsigned tokenIndex) const -{ - const Token &token = tokenAt(tokenIndex); - unsigned line, column; - document()->translationUnit()->getPosition(token.begin(), &line, &column); - const int start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1; - return ChangeSet::Range(start, start + token.length()); -} - -ChangeSet::Range CppQuickFixState::range(AST *ast) const -{ - return ChangeSet::Range(startOf(ast), endOf(ast)); -} - -int CppQuickFixState::startOf(unsigned index) const -{ - unsigned line, column; - document()->translationUnit()->getPosition(tokenAt(index).begin(), &line, &column); - return editor()->document()->findBlockByNumber(line - 1).position() + column - 1; -} - -int CppQuickFixState::startOf(const AST *ast) const -{ - return startOf(ast->firstToken()); -} - -int CppQuickFixState::endOf(unsigned index) const -{ - unsigned line, column; - document()->translationUnit()->getPosition(tokenAt(index).end(), &line, &column); - return editor()->document()->findBlockByNumber(line - 1).position() + column - 1; -} - -int CppQuickFixState::endOf(const AST *ast) const -{ - if (unsigned end = ast->lastToken()) - return endOf(end - 1); - else - return 0; -} - -void CppQuickFixState::startAndEndOf(unsigned index, int *start, int *end) const -{ - unsigned line, column; - Token token(tokenAt(index)); - document()->translationUnit()->getPosition(token.begin(), &line, &column); - *start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1; - *end = *start + token.length(); -} - -QString CppQuickFixState::textOf(const AST *ast) const -{ - return textOf(startOf(ast), endOf(ast)); -} - -const Token &CppQuickFixState::tokenAt(unsigned index) const -{ - return document()->translationUnit()->tokenAt(index); -} CppQuickFixOperation::CppQuickFixOperation(const CppQuickFixState &state, int priority) : QuickFixOperation(priority) diff --git a/src/plugins/cppeditor/cppquickfix.h b/src/plugins/cppeditor/cppquickfix.h index 53b8a0786e4a6ab6fbb3cdcaa26ea8a700eb5367..0470cde1ed217beab54fc612454e184de7b6f30d 100644 --- a/src/plugins/cppeditor/cppquickfix.h +++ b/src/plugins/cppeditor/cppquickfix.h @@ -62,7 +62,6 @@ class CPPEDITOR_EXPORT CppQuickFixState: public TextEditor::QuickFixState public: CppQuickFixState(TextEditor::BaseTextEditor *editor); - typedef Utils::ChangeSet::Range Range; const QList<CPlusPlus::AST *> &path() const; CPlusPlus::Snapshot snapshot() const; @@ -70,27 +69,12 @@ public: CppEditor::Internal::SemanticInfo semanticInfo() const; const CPlusPlus::LookupContext &context() const; - using TextEditor::QuickFixState::range; - using TextEditor::QuickFixState::textOf; - using TextEditor::QuickFixState::charAt; - - CPlusPlus::Scope *scopeAt(unsigned index) const; - - bool isCursorOn(unsigned tokenIndex) const; - bool isCursorOn(const CPlusPlus::AST *ast) const; - - Range range(unsigned tokenIndex) const; - Range range(CPlusPlus::AST *ast) const; - - const CPlusPlus::Token &tokenAt(unsigned index) const; + const CppRefactoringFile currentFile() const; - int startOf(unsigned index) const; - int startOf(const CPlusPlus::AST *ast) const; - int endOf(unsigned index) const; - int endOf(const CPlusPlus::AST *ast) const; - void startAndEndOf(unsigned index, int *start, int *end) const; - - QString textOf(const CPlusPlus::AST *ast) const; + bool isCursorOn(unsigned tokenIndex) const + { return currentFile().isCursorOn(tokenIndex); } + bool isCursorOn(const CPlusPlus::AST *ast) const + { return currentFile().isCursorOn(ast); } private: QList<CPlusPlus::AST *> _path; @@ -119,18 +103,6 @@ protected: protected: // Utility functions forwarding to CppQuickFixState typedef Utils::ChangeSet::Range Range; - bool isCursorOn(unsigned tokenIndex) const { return state().isCursorOn(tokenIndex); } - bool isCursorOn(const CPlusPlus::AST *ast) const { return state().isCursorOn(ast); } - - Range range(int start, int end) const { return CppQuickFixState::range(start, end); } - Range range(unsigned tokenIndex) const { return state().range(tokenIndex); } - Range range(CPlusPlus::AST *ast) const { return state().range(ast); } - - int startOf(unsigned index) const { return state().startOf(index); } - int startOf(const CPlusPlus::AST *ast) const { return state().startOf(ast); } - int endOf(unsigned index) const { return state().endOf(index); } - int endOf(const CPlusPlus::AST *ast) const { return state().endOf(ast); } - private: CppQuickFixState _state; }; diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 7b9c208505f66de1ebafa47b2a405a53cb101575..a9827749fa588311a34d753fc8bf9d584b616286 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -76,6 +76,7 @@ public: virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state) { QList<CppQuickFixOperation::Ptr> result; + const CppRefactoringFile &file = state.currentFile(); const QList<AST *> &path = state.path(); int index = path.size() - 1; @@ -86,7 +87,7 @@ public: return result; Kind invertToken; - switch (state.tokenAt(binary->binary_op_token).kind()) { + switch (file.tokenAt(binary->binary_op_token).kind()) { case T_LESS_EQUAL: invertToken = T_GREATER; break; @@ -138,7 +139,7 @@ private: // check for ! before parentheses if (nested && priority - 2 >= 0) { negation = state.path()[priority - 2]->asUnaryExpression(); - if (negation && ! state.tokenAt(negation->unary_op_token).is(T_EXCLAIM)) + if (negation && ! state.currentFile().tokenAt(negation->unary_op_token).is(T_EXCLAIM)) negation = 0; } } @@ -153,14 +154,14 @@ private: ChangeSet changes; if (negation) { // can't remove parentheses since that might break precedence - changes.remove(range(negation->unary_op_token)); + changes.remove(currentFile->range(negation->unary_op_token)); } else if (nested) { - changes.insert(state().startOf(nested), "!"); + changes.insert(currentFile->startOf(nested), "!"); } else { - changes.insert(state().startOf(binary), "!("); - changes.insert(state().endOf(binary), ")"); + changes.insert(currentFile->startOf(binary), "!("); + changes.insert(currentFile->endOf(binary), ")"); } - changes.replace(range(binary->binary_op_token), replacement); + changes.replace(currentFile->range(binary->binary_op_token), replacement); currentFile->change(changes); } }; @@ -180,6 +181,7 @@ public: { QList<QuickFixOperation::Ptr> result; const QList<AST *> &path = state.path(); + const CppRefactoringFile &file = state.currentFile(); int index = path.size() - 1; BinaryExpressionAST *binary = path.at(index)->asBinaryExpression(); @@ -189,7 +191,7 @@ public: return result; Kind flipToken; - switch (state.tokenAt(binary->binary_op_token).kind()) { + switch (file.tokenAt(binary->binary_op_token).kind()) { case T_LESS_EQUAL: flipToken = T_GREATER_EQUAL; break; @@ -247,9 +249,9 @@ private: { ChangeSet changes; - changes.flip(range(binary->left_expression), range(binary->right_expression)); + changes.flip(currentFile->range(binary->left_expression), currentFile->range(binary->right_expression)); if (! replacement.isEmpty()) - changes.replace(range(binary->binary_op_token), replacement); + changes.replace(currentFile->range(binary->binary_op_token), replacement); currentFile->change(changes); } @@ -275,6 +277,7 @@ public: QList<QuickFixOperation::Ptr> result; BinaryExpressionAST *expression = 0; const QList<AST *> &path = state.path(); + const CppRefactoringFile &file = state.currentFile(); int index = path.size() - 1; for (; index != -1; --index) { @@ -292,9 +295,9 @@ public: QSharedPointer<Operation> op(new Operation(state)); if (expression->match(op->pattern, &matcher) && - state.tokenAt(op->pattern->binary_op_token).is(T_AMPER_AMPER) && - state.tokenAt(op->left->unary_op_token).is(T_EXCLAIM) && - state.tokenAt(op->right->unary_op_token).is(T_EXCLAIM)) { + file.tokenAt(op->pattern->binary_op_token).is(T_AMPER_AMPER) && + file.tokenAt(op->left->unary_op_token).is(T_EXCLAIM) && + file.tokenAt(op->right->unary_op_token).is(T_EXCLAIM)) { op->setDescription(QApplication::translate("CppTools::QuickFix", "Rewrite Condition Using ||")); op->setPriority(index); result.append(op); @@ -324,16 +327,16 @@ private: virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; - changes.replace(range(pattern->binary_op_token), QLatin1String("||")); - changes.remove(range(left->unary_op_token)); - changes.remove(range(right->unary_op_token)); - const int start = state().startOf(pattern); - const int end = state().endOf(pattern); + changes.replace(currentFile->range(pattern->binary_op_token), QLatin1String("||")); + changes.remove(currentFile->range(left->unary_op_token)); + changes.remove(currentFile->range(right->unary_op_token)); + const int start = currentFile->startOf(pattern); + const int end = currentFile->endOf(pattern); changes.insert(start, QLatin1String("!(")); changes.insert(end, QLatin1String(")")); currentFile->change(changes); - currentFile->indent(range(pattern)); + currentFile->indent(currentFile->range(pattern)); } }; @@ -376,6 +379,7 @@ public: QList<CppQuickFixOperation::Ptr> result; CoreDeclaratorAST *core_declarator = 0; const QList<AST *> &path = state.path(); + const CppRefactoringFile &file = state.currentFile(); for (int index = path.size() - 1; index != -1; --index) { AST *node = path.at(index); @@ -387,10 +391,10 @@ public: if (checkDeclaration(simpleDecl)) { SimpleDeclarationAST *declaration = simpleDecl; - const int cursorPosition = state.selectionStart(); + const int cursorPosition = file.cursor().selectionStart(); - const int startOfDeclSpecifier = state.startOf(declaration->decl_specifier_list->firstToken()); - const int endOfDeclSpecifier = state.endOf(declaration->decl_specifier_list->lastToken() - 1); + const int startOfDeclSpecifier = file.startOf(declaration->decl_specifier_list->firstToken()); + const int endOfDeclSpecifier = file.endOf(declaration->decl_specifier_list->lastToken() - 1); if (cursorPosition >= startOfDeclSpecifier && cursorPosition <= endOfDeclSpecifier) { // the AST node under cursor is a specifier. @@ -427,9 +431,9 @@ private: ChangeSet changes; SpecifierListAST *specifiers = declaration->decl_specifier_list; - int declSpecifiersStart = state().startOf(specifiers->firstToken()); - int declSpecifiersEnd = state().endOf(specifiers->lastToken() - 1); - int insertPos = state().endOf(declaration->semicolon_token); + int declSpecifiersStart = currentFile->startOf(specifiers->firstToken()); + int declSpecifiersEnd = currentFile->endOf(specifiers->lastToken() - 1); + int insertPos = currentFile->endOf(declaration->semicolon_token); DeclaratorAST *prevDeclarator = declaration->declarator_list->value; @@ -439,17 +443,17 @@ private: changes.insert(insertPos, QLatin1String("\n")); changes.copy(declSpecifiersStart, declSpecifiersEnd, insertPos); changes.insert(insertPos, QLatin1String(" ")); - changes.move(range(declarator), insertPos); + changes.move(currentFile->range(declarator), insertPos); changes.insert(insertPos, QLatin1String(";")); - const int prevDeclEnd = state().endOf(prevDeclarator); - changes.remove(prevDeclEnd, state().startOf(declarator)); + const int prevDeclEnd = currentFile->endOf(prevDeclarator); + changes.remove(prevDeclEnd, currentFile->startOf(declarator)); prevDeclarator = declarator; } currentFile->change(changes); - currentFile->indent(range(declaration)); + currentFile->indent(currentFile->range(declaration)); } private: @@ -509,14 +513,14 @@ private: { ChangeSet changes; - const int start = endOf(_statement->firstToken() - 1); + const int start = currentFile->endOf(_statement->firstToken() - 1); changes.insert(start, QLatin1String(" {")); - const int end = endOf(_statement->lastToken() - 1); + const int end = currentFile->endOf(_statement->lastToken() - 1); changes.insert(end, "\n}"); currentFile->change(changes); - currentFile->indent(range(start, end)); + currentFile->indent(Range(start, end)); } private: @@ -580,14 +584,14 @@ private: { ChangeSet changes; - changes.copy(range(core), startOf(condition)); + changes.copy(currentFile->range(core), currentFile->startOf(condition)); - int insertPos = startOf(pattern); - changes.move(range(condition), insertPos); + int insertPos = currentFile->startOf(pattern); + changes.move(currentFile->range(condition), insertPos); changes.insert(insertPos, QLatin1String(";\n")); currentFile->change(changes); - currentFile->indent(range(pattern)); + currentFile->indent(currentFile->range(pattern)); } ASTMatcher matcher; @@ -662,17 +666,17 @@ private: { ChangeSet changes; - changes.insert(startOf(condition), QLatin1String("(")); - changes.insert(endOf(condition), QLatin1String(") != 0")); + changes.insert(currentFile->startOf(condition), QLatin1String("(")); + changes.insert(currentFile->endOf(condition), QLatin1String(") != 0")); - int insertPos = startOf(pattern); - const int conditionStart = startOf(condition); - changes.move(conditionStart, startOf(core), insertPos); - changes.copy(range(core), insertPos); + int insertPos = currentFile->startOf(pattern); + const int conditionStart = currentFile->startOf(condition); + changes.move(conditionStart, currentFile->startOf(core), insertPos); + changes.copy(currentFile->range(core), insertPos); changes.insert(insertPos, QLatin1String(";\n")); currentFile->change(changes); - currentFile->indent(range(pattern)); + currentFile->indent(currentFile->range(pattern)); } ASTMatcher matcher; @@ -732,7 +736,7 @@ public: if (! condition) return noResult(); - Token binaryToken = state.tokenAt(condition->binary_op_token); + Token binaryToken = state.currentFile().tokenAt(condition->binary_op_token); // only accept a chain of ||s or &&s - no mixing if (! splitKind) { @@ -769,7 +773,7 @@ private: virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { - const Token binaryToken = state().tokenAt(condition->binary_op_token); + const Token binaryToken = currentFile->tokenAt(condition->binary_op_token); if (binaryToken.is(T_AMPER_AMPER)) splitAndCondition(currentFile); @@ -781,17 +785,17 @@ private: { ChangeSet changes; - int startPos = startOf(pattern); + int startPos = currentFile->startOf(pattern); changes.insert(startPos, QLatin1String("if (")); - changes.move(range(condition->left_expression), startPos); + changes.move(currentFile->range(condition->left_expression), startPos); changes.insert(startPos, QLatin1String(") {\n")); - const int lExprEnd = endOf(condition->left_expression); - changes.remove(lExprEnd, startOf(condition->right_expression)); - changes.insert(endOf(pattern), QLatin1String("\n}")); + const int lExprEnd = currentFile->endOf(condition->left_expression); + changes.remove(lExprEnd, currentFile->startOf(condition->right_expression)); + changes.insert(currentFile->endOf(pattern), QLatin1String("\n}")); currentFile->change(changes); - currentFile->indent(range(pattern)); + currentFile->indent(currentFile->range(pattern)); } void splitOrCondition(CppRefactoringFile *currentFile) @@ -801,25 +805,25 @@ private: StatementAST *ifTrueStatement = pattern->statement; CompoundStatementAST *compoundStatement = ifTrueStatement->asCompoundStatement(); - int insertPos = endOf(ifTrueStatement); + int insertPos = currentFile->endOf(ifTrueStatement); if (compoundStatement) changes.insert(insertPos, QLatin1String(" ")); else changes.insert(insertPos, QLatin1String("\n")); changes.insert(insertPos, QLatin1String("else if (")); - const int rExprStart = startOf(condition->right_expression); - changes.move(rExprStart, startOf(pattern->rparen_token), insertPos); + const int rExprStart = currentFile->startOf(condition->right_expression); + changes.move(rExprStart, currentFile->startOf(pattern->rparen_token), insertPos); changes.insert(insertPos, QLatin1String(")")); - const int rParenEnd = endOf(pattern->rparen_token); - changes.copy(rParenEnd, endOf(pattern->statement), insertPos); + const int rParenEnd = currentFile->endOf(pattern->rparen_token); + changes.copy(rParenEnd, currentFile->endOf(pattern->statement), insertPos); - const int lExprEnd = endOf(condition->left_expression); - changes.remove(lExprEnd, startOf(condition->right_expression)); + const int lExprEnd = currentFile->endOf(condition->left_expression); + changes.remove(lExprEnd, currentFile->startOf(condition->right_expression)); currentFile->change(changes); - currentFile->indent(range(pattern)); + currentFile->indent(currentFile->range(pattern)); } private: @@ -844,6 +848,7 @@ public: ExpressionAST *literal = 0; Type type = TypeNone; const QList<AST *> &path = state.path(); + const CppRefactoringFile &file = state.currentFile(); if (path.isEmpty()) return noResult(); // nothing to do @@ -852,7 +857,7 @@ public: if (! literal) { literal = path.last()->asNumericLiteral(); - if (!literal || !state.tokenAt(literal->asNumericLiteral()->literal_token).is(T_CHAR_LITERAL)) + if (!literal || !file.tokenAt(literal->asNumericLiteral()->literal_token).is(T_CHAR_LITERAL)) return noResult(); else type = TypeChar; @@ -865,7 +870,7 @@ public: if (call->base_expression) { if (IdExpressionAST *idExpr = call->base_expression->asIdExpression()) { if (SimpleNameAST *functionName = idExpr->name->asSimpleName()) { - const QByteArray id(state.tokenAt(functionName->identifier_token).identifier->chars()); + const QByteArray id(file.tokenAt(functionName->identifier_token).identifier->chars()); if (id == "QT_TRANSLATE_NOOP" || id == "tr" || id == "trUtf8" || (type == TypeString && (id == "QLatin1String" || id == "QLatin1Literal")) @@ -878,7 +883,7 @@ public: } if (type == TypeString) { - if (state.charAt(state.startOf(literal)) == QLatin1Char('@')) + if (file.charAt(file.startOf(literal)) == QLatin1Char('@')) type = TypeObjCString; } return singleResult(new Operation(state, @@ -909,7 +914,7 @@ private: { ChangeSet changes; - const int startPos = startOf(literal); + const int startPos = currentFile->startOf(literal); QLatin1String replacement = (type == TypeChar ? QLatin1String("QLatin1Char(") : QLatin1String("QLatin1String(")); @@ -918,7 +923,7 @@ private: else changes.insert(startPos, replacement); - changes.insert(endOf(literal), ")"); + changes.insert(currentFile->endOf(literal), ")"); currentFile->change(changes); } @@ -962,7 +967,7 @@ public: if (call->base_expression) { if (IdExpressionAST *idExpr = call->base_expression->asIdExpression()) { if (SimpleNameAST *functionName = idExpr->name->asSimpleName()) { - const QByteArray id(state.tokenAt(functionName->identifier_token).identifier->chars()); + const QByteArray id(state.currentFile().tokenAt(functionName->identifier_token).identifier->chars()); if (id == "tr" || id == "trUtf8" || id == "translate" @@ -1030,7 +1035,7 @@ private: { ChangeSet changes; - const int startPos = startOf(m_literal); + const int startPos = currentFile->startOf(m_literal); QString replacement(QLatin1String("tr(")); if (m_option == useQCoreApplicationTranslate) { replacement = QLatin1String("QCoreApplication::translate(\"") @@ -1041,7 +1046,7 @@ private: } changes.insert(startPos, replacement); - changes.insert(endOf(m_literal), QLatin1String(")")); + changes.insert(currentFile->endOf(m_literal), QLatin1String(")")); currentFile->change(changes); } @@ -1058,6 +1063,8 @@ class CStringToNSString: public CppQuickFixFactory public: virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state) { + const CppRefactoringFile &file = state.currentFile(); + if (state.editor()->mimeType() != CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE) return noResult(); @@ -1073,7 +1080,7 @@ public: if (! stringLiteral) return noResult(); - else if (state.charAt(state.startOf(stringLiteral)) == QLatin1Char('@')) + else if (file.charAt(file.startOf(stringLiteral)) == QLatin1Char('@')) return noResult(); // it's already an objc string literal. else if (path.size() > 1) { @@ -1081,7 +1088,7 @@ public: if (call->base_expression) { if (IdExpressionAST *idExpr = call->base_expression->asIdExpression()) { if (SimpleNameAST *functionName = idExpr->name->asSimpleName()) { - const QByteArray id(state.tokenAt(functionName->identifier_token).identifier->chars()); + const QByteArray id(state.currentFile().tokenAt(functionName->identifier_token).identifier->chars()); if (id == "QLatin1String" || id == "QLatin1Literal") qlatin1Call = call; @@ -1112,10 +1119,10 @@ private: ChangeSet changes; if (qlatin1Call) { - changes.replace(startOf(qlatin1Call), startOf(stringLiteral), QLatin1String("@")); - changes.remove(endOf(stringLiteral), endOf(qlatin1Call)); + changes.replace(currentFile->startOf(qlatin1Call), currentFile->startOf(stringLiteral), QLatin1String("@")); + changes.remove(currentFile->endOf(stringLiteral), currentFile->endOf(qlatin1Call)); } else { - changes.insert(startOf(stringLiteral), "@"); + changes.insert(currentFile->startOf(stringLiteral), "@"); } currentFile->change(changes); @@ -1151,6 +1158,7 @@ public: QList<QuickFixOperation::Ptr> result; const QList<AST *> &path = state.path(); + const CppRefactoringFile &file = state.currentFile(); if (path.isEmpty()) return result; // nothing to do @@ -1160,7 +1168,7 @@ public: if (! literal) return result; - Token token = state.tokenAt(literal->asNumericLiteral()->literal_token); + Token token = file.tokenAt(literal->asNumericLiteral()->literal_token); if (!token.is(T_NUMERIC_LITERAL)) return result; const NumericLiteral *numeric = token.number; @@ -1182,7 +1190,7 @@ public: return result; const int priority = path.size() - 1; // very high priority - const int start = state.startOf(literal); + const int start = file.startOf(literal); const char * const str = numeric->chars(); if (!numeric->isHex()) { @@ -1412,12 +1420,12 @@ private: virtual void performChanges(CppRefactoringFile *currentFile, CppRefactoringChanges *) { ChangeSet changes; - int start = endOf(compoundStatement->lbrace_token); + int start = currentFile->endOf(compoundStatement->lbrace_token); changes.insert(start, QLatin1String("\ncase ") + values.join(QLatin1String(":\nbreak;\ncase ")) + QLatin1String(":\nbreak;")); currentFile->change(changes); - currentFile->indent(range(compoundStatement)); + currentFile->indent(currentFile->range(compoundStatement)); } CompoundStatementAST *compoundStatement; @@ -1528,9 +1536,9 @@ private: if (best.isEmpty()) best = headerFile; - int pos = startOf(1); + int pos = currentFile->startOf(1); - unsigned currentLine = state().textCursor().blockNumber() + 1; + unsigned currentLine = currentFile->cursor().blockNumber() + 1; unsigned bestLine = 0; foreach (const Document::Include &incl, state().document()->includes()) { if (incl.line() < currentLine) @@ -1538,7 +1546,7 @@ private: } if (bestLine) - pos = state().editor()->document()->findBlockByNumber(bestLine).position(); + pos = currentFile->document()->findBlockByNumber(bestLine).position(); Utils::ChangeSet changes; changes.insert(pos, QString("#include <%1>\n").arg(QFileInfo(best).fileName())); @@ -1557,14 +1565,15 @@ public: virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state) { const QList<AST *> &path = state.path(); + const CppRefactoringFile &file = state.currentFile(); for (int index = path.size() - 1; index != -1; --index) { if (BinaryExpressionAST *binary = path.at(index)->asBinaryExpression()) { - if (binary->left_expression && binary->right_expression && state.tokenAt(binary->binary_op_token).is(T_EQUAL)) { + if (binary->left_expression && binary->right_expression && file.tokenAt(binary->binary_op_token).is(T_EQUAL)) { IdExpressionAST *idExpr = binary->left_expression->asIdExpression(); if (state.isCursorOn(binary->left_expression) && idExpr && idExpr->name->asSimpleName() != 0) { SimpleNameAST *nameAST = idExpr->name->asSimpleName(); - const QList<LookupItem> results = state.context().lookup(nameAST->name, state.scopeAt(nameAST->firstToken())); + const QList<LookupItem> results = state.context().lookup(nameAST->name, file.scopeAt(nameAST->firstToken())); Declaration *decl = 0; foreach (const LookupItem &r, results) { if (! r.declaration()) @@ -1603,8 +1612,8 @@ private: { TypeOfExpression typeOfExpression; typeOfExpression.init(state().document(), state().snapshot(), state().context().bindings()); - const QList<LookupItem> result = typeOfExpression(state().textOf(binaryAST->right_expression), - state().scopeAt(binaryAST->firstToken()), + const QList<LookupItem> result = typeOfExpression(currentFile->textOf(binaryAST->right_expression), + currentFile->scopeAt(binaryAST->firstToken()), TypeOfExpression::Preprocess); if (! result.isEmpty()) { @@ -1627,7 +1636,7 @@ private: ty += QLatin1Char(' '); Utils::ChangeSet changes; - changes.insert(startOf(binaryAST), ty); + changes.insert(currentFile->startOf(binaryAST), ty); currentFile->change(changes); } } diff --git a/src/plugins/cppeditor/cpprefactoringchanges.cpp b/src/plugins/cppeditor/cpprefactoringchanges.cpp index 25050360ea26f8bde81d830826ab239b308976b3..762c4cab1269a85773a2a161ec93d742a1af1bef 100644 --- a/src/plugins/cppeditor/cpprefactoringchanges.cpp +++ b/src/plugins/cppeditor/cpprefactoringchanges.cpp @@ -103,6 +103,14 @@ CppRefactoringFile::CppRefactoringFile(const QString &fileName, CppRefactoringCh : RefactoringFile(fileName, refactoringChanges) { } +CppRefactoringFile::CppRefactoringFile(TextEditor::BaseTextEditor *editor, CPlusPlus::Document::Ptr document) + : RefactoringFile() + , m_cppDocument(document) +{ + m_fileName = document->fileName(); + m_editor = editor; +} + Document::Ptr CppRefactoringFile::cppDocument() const { if (!m_cppDocument) { diff --git a/src/plugins/cppeditor/cpprefactoringchanges.h b/src/plugins/cppeditor/cpprefactoringchanges.h index 9a7e21525539141acb6d4b86d2231ed28331157f..92b8c575f658c2b9b8125c2e8bcf1db1615f523d 100644 --- a/src/plugins/cppeditor/cpprefactoringchanges.h +++ b/src/plugins/cppeditor/cpprefactoringchanges.h @@ -48,6 +48,7 @@ class CPPEDITOR_EXPORT CppRefactoringFile: public TextEditor::RefactoringFile public: CppRefactoringFile(); CppRefactoringFile(const QString &fileName, CppRefactoringChanges *refactoringChanges); + CppRefactoringFile(TextEditor::BaseTextEditor *editor, CPlusPlus::Document::Ptr document); CPlusPlus::Document::Ptr cppDocument() const; diff --git a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp index 3b49624be488af88db86e9f6b8f81df959420d49..3f08786114f5275d6075b7f38538692788d48c86 100644 --- a/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp +++ b/src/plugins/qmljseditor/qmljscomponentfromobjectdef.cpp @@ -92,22 +92,22 @@ public: "Move Component into '%1.qml'").arg(m_componentName)); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) + virtual void performChanges(QmlJSRefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) { const QString newFileName = QFileInfo(fileName()).path() + QDir::separator() + m_componentName + QLatin1String(".qml"); QString imports; - UiProgram *prog = state().semanticInfo().document->qmlProgram(); + UiProgram *prog = currentFile->qmljsDocument()->qmlProgram(); if (prog && prog->imports) { - const int start = startPosition(prog->imports->firstSourceLocation()); - const int end = startPosition(prog->members->member->firstSourceLocation()); - imports = state().textOf(start, end); + const int start = currentFile->startOf(prog->imports->firstSourceLocation()); + const int end = currentFile->startOf(prog->members->member->firstSourceLocation()); + imports = currentFile->textOf(start, end); } - const int start = startPosition(m_objDef->firstSourceLocation()); - const int end = startPosition(m_objDef->lastSourceLocation()); - const QString txt = imports + state().textOf(start, end) + const int start = currentFile->startOf(m_objDef->firstSourceLocation()); + const int end = currentFile->startOf(m_objDef->lastSourceLocation()); + const QString txt = imports + currentFile->textOf(start, end) + QLatin1String("}\n"); // stop if we can't create the new file @@ -117,7 +117,7 @@ public: Utils::ChangeSet changes; changes.replace(start, end, m_componentName + QLatin1String(" {\n")); currentFile->change(changes); - currentFile->indent(range(start, end + 1)); + currentFile->indent(Range(start, end + 1)); } }; @@ -126,7 +126,7 @@ public: QList<QmlJSQuickFixOperation::Ptr> ComponentFromObjectDef::match(const QmlJSQuickFixState &state) { QList<QmlJSQuickFixOperation::Ptr> result; - const int pos = state.textCursor().position(); + const int pos = state.currentFile().cursor().position(); QList<Node *> path = state.semanticInfo().astPath(pos); for (int i = path.size() - 1; i >= 0; --i) { diff --git a/src/plugins/qmljseditor/qmljsquickfix.cpp b/src/plugins/qmljseditor/qmljsquickfix.cpp index 5496acb38ae03e6195496ee4b0fde3214e28544d..476bf4f488a806d6d0d6bf5dbafad86fc390c65e 100644 --- a/src/plugins/qmljseditor/qmljsquickfix.cpp +++ b/src/plugins/qmljseditor/qmljsquickfix.cpp @@ -67,9 +67,9 @@ Document::Ptr QmlJSQuickFixState::document() const return _semanticInfo.document; } -unsigned QmlJSQuickFixState::startPosition(const QmlJS::AST::SourceLocation &loc) const +const QmlJSRefactoringFile QmlJSQuickFixState::currentFile() const { - return position(loc.startLine, loc.startColumn); + return QmlJSRefactoringFile(editor(), document()); } QmlJSQuickFixOperation::QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority) @@ -86,7 +86,7 @@ void QmlJSQuickFixOperation::perform() { QmlJSRefactoringChanges refactoring(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(), _state.snapshot()); - TextEditor::RefactoringFile current = refactoring.file(fileName()); + QmlJSRefactoringFile current = refactoring.file(fileName()); performChanges(¤t, &refactoring); } diff --git a/src/plugins/qmljseditor/qmljsquickfix.h b/src/plugins/qmljseditor/qmljsquickfix.h index 271bd226283574a05dc2d90337b6feb6f30ee227..50b248426b4c2088af9f931ee9fe63dee384949b 100644 --- a/src/plugins/qmljseditor/qmljsquickfix.h +++ b/src/plugins/qmljseditor/qmljsquickfix.h @@ -64,7 +64,6 @@ class QmlJSQuickFixState: public TextEditor::QuickFixState public: /// Creates a new state for the given editor. QmlJSQuickFixState(TextEditor::BaseTextEditor *editor); - typedef Utils::ChangeSet::Range Range; Internal::SemanticInfo semanticInfo() const; @@ -74,11 +73,7 @@ public: /// \returns the document of the editor QmlJS::Document::Ptr document() const; - /*! - \returns the offset in the document for the start position of the given - source location. - */ - unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const; + const QmlJSRefactoringFile currentFile() const; private: Internal::SemanticInfo _semanticInfo; @@ -108,7 +103,9 @@ public: virtual void perform(); protected: - virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) = 0; + typedef Utils::ChangeSet::Range Range; + + virtual void performChanges(QmlJSRefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) = 0; /// \returns A const-reference to the state of the operation. const QmlJSQuickFixState &state() const; @@ -116,15 +113,6 @@ protected: /// \returns The name of the file for for which this operation is invoked. QString fileName() const; -protected: // Utility functions forwarding to QmlJSQuickFixState - /// \see QmlJSQuickFixState#startPosition - unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const - { return state().startPosition(loc); } - - /// \see QmlJSQuickFixState#range - static QmlJSQuickFixState::Range range(int start, int end) - { return QmlJSQuickFixState::range(start, end); } - private: QmlJSQuickFixState _state; }; diff --git a/src/plugins/qmljseditor/qmljsquickfixes.cpp b/src/plugins/qmljseditor/qmljsquickfixes.cpp index a610329f5b43f6f3d1a1bf5671204923777b89a1..145bcee52275e627fa60c16d062d628ed0b7719b 100644 --- a/src/plugins/qmljseditor/qmljsquickfixes.cpp +++ b/src/plugins/qmljseditor/qmljsquickfixes.cpp @@ -56,7 +56,7 @@ public: UiObjectInitializer *objectInitializer = 0; - const int pos = state.textCursor().position(); + const int pos = state.currentFile().cursor().position(); if (QmlJS::AST::Node *member = state.semanticInfo().declaringMember(pos)) { if (QmlJS::AST::UiObjectBinding *b = QmlJS::AST::cast<QmlJS::AST::UiObjectBinding *>(member)) { @@ -88,7 +88,7 @@ private: "Split initializer")); } - virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *) + virtual void performChanges(QmlJSRefactoringFile *currentFile, QmlJSRefactoringChanges *) { Q_ASSERT(_objectInitializer != 0); @@ -99,17 +99,17 @@ private: const QmlJS::AST::SourceLocation loc = member->firstSourceLocation(); // insert a newline at the beginning of this binding - changes.insert(startPosition(loc), QLatin1String("\n")); + changes.insert(currentFile->startOf(loc), QLatin1String("\n")); } } // insert a newline before the closing brace - changes.insert(startPosition(_objectInitializer->rbraceToken), + changes.insert(currentFile->startOf(_objectInitializer->rbraceToken), QLatin1String("\n")); currentFile->change(changes); - currentFile->indent(range(startPosition(_objectInitializer->lbraceToken), - startPosition(_objectInitializer->rbraceToken))); + currentFile->indent(Range(currentFile->startOf(_objectInitializer->lbraceToken), + currentFile->startOf(_objectInitializer->rbraceToken))); } }; }; diff --git a/src/plugins/qmljseditor/qmljsrefactoringchanges.cpp b/src/plugins/qmljseditor/qmljsrefactoringchanges.cpp index 4f99c3a7f5891560b3e46651e5fa40949e7764cc..a612b070cdfdbd442e786f92e834c9f52cb698b2 100644 --- a/src/plugins/qmljseditor/qmljsrefactoringchanges.cpp +++ b/src/plugins/qmljseditor/qmljsrefactoringchanges.cpp @@ -45,6 +45,16 @@ QmlJSRefactoringChanges::QmlJSRefactoringChanges(ModelManagerInterface *modelMan Q_ASSERT(modelManager); } +const Snapshot &QmlJSRefactoringChanges::snapshot() const +{ + return m_snapshot; +} + +QmlJSRefactoringFile QmlJSRefactoringChanges::file(const QString &fileName) +{ + return QmlJSRefactoringFile(fileName, this); +} + void QmlJSRefactoringChanges::indentSelection(const QTextCursor &selection) const { // ### shares code with QmlJSTextEditor::indent @@ -68,3 +78,43 @@ void QmlJSRefactoringChanges::fileChanged(const QString &fileName) { m_modelManager->updateSourceFiles(QStringList(fileName), true); } + + +QmlJSRefactoringFile::QmlJSRefactoringFile() +{ } + +QmlJSRefactoringFile::QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges) + : RefactoringFile(fileName, refactoringChanges) +{ } + +QmlJSRefactoringFile::QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document) + : RefactoringFile() + , m_qmljsDocument(document) +{ + m_fileName = document->fileName(); + m_editor = editor; +} + +Document::Ptr QmlJSRefactoringFile::qmljsDocument() const +{ + if (!m_qmljsDocument) { + const QString source = document()->toPlainText(); + const QString name = fileName(); + const Snapshot &snapshot = refactoringChanges()->snapshot(); + + m_qmljsDocument = snapshot.documentFromSource(source, name); + m_qmljsDocument->parse(); + } + + return m_qmljsDocument; +} + +unsigned QmlJSRefactoringFile::startOf(const QmlJS::AST::SourceLocation &loc) const +{ + return position(loc.startLine, loc.startColumn); +} + +QmlJSRefactoringChanges *QmlJSRefactoringFile::refactoringChanges() const +{ + return static_cast<QmlJSRefactoringChanges *>(m_refactoringChanges); +} diff --git a/src/plugins/qmljseditor/qmljsrefactoringchanges.h b/src/plugins/qmljseditor/qmljsrefactoringchanges.h index b68756d718e4a539f19a58ec17501a9ada44eaa7..993012e9c8cb1332696ff6ae142f6441d9751317 100644 --- a/src/plugins/qmljseditor/qmljsrefactoringchanges.h +++ b/src/plugins/qmljseditor/qmljsrefactoringchanges.h @@ -40,12 +40,40 @@ class ModelManagerInterface; namespace QmlJSEditor { +class QmlJSRefactoringChanges; + +class QmlJSRefactoringFile: public TextEditor::RefactoringFile +{ +public: + QmlJSRefactoringFile(); + QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges); + QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document); + + QmlJS::Document::Ptr qmljsDocument() const; + + /*! + \returns the offset in the document for the start position of the given + source location. + */ + unsigned startOf(const QmlJS::AST::SourceLocation &loc) const; + +private: + QmlJSRefactoringChanges *refactoringChanges() const; + + mutable QmlJS::Document::Ptr m_qmljsDocument; +}; + + class QmlJSRefactoringChanges: public TextEditor::RefactoringChanges { public: QmlJSRefactoringChanges(QmlJS::ModelManagerInterface *modelManager, const QmlJS::Snapshot &snapshot); + const QmlJS::Snapshot &snapshot() const; + + QmlJSRefactoringFile file(const QString &fileName); + private: virtual void indentSelection(const QTextCursor &selection) const; virtual void fileChanged(const QString &fileName); diff --git a/src/plugins/texteditor/quickfix.cpp b/src/plugins/texteditor/quickfix.cpp index 6a269dbedaee0eb14e7e1f099f62d3a3156e1329..ca1d62e5db7d5627484c0de603836242587f2c09 100644 --- a/src/plugins/texteditor/quickfix.cpp +++ b/src/plugins/texteditor/quickfix.cpp @@ -41,7 +41,6 @@ using namespace TextEditor; QuickFixState::QuickFixState(TextEditor::BaseTextEditor *editor) : _editor(editor) - , _textCursor(editor->textCursor()) { } @@ -54,45 +53,6 @@ TextEditor::BaseTextEditor *QuickFixState::editor() const return _editor; } -QTextCursor QuickFixState::textCursor() const -{ - return _textCursor; -} - -int QuickFixState::selectionStart() const -{ - return _textCursor.selectionStart(); -} - -int QuickFixState::selectionEnd() const -{ - return _textCursor.selectionEnd(); -} - -int QuickFixState::position(int line, int column) const -{ - QTextDocument *doc = editor()->document(); - return doc->findBlockByNumber(line - 1).position() + column - 1; -} - -QChar QuickFixState::charAt(int offset) const -{ - QTextDocument *doc = _textCursor.document(); - return doc->characterAt(offset); -} - -QString QuickFixState::textOf(int start, int end) const -{ - QTextCursor tc = _textCursor; - tc.setPosition(start); - tc.setPosition(end, QTextCursor::KeepAnchor); - return tc.selectedText(); -} - -Utils::ChangeSet::Range QuickFixState::range(int start, int end) -{ - return Utils::ChangeSet::Range(start, end); -} QuickFixOperation::QuickFixOperation(int priority) { diff --git a/src/plugins/texteditor/quickfix.h b/src/plugins/texteditor/quickfix.h index f632ac32c8b219218b91fc3c6e0354a585931083..d2171cb240b81875a6d7c680a1b49fc87aac13ab 100644 --- a/src/plugins/texteditor/quickfix.h +++ b/src/plugins/texteditor/quickfix.h @@ -56,42 +56,8 @@ public: TextEditor::BaseTextEditor *editor() const; - /*! - \returns A QTextCursor positioned as the editor's visible cursor, including - possible selections. - */ - QTextCursor textCursor() const; - - /// \returns The character offset in the document where the selection starts. - int selectionStart() const; - - /// \returns The character offset in the document where the selection ends. - int selectionEnd() const; - - /*! - Calculates the offset in the document for the given line and column. - - \param line The line number, 1-based. - \param column The column number, 1-based. - \return The offset in the \c QTextDocument of the editor. - */ - int position(int line, int column) const; - - /// \returns The character at the given offset in the editor's text document. - QChar charAt(int offset) const; - - /*! - \returns The text between the given start- and end-offset in the editor's - text document. - */ - QString textOf(int start, int end) const; - - /// Utility method to create a range. - static Utils::ChangeSet::Range range(int start, int end); - private: TextEditor::BaseTextEditor *_editor; - QTextCursor _textCursor; }; /*!