diff --git a/cider-eval.el b/cider-eval.el index 2f0083e23..bb88106aa 100644 --- a/cider-eval.el +++ b/cider-eval.el @@ -561,54 +561,56 @@ It delegates the actual error content to the eval or op handler." (cider-default-err-eval-handler)) (t (cider-default-err-eval-print-handler)))) - -(defconst cider-clojure-1.10--location `((or "at (" - (sequence "at " - (minimal-match (one-or-more anything)) ;; the fully-qualified name of the function that triggered the error - " (")) - (group-n 2 (minimal-match (zero-or-more anything))) - ":" - (group-n 3 (one-or-more digit)) - (optional ":" (group-n 4 (one-or-more digit))) - ").")) - -(defconst cider-clojure-1.10-error (append `(sequence - "Syntax error " - (minimal-match (zero-or-more anything)) - (or "compiling " - "macroexpanding " - "reading source ") - (minimal-match (zero-or-more anything))) - cider-clojure-1.10--location)) - -(defconst cider-clojure-unexpected-error (append `(sequence - "Unexpected error (" - (minimal-match (one-or-more anything)) - ") " - (or "compiling " - "macroexpanding " - "reading source ") - (minimal-match (one-or-more anything))) - cider-clojure-1.10--location)) - -(defconst cider-clojure-warning `(sequence - (minimal-match (zero-or-more anything)) - (group-n 1 "warning") - ", " - (group-n 2 (minimal-match (zero-or-more anything))) - ":" - (group-n 3 (one-or-more digit)) - (optional ":" (group-n 4 (one-or-more digit))) - " - ")) +;; Reference: +;; https://github.com/clojure/clojure/blob/clojure-1.10.0/src/clj/clojure/main.clj#L251 +;; See `cider-compilation-regexp' for interpretation of match groups. +(defconst cider-clojure-1.10--location + '(sequence + "at " (minimal-match (zero-or-more anything)) ;; the fully-qualified name of the function that triggered the error + "(" + (group-n 2 (minimal-match (zero-or-more anything))) ; source file + ":" (group-n 3 (one-or-more (any "-" digit))) ; line number, may be negative (#3687) + (optional + ":" (group-n 4 (one-or-more (any "-" digit)))) ; column number + ").")) + +(defconst cider-clojure-1.10-error + `(sequence + "Syntax error " + (minimal-match (zero-or-more anything)) + (or "compiling " + "macroexpanding " + "reading source ") + (minimal-match (zero-or-more anything)) + ,cider-clojure-1.10--location)) + +(defconst cider-clojure-unexpected-error + `(sequence + "Unexpected error (" (minimal-match (one-or-more anything)) ") " + (or "compiling " + "macroexpanding " + "reading source ") + (minimal-match (one-or-more anything)) + ,cider-clojure-1.10--location)) + +(defconst cider-clojure-warning + `(sequence + (minimal-match (zero-or-more anything)) + (group-n 1 "warning") + ", " (group-n 2 (minimal-match (zero-or-more anything))) + ":" (group-n 3 (one-or-more (any "-" digit))) + (optional + ":" (group-n 4 (one-or-more (any "-" digit)))) + " - ")) ;; Please keep this in sync with `cider-clojure-compilation-error-regexp', ;; which is a subset of these regexes. (defconst cider-clojure-compilation-regexp - (eval - `(rx bol (or ,cider-clojure-warning - ,cider-clojure-1.10-error - ,cider-clojure-unexpected-error)) - t) + (rx-to-string + `(seq bol (or ,cider-clojure-warning + ,cider-clojure-1.10-error + ,cider-clojure-unexpected-error)) + 'nogroup) "A few example values that will match: \"Reflection warning, /tmp/foo/src/foo/core.clj:14:1 - \" \"CompilerException java.lang.RuntimeException: Unable to resolve symbol: \\ @@ -617,10 +619,10 @@ lol in this context, compiling:(/foo/core.clj:10:1)\" \"Unexpected error (ClassCastException) macroexpanding defmulti at (src/haystack/parser.cljc:21:1).\"") (defconst cider-clojure-compilation-error-regexp - (eval - `(rx bol (or ,cider-clojure-1.10-error - ,cider-clojure-unexpected-error)) - t) + (rx-to-string + `(seq bol (or ,cider-clojure-1.10-error + ,cider-clojure-unexpected-error)) + 'nogroup) "Like `cider-clojure-compilation-regexp', but excluding warnings such as reflection warnings. @@ -631,26 +633,23 @@ lol in this context, compiling:(/foo/core.clj:10:1)\" \"Unexpected error (ClassCastException) macroexpanding defmulti at (src/haystack/parser.cljc:21:1).\"") (defconst cider--clojure-execution-error-regexp - (append `(sequence - "Execution error " - (or (sequence "(" - (minimal-match (one-or-more anything)) - ")") - (minimal-match (zero-or-more anything)))) - cider-clojure-1.10--location)) + `(sequence + "Execution error " + (minimal-match (zero-or-more anything)) + ,cider-clojure-1.10--location)) (defconst cider--clojure-spec-execution-error-regexp - (append `(sequence - "Execution error - invalid arguments to " - (minimal-match (one-or-more anything)) - " ") - cider-clojure-1.10--location)) + `(sequence + "Execution error - invalid arguments to " + (minimal-match (one-or-more anything)) + " " + ,cider-clojure-1.10--location)) (defconst cider-clojure-runtime-error-regexp - (eval - `(rx bol (or ,cider--clojure-execution-error-regexp - ,cider--clojure-spec-execution-error-regexp)) - t) + (rx-to-string + `(seq bol (or ,cider--clojure-execution-error-regexp + ,cider--clojure-spec-execution-error-regexp)) + 'nogroup) "Matches runtime errors, as oppsed to compile-time/macroexpansion-time errors. A few example values that will match: @@ -674,7 +673,11 @@ A few example values that will match: ")")) (defvar cider-compilation-regexp - (list cider-clojure-compilation-regexp 2 3 4 '(1)) + (list cider-clojure-compilation-regexp + 2 ; FILE + 3 ; LINE + 4 ; COLUMN + '(1)) ; TYPE = (WARNING . INFO) "Specifications for matching errors and warnings in Clojure stacktraces. See `compilation-error-regexp-alist' for help on their format.") diff --git a/test/cider-error-parsing-tests.el b/test/cider-error-parsing-tests.el index 4a887ac47..8c01cd2c2 100644 --- a/test/cider-error-parsing-tests.el +++ b/test/cider-error-parsing-tests.el @@ -178,7 +178,16 @@ (expect (progn (string-match cider-clojure-runtime-error-regexp specimen) (match-string 2 specimen)) - :to-equal "src/haystack/parser.cljc")))) + :to-equal "src/haystack/parser.cljc"))) + + ;; Java source locations may be negative (#3687) + (it "Recognizes an error thrown from a java source file" + (let ((specimen "Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).")) + (expect specimen :to-match cider-clojure-runtime-error-regexp) + (expect (progn + (string-match cider-clojure-runtime-error-regexp specimen) + (match-string 2 specimen)) + :to-equal "FileInputStream.java")))) (describe "cider-module-info-regexp" (it "Matches module info provided by Java"