mirror of https://github.com/logseq/logseq
Add rules linter for unbound vars and invalid queries
Linter caught one unbound var which wasn't an error but nonetheless good to cleanuppull/4512/head
parent
016efe8aff
commit
6200ec70d3
|
@ -113,6 +113,9 @@ jobs:
|
||||||
- name: Lint invalid translation entries
|
- name: Lint invalid translation entries
|
||||||
run: bb lang:invalid-translations
|
run: bb lang:invalid-translations
|
||||||
|
|
||||||
|
- name: Lint datalog rules
|
||||||
|
run: scripts/lint_rules.clj
|
||||||
|
|
||||||
e2e-test:
|
e2e-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#!/usr/bin/env bb
|
||||||
|
|
||||||
|
(require '[babashka.deps :as deps])
|
||||||
|
(deps/add-deps '{:deps {me.tagaholic/dlint {:mvn/version "0.1.0"}
|
||||||
|
io.lambdaforge/datalog-parser {:mvn/version "0.1.11"}}
|
||||||
|
:paths ["src/main"]})
|
||||||
|
|
||||||
|
(ns lint-rules
|
||||||
|
"Lint datalog rules for parse-ability and unbound variables"
|
||||||
|
(:require [datalog.parser.impl :as parser-impl]
|
||||||
|
[dlint.core :as dlint]
|
||||||
|
[frontend.db.rules :as rules]))
|
||||||
|
|
||||||
|
(defn- lint-unbound-rule [rule]
|
||||||
|
(->> (dlint/lint [rule])
|
||||||
|
(keep
|
||||||
|
(fn [[k v]]
|
||||||
|
(when (seq v)
|
||||||
|
{:success false :name k :rule rule :unbound-vars v})))))
|
||||||
|
|
||||||
|
(defn- lint-rule [rule]
|
||||||
|
(try (parser-impl/parse-rule rule)
|
||||||
|
{:success true :rule rule}
|
||||||
|
(catch Exception e
|
||||||
|
{:success false :rule rule :error (.getMessage e)})))
|
||||||
|
|
||||||
|
(defn- collect-logseq-rules
|
||||||
|
"Collects logseq rules and prepares them for linting"
|
||||||
|
[]
|
||||||
|
(into rules/rules
|
||||||
|
(-> rules/query-dsl-rules
|
||||||
|
;; TODO: Update linter to handle false positive on ?str-val
|
||||||
|
(dissoc :property)
|
||||||
|
vals)))
|
||||||
|
|
||||||
|
(defn -main [rules]
|
||||||
|
(let [invalid-unbound-rules (->> rules
|
||||||
|
(mapcat lint-unbound-rule)
|
||||||
|
(remove :success))
|
||||||
|
invalid-rules (->> rules
|
||||||
|
(map lint-rule)
|
||||||
|
(remove :success))
|
||||||
|
lint-results (concat invalid-unbound-rules invalid-rules)]
|
||||||
|
(if (seq lint-results)
|
||||||
|
(do
|
||||||
|
(println (count lint-results) "rules failed to lint:")
|
||||||
|
(println lint-results)
|
||||||
|
(System/exit 1))
|
||||||
|
(println (count rules) "datalog rules linted fine!"))))
|
||||||
|
|
||||||
|
(when (= *file* (System/getProperty "babashka.file"))
|
||||||
|
(-main (collect-logseq-rules)))
|
|
@ -1,4 +1,4 @@
|
||||||
(ns frontend.db.rules)
|
(ns ^:bb-compatible frontend.db.rules)
|
||||||
|
|
||||||
(def rules
|
(def rules
|
||||||
;; rule "parent" is optimized for child node -> parent node nesting queries
|
;; rule "parent" is optimized for child node -> parent node nesting queries
|
||||||
|
@ -31,9 +31,9 @@
|
||||||
;; Should optimize for query the decendents of a block
|
;; Should optimize for query the decendents of a block
|
||||||
;; Quote:
|
;; Quote:
|
||||||
;; My theory is that your rules are not written in a way that Datalog can optimize for this read pattern - probably resulting in a traversal of all the entities. I suggest to rewrite them as follows:
|
;; My theory is that your rules are not written in a way that Datalog can optimize for this read pattern - probably resulting in a traversal of all the entities. I suggest to rewrite them as follows:
|
||||||
;; [[(ubersymbol ?c ?p)
|
;; [[(ubersymbol ?c ?p)
|
||||||
;; (?c :ml/parent ?p)]
|
;; (?c :ml/parent ?p)]
|
||||||
;; [(ubersymbol ?c ?p)
|
;; [(ubersymbol ?c ?p)
|
||||||
;; ;; we bind a child of the ancestor, instead of a parent of the descendant
|
;; ;; we bind a child of the ancestor, instead of a parent of the descendant
|
||||||
;; (?c1 :ml/parent ?p)
|
;; (?c1 :ml/parent ?p)
|
||||||
;; (ubersymbol ?c ?c1)]]
|
;; (ubersymbol ?c ?c1)]]
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
|
|
||||||
:all-page-tags
|
:all-page-tags
|
||||||
'[(all-page-tags ?p)
|
'[(all-page-tags ?p)
|
||||||
[?e :block/tags ?p]]
|
[_ :block/tags ?p]]
|
||||||
|
|
||||||
:between
|
:between
|
||||||
'[(between ?b ?start ?end)
|
'[(between ?b ?start ?end)
|
Loading…
Reference in New Issue