parent
4a62e9ed76
commit
a5909ac4de
|
@ -76,6 +76,18 @@ bool CBotFunction::IsPublic()
|
|||
return m_bPublic;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotFunction::IsProtected()
|
||||
{
|
||||
return m_bProtect;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotFunction::IsPrivate()
|
||||
{
|
||||
return m_bPrivate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotFunction::IsExtern()
|
||||
{
|
||||
|
@ -135,13 +147,11 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
|||
|
||||
while (true)
|
||||
{
|
||||
if ( IsOfType(p, ID_PUBLIC) )
|
||||
{
|
||||
func->m_bPublic = true;
|
||||
continue;
|
||||
}
|
||||
if (IsOfType(p, ID_PRIVATE)) break;
|
||||
if (IsOfType(p, ID_PROTECTED)) break;
|
||||
if (IsOfType(p, ID_PUBLIC)) continue;
|
||||
pp = p;
|
||||
if ( IsOfType(p, ID_EXTERN) )
|
||||
if (IsOfType(p, ID_EXTERN))
|
||||
{
|
||||
func->m_extern = *pp; // for the position of the word "extern"
|
||||
func->m_bExtern = true;
|
||||
|
@ -249,14 +259,30 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
|||
|
||||
CBotCStack* pStk = pStack->TokenStack(p, true);
|
||||
|
||||
CBotToken* pPriv = p;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if ( IsOfType(p, ID_PUBLIC) )
|
||||
if (!func->m_bPublic) // don't repeat 'public'
|
||||
{
|
||||
// func->m_bPublic = true; // will be done in two passes
|
||||
continue;
|
||||
pPriv = p;
|
||||
if (IsOfType(p, ID_PRIVATE))
|
||||
{
|
||||
func->m_bPrivate = true;
|
||||
break;
|
||||
}
|
||||
if (IsOfType(p, ID_PROTECTED))
|
||||
{
|
||||
func->m_bProtect = true;
|
||||
break;
|
||||
}
|
||||
if (IsOfType(p, ID_PUBLIC))
|
||||
{
|
||||
func->m_bPublic = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( IsOfType(p, ID_EXTERN) )
|
||||
if (!func->m_bExtern && IsOfType(p, ID_EXTERN))
|
||||
{
|
||||
func->m_bExtern = true;
|
||||
continue;
|
||||
|
@ -292,6 +318,14 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
|||
if (!IsOfType(p, TokenTypVar)) goto bad;
|
||||
|
||||
}
|
||||
else if (pClass == nullptr) // not method in a class ?
|
||||
{
|
||||
if (func->m_bPrivate || func->m_bProtect) // not allowed for regular functions
|
||||
{
|
||||
pStk->SetError(CBotErrNoType, pPriv);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
CBotToken* openPar = p;
|
||||
func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters
|
||||
|
@ -877,6 +911,25 @@ CBotTypResult CBotFunction::CompileMethodCall(const std::string& name, CBotVar**
|
|||
|
||||
if (pt != nullptr)
|
||||
{
|
||||
CBotToken token("this");
|
||||
CBotVar* pThis = pStack->FindVar(token); // for 'this' context
|
||||
|
||||
if (pThis == nullptr || pThis->GetType() != CBotTypPointer) // called from inside a function
|
||||
{
|
||||
if (pt->IsPrivate() || pt->IsProtected())
|
||||
type.SetType(CBotErrPrivate);
|
||||
}
|
||||
else // called from inside a method
|
||||
{
|
||||
CBotClass* thisClass = pThis->GetClass(); // current class
|
||||
CBotClass* funcClass = CBotClass::Find(pt->m_MasterClass); // class of the method
|
||||
|
||||
if (pt->IsPrivate() && thisClass != funcClass)
|
||||
type.SetType(CBotErrPrivate);
|
||||
|
||||
if (pt->IsProtected() && !thisClass->IsChildOf(funcClass))
|
||||
type.SetType(CBotErrPrivate);
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
|
|
|
@ -283,6 +283,18 @@ public:
|
|||
*/
|
||||
bool IsPublic();
|
||||
|
||||
/*!
|
||||
* \brief Check if a method is protected.
|
||||
* \return true if a method was compiled with "protected" keyword.
|
||||
*/
|
||||
bool IsProtected();
|
||||
|
||||
/*!
|
||||
* \brief Check if a method is private.
|
||||
* \return true if a method was compiled with "private" keyword.
|
||||
*/
|
||||
bool IsPrivate();
|
||||
|
||||
/*!
|
||||
* \brief IsExtern
|
||||
* \return
|
||||
|
@ -328,6 +340,10 @@ private:
|
|||
CBotTypResult m_retTyp;
|
||||
//! Public function.
|
||||
bool m_bPublic;
|
||||
//! Protected method.
|
||||
bool m_bProtect = false;
|
||||
//! Private method.
|
||||
bool m_bPrivate = false;
|
||||
//! Extern function.
|
||||
bool m_bExtern;
|
||||
//! Name of the class we are part of
|
||||
|
|
|
@ -3068,3 +3068,132 @@ TEST_F(CBotUT, ClassInheritanceTestThisOutOfClass)
|
|||
"}\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassTestProtectedMethod)
|
||||
{
|
||||
auto publicProgram = ExecuteTest(
|
||||
"public class BaseClass {\n"
|
||||
" protected bool BaseClassProtected() {\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
" bool NoErrorProtectedSameClass() {\n"
|
||||
" BaseClass b();\n"
|
||||
" ASSERT(true == b.BaseClassProtected());\n"
|
||||
" return BaseClassProtected();\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"extern void Test() {\n"
|
||||
" BaseClass b();\n"
|
||||
" ASSERT(true == b.NoErrorProtectedSameClass());\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {\n"
|
||||
" bool NoErrorProtectedSubClass() {\n"
|
||||
" ASSERT(true == BaseClassProtected());\n"
|
||||
" ASSERT(true == this.BaseClassProtected());\n"
|
||||
" ASSERT(true == super.BaseClassProtected());\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"extern void TestNoErrorProtected() {\n"
|
||||
" SubClass s();\n"
|
||||
" ASSERT(true == s.NoErrorProtectedSubClass());\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void TestErrorProtected_1() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.BaseClassProtected();\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {}\n"
|
||||
"\n"
|
||||
"extern void TestErrorProtected_2() {\n"
|
||||
" SubClass s();\n"
|
||||
" s.BaseClassProtected();\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SomeOtherClass {\n"
|
||||
" void testErrorProtected() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.BaseClassProtected();\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassTestPrivateMethod)
|
||||
{
|
||||
auto publicProgram = ExecuteTest(
|
||||
"public class BaseClass {\n"
|
||||
" private bool BaseClassPrivate() {\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
" bool NoErrorPrivateSameClass() {\n"
|
||||
" BaseClass b();\n"
|
||||
" ASSERT(true == b.BaseClassPrivate());\n"
|
||||
" return BaseClassPrivate();\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"extern void Test() {\n"
|
||||
" BaseClass b();\n"
|
||||
" ASSERT(true == b.NoErrorPrivateSameClass());\n"
|
||||
"}\n"
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {\n"
|
||||
" void ErrorPrivateThis() {\n"
|
||||
" this.BaseClassPrivate();\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {\n"
|
||||
" void ErrorPrivateSuper() {\n"
|
||||
" super.BaseClassPrivate();\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"extern void TestErrorPrivate_1() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.BaseClassPrivate();\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SubClass extends BaseClass {}\n"
|
||||
"\n"
|
||||
"extern void TestErrorPrivate_2() {\n"
|
||||
" SubClass s();\n"
|
||||
" s.BaseClassPrivate();\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class SomeOtherClass {\n"
|
||||
" void ErrorPrivate() {\n"
|
||||
" BaseClass b();\n"
|
||||
" b.BaseClassPrivate();\n"
|
||||
" }\n"
|
||||
"}\n",
|
||||
CBotErrPrivate
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue