OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / libs / cplusplus / ExpressionUnderCursor.cpp
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 #include "ExpressionUnderCursor.h"
35 #include "SimpleLexer.h"
36 #include "BackwardsScanner.h"
37 #include <Token.h>
38
39 #include <QTextCursor>
40 #include <QTextBlock>
41
42 using namespace CPlusPlus;
43
44 ExpressionUnderCursor::ExpressionUnderCursor()
45     : _jumpedComma(false)
46 { }
47
48 ExpressionUnderCursor::~ExpressionUnderCursor()
49 { }
50
51 int ExpressionUnderCursor::startOfExpression(BackwardsScanner &tk, int index)
52 {
53     if (tk[index - 1].is(T_GREATER)) {
54         const int matchingBraceIndex = tk.startOfMatchingBrace(index);
55
56         if (tk[matchingBraceIndex - 1].is(T_IDENTIFIER))
57             index = matchingBraceIndex - 1;
58     }
59
60     index = startOfExpression_helper(tk, index);
61
62     if (_jumpedComma) {
63         const Token &tok = tk[index - 1];
64
65         switch (tok.kind()) {
66         case T_COMMA:
67         case T_LPAREN:
68         case T_LBRACKET:
69         case T_LBRACE:
70         case T_SEMICOLON:
71         case T_COLON:
72         case T_QUESTION:
73             break;
74
75         default:
76             if (tok.isOperator())
77                 return startOfExpression(tk, index - 1);
78
79             break;
80         }
81     }
82
83     return index;
84 }
85
86 int ExpressionUnderCursor::startOfExpression_helper(BackwardsScanner &tk, int index)
87 {
88     if (tk[index - 1].isLiteral()) {
89         return index - 1;
90     } else if (tk[index - 1].is(T_THIS)) {
91         return index - 1;
92     } else if (tk[index - 1].is(T_TYPEID)) {
93         return index - 1;
94     } else if (tk[index - 1].is(T_SIGNAL)) {
95         if (tk[index - 2].is(T_COMMA) && !_jumpedComma) {
96             _jumpedComma = true;
97             return startOfExpression(tk, index - 2);
98         }
99         return index - 1;
100     } else if (tk[index - 1].is(T_SLOT)) {
101         if (tk[index - 2].is(T_COMMA) && !_jumpedComma) {
102             _jumpedComma = true;
103             return startOfExpression(tk, index - 2);
104         }
105         return index - 1;
106     } else if (tk[index - 1].is(T_IDENTIFIER)) {
107         if (tk[index - 2].is(T_TILDE)) {
108             if (tk[index - 3].is(T_COLON_COLON)) {
109                 return startOfExpression(tk, index - 3);
110             } else if (tk[index - 3].is(T_DOT) || tk[index - 3].is(T_ARROW)) {
111                 return startOfExpression(tk, index - 3);
112             }
113             return index - 2;
114         } else if (tk[index - 2].is(T_COLON_COLON)) {
115             return startOfExpression(tk, index - 1);
116         } else if (tk[index - 2].is(T_DOT) || tk[index - 2].is(T_ARROW)) {
117             return startOfExpression(tk, index - 2);
118         } else if (tk[index - 2].is(T_DOT_STAR) || tk[index - 2].is(T_ARROW_STAR)) {
119             return startOfExpression(tk, index - 2);
120         } else if (tk[index - 2].is(T_LBRACKET)) {
121             // array subscription:
122             //     array[i
123             return index - 1;
124         } else if (tk[index - 2].is(T_COLON)) {
125             // either of:
126             //     cond ? expr1 : id
127             // or:
128             //     [receiver messageParam:id
129             // and in both cases, the id (and only the id) is what we want, so:
130             return index - 1;
131         } else if (tk[index - 2].is(T_IDENTIFIER) && tk[index - 3].is(T_LBRACKET)) {
132             // Very common Objective-C case:
133             //     [receiver message
134             // which we handle immediately:
135             return index - 3;
136         } else {
137 #if 0 // see QTCREATORBUG-1501
138             // See if we are handling an Objective-C messaging expression in the form of:
139             //     [receiver messageParam1:expression messageParam2
140             // or:
141             //     [receiver messageParam1:expression messageParam2:expression messageParam3
142             // ... etc
143             int i = index - 1;
144             while (i >= 0 && tk[i].isNot(T_EOF_SYMBOL)) {
145                 if (tk[i].is(T_LBRACKET))
146                     break;
147                 if (tk[i].is(T_LBRACE) || tk[i].is(T_RBRACE))
148                     break;
149                 else if (tk[i].is(T_RBRACKET))
150                     i = tk.startOfMatchingBrace(i + 1) - 1;
151                 else
152                     --i;
153             }
154
155             if (i >= 0) {
156                 int j = i;
157                 while (tk[j].is(T_LBRACKET))
158                     ++j;
159                 if (tk[j].is(T_IDENTIFIER) && tk[j + 1].is(T_IDENTIFIER))
160                     return i;
161             }
162 #endif
163         }
164         return index - 1;
165     } else if (tk[index - 1].is(T_RPAREN)) {
166         int matchingBraceIndex = tk.startOfMatchingBrace(index);
167         if (matchingBraceIndex != index) {
168             if (tk[matchingBraceIndex - 1].is(T_GREATER)) {
169                 int lessIndex = tk.startOfMatchingBrace(matchingBraceIndex);
170                 if (lessIndex != matchingBraceIndex - 1) {
171                     if (tk[lessIndex - 1].is(T_DYNAMIC_CAST)     ||
172                         tk[lessIndex - 1].is(T_STATIC_CAST)      ||
173                         tk[lessIndex - 1].is(T_CONST_CAST)       ||
174                         tk[lessIndex - 1].is(T_REINTERPRET_CAST))
175                         return lessIndex - 1;
176                     else if (tk[lessIndex - 1].is(T_IDENTIFIER))
177                         return startOfExpression(tk, lessIndex);
178                     else if (tk[lessIndex - 1].is(T_SIGNAL))
179                         return startOfExpression(tk, lessIndex);
180                     else if (tk[lessIndex - 1].is(T_SLOT))
181                         return startOfExpression(tk, lessIndex);
182                 }
183             }
184             return startOfExpression(tk, matchingBraceIndex);
185         }
186         return index;
187     } else if (tk[index - 1].is(T_RBRACKET)) {
188         int rbracketIndex = tk.startOfMatchingBrace(index);
189         if (rbracketIndex != index)
190             return startOfExpression(tk, rbracketIndex);
191         return index;
192     } else if (tk[index - 1].is(T_COLON_COLON)) {
193         if (tk[index - 2].is(T_GREATER)) { // ### not exactly
194             int lessIndex = tk.startOfMatchingBrace(index - 1);
195             if (lessIndex != index - 1)
196                 return startOfExpression(tk, lessIndex);
197             return index - 1;
198         } else if (tk[index - 2].is(T_IDENTIFIER)) {
199             return startOfExpression(tk, index - 1);
200         }
201         return index - 1;
202     } else if (tk[index - 1].is(T_DOT) || tk[index - 1].is(T_ARROW)) {
203         return startOfExpression(tk, index - 1);
204     } else if (tk[index - 1].is(T_DOT_STAR) || tk[index - 1].is(T_ARROW_STAR)) {
205         return startOfExpression(tk, index - 1);
206     }
207
208     return index;
209 }
210
211 bool ExpressionUnderCursor::isAccessToken(const Token &tk)
212 {
213     switch (tk.kind()) {
214     case T_COLON_COLON:
215     case T_DOT:      case T_ARROW:
216     case T_DOT_STAR: case T_ARROW_STAR:
217         return true;
218     default:
219         return false;
220     } // switch
221 }
222
223 QString ExpressionUnderCursor::operator()(const QTextCursor &cursor)
224 {
225     BackwardsScanner scanner(cursor);
226
227     _jumpedComma = false;
228
229     const int initialSize = scanner.startToken();
230     const int i = startOfExpression(scanner, initialSize);
231     if (i == initialSize)
232         return QString();
233
234     return scanner.mid(i);
235 }
236
237 int ExpressionUnderCursor::startOfFunctionCall(const QTextCursor &cursor) const
238 {
239     BackwardsScanner scanner(cursor);
240
241     int index = scanner.startToken();
242
243     forever {
244         const Token &tk = scanner[index - 1];
245
246         if (tk.is(T_EOF_SYMBOL))
247             break;
248         else if (tk.is(T_LPAREN))
249             return scanner.startPosition() + tk.begin();
250         else if (tk.is(T_RPAREN)) {
251             int matchingBrace = scanner.startOfMatchingBrace(index);
252
253             if (matchingBrace == index) // If no matching brace found
254                 return -1;
255
256             index = matchingBrace;
257         } else
258             --index;
259     }
260
261     return -1;
262 }