Resolves: tdf#142293 Implement the temporariness of GetOpCodeMap()

 This is a combination of 5 commits.

Related: tdf#142293 Introduce a protected FormulaCompiler::GetFinalOpCodeMap()

... to prepare having GetOpCodeMap() return a temporary if a final
doesn't exist yet. Currently just an alias.

xChange-Id: I6fc100ae6223010e149e4af01fc7c17630930de7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139162
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit 603f9ce4f39a59bd84b5c08e3d725e0ee664991f)

Related: tdf#142293 Use FormulaCompiler::GetFinalOpCodeMap() in ScCompiler

xChange-Id: I65bf11fca11acfbc372c99a5210e0f79b61f2be4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139171
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit b8a83c5c63873faf1a63205b8aad634f351d1a9f)

Resolves: tdf#142293 Implement the temporariness of GetOpCodeMap()

xChange-Id: I7c587a68dbdeab9a8c8ed324ecae2eb5dd75b9df
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139201
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit 5aaa0cda74de4170972b7988d8fca16a560b8500)

Related: tdf#142293 Remove temporariness now implemented at GetOpCodeMap()

xChange-Id: Ic61f45b1da286e2f4890bbc81dc5cd18c0d5bbe5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139202
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit 15acaddb54c3e14a49b0d26d879c4436d34933e1)

Related: tdf#142293 Have ScCompiler::GetOpCodeMap() overwrite

... FormulaCompiler::GetOpCodeMap() forwarding to
GetFinalOpCodeMap() as that is what we want from ScCompiler (and
always had), eliminating the now possible temporariness of
FormulaCompiler::GetOpCodeMap().

xChange-Id: Ia87fb0e911e4f7995bfb5df07dcd1fde3713d006
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139205
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit 033e98dbe6aafd6719eb83ea4d2fc68110e195c9)

Change-Id: I7c587a68dbdeab9a8c8ed324ecae2eb5dd75b9df
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139230
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 591b287..044921d 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -817,6 +817,15 @@ FormulaCompiler::~FormulaCompiler()

FormulaCompiler::OpCodeMapPtr FormulaCompiler::GetOpCodeMap( const sal_Int32 nLanguage ) const
{
    const bool bTemporary = !HasOpCodeMap(nLanguage);
    OpCodeMapPtr xMap = GetFinalOpCodeMap(nLanguage);
    if (bTemporary)
        const_cast<FormulaCompiler*>(this)->DestroyOpCodeMap(nLanguage);
    return xMap;
}

FormulaCompiler::OpCodeMapPtr FormulaCompiler::GetFinalOpCodeMap( const sal_Int32 nLanguage ) const
{
    FormulaCompiler::OpCodeMapPtr xMap;
    using namespace sheet;
    switch (nLanguage)
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index 3663203..d94dbd4 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -196,7 +196,30 @@ public:
    typedef std::shared_ptr< const OpCodeMap >  OpCodeMapPtr;
    typedef std::shared_ptr< OpCodeMap >        NonConstOpCodeMapPtr;

protected:
    /** Get finalized OpCodeMap for formula language.

        Creates/returns a singleton instance of an OpCodeMap that contains
        external AddIn mappings if the derived class supports them. Do not call
        at this base class as it results in a permanent mapping without AddIns
        even for derived classes (unless it is for the implementation of the
        temporary GetOpCodeMap()).

        @param nLanguage
            One of css::sheet::FormulaLanguage constants.
        @return Map for nLanguage. If nLanguage is unknown, a NULL map is returned.
     */
    OpCodeMapPtr GetFinalOpCodeMap( const sal_Int32 nLanguage ) const;

public:
    /** Get OpCodeMap for formula language.

        Returns either the finalized OpCodeMap (created by GetFinalOpCodeMap()
        of a derived class) for nLanguage if there is such, or if not then a
        temporary map of which its singleton is reset immediately and the
        temporary will get destroyed by the caller's scope. A temporary map
        created at this base class does *not* contain AddIn mappings.

        @param nLanguage
            One of css::sheet::FormulaLanguage constants.
        @return Map for nLanguage. If nLanguage is unknown, a NULL map is returned.
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 5f6c521..cb60e1f 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -439,6 +439,11 @@ public:

    static const Convention* GetRefConvention( formula::FormulaGrammar::AddressConvention eConv );

    /** Overwrite FormulaCompiler::GetOpCodeMap() forwarding to
        GetFinalOpCodeMap().
     */
    OpCodeMapPtr    GetOpCodeMap( const sal_Int32 nLanguage ) const { return GetFinalOpCodeMap(nLanguage); }

    /// Set symbol map if not empty.
    void            SetFormulaLanguage( const OpCodeMapPtr & xMap );

diff --git a/sc/source/core/tool/calcconfig.cxx b/sc/source/core/tool/calcconfig.cxx
index 2783670..7eb36d7 100644
--- a/sc/source/core/tool/calcconfig.cxx
+++ b/sc/source/core/tool/calcconfig.cxx
@@ -187,11 +187,7 @@ bool ScCalcConfig::operator!= (const ScCalcConfig& r) const
OUString ScOpCodeSetToSymbolicString(const ScCalcConfig::OpCodeSet& rOpCodes)
{
    OUStringBuffer result(256);
    // If GetOpCodeMap() initializes the map at base class
    // formula::FormulaCompiler before any ScCompiler did, all AddIn mapping
    // would be missing also in future. So if it didn't exist destroy it again.
    formula::FormulaCompiler aCompiler;
    const bool bTemporary = !aCompiler.HasOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);
    formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(aCompiler.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH));

    for (auto i = rOpCodes->begin(); i != rOpCodes->end(); ++i)
@@ -201,18 +197,13 @@ OUString ScOpCodeSetToSymbolicString(const ScCalcConfig::OpCodeSet& rOpCodes)
        result.append(pOpCodeMap->getSymbol(*i));
    }

    if (bTemporary)
        aCompiler.DestroyOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);

    return result.makeStringAndClear();
}

ScCalcConfig::OpCodeSet ScStringToOpCodeSet(std::u16string_view rOpCodes)
{
    ScCalcConfig::OpCodeSet result = std::make_shared<o3tl::sorted_vector< OpCode >>();
    // Same as above.
    formula::FormulaCompiler aCompiler;
    const bool bTemporary = !aCompiler.HasOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);
    formula::FormulaCompiler::OpCodeMapPtr pOpCodeMap(aCompiler.GetOpCodeMap(css::sheet::FormulaLanguage::ENGLISH));

    const formula::OpCodeHashMap& rHashMap(pOpCodeMap->getHashMap());
@@ -244,9 +235,6 @@ ScCalcConfig::OpCodeSet ScStringToOpCodeSet(std::u16string_view rOpCodes)
    if( result->find( ocSub ) != result->end())
        result->insert( ocNegSub );

    if (bTemporary)
        aCompiler.DestroyOpCodeMap(css::sheet::FormulaLanguage::ENGLISH);

    return result;
}

diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index b6784f8..580c7ef 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -257,17 +257,17 @@ void ScCompiler::SetGrammar( const FormulaGrammar::Grammar eGrammar )
    if( eGrammar == FormulaGrammar::GRAM_EXTERNAL )
    {
        meGrammar = eGrammar;
        mxSymbols = GetOpCodeMap( css::sheet::FormulaLanguage::NATIVE);
        mxSymbols = GetFinalOpCodeMap( css::sheet::FormulaLanguage::NATIVE);
    }
    else
    {
        FormulaGrammar::Grammar eMyGrammar = eGrammar;
        const sal_Int32 nFormulaLanguage = FormulaGrammar::extractFormulaLanguage( eMyGrammar);
        OpCodeMapPtr xMap = GetOpCodeMap( nFormulaLanguage);
        OpCodeMapPtr xMap = GetFinalOpCodeMap( nFormulaLanguage);
        OSL_ENSURE( xMap, "ScCompiler::SetGrammar: unknown formula language");
        if (!xMap)
        {
            xMap = GetOpCodeMap( css::sheet::FormulaLanguage::NATIVE);
            xMap = GetFinalOpCodeMap( css::sheet::FormulaLanguage::NATIVE);
            eMyGrammar = xMap->getGrammar();
        }