Add private and protected keywords for methods

fixes #854
fixes #882
1164-fix
melex750 2017-11-15 16:22:00 -05:00 committed by Mateusz Przybył
parent 4a62e9ed76
commit a5909ac4de
3 changed files with 208 additions and 10 deletions

View File

@ -76,6 +76,18 @@ bool CBotFunction::IsPublic()
return m_bPublic; return m_bPublic;
} }
////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::IsProtected()
{
return m_bProtect;
}
////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::IsPrivate()
{
return m_bPrivate;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CBotFunction::IsExtern() bool CBotFunction::IsExtern()
{ {
@ -135,13 +147,11 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
while (true) while (true)
{ {
if ( IsOfType(p, ID_PUBLIC) ) if (IsOfType(p, ID_PRIVATE)) break;
{ if (IsOfType(p, ID_PROTECTED)) break;
func->m_bPublic = true; if (IsOfType(p, ID_PUBLIC)) continue;
continue;
}
pp = p; 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_extern = *pp; // for the position of the word "extern"
func->m_bExtern = true; func->m_bExtern = true;
@ -249,14 +259,30 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
CBotCStack* pStk = pStack->TokenStack(p, true); CBotCStack* pStk = pStack->TokenStack(p, true);
CBotToken* pPriv = p;
while (true) 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 pPriv = p;
continue; 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; func->m_bExtern = true;
continue; continue;
@ -292,6 +318,14 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
if (!IsOfType(p, TokenTypVar)) goto bad; 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; CBotToken* openPar = p;
func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters
@ -877,6 +911,25 @@ CBotTypResult CBotFunction::CompileMethodCall(const std::string& name, CBotVar**
if (pt != nullptr) 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; return type;

View File

@ -283,6 +283,18 @@ public:
*/ */
bool IsPublic(); 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 * \brief IsExtern
* \return * \return
@ -328,6 +340,10 @@ private:
CBotTypResult m_retTyp; CBotTypResult m_retTyp;
//! Public function. //! Public function.
bool m_bPublic; bool m_bPublic;
//! Protected method.
bool m_bProtect = false;
//! Private method.
bool m_bPrivate = false;
//! Extern function. //! Extern function.
bool m_bExtern; bool m_bExtern;
//! Name of the class we are part of //! Name of the class we are part of

View File

@ -3068,3 +3068,132 @@ TEST_F(CBotUT, ClassInheritanceTestThisOutOfClass)
"}\n" "}\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
);
}