OSDN Git Service

86d8a0a8ee847ec06166d4692566ec57b8826827
[qt-creator-jp/qt-creator-jp.git] / src / plugins / cpptools / cppcodeformatter.h
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #ifndef CPPCODEFORMATTER_H
35 #define CPPCODEFORMATTER_H
36
37 #include "cpptools_global.h"
38
39 #include <cplusplus/SimpleLexer.h>
40 #include <Token.h>
41
42 #include <QtCore/QChar>
43 #include <QtCore/QStack>
44 #include <QtCore/QList>
45 #include <QtCore/QVector>
46 #include <QtCore/QPointer>
47
48 QT_BEGIN_NAMESPACE
49 class QTextDocument;
50 class QTextBlock;
51 QT_END_NAMESPACE
52
53 namespace TextEditor {
54     class TabSettings;
55 }
56
57 namespace CppTools {
58 namespace Internal {
59 class CppCodeFormatterData;
60 }
61
62 class CPPTOOLS_EXPORT CodeFormatter
63 {
64     Q_GADGET
65 public:
66     CodeFormatter();
67     virtual ~CodeFormatter();
68
69     // updates all states up until block if necessary
70     // it is safe to call indentFor on block afterwards
71     void updateStateUntil(const QTextBlock &block);
72
73     // calculates the state change introduced by changing a single line
74     void updateLineStateChange(const QTextBlock &block);
75
76     void indentFor(const QTextBlock &block, int *indent, int *padding);
77     void indentForNewLineAfter(const QTextBlock &block, int *indent, int *padding);
78
79     void setTabSize(int tabSize);
80
81     void invalidateCache(QTextDocument *document);
82
83 protected:
84     virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth, int *paddingDepth, int *savedPaddingDepth) const = 0;
85     virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth, int *paddingDepth) const = 0;
86
87     class State;
88     class BlockData
89     {
90     public:
91         BlockData();
92
93         QStack<State> m_beginState;
94         QStack<State> m_endState;
95         int m_indentDepth;
96         int m_paddingDepth;
97         int m_blockRevision;
98     };
99
100     virtual void saveBlockData(QTextBlock *block, const BlockData &data) const = 0;
101     virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const = 0;
102
103     virtual void saveLexerState(QTextBlock *block, int state) const = 0;
104     virtual int loadLexerState(const QTextBlock &block) const = 0;
105
106 public: // must be public to make Q_GADGET introspection work
107     enum StateType {
108         invalid = 0,
109
110         topmost_intro, // The first line in a "topmost" definition.
111
112         multiline_comment_start, // Inside the first line of a multi-line C style block comment.
113         multiline_comment_cont, // Inside the following lines of a multi-line C style block comment.
114         cpp_macro_start, // After the '#' token
115         cpp_macro, // The start of a C preprocessor macro definition.
116         cpp_macro_cont, // Subsequent lines of a multi-line C preprocessor macro definition.
117         cpp_macro_conditional, // Special marker used for separating saved from current state when dealing with #ifdef
118         qt_like_macro, // after an identifier starting with Q_ or QT_ at the beginning of the line
119         label, // after an identifier followed by a colon
120
121         defun_open, // Brace that opens a top-level function definition.
122         using_start, // right after the "using" token
123
124         class_start, // after the 'class' token
125         class_open, // Brace that opens a class definition.
126
127         member_init_open, // After ':' that starts a member initialization list.
128         member_init, // At the start and after every ',' in member_init_open
129         member_init_paren_open, // After '(' in member_init.
130
131         enum_start, // After 'enum'
132         enum_open, // Brace that opens a enum declaration.
133         brace_list_open, // Open brace nested inside an enum or for a static array list.
134
135         namespace_start, // after the namespace token, before the opening brace.
136         namespace_open, // Brace that opens a C++ namespace block.
137
138         declaration_start, // shifted a token which could start a declaration.
139         operator_declaration, // after 'operator' in declaration_start
140
141         template_start, // after the 'template' token
142         template_param, // after the '<' in a template_start
143
144         if_statement, // After 'if'
145         maybe_else, // after the first substatement in an if
146         else_clause, // The else line of an if-else construct.
147
148         for_statement, // After the 'for' token
149         for_statement_paren_open, // While inside the (...)
150         for_statement_init, // The initializer part of the for statement
151         for_statement_condition, // The condition part of the for statement
152         for_statement_expression, // The expression part of the for statement
153
154         switch_statement, // After 'switch' token
155         case_start, // after a 'case' or 'default' token
156         case_cont, // after the colon in a case/default
157
158         statement_with_condition, // A statement that takes a condition after the start token.
159         do_statement, // After 'do' token
160         return_statement, // After 'return'
161         block_open, // Statement block open brace.
162
163         substatement, // The first line after a conditional or loop construct.
164         substatement_open, // The brace that opens a substatement block.
165
166         arglist_open, // after the lparen. TODO: check if this is enough.
167         stream_op, // After a '<<' or '>>' in a context where it's likely a stream operator.
168         stream_op_cont, // When finding another stream operator in stream_op
169         ternary_op, // The ? : operator
170
171         condition_open, // Start of a condition in 'if', 'while', entered after opening paren
172         condition_paren_open, // After an lparen in a condition
173
174         assign_open, // after an assignment token
175
176         expression, // after a '=' in a declaration_start once we're sure it's not '= {'
177         initializer // after a '=' in a declaration start
178     };
179     Q_ENUMS(StateType)
180
181 protected:
182     class State {
183     public:
184         State()
185             : savedIndentDepth(0)
186             , savedPaddingDepth(0)
187             , type(0)
188         {}
189
190         State(quint8 ty, quint16 savedIndentDepth, qint16 savedPaddingDepth)
191             : savedIndentDepth(savedIndentDepth)
192             , savedPaddingDepth(savedPaddingDepth)
193             , type(ty)
194         {}
195
196         quint16 savedIndentDepth;
197         quint16 savedPaddingDepth;
198         quint8 type;
199
200         bool operator==(const State &other) const {
201             return type == other.type
202                 && savedIndentDepth == other.savedIndentDepth
203                 && savedPaddingDepth == other.savedPaddingDepth;
204         }
205     };
206
207     State state(int belowTop = 0) const;
208     const QVector<State> &newStatesThisLine() const;
209     int tokenIndex() const;
210     int tokenCount() const;
211     const CPlusPlus::Token &currentToken() const;
212     const CPlusPlus::Token &tokenAt(int idx) const;
213     int column(int position) const;
214
215     bool isBracelessState(int type) const;
216
217     void dump() const;
218
219 private:
220     void recalculateStateAfter(const QTextBlock &block);
221     void saveCurrentState(const QTextBlock &block);
222     void restoreCurrentState(const QTextBlock &block);
223
224     QStringRef currentTokenText() const;
225
226     int tokenizeBlock(const QTextBlock &block, bool *endedJoined = 0);
227
228     void turnInto(int newState);
229
230     bool tryExpression(bool alsoExpression = false);
231     bool tryDeclaration();
232     bool tryStatement();
233
234     void enter(int newState);
235     void leave(bool statementDone = false);
236     void correctIndentation(const QTextBlock &block);
237
238 private:
239     static QStack<State> initialState();
240
241     QStack<State> m_beginState;
242     QStack<State> m_currentState;
243     QStack<State> m_newStates;
244
245     QList<CPlusPlus::Token> m_tokens;
246     QString m_currentLine;
247     CPlusPlus::Token m_currentToken;
248     int m_tokenIndex;
249
250     int m_indentDepth;
251     int m_paddingDepth;
252
253     int m_tabSize;
254
255     friend class Internal::CppCodeFormatterData;
256 };
257
258 class CPPTOOLS_EXPORT QtStyleCodeFormatter : public CodeFormatter
259 {
260 public:
261     QtStyleCodeFormatter();
262     explicit QtStyleCodeFormatter(const TextEditor::TabSettings &tabSettings);
263
264     void setIndentSize(int size);
265
266     void setIndentSubstatementBraces(bool onOff);
267     void setIndentSubstatementStatements(bool onOff);
268     void setIndentDeclarationBraces(bool onOff);
269     void setIndentDeclarationMembers(bool onOff);
270
271 protected:
272     virtual void onEnter(int newState, int *indentDepth, int *savedIndentDepth, int *paddingDepth, int *savedPaddingDepth) const;
273     virtual void adjustIndent(const QList<CPlusPlus::Token> &tokens, int lexerState, int *indentDepth, int *paddingDepth) const;
274
275     virtual void saveBlockData(QTextBlock *block, const BlockData &data) const;
276     virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const;
277
278     virtual void saveLexerState(QTextBlock *block, int state) const;
279     virtual int loadLexerState(const QTextBlock &block) const;
280
281     static bool shouldClearPaddingOnEnter(int state);
282
283 private:
284     int m_indentSize;
285     bool m_indentSubstatementBraces;
286     bool m_indentSubstatementStatements;
287     bool m_indentDeclarationBraces;
288     bool m_indentDeclarationMembers;
289 };
290
291 } // namespace CppTools
292
293 #endif // CPPCODEFORMATTER_H