Skip to content

Instantly share code, notes, and snippets.

@martinklepsch

martinklepsch/README.md

Last active Nov 12, 2018
Embed
What would you like to do?
Notes about fixing https://cljdoc.org analysis issues with ClojureScript 1.10.439 https://github.com/cljdoc/cljdoc/issues/201

How to analyze-file with foreign-lib dependencies?

  • I'm trying to figure out how to analyze a file that depends on react (via CLJSJS)
  • Previously cljdoc.org would analyze with *analyze-deps* set to false
  • With 1.10.439 this no longer works. (Dynamic vars can't be resolved, see old description below)
  • With *analyze-deps* set to true I need to properly supply the foreign lib information but I can't figure out how.

Solution

When calling cljs.analyzer.api/analyze-file with the state-as-first-arg arity it calls cljs.env/with-compiler-env which shadowed my own binding described in Current Approach section. I was unaware that analyzer.api/empty-state is actually just a compiler env as well so creating the right compiler env and passing it to analyze-file solved all issues:

(defn- analyze-file [file]
  (let [opts  (cljs.closure/add-implicit-options {})
        state (cljs.env/default-compiler-env opts)]
    (ana/no-warn
     (cljs.closure/validate-opts opts)
     (ana/analyze-file state file opts))
    state))

Current Approach

Supplying :js-dependency-index via cljs.env/default-compiler-env like this:

(binding [cljs.env/*compiler* (cljs.env/default-compiler-env
                                (cljs.closure/add-implicit-options {}))]

I think it's not possible to pass this via analyze-file's third opts arg since that is only the :options part of the compiler env. Unfortunately analyze-deps still throws when doing the check below. The check succeeds right after the binding form (see repro.clj):

(println "REACT FOUND?" (contains? (:js-dependency-index @cljs.env/*compiler*) "react"))

??? Is something modifying the compiler env after the binding? I grepped for swap! calls but couldn't find anything that seemed relevant.

Notes

  • cljs.closure/add-implicit-options is called in the compiler itself and properly discovers the foreign lib information on the classpath (via cljs.closure/get-upstream-deps). Tried passing the return value as opts to analyze-file. Wasn't enough but helpful to better understand stuff.

Old Description (ignore this)

This seems to be a regression between 1.10.339 and 1.10.439.

The error typically looks like this, but also occurs with other dynamic vars:

Unable to resolve var: *instrument-enabled* in this context

Working with 1.10.339:

clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.339"}}}' repro.clj spec.cljc

Failing with 1.10.439:

clj -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.439"}}}' repro.clj spec.cljc
  • It seems to be irrelevant whether the file is a .cljc or .cljs file.
  • In most (maybe all) cases the exception was thrown from inside a macro
{:deps {cljsjs/react {:mvn/version "16.6.0-0"}
org.clojure/clojurescript {:mvn/version "1.10.439"}
org.clojure/test.check {:mvn/version "0.9.0"}}}
(require '[clojure.java.io :as io]
'[cljs.analyzer :as an]
'[cljs.closure]
'[cljs.js-deps]
'[cljs.analyzer.api :as ana])
(defn- analyze-file [file]
(let [opts (cljs.closure/add-implicit-options {})
state (cljs.env/default-compiler-env opts)]
(ana/no-warn
(cljs.closure/validate-opts opts)
(ana/analyze-file state file opts))
state))
(comment
(analyze-file (io/file "spec.cljc"))
)
(doseq [f *command-line-args*]
(try
(analyze-file (io/file f))
(printf "Successfully analyzed %s\n" f)
(catch Exception e
(println "Failed!" (.getMessage e))
(.printStackTrace e))))
(ns codox-test.spec
(:require [clojure.spec.test.alpha :as st]
[react]))
(defn test [foo bar]
(+ foo bar))
(defn macro-calling [a b]
(st/with-instrument-disabled (test a b)))
(ns codox-test.spec-two
(:require [clojure.spec.test.alpha :as st]))
(st/with-instrument-disabled (+ 1 2 3))
@martinklepsch

This comment has been minimized.

Copy link
Owner Author

@martinklepsch martinklepsch commented Nov 9, 2018

ℹ️ the issue was that [an/*analyze-deps* false] — with that flag set to true everything works as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment