Fork me on GitHub
#clojurescript
<
2019-06-14
>
vemv00:06:01

Can I use cljs.analyzer.api to analyze a whole project, obtaining a large map with all kind of info? Envisioned usage: I analyze a project -> I inspect the resulting map -> I can query with all accuracy the type/metadata/... of symbols at an arbitrary point (e.g filename f, line 30, column 10)

thheller08:06:32

depends on what in particular you want to do since not all analyzer data is stored

thheller08:06:44

but simple queries like the one you mentioned is possible yes

vemv11:06:56

nice! how does one do it? the api shows how to analyze one file, not a whole project. not sure if one has to manage traversal himself or...?

thheller12:06:12

in shadow-cljs I could tell you how to get access to the complete build state after compilation

thheller12:06:20

but for the normal analyzer API I'm not too sure

vemv12:06:49

> in shadow-cljs I could tell you how to get access to the complete build state after compilation this would be usable for me, feel free to share 🙂

thheller12:06:09

well what in particular are you trying to do?

thheller12:06:57

you can try this in the shadow-cljs clj-repl

thheller12:06:17

(def build-state (shadow/compile! :your-build-id {})

thheller12:06:32

build-state is a gigantic map, don't print it

thheller12:06:47

but it contains a :compiler-env key which is the entire analyzer data from that build

vemv12:06:51

> well what in particular are you trying to do? I tend to be always tinkering 🙂

vemv12:06:07

> but it contains a :compiler-env key which is the entire analyzer data from that build awesome stuff.

thheller12:06:27

so (keys (get-in build-state [:compiler-env :cljs.analyzer/namespaces 'cljs.core :defs])) or so

👍 4
vemv12:06:36

> well what in particular are you trying to do? let's make an hypothetical example, a "find usages" API, for accurate refactoring

thheller12:06:00

thats not gonna be possible with that analyzer data

thheller12:06:13

that requires access to the full AST which is not stored

vemv12:06:40

is it a limitation of cljs.ana or shadow?

thheller12:06:19

the stored analyzer data only contains infos about CLJS "vars"

thheller12:06:32

not what the actual code does

thheller12:06:17

well if you use the actual cljs.analyzer and get the full AST you can do things

vemv12:06:36

> well if you use the actual cljs.analyzer`

vemv12:06:41

as opposed to?

thheller12:06:39

well actual cljs.analyzer not cljs.analyzer.api

vemv12:06:10

got it! do you know of any projects (other than cljs) using it? so I can study those

thheller12:06:59

shadow-cljs of course 😛

thheller12:06:04

but the basics are: read forms using tools.reader, analyze it, process AST in any way you need

thheller12:06:44

doing that for the entire build is where things get a bit more complicated since you have to analyze things in the correct order and so on

thheller12:06:20

cljdoc also does a bit of this I think

vemv12:06:13

> but the basics are: read forms using tools.reader, analyze it, process AST in any way you need would seem less accurate than a project-wide analysis, right? anyway, thanks for all the help, now I can understand the landscape better!

thheller12:06:37

well yes you process the entire project that way and produce whatever data you need. ie. a call graph

dpsutton17:06:30

anyone know of a reason logging to the console from a goloop would be broken in IE11?

joshkh17:06:52

are there any clojurescript http libraries that play well with Transfer-Encoding: chunked?

joshkh17:06:22

cljs-http's :progress. nvm. 🙂

dpsutton17:06:06

Can anyone explain the technical differences between (.log js/console :foo) and (js/console.log :foo). It seems the async macros are particularly sensitive to the difference in a goloop

dpsutton17:06:09

interesting. well i seem to have found an interesting case in IE11 with the dev console closed lol

Dustin Getz19:06:41

Thanks for this

dpsutton19:06:15

thanks very much @mfikes. I think i was wrong and this is unrelated to the distinction between (.log js/console and (js/console.log. Hard to pin down a smallest reproduction in the app

john20:06:33

Does it matter whether it's compiled in advanced or not?

john20:06:24

Well, I guess you wouldn't be logging to the console in advanced...

mfikes20:06:02

@john Both ClojureScript forms compile to the same JavaScript.

ghadi21:06:45

@mfikes but not in core.async/go

ghadi21:06:50

apparently

mfikes21:06:14

Oh, hah. Yeah. It has first crack at it maybe.

ghadi21:06:27

salient code, I think ^

ghadi21:06:42

cljs.user=> (macroexpand '(.log js/console))
(. js/console log)
cljs.user=> (macroexpand '(js/console.log :foo))
(js/console.log :foo)
@dpsutton coreasync treats the first one specially

ghadi21:06:03

which is the one that works properly in go?

ghadi21:06:28

my guess is the second one

ghadi21:06:47

both seem to work for me in isolation -- maybe need a different repro case @dpsutton

mfikes21:06:19

This is why core.async has heartburn with and and or

cljs.user=> (let [x true y false] (macroexpand '(and x y)))
(js* "((~{}) && (~{}))" x y)

ghadi21:06:57

is that only when the locals have a known type? @mfikes

ghadi21:06:19

cljs.user=> (macroexpand '(and a b))
(let* [and__4120__auto__ a] (if and__4120__auto__ (cljs.core/and b) and__4120__auto__))

mfikes21:06:44

I think what happens is that you might have some code that does indeed get inferred in a way that causes js* to be emitted, and then core.async will lift things out of the js* special form, IIRC, cause some sort of breakage. Let me see if I can find the JIRA.

mfikes21:06:17

The way I look at it, just like if is a special form that can suppress evaluation of its arguments, js* can essentially do the same.

mfikes21:06:10

I wonder if core.async has any knowledge that js* is a special form. :thinking_face:

ghadi21:06:28

it does not

ghadi21:06:39

see the extenders to sexpr-to-ssa

mfikes21:06:26

Interesting. At first blush, this makes me think it might be an easy fix. Just teach it that js* is special, and don't rearrange code involved with it. But I have a naïve understanding of core.async at best.

ghadi21:06:25

@mfikes where it would get interesting is code like (go (and (<! chan) (<! chan)))

mfikes21:06:49

Indeed. I reflexively no longer write code like that 😞

mfikes21:06:53

It is too hard to remember to not use and and or in go blocks, though, to be honest.

ghadi21:06:55

what causes that error ^?

ghadi21:06:36

> It is too hard to remember to not use and and or in go blocks, though, to be honest. i've never even heard that folklore, that's wild

mfikes21:06:41

I think it only matters if you are passing things in where the failure to short-circuit can bite you, owing to side effects

mfikes21:06:09

I think your error above @ghadi can be caused if it has problems talking to the browser it launches

ghadi21:06:18

it seems to happen 25% of the time

mfikes21:06:20

I'd slap on a -re node -r

mfikes21:06:15

Wow. 25% is bad

ghadi21:06:21

the thing about if vs js* is that not all the js* forms change evaluation order

ghadi21:06:31

with if you know enough to parse it correctly

ghadi21:06:20

but maybe being aware of js* is sufficient