<commit_before>(ns shadow.build.classpath
  (:require [clojure.tools.reader.reader-types :as readers]
            [clojure.tools.reader :as reader]
            [clojure.edn :as edn]
            [clojure.spec.alpha :as s]
            [clojure.string :as str]
            [clojure.java.io :as io]
            [clojure.set :as set]
            [cljs.tagged-literals :as tags]
            [shadow.jvm-log :as log]
            [shadow.spec :as ss]
            [shadow.build.resource :as rc]
            [shadow.cljs.util :as util]
            [shadow.build.cache :as cache]
            [shadow.build.ns-form :as ns-form]
            [shadow.build.config :as config]
            [shadow.build.cljs-bridge :as cljs-bridge]
            [shadow.build.npm :as npm]
            [shadow.build.data :as data])
  (:import (java.io File)
           (java.util.jar JarFile JarEntry)
           (java.net URL)
           (java.util.zip ZipException)
           (shadow.build.closure JsInspector)
           [java.nio.file Paths Path]
           [com.google.javascript.jscomp CompilerOptions$LanguageMode CompilerOptions SourceFile]
           [com.google.javascript.jscomp.deps ModuleNames]
           [javax.xml.parsers DocumentBuilderFactory]
           [org.w3c.dom Node Element]))

(set! *warn-on-reflection* true)

(def CACHE-TIMESTAMP (util/resource-last-modified "shadow/build/classpath.clj"))

(defn get-classpath []
  ;; in case of a dynamically modified classpath
  ;; we can't use java.class.path so its used last
  ;; shadow-cljs-launcher sets shadow.class.path
  ;; boot-clj sets boot.class-path
  (-> (or (System/getProperty "shadow.class.path")
          (System/getProperty "boot.class.path")
          (System/getProperty "java.class.path"))
      (.split File/pathSeparator)
      (->> (into [] (map io/file)))
      ))

(defn service? [x]
  (and (map? x) (::service x)))

(defn inspect-js [{:keys [compiler] :as state} {:keys [resource-name url] :as rc}]
  ;; avoid parsing cljsjs files since they are standalone bundles
  ;; and can never require/import anything, we don't want to ever include them anyways
  (when-not (str/starts-with? resource-name "cljsjs/")
    (let [source
          (slurp url)

          ;; all requires are collected into
          ;; :js-requires ["foo" "bar/thing" "./baz]
          ;; all imports are collected into
          ;; :js-imports ["react"]
          {:keys [js-requires
                  js-imports<commit_msg>add support for Class-Path helper jars<commit_after>(ns shadow.build.classpath
  (:require [clojure.tools.reader.reader-types :as readers]
            [clojure.tools.reader :as reader]
            [clojure.edn :as edn]
            [clojure.spec.alpha :as s]
            [clojure.string :as str]
            [clojure.java.io :as io]
            [clojure.set :as set]
            [cljs.tagged-literals :as tags]
            [shadow.jvm-log :as log]
            [shadow.spec :as ss]
            [shadow.build.resource :as rc]
            [shadow.cljs.util :as util]
            [shadow.build.cache :as cache]
            [shadow.build.ns-form :as ns-form]
            [shadow.build.config :as config]
            [shadow.build.cljs-bridge :as cljs-bridge]
            [shadow.build.npm :as npm]
            [shadow.build.data :as data])
  (:import (java.io File)
           (java.util.jar JarFile JarEntry Attributes$Name)
           (java.net URL)
           (java.util.zip ZipException)
           (shadow.build.closure JsInspector)
           [java.nio.file Paths Path]
           [com.google.javascript.jscomp CompilerOptions$LanguageMode CompilerOptions SourceFile]
           [com.google.javascript.jscomp.deps ModuleNames]
           [javax.xml.parsers DocumentBuilderFactory]
           [org.w3c.dom Node Element]))

(set! *warn-on-reflection* true)

(def CACHE-TIMESTAMP (util/resource-last-modified "shadow/build/classpath.clj"))

(defn get-classpath []
  ;; in case of a dynamically modified classpath
  ;; we can't use java.class.path so its used last
  ;; shadow-cljs-launcher sets shadow.class.path
  ;; boot-clj sets boot.class-path
  (let [classpath-entries
        (-> (or (System/getProperty "shadow.class.path")
                (System/getProperty "boot.class.path")
                (System/getProperty "java.class.path"))
            (.split File/pathSeparator)
            (->> (into [] (map io/file))))]

    ;; java -cp helper.jar foo.main
    ;; java supports a single jar with a manifest Class-Path entry to further
    ;; expand the classpath. sometimes used when the classpath is too long
    ;; on Windows to be invoked as a command. the original jar will likely be empty
    (if (not= 1 (count classpath-entries))
      classpath-entries
      (let [^File entry (nth classpath-entries 0)]
        ;; don't think it is even possible to get here
        ;; with one classpath entry that isn't a jar but who knows
        (if-not (.endsWith (-> entry (.getName) (.toLowerCase)) ".jar")
          classpath-entries
          (let [jar-file (JarFile. entry)
                manifest (.getManifest jar-file)
                cp-from-jar
                (-> (.getMainAttributes manifest)
                    (.getValue Attributes$Name/CLASS_PATH))]
            ;; no Class-Path:, might be uberjar?
            (if-not cp-from-jar
              classpath-entries
              (->> (str/split cp-from-jar #"\s")
                   ;; spec says they must he urls, so assuming file:/...
                   ;; spec also allows remote urls but unlikely we have that?
                   ;; FIXME: should likely check just in case
                   (map (fn [s] (-> (URL. s) (.getPath) (io/file))))
                   (vec)))))))))

(defn service? [x]
  (and (map? x) (::service x)))

(defn inspect-js [{:keys [compiler] :as state} {:keys [resource-name url] :as rc}]
  ;; avoid parsing cljsjs files since they are standalone bundles
  ;; and can never require/import anything, we don't want to ever include them anyways
  (when-not (str/starts-with? resource-name "cljsjs/")
    (let [source
          (slurp url)

          ;; all requires are collected into
          ;; :js-requires ["foo" "bar/thing" "./baz]
          ;; all imports are collected into
          ;; :js-imports ["react"]
          {:keys [js-requires
                  js-imports
{'fraction_non_alphanumeric': 0.12430720506730007, 'fraction_numerical': 0.0006334125098970705, 'mean_word_length': 2.0689990281827018, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3205734', 'n_tokens_mistral': 1967, 'n_tokens_neox': 1884, 'n_words': 531}