cpprefactoringchanges.cpp 8.39 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29
30

#include "cpprefactoringchanges.h"
31

32
#include "cppqtstyleindenter.h"
33
34
#include "cppcodeformatter.h"
#include "cppmodelmanager.h"
35
#include <projectexplorer/editorconfiguration.h>
36

37
#include <utils/qtcassert.h>
38

Roberto Raggi's avatar
Roberto Raggi committed
39
using namespace CPlusPlus;
40
using namespace CppTools;
41
using namespace Utils;
42

43
44
45
46
47
48
49
50
51
52
53
54
55
class CppTools::CppRefactoringChangesData : public TextEditor::RefactoringChangesData
{
public:
    CppRefactoringChangesData(const Snapshot &snapshot)
        : m_snapshot(snapshot)
        , m_modelManager(Internal::CppModelManager::instance())
        , m_workingCopy(m_modelManager->workingCopy())
    {}

    virtual void indentSelection(const QTextCursor &selection,
                                 const QString &fileName,
                                 const TextEditor::BaseTextEditorWidget *textEditor) const
    {
56
57
        const TextEditor::TabSettings &tabSettings =
            ProjectExplorer::actualTabSettings(fileName, textEditor);
58

59
60
61
        CppQtStyleIndenter indenter;
        indenter.indent(selection.document(), selection, QChar::Null, tabSettings);
    }
62

63
64
65
66
    virtual void reindentSelection(const QTextCursor &selection,
                                   const QString &fileName,
                                   const TextEditor::BaseTextEditorWidget *textEditor) const
    {
67
68
69
        const TextEditor::TabSettings &tabSettings =
            ProjectExplorer::actualTabSettings(fileName, textEditor);

70
71
        CppQtStyleIndenter indenter;
        indenter.reindent(selection.document(), selection, tabSettings);
72
73
74
75
76
77
78
    }

    virtual void fileChanged(const QString &fileName)
    {
        m_modelManager->updateSourceFiles(QStringList(fileName));
    }

79
80
81
    Snapshot m_snapshot;
    CppModelManagerInterface *m_modelManager;
    CppModelManagerInterface::WorkingCopy m_workingCopy;
82
83
84

};

85
CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot)
86
    : RefactoringChanges(new CppRefactoringChangesData(snapshot))
87
88
89
{
}

90
CppRefactoringChangesData *CppRefactoringChanges::data() const
91
{
92
    return static_cast<CppRefactoringChangesData *>(m_data.data());
93
94
}

95
CppRefactoringFilePtr CppRefactoringChanges::file(TextEditor::BaseTextEditorWidget *editor, const Document::Ptr &document)
96
{
97
98
99
    CppRefactoringFilePtr result(new CppRefactoringFile(editor));
    result->setCppDocument(document);
    return result;
100
}
101

102
CppRefactoringFilePtr CppRefactoringChanges::file(const QString &fileName) const
103
{
104
105
106
    CppRefactoringFilePtr result(new CppRefactoringFile(fileName, m_data));
    return result;
}
107

108
109
110
111
CppRefactoringFileConstPtr CppRefactoringChanges::fileNoEditor(const QString &fileName) const
{
    QTextDocument *document = 0;
    if (data()->m_workingCopy.contains(fileName))
112
        document = new QTextDocument(QString::fromUtf8(data()->m_workingCopy.source(fileName)));
113
114
    CppRefactoringFilePtr result(new CppRefactoringFile(document, fileName));
    result->m_data = m_data;
115

116
117
118
    Document::Ptr cppDocument = data()->m_snapshot.document(fileName);
    if (cppDocument)
        result->setCppDocument(cppDocument);
119

120
    return result;
121
}
122

123
const Snapshot &CppRefactoringChanges::snapshot() const
124
{
125
    return data()->m_snapshot;
126
}
127

128
129
CppRefactoringFile::CppRefactoringFile(const QString &fileName, const QSharedPointer<TextEditor::RefactoringChangesData> &data)
    : RefactoringFile(fileName, data)
130
{
131
    const Snapshot &snapshot = this->data()->m_snapshot;
132
133
    m_cppDocument = snapshot.document(fileName);
}
134

