Skip to content

Commit

Permalink
GitHub Issue #137 - only process the first ns form (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
oakmac authored Oct 22, 2024
1 parent ce67c60 commit 0335fec
Show file tree
Hide file tree
Showing 2 changed files with 235 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/standard-clojure-style.js
Original file line number Diff line number Diff line change
Expand Up @@ -3345,7 +3345,7 @@
nodesArr = recordOriginalColIndexes(nodesArr, idx)
}

if (parenNestingDepth === 1 && isNsNode(node)) {
if (nsStartStringIdx === -1 && parenNestingDepth === 1 && isNsNode(node)) {
insideNsForm = true
nsStartStringIdx = strLen(strConcat(outTxt, lineTxt))
}
Expand Down
234 changes: 234 additions & 0 deletions test_format/format.eno
Original file line number Diff line number Diff line change
Expand Up @@ -1718,3 +1718,237 @@ hee, haz,
gee, gaz
hee, haz
--Expected

# GitHub Issue #137 - defmacro ns

> https://github.com/oakmac/standard-clojure-style-js/issues/137

--Input
; 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.

(ns ^{:doc "The core Clojure language."
:author "Rich Hickey"}
clojure.core)

(def unquote)
(def unquote-splicing)

(def
^{:arglists '([& items])
:doc "Creates a new list containing the items."
:added "1.0"}
list (. clojure.lang.PersistentList creator))

(def
^{:arglists '([x seq])
:doc "Returns a new seq where x is the first element and seq is
the rest."
:added "1.0"
:static true}

cons (fn* ^:static cons [x seq] (. clojure.lang.RT (cons x seq))))

;during bootstrap we don't have destructuring let, loop or fn, will redefine later
(def
^{:macro true
:added "1.0"}
let (fn* let [&form &env & decl] (cons 'let* decl)))

;; ...

(declare gen-class)

(defmacro with-loading-context [& body]
`((fn loading# []
(. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER
(.getClassLoader (.getClass ^Object loading#))}))
(try
~@body
(finally
(. clojure.lang.Var (popThreadBindings)))))))

(defmacro ns
"Sets *ns* to the namespace named by name (unevaluated), creating it
if needed. references can be zero or more of: (:refer-clojure ...)
(:require ...) (:use ...) (:import ...) (:load ...) (:gen-class)
with the syntax of refer-clojure/require/use/import/load/gen-class
respectively, except the arguments are unevaluated and need not be
quoted. (:gen-class ...), when supplied, defaults to :name
corresponding to the ns name, :main true, :impl-ns same as ns, and
:init-impl-ns true. All options of gen-class are
supported. The :gen-class directive is ignored when not
compiling. If :gen-class is not supplied, when compiled only an
nsname__init.class will be generated. If :refer-clojure is not used, a
default (refer 'clojure.core) is used. Use of ns is preferred to
individual calls to in-ns/require/use/import:

(ns foo.bar
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql combinatorics))
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement)))"
{:arglists '([name docstring? attr-map? references*])
:added "1.0"}
[name & references]
(let [process-reference
(fn [[kname & args]]
`(~(symbol "clojure.core" (clojure.core/name kname))
~@(map #(list 'quote %) args)))
docstring (when (string? (first references)) (first references))
references (if docstring (next references) references)
name (if docstring
(vary-meta name assoc :doc docstring)
name)
metadata (when (map? (first references)) (first references))
references (if metadata (next references) references)
name (if metadata
(vary-meta name merge metadata)
name)
gen-class-clause (first (filter #(= :gen-class (first %)) references))
gen-class-call
(when gen-class-clause
(list* `gen-class :name (.replace (str name) \- \_) :impl-ns name :main true (next gen-class-clause)))
references (remove #(= :gen-class (first %)) references)
;ns-effect (clojure.core/in-ns name)
name-metadata (meta name)]
`(do
(clojure.core/in-ns '~name)
~@(when name-metadata
`((.resetMeta (clojure.lang.Namespace/find '~name) ~name-metadata)))
(with-loading-context
~@(when gen-class-call (list gen-class-call))
~@(when (and (not= name 'clojure.core) (not-any? #(= :refer-clojure (first %)) references))
`((clojure.core/refer '~'clojure.core)))
~@(map process-reference references))
(if (.equals '~name 'clojure.core)
nil
(do (dosync (commute @#'*loaded-libs* conj '~name)) nil)))))

(defmacro refer-clojure
"Same as (refer 'clojure.core <filters>)"
{:added "1.0"}
[& filters]
`(clojure.core/refer '~'clojure.core ~@filters))
--Input

--Expected
; 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.

(ns clojure.core
{:doc "The core Clojure language."
:author "Rich Hickey"})

(def unquote)
(def unquote-splicing)

(def
^{:arglists '([& items])
:doc "Creates a new list containing the items."
:added "1.0"}
list (. clojure.lang.PersistentList creator))

(def
^{:arglists '([x seq])
:doc "Returns a new seq where x is the first element and seq is
the rest."
:added "1.0"
:static true}

cons (fn* ^:static cons [x seq] (. clojure.lang.RT (cons x seq))))

; during bootstrap we don't have destructuring let, loop or fn, will redefine later
(def
^{:macro true
:added "1.0"}
let (fn* let [&form &env & decl] (cons 'let* decl)))

;; ...

(declare gen-class)

(defmacro with-loading-context [& body]
`((fn loading# []
(. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER
(.getClassLoader (.getClass ^Object loading#))}))
(try
~@body
(finally
(. clojure.lang.Var (popThreadBindings)))))))

(defmacro ns
"Sets *ns* to the namespace named by name (unevaluated), creating it
if needed. references can be zero or more of: (:refer-clojure ...)
(:require ...) (:use ...) (:import ...) (:load ...) (:gen-class)
with the syntax of refer-clojure/require/use/import/load/gen-class
respectively, except the arguments are unevaluated and need not be
quoted. (:gen-class ...), when supplied, defaults to :name
corresponding to the ns name, :main true, :impl-ns same as ns, and
:init-impl-ns true. All options of gen-class are
supported. The :gen-class directive is ignored when not
compiling. If :gen-class is not supplied, when compiled only an
nsname__init.class will be generated. If :refer-clojure is not used, a
default (refer 'clojure.core) is used. Use of ns is preferred to
individual calls to in-ns/require/use/import:

(ns foo.bar
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql combinatorics))
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement)))"
{:arglists '([name docstring? attr-map? references*])
:added "1.0"}
[name & references]
(let [process-reference
(fn [[kname & args]]
`(~(symbol "clojure.core" (clojure.core/name kname))
~@(map #(list 'quote %) args)))
docstring (when (string? (first references)) (first references))
references (if docstring (next references) references)
name (if docstring
(vary-meta name assoc :doc docstring)
name)
metadata (when (map? (first references)) (first references))
references (if metadata (next references) references)
name (if metadata
(vary-meta name merge metadata)
name)
gen-class-clause (first (filter #(= :gen-class (first %)) references))
gen-class-call
(when gen-class-clause
(list* `gen-class :name (.replace (str name) \- \_) :impl-ns name :main true (next gen-class-clause)))
references (remove #(= :gen-class (first %)) references)
; ns-effect (clojure.core/in-ns name)
name-metadata (meta name)]
`(do
(clojure.core/in-ns '~name)
~@(when name-metadata
`((.resetMeta (clojure.lang.Namespace/find '~name) ~name-metadata)))
(with-loading-context
~@(when gen-class-call (list gen-class-call))
~@(when (and (not= name 'clojure.core) (not-any? #(= :refer-clojure (first %)) references))
`((clojure.core/refer '~'clojure.core)))
~@(map process-reference references))
(if (.equals '~name 'clojure.core)
nil
(do (dosync (commute @#'*loaded-libs* conj '~name)) nil)))))

(defmacro refer-clojure
"Same as (refer 'clojure.core <filters>)"
{:added "1.0"}
[& filters]
`(clojure.core/refer '~'clojure.core ~@filters))
--Expected

0 comments on commit 0335fec

Please sign in to comment.