eastwood

All things realted to eastwood - the Clojure linter
2018-10-09T06:54:45.000100Z

@slipset Hope I'm not messing up any pending commits you might have while I blast several changes into Eastwood repo today... Finding a few small things and fixing them (I hope).

slipset 2018-10-09T07:10:10.000100Z

@andy.fingerhut No problem! I’m just hugely grateful for all the help I’m getting from you.

slipset 2018-10-09T07:11:56.000100Z

I have some more stuff on the way wrt cleaning up the callback code.

slipset 2018-10-09T12:57:27.000100Z

I know I’ve asked this before, but say I have a project which contains two namespaces.

slipset 2018-10-09T12:57:38.000100Z

Would it be possible to do something like:

slipset 2018-10-09T12:59:41.000100Z

(let [f1 (future (lint-and-analyze ns1 linters)
        f2 (future (lint-and-analyze ns2 linters)]
    (results @f1 @f2))

slipset 2018-10-09T13:00:44.000100Z

My main question being, would the analyzer be tripping over itself because it’s doing analysis on two ns’s in parallell?

bronsa 2018-10-09T13:30:53.000100Z

unforunately, because namespace loading in clojure is side-effectful , this is not possible to do in the general case

bronsa 2018-10-09T13:33:10.000100Z

Imagine (ns foo) (def a 1) (ns bar) (def a (resolve 'foo/a))

bronsa 2018-10-09T13:33:14.000100Z

which unfortunately is valid clojure

😞 1
slipset 2018-10-09T14:00:38.000100Z

Hmm, but would stuff break, or would I just end up analyzing both ns’s in both futures?

slipset 2018-10-09T14:01:47.000100Z

I guess my end goal would be to analyze several ns’s at the same time. I wouldn’t mind getting the occasional penalty from analyzing the same ns in two threads, but I wouldn’t want the two threads to mess up each others analyzis.

slipset 2018-10-09T14:01:59.000100Z

If you see what I’m getting at?

bronsa 2018-10-09T14:02:17.000100Z

analysis is not the problem, t.a in theory has no issues analysing two namespaces in parallel

bronsa 2018-10-09T14:03:12.000100Z

the problem is that clojure makes no guarantees that all the namespace dependencies will be declaratively defined in ns

bronsa 2018-10-09T14:03:36.000100Z

so side-effecty stuff in the namespace could depend on a particular order of loading namespaces

bronsa 2018-10-09T14:04:25.000100Z

and given that namespace loading is not transactional in clojure, if we mess up and accidentally load in the wrong order, we might end up with 2 broken namespaces, which could lead to a snowball effect of further namespaces breaking down the line

slipset 2018-10-09T14:04:53.000100Z

would this comment in eastwood have something to do with that situation?

slipset 2018-10-09T14:05:01.000100Z

;; Create all namespaces to be analyzed.  This can help in some
       ;; (unusual) situations, such as when namespace A requires B,
       ;; so Eastwood analyzes B first, but eval'ing B assumes that
       ;; A's namespace has been created first because B contains
       ;; (alias 'x 'A)
       (doseq [n namespaces]
         (create-ns n))

bronsa 2018-10-09T14:05:09.000200Z

no

slipset 2018-10-09T14:05:14.000100Z

Ok.

bronsa 2018-10-09T14:05:31.000100Z

I'm not saying it's never possible to do this parallel loading, in fact it's likely the case that for > 80% of the clojure projects it could be for a certain subset of the ns graph

bronsa 2018-10-09T14:05:45.000100Z

just that there's no clear way to know whether it's possible or not, doing analysis

bronsa 2018-10-09T14:05:52.000100Z

other than trying and catching errors

slipset 2018-10-09T14:06:00.000100Z

So a :parallel true option would be nice 🙂

bronsa 2018-10-09T14:06:08.000100Z

yep that's what I was going to suggest

bronsa 2018-10-09T14:06:33.000200Z

possibly true vs a vector of top-level namespaces?

slipset 2018-10-09T14:07:01.000100Z

But out of curiousity. It seems like the order eastwood processes ns’s is somewhat arbitrary?

bronsa 2018-10-09T14:07:29.000100Z

IIRC it's the order derived by tools.namespace's topological sort?

slipset 2018-10-09T14:10:56.000200Z

Hmm, doesn’t seem like there is any sorting?

slipset 2018-10-09T14:11:25.000100Z

hmm maybe it does.

slipset 2018-10-09T14:12:13.000200Z

Probably here:

bronsa 2018-10-09T14:14:09.000100Z

yeah I think that's it

slipset 2018-10-09T14:14:23.000100Z

I guess it would be nice that the fact that namespaces has some sort of order was somewhat clearer in the code.

2018-10-09T15:22:47.000100Z

I believe the :namespaces option the user can provide does not really have an order, even though it is a vector. That is, they are sorted in dependency order regardless of the order the user provides them. IIRC

slipset 2018-10-09T15:48:04.000100Z

So I see that in nss-in-dirs we get the namespaces in a toplogical sorted order (from extracting :tools.namespace.tracker/load from the tracker map`)

slipset 2018-10-09T15:52:47.000100Z

But then we seem to bash the test-ns’s and source-ns’s together. How are we sure that the correct order is preserved?

2018-10-09T16:04:31.000100Z

It should do the topological sorting on the combination of source-ns's and test-ns's, I thought. Looking...

2018-10-09T16:09:04.000200Z

ok, I probably said something wrong earlier -- perhaps Eastwood does honor the order the user provides in the :namespaces vector. Within that vector, if it finds the keyword :source-paths it replaces it with a topologically sorted sequence of source namespaces, and independently also does that for :test-paths. If that description is correct, then you could often mess up Eastwood's linting by specifying :test-paths earlier than :source-paths.

2018-10-09T16:09:56.000100Z

It would still work in cases where loading the namespace twice in the same JVM, without unloading it in between, gave the same results, because even if you do not lint a namespace, the namespace can still be loaded by Clojure normally via eval'ing ns and require statements.

2018-10-09T16:27:19.000100Z

FYI, regarding magnitude of false positives in the current version of the new :implicit-dependencies linter, I have been updating lots of project versions in the crucible set of projects, and one, carmine, has 1003 such warnings with the latest Eastwood code. I suspect most of them are probably noise, but haven't looked at them in any detail.

2018-10-09T18:38:35.000100Z

@slipset You should regard this recent commit of mine with suspicion -- I have tested that it achieves the effect I had in mind of printing stack traces of exceptions thrown by linters (as older versions of Eastwood did, but 0.3.1 and maybe some other versions don't), but it may clash with your plans for the callback restructuring.

2018-10-09T18:40:18.000100Z

I would understand if maybe you'd prefer the default behavior not to spew all that stuff to the output when Eastwood code throws an exception, but there ought to at least be a debug flag to enable it, if it is not the default.

slipset 2018-10-09T18:42:18.000100Z

I’ll take a look. I’ll push a branch later tonight CEST to show where I’m heading.