source: trunk/tools/qdoc3/yyindent.cpp@ 683

Last change on this file since 683 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 34.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the tools applications of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*
43 This file is a self-contained interactive indenter for C++ and Qt
44 Script.
45
46 The general problem of indenting a C++ program is ill posed. On
47 the one hand, an indenter has to analyze programs written in a
48 free-form formal language that is best described in terms of
49 tokens, not characters, not lines. On the other hand, indentation
50 applies to lines and white space characters matter, and otherwise
51 the programs to indent are formally invalid in general, as they
52 are begin edited.
53
54 The approach taken here works line by line. We receive a program
55 consisting of N lines or more, and we want to compute the
56 indentation appropriate for the Nth line. Lines beyond the Nth
57 lines are of no concern to us, so for simplicity we pretend the
58 program has exactly N lines and we call the Nth line the "bottom
59 line". Typically, we have to indent the bottom line when it's
60 still empty, so we concentrate our analysis on the N - 1 lines
61 that precede.
62
63 By inspecting the (N - 1)-th line, the (N - 2)-th line, ...
64 backwards, we determine the kind of the bottom line and indent it
65 accordingly.
66
67 * The bottom line is a comment line. See
68 bottomLineStartsInCComment() and
69 indentWhenBottomLineStartsInCComment().
70 * The bottom line is a continuation line. See isContinuationLine()
71 and indentForContinuationLine().
72 * The bottom line is a standalone line. See
73 indentForStandaloneLine().
74
75 Certain tokens that influence the indentation, notably braces,
76 are looked for in the lines. This is done by simple string
77 comparison, without a real tokenizer. Confusing constructs such
78 as comments and string literals are removed beforehand.
79*/
80
81#include <qregexp.h>
82#include <qstringlist.h>
83
84QT_BEGIN_NAMESPACE
85
86/* qmake ignore Q_OBJECT */
87
88/*
89 The indenter avoids getting stuck in almost infinite loops by
90 imposing arbitrary limits on the number of lines it analyzes when
91 looking for a construct.
92
93 For example, the indenter never considers more than BigRoof lines
94 backwards when looking for the start of a C-style comment.
95*/
96static const int SmallRoof = 40;
97static const int BigRoof = 400;
98
99/*
100 The indenter supports a few parameters:
101
102 * ppHardwareTabSize is the size of a '\t' in your favorite editor.
103 * ppIndentSize is the size of an indentation, or software tab
104 size.
105 * ppContinuationIndentSize is the extra indent for a continuation
106 line, when there is nothing to align against on the previous
107 line.
108 * ppCommentOffset is the indentation within a C-style comment,
109 when it cannot be picked up.
110*/
111
112static int ppHardwareTabSize = 8;
113static int ppIndentSize = 4;
114static int ppContinuationIndentSize = 8;
115
116static const int ppCommentOffset = 2;
117
118void setTabSize( int size )
119{
120 ppHardwareTabSize = size;
121}
122
123void setIndentSize( int size )
124{
125 ppIndentSize = size;
126 ppContinuationIndentSize = 2 * size;
127}
128
129static QRegExp *literal = 0;
130static QRegExp *label = 0;
131static QRegExp *inlineCComment = 0;
132static QRegExp *braceX = 0;
133static QRegExp *iflikeKeyword = 0;
134
135/*
136 Returns the first non-space character in the string t, or
137 QChar::Null if the string is made only of white space.
138*/
139static QChar firstNonWhiteSpace( const QString& t )
140{
141 int i = 0;
142 while ( i < (int) t.length() ) {
143 if ( !t[i].isSpace() )
144 return t[i];
145 i++;
146 }
147 return QChar::Null;
148}
149
150/*
151 Returns true if string t is made only of white space; otherwise
152 returns false.
153*/
154static bool isOnlyWhiteSpace( const QString& t )
155{
156 return firstNonWhiteSpace( t ).isNull();
157}
158
159/*
160 Assuming string t is a line, returns the column number of a given
161 index. Column numbers and index are identical for strings that don't
162 contain '\t's.
163*/
164int columnForIndex( const QString& t, int index )
165{
166 int col = 0;
167 if ( index > (int) t.length() )
168 index = t.length();
169
170 for ( int i = 0; i < index; i++ ) {
171 if ( t[i] == QChar('\t') ) {
172 col = ( (col / ppHardwareTabSize) + 1 ) * ppHardwareTabSize;
173 } else {
174 col++;
175 }
176 }
177 return col;
178}
179
180/*
181 Returns the indentation size of string t.
182*/
183int indentOfLine( const QString& t )
184{
185 return columnForIndex( t, t.indexOf(firstNonWhiteSpace(t)) );
186}
187
188/*
189 Replaces t[k] by ch, unless t[k] is '\t'. Tab characters are better
190 left alone since they break the "index equals column" rule. No
191 provisions are taken against '\n' or '\r', which shouldn't occur in
192 t anyway.
193*/
194static inline void eraseChar( QString& t, int k, QChar ch )
195{
196 if ( t[k] != '\t' )
197 t[k] = ch;
198}
199
200/*