File indexing completed on 2024-05-12 12:35:52

0001 /* This file is part of KDevelop
0002  *
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 #include <QtTest/QtTest>
0021 #include <completion/tests/completion.h>
0022 #include <completion/context.h>
0023 #include <language/codecompletion/codecompletiontesthelper.h>
0024 
0025 
0026 QTEST_MAIN(ruby::TestCompletion)
0027 
0028 using namespace KDevelop;
0029 namespace ruby
0030 {
0031 
0032 //BEGIN: Helper structures
0033 using BaseRubyCompletionTester =
0034     CodeCompletionItemTester<CodeCompletionContext>;
0035 
0036 class RubyCompletionTester : public BaseRubyCompletionTester
0037 {
0038 public:
0039     RubyCompletionTester(DUContext *context, QString text = "; ", QString followingText = "",
0040                          CursorInRevision position = CursorInRevision::invalid())
0041         : BaseRubyCompletionTester(context, text, followingText, position)
0042     {
0043         /* There's nothing to do here */
0044     }
0045 };
0046 
0047 const QByteArray testBase(
0048     "class Base\n"
0049     "   def somewhere; end\n"
0050     "   def over; end\n"
0051     "   protected\n"
0052     "   def the; end\n"
0053     "   private\n"
0054     "   def rainbow; end\n"
0055     "end\n"
0056 );
0057 
0058 const QByteArray testKlass(
0059     "class Klass < Base\n"
0060     "end\n"
0061 );
0062 //END: Helper structures
0063 
0064 TestCompletion::TestCompletion()
0065 {
0066     /* There's nothing to do here */
0067 }
0068 
0069 KDevelop::TopDUContext * TestCompletion::parse(const QByteArray &code, const QString &id)
0070 {
0071     const QString &name = "completion_" + id;
0072     return DUChainTestBase::parse(code, name);
0073 }
0074 
0075 void TestCompletion::shouldContain(const QStringList &list, const QStringList &shoulda, bool sameSize)
0076 {
0077     if (sameSize)
0078         QCOMPARE(list.size(), shoulda.size());
0079     foreach (const QString &str, shoulda)
0080         QVERIFY(list.contains(str, Qt::CaseSensitive));
0081 }
0082 
0083 void TestCompletion::standardAccess()
0084 {
0085     QByteArray code("obj = 1; ");
0086     TopDUContext *top = parse(code, "standardAccess");
0087     DUChainReleaser releaseTop(top);
0088     DUChainWriteLocker lock;
0089 
0090     {
0091         RubyCompletionTester tester(top, "");
0092         shouldContain(tester.names, QStringList() << "obj" << "Kernel" << "while");
0093     }
0094 }
0095 
0096 void TestCompletion::baseClass()
0097 {
0098     QByteArray code("class BaseClass; end;");
0099     TopDUContext *top = parse(code, "baseClass");
0100     DUChainReleaser releaseTop(top);
0101     DUChainWriteLocker lock;
0102 
0103     {
0104         RubyCompletionTester tester(top, "class Klass < ");
0105         shouldContain(tester.names, QStringList() << "BaseClass" << "Object" << "String");
0106     }
0107 }
0108 
0109 void TestCompletion::moduleMixins()
0110 {
0111     QByteArray code("module Awesome; end; ");
0112     TopDUContext *top = parse(code, "moduleMixins");
0113     DUChainReleaser releaseTop(top);
0114     DUChainWriteLocker lock;
0115 
0116     {
0117         RubyCompletionTester tester(top, "module MyModule; include ");
0118         shouldContain(tester.names, QStringList() << "Awesome" << "Kernel" << "Enumerable");
0119     }
0120 
0121     {
0122         RubyCompletionTester tester(top, "module MyModule; extend ");
0123         shouldContain(tester.names, QStringList() << "Awesome" << "Kernel" << "Enumerable");
0124     }
0125 }
0126 
0127 void TestCompletion::memberAccess()
0128 {
0129     QByteArray code(testBase);
0130     TopDUContext *top = parse(code, "memberAccess");
0131     DUChainReleaser releaseTop(top);
0132     DUChainWriteLocker lock;
0133 
0134     {
0135         RubyCompletionTester tester(top, "obj = Base.new; obj.");
0136         shouldContain(tester.names, QStringList() << "somewhere" << "over", true);
0137     }
0138 }
0139 
0140 void TestCompletion::checkSubclassing()
0141 {
0142     QByteArray code(testBase + testKlass);
0143     TopDUContext *top = parse(code, "checkSubclassing");
0144     DUChainReleaser releaseTop(top);
0145     DUChainWriteLocker lock;
0146 
0147     {
0148         RubyCompletionTester tester(top, testBase + testKlass + "obj = Klass.new; obj.");
0149         shouldContain(tester.names, QStringList() << "somewhere" << "over", true);
0150     }
0151 }
0152 
0153 void TestCompletion::classMemberAccess()
0154 {
0155     // TODO: I think that the text should not be in here anymore...
0156     QByteArray code("module MyModule; class Klass; end; end\n");
0157     TopDUContext *top = parse(code, "classMemberAccess");
0158     DUChainReleaser releaseTop(top);
0159     DUChainWriteLocker lock;
0160 
0161     {
0162         RubyCompletionTester tester(top, "module MyModule; class Klass; end; end\nMyModule::");
0163         shouldContain(tester.names, QStringList() << "Klass", true);
0164     }
0165 }
0166 
0167 void TestCompletion::fileChoose()
0168 {
0169     QByteArray code("a = 0\n");
0170     TopDUContext *top = parse(code, "fileChoose");
0171     DUChainReleaser releaseTop(top);
0172     DUChainWriteLocker lock;
0173 
0174     {
0175         // Using the stdlib. It's ok if you've installed ruby 1.8.x or 1.9.x
0176         RubyCompletionTester tester(top, "require 'rss/");
0177         shouldContain(tester.names, QStringList() << "maker/" << "0.9.rb" << "utils.rb");
0178     }
0179 
0180     {
0181         // The name used to check if it works is the file containing this same test.
0182         RubyCompletionTester tester(top, "require_relative '");
0183         shouldContain(tester.names, QStringList() << "kdevruby_completion_fileChoose.rb");
0184     }
0185 }
0186 
0187 }
0188