File indexing completed on 2024-04-28 04:35:54

0001 /*
0002  * This file is part of KDevelop
0003  * Copyright (C) 2012-2015 Miquel Sabaté Solà <mikisabate@gmail.com>
0004  *
0005  * This program is free software: you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation, either version 3 of the License, or
0008  * (at your option) any later version.
0009  *
0010  * This program is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  * GNU General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU General Public License
0016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017  */
0018 
0019 
0020 // Qt + KDevelop
0021 #include <QtTest/QtTest>
0022 #include <language/duchain/declaration.h>
0023 #include <language/duchain/types/structuretype.h>
0024 #include <language/duchain/duchainutils.h>
0025 
0026 // Ruby
0027 #include <duchain/helpers.h>
0028 #include <duchain/tests/uses.h>
0029 #include <duchain/declarations/methoddeclaration.h>
0030 #include <duchain/declarations/moduledeclaration.h>
0031 
0032 
0033 QTEST_MAIN(ruby::TestUseBuilder)
0034 
0035 using namespace KDevelop;
0036 namespace ruby
0037 {
0038 
0039 TestUseBuilder::TestUseBuilder()
0040 {
0041     /* There's nothing do here! */
0042 }
0043 
0044 TopDUContext * TestUseBuilder::parse(const QByteArray &code, const QString &id)
0045 {
0046     const QString &name = "uses_" + id;
0047     return DUChainTestBase::parse(code, name);
0048 }
0049 
0050 void TestUseBuilder::compareUses(Declaration *dec, const RangeInRevision &range)
0051 {
0052     QList<RangeInRevision> ranges;
0053     ranges << range;
0054     compareUses(dec, ranges);
0055 }
0056 
0057 void TestUseBuilder::compareUses(Declaration *dec, QList<RangeInRevision> ranges)
0058 {
0059     QCOMPARE(dec->uses().keys().count(), 1);
0060     QCOMPARE(dec->uses().values().count(), 1);
0061     QCOMPARE(dec->uses().values().first().count(), ranges.count());
0062     for (int i = 0; i < ranges.count(); ++i)
0063         QCOMPARE(dec->uses().values().first().at(i), ranges.at(i));
0064 }
0065 
0066 //BEGIN: Basic stuff
0067 
0068 void TestUseBuilder::stringInterpolation()
0069 {
0070     //               0          1
0071     //               01234567 89012 34
0072     QByteArray code("a = 1; \"#{a}\"");
0073     TopDUContext *top = parse(code, "stringInterpolation");
0074     DUChainReleaser releaser(top);
0075     DUChainWriteLocker lock;
0076 
0077     Declaration *dec = top->localDeclarations().at(0);
0078     compareUses(dec, RangeInRevision(0, 10, 0, 11));
0079 
0080     /* Make sure that types are not screwed up after building this new use */
0081     QVERIFY(dec->type<StructureType>());
0082     QCOMPARE(dec->type<StructureType>()->qualifiedIdentifier(), QualifiedIdentifier("Fixnum"));
0083 }
0084 
0085 void TestUseBuilder::alias()
0086 {
0087     //               0          1        2
0088     //               0123456789012345678901234567
0089     QByteArray code("def foo; end; alias asd foo ");
0090     TopDUContext *top = parse(code, "alias");
0091     DUChainReleaser releaser(top);
0092     DUChainWriteLocker lock;
0093 
0094     Declaration *dec = top->localDeclarations().at(0);
0095     compareUses(dec, RangeInRevision(0, 24, 0, 27));
0096 }
0097 
0098 void TestUseBuilder::assignment()
0099 {
0100     //               0          1        2         3
0101     //               01234567890123456789012345678901234567
0102     QByteArray code("b = 0; a, *, c = b, nil, 3, 4, 5, 'asd'");
0103     TopDUContext *top = parse(code, "alias");
0104     DUChainReleaser releaser(top);
0105     DUChainWriteLocker lock;
0106 
0107     Declaration *dec = top->localDeclarations().at(0);
0108     compareUses(dec, RangeInRevision(0, 17, 0, 18));
0109 }
0110 
0111 void TestUseBuilder::checkSubClassing()
0112 {
0113     //               0          1        2         3
0114     //               0123456789012345678901234567890123456789
0115     QByteArray code("class Base; end; class Final < Base; end");
0116     TopDUContext *top = parse(code, "checkSubClassing");
0117     DUChainReleaser releaser(top);
0118     DUChainWriteLocker lock;
0119 
0120     Declaration *d = top->localDeclarations().first();
0121     QCOMPARE(d->uses().count(), 1);
0122     compareUses(d, RangeInRevision(0, 31, 0, 35));
0123 }
0124 
0125 void TestUseBuilder::instanceVariable()
0126 {
0127     //               0         1         2         3         4         5         6         7
0128     //               012345678901234567890123456789012345678901234567890123456789012345678901
0129     QByteArray code("class Klass; def foo; @lala = 1; end; def asd; @lala = 'asd'; end; end; ");
0130     //               8         9         10
0131     //       23456789012345678901234567890123456
0132     code += "class SubClass < Klass; @lala; end";
0133     TopDUContext *top = parse(code, "instanceVariable");
0134     DUChainReleaser releaser(top);
0135     DUChainWriteLocker lock;
0136 
0137     Declaration *decl = top->localDeclarations().first();
0138     decl = decl->internalContext()->findDeclarations(QualifiedIdentifier("@lala")).first();
0139     QVERIFY(decl);
0140     QList<RangeInRevision> list;
0141     list << RangeInRevision(0, 22, 0, 27) << RangeInRevision(0, 47, 0, 52)
0142          << RangeInRevision(0, 96, 0, 101);
0143     compareUses(decl, list);
0144 }
0145 
0146 void TestUseBuilder::classVariable()
0147 {
0148     //               0         1         2         3         4         5         6
0149     //               0123456789012345678901234567890123456789012345678901234567890
0150     QByteArray code("class Base; @@lala = 1; end; class Klass < Base; @@lala; end");
0151     TopDUContext *top = parse(code, "classVariable");
0152     DUChainReleaser releaser(top);
0153     DUChainWriteLocker lock;
0154 
0155     Declaration *decl = top->localDeclarations().first();
0156     decl = decl->internalContext()->findDeclarations(QualifiedIdentifier("@@lala")).first();
0157     QVERIFY(decl);
0158     QList<RangeInRevision> list;
0159     list << RangeInRevision(0, 12, 0, 18) << RangeInRevision(0, 49, 0, 55);
0160     compareUses(decl, list);
0161 }
0162 
0163 void TestUseBuilder::exceptions()
0164 {
0165     //               0         1         2         3         4         5         6
0166     //               012345678901234567890123456789012345678901234567890123456789012
0167     QByteArray code("def defas; a = 1; 1 / 0; rescue ZeroDivisionError; puts a; end");
0168     TopDUContext *top = parse(code, "exceptions");
0169     DUChainReleaser releaser(top);
0170     DUChainWriteLocker lock;
0171 
0172     // a
0173     Declaration *decl = top->localDeclarations().first();
0174     Declaration *a = decl->internalContext()->localDeclarations().first();
0175     compareUses(a, RangeInRevision(0, 56, 0, 57));
0176 
0177     // ZeroDivisionError
0178     QualifiedIdentifier id("ZeroDivisionError");
0179     Declaration *zero = decl->topContext()->findDeclarations(id).first();
0180     compareUses(zero, RangeInRevision(0, 32, 0, 49));
0181 }
0182 
0183 //END: Basic stuff
0184 
0185 //BEGIN: Contexts
0186 
0187 void TestUseBuilder::block()
0188 {
0189     //               0         1         2         3         4
0190     //               01234567890123456789012345678901234567890123456
0191     QByteArray code("a = ''; 5.times do |a, b|; puts a; puts b; end");
0192     TopDUContext *top = parse(code, "block");
0193     DUChainReleaser releaser(top);
0194     DUChainWriteLocker lock;
0195 
0196     // Outer "a" has no uses
0197     Declaration *a = top->localDeclarations().first();
0198     QCOMPARE(a->uses().count(), 0);
0199 
0200     // Inner a
0201     DUContext *block = top->topContext()->childContexts().first();
0202     a = block->localDeclarations().first();
0203     QCOMPARE(a->range(), RangeInRevision(0, 20, 0, 21));
0204     compareUses(a, RangeInRevision(0, 32, 0, 33));
0205 }
0206 
0207 void TestUseBuilder::checkMethodArgumentsContext()
0208 {
0209     //               0          1        2
0210     //               0123456789012345678901234
0211     QByteArray code("def foo(a, b); a; end; a");
0212     TopDUContext *top = parse(code, "checkMethodArgumentsContext");
0213     DUChainReleaser releaser(top);
0214     DUChainWriteLocker lock;
0215 
0216     // Check that exists a method declaration and that it has a proper
0217     // context for its parameters
0218     QCOMPARE(top->localDeclarations().count(), 1);
0219     Declaration *d = dynamic_cast<Declaration *>(top->localDeclarations().first());
0220     QVERIFY(d);
0221     DUContext *params = DUChainUtils::argumentContext(d);
0222     QVERIFY(params);
0223     QCOMPARE(params->range(), RangeInRevision(0, 8, 0, 12));
0224 
0225     // Check that there's a context for the method body and that it imports
0226     // the context of the parameters
0227     DUContext *body = d->internalContext();
0228     QVERIFY(body);
0229     QCOMPARE(body->range(), RangeInRevision(0, 13, 0, 18));
0230     QCOMPARE(body->importedParentContexts().count(), 1);
0231     QCOMPARE(body->importedParentContexts().first().context(top), params);
0232 
0233     // And finally check the uses of the parameters. There's only one use of a,
0234     // but it's in the method's body. not the a that is outside.
0235     QCOMPARE(params->localDeclarations().count(), 2);
0236     Declaration *a = params->localDeclarations().first();
0237     QCOMPARE(a->qualifiedIdentifier(), QualifiedIdentifier("foo::a"));
0238     QCOMPARE(a->uses().count(), 1);
0239     compareUses(a, RangeInRevision(0, 15, 0, 16));
0240 }
0241 
0242 void TestUseBuilder::checkMethodLocalDeclarations()
0243 {
0244     //               0         1         2
0245     //               01234567890123456789012345
0246     QByteArray code("a = 0; def foo(a); a; end");
0247     TopDUContext *top = parse(code, "checkMethodLocalDeclarations");
0248     DUChainReleaser releaser(top);
0249     DUChainWriteLocker lock;
0250 
0251     // Outer "a" has no uses
0252     Declaration *a = top->localDeclarations().first();
0253     QCOMPARE(a->uses().count(), 0);
0254 
0255     // Inner a
0256     DUContext *method = top->topContext()->childContexts().first();
0257     a = method->localDeclarations().first();
0258     QCOMPARE(a->range(), RangeInRevision(0, 15, 0, 16));
0259     compareUses(a, RangeInRevision(0, 19, 0, 20));
0260 }
0261 
0262 void TestUseBuilder::instanceClassMethods()
0263 {
0264     //               0         1         2         3         4         5         6         7         8
0265     //               01234567890123456789012345678901234567890123456789012345678901234567890123456789012
0266     QByteArray code("class Klass; def self.foo; end; def foo; end; end; a = Klass.new; a.foo; Klass.foo");
0267     TopDUContext *top = parse(code, "instanceClassMethods");
0268     DUChainReleaser releaser(top);
0269     DUChainWriteLocker lock;
0270 
0271     ModuleDeclaration *module = dynamic_cast<ModuleDeclaration *>(top->localDeclarations().first());
0272     QVERIFY(module);
0273     QVector<Declaration *> decls = module->internalContext()->localDeclarations();
0274     QCOMPARE(decls.size(), 1);
0275     MethodDeclaration *md = dynamic_cast<MethodDeclaration *>(decls.first());
0276     QVERIFY(md);
0277     compareUses(md, RangeInRevision(0, 68, 0, 71));
0278 
0279     decls = module->eigenClass()->localDeclarations();
0280     QCOMPARE(decls.size(), 1);
0281     md = dynamic_cast<MethodDeclaration *>(decls.first());
0282     QVERIFY(md);
0283     compareUses(decls.last(), RangeInRevision(0, 79, 0, 81));
0284 }
0285 
0286 void TestUseBuilder::globals1()
0287 {
0288     //               0         1         2         3         4         5         6         7         8
0289     //               01234567890123456789012345678901234567890123456789012345678901234567890123456789012
0290     QByteArray code("$a = 1; def foo; $a; end; class Klass; def foo; $a; end; end; module Modul; $a; end");
0291     TopDUContext *top = parse(code, "globals1");
0292     DUChainReleaser releaser(top);
0293     DUChainWriteLocker lock;
0294 
0295     // Let there be the $a variable.
0296     Declaration *a = top->localDeclarations().first();
0297     QVERIFY(a);
0298     QCOMPARE(a->qualifiedIdentifier(), QualifiedIdentifier("$a"));
0299 
0300     // Let there be uses.
0301     QList<RangeInRevision> ranges;
0302     ranges << RangeInRevision(0, 17, 0, 19) << RangeInRevision(0, 48, 0, 50)
0303            << RangeInRevision(0, 76, 0, 78);
0304     compareUses(a, ranges);
0305 }
0306 
0307 void TestUseBuilder::globals2()
0308 {
0309     //               0         1         2         3         4         5
0310     //               01234567890123456789012345678901234567890123456789012345
0311     QByteArray code("$asd = 1234; class Klass; a = $asd; $asd = 1; class Sub;");
0312     //           6         7
0313     //       67890123456789012345678
0314     code += " $asd = 'asd'; end; end";
0315     TopDUContext *top = parse(code, "globals2");
0316     DUChainReleaser releaser(top);
0317     DUChainWriteLocker lock;
0318 
0319     // Globals are scoped properly even if they're in assignments.
0320 
0321     Declaration *asd = top->localDeclarations().first();
0322     QCOMPARE(asd->qualifiedIdentifier(), QualifiedIdentifier("$asd"));
0323     QList<RangeInRevision> ranges;
0324     ranges << RangeInRevision(0, 30, 0, 34) << RangeInRevision(0, 36, 0, 40);
0325     ranges << RangeInRevision(0, 57, 0, 61);
0326     compareUses(asd, ranges);
0327 }
0328 
0329 void TestUseBuilder::globals3()
0330 {
0331     //               0         1         2         3         4         5
0332     //               0123456789012345678901234567890123456789012345678901234567
0333     QByteArray code("class Klass; $asd = 1; end; module Mod; $asd = 'asd'; end");
0334     TopDUContext *top = parse(code, "globals3");
0335     DUChainReleaser releaser(top);
0336     DUChainWriteLocker lock;
0337 
0338     Declaration *asd = top->localDeclarations().at(1);
0339     QCOMPARE(asd->qualifiedIdentifier(), QualifiedIdentifier("$asd"));
0340     QList<RangeInRevision> ranges;
0341     ranges << RangeInRevision(0, 40, 0, 44);
0342     compareUses(asd, ranges);
0343 }
0344 
0345 
0346 void TestUseBuilder::defaultGlobals()
0347 {
0348     //               0         1
0349     //               01234567890123456789
0350     QByteArray code("def foo; $stdin; end");
0351     TopDUContext *top = parse(code, "defaultGlobals");
0352     DUChainReleaser releaser(top);
0353     DUChainWriteLocker lock;
0354 
0355     // Get the declaration of the $stdin default global variable.
0356     QList<Declaration *> decls = top->findDeclarations(QualifiedIdentifier("$stdin"));
0357     QCOMPARE(decls.size(), 1);
0358 
0359     QList<RangeInRevision> ranges;
0360     ranges << RangeInRevision(0, 9, 0, 15);
0361     compareUses(decls.first(), ranges);
0362 }
0363 
0364 void TestUseBuilder::classModulesScopes()
0365 {
0366     // TODO
0367     QSKIP("There's still some work to do before getting this test to pass");
0368 
0369     // module Klass
0370     // end
0371     //
0372     // module Modul
0373     // end
0374     //
0375     // class Modul::Klass
0376     //   ::Klass
0377     //
0378     //   module Thing
0379     //     Klass
0380     //     ::Klass
0381     //   end
0382     // end
0383     //
0384     // ::Klass
0385     // Modul::Klass
0386 
0387     //               0         1         2         3         4         5
0388     //               012345678901234567890123456789012345678901234567890123456
0389     QByteArray code("module Klass; end; module Modul; end; class Modul::Klass;");
0390     //          6         7         8         9        10        11        12
0391     //       78901234567890123456789012345678901234567890123456789012345678901234567
0392     code += " ::Klass; module Thing; Klass; ::Klass; end; end; ::Klass; Modul::Klass";
0393     TopDUContext *top = parse(code, "classModulesScopes");
0394     DUChainReleaser releaser(top);
0395     DUChainWriteLocker lock;
0396 
0397     // Klass
0398     Declaration *d = top->localDeclarations().first();
0399     QVERIFY(d);
0400     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("Klass"));
0401     QList<RangeInRevision> ranges;
0402     ranges << RangeInRevision(0, 60, 0, 65) << RangeInRevision(0, 90, 0, 95);
0403     ranges << RangeInRevision(0, 109, 0, 114);
0404     compareUses(d, ranges);
0405 
0406     // Modul
0407     d = top->localDeclarations().at(1);
0408     QVERIFY(d);
0409     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("Modul"));
0410     ranges.clear();
0411     ranges << RangeInRevision(0, 44, 0, 49) << RangeInRevision(0, 116, 0, 121);
0412     compareUses(d, ranges);
0413 
0414     // Modul::Klass
0415     d = d->internalContext()->localDeclarations().first();
0416     QVERIFY(d);
0417     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("Modul::Klass"));
0418     ranges.clear();
0419     ranges << RangeInRevision(0, 81, 0, 86) << RangeInRevision(0, 123, 0, 128);
0420     compareUses(d, ranges);
0421 }
0422 
0423 //END: Contexts
0424 
0425 //BEGIN: Method calls
0426 
0427 void TestUseBuilder::builtinUses()
0428 {
0429     //               0          1        2
0430     //               012345678901234567890123
0431     QByteArray code("a = 0; a.zero?; 1.zero?");
0432     TopDUContext *top = parse(code, "builtinUses");
0433     DUChainReleaser releaser(top);
0434     DUChainWriteLocker lock;
0435 
0436     // a
0437     Declaration *d = top->localDeclarations().first();
0438     QVERIFY(d);
0439     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("a"));
0440     compareUses(d, RangeInRevision(0, 7, 0, 8));
0441 
0442     // zero?
0443     d = getBuiltinDeclaration("Fixnum#zero?", top, d->context());
0444     QVERIFY(d);
0445     QList<RangeInRevision> ranges;
0446     ranges << RangeInRevision(0, 9, 0, 14) << RangeInRevision(0, 18, 0, 23);
0447     compareUses(d, ranges);
0448 }
0449 
0450 void TestUseBuilder::chained()
0451 {
0452     // TODO
0453     QSKIP("Not ready...");
0454 
0455     //               0         1         2         3         4         5
0456     //               012345678901234567890123456789012345678901234567890
0457     QByteArray code("module Modul; class Klass; def self.selfish(a, b); ");
0458     //                6         7         8         9         0         1
0459     //       12345678901234567890123456789012345678901234567890123456789012345678
0460     code += "'string'; end; end; end; a = 0; Modul::Klass.selfish(a, 1).bytesize ";
0461     TopDUContext *top = parse(code, "chained");
0462     DUChainReleaser releaser(top);
0463     DUChainWriteLocker lock;
0464 
0465     // Module
0466     Declaration *d = top->localDeclarations().first();
0467     QVERIFY(d);
0468     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("Modul"));
0469     QCOMPARE(d->uses().count(), 1);
0470     compareUses(d, RangeInRevision(0, 83, 0, 88));
0471 
0472     // Modul::Klass
0473     d = d->internalContext()->localDeclarations().first();
0474     QVERIFY(d);
0475     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("Modul::Klass"));
0476     QCOMPARE(d->uses().count(), 1);
0477     compareUses(d, RangeInRevision(0, 90, 0, 95));
0478 
0479     // Modul::Klass.selfish
0480     d = d->internalContext()->localDeclarations().first();
0481     QVERIFY(d);
0482     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("Modul::Klass::selfish"));
0483     QCOMPARE(d->uses().count(), 1);
0484     compareUses(d, RangeInRevision(0, 96, 0, 103));
0485 
0486     // a
0487     d = top->localDeclarations().last();
0488     QVERIFY(d);
0489     QCOMPARE(d->qualifiedIdentifier(), QualifiedIdentifier("a"));
0490     QCOMPARE(d->uses().count(), 1);
0491     compareUses(d, RangeInRevision(0, 104, 0, 105));
0492 
0493     // String#bytesize
0494     d = getBuiltinDeclaration("String#bytesize", top);
0495     QVERIFY(d);
0496     QCOMPARE(d->uses().count(), 1);
0497     compareUses(d, RangeInRevision(0, 110, 0, 118));
0498 }
0499 
0500 void TestUseBuilder::fromClassAndAbove()
0501 {
0502     //               0         1         2         3
0503     //               01234567890123456789012345678901234
0504     QByteArray code("class Klass; attr_reader :asd; end");
0505     TopDUContext *top = parse(code, "fromClassAndAbove");
0506     DUChainReleaser releaser(top);
0507     DUChainWriteLocker lock;
0508 
0509     // Module#attr_reader
0510     Declaration *d = getBuiltinDeclaration("Module#attr_reader", top);
0511     QVERIFY(d);
0512     compareUses(d, RangeInRevision(0, 13, 0, 24));
0513 }
0514 
0515 void TestUseBuilder::super()
0516 {
0517     //               0         1         2         3         4         5
0518     //               0123456789012345678901234567890123456789012345678901234
0519     QByteArray code("class Base; def foo; 'string'; end; end; class Klass < ");
0520     //            6         7         8         9
0521     //       5678901234567890123456789012345678901234
0522     code += "Base; def foo; super.bytesize; end; end";
0523     TopDUContext *top = parse(code, "super");
0524     DUChainReleaser releaser(top);
0525     DUChainWriteLocker lock;
0526 
0527     Declaration *d = getBuiltinDeclaration("String#bytesize", top);
0528     QVERIFY(d);
0529     compareUses(d, RangeInRevision(0, 76, 0, 84));
0530 }
0531 
0532 void TestUseBuilder::moduleMixins1()
0533 {
0534     //               0         1         2         3         4         5
0535     //               0123456789012345678901234567890123456789012345678901234567890
0536     QByteArray code("module A; end; class Klass; include Enumerable; extend A; end");
0537     TopDUContext *top = parse(code, "moduleMixins1");
0538     DUChainReleaser releaser(top);
0539     DUChainWriteLocker lock;
0540 
0541     Declaration *d = top->localDeclarations().first();
0542     QVERIFY(d);
0543     compareUses(d, RangeInRevision(0, 55, 0, 56));
0544 
0545     AbstractType::Ptr type = getBuiltinsType(QString("Enumerable"), top);
0546     auto sType = type.dynamicCast<StructureType>();
0547     QVERIFY(sType);
0548     d = sType->declaration(top);
0549     QVERIFY(d);
0550     compareUses(d, RangeInRevision(0, 36, 0, 46));
0551 }
0552 
0553 void TestUseBuilder::moduleMixins2()
0554 {
0555     //               0         1         2         3         4         5
0556     //               012345678901234567890123456789012345678901234567890123456
0557     QByteArray code("module A; module B; end; end; module C; include A::B; end");
0558     TopDUContext *top = parse(code, "moduleMixins2");
0559     DUChainReleaser releaser(top);
0560     DUChainWriteLocker lock;
0561 
0562     // module A
0563     Declaration *d = top->localDeclarations().first();
0564     QVERIFY(d);
0565     compareUses(d, RangeInRevision(0, 48, 0, 49));
0566 
0567     // module B
0568     d = d->internalContext()->localDeclarations().first();
0569     QVERIFY(d);
0570     compareUses(d, RangeInRevision(0, 51, 0, 52));
0571 }
0572 
0573 void TestUseBuilder::exprIsCalling()
0574 {
0575     //               0         1         2
0576     //               012345678901234567890123456
0577     QByteArray code("a = 0; b = 0; (a - b).to_s ");
0578     TopDUContext *top = parse(code, "exprIsCalling");
0579     DUChainReleaser releaser(top);
0580     DUChainWriteLocker lock;
0581 
0582     // a
0583     Declaration *d = top->localDeclarations().first();
0584     QVERIFY(d);
0585     compareUses(d, RangeInRevision(0, 15, 0, 16));
0586 
0587     // b
0588     d = top->localDeclarations().last();
0589     QVERIFY(d);
0590     compareUses(d, RangeInRevision(0, 19, 0, 20));
0591 
0592     // to_s
0593     d = getBuiltinDeclaration("Fixnum#to_s", top, d->context());
0594     QVERIFY(d);
0595     compareUses(d, RangeInRevision(0, 22, 0, 26));
0596 }
0597 
0598 void TestUseBuilder::stringCalling()
0599 {
0600     //               0         1         2         3
0601     //               0123456789012345678901234567890123456789
0602     QByteArray code("calling = 0; `String is #{calling}`.foo");
0603     TopDUContext *top = parse(code, "stringCalling");
0604     DUChainReleaser releaser(top);
0605     DUChainWriteLocker lock;
0606 
0607     // calling
0608     Declaration *d = top->localDeclarations().first();
0609     QVERIFY(d);
0610     compareUses(d, RangeInRevision(0, 26, 0, 33));
0611 }
0612 
0613 //END: Method calls
0614 
0615 //BEGIN: Others
0616 
0617 void TestUseBuilder::nestedIdentifier()
0618 {
0619     //               0         1         2         3         4         5         6
0620     //               0123456789012345678901234567890123456789012345678901234567890123456789
0621     QByteArray code("module Modul; end; class Modul::Klass; end; module Modul::Nodule; end");
0622     TopDUContext *top = parse(code, "nestedIdentifier");
0623     DUChainReleaser releaser(top);
0624     DUChainWriteLocker lock;
0625 
0626     Declaration *d = top->localDeclarations().first();
0627     QVERIFY(d);
0628     QList<RangeInRevision> list;
0629     list << RangeInRevision(0, 25, 0, 30) << RangeInRevision(0, 51, 0, 56);
0630     compareUses(d, list);
0631 }
0632 
0633 //END: Others
0634 
0635 }
0636