summaryrefslogtreecommitdiff
path: root/addons/web/static
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2018-06-22 11:47:51 +0200
committerAdrien Dieudonne <adr@odoo.com>2018-07-06 14:09:09 +0200
commit0194d85b67c38701befa7d8560a211358fcf79e9 (patch)
tree04cdf311d6d592d3e58c64f2edba4ccfbd2dcc5a /addons/web/static
parent3248498f4844bbeb06768c064b6fd3a1f400030e (diff)
[IMP] web: implement normalize domain utility function
In this commit, we implement a function which normalize a domain represented as a py.js syntax tree.
Diffstat (limited to 'addons/web/static')
-rw-r--r--addons/web/static/src/js/core/py_utils.js30
-rw-r--r--addons/web/static/tests/core/py_utils_tests.js39
2 files changed, 69 insertions, 0 deletions
diff --git a/addons/web/static/src/js/core/py_utils.js b/addons/web/static/src/js/core/py_utils.js
index c077cfc2e7e..f275302279b 100644
--- a/addons/web/static/src/js/core/py_utils.js
+++ b/addons/web/static/src/js/core/py_utils.js
@@ -407,6 +407,35 @@ function formatAST(ast, lbp) {
throw new Error("Unimplemented python construct");
}
+/**
+ * Normalize a domain, at the level of the AST.
+ *
+ * Note: this function does not evaluate anything inside the domain. This is
+ * actually quite critical because this allows the manipulation of unevaluated
+ * (dynamic) domains.
+ *
+ * @param {PyJS AST} domain valid AST representing a domain
+ * @returns {PyJS AST} normalized domain AST
+ */
+function normalizeDomain(domain) {
+ var expected = 1;
+ for (var i = 0; i < domain.first.length; i++) {
+ var value = domain.first[i].value;
+ if (value === '&' || value === '|') {
+ expected++;
+ } else if (value !== '!') {
+ expected--;
+ }
+ }
+ var andOperator = py.tokenize("'&'")[0];
+
+ if (expected < 0) {
+ domain.first.unshift.apply(domain.first, _.times(Math.abs(expected), _.constant(andOperator)));
+ }
+
+ return domain;
+}
+
return {
context: pycontext,
ensure_evaluated: ensure_evaluated,
@@ -414,6 +443,7 @@ return {
eval_domains_and_contexts: eval_domains_and_contexts,
py_eval: py_eval,
formatAST: formatAST,
+ normalizeDomain: normalizeDomain,
};
});
diff --git a/addons/web/static/tests/core/py_utils_tests.js b/addons/web/static/tests/core/py_utils_tests.js
index 99fe3c60862..fafb3d8f6ca 100644
--- a/addons/web/static/tests/core/py_utils_tests.js
+++ b/addons/web/static/tests/core/py_utils_tests.js
@@ -1159,6 +1159,45 @@ QUnit.module('core', function () {
assert.checkAST(expr);
});
+ QUnit.module('pyutils (normalizeDomain)');
+
+ QUnit.assert.checkNormalization = function (domainStr, normalizedDomain) {
+ normalizedDomain = normalizedDomain || domainStr;
+ var domainAST = py.parse(py.tokenize(domainStr));
+ var normalizedDomainAST = pyUtils.normalizeDomain(domainAST);
+ var result = pyUtils.formatAST(normalizedDomainAST);
+ this.pushResult({
+ result: result === normalizedDomain,
+ actual: result,
+ expected: normalizedDomain
+ });
+ };
+
+
+ QUnit.test("return simple (normalized) domains", function (assert) {
+ assert.expect(3);
+
+ assert.checkNormalization("[]");
+ assert.checkNormalization("[('a', '=', 1)]");
+ assert.checkNormalization("['!', ('a', '=', 1)]");
+ });
+
+ QUnit.test("properly add the & in a non normalized domain", function (assert) {
+ assert.expect(1);
+ assert.checkNormalization(
+ "[('a', '=', 1), ('b', '=', 2)]",
+ "['&', ('a', '=', 1), ('b', '=', 2)]"
+ );
+ });
+
+ QUnit.test("normalize domain with ! operator", function (assert) {
+ assert.expect(1);
+ assert.checkNormalization(
+ "['!', ('a', '=', 1), ('b', '=', 2)]",
+ "['&', '!', ('a', '=', 1), ('b', '=', 2)]"
+ );
+ });
+
});
});