Fix inherited data members not being saved

* Removed erroneous 'parent instance' from CBotVarClass.
* Fixed output of CBVarClass::GetValString()
fix-squashed-planets
melex750 2021-06-11 22:44:20 -04:00
parent fabbdda964
commit 993a6adf6e
4 changed files with 108 additions and 39 deletions

View File

@ -908,13 +908,18 @@ bool CBotVar::RestoreState(std::istream &istr, CBotVar* &pVar)
if (isClass && p == nullptr) // set id for each item in this instance
{
CBotVar* pVars = pNew->GetItemList();
CBotVar* pv = pNew->GetClass()->GetVar();
CBotClass* pClass = pNew->GetClass();
CBotVar* pVars = (static_cast<CBotVarClass*>(pNew))->m_pVar;
while (pClass != nullptr && pVars != nullptr)
{
CBotVar* pv = pClass->GetVar();
while (pVars != nullptr && pv != nullptr)
{
pVars->m_ident = pv->m_ident;
pv = pv->GetNext();
pVars = pVars->GetNext();
pVars = pVars->m_next;
pv = pv->m_next;
}
pClass = pClass->GetParent();
}
}

View File

@ -54,7 +54,6 @@ CBotVarClass::CBotVarClass(const CBotToken& name, const CBotTypResult& type) : C
// official type for this object
m_pClass = nullptr;
m_pParent = nullptr;
m_binit = InitType::UNDEF;
m_bStatic = false;
m_mPrivate = ProtectionLevel::Public;
@ -63,14 +62,9 @@ CBotVarClass::CBotVarClass(const CBotToken& name, const CBotTypResult& type) : C
m_ItemIdent = type.Eq(CBotTypIntrinsic) ? 0 : CBotVar::NextUniqNum();
// add to the list
m_instances.insert(this);
if (m_ItemIdent != 0) m_instances.insert(this);
CBotClass* pClass = type.GetClass();
if ( pClass != nullptr && pClass->GetParent() != nullptr )
{
// also creates an instance of the parent class
m_pParent = new CBotVarClass(name, CBotTypResult(type.GetType(), pClass->GetParent()) ); //, nIdent);
}
SetClass( pClass );
@ -82,11 +76,8 @@ CBotVarClass::~CBotVarClass( )
if ( m_CptUse != 0 )
assert(0);
if ( m_pParent ) delete m_pParent;
m_pParent = nullptr;
// removes the class list
m_instances.erase(this);
if (m_ItemIdent != 0) m_instances.erase(this);
delete m_pVar;
}
@ -113,10 +104,6 @@ void CBotVarClass::Copy(CBotVar* pSrc, bool bName)
m_binit = p->m_binit;
//- m_bStatic = p->m_bStatic;
m_pClass = p->m_pClass;
if ( p->m_pParent )
{
assert(0); // "que faire du pParent";
}
// m_next = nullptr;
m_pUserPtr = p->m_pUserPtr;
@ -162,9 +149,11 @@ void CBotVarClass::SetClass(CBotClass* pClass)//, int &nIdent)
if (pClass == nullptr) return;
CBotVar* pv = pClass->GetVar(); // first on a list
while ( pv != nullptr )
CBotVar* pv = nullptr;
while (pClass != nullptr)
{
if ( pv == nullptr ) pv = pClass->GetVar();
if ( pv == nullptr ) { pClass = pClass->GetParent(); continue; }
// seeks the maximum dimensions of the table
CBotInstr* p = pv->m_LimExpr; // the different formulas
if ( p != nullptr )
@ -214,6 +203,7 @@ void CBotVarClass::SetClass(CBotClass* pClass)//, int &nIdent)
if ( m_pVar == nullptr) m_pVar = pn;
else m_pVar->AddNext( pn );
pv = pv->GetNext();
if ( pv == nullptr ) pClass = pClass->GetParent();
}
}
@ -246,7 +236,6 @@ CBotVar* CBotVarClass::GetItem(const std::string& name)
p = p->GetNext();
}
if ( m_pParent != nullptr ) return m_pParent->GetItem(name);
return nullptr;
}
@ -261,7 +250,6 @@ CBotVar* CBotVarClass::GetItemRef(int nIdent)
p = p->GetNext();
}
if ( m_pParent != nullptr ) return m_pParent->GetItemRef(nIdent);
return nullptr;
}
@ -311,31 +299,45 @@ std::string CBotVarClass::GetValString()
{
res = m_pClass->GetName() + std::string("( ");
CBotVarClass* my = this;
while ( my != nullptr )
CBotClass* pClass = m_pClass;
long prevID = 0;
{
CBotVar* pv = my->m_pVar;
while ( pv != nullptr )
CBotVar* pv = m_pVar;
if (pv != nullptr) while (true)
{
if (pv->GetUniqNum() < prevID)
{
pClass = pClass->GetParent();
if (pClass == nullptr) break;
res += " ) extends ";
res += pClass->GetName();
res += "( ";
if (pClass->GetVar() == nullptr) continue;
}
prevID = pv->GetUniqNum();
res += pv->GetName() + std::string("=");
if ( pv->IsStatic() )
{
CBotVar* pvv = my->m_pClass->GetItem(pv->GetName());
res += pvv->GetValString();
res += pClass->GetItemRef(prevID)->GetValString();
}
else
{
res += pv->GetValString();
}
pv = pv->GetNext();
if ( pv != nullptr ) res += ", ";
if ( pv == nullptr ) break;
if ( pv->GetUniqNum() > prevID ) res += ", ";
}
my = my->m_pParent;
if ( my != nullptr )
if (pClass != nullptr) while (true)
{
pClass = pClass->GetParent();
if (pClass == nullptr) break;
res += " ) extends ";
res += my->m_pClass->GetName();
res += pClass->GetName();
res += "( ";
}
}

View File

@ -99,8 +99,6 @@ private:
static std::set<CBotVarClass*> m_instances;
//! Class definition
CBotClass* m_pClass;
//! Parent class instance
CBotVarClass* m_pParent;
//! Class members
CBotVar* m_pVar;
//! Reference counter

View File

@ -747,6 +747,48 @@ TEST_F(CBotUT, ToString)
"}\n"
);
ExecuteTest(
"extern void ClassToString_2()\n"
"{\n"
" string s = new TestClass;\n"
" ASSERT(s == \"Pointer to TestClass( )\");\n"
"}\n"
"public class TestClass { /* no fields */ }\n"
);
ExecuteTest(
"extern void ClassInheritanceToString()\n"
"{\n"
" string s = new SubClass;\n"
" ASSERT(s == \"Pointer to SubClass( c=7, d=8, e=9 ) extends MidClass( b=4, c=5, d=6 ) extends BaseClass( a=1, b=2, c=3 )\");\n"
"}\n"
"public class BaseClass { int a = 1, b = 2, c = 3; }\n"
"public class MidClass extends BaseClass { int b = 4, c = 5, d = 6; }\n"
"public class SubClass extends MidClass { int c = 7, d = 8, e = 9; }\n"
);
ExecuteTest(
"extern void ClassInheritanceToString_2()\n"
"{\n"
" string s = new SubClass;\n"
" ASSERT(s == \"Pointer to SubClass( c=7, d=8, e=9 ) extends MidClass( ) extends BaseClass( a=1, b=2, c=3 )\");\n"
"}\n"
"public class BaseClass { int a = 1, b = 2, c = 3; }\n"
"public class MidClass extends BaseClass { /* no fields */ }\n"
"public class SubClass extends MidClass { int c = 7, d = 8, e = 9; }\n"
);
ExecuteTest(
"extern void ClassInheritanceToString_3()\n"
"{\n"
" string s = new SubClass;\n"
" ASSERT(s == \"Pointer to SubClass( c=7, d=8, e=9 ) extends MidClass( ) extends BaseClass( )\");\n"
"}\n"
"public class BaseClass { /* no fields */ }\n"
"public class MidClass extends BaseClass { /* no fields */ }\n"
"public class SubClass extends MidClass { int c = 7, d = 8, e = 9; }\n"
);
// TODO: IntrinsicClassToString ? (e.g. point)
}
@ -3197,3 +3239,25 @@ TEST_F(CBotUT, ClassTestPrivateMethod)
CBotErrPrivate
);
}
TEST_F(CBotUT, ClassTestSaveInheritedMembers)
{
auto publicProgram = ExecuteTest(
"public class TestClass { int a = 123; }\n"
"public class TestClass2 extends TestClass { int b = 456; }\n"
);
// Note: Use --CBotUT_TestSaveState command line arg.
ExecuteTest(
"extern void TestSaveInheritedMembers()\n"
"{\n"
" TestClass2 t();\n"
" ASSERT(t.a == 123);\n"
" ASSERT(t.b == 456);\n"
" t.a = 789; t.b = 1011;\n"
" ASSERT(t.a == 789);\n"
" ASSERT(t.b == 1011);\n"
" ASSERT(789 == t.a);\n"
" ASSERT(1011 == t.b);\n"
"}\n"
);
}