-
-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The `immutable-source-file?` check is used in `class-info` to know if it makes sense to invalidate a cache entry based on modification time. This check uses the `:file` it is given to see if the resource is inside a jar or not. This `:path` comes from `orchard.java.{parser,legacy-parser}`, and is the relative path on the classpath. This is then looked up via `io/resource`, so that the URL can be checked to see if it's a jar or not. This resource check is expensive, depending on circumstances cider-nrepl's "stacktrace" analysis can get extremely slow, around 10~20 seconds to analyze all stack frames and return a result, which means that the error buffer will only pop up 10~20 seconds after evaluating a form which causes an error. The check is performed whether we have a cached result or not. However java.parser already calls `io/resource` to resolve the full resource URL, so we should be able to use the information we already have. However, the way java.parser was doing this caused inconsistencies between filesystem resources vs archived resources. It does a `(.getPath (io/resource path))`, and stores that under `:file`. This works for regular files, because `.getPath` on a `file:` URL returns the path of the file. For `jar:` URLs it returns the nested url+the jar entry, so a `:file` URL but with a dangling `!/jar/entry`. In other words the `:file` entry is either an actual file path, or something that looks like a `file:` URL but isn't. This patch - Makes the result from java.parser consistent: `:path` is a relative classpath resource path, `:file` is a file on the filesystem path. Either it points at the resource, or at the archive containing the resource. - Add an `archive?` flag to the result of `source-info`, so we don't have to figure out again later if it's an archived resource or not - Changes the check in `class-info` to be a cheap lookup of two map keys. If it's an archive or if we don't have a filesystem path, then don't bother checking the lastModified time. Illustration of why calling `getPath` on `jar:` URLs is not useful: ```clojure (io/resource "lambdaisland/witchcraft.clj") ;;=> #java.net.URL "file:/srv/mc/witchcraft/src/lambdaisland/witchcraft.clj" (.getPath (io/resource "lambdaisland/witchcraft.clj")) ;;=> "/srv/mc/witchcraft/src/lambdaisland/witchcraft.clj" (io/resource "clojure/lang/RT.class") ;;=> #java.net.URL "jar:file:/root/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar!/clojure/lang/RT.class" (.getPath (io/resource "clojure/lang/RT.class")) ;;=> "file:/root/.m2/repository/org/clojure/clojure/1.10.3/clojure-1.10.3.jar!/clojure/lang/RT.class" ``` This has chopped of the `jar:` prefix, but not the `!/jar/file/entry` suffix. The result is a `file:` URL that can't be resolved.
- Loading branch information
Showing
7 changed files
with
153 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package orchard.java; | ||
|
||
/** | ||
* Class level docstring. | ||
* | ||
* <pre> | ||
* DummyClass dc = new DummyClass(); | ||
* </pre> | ||
* | ||
* @author Arne Brasseur | ||
*/ | ||
public class DummyClass { | ||
/** | ||
* Method-level docstring. | ||
* | ||
* @returns the string "hello" | ||
*/ | ||
public String dummyMethod() { | ||
return "hello"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
(ns orchard.java.parser-test | ||
(:require [orchard.misc :as misc] | ||
[clojure.test :refer :all])) | ||
|
||
(when (>= orchard.misc/java-api-version 9) | ||
(require '[orchard.java.parser :as parser]) | ||
|
||
(defn compile-class-from-source | ||
"Compile a java file on the classpath. | ||
Returns true if all went well." | ||
[classname] | ||
(let [compiler (javax.tools.ToolProvider/getSystemJavaCompiler)] | ||
(.. compiler | ||
(getTask | ||
nil ;; out | ||
nil ;; fileManager | ||
nil ;; diagnosticListener | ||
nil ;; compilerOptions | ||
nil ;; classnames for annotation processing | ||
;; compilationUnits | ||
[(.. compiler | ||
(getStandardFileManager nil nil nil) | ||
(getJavaFileForInput javax.tools.StandardLocation/CLASS_PATH | ||
classname | ||
javax.tools.JavaFileObject$Kind/SOURCE))]) | ||
call))) | ||
|
||
(deftest source-info-test | ||
(is (compile-class-from-source "orchard.java.DummyClass")) | ||
|
||
(testing "file on the filesystem" | ||
(is (= {:class 'orchard.java.DummyClass, | ||
:members | ||
'{orchard.java.DummyClass | ||
{[] | ||
{:name orchard.java.DummyClass, | ||
:type void, | ||
:argtypes [], | ||
:argnames [], | ||
:doc nil, | ||
:line 12, | ||
:column 8}}, | ||
dummyMethod | ||
{[] | ||
{:name dummyMethod, | ||
:type java.lang.String, | ||
:argtypes [], | ||
:argnames [], | ||
:doc "Method-level docstring. @returns the string \"hello\"", | ||
:line 18, | ||
:column 3}}}, | ||
:doc | ||
"Class level docstring.\n\n```\n DummyClass dc = new DummyClass();\n```\n\n@author Arne Brasseur", | ||
:line 12, | ||
:column 1, | ||
:file "orchard/java/DummyClass.java", | ||
:path (str (System/getProperty "user.dir") | ||
"/test/orchard/java/DummyClass.java") | ||
:archive? false} | ||
((resolve 'orchard.java.parser/source-info) 'orchard.java.DummyClass)))) | ||
|
||
(testing "java file in a jar" | ||
(let [rt-info ((resolve 'orchard.java.parser/source-info) 'clojure.lang.RT)] | ||
(is (= {:file "clojure/lang/RT.java" :archive? true} | ||
(select-keys rt-info [:file :archive?]))) | ||
(is (re-find #"/.*/.m2/repository/org/clojure/clojure/.*/clojure-.*-sources.jar" | ||
(:path rt-info))))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters