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