-
-
Notifications
You must be signed in to change notification settings - Fork 149
/
config.clj
132 lines (116 loc) · 5.49 KB
/
config.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
(ns clojure-lsp.config
(:require
[clojure-lsp.logger :as logger]
[clojure-lsp.shared :as shared]
[clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.string :as string])
(:import
(java.util.jar JarFile JarFile$JarFileEntry)))
(set! *warn-on-reflection* true)
(def default-source-path-ignore-regexs ["resources.*" "target.*"])
(defn read-edn-file [^java.io.File file]
(try
(->> (slurp file)
(edn/read-string {:readers {'re re-pattern}})
shared/keywordize-first-depth)
(catch Exception e
(logger/error "WARNING: error while reading" (.getCanonicalPath file) (format "(%s)" (.getMessage e))))))
(defn get-property [p]
(System/getProperty p))
(defn get-env [p]
(System/getenv p))
(defn global-config-file []
(let [xdg-config-home (or (get-env "XDG_CONFIG_HOME")
(io/file (get-property "user.home") ".config"))
xdg-config (io/file xdg-config-home "clojure-lsp")
home-config (io/file (get-property "user.home") ".lsp")
path (if (shared/file-exists? xdg-config)
xdg-config
home-config)]
(io/file path "config.edn")))
(defn global-cache-dir []
(let [cache-home (or (get-env "XDG_CACHE_HOME")
(io/file (get-property "user.home") ".cache"))]
(io/file cache-home "clojure-lsp")))
(defn local-cache-dir [db]
(let [project-root (shared/uri->path (:project-root-uri db))
overwritten-path (some-> (get db [:settings :cache-path])
io/file)
default (io/file (str project-root) ".lsp" ".cache")]
^java.io.File (or overwritten-path default)))
(defn ^:private resolve-global-config [^java.io.File global-lsp-config-file]
(when (shared/file-exists? global-lsp-config-file)
(read-edn-file global-lsp-config-file)))
(defn ^:private resolve-project-configs [project-root-uri ^java.io.File global-lsp-config-file]
(loop [dir (io/file (shared/uri->filename project-root-uri))
configs []]
(let [file (io/file dir ".lsp" "config.edn")
parent (.getParentFile dir)]
(if parent
(recur parent (cond->> configs
(and (shared/file-exists? file)
(not (= (.getAbsolutePath global-lsp-config-file) (.getAbsolutePath file))))
(concat [(read-edn-file file)])))
configs))))
(defn resolve-for-root [project-root-uri]
(when project-root-uri
(let [global-lsp-config-file (global-config-file)
project-configs (resolve-project-configs project-root-uri global-lsp-config-file)]
(reduce shared/deep-merge
(merge {}
(resolve-global-config global-lsp-config-file))
project-configs))))
(defn ^:private jar-file->config
[^java.io.File file config-paths]
(with-open [jar (JarFile. file)]
(->> (enumeration-seq (.entries jar))
(filter (fn [^JarFile$JarFileEntry entry]
(let [entry-name (.getName entry)]
(and (string/starts-with? entry-name "clojure-lsp.exports")
(string/includes? entry-name "config.edn")))))
(mapv (fn [^JarFile$JarFileEntry config-entry]
(let [[_ group artifact] (string/split (.getName config-entry) #"/")]
(when (some #(and (string/starts-with? % group)
(string/ends-with? % artifact)) config-paths)
(logger/info (format "Resolving found clojure-lsp config for '%s/%s' in classpath" group artifact))
(edn/read-string {:readers {'re re-pattern}}
(slurp (.getInputStream jar config-entry))))))))))
(defn deep-merge-fixing-cljfmt
([a b]
(let [deep-merged (shared/deep-merge a b)]
(if (-> deep-merged :cljfmt :indents)
(let [cljfmt-a (-> a :cljfmt :indents)
cljfmt-b (-> b :cljfmt :indents)]
(-> deep-merged
(update-in [:cljfmt :indents] merge cljfmt-a cljfmt-b)))
deep-merged)))
([a b & more]
(reduce deep-merge-fixing-cljfmt (or a {}) (cons b more))))
(defn ^:private resolve-from-classpath-config-paths-impl [classpath {:keys [classpath-config-paths]}]
(when-let [cp-config-paths (and (coll? classpath-config-paths)
(seq classpath-config-paths))]
(when-let [jar-files (->> classpath
(filter #(string/ends-with? % ".jar"))
distinct
(map io/file)
(filter shared/file-exists?))]
(when-let [configs (->> jar-files
(map #(jar-file->config % cp-config-paths))
flatten
(remove nil?)
seq)]
(reduce deep-merge-fixing-cljfmt configs)))))
(defn classpath-config-paths? [{:keys [classpath-config-paths]}]
(and (coll? classpath-config-paths)
(seq classpath-config-paths)))
(defn resolve-from-classpath-config-paths [classpath settings]
(shared/logging-time
"Finding classpath configs took %s"
(loop [{:keys [classpath-config-paths] :as cp-settings} (resolve-from-classpath-config-paths-impl classpath settings)
merge-config nil]
(if (and (coll? classpath-config-paths)
(seq classpath-config-paths))
(recur (resolve-from-classpath-config-paths-impl classpath cp-settings)
cp-settings)
(shared/deep-merge merge-config cp-settings)))))