~ubuntu-branches/ubuntu/utopic/kdevelop-php/utopic

« back to all changes in this revision

Viewing changes to duchain/tests/test_expressionparser.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2010-01-17 17:10:22 UTC
  • Revision ID: james.westby@ubuntu.com-20100117171022-q2xlgd9ekewo2ijx
Tags: upstream-1.0.0~beta2
ImportĀ upstreamĀ versionĀ 1.0.0~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of KDevelop
 
2
    Copyright 2008 Niko Sams <niko.sams@gmail.com>
 
3
 
 
4
   This library is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU Library General Public
 
6
   License version 2 as published by the Free Software Foundation.
 
7
 
 
8
   This library is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
   Library General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU Library General Public License
 
14
   along with this library; see the file COPYING.LIB.  If not, write to
 
15
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
16
   Boston, MA 02110-1301, USA.
 
17
*/
 
18
 
 
19
#include "test_expressionparser.h"
 
20
 
 
21
#include <QtTest/QtTest>
 
22
 
 
23
#include <language/duchain/parsingenvironment.h>
 
24
#include <language/duchain/duchain.h>
 
25
#include <language/duchain/duchainlock.h>
 
26
#include <language/duchain/topducontext.h>
 
27
#include <language/duchain/types/functiontype.h>
 
28
#include <language/duchain/types/integraltype.h>
 
29
#include <language/duchain/declaration.h>
 
30
 
 
31
#include "structuretype.h"
 
32
#include "expressionparser.h"
 
33
 
 
34
using namespace KTextEditor;
 
35
using namespace KDevelop;
 
36
 
 
37
QTEST_MAIN(Php::TestExpressionParser)
 
38
 
 
39
namespace Php
 
40
{
 
41
 
 
42
TestExpressionParser::TestExpressionParser()
 
43
{
 
44
}
 
45
 
 
46
 
 
47
void TestExpressionParser::newClass()
 
48
{
 
49
    //                 0         1         2         3         4         5         6         7
 
50
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
51
    QByteArray method("<? class A { function foo() {} } $i = new A();");
 
52
 
 
53
    TopDUContext* top = parse(method, DumpNone);
 
54
    DUChainReleaser releaseTop(top);
 
55
    DUChainWriteLocker lock(DUChain::lock());
 
56
 
 
57
    ExpressionParser p(true);
 
58
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("$i"), DUContextPointer(top), SimpleCursor(1, 0));
 
59
    QVERIFY(res.type());
 
60
    QCOMPARE(StructureType::Ptr::staticCast(res.type())->qualifiedIdentifier(), QualifiedIdentifier("a"));
 
61
}
 
62
void TestExpressionParser::memberVariable()
 
63
{
 
64
    //                 0         1         2         3         4         5         6         7
 
65
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
66
    QByteArray method("<? class A { /** @var A **/ public $foo; } $i = new A();");
 
67
 
 
68
    TopDUContext* top = parse(method, DumpNone);
 
69
    DUChainReleaser releaseTop(top);
 
70
    DUChainWriteLocker lock(DUChain::lock());
 
71
 
 
72
    ExpressionParser p(true);
 
73
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("$i->foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
74
    QVERIFY(res.type());
 
75
    QCOMPARE(res.allDeclarations().count(), 1);
 
76
    QCOMPARE(res.allDeclarations().first(), top->childContexts().first()->localDeclarations().first());
 
77
    QCOMPARE(StructureType::Ptr::staticCast(res.type())->qualifiedIdentifier(), QualifiedIdentifier("a"));
 
78
}
 
79
void TestExpressionParser::memberFunction()
 
80
{
 
81
    //                 0         1         2         3         4         5         6         7
 
82
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
83
    QByteArray method("<? class A { public function foo() {} } $i = new A();");
 
84
 
 
85
    TopDUContext* top = parse(method, DumpAll);
 
86
    DUChainReleaser releaseTop(top);
 
87
    DUChainWriteLocker lock(DUChain::lock());
 
88
 
 
89
    ExpressionParser p(true);
 
90
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("$i->foo()"), DUContextPointer(top), SimpleCursor(1, 0));
 
91
    QVERIFY(res.type());
 
92
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
93
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type())->dataType() == IntegralType::TypeVoid);
 
