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

View File

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

View File

@ -747,6 +747,48 @@ TEST_F(CBotUT, ToString)
"}\n" "}\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) // TODO: IntrinsicClassToString ? (e.g. point)
} }
@ -3197,3 +3239,25 @@ TEST_F(CBotUT, ClassTestPrivateMethod)
CBotErrPrivate 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"
);
}