cppquickfix.cpp 7.87 KB
Newer Older
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
**
** 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.
**
**************************************************************************/

#include "cppquickfix.h"
#include "cppeditor.h"
32
#include "cppdeclfromdef.h"
33

34
35
36
37
#include <AST.h>
#include <TranslationUnit.h>
#include <Token.h>

38
#include <cplusplus/ASTPath.h>
39
#include <cplusplus/CppDocument.h>
40
#include <cplusplus/ResolveExpression.h>
Tobias Hunger's avatar
Tobias Hunger committed
41
#include <cplusplus/Overview.h>
42
#include <cplusplus/TypeOfExpression.h>
43
#include <cplusplus/DependencyTable.h>
44
#include <cplusplus/CppRewriter.h>
45

46
#include <cppeditor/cppeditor.h>
Roberto Raggi's avatar
Roberto Raggi committed
47
#include <cppeditor/cpprefactoringchanges.h>
48
#include <cpptools/cpptoolsconstants.h>
49
#include <cpptools/cppmodelmanagerinterface.h>
Roberto Raggi's avatar
Roberto Raggi committed
50
#include <extensionsystem/pluginmanager.h>
51
52

#include <QtGui/QTextBlock>
53

54
using namespace CppEditor;
55
using namespace CppEditor::Internal;
56
using namespace TextEditor;
57
using namespace CPlusPlus;
58
using namespace Utils;
59

60
61
62
CppQuickFixState::CppQuickFixState(TextEditor::BaseTextEditor *editor)
    : QuickFixState(editor)
{}
63

64
const QList<AST *> &CppQuickFixState::path() const
65
{
66
67
    return _path;
}
68

69
Snapshot CppQuickFixState::snapshot() const
70
{
71
72
    return _snapshot;
}
73

74
Document::Ptr CppQuickFixState::document() const
75
{
76
77
    return _semanticInfo.doc;
}
78

79
SemanticInfo CppQuickFixState::semanticInfo() const
80
{
81
82
    return _semanticInfo;
}
83

84
const LookupContext &CppQuickFixState::context() const
85
{
86
87
    return _context;
}
88

89
Scope *CppQuickFixState::scopeAt(unsigned index) const
90
{
91
92
93
94
    unsigned line, column;
    document()->translationUnit()->getTokenStartPosition(index, &line, &column);
    return document()->scopeAt(line, column);
}
95

96
bool CppQuickFixState::isCursorOn(unsigned tokenIndex) const
97
{
98
99
    QTextCursor tc = textCursor();
    int cursorBegin = tc.selectionStart();
100

101
102
    int start = startOf(tokenIndex);
    int end = endOf(tokenIndex);
103

104
105
    if (cursorBegin >= start && cursorBegin <= end)
        return true;
106

107
108
    return false;
}
109

110
bool CppQuickFixState::isCursorOn(const AST *ast) const
111
{
112
113
    QTextCursor tc = textCursor();
    int cursorBegin = tc.selectionStart();
114

115
116
    int start = startOf(ast);
    int end = endOf(ast);
117

118
119
    if (cursorBegin >= start && cursorBegin <= end)
        return true;
Roberto Raggi's avatar
Roberto Raggi committed
120

121
    return false;
122
}
Roberto Raggi's avatar
Roberto Raggi committed
123

124
ChangeSet::Range CppQuickFixState::range(unsigned tokenIndex) const
125
{
126
    const Token &token = tokenAt(tokenIndex);
127
    unsigned line, column;
128
    document()->translationUnit()->getPosition(token.begin(), &line, &column);
129
    const int start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
130
    return ChangeSet::Range(start, start + token.length());
131
132
}

133
ChangeSet::Range CppQuickFixState::range(AST *ast) const
134
{
135
    return ChangeSet::Range(startOf(ast), endOf(ast));
136
137
}

138
int CppQuickFixState::startOf(unsigned index) const
139
{
140
    unsigned line, column;
141
    document()->translationUnit()->getPosition(tokenAt(index).begin(), &line, &column);
142
    return editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
143
}
144

145
int CppQuickFixState::startOf(const AST *ast) const
146
147
148
149
{
    return startOf(ast->firstToken());
}

150
int CppQuickFixState::endOf(unsigned index) const
151
152
{
    unsigned line, column;
153
    document()->translationUnit()->getPosition(tokenAt(index).end(), &line, &column);
154
    return editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
155
156
}

