Skip to content

Commit

Permalink
Observe thread interruption status for cancellable tasks (#319)
Browse files Browse the repository at this point in the history
Otherwise `future-cancel` wouldn't do much - at least from what I can infer reading the code.

Fixes #316
  • Loading branch information
vemv committed Jul 8, 2021
1 parent b78e354 commit 67518a5
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* This increases the chances that a namespace will be found, which in turns makes refactor-nrepl more complete/accurate.
* Replace Cheshire with `clojure.data.json`
* Build ASTs more robustly (by using locks and ruling out certain namespaces like refactor-nrepl itself)
* Honor internal `future-cancel` calls, improving overall responsiveness and stability.

### Bugs fixed
* [#289](https://github.com/clojure-emacs/refactor-nrepl/issues/289): Fix an edge-case with involving keywords that caused find-symbol to crash.
Expand Down
16 changes: 12 additions & 4 deletions src/refactor_nrepl/find/find_macros.clj
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
opts {:read-cond :allow :features #{:clj} :eof :eof}]
(loop [macros [], form (reader/read opts rdr)]
(cond
(= form :eof) macros
(or (= form :eof)
(util/interrupted?)) macros
(and (sequential? form) (= (first form) 'defmacro))
(recur (conj macros (build-macro-meta form f))
(reader/read opts rdr))
Expand All @@ -82,7 +83,8 @@
"Finds all macros that are defined in the project."
[ignore-errors?]
(->> (core/find-in-project (util/with-suppressed-errors
(some-fn core/cljc-file? core/clj-file?)
(every-pred (complement util/interrupted?)
(some-fn core/cljc-file? core/clj-file?))
ignore-errors?))
(mapcat #(try
(get-macro-definitions-in-file-with-caching %)
Expand Down Expand Up @@ -217,14 +219,20 @@
(when (fully-qualified-name? fully-qualified-name)
(let [all-defs (find-macro-definitions-in-project ignore-errors?)
macro-def (first (filter #(= (:name %) fully-qualified-name) all-defs))
tracker (tracker/build-tracker (util/with-suppressed-errors tracker/default-file-filter-predicate ignore-errors?))
tracker (tracker/build-tracker (util/with-suppressed-errors
(every-pred (complement util/interrupted?)
tracker/default-file-filter-predicate)
ignore-errors?))
origin-ns (symbol (core/prefix fully-qualified-name))
dependents (tracker/get-dependents tracker origin-ns)]
(some->> macro-def
^String (:file)
File.
(conj dependents)
(mapcat (partial find-usages-in-file [macro-def]))
(keep (fn [x]
(when-not (util/interrupted?)
(find-usages-in-file [macro-def] x))))
(apply concat)
(into #{})
(remove nil?)
(sort-by :line-beg)))))
Expand Down
40 changes: 24 additions & 16 deletions src/refactor_nrepl/find/find_symbol.clj
Original file line number Diff line number Diff line change
Expand Up @@ -137,21 +137,28 @@
(str/join "/" [namespace var-name]))
referred-syms (libspecs/referred-syms-by-file&fullname ignore-errors)]
(->> (core/dirs-on-classpath)
(mapcat (partial core/find-in-dir (util/with-suppressed-errors
(every-pred (some-fn core/clj-file? core/cljc-file?)
(fn [f]
(try
(let [n (some-> f
core/read-ns-form
parse/name-from-ns-decl)]
(if-not n
false
(not (self-referential? n))))
(catch Exception e
(util/maybe-log-exception e)
false))))
ignore-errors)))
(mapcat (partial find-symbol-in-file fully-qualified-name ignore-errors referred-syms)))))
(keep (fn [x]
(when-not (util/interrupted?)
(core/find-in-dir (util/with-suppressed-errors
(every-pred (some-fn core/clj-file? core/cljc-file?)
(fn [f]
(try
(let [n (some-> f
core/read-ns-form
parse/name-from-ns-decl)]
(if-not n
false
(not (self-referential? n))))
(catch Exception e
(util/maybe-log-exception e)
false))))
ignore-errors)
x))))
(apply concat)
(keep (fn [x]
(when-not (util/interrupted?)
(find-symbol-in-file fully-qualified-name ignore-errors referred-syms x))))
(apply concat))))

(defn- get&read-enclosing-sexps
[file-content {:keys [^long line-beg ^long col-beg]}]
Expand Down Expand Up @@ -249,7 +256,8 @@
macros (future (find-macro (core/fully-qualify ns name) ignore-errors?))
globals (->> (find-global-symbol file ns name ignore-errors?)
distinct
(remove find-util/spurious?)
(remove (some-fn util/interrupted?
find-util/spurious?))
future)]

(or
Expand Down
6 changes: 4 additions & 2 deletions src/refactor_nrepl/ns/tracker.clj
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@
"Get the dependent files for ns from tracker."
[tracker my-ns]
(let [deps (dep/immediate-dependents (:clojure.tools.namespace.track/deps tracker)
(symbol my-ns))]
(symbol my-ns))
deps-set (set deps)]
(for [[file ns] (:clojure.tools.namespace.file/filemap tracker)
:when ((set deps) ns)]
:when (and (not (util/interrupted?))
(deps-set ns))]
file)))

(defn- in-refresh-dirs? [refresh-dirs file]
Expand Down
11 changes: 11 additions & 0 deletions src/refactor_nrepl/util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,14 @@
(maybe-log-exception e)
;; return false, because `with-suppressed-errors` is oriented for predicate usage
false)))))

(defn interrupted?
"Has the current thread been interrupted?
Observing this condition helps `future-cancel` effectively cancel `future`s."
([]
(interrupted? ::_))
;; The arity with a "useless" arg is there so that this can be used as a predicate
;; in other places that already are using `some-fn`, `every-pred`, etc
([_]
(.isInterrupted (Thread/currentThread))))

0 comments on commit 67518a5

Please sign in to comment.