diff options
author | Noel Power <noel.power@novell.com> | 2012-07-05 19:30:00 +0100 |
---|---|---|
committer | Noel Power <noel.power@novell.com> | 2012-07-05 19:31:16 +0100 |
commit | 0996c0d3193352fe65414ea5577f804dbad8d07b (patch) | |
tree | e12f513ae628ee7c5423b986824ddab9a7084a55 | |
parent | 3de25305a8a495fb63012d36f86461ce003bb5ef (diff) |
make unoCheckStruct uglier but detect unfixed type assignment + add new tests
Change-Id: I6160e7d1abeeda1ea89e2fe15a9155041f2e5adb
-rw-r--r-- | basic/qa/cppunit/test_nested_struct.cxx | 69 | ||||
-rw-r--r-- | basic/source/runtime/step0.cxx | 63 |
2 files changed, 102 insertions, 30 deletions
diff --git a/basic/qa/cppunit/test_nested_struct.cxx b/basic/qa/cppunit/test_nested_struct.cxx index defcaf1b2fe3..21b49132f666 100644 --- a/basic/qa/cppunit/test_nested_struct.cxx +++ b/basic/qa/cppunit/test_nested_struct.cxx @@ -20,12 +20,16 @@ namespace Nested_Struct() {}; void testAssign1(); void testOldAssign(); + void testUnfixedVarAssign(); + void testFixedVarAssign(); // Adds code needed to register the test suite CPPUNIT_TEST_SUITE(Nested_Struct); // Declares the method as a test to call CPPUNIT_TEST(testAssign1); CPPUNIT_TEST(testOldAssign); + CPPUNIT_TEST(testUnfixedVarAssign); + CPPUNIT_TEST(testFixedVarAssign); // End of test suite definition CPPUNIT_TEST_SUITE_END(); @@ -57,6 +61,35 @@ rtl::OUString sTestSource2( "End Function\n" ); +// it should be legal to assign a variant to a struct ( and copy by val ) +// make sure we aren't copying by reference, we make sure that l is not +// a reference copy of b0.HorizontalLine, each one should have an +// OuterLineWidth of 4 & 9 respectively and we should be returning +// 13 the sum of the two ( hopefully unique values if we haven't copied by reference ) +rtl::OUString sTestSource3( + "Function testUnfixedVarAssign()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "l.OuterLineWidth = 4\n" + "testUnfixedVarAssign = b0.HorizontalLine.OuterLineWidth + l.OuterLineWidth\n" +"End Function\n" +); + +// nearly the same as above but this time for a fixed type +// variable +rtl::OUString sTestSource4( + "Function testFixedVarAssign()\n" + "Dim b0 as new \"com.sun.star.table.TableBorder\", l as new \"com.sun.star.table.BorderLine\"\n" + "l = b0.HorizontalLine\n" + "l.OuterLineWidth = 9\n" + "b0.HorizontalLine = l\n" + "l.OuterLineWidth = 4\n" + "testFixedVarAssign = b0.HorizontalLine.OuterLineWidth + l.OuterLineWidth\n" +"End Function\n" +); + void Nested_Struct::testAssign1() { CPPUNIT_ASSERT_MESSAGE( "No resource manager", basicDLL().GetBasResMgr() != NULL ); @@ -93,6 +126,42 @@ void Nested_Struct::testOldAssign() CPPUNIT_ASSERT(pNew->GetInteger() == 9 ); } +void Nested_Struct::testUnfixedVarAssign() +{ + CPPUNIT_ASSERT_MESSAGE( "No resource manager", basicDLL().GetBasResMgr() != NULL ); + StarBASICRef pBasic = new StarBASIC(); + ResetError(); + StarBASIC::SetGlobalErrorHdl( LINK( this, Nested_Struct, BasicErrorHdl ) ); + + SbModule* pMod = pBasic->MakeModule( rtl::OUString( "TestModule" ), sTestSource3 ); + pMod->Compile(); + CPPUNIT_ASSERT_MESSAGE("testUnfixedVarAssign fails with compile error",!HasError() ); + SbMethod* pMeth = static_cast<SbMethod*>(pMod->Find( rtl::OUString("testUnfixedVarAssign"), SbxCLASS_METHOD )); + CPPUNIT_ASSERT_MESSAGE("testUnfixedVarAssign no method found", pMeth ); + SbxVariableRef refTemp = pMeth; + // forces a broadcast + SbxVariableRef pNew = new SbxMethod( *((SbxMethod*)pMeth)); + CPPUNIT_ASSERT(pNew->GetInteger() == 13 ); +} + +void Nested_Struct::testFixedVarAssign() +{ + CPPUNIT_ASSERT_MESSAGE( "No resource manager", basicDLL().GetBasResMgr() != NULL ); + StarBASICRef pBasic = new StarBASIC(); + ResetError(); + StarBASIC::SetGlobalErrorHdl( LINK( this, Nested_Struct, BasicErrorHdl ) ); + + SbModule* pMod = pBasic->MakeModule( rtl::OUString( "TestModule" ), sTestSource4 ); + pMod->Compile(); + CPPUNIT_ASSERT_MESSAGE("testFixedVarAssign fails with compile error",!HasError() ); + SbMethod* pMeth = static_cast<SbMethod*>(pMod->Find( rtl::OUString("testFixedVarAssign"), SbxCLASS_METHOD )); + CPPUNIT_ASSERT_MESSAGE("testFixedVarAssign no method found", pMeth ); + SbxVariableRef refTemp = pMeth; + // forces a broadcast + SbxVariableRef pNew = new SbxMethod( *((SbxMethod*)pMeth)); + CPPUNIT_ASSERT(pNew->GetInteger() == 13 ); +} + // Put the test suite in the registry CPPUNIT_TEST_SUITE_REGISTRATION(Nested_Struct); } // namespace diff --git a/basic/source/runtime/step0.cxx b/basic/source/runtime/step0.cxx index 9149248cb0e0..74b528a41759 100644 --- a/basic/source/runtime/step0.cxx +++ b/basic/source/runtime/step0.cxx @@ -335,54 +335,57 @@ void SbiRuntime::StepGET() inline bool checkUnoStructCopy( bool bVBA, SbxVariableRef& refVal, SbxVariableRef& refVar ) { SbxDataType eVarType = refVar->GetType(); + SbxDataType eValType = refVal->GetType(); - if ( !( !bVBA|| ( bVBA && refVar->GetType() != SbxEMPTY ) ) ) + if ( !( !bVBA|| ( bVBA && refVar->GetType() != SbxEMPTY ) ) || !refVar->CanWrite() ) return false; + if ( eValType != SbxOBJECT ) + return false; + // we seem to be duplicating parts of SbxValue=operator, maybe we should just move this to + // there :-/ not sure if for every '=' we would want struct handling if( eVarType != SbxOBJECT ) + { + if ( refVar->IsFixed() ) + return false; + } + // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure + else if( refVar->ISA(SbProcedureProperty) ) return false; SbxObjectRef xValObj = (SbxObject*)refVal->GetObject(); if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) ) return false; - // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure - if( refVar->ISA(SbProcedureProperty) ) - return false; - - SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject(); - SbxDataType eValType = refVal->GetType(); - if( eValType == SbxOBJECT ) + SbUnoObject* pUnoVal = PTR_CAST(SbUnoObject,(SbxObject*)xValObj); + SbUnoStructRefObject* pUnoStructVal = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xValObj); + Any aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny(); + if ( aAny.getValueType().getTypeClass() == TypeClass_STRUCT ) { + refVar->SetType( SbxOBJECT ); + SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject(); SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)xVarObj); SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xVarObj); - SbUnoObject* pUnoVal = PTR_CAST(SbUnoObject,(SbxObject*)xValObj); - SbUnoStructRefObject* pUnoStructVal = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xValObj); - - if ( ( !pUnoObj && !pUnoStructObj ) || ( !pUnoVal && !pUnoStructVal ) ) + if ( ( !pUnoVal && !pUnoStructVal ) ) return false; - Any aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny(); - if ( aAny.getValueType().getTypeClass() == TypeClass_STRUCT ) - { - String sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName(); - String sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName(); + String sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName(); + String sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName(); - if ( pUnoObj ) - { - SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny ); - // #70324: adopt ClassName - pNewUnoObj->SetClassName( sClassName ); - refVar->PutObject( pNewUnoObj ); - return true; - } - else - { - StructRefInfo aInfo = pUnoStructObj->getStructInfo(); - aInfo.setValue( aAny ); - } + if ( pUnoStructObj ) + { + StructRefInfo aInfo = pUnoStructObj->getStructInfo(); + aInfo.setValue( aAny ); + } + else + { + SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny ); + // #70324: adopt ClassName + pNewUnoObj->SetClassName( sClassName ); + refVar->PutObject( pNewUnoObj ); } + return true; } return false; } |