1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
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
16 ** GNU Lesser General Public License Usage
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.
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.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #ifndef CPPCODEFORMATTER_H
35 #define CPPCODEFORMATTER_H
37 #include "cpptools_global.h"
39 #include <cplusplus/SimpleLexer.h>
42 #include <QtCore/QChar>
43 #include <QtCore/QStack>
44 #include <QtCore/QList>
45 #include <QtCore/QVector>
46 #include <QtCore/QPointer>
53 namespace TextEditor {
59 class CppCodeFormatterData;
62 class CPPTOOLS_EXPORT CodeFormatter
67 virtual ~CodeFormatter();
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);
73 // calculates the state change introduced by changing a single line
74 void updateLineStateChange(const QTextBlock &block);
76 void indentFor(const QTextBlock &block, int *indent, int *padding);
77 void indentForNewLineAfter(const QTextBlock &block, int *indent, int *padding);
79 void setTabSize(int tabSize);
81 void invalidateCache(QTextDocument *document);
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;
93 QStack<State> m_beginState;
94 QStack<State> m_endState;
100 virtual void saveBlockData(QTextBlock *block, const BlockData &data) const = 0;
101 virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const = 0;
103 virtual void saveLexerState(QTextBlock *block, int state) const = 0;
104 virtual int loadLexerState(const QTextBlock &block) const = 0;
106 public: // must be public to make Q_GADGET introspection work
110 topmost_intro, // The first line in a "topmost" definition.
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
121 defun_open, // Brace that opens a top-level function definition.
122 using_start, // right after the "using" token
124 class_start, // after the 'class' token
125 class_open, // Brace that opens a class definition.
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.
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.
135 namespace_start, // after the namespace token, before the opening brace.
136 namespace_open, // Brace that opens a C++ namespace block.
138 declaration_start, // shifted a token which could start a declaration.
139 operator_declaration, // after 'operator' in declaration_start
141 template_start, // after the 'template' token
142 template_param, // after the '<' in a template_start
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.
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
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
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.
163 substatement, // The first line after a conditional or loop construct.
164 substatement_open, // The brace that opens a substatement block.
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
171 condition_open, // Start of a condition in 'if', 'while', entered after opening paren
172 condition_paren_open, // After an lparen in a condition
174 assign_open, // after an assignment token
176 expression, // after a '=' in a declaration_start once we're sure it's not '= {'
177 initializer // after a '=' in a declaration start
185 : savedIndentDepth(0)
186 , savedPaddingDepth(0)
190 State(quint8 ty, quint16 savedIndentDepth, qint16 savedPaddingDepth)
191 : savedIndentDepth(savedIndentDepth)
192 , savedPaddingDepth(savedPaddingDepth)
196 quint16 savedIndentDepth;
197 quint16 savedPaddingDepth;
200 bool operator==(const State &other) const {
201 return type == other.type
202 && savedIndentDepth == other.savedIndentDepth
203 && savedPaddingDepth == other.savedPaddingDepth;
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 ¤tToken() const;
212 const CPlusPlus::Token &tokenAt(int idx) const;
213 int column(int position) const;
215 bool isBracelessState(int type) const;
220 void recalculateStateAfter(const QTextBlock &block);
221 void saveCurrentState(const QTextBlock &block);
222 void restoreCurrentState(const QTextBlock &block);
224 QStringRef currentTokenText() const;
226 int tokenizeBlock(const QTextBlock &block, bool *endedJoined = 0);
228 void turnInto(int newState);
230 bool tryExpression(bool alsoExpression = false);
231 bool tryDeclaration();
234 void enter(int newState);
235 void leave(bool statementDone = false);
236 void correctIndentation(const QTextBlock &block);
239 static QStack<State> initialState();
241 QStack<State> m_beginState;
242 QStack<State> m_currentState;
243 QStack<State> m_newStates;
245 QList<CPlusPlus::Token> m_tokens;
246 QString m_currentLine;
247 CPlusPlus::Token m_currentToken;
255 friend class Internal::CppCodeFormatterData;
258 class CPPTOOLS_EXPORT QtStyleCodeFormatter : public CodeFormatter
261 QtStyleCodeFormatter();
262 explicit QtStyleCodeFormatter(const TextEditor::TabSettings &tabSettings);
264 void setIndentSize(int size);
266 void setIndentSubstatementBraces(bool onOff);
267 void setIndentSubstatementStatements(bool onOff);
268 void setIndentDeclarationBraces(bool onOff);
269 void setIndentDeclarationMembers(bool onOff);
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;
275 virtual void saveBlockData(QTextBlock *block, const BlockData &data) const;
276 virtual bool loadBlockData(const QTextBlock &block, BlockData *data) const;
278 virtual void saveLexerState(QTextBlock *block, int state) const;
279 virtual int loadLexerState(const QTextBlock &block) const;
281 static bool shouldClearPaddingOnEnter(int state);
285 bool m_indentSubstatementBraces;
286 bool m_indentSubstatementStatements;
287 bool m_indentDeclarationBraces;
288 bool m_indentDeclarationMembers;
291 } // namespace CppTools
293 #endif // CPPCODEFORMATTER_H