135
136
137
138
139
140
141
CppRefactoringFile::CppRefactoringFile(QTextDocument *document, const QString &fileName)
    : RefactoringFile(document, fileName)
{ }

CppRefactoringFile::CppRefactoringFile(TextEditor::BaseTextEditorWidget *editor)
    : RefactoringFile(editor)
{ }
142

143
144
Document::Ptr CppRefactoringFile::cppDocument() const
{
145
146
    if (!m_cppDocument || !m_cppDocument->translationUnit() ||
            !m_cppDocument->translationUnit()->ast()) {
147
        const QByteArray source = document()->toPlainText().toUtf8();
148
        const QString name = fileName();
149
        const Snapshot &snapshot = data()->m_snapshot;
150

151
        m_cppDocument = snapshot.preprocessedDocument(source, name);
152
153
154
155
156
157
        m_cppDocument->check();
    }

    return m_cppDocument;
}

158
159
160
161
162
void CppRefactoringFile::setCppDocument(Document::Ptr document)
{
    m_cppDocument = document;
}

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
Scope *CppRefactoringFile::scopeAt(unsigned index) const
{
    unsigned line, column;
    cppDocument()->translationUnit()->getTokenStartPosition(index, &line, &column);
    return cppDocument()->scopeAt(line, column);
}

bool CppRefactoringFile::isCursorOn(unsigned tokenIndex) const
{
    QTextCursor tc = cursor();
    int cursorBegin = tc.selectionStart();

    int start = startOf(tokenIndex);
    int end = endOf(tokenIndex);

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

    return false;
}

bool CppRefactoringFile::isCursorOn(const AST *ast) const
{
    QTextCursor tc = cursor();
    int cursorBegin = tc.selectionStart();

    int start = startOf(ast);
    int end = endOf(ast);

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

    return false;
}

ChangeSet::Range CppRefactoringFile::range(unsigned tokenIndex) const
{
    const Token &token = tokenAt(tokenIndex);
    unsigned line, column;
    cppDocument()->translationUnit()->getPosition(token.begin(), &line, &column);
    const int start = document()->findBlockByNumber(line - 1).position() + column - 1;
    return ChangeSet::Range(start, start + token.length());
}

ChangeSet::Range CppRefactoringFile::range(AST *ast) const
{
    return ChangeSet::Range(startOf(ast), endOf(ast));
}

int CppRefactoringFile::startOf(unsigned index) const
{
    unsigned line, column;
    cppDocument()->translationUnit()->getPosition(tokenAt(index).begin(), &line, &column);
    return document()->findBlockByNumber(line - 1).position() + column - 1;
}

int CppRefactoringFile::startOf(const AST *ast) const
{
    return startOf(ast->firstToken());
}

int CppRefactoringFile::endOf(unsigned index) const
{
    unsigned line, column;
    cppDocument()->translationUnit()->getPosition(tokenAt(index).end(), &line, &column);
    return document()->findBlockByNumber(line - 1).position() + column - 1;
}

int CppRefactoringFile::endOf(const AST *ast) const
{
233
    unsigned end = ast->lastToken();
234
    QTC_ASSERT(end > 0, return -1);
235
    return endOf(end - 1);
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
}

void CppRefactoringFile::startAndEndOf(unsigned index, int *start, int *end) const
{
    unsigned line, column;
    Token token(tokenAt(index));
    cppDocument()->translationUnit()->getPosition(token.begin(), &line, &column);
    *start = document()->findBlockByNumber(line - 1).position() + column - 1;
    *end = *start + token.length();
}

QString CppRefactoringFile::textOf(const AST *ast) const
{
    return textOf(startOf(ast), endOf(ast));
}

const Token &CppRefactoringFile::tokenAt(unsigned index) const
{
    return cppDocument()->translationUnit()->tokenAt(index);
}

257
258
259
260
261
262
CppRefactoringChangesData *CppRefactoringFile::data() const
{
    return static_cast<CppRefactoringChangesData *>(m_data.data());
}

void CppRefactoringFile::fileChanged()
263
{
264
265
    m_cppDocument.clear();
    RefactoringFile::fileChanged();
266
}