94
    QCOMPARE(res.allDeclarations().size(), 1);
 
95
    QCOMPARE(res.allDeclarations().first(), top->childContexts().first()->localDeclarations().first());
 
96
}
 
97
void TestExpressionParser::globalFunction()
 
98
{
 
99
    //                 0         1         2         3         4         5         6         7
 
100
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
101
    QByteArray method("<? function foo() {}");
 
102
 
 
103
    TopDUContext* top = parse(method, DumpNone);
 
104
    DUChainReleaser releaseTop(top);
 
105
    DUChainWriteLocker lock(DUChain::lock());
 
106
 
 
107
    ExpressionParser p(true);
 
108
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
109
    QVERIFY(res.type());
 
110
    QVERIFY(FunctionType::Ptr::dynamicCast(res.type()));
 
111
    QCOMPARE(res.allDeclarations().count(), 1);
 
112
    QCOMPARE(res.allDeclarations().first(), top->localDeclarations().first());
 
113
}
 
114
 
 
115
void TestExpressionParser::chainCall()
 
116
{
 
117
    //                 0         1         2         3         4         5         6         7
 
118
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
119
    QByteArray method("<? class A { function foo() { return $this; } } $a = new A();");
 
120
 
 
121
    TopDUContext* top = parse(method, DumpAll);
 
122
    DUChainReleaser releaseTop(top);
 
123
    DUChainWriteLocker lock(DUChain::lock());
 
124
 
 
125
    FunctionType::Ptr fn = top->childContexts().first()->localDeclarations().first()->type<FunctionType>();
 
126
    QVERIFY(fn);
 
127
    QVERIFY(fn->returnType()->equals(top->localDeclarations().first()->abstractType().unsafeData()));
 
128
 
 
129
    ExpressionParser p(true);
 
130
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("$a->foo()"), DUContextPointer(top), SimpleCursor(1, 0));
 
131
    QVERIFY(res.type());
 
132
    QVERIFY(res.type()->equals(top->localDeclarations().first()->abstractType().unsafeData()));
 
133
 
 
134
    res = p.evaluateType(QByteArray("$a->foo()->foo()->foo()"), DUContextPointer(top), SimpleCursor(1, 0));
 
135
    QVERIFY(res.type());
 
136
    QVERIFY(res.type()->equals(top->localDeclarations().first()->abstractType().unsafeData()));
 
137
}
 
138
void TestExpressionParser::thisObject()
 
139
{
 
140
    //                 0         1         2         3         4         5         6         7
 
141
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
142
    QByteArray method("<? class A { public function foo() {} }");
 
143
 
 
144
    TopDUContext* top = parse(method, DumpNone);
 
145
    DUChainReleaser releaseTop(top);
 
146
    DUChainWriteLocker lock(DUChain::lock());
 
147
 
 
148
    DUContext* funContext = top->childContexts().first()->localDeclarations().first()->internalContext();
 
149
    ExpressionParser p(true);
 
150
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("$this"), DUContextPointer(funContext), SimpleCursor(1, 0));
 
151
    QCOMPARE(res.allDeclarations().count(), 1);
 
152
    QCOMPARE(res.allDeclarations().first(), top->localDeclarations().first());
 
153
    QVERIFY(res.type());
 
154
    QVERIFY(StructureType::Ptr::dynamicCast(res.type()));
 
155
    QCOMPARE(StructureType::Ptr::dynamicCast(res.type())->declaration(top), top->localDeclarations().first());
 
156
}
 
157
 
 
158
void TestExpressionParser::integralTypes()
 
159
{
 
160
    //                 0         1         2         3         4         5         6         7
 
161
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
162
    QByteArray method("<? $foo=1;");
 
163
 
 
164
    TopDUContext* top = parse(method, DumpNone);
 
165
    DUChainReleaser releaseTop(top);
 
166
    DUChainWriteLocker lock(DUChain::lock());
 
167
 
 
168
    ExpressionParser p(true);
 
169
 
 
170
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("123"), DUContextPointer(top), SimpleCursor(1, 0));
 
171
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
172
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeInt));
 
173
 
 
174
    res = p.evaluateType(QByteArray("123.1"), DUContextPointer(top), SimpleCursor(1, 0));
 
175
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
176
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeFloat));
 
