From f413b6d73fc04dda4addd5241d3268daa1c2c732 Mon Sep 17 00:00:00 2001 From: Stephen Nelson Date: Sun, 31 May 2015 02:05:29 +1200 Subject: [PATCH] Add support for reader conditional files (cljc) Clojure 1.7.0 will add support for reader conditionals: http://dev.clojure.org/display/design/Reader+Conditionals This patch adds reader conditional support to leiningen, in particular for compilation (including aot and stale files) and testing. --- leiningen-core/project.clj | 2 +- leiningen-core/src/leiningen/core/utils.clj | 2 +- project.clj | 4 ++-- src/leiningen/compile.clj | 22 ++++++++++++------- src/leiningen/jar.clj | 3 ++- src/leiningen/test.clj | 2 +- test/leiningen/test/compile.clj | 8 +++++++ test/leiningen/test/helper.clj | 2 ++ test/leiningen/test/test.clj | 5 +++++ test_projects/sample-reader-cond/project.clj | 10 +++++++++ .../sample-reader-cond/src/nom/nom/clj.clj | 1 + .../sample-reader-cond/src/nom/nom/cljc.cljc | 1 + .../sample-reader-cond/test/clj_test.clj | 7 ++++++ .../sample-reader-cond/test/cljc_test.cljc | 8 +++++++ .../sample-reader-cond/test/selectors.clj | 10 +++++++++ 15 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 test_projects/sample-reader-cond/project.clj create mode 100644 test_projects/sample-reader-cond/src/nom/nom/clj.clj create mode 100644 test_projects/sample-reader-cond/src/nom/nom/cljc.cljc create mode 100644 test_projects/sample-reader-cond/test/clj_test.clj create mode 100644 test_projects/sample-reader-cond/test/cljc_test.cljc create mode 100644 test_projects/sample-reader-cond/test/selectors.clj diff --git a/leiningen-core/project.clj b/leiningen-core/project.clj index 2802d3cc2..7e6f6bc28 100644 --- a/leiningen-core/project.clj +++ b/leiningen-core/project.clj @@ -4,7 +4,7 @@ :url "http://www.eclipse.org/legal/epl-v10.html"} :description "Library for core functionality of Leiningen." :dependencies [[org.clojure/clojure "1.7.0"] - [bultitude "0.2.6"] + [bultitude "0.2.8"] [classlojure "0.6.6"] [robert/hooke "1.3.0"] [com.cemerick/pomegranate "0.3.0"] diff --git a/leiningen-core/src/leiningen/core/utils.clj b/leiningen-core/src/leiningen/core/utils.clj index 5c7b25dda..76de0b2e9 100644 --- a/leiningen-core/src/leiningen/core/utils.clj +++ b/leiningen-core/src/leiningen/core/utils.clj @@ -64,7 +64,7 @@ (subs 1) (str suffix) io/resource)) - [".clj" (str clojure.lang.RT/LOADER_SUFFIX ".class")])) + [".clj" ".cljc" (str clojure.lang.RT/LOADER_SUFFIX ".class")])) (defn error [& args] (binding [*out* *err*] ;; TODO: use main/warn for this in 3.0 diff --git a/project.clj b/project.clj index 4a6b5de05..3a73fbbef 100644 --- a/project.clj +++ b/project.clj @@ -6,10 +6,10 @@ :url "https://github.com/technomancy/leiningen" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[leiningen-core "2.5.1"] + :dependencies [[leiningen-core "2.5.2-SNAPSHOT"] [org.clojure/data.xml "0.0.3"] [commons-io "2.4"] - [bultitude "0.2.6"] + [bultitude "0.2.8"] [stencil "0.3.5" :exclusions [org.clojure/core.cache]] [org.apache.maven.indexer/indexer-core "4.1.3" :exclusions [org.apache.maven/maven-model diff --git a/src/leiningen/compile.clj b/src/leiningen/compile.clj index bad1c1d8d..ab6e29907 100644 --- a/src/leiningen/compile.clj +++ b/src/leiningen/compile.clj @@ -5,7 +5,7 @@ [bultitude.core :as b] [clojure.java.io :as io]) (:refer-clojure :exclude [compile]) - (:import (java.io PushbackReader))) + (:import (java.io PushbackReader File))) (defn- regex? [str-or-re] (instance? java.util.regex.Pattern str-or-re)) @@ -34,13 +34,17 @@ out-of-date class files." [project] (for [namespace (compilable-namespaces project) - :let [rel-source (b/path-for namespace) - source (first (sort-by (fn [f] (not (.exists f))) - (for [source-path (:source-paths project) - :let [file (io/file source-path rel-source)]] - file)))] + :let [[rel-source source] + (or (first (for [source-path (:source-paths project) + rel-source (map (partial b/path-for namespace) ["clj" "cljc"]) + :let [file (io/file source-path rel-source)] + :when (.exists ^File file)] + [rel-source file])) + (let [rel-source (b/path-for namespace)] + ;; always return a source file location (#1205) + [rel-source (io/file (first (:source-paths project)) rel-source)]))] :when source - :let [rel-compiled (.replaceFirst rel-source "\\.clj$" "__init.class") + :let [rel-compiled (.replaceFirst rel-source "\\.cljc?$" "__init.class") compiled (io/file (:compile-path project) rel-compiled)] :when (>= (.lastModified source) (.lastModified compiled))] namespace)) @@ -68,7 +72,9 @@ (defn- source-in-project? "Tests if a file found in the compile path exists in the source path." [parent compile-path source-path] - (.exists (io/file (str (.replace parent compile-path source-path) ".clj")))) + (let [path (.replace parent compile-path source-path)] + (or (.exists (io/file (str path ".clj"))) + (.exists (io/file (str path ".cljc")))))) (defn- class-in-project? [project f] (or (has-source-package? project f (:source-paths project)) diff --git a/src/leiningen/jar.clj b/src/leiningen/jar.clj index aad5be473..48a1a6618 100644 --- a/src/leiningen/jar.clj +++ b/src/leiningen/jar.clj @@ -231,7 +231,8 @@ (defn- compile-main? [{:keys [main source-paths] :as project}] (and main (not (:skip-aot (meta main))) - (some #(.exists (io/file % (b/path-for main))) source-paths))) + (some #(or (.exists (io/file % (b/path-for main "clj"))) + (.exists (io/file % (b/path-for main "cljc")))) source-paths))) (def ^:private implicit-aot-warning (delay diff --git a/src/leiningen/test.clj b/src/leiningen/test.clj index f03d7dd6d..413ba7469 100644 --- a/src/leiningen/test.clj +++ b/src/leiningen/test.clj @@ -134,7 +134,7 @@ vars))]) (defn- convert-to-ns [possible-file] - (if (and (.endsWith possible-file ".clj") (.exists (io/file possible-file))) + (if (and (re-matches #".*\.cljc?" possible-file) (.exists (io/file possible-file))) (str (second (b/ns-form-for-file possible-file))) possible-file)) diff --git a/test/leiningen/test/compile.clj b/test/leiningen/test/compile.clj index cb957505f..b11d3f80a 100644 --- a/test/leiningen/test/compile.clj +++ b/test/leiningen/test/compile.clj @@ -6,6 +6,7 @@ [leiningen.compile] [leiningen.test.helper :only [sample-project delete-file-recursively sample-failing-project + sample-reader-cond-project tricky-name-project more-gen-classes-project with-system-err-str]]) @@ -39,6 +40,13 @@ (is (not (.exists (file "test_projects" "more-gen-classes" "target" "classes" "more_gen_classes" "foo.class"))))) +(deftest test-compile-cljc + (compile sample-reader-cond-project) + (is (.exists (file "test_projects" "sample-reader-cond" "target" + "classes" "nom" "nom" "clj__init.class"))) + (is (.exists (file "test_projects" "sample-reader-cond" "target" + "classes" "nom" "nom" "cljc__init.class")))) + (def eip-check (atom false)) (deftest ^:online test-plugin diff --git a/test/leiningen/test/helper.clj b/test/leiningen/test/helper.clj index b1441df8d..61c2f01c3 100644 --- a/test/leiningen/test/helper.clj +++ b/test/leiningen/test/helper.clj @@ -36,6 +36,8 @@ (def sample-profile-meta-project (read-test-project "sample-profile-meta")) +(def sample-reader-cond-project (read-test-project "sample-reader-cond")) + (def tricky-name-project (read-test-project "tricky-name")) (def native-project (read-test-project "native")) diff --git a/test/leiningen/test/test.clj b/test/leiningen/test/test.clj index 8afda132b..ebe5d65f2 100644 --- a/test/leiningen/test/test.clj +++ b/test/leiningen/test/test.clj @@ -3,6 +3,7 @@ (:require [clojure.test :refer :all] [leiningen.test :refer :all] [leiningen.test.helper :refer [tmp-dir sample-no-aot-project + sample-reader-cond-project sample-failing-project with-system-err-str]] [clojure.java.io :as io] @@ -68,6 +69,10 @@ (test sample-no-aot-project "selectors") (is (= (ran?) #{:regular :not-custom :int2 :fixture}))) +(deftest test-reader-conditional-tests + (test sample-reader-cond-project) + (is (= (ran?) #{:clj-test :cljc-test}))) + (deftest test-invalid-namespace-argument (is (.contains (with-system-err-str diff --git a/test_projects/sample-reader-cond/project.clj b/test_projects/sample-reader-cond/project.clj new file mode 100644 index 000000000..e67c4a21e --- /dev/null +++ b/test_projects/sample-reader-cond/project.clj @@ -0,0 +1,10 @@ +;; This project is used for leiningen's test suite, so don't change +;; any of these values without updating the relevant tests. If you +;; just want a basic project to work from, generate a new one with +;; "lein new". + +(defproject nomnomnom "0.5.0-SNAPSHOT" + :dependencies [[org.clojure/clojure "1.7.0"] + [janino "2.5.15"]] + :aot :all + :uberjar-exclusions [#"DUMMY"]) diff --git a/test_projects/sample-reader-cond/src/nom/nom/clj.clj b/test_projects/sample-reader-cond/src/nom/nom/clj.clj new file mode 100644 index 000000000..5abf5242f --- /dev/null +++ b/test_projects/sample-reader-cond/src/nom/nom/clj.clj @@ -0,0 +1 @@ +(ns nom.nom.clj) diff --git a/test_projects/sample-reader-cond/src/nom/nom/cljc.cljc b/test_projects/sample-reader-cond/src/nom/nom/cljc.cljc new file mode 100644 index 000000000..23191facd --- /dev/null +++ b/test_projects/sample-reader-cond/src/nom/nom/cljc.cljc @@ -0,0 +1 @@ +(ns nom.nom.cljc) diff --git a/test_projects/sample-reader-cond/test/clj_test.clj b/test_projects/sample-reader-cond/test/clj_test.clj new file mode 100644 index 000000000..0d6a1eed5 --- /dev/null +++ b/test_projects/sample-reader-cond/test/clj_test.clj @@ -0,0 +1,7 @@ +(ns clj-test + (:use [clojure.test] + [selectors :only [record-ran]])) + +(deftest clojure-test + (record-ran :clj-test) + (is true)) diff --git a/test_projects/sample-reader-cond/test/cljc_test.cljc b/test_projects/sample-reader-cond/test/cljc_test.cljc new file mode 100644 index 000000000..8fc7fccac --- /dev/null +++ b/test_projects/sample-reader-cond/test/cljc_test.cljc @@ -0,0 +1,8 @@ +(ns cljc-test + (:use #?(:clj [clojure.test] + :cljs [cljs.test]) + [selectors :only [record-ran]])) + +(deftest conditional-test + (record-ran :cljc-test) + (is true)) diff --git a/test_projects/sample-reader-cond/test/selectors.clj b/test_projects/sample-reader-cond/test/selectors.clj new file mode 100644 index 000000000..c0518eb5c --- /dev/null +++ b/test_projects/sample-reader-cond/test/selectors.clj @@ -0,0 +1,10 @@ +(ns selectors + (:use [clojure.test] + [clojure.java.io])) + +(defn record-ran [t] + (let [file-name (format "%s/lein-test-ran" + (System/getProperty "java.io.tmpdir"))] + (with-open [w (writer file-name :append true)] + (.write w (str t "\n"))))) +