cppinsertdecldef.cpp 7.17 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

30
#include "cppinsertdecldef.h"
31
32
33
34
35
36
37
38

#include <AST.h>
#include <ASTVisitor.h>
#include <CoreTypes.h>
#include <Names.h>
#include <Symbols.h>
#include <TranslationUnit.h>
#include <cplusplus/ASTPath.h>
39
#include <cplusplus/InsertionPointLocator.h>
40
41
42
43
44
45
#include <cplusplus/LookupContext.h>
#include <cplusplus/Overview.h>

#include <QtCore/QCoreApplication>

using namespace CPlusPlus;
46
using namespace CppEditor;
47
48
49
50
51
52
53
using namespace CppEditor::Internal;
using namespace CppTools;

using CppEditor::CppRefactoringChanges;

namespace {

54
55
56
57
class Operation: public CppQuickFixOperation
{
public:
    Operation(const CppQuickFixState &state, int priority,
58
              const QString &targetFileName, const Class *targetSymbol,
59
              InsertionPointLocator::AccessSpec xsSpec,
60
61
62
              const QString &decl)
        : CppQuickFixOperation(state, priority)
        , m_targetFileName(targetFileName)
63
        , m_targetSymbol(targetSymbol)
64
        , m_xsSpec(xsSpec)
65
66
        , m_decl(decl)
    {
67
68
69
70
71
72
73
74
75
76
77
78
79
        QString type;
        switch (xsSpec) {
        case InsertionPointLocator::Public: type = QLatin1String("public"); break;
        case InsertionPointLocator::Protected: type = QLatin1String("protected"); break;
        case InsertionPointLocator::Private: type = QLatin1String("private"); break;
        case InsertionPointLocator::PublicSlot: type = QLatin1String("public slot"); break;
        case InsertionPointLocator::ProtectedSlot: type = QLatin1String("protected slot"); break;
        case InsertionPointLocator::PrivateSlot: type = QLatin1String("private slot"); break;
        default: break;
        }

        setDescription(QCoreApplication::tr("Create %1 Declaration from Definition",
                                            "CppEditor::DeclFromDef").arg(type));
80
    }
81

82
    void performChanges(CppRefactoringFile *, CppRefactoringChanges *refactoring)
83
    {
84
85
        CppRefactoringFile targetFile = refactoring->file(m_targetFileName);
        Document::Ptr targetDoc = targetFile.cppDocument();
86
        InsertionPointLocator locator(targetDoc);
87
        const InsertionLocation loc = locator.methodDeclarationInClass(m_targetSymbol, m_xsSpec);
Roberto Raggi's avatar
Roberto Raggi committed
88
        Q_ASSERT(loc.isValid());
89

90
91
        int targetPosition1 = targetFile.position(loc.line(), loc.column());
        int targetPosition2 = qMax(0, targetFile.position(loc.line(), 1) - 1);
92
93

        Utils::ChangeSet target;
94
        target.insert(targetPosition1, loc.prefix() + m_decl);
95
96
        targetFile.change(target);
        targetFile.indent(Utils::ChangeSet::Range(targetPosition2, targetPosition1));
97

98
        refactoring->activateEditor(m_targetFileName, targetPosition1);
99
100
101
102
    }

private:
    QString m_targetFileName;
103
    const Class *m_targetSymbol;
104
    InsertionPointLocator::AccessSpec m_xsSpec;
105
106
107
108
    QString m_decl;
};

} // anonymous namespace
109

110
QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &state)
111
{
112
    const QList<AST *> &path = state.path();
113
    const CppRefactoringFile &file = state.currentFile();
114
115
116
117
118

    FunctionDefinitionAST *funDef = 0;
    int idx = 0;
    for (; idx < path.size(); ++idx) {
        AST *node = path.at(idx);
mae's avatar
mae committed
119
        if (FunctionDefinitionAST *candidate = node->asFunctionDefinition()) {
120
            if (!funDef && file.isCursorOn(candidate) && !file.isCursorOn(candidate->function_body))
121
                funDef = candidate;
mae's avatar
mae committed
122
        } else if (node->asClassSpecifier()) {
123
            return noResult();
mae's avatar
mae committed
124
        }
125
126
127
    }

    if (!funDef || !funDef->symbol)
128
        return noResult();
129
130
131

    Function *method = funDef->symbol;

132
    if (ClassOrNamespace *targetBinding = state.context().lookupParent(method)) {
133
134
        foreach (Symbol *s, targetBinding->symbols()) {
            if (Class *clazz = s->asClass()) {
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
                QList<CppQuickFixOperation::Ptr> results;
                const QLatin1String fn(clazz->fileName());
                const QString decl = generateDeclaration(state,
                                                         method,
                                                         targetBinding);
                results.append(singleResult(new Operation(state, idx, fn, clazz,
                                                          InsertionPointLocator::Public,
                                                          decl)));
                results.append(singleResult(new Operation(state, idx, fn, clazz,
                                                          InsertionPointLocator::Protected,
                                                          decl)));
                results.append(singleResult(new Operation(state, idx, fn, clazz,
                                                          InsertionPointLocator::Private,
                                                          decl)));
                results.append(singleResult(new Operation(state, idx, fn, clazz,
                                                          InsertionPointLocator::PublicSlot,
                                                          decl)));
                results.append(singleResult(new Operation(state, idx, fn, clazz,
                                                          InsertionPointLocator::ProtectedSlot,
                                                          decl)));
                results.append(singleResult(new Operation(state, idx, fn, clazz,
                                                          InsertionPointLocator::PrivateSlot,
                                                          decl)));
                return results;
159
            } //! \todo support insertion into namespaces
160
161
162
        }
    }

163
    return noResult();
164
165
}

166
QString DeclFromDef::generateDeclaration(const CppQuickFixState &,
167
168
                                         Function *method,
                                         ClassOrNamespace *targetBinding)
169
{
170
171
    Q_UNUSED(targetBinding);

172
    Overview oo;
173
174
175
    oo.setShowFunctionSignatures(true);
    oo.setShowReturnTypes(true);
    oo.setShowArgumentNames(true);
176

177
    QString decl;
178
    decl += oo(method->type(), method->unqualifiedName());
179
    decl += QLatin1String(";\n");
180
181
182

    return decl;
}