177
 
 
178
    res = p.evaluateType(QByteArray("\"asdf\""), DUContextPointer(top), SimpleCursor(1, 0));
 
179
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
180
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeString));
 
181
 
 
182
    res = p.evaluateType(QByteArray("\"as $foo df\""), DUContextPointer(top), SimpleCursor(1, 0));
 
183
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
184
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeString));
 
185
 
 
186
    res = p.evaluateType(QByteArray("'asdf'"), DUContextPointer(top), SimpleCursor(1, 0));
 
187
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
188
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeString));
 
189
 
 
190
    res = p.evaluateType(QByteArray("true"), DUContextPointer(top), SimpleCursor(1, 0));
 
191
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
192
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeBoolean));
 
193
 
 
194
    res = p.evaluateType(QByteArray("TRUE"), DUContextPointer(top), SimpleCursor(1, 0));
 
195
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
196
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeBoolean));
 
197
 
 
198
    res = p.evaluateType(QByteArray("null"), DUContextPointer(top), SimpleCursor(1, 0));
 
199
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
200
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeNull));
 
201
 
 
202
    res = p.evaluateType(QByteArray("NULL"), DUContextPointer(top), SimpleCursor(1, 0));
 
203
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
204
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeNull));
 
205
}
 
206
 
 
207
void TestExpressionParser::newObject()
 
208
{
 
209
    //                 0         1         2         3         4         5         6         7
 
210
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
211
    QByteArray method("<? class A {} ");
 
212
 
 
213
    TopDUContext* top = parse(method, DumpNone);
 
214
    DUChainReleaser releaseTop(top);
 
215
    DUChainWriteLocker lock(DUChain::lock());
 
216
 
 
217
    ExpressionParser p(true);
 
218
 
 
219
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("new A();"), DUContextPointer(top), SimpleCursor(1, 0));
 
220
    QVERIFY(StructureType::Ptr::dynamicCast(res.type()));
 
221
    QCOMPARE(StructureType::Ptr::staticCast(res.type())->declaration(top), top->localDeclarations().first());
 
222
}
 
223
 
 
224
void TestExpressionParser::cast()
 
225
{
 
226
    //                 0         1         2         3         4         5         6         7
 
227
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
228
    QByteArray method("<? $foo = 1; ");
 
229
 
 
230
    TopDUContext* top = parse(method, DumpNone);
 
231
    DUChainReleaser releaseTop(top);
 
232
    DUChainWriteLocker lock(DUChain::lock());
 
233
 
 
234
    ExpressionParser p(true);
 
235
 
 
236
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("(string)$foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
237
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
238
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeString);
 
239
 
 
240
    res = p.evaluateType(QByteArray("(int)$foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
241
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
242
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeInt);
 
243
 
 
244
    res = p.evaluateType(QByteArray("(double)$foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
245
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
246
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeFloat);
 
247
 
 
248
    res = p.evaluateType(QByteArray("(bool)$foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
249
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
250
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeBoolean);
 
251
 
 
252
    res = p.evaluateType(QByteArray("(array)$foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
253
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
254
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeArray);
 
255
 
 
256
    res = p.evaluateType(QByteArray("(object)$foo"), DUContextPointer(top), SimpleCursor(1, 0));
 
257
    kDebug() << res.type();
 
258
    kDebug() << res.type()->toString();
 
259
    QVERIFY(StructureType::Ptr::dynamicCast(res.type()));
 
260
    QVERIFY(StructureType::Ptr::staticCast(res.type())->qualifiedIdentifier() == QualifiedIdentifier("stdclass"));
 
261
}
 
262
 
 
263
void TestExpressionParser::operations()
 
264
{
 
265
    //                 0         1         2         3         4         5         6         7
 
266
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
267
    QByteArray method("<? $foo = 1; ");
 
268
 
 
269
    TopDUContext* top = parse(method, DumpNone);
 
270
    DUChainReleaser releaseTop(top);
 
271
    DUChainWriteLocker lock(DUChain::lock());
 
272
 
 
273
    ExpressionParser p(true);
 
274
 
 
275
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("'1' . '1'"), DUContextPointer(top), SimpleCursor(1, 0));
 
276
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
277
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeString);
 
278
 
 
279
    res = p.evaluateType(QByteArray("1 . 1"), DUContextPointer(top), SimpleCursor(1, 0));
 
280
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
281
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeString);
 
282
 
 
283
    res = p.evaluateType(QByteArray("1 + 1"), DUContextPointer(top), SimpleCursor(1, 0));
 
284
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
285
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeInt);
 
286
 
 
287
    res = p.evaluateType(QByteArray("'1' + '1'"), DUContextPointer(top), SimpleCursor(1, 0));
 
288
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
289
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeInt);
 
