[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdev-ruby/gsoc] duchain: This commit fixes a few things regarding class subclassing:
From: Miquel_Sabaté <mikisabate () gmail ! com>
Date: 2012-05-31 19:29:56
Message-ID: 20120531192956.5C8DBA60A9 () git ! kde ! org
[Download RAW message or body]
Git commit 95c6675fef5d9ae7ec0770f64fb6d30ca4ab2570 by Miquel Sabaté.
Committed on 30/05/2012 at 12:54.
Pushed by mssola into branch 'gsoc'.
This commit fixes a few things regarding class subclassing:
- Fixed visitors of methods/classes/modules from modifying the original AST.
- Properly importing the context of the base class.
- Implemented tests (both duchain and uses) regarding subclassing.
M +9 -2 duchain/builders/contextbuilder.cpp
M +9 -13 duchain/builders/declarationbuilder.cpp
M +49 -14 duchain/tests/duchain.cpp
M +3 -0 duchain/tests/duchain.h
M +5 -0 duchain/tests/duchaintestbase.h
M +14 -0 duchain/tests/uses.cpp
M +1 -0 duchain/tests/uses.h
http://commits.kde.org/kdev-ruby/95c6675fef5d9ae7ec0770f64fb6d30ca4ab2570
diff --git a/duchain/builders/contextbuilder.cpp \
b/duchain/builders/contextbuilder.cpp index 184a214..c541ac6 100644
--- a/duchain/builders/contextbuilder.cpp
+++ b/duchain/builders/contextbuilder.cpp
@@ -148,14 +148,20 @@ KDevelop::QualifiedIdentifier \
ContextBuilder::identifierForNode(NameAst *name)
void ContextBuilder::visitModuleStatement(RubyAst *node)
{
- node->tree = node->tree->l;
+ Node *aux = node->tree;
+ node->tree = aux->l;
visitBody(node);
+ node->tree = aux;
}
void ContextBuilder::visitClassStatement(RubyAst *node)
{
- node->tree = node->tree->l;
+ Node *aux = node->tree;
+ node->tree = aux->cond;
+ visitNode(node);
+ node->tree = aux->l;
visitBody(node);
+ node->tree = aux;
}
void ContextBuilder::visitMethodStatement(RubyAst *node)
@@ -183,6 +189,7 @@ void ContextBuilder::visitMethodStatement(RubyAst *node)
RubyAstVisitor::visitBody(node);
closeContext();
}
+ node->tree = aux;
}
void ContextBuilder::visitRequire(RubyAst *node)
diff --git a/duchain/builders/declarationbuilder.cpp \
b/duchain/builders/declarationbuilder.cpp index 774ddb1..2134f1f 100644
--- a/duchain/builders/declarationbuilder.cpp
+++ b/duchain/builders/declarationbuilder.cpp
@@ -88,6 +88,7 @@ void DeclarationBuilder::visitClassStatement(RubyAst *node)
m_accessPolicyStack.push(Declaration::Public);
lastClassModule = decl;
insideClassModule = true;
+ openContextForClassDefinition(node);
/*
* Now let's check for the base class. Ruby does not support multiple
@@ -98,17 +99,18 @@ void DeclarationBuilder::visitClassStatement(RubyAst *node)
if (node->tree) {
QualifiedIdentifier baseId = getIdentifier(node);
KDevelop::Declaration *baseDecl = declarationForNode(baseId, range, \
DUContextPointer(currentContext()));
- if (!baseDecl) {
+ if (!baseDecl)
appendProblem(node->tree, i18n("NameError: undefined local variable or \
method `%1'", baseId.toString()));
- } else {
+ else {
ClassDeclaration *realClass = dynamic_cast<ClassDeclaration \
*>(baseDecl);
- if (!realClass || realClass->classType() == \
ClassDeclarationData::Interface) { + if (!realClass || \
realClass->classType() == ClassDeclarationData::Interface)
appendProblem(node->tree, i18n("TypeError: wrong argument type \
(expected Class)"));
- } else {
+ else {
+ currentContext()->addImportedParentContext(realClass->internalContext());
BaseClassInstance base;
- StructureType::Ptr baseType = baseDecl->type<StructureType>();
- base.baseClass = baseType->indexed();
+ base.baseClass = realClass->indexedType();
base.access = KDevelop::Declaration::Public;
+ base.virtualInheritance = false;
decl->addBaseClass(base);
}
}
@@ -116,16 +118,13 @@ void DeclarationBuilder::visitClassStatement(RubyAst *node)
node->tree = aux;
/* Setup types and go for the class body */
- StructureType::Ptr type = StructureType::Ptr(new ClassType());
+ ClassType::Ptr type = ClassType::Ptr(new ClassType());
type->setDeclaration(decl);
decl->setType(type);
openType(type);
- openContextForClassDefinition(node);
decl->setInternalContext(currentContext());
- lock.unlock();
DeclarationBuilderBase::visitClassStatement(node);
- lock.lock();
closeContext();
closeType();
@@ -141,7 +140,6 @@ void DeclarationBuilder::visitModuleStatement(RubyAst* node)
QualifiedIdentifier id = getIdentifier(node);
setComment(getComment(node));
- /* TODO: should this get a ModuleDeclaration or so? */
ClassDeclaration *decl = openDeclaration<ClassDeclaration>(id, range);
decl->setKind(KDevelop::Declaration::Type);
decl->clearBaseClasses();
@@ -157,9 +155,7 @@ void DeclarationBuilder::visitModuleStatement(RubyAst* node)
openContextForClassDefinition(node);
decl->setInternalContext(currentContext());
- lock.unlock();
DeclarationBuilderBase::visitModuleStatement(node);
- lock.lock();
closeContext();
closeType();
diff --git a/duchain/tests/duchain.cpp b/duchain/tests/duchain.cpp
index ab02572..6c4329f 100644
--- a/duchain/tests/duchain.cpp
+++ b/duchain/tests/duchain.cpp
@@ -33,6 +33,7 @@
#include <duchain/tests/duchain.h>
#include <duchain/types/classtype.h>
#include <duchain/declarations/methoddeclaration.h>
+#include <duchain/declarations/classdeclaration.h>
QTEST_MAIN(Ruby::TestDUChain)
@@ -312,8 +313,7 @@ void TestDUChain::multipleAssignment2()
{
QByteArray code("a, b = 1, [1, 2, 3]");
- /* TODO: pending */
- QVERIFY(true);
+ PENDING("Waiting for the ClassType to be supported");
}
void TestDUChain::multipleAssignmentLeft()
@@ -546,32 +546,28 @@ void TestDUChain::assignFromArrayItem1()
{
QByteArray code("a = [1, 2, 3]; b = a[0]");
- /* TODO: pending */
- QVERIFY(true);
+ PENDING("Waiting for the ClassType to be supported");
}
void TestDUChain::assignFromArrayItem2()
{
QByteArray code("a = [1, '2']; b = a[0]");
- /* TODO: pending */
- QVERIFY(true);
+ PENDING("Waiting for the ClassType to be supported");
}
void TestDUChain::assignFromHashItem()
{
QByteArray code("a = { :a => 'a', b: 1 }; b = a[:a]");
- /* TODO: pending */
- QVERIFY(true);
+ PENDING("Waiting for the ClassType to be supported");
}
void TestDUChain::assignToArrayItem()
{
QByteArray code("a = [1, nil]; a[1] = 2");
- /* TODO: pending */
- QVERIFY(true);
+ PENDING("Waiting for the ClassType to be supported");
}
//END: Variable Length Container
@@ -646,6 +642,47 @@ void TestDUChain::accessPolicyMethodInModule()
QVERIFY(d4->accessPolicy() == Declaration::Public);
}
+void TestDUChain::checkSubClassing()
+{
+ QByteArray code("class Base; end; class Final < Base; end");
+ TopDUContext *top = parse(code, "checkSubClassing");
+ DUChainReleaser releaser(top);
+ DUChainWriteLocker lock(DUChain::lock());
+
+ // Base
+ ClassDeclaration *base = dynamic_cast<ClassDeclaration \
*>(top->localDeclarations().first()); + QVERIFY(base);
+ QCOMPARE(base->internalContext()->childContexts().count(), 0);
+ QCOMPARE(base->internalContext()->importedParentContexts().count(), 0);
+ QCOMPARE(base->internalContext()->localScopeIdentifier(), \
QualifiedIdentifier("Base")); +
+ // Final
+ ClassDeclaration *final = dynamic_cast<ClassDeclaration \
*>(top->localDeclarations().last()); + QVERIFY(final);
+ QCOMPARE(final->internalContext()->childContexts().count(), 0);
+ QCOMPARE(final->internalContext()->importedParentContexts().count(), 1);
+ QCOMPARE(final->internalContext()->localScopeIdentifier(), \
QualifiedIdentifier("Final")); + QCOMPARE(final->baseClassesSize(), 1u);
+ QCOMPARE(final->baseClasses()[0].baseClass, base->indexedType());
+}
+
+void TestDUChain::checkDeclarationsOnSubClass()
+{
+ /*
+ * The class Base defines a public instance method and a public class
+ * method. Then it defines a protected instance method and a private one.
+ * Finally, the class Final gets defined, and it subclasses the Base class.
+ */
+ QByteArray code("class Base; def foo; end; def self.selfish; end; ");
+ code += "protected; def protected_foo; end; private; def private_foo;";
+ code += "end; end; class Final < Base; end";
+ TopDUContext *top = parse(code, "checkDeclarationsOnSubClass");
+ DUChainReleaser releaser(top);
+ DUChainWriteLocker lock(DUChain::lock());
+
+ PENDING("Still hacking on the subclassing code");
+}
+
//END: Declarations
//BEGIN: Returning Values
@@ -788,8 +825,7 @@ void TestDUChain::include2()
DUChainReleaser releaser(top);
DUChainWriteLocker lock(DUChain::lock());
- /* TODO: pending */
- QVERIFY(true);
+ PENDING("Left as pending for some reason.");
}
void TestDUChain::extend1()
@@ -801,8 +837,7 @@ void TestDUChain::extend1()
DUChainReleaser releaser(top);
DUChainWriteLocker lock(DUChain::lock());
- /* TODO: pending */
- QVERIFY(true);
+ PENDING("Left as pending for some reason.");
}
//END: Include & Extend
diff --git a/duchain/tests/duchain.h b/duchain/tests/duchain.h
index fba1bb2..a0207d9 100644
--- a/duchain/tests/duchain.h
+++ b/duchain/tests/duchain.h
@@ -89,6 +89,7 @@ private slots:
void hashAssignment();
// Variable Length Container
+ // TODO: rename the VariableLengthContainer thingy.
void assignFromArrayItem1();
void assignFromArrayItem2();
void assignFromHashItem();
@@ -98,6 +99,8 @@ private slots:
void instanceClassMethodDeclaration();
void accessPolicyMethodInClass();
void accessPolicyMethodInModule();
+ void checkSubClassing();
+ void checkDeclarationsOnSubClass();
// Returning values
void multipleReturns();
diff --git a/duchain/tests/duchaintestbase.h b/duchain/tests/duchaintestbase.h
index c1d4e07..52f7f48 100644
--- a/duchain/tests/duchaintestbase.h
+++ b/duchain/tests/duchaintestbase.h
@@ -32,6 +32,11 @@
#include <duchain/duchainexport.h>
+// Defined so tests can be marked as pending.
+#define DO_PRAGMA(x) _Pragma (#x)
+#define PENDING(x) DO_PRAGMA(message ("PENDING: " #x))
+
+
namespace Ruby
{
diff --git a/duchain/tests/uses.cpp b/duchain/tests/uses.cpp
index bceda75..56dfd2f 100644
--- a/duchain/tests/uses.cpp
+++ b/duchain/tests/uses.cpp
@@ -104,6 +104,20 @@ void TestUseBuilder::assignment()
compareUses(dec, RangeInRevision(0, 17, 0, 18));
}
+void TestUseBuilder::checkSubClassing()
+{
+ // 0 1 2 3
+ // 0123456789012345678901234567890123456789
+ QByteArray code("class Base; end; class Final < Base; end");
+ TopDUContext *top = parse(code, "checkSubClassing");
+ DUChainReleaser releaser(top);
+ DUChainWriteLocker lock(DUChain::lock());
+
+ Declaration *d = top->localDeclarations().first();
+ QCOMPARE(d->uses().count(), 1);
+ compareUses(d, RangeInRevision(0, 31, 0, 35));
+}
+
} // End of namespace Ruby
diff --git a/duchain/tests/uses.h b/duchain/tests/uses.h
index 36f14e3..1521e31 100644
--- a/duchain/tests/uses.h
+++ b/duchain/tests/uses.h
@@ -56,6 +56,7 @@ private slots:
void stringInterpolation();
void alias();
void assignment();
+ void checkSubClassing();
};
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic