sc: let @ collapse arrays from range arithmetic, not just functions
The @ operator collapses an array operand to its upper-left value. A function operand like SEQUENCE pushes a matrix and @ collapses it. A range arithmetic operand like (B2:B3+0) does implicit intersection first and hands @ a scalar, so @ has nothing to collapse. Mark @'s operand as ForceArray in the parameter classifier and wrap UnaryLine in a CurrentFactor scope so the classification reaches the nested operators. Range arithmetic inside @ then materialises as a matrix and reaches @ for the upper-left pick. testSingleValueOperator covers @ on a range expression and a chained @ binary. Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> Change-Id: I7f59bfa1efbceeceb9a3d7f71a0243e9a521b24a Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5517 Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> (cherry picked from commit 4148cbecbdaa3164c53d3869252a3ca714ba5726) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207868 Tested-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
ee4bd7f201
commit
14d723ea36
@@ -2417,7 +2417,14 @@ void FormulaCompiler::UnaryLine()
|
||||
{
|
||||
FormulaTokenRef p = mpToken;
|
||||
NextToken();
|
||||
UnaryLine();
|
||||
// Hold the unary operator as the current factor so its
|
||||
// parameter classification reaches the nested operators.
|
||||
{
|
||||
CurrentFactor pInnerFac(this);
|
||||
pInnerFac = p;
|
||||
CheckSetForceArrayParameter(mpToken, 0);
|
||||
UnaryLine();
|
||||
}
|
||||
if (mbComputeII)
|
||||
{
|
||||
FormulaToken** pArg = mpCode - 1;
|
||||
|
||||
@@ -5955,6 +5955,25 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testSingleValueOperator)
|
||||
// No spill into the row below.
|
||||
CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 1, 0)));
|
||||
|
||||
// The @ also collapses an array produced by range arithmetic. B2:B3+0
|
||||
// is a two-cell array whose upper-left is B2. The formula sits in a
|
||||
// row that does not overlap B2:B3, so implicit intersection on the
|
||||
// range would otherwise fail and the @ has to drive the collapse.
|
||||
m_pDoc->SetValue(ScAddress(1, 1, 0), 7.0);
|
||||
m_pDoc->SetValue(ScAddress(1, 2, 0), 9.0);
|
||||
m_pDoc->SetFormula(ScAddress(0, 5, 0), u"=@(B2:B3+0)"_ustr,
|
||||
formula::FormulaGrammar::GRAM_NATIVE);
|
||||
CPPUNIT_ASSERT_EQUAL(7.0, m_pDoc->GetValue(ScAddress(0, 5, 0)));
|
||||
CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 6, 0)));
|
||||
|
||||
// Two @-collapsed sub-expressions joined by a binary operator stay
|
||||
// scalar. Without the collapse on each side the addition would see
|
||||
// two arrays and produce one too, leaving the row below populated.
|
||||
m_pDoc->SetFormula(ScAddress(0, 8, 0), u"=@((B2:B3+0)) + @((B2:B3+0))"_ustr,
|
||||
formula::FormulaGrammar::GRAM_NATIVE);
|
||||
CPPUNIT_ASSERT_EQUAL(14.0, m_pDoc->GetValue(ScAddress(0, 8, 0)));
|
||||
CPPUNIT_ASSERT_EQUAL(CELLTYPE_NONE, m_pDoc->GetCellType(ScAddress(0, 9, 0)));
|
||||
|
||||
m_pDoc->DeleteTab(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +249,7 @@ const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
|
||||
{ ocScan, {{ Value, ForceArray, Value }, 0, ForceArrayReturn }},
|
||||
{ ocSheet, {{ Reference }, 0, Value }},
|
||||
{ ocSheets, {{ Reference }, 1, Value }},
|
||||
{ ocSingleValue, {{ ForceArray }, 0, Value }},
|
||||
{ ocSkew, {{ Reference }, 1, Value }},
|
||||
{ ocSkewp, {{ Reference }, 1, Value }},
|
||||
{ ocSlope, {{ ForceArray, ForceArray }, 0, Value }},
|
||||
|
||||
Reference in New Issue
Block a user