157
int CppQuickFixState::endOf(const AST *ast) const
158
{
159
160
161
162
    if (unsigned end = ast->lastToken())
        return endOf(end - 1);
    else
        return 0;
163
164
}

165
void CppQuickFixState::startAndEndOf(unsigned index, int *start, int *end) const
166
167
{
    unsigned line, column;
168
169
    Token token(tokenAt(index));
    document()->translationUnit()->getPosition(token.begin(), &line, &column);
170
    *start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
171
172
173
    *end = *start + token.length();
}

174
QString CppQuickFixState::textOf(const AST *ast) const
175
{
176
177
    return textOf(startOf(ast), endOf(ast));
}
178

179
180
181
182
const Token &CppQuickFixState::tokenAt(unsigned index) const
{
    return document()->translationUnit()->tokenAt(index);
}
183

184
185
186
187
188
CppQuickFixOperation::CppQuickFixOperation(const CppQuickFixState &state, int priority)
    : QuickFixOperation(priority)
    , _state(state)
    , _refactoringChanges(new CppRefactoringChanges(state.document(), state.snapshot()))
{}
189

190
191
192
193
194
195
CppQuickFixOperation::~CppQuickFixOperation()
{}

const CppQuickFixState &CppQuickFixOperation::state() const
{
    return _state;
196
197
}

198
199
200
201
202
203
204
QString CppQuickFixOperation::fileName() const
{ return state().document()->fileName(); }

CppRefactoringChanges *CppQuickFixOperation::refactoringChanges() const
{ return _refactoringChanges.data(); }

CppQuickFixFactory::CppQuickFixFactory()
205
{
206
}
207

208
209
210
CppQuickFixFactory::~CppQuickFixFactory()
{
}
211

212
213
214
215
216
217
218
QList<QuickFixOperation::Ptr> CppQuickFixFactory::matchingOperations(QuickFixState *state)
{
    if (CppQuickFixState *cppState = static_cast<CppQuickFixState *>(state))
        return match(*cppState);
    else
        return QList<TextEditor::QuickFixOperation::Ptr>();
}
219

220
221
222
223
224
QList<CppQuickFixOperation::Ptr> CppQuickFixFactory::singleResult(CppQuickFixOperation *operation)
{
    QList<CppQuickFixOperation::Ptr> result;
    result.append(CppQuickFixOperation::Ptr(operation));
    return result;
225
226
}

227
QList<CppQuickFixOperation::Ptr> CppQuickFixFactory::noResult()
228
{
229
    return QList<CppQuickFixOperation::Ptr>();
230
231
}

232
CppQuickFixCollector::CppQuickFixCollector()
233
234
{
}
235

236
CppQuickFixCollector::~CppQuickFixCollector()
237
{
238
}
239

240
241
242
243
244
bool CppQuickFixCollector::supportsEditor(TextEditor::ITextEditable *editor)
{
    return CppTools::CppModelManagerInterface::instance()->isCppEditor(editor);
}

245
TextEditor::QuickFixState *CppQuickFixCollector::initializeCompletion(TextEditor::BaseTextEditor *editor)
246
{
247
248
    if (CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor)) {
        const SemanticInfo info = cppEditor->semanticInfo();
249

250
        if (info.revision != cppEditor->editorRevision()) {
251
252
253
            // outdated
            qWarning() << "TODO: outdated semantic info, force a reparse.";
            return 0;
254
        }
Roberto Raggi's avatar
Roberto Raggi committed
255

256
257
        if (info.doc) {
            ASTPath astPath(info.doc);
258

259
            const QList<AST *> path = astPath(cppEditor->textCursor());
260
            if (! path.isEmpty()) {
261
262
263
264
265
                CppQuickFixState *state = new CppQuickFixState(editor);
                state->_path = path;
                state->_semanticInfo = info;
                state->_snapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
                state->_context = LookupContext(info.doc, state->snapshot());
266
267
                return state;
            }
268
        }
269
270
    }

271
    return 0;
272
273
}

274
QList<TextEditor::QuickFixFactory *> CppQuickFixCollector::quickFixFactories() const
Roberto Raggi's avatar
Roberto Raggi committed
275
{
276
277
278
279
280
    QList<TextEditor::QuickFixFactory *> results;
    ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
    foreach (CppQuickFixFactory *f, pm->getObjects<CppEditor::CppQuickFixFactory>())
        results.append(f);
    return results;
281
}