diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp index aabad07a19d16f332711c95433cf8485c726295e..d252b0f2a4a73155226dccb0a58a8a1bb6ae9638 100644 --- a/src/libs/cplusplus/Overview.cpp +++ b/src/libs/cplusplus/Overview.cpp @@ -158,6 +158,8 @@ QString Overview::prettyType(const FullySpecifiedType &ty, * \param the name for the named-type to use * \param the control where the name is registered * \return the pretty-printed name + * + * \todo Remove this method, and do it "for real" using the class CPlusPlus::Rewrite. */ QString Overview::prettyTypeWithName(const FullySpecifiedType &type, const Name *name, diff --git a/src/plugins/cppeditor/cppdeclfromdef.cpp b/src/plugins/cppeditor/cppdeclfromdef.cpp index 4d87c02bfcfbe5a73f8868967084a72e93ce1ea9..034c478b1125cb88e5220c8ca7f7cc69b14084df 100644 --- a/src/plugins/cppeditor/cppdeclfromdef.cpp +++ b/src/plugins/cppeditor/cppdeclfromdef.cpp @@ -54,6 +54,7 @@ using CppEditor::CppRefactoringChanges; namespace { +//! \todo This method should probably be changed when Overview#prettyTypeWithName is removed. QString prettyMinimalType(const FullySpecifiedType &ty, const LookupContext &context, Scope *source, @@ -144,7 +145,7 @@ QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &stat generateDeclaration(state, method, targetBinding))); - } // ### TODO: support insertion into namespaces + } //! \todo support insertion into namespaces } } diff --git a/src/plugins/cppeditor/cppquickfix.h b/src/plugins/cppeditor/cppquickfix.h index 1e4ca58876ee8e6e24e51d062ca11df7b382e8e5..42399ebdc8e78182bf675f61ba7c58efb55d0cb9 100644 --- a/src/plugins/cppeditor/cppquickfix.h +++ b/src/plugins/cppeditor/cppquickfix.h @@ -143,10 +143,21 @@ public: virtual ~CppQuickFixFactory(); virtual QList<TextEditor::QuickFixOperation::Ptr> matchingOperations(TextEditor::QuickFixState *state); + /*! + Implement this method to match and create the appropriate + CppQuickFixOperation objects. + */ virtual QList<CppQuickFixOperation::Ptr> match(const CppQuickFixState &state) = 0; protected: + /*! + Creates a list of 1 single element: the shared-pointer to the given + operation. This shared-pointer takes over the ownership (meaning the + responsibility to delete the operation). + */ static QList<CppQuickFixOperation::Ptr> singleResult(CppQuickFixOperation *operation); + + /// Utility method which creates an empty list. static QList<CppQuickFixOperation::Ptr> noResult(); }; @@ -165,6 +176,7 @@ public: virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const; + /// Registers all quick-fixes in this plug-in as auto-released objects. static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn); }; diff --git a/src/plugins/designer/qtcreatorintegration.cpp b/src/plugins/designer/qtcreatorintegration.cpp index abe3881d31c722a1d9c09d772b17698ac6064ae4..9ebbc59903067b18997d8fde1e6c3853631cd43d 100644 --- a/src/plugins/designer/qtcreatorintegration.cpp +++ b/src/plugins/designer/qtcreatorintegration.cpp @@ -262,19 +262,6 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) return Document::Ptr(); } -static bool isEndingQuote(const QString &contents, int quoteIndex) -{ - bool endingQuote = true; - if (quoteIndex > 0) { - int previous = 1; - while (contents.at(quoteIndex - previous) == QLatin1Char('\\')) { - previous++; - endingQuote = !endingQuote; - } - } - return endingQuote; -} - static inline ITextEditable *editableAt(const QString &fileName, int line, int column) { return qobject_cast<ITextEditable *>(TextEditor::BaseTextEditor::openEditorAt(fileName, line, column)); @@ -291,7 +278,7 @@ static void addDeclaration(Document::Ptr doc, const Class *cl, const QString &fu const InsertionLocation loc = find.methodDeclarationInClass(cl, InsertionPointLocator::PrivateSlot); // - // ### FIXME: change this to use the Refactoring changes. + //! \todo change this to use the Refactoring changes. // if (ITextEditable *editable = editableAt(docFileName, loc.line(), loc.column() - 1)) { @@ -332,13 +319,13 @@ static Document::Ptr addDefinition(const CPlusPlus::Snapshot &docTable, // we take only those documents which have the same filename if (headerBaseName == sourceFI.baseName()) { // - // ### FIXME: change this to use the Refactoring changes. + //! \todo change this to use the Refactoring changes. // if (ITextEditable *editable = editableAt(doc->fileName(), 0, 0)) { // - // ### FIXME: use the InsertionPointLocator to insert at the correct place. + //! \todo use the InsertionPointLocator to insert at the correct place. // (we'll have to extend that class first to do definition insertions) const QString contents = editable->contents(); diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index eccf2eb12127fb65d09232bdb61011a251215aa7..238197a306e504215c29882fbaebd0955123b7ab 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -55,6 +55,9 @@ namespace QmlJS { class IContextPane; } +/*! + The top-level namespace of the QmlJSEditor plug-in. + */ namespace QmlJSEditor { class Highlighter; diff --git a/src/plugins/qmljseditor/qmljsquickfix.h b/src/plugins/qmljseditor/qmljsquickfix.h index 97f26141f466549231a9a3433f629be56a3e2f2c..3b5938ed1828586d1aa49bc47f12fd6eb4e6f8f5 100644 --- a/src/plugins/qmljseditor/qmljsquickfix.h +++ b/src/plugins/qmljseditor/qmljsquickfix.h @@ -51,43 +51,76 @@ namespace Internal { class QmlJSQuickFixCollector; } // end of namespace Internal +/*! + Specialized QuickFixState for QML/JavaScript quick-fixes. + + This specialized state for QML/JavaScript quick-fixes also holds the + QmlJSEditor::Internal::SemanticInfo for the document in the editor. + */ class QmlJSQuickFixState: public TextEditor::QuickFixState { friend class Internal::QmlJSQuickFixCollector; public: + /// Creates a new state for the given editor. QmlJSQuickFixState(TextEditor::BaseTextEditor *editor); typedef Utils::ChangeSet::Range Range; Internal::SemanticInfo semanticInfo() const; + + /// \returns the snapshot holding the document of the editor. QmlJS::Snapshot snapshot() const; + + /// \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; private: Internal::SemanticInfo _semanticInfo; }; +/*! + A quick-fix operation for the QML/JavaScript editor, which works on a + QmlJSQuickFixState . + */ class QmlJSQuickFixOperation: public TextEditor::QuickFixOperation { Q_DISABLE_COPY(QmlJSQuickFixOperation) public: + /*! + Creates a new QmlJSQuickFixOperation. + + This operation will copy the complete state, in order to be able to perform + its changes later on. + + \param state The state for which this operation was created. + \param priority The priority for this operation. + */ QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority = -1); virtual ~QmlJSQuickFixOperation(); +protected: + /// \returns A const-reference to the state of the operation. const QmlJSQuickFixState &state() const; -protected: + /// \returns The name of the file for for which this operation is invoked. QString fileName() const; + /// \returns The refactoring changes associated with this quick-fix operation. QmlJSRefactoringChanges *refactoringChanges() 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); } @@ -105,6 +138,11 @@ public: virtual ~QmlJSQuickFixFactory(); virtual QList<TextEditor::QuickFixOperation::Ptr> matchingOperations(TextEditor::QuickFixState *state); + + /*! + Implement this method to match and create the appropriate + QmlJSQuickFixOperation objects. + */ virtual QList<QmlJSQuickFixOperation::Ptr> match(const QmlJSQuickFixState &state) = 0; }; @@ -123,6 +161,7 @@ public: virtual QList<TextEditor::QuickFixFactory *> quickFixFactories() const; + /// Registers all quick-fixes in this plug-in as auto-released objects. static void registerQuickFixes(ExtensionSystem::IPlugin *plugIn); }; diff --git a/src/plugins/texteditor/quickfix.cpp b/src/plugins/texteditor/quickfix.cpp index 415c0119abcf01490f6731451a66b16690aac417..a9d18f141c3fae75e415f69f1227a25df2fac9ea 100644 --- a/src/plugins/texteditor/quickfix.cpp +++ b/src/plugins/texteditor/quickfix.cpp @@ -59,11 +59,6 @@ QTextCursor QuickFixState::textCursor() const return _textCursor; } -void QuickFixState::setCursor(const QTextCursor &cursor) -{ - _textCursor = cursor; -} - int QuickFixState::selectionStart() const { return _textCursor.selectionStart(); diff --git a/src/plugins/texteditor/quickfix.h b/src/plugins/texteditor/quickfix.h index 342fce4ecfe603e1d967c5b19a3dff6b1ca54455..51b604ffe39fb668e764c6a653b93b81ad5c3810 100644 --- a/src/plugins/texteditor/quickfix.h +++ b/src/plugins/texteditor/quickfix.h @@ -43,32 +43,51 @@ namespace TextEditor { class BaseTextEditor; +/*! + State of the editor on which the QuickFixFactory and the QuickFixOperation work. + + This class contains a reference + */ class TEXTEDITOR_EXPORT QuickFixState { public: + /// Creates a new state object for the given text editor. QuickFixState(TextEditor::BaseTextEditor *editor); virtual ~QuickFixState(); TextEditor::BaseTextEditor *editor() const; + /*! + \returns A QTextCursor positioned as the editor's visible cursor, including + possible selections. + */ QTextCursor textCursor() const; - void setCursor(const QTextCursor &cursor); + /// \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. + /*! + 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 TextEditor::RefactoringChanges::Range range(int start, int end); private: @@ -76,6 +95,15 @@ private: QTextCursor _textCursor; }; +/*! + Class to perform a single quick-fix. + + Quick-fix operations cannot be copied, and must be passed around as explicitly + shared pointers ( QuickFixOperation::Ptr ). + + Subclasses should make sure that they copy parts of, or the whole QuickFixState , + which are needed to perform the quick-fix operation. + */ class TEXTEDITOR_EXPORT QuickFixOperation { Q_DISABLE_COPY(QuickFixOperation) @@ -87,13 +115,35 @@ public: QuickFixOperation(int priority = -1); virtual ~QuickFixOperation(); + /*! + \returns The priority for this quick-fix. See the QuickFixCollector for more + information. + */ virtual int priority() const; + + /// Sets the priority for this quick-fix operation. void setPriority(int priority); + + /*! + \returns The description for this quick-fix. This description is shown to the + user. + */ virtual QString description() const; + + /// Sets the description for this quick-fix, which will be shown to the user. void setDescription(const QString &description); + /*! + Perform this quick-fix's operation. + + This implementation will call perform and then RefactoringChanges::apply() . + */ virtual void perform(); + /*! + Subclasses should implement this method to do the actual changes by using the + RefactoringChanges. + */ virtual void createChanges() = 0; protected: @@ -105,6 +155,17 @@ private: QString _description; }; +/*! + The QuickFixFactory is responsible for generating QuickFixOperation s which are + applicable to the given QuickFixState. + + A QuickFixFactory should not have any state -- it can be invoked multiple times + for different QuickFixState objects to create the matching operations, before any + of those operations are applied (or released). + + This way, a single factory can be used by multiple editors, and a single editor + can have multiple QuickFixCollector objects for different parts of the code. + */ class TEXTEDITOR_EXPORT QuickFixFactory: public QObject { Q_OBJECT @@ -113,9 +174,20 @@ public: QuickFixFactory(QObject *parent = 0); virtual ~QuickFixFactory() = 0; + /*! + \returns A list of operations which can be performed for the given state. + */ virtual QList<QuickFixOperation::Ptr> matchingOperations(QuickFixState *state) = 0; }; +/*! + A completion collector which will use the QuickFixFactory classes to generate + quickfixes for the given editor. + + All QuickFixFactory instances returned by #quickFixFactories are queried for + possible quick-fix operations. The operations(s) with the highest priority are + stored, and can be queried by calling #quickFixes . + */ class TEXTEDITOR_EXPORT QuickFixCollector: public TextEditor::IQuickFixCollector { Q_OBJECT @@ -124,16 +196,22 @@ public: QuickFixCollector(); virtual ~QuickFixCollector(); - QList<TextEditor::QuickFixOperation::Ptr> quickFixes() const { return _quickFixes; } + QList<TextEditor::QuickFixOperation::Ptr> quickFixes() const + { return _quickFixes; } virtual TextEditor::ITextEditable *editor() const; virtual int startPosition() const; virtual bool triggersCompletion(TextEditor::ITextEditable *editor); virtual int startCompletion(TextEditor::ITextEditable *editor); virtual void completions(QList<TextEditor::CompletionItem> *completions); + + /// See IQuickFixCollector::fix virtual void fix(const TextEditor::CompletionItem &item); + + /// See ICompletionCollector::cleanup . virtual void cleanup(); + /// Called from #startCompletion to create a QuickFixState . virtual TextEditor::QuickFixState *initializeCompletion(BaseTextEditor *editable) = 0; virtual QList<QuickFixFactory *> quickFixFactories() const = 0; diff --git a/src/plugins/texteditor/refactoringchanges.h b/src/plugins/texteditor/refactoringchanges.h index be3371bcc117b9be157cc68ce8c9fb82a5f97c1f..e4a5cd6eb8c0e1ec44d37d777f088be542d5d97f 100644 --- a/src/plugins/texteditor/refactoringchanges.h +++ b/src/plugins/texteditor/refactoringchanges.h @@ -40,6 +40,10 @@ namespace TextEditor { +/*! + This class batches changes to multiple file, which are applied as a single big + change. + */ class TEXTEDITOR_EXPORT RefactoringChanges { public: @@ -56,6 +60,11 @@ public: void reindent(const QString &fileName, const Range &range); + /*! + Applies all changes to open editors or to text files. + + \return The list of changed files, including newly-created ones. + */ virtual QStringList apply(); int positionInFile(const QString &fileName, int line, int column = 0) const; diff --git a/tests/auto/cplusplus/codegen/tst_codegen.cpp b/tests/auto/cplusplus/codegen/tst_codegen.cpp index 60b66b6b97b80a8c8e23d269f296ccc7ee6c2d19..c53dfad3cdd3a604ef08097c5361ccc9fce932ab 100644 --- a/tests/auto/cplusplus/codegen/tst_codegen.cpp +++ b/tests/auto/cplusplus/codegen/tst_codegen.cpp @@ -13,6 +13,10 @@ #include <QtDebug> #include <QTextDocument> +/*! + Tests for various parts of the code generation. Well, okay, currently it only + tests the InsertionPointLocator. + */ using namespace CPlusPlus; class tst_Codegen: public QObject @@ -29,16 +33,18 @@ private slots: void qtdesigner_integration(); }; -void tst_Codegen::public_in_nonempty_class() +/*! + Should insert at line 3, column 1, with "public:\n" as prefix and without suffix. + */ +void tst_Codegen::public_in_empty_class() { const QByteArray src = "\n" "class Foo\n" // line 1 "{\n" - "public:\n" // line 3 - "};\n" // line 4 + "};\n" "\n"; - Document::Ptr doc = Document::create("public_in_nonempty_class"); + Document::Ptr doc = Document::create("public_in_empty_class"); doc->setSource(src); doc->parse(); doc->check(); @@ -52,23 +58,29 @@ void tst_Codegen::public_in_nonempty_class() QCOMPARE(mainWindow->column(), 7U); InsertionPointLocator find(doc); - InsertionLocation loc = find.methodDeclarationInClass(mainWindow, InsertionPointLocator::Public); + InsertionLocation loc = find.methodDeclarationInClass( + mainWindow, + InsertionPointLocator::Public); QVERIFY(loc.isValid()); - QVERIFY(loc.prefix().isEmpty()); + QCOMPARE(loc.prefix(), QLatin1String("public:\n")); QVERIFY(loc.suffix().isEmpty()); - QCOMPARE(loc.line(), 4U); + QCOMPARE(loc.line(), 3U); QCOMPARE(loc.column(), 1U); } -void tst_Codegen::public_in_empty_class() +/*! + Should insert at line 3, column 1, without prefix and without suffix. + */ +void tst_Codegen::public_in_nonempty_class() { const QByteArray src = "\n" "class Foo\n" // line 1 "{\n" - "};\n" + "public:\n" // line 3 + "};\n" // line 4 "\n"; - Document::Ptr doc = Document::create("public_in_empty_class"); + Document::Ptr doc = Document::create("public_in_nonempty_class"); doc->setSource(src); doc->parse(); doc->check(); @@ -82,14 +94,19 @@ void tst_Codegen::public_in_empty_class() QCOMPARE(mainWindow->column(), 7U); InsertionPointLocator find(doc); - InsertionLocation loc = find.methodDeclarationInClass(mainWindow, InsertionPointLocator::Public); + InsertionLocation loc = find.methodDeclarationInClass( + mainWindow, + InsertionPointLocator::Public); QVERIFY(loc.isValid()); - QCOMPARE(loc.prefix(), QLatin1String("public:\n")); + QVERIFY(loc.prefix().isEmpty()); QVERIFY(loc.suffix().isEmpty()); - QCOMPARE(loc.line(), 3U); + QCOMPARE(loc.line(), 4U); QCOMPARE(loc.column(), 1U); } +/*! + Should insert at line 3, column 1, with "public:\n" as prefix and "\n suffix. + */ void tst_Codegen::public_before_protected() { const QByteArray src = "\n" @@ -113,7 +130,9 @@ void tst_Codegen::public_before_protected() QCOMPARE(mainWindow->column(), 7U); InsertionPointLocator find(doc); - InsertionLocation loc = find.methodDeclarationInClass(mainWindow, InsertionPointLocator::Public); + InsertionLocation loc = find.methodDeclarationInClass( + mainWindow, + InsertionPointLocator::Public); QVERIFY(loc.isValid()); QCOMPARE(loc.prefix(), QLatin1String("public:\n")); QCOMPARE(loc.suffix(), QLatin1String("\n")); @@ -121,6 +140,10 @@ void tst_Codegen::public_before_protected() QCOMPARE(loc.line(), 3U); } +/*! + Should insert at line 4, column 1, with "private:\n" as prefix and without + suffix. + */ void tst_Codegen::private_after_protected() { const QByteArray src = "\n" @@ -144,7 +167,9 @@ void tst_Codegen::private_after_protected() QCOMPARE(mainWindow->column(), 7U); InsertionPointLocator find(doc); - InsertionLocation loc = find.methodDeclarationInClass(mainWindow, InsertionPointLocator::Private); + InsertionLocation loc = find.methodDeclarationInClass( + mainWindow, + InsertionPointLocator::Private); QVERIFY(loc.isValid()); QCOMPARE(loc.prefix(), QLatin1String("private:\n")); QVERIFY(loc.suffix().isEmpty()); @@ -152,6 +177,10 @@ void tst_Codegen::private_after_protected() QCOMPARE(loc.line(), 4U); } +/*! + Should insert at line 4, column 1, with "protected:\n" as prefix and without + suffix. + */ void tst_Codegen::protected_in_nonempty_class() { const QByteArray src = "\n" @@ -175,7 +204,9 @@ void tst_Codegen::protected_in_nonempty_class() QCOMPARE(mainWindow->column(), 7U); InsertionPointLocator find(doc); - InsertionLocation loc = find.methodDeclarationInClass(mainWindow, InsertionPointLocator::Protected); + InsertionLocation loc = find.methodDeclarationInClass( + mainWindow, + InsertionPointLocator::Protected); QVERIFY(loc.isValid()); QCOMPARE(loc.prefix(), QLatin1String("protected:\n")); QVERIFY(loc.suffix().isEmpty()); @@ -183,6 +214,9 @@ void tst_Codegen::protected_in_nonempty_class() QCOMPARE(loc.line(), 4U); } +/*! + Should insert at line 4, column 1, with "protected\n" as prefix and "\n" suffix. + */ void tst_Codegen::protected_betwee_public_and_private() { const QByteArray src = "\n" @@ -207,7 +241,9 @@ void tst_Codegen::protected_betwee_public_and_private() QCOMPARE(mainWindow->column(), 7U); InsertionPointLocator find(doc); - InsertionLocation loc = find.methodDeclarationInClass(mainWindow, InsertionPointLocator::Protected); + InsertionLocation loc = find.methodDeclarationInClass( + mainWindow, + InsertionPointLocator::Protected); QVERIFY(loc.isValid()); QCOMPARE(loc.prefix(), QLatin1String("protected:\n")); QCOMPARE(loc.suffix(), QLatin1String("\n")); @@ -215,6 +251,13 @@ void tst_Codegen::protected_betwee_public_and_private() QCOMPARE(loc.line(), 4U); } +/*! + Should insert at line 18, column 1, with "private slots:\n" as prefix and "\n" + as suffix. + + This is the typical Qt Designer case, with test-input like what the integration + generates. + */ void tst_Codegen::qtdesigner_integration() { const QByteArray src = "/**** Some long (C)opyright notice ****/\n" @@ -255,7 +298,9 @@ void tst_Codegen::qtdesigner_integration() QCOMPARE(mainWindow->column(), 7U); InsertionPointLocator find(doc); - InsertionLocation loc = find.methodDeclarationInClass(mainWindow, InsertionPointLocator::PrivateSlot); + InsertionLocation loc = find.methodDeclarationInClass( + mainWindow, + InsertionPointLocator::PrivateSlot); QVERIFY(loc.isValid()); QCOMPARE(loc.prefix(), QLatin1String("private slots:\n")); QCOMPARE(loc.suffix(), QLatin1String("\n"));