initial import
This commit is contained in:
130
task/0012-Backport-parser-issues-fixes.patch
Normal file
130
task/0012-Backport-parser-issues-fixes.patch
Normal file
@@ -0,0 +1,130 @@
|
||||
From: Tomas Babej <tomas@tbabej.com>
|
||||
Date: Sat, 30 Jan 2021 17:50:58 -0500
|
||||
Subject: Backport parser issues fixes
|
||||
|
||||
This backports upstream PR #2405 and commit a5eee5f, which contain extra
|
||||
fixes and tests for issues with numeric project names (amongst others)
|
||||
which were being wrongly interpreted as expressions.
|
||||
|
||||
Addresses upstream issues TW-{2388,2386,2257,1908,1896}
|
||||
---
|
||||
|
||||
diff --git a/src/CLI2.cpp b/src/CLI2.cpp
|
||||
index ec2bd6c7..c49eb4d7 100644
|
||||
--- a/src/CLI2.cpp
|
||||
+++ b/src/CLI2.cpp
|
||||
@@ -1277,7 +1277,9 @@ void CLI2::desugarFilterAttributes ()
|
||||
A2 op ("", Lexer::Type::op);
|
||||
op.tag ("FILTER");
|
||||
|
||||
- A2 rhs ("", values[0]._lextype);
|
||||
+ // Attribute types that do not support evaluation should be interpreted
|
||||
+ // as strings (currently this means that string attributes are not evaluated)
|
||||
+ A2 rhs ("", evalSupported ? values[0]._lextype: Lexer::Type::string);
|
||||
rhs.tag ("FILTER");
|
||||
|
||||
// Special case for '<name>:<value>'.
|
||||
@@ -1371,7 +1373,7 @@ void CLI2::desugarFilterAttributes ()
|
||||
|
||||
// Do not modify this construct without full understanding.
|
||||
// Getting this wrong breaks a whole lot of filtering tests.
|
||||
- if (values.size () > 1 || evalSupported)
|
||||
+ if (evalSupported)
|
||||
{
|
||||
for (auto& v : values)
|
||||
reconstructed.push_back (v);
|
||||
@@ -1946,6 +1948,41 @@ void CLI2::desugarFilterPlainArgs ()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
+// Detects if the bracket at iterator it is a start or end of an empty paren expression
|
||||
+// Examples:
|
||||
+// ( status = pending ) ( )
|
||||
+// ^
|
||||
+// it -----| => true
|
||||
+//
|
||||
+// ( status = pending ) ( project = Home )
|
||||
+// ^
|
||||
+// it -----| => false
|
||||
+bool CLI2::isEmptyParenExpression (std::vector<A2>::iterator it, bool forward /* = true */) const
|
||||
+{
|
||||
+ int open = 0;
|
||||
+ int closed = 0;
|
||||
+
|
||||
+ for (auto a = it; a != (forward ? _args.end (): _args.begin()); (forward ? ++a: --a))
|
||||
+ {
|
||||
+ if (a->attribute("raw") == "(")
|
||||
+ open++;
|
||||
+ else if (a->attribute("raw") == ")")
|
||||
+ closed++;
|
||||
+ else
|
||||
+ // Encountering a non-paren token means there is something between parenthees
|
||||
+ return false;
|
||||
+
|
||||
+ // Getting balanced parentheses means we have an empty paren expression
|
||||
+ if (open == closed && open != 0)
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // Should not end here.
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+////////////////////////////////////////////////////////////////////////////////
|
||||
// Two consecutive FILTER, non-OP arguments that are not "(" or ")" need an
|
||||
// "and" operator inserted between them.
|
||||
//
|
||||
@@ -1971,10 +2008,18 @@ void CLI2::insertJunctions ()
|
||||
// Insert AND between terms.
|
||||
else if (a != prev)
|
||||
{
|
||||
- if ((prev->_lextype != Lexer::Type::op && a->attribute ("raw") == "(") ||
|
||||
- (prev->_lextype != Lexer::Type::op && a->_lextype != Lexer::Type::op) ||
|
||||
- (prev->attribute ("raw") == ")" && a->_lextype != Lexer::Type::op) ||
|
||||
- (prev->attribute ("raw") == ")" && a->attribute ("raw") == "("))
|
||||
+ if ((prev->_lextype != Lexer::Type::op &&
|
||||
+ a->attribute ("raw") == "(" &&
|
||||
+ ! isEmptyParenExpression(a, true) ) ||
|
||||
+ (prev->attribute ("raw") == ")" &&
|
||||
+ a->_lextype != Lexer::Type::op &&
|
||||
+ ! isEmptyParenExpression(prev, false)) ||
|
||||
+ (prev->attribute ("raw") == ")" &&
|
||||
+ a->attribute ("raw") == "(" &&
|
||||
+ ! isEmptyParenExpression(a, true) &&
|
||||
+ ! isEmptyParenExpression(prev, false)) ||
|
||||
+ (prev->_lextype != Lexer::Type::op &&
|
||||
+ a->_lextype != Lexer::Type::op))
|
||||
{
|
||||
A2 opOr ("and", Lexer::Type::op);
|
||||
opOr.tag ("FILTER");
|
||||
diff --git a/src/CLI2.h b/src/CLI2.h
|
||||
index f6b0ce94..025be4c8 100644
|
||||
--- a/src/CLI2.h
|
||||
+++ b/src/CLI2.h
|
||||
@@ -99,6 +99,7 @@ private:
|
||||
void findUUIDs ();
|
||||
void insertIDExpr ();
|
||||
void lexFilterArgs ();
|
||||
+ bool isEmptyParenExpression (std::vector<A2>::iterator it, bool forward = true) const;
|
||||
void desugarFilterPlainArgs ();
|
||||
void insertJunctions ();
|
||||
void defaultCommand ();
|
||||
diff --git a/src/columns/ColTypeString.cpp b/src/columns/ColTypeString.cpp
|
||||
index 37c1433d..4ef97578 100644
|
||||
--- a/src/columns/ColTypeString.cpp
|
||||
+++ b/src/columns/ColTypeString.cpp
|
||||
@@ -58,7 +58,12 @@ void ColumnTypeString::modify (Task& task, const std::string& value)
|
||||
std::string domRef;
|
||||
Lexer::Type type;
|
||||
if (lexer.token (domRef, type) &&
|
||||
- type == Lexer::Type::dom)
|
||||
+ type == Lexer::Type::dom &&
|
||||
+ // Ensure 'value' contains only the DOM reference and no other tokens
|
||||
+ // The lexer.token returns false for end-of-string.
|
||||
+ // This works as long as all the DOM references we should support consist
|
||||
+ // only of a single token.
|
||||
+ lexer.token (domRef, type) == false)
|
||||
{
|
||||
Eval e;
|
||||
e.addSource (domSource);
|
||||
Reference in New Issue
Block a user