From d955dc9a571077a493b89f7e49b8847922f414f5 Mon Sep 17 00:00:00 2001 From: Stuart Halloway Date: Sun, 16 Oct 2011 07:01:36 -0400 Subject: [PATCH] CLJ-733 data conveying exception --- src/clj/clojure/core.clj | 16 ++++++++++++ src/clj/clojure/main.clj | 1 + src/clj/clojure/repl.clj | 4 ++- src/jvm/clojure/lang/ExceptionInfo.java | 40 +++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletions(-) create mode 100644 src/jvm/clojure/lang/ExceptionInfo.java diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index b1801e9..ec80412 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -4220,6 +4220,22 @@ (with-out-str (apply println xs))) +(import clojure.lang.ExceptionInfo) +(defn ex-info + "Create an instance of ExceptionInfo, a RuntimeException subclass + that carries a map of additional data." + {:added "1.4"} + ([msg map] (ExceptionInfo. msg map)) + ([msg map cause] (ExceptionInfo. msg map cause))) + +(defn ex-data + "Returns exception data (a map) if ex is an ExceptionInfo. + Otherwise returns nil." + {:added "1.4"} + [ex] + (when (instance? ExceptionInfo ex) + (.getData ^ExceptionInfo ex))) + (defmacro assert "Evaluates expr and throws an exception if it does not evaluate to logical true." diff --git a/src/clj/clojure/main.clj b/src/clj/clojure/main.clj index 8efff8d..182a953 100644 --- a/src/clj/clojure/main.clj +++ b/src/clj/clojure/main.clj @@ -173,6 +173,7 @@ (binding [*out* *err*] (println (str (-> ex class .getSimpleName) " " (.getMessage ex) " " + (when-let [info (ex-data ex)] (str info " ")) (when-not (instance? clojure.lang.Compiler$CompilerException ex) (str " " (if el (stack-element-str el) "[trace missing]")))))))) diff --git a/src/clj/clojure/repl.clj b/src/clj/clojure/repl.clj index 3218180..af55a2f 100644 --- a/src/clj/clojure/repl.clj +++ b/src/clj/clojure/repl.clj @@ -251,7 +251,9 @@ str-or-pattern." (pst (root-cause e) e-or-depth)))) ([^Throwable e depth] (binding [*out* *err*] - (println (str (-> e class .getSimpleName) " " (.getMessage e))) + (println (str (-> e class .getSimpleName) " " + (.getMessage e) + (when-let [info (ex-data e)] (str " " info)))) (let [st (.getStackTrace e) cause (.getCause e)] (doseq [el (take depth diff --git a/src/jvm/clojure/lang/ExceptionInfo.java b/src/jvm/clojure/lang/ExceptionInfo.java new file mode 100644 index 0000000..1f6acc2 --- /dev/null +++ b/src/jvm/clojure/lang/ExceptionInfo.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + */ + +package clojure.lang; + +import java.util.Map; + +/** + * Exception that carries data (a map) as additional payload. Clojure programs that need + * richer semantics for exceptions should use this in lieu of defining project-specific + * exception classes. + */ +public class ExceptionInfo extends RuntimeException{ + public final IPersistentMap data; + + public ExceptionInfo(String s, IPersistentMap data) { + super(s); + this.data = data; + } + + public ExceptionInfo(String s, IPersistentMap data, Throwable throwable) { + super(s, throwable); + this.data = data; + } + + public IPersistentMap getData() { + return data; + } + + public String toString() { + return "clojure.lang.ExceptionInfo: " + getMessage() + " " + data.toString(); + } +} -- 1.7.3.3