diff options
author | Eike Rathke <erack@erack.de> | 2011-08-26 13:24:18 +0200 |
---|---|---|
committer | Eike Rathke <erack@erack.de> | 2011-08-26 13:34:59 +0200 |
commit | 6f42e4d03b04204b7a864f3c5c9c03548f5e2392 (patch) | |
tree | 1da52b208ff6e38c524ee8d4a4a4c509d7bcbbce | |
parent | 0e735d61b2601392c2054188166b055bdc061d43 (diff) |
fdo#40378 compile defined names that had unresolveds during load
Dependencies of defined names must not depend on the order in which they
are inserted during file load. In a second step compile defined names
that had unresolved names during load, and only those.
-rw-r--r-- | sc/inc/compiler.hxx | 11 | ||||
-rw-r--r-- | sc/inc/rangenam.hxx | 13 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 3 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 3 | ||||
-rw-r--r-- | sc/source/core/tool/compiler.cxx | 11 | ||||
-rw-r--r-- | sc/source/core/tool/rangenam.cxx | 89 | ||||
-rw-r--r-- | sc/source/ui/view/viewfunc.cxx | 2 |
7 files changed, 102 insertions, 30 deletions
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index 7f418e32486d..f7dde6ae7ed2 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -230,6 +230,13 @@ public: ENCODE_NEVER, }; + enum ExtendedErrorDetection + { + EXTENDED_ERROR_DETECTION_NONE = 0, // no error on unknown symbols, default (interpreter handles it) + EXTENDED_ERROR_DETECTION_NAME_BREAK, // name error on unknown symbols and break, pCode incomplete + EXTENDED_ERROR_DETECTION_NAME_NO_BREAK // name error on unknown symbols, don't break, continue + }; + struct Convention { const formula::FormulaGrammar::AddressConvention meConv; @@ -330,8 +337,8 @@ private: sal_Int32 mnRangeOpPosInSymbol; // if and where a range operator is in symbol const Convention *pConv; EncodeUrlMode meEncodeUrlMode; + ExtendedErrorDetection meExtendedErrorDetection; bool mbCloseBrackets; // whether to close open brackets automatically, default TRUE - bool mbExtendedErrorDetection; bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis bool NextNewToken(bool bInArray = false); @@ -417,7 +424,7 @@ public: void CreateStringFromXMLTokenArray( String& rFormula, String& rFormulaNmsp ); - void SetExtendedErrorDetection( bool bVal ) { mbExtendedErrorDetection = bVal; } + void SetExtendedErrorDetection( ExtendedErrorDetection eVal ) { meExtendedErrorDetection = eVal; } bool IsCorrected() { return bCorrected; } const String& GetCorrectedFormula() { return aCorrectedFormula; } diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index 2774028334af..7b5036216851 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -77,7 +77,8 @@ private: ScAddress aPos; RangeType eType; ScDocument* pDoc; - sal_uInt16 nIndex; + formula::FormulaGrammar::Grammar eTempGrammar; // needed for unresolved XML compiles + sal_uInt16 nIndex; bool bModified; // is set/cleared by UpdateReference // max row and column to use for wrapping of references. If -1 use the @@ -86,6 +87,9 @@ private: SCCOL mnMaxCol; ScRangeData( sal_uInt16 nIndex ); + + void CompileRangeData( const String& rSymbol, bool bSetError ); + public: typedef ::std::map<sal_uInt16, sal_uInt16> IndexMap; @@ -161,6 +165,8 @@ public: SCROW GetMaxRow() const; SC_DLLPUBLIC void SetMaxCol(SCCOL nCol); SCCOL GetMaxCol() const; + + void CompileUnresolvedXML(); }; inline bool ScRangeData::HasType( RangeType nType ) const @@ -204,6 +210,11 @@ public: void UpdateTranspose(const ScRange& rSource, const ScAddress& rDest); void UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY); + /** Compile those names that couldn't be resolved during loading and + inserting because they may have referred a name that was inserted later. + */ + void CompileUnresolvedXML(); + SC_DLLPUBLIC const_iterator begin() const; SC_DLLPUBLIC const_iterator end() const; SC_DLLPUBLIC iterator begin(); diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 75cb42472c39..e475d8aa8172 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -3425,6 +3425,9 @@ void ScDocument::CompileXML() OSL_ENSURE( !pAutoNameCache, "AutoNameCache already set" ); pAutoNameCache = new ScAutoNameCache( this ); + if (pRangeName) + pRangeName->CompileUnresolvedXML(); + TableContainer::iterator it = maTabs.begin(); for (; it != maTabs.end(); ++it) if (*it) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 10f0e9f08c31..812b07f4ccce 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1302,6 +1302,9 @@ void ScTable::CompileAll() void ScTable::CompileXML( ScProgress& rProgress ) { + if (mpRangeName) + mpRangeName->CompileUnresolvedXML(); + for (SCCOL i=0; i <= MAXCOL; i++) { aCol[i].CompileXML( rProgress ); diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 8d1ad64e4742..22c6c910c533 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -1735,8 +1735,8 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra mnRangeOpPosInSymbol(-1), pConv( pConvOOO_A1 ), meEncodeUrlMode( ENCODE_BY_GRAMMAR ), + meExtendedErrorDetection( EXTENDED_ERROR_DETECTION_NONE ), mbCloseBrackets( true ), - mbExtendedErrorDetection( false ), mbRewind( false ) { nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0; @@ -1751,8 +1751,8 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos) mnRangeOpPosInSymbol(-1), pConv( pConvOOO_A1 ), meEncodeUrlMode( ENCODE_BY_GRAMMAR ), + meExtendedErrorDetection( EXTENDED_ERROR_DETECTION_NONE ), mbCloseBrackets( true ), - mbExtendedErrorDetection( false ), mbRewind( false ) { nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0; @@ -3703,11 +3703,12 @@ bool ScCompiler::NextNewToken( bool bInArray ) } while (mbRewind); - if ( mbExtendedErrorDetection ) + if ( meExtendedErrorDetection != EXTENDED_ERROR_DETECTION_NONE ) { - // set an error and end compilation + // set an error SetError( errNoName ); - return false; + if (meExtendedErrorDetection == EXTENDED_ERROR_DETECTION_NAME_BREAK) + return false; // end compilation } // Provide single token information and continue. Do not set an error, that diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 2437eb4844fd..23e1b2f88aba 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -75,33 +75,16 @@ ScRangeData::ScRangeData( ScDocument* pDok, aPos ( rAddress ), eType ( nType ), pDoc ( pDok ), + eTempGrammar( eGrammar ), nIndex ( 0 ), bModified ( false ), mnMaxRow (-1), mnMaxCol (-1) { if (rSymbol.Len() > 0) - { - ScCompiler aComp( pDoc, aPos ); - aComp.SetGrammar(eGrammar); - pCode = aComp.CompileString( rSymbol ); - if( !pCode->GetCodeError() ) - { - pCode->Reset(); - FormulaToken* p = pCode->GetNextReference(); - if( p )// genau eine Referenz als erstes - { - if( p->GetType() == svSingleRef ) - eType = eType | RT_ABSPOS; - else - eType = eType | RT_ABSAREA; - } - // ggf. den Fehlercode wg. unvollstaendiger Formel setzen! - // Dies ist fuer die manuelle Eingabe - aComp.CompileTokenArray(); - pCode->DelRPN(); - } - } + CompileRangeData( rSymbol, pDoc->IsImportingXML()); + // Let the compiler set an error on unknown names for a subsequent + // CompileUnresolvedXML(). else { // #i63513#/#i65690# don't leave pCode as NULL. @@ -123,6 +106,7 @@ ScRangeData::ScRangeData( ScDocument* pDok, aPos ( rAddress ), eType ( nType ), pDoc ( pDok ), + eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ), nIndex ( 0 ), bModified ( false ), mnMaxRow (-1), @@ -151,6 +135,7 @@ ScRangeData::ScRangeData( ScDocument* pDok, aPos ( rTarget ), eType ( RT_NAME ), pDoc ( pDok ), + eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ), nIndex ( 0 ), bModified ( false ), mnMaxRow (-1), @@ -174,6 +159,7 @@ ScRangeData::ScRangeData(const ScRangeData& rScRangeData, ScDocument* pDocument) aPos (rScRangeData.aPos), eType (rScRangeData.eType), pDoc (pDocument ? pDocument : rScRangeData.pDoc), + eTempGrammar(rScRangeData.eTempGrammar), nIndex (rScRangeData.nIndex), bModified (rScRangeData.bModified), mnMaxRow (rScRangeData.mnMaxRow), @@ -185,6 +171,60 @@ ScRangeData::~ScRangeData() delete pCode; } +void ScRangeData::CompileRangeData( const String& rSymbol, bool bSetError ) +{ + if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED) + { + OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar"); + // Anything is almost as bad as this, but we might have the best choice + // if not loading documents. + eTempGrammar = FormulaGrammar::GRAM_NATIVE; + } + + ScCompiler aComp( pDoc, aPos ); + aComp.SetGrammar( eTempGrammar); + if (bSetError) + aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_NO_BREAK); + ScTokenArray* pNewCode = aComp.CompileString( rSymbol ); + ::std::auto_ptr<ScTokenArray> pOldCode( pCode); // old pCode will be deleted + pCode = pNewCode; + if( !pCode->GetCodeError() ) + { + pCode->Reset(); + FormulaToken* p = pCode->GetNextReference(); + if( p ) + { + // first token is a reference + /* FIXME: wouldn't that need a check if it's exactly one reference? */ + if( p->GetType() == svSingleRef ) + eType = eType | RT_ABSPOS; + else + eType = eType | RT_ABSAREA; + } + // For manual input set an error for an incomplete formula. + if (!pDoc->IsImportingXML()) + { + aComp.CompileTokenArray(); + pCode->DelRPN(); + } + } +} + +void ScRangeData::CompileUnresolvedXML() +{ + if (pCode->GetCodeError() == errNoName) + { + // Reconstruct the symbol/formula and then recompile. + String aSymbol; + ScCompiler aComp( pDoc, aPos, *pCode); + aComp.SetGrammar( eTempGrammar); + aComp.CreateStringFromTokenArray( aSymbol); + // Don't let the compiler set an error for unknown names on final + // compile, errors are handled by the interpreter thereafter. + CompileRangeData( aSymbol, false); + } +} + void ScRangeData::GuessPosition() { // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel @@ -815,6 +855,13 @@ void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) itr->UpdateGrow(rArea, nGrowX, nGrowY); } +void ScRangeName::CompileUnresolvedXML() +{ + DataType::iterator itr = maData.begin(), itrEnd = maData.end(); + for (; itr != itrEnd; ++itr) + itr->CompileUnresolvedXML(); +} + ScRangeName::const_iterator ScRangeName::begin() const { return maData.begin(); diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 2187a736d850..2186e58499be 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -480,7 +480,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS aComp.SetAutoCorrection( sal_True ); if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) { - aComp.SetExtendedErrorDetection( true ); + aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_BREAK ); } String aFormula( rString ); ScTokenArray* pArr; |