290
 
 
291
    res = p.evaluateType(QByteArray("$foo .= '1'"), DUContextPointer(top), SimpleCursor(1, 0));
 
292
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
293
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeString);
 
294
 
 
295
    res = p.evaluateType(QByteArray("$foo .= 1"), DUContextPointer(top), SimpleCursor(1, 0));
 
296
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
297
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeString);
 
298
 
 
299
    res = p.evaluateType(QByteArray("$foo += 1"), DUContextPointer(top), SimpleCursor(1, 0));
 
300
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
301
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeInt);
 
302
 
 
303
    res = p.evaluateType(QByteArray("$foo += '1'"), DUContextPointer(top), SimpleCursor(1, 0));
 
304
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
305
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeInt);
 
306
 
 
307
    res = p.evaluateType(QByteArray("$foo *= 1"), DUContextPointer(top), SimpleCursor(1, 0));
 
308
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
309
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeInt);
 
310
 
 
311
    res = p.evaluateType(QByteArray("$foo *= '1'"), DUContextPointer(top), SimpleCursor(1, 0));
 
312
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
313
    QVERIFY(IntegralType::Ptr::staticCast(res.type())->dataType() == IntegralType::TypeInt);
 
314
}
 
315
 
 
316
void TestExpressionParser::findArg()
 
317
{
 
318
    //                 0         1         2         3         4         5         6         7
 
319
    //                 01234567890123456789012345678901234567890123456789012345678901234567890123456789
 
320
    QByteArray method("<? class A{} function foo($arg, &$bar, A &$a) {  } ");
 
321
 
 
322
    TopDUContext* top = parse(method, DumpNone);
 
323
    DUChainReleaser releaseTop(top);
 
324
    DUChainWriteLocker lock(DUChain::lock());
 
325
 
 
326
    ExpressionParser p(true);
 
327
 
 
328
    QCOMPARE(top->childContexts().size(), 3);
 
329
    QVERIFY(top->childContexts().at(0)->type() == DUContext::Class);
 
330
    QVERIFY(top->childContexts().at(1)->type() == DUContext::Function);
 
331
    QVERIFY(top->childContexts().at(2)->type() != DUContext::Function);
 
332
 
 
333
    ExpressionEvaluationResult res = p.evaluateType(QByteArray("$arg"), DUContextPointer(top->childContexts().last()),
 
334
                                                    SimpleCursor(0, 47));
 
335
    QVERIFY(IntegralType::Ptr::dynamicCast(res.type()));
 
336
    QCOMPARE(IntegralType::Ptr::staticCast(res.type())->dataType(), static_cast<uint>(IntegralType::TypeMixed));
 
337
 
 
338
    res = p.evaluateType(QByteArray("$bar"), DUContextPointer(top->childContexts().last()),
 
339
                         SimpleCursor(0, 47));
 
340
    ReferenceType::Ptr type = ReferenceType::Ptr::dynamicCast(res.type());
 
341
    QVERIFY(type);
 
342
    QVERIFY(IntegralType::Ptr::dynamicCast(type->baseType()));
 
343
    QCOMPARE(IntegralType::Ptr::staticCast(type->baseType())->dataType(), static_cast<uint>(IntegralType::TypeMixed));
 
344
 
 
345
    res = p.evaluateType(QByteArray("$a"), DUContextPointer(top->childContexts().last()),
 
346
                         SimpleCursor(0, 47));
 
347
    type = ReferenceType::Ptr::dynamicCast(res.type());
 
348
    QVERIFY(type);
 
349
    QVERIFY(StructureType::Ptr::dynamicCast(type->baseType()));
 
350
    QCOMPARE(StructureType::Ptr::staticCast(type->baseType())->declaration(top), top->localDeclarations().first());
 
351
}
 
352
 
 
353
}
 
354
 
 
355
#include "test_expressionparser.moc"