Commits on Mar 28, 2014
  1. @guns

    Rename example namespace to match file name

    This was causing problems for vim-fireplace. It is otherwise a harmless
    guns committed Mar 28, 2014
Commits on Mar 27, 2014
  1. @DavidGregory084 @guns

    Ensure the file separator is correct

    The regex used to filter for Clojure source files assumes a file
    separator of "/". Replace the system file separator with this.
    DavidGregory084 committed with guns Mar 27, 2014
Commits on Mar 25, 2014
  1. @guns

    Add link to slamhound-lt, a Light Table plugin

    If the list of plugins gets to be very long, or nrepl/op gains traction,
    we can move this section of the README to a github wiki.
    guns committed Mar 24, 2014
Commits on Mar 23, 2014
  1. @guns

    Style refactoring in asplode

    Notice the new compact :refer vector due to the changes to the prettify
    guns committed Mar 23, 2014
  2. @guns

    Keywordize ns reference keys

    A common confusion regarding the ns macro is the use of symbols vs
    keywords for `:require`, `:import`, etc.
    The fact that both work just fine in the ns form does not help at all.
    Since one goal of Slamhound is to promote a single conventional style
    for ns forms, it is a good idea to be graceful on this issue.
    Closes #73
    guns committed Mar 23, 2014
  3. @guns

    Release 1.5.3

    guns committed Mar 23, 2014
  4. @guns

    Merge branch 'rename-support'

    Closes #68
    * rename-support:
      Add :rename failure type to regrow
      Add asplode support for :rename option in :require libspecs
    guns committed Mar 23, 2014
  5. @guns

    Add :rename failure type to regrow

    If an old ns contains a :rename entry for a missing refer, we attempt
    this rename before any others.
    If the old ns does not contain a possible :rename entry, the :rename
    path is __NEVER__ attempted since a missing reference could be
    hypothesized to be a rename of ANY public var.
    slam.hound.regrow/candidate has been made private as the function
    signature has changed, decreasing its suitability for public
    guns committed Mar 22, 2014
  6. @guns

    Add asplode support for :rename option in :require libspecs

    Since both `require` and `use` both call `load-lib` internally, both
    functions can also be supplied a :rename option.
    guns committed Mar 22, 2014
  7. @guns

    Allow certain libspecs to have keys on multiple lines

    The following require form fits nicely on one line:
        (:require [my.ns :as ns :refer [alpha beta gamma]])
    If the vector of refers is long, it overflows to the next line but the
    :refer key stays on the first line:
        (:require [my.ns :as ns :refer [alpha beta gamma delta epsilon
                                        zeta eta theta]])
    This may not work nicely when there are two libspecs options that are
        (:require [my.ns :as ns :refer [alpha beta gamma delta epsilon
                                        zeta eta theta] :rename {alpha α,
                                                                 beta β,
                                                                 gamma γ}])
    In this case, allow each option pair to start on a new line:
        (:require [my.ns :as ns
                   :refer [alpha beta gamma delta epsilon zeta eta theta]
                   :rename {alpha α, beta β, gamma γ}])
    guns committed Mar 22, 2014
Commits on Mar 22, 2014
  1. @guns

    Don't insert :refer vector for mass referred namespaces

    e.g. (:require [my.ns :refer [foo] :refer :all]) is not valid.
    guns committed Mar 22, 2014
  2. @guns
  3. @guns

    Add support for core.typed

    The core.typed `ann` macro generates its own failure messages.
    Addresses #69 and #70
    guns committed Mar 21, 2014
  4. @guns

    Add namespaces beginning with "cljs." to the blacklist

    Many contrib libraries ship with Clojure ( and ClojureScript
    ( namespaces. Because the CLJS namespaces contain many
    of the same vars as their Clojure counterparts, these namespaces
    frequently appear in candidate lists. Furthermore, they often win the
    disambiguation process since "cljs" is shorter than "clojure".
    Slamhound does not currently support ClojureScript, so blacklisting
    these namespaces for the time being is quite convenient.
    guns committed Mar 21, 2014
Commits on Mar 21, 2014
  1. @guns

    Minor refactoring

    guns committed Mar 21, 2014
  2. @guns

    Identify aliases that conflict namespaces

    Slamhound erroneously returns the var portion of an ns-qualified
    namespace for a missing alias when the alias happens to correspond with
    an existing namespace.
    Closes #67
    guns committed Mar 21, 2014
Commits on Mar 20, 2014
  1. @guns
Commits on Mar 18, 2014
  1. Bump slamhound.el version.

    committed Mar 18, 2014
  2. @guns

    Extend print-liblist to handle libspecs with multiple options

    This is what used to happen to some libspecs with both :alias and :refer
        (ns foo
          (:require [clojure.pprint :as pp :refer
    This now prints as:
        (ns foo
          (:require [clojure.pprint :as pp :refer [*print-miser-width*
                                                   cl-format code-dispatch
                                                   formatter-out pprint
    Note that libspecs with very long namespace names, aliases, or 3+
    options are unlikely to respect *print-right-margin* with the current
    implementation. In practice this does not seem like a problem.
    guns committed Mar 18, 2014
  3. @guns

    Disable :miser mode during ns prettify

    *print-miser-width* -> 40
        (:require [my.very.sequipedalian.namespace :refer [alpha
                                                           delta epsilon]])
    *print-miser-width* -> nil
        (:require [my.very.sequipedalian.namespace :refer [alpha beta gamma
                                                           delta epsilon]])
    guns committed Mar 18, 2014
Commits on Mar 17, 2014
  1. @guns

    Extract inner (pprint-logical-block) to its own function

    This primarily serves to make the incredibly daunting cl-format routine
    a little more approachable.
    This change also provides a link to the Common Lisp format string spec
    in the ns doc for quick reference.
    guns committed Mar 16, 2014
Commits on Mar 14, 2014
  1. @guns

    Release 1.5.2

    guns committed Mar 14, 2014
  2. @guns

    Handle case where an alias is used to refer to private vars

        (ns alpha)
        (def ^:private foo)
        (def bar)
        (ns beta)
        (def foo #'a/foo)
        (def bar a/bar)
    The beta namespace uses the `a` alias to refer to both alpha/bar and the
    private var alpha/foo.
    Slamhound previously failed to find `alpha` -> `a` in this case since it
    attempts to find a ns that contains #{foo bar} in its set of _public_
    The solution implemented here is to try the alias search twice, once
    with all symbols, and again without (var symbol) forms.
    This does mean that Slamhound will be unable to find aliases that are
    used to refer to both public and private vars via #':
        (def foo #'b/private-var)
        (def foo #'a/public-var)    ; Just use a/public-var
    guns committed Mar 14, 2014
  3. @guns

    Merge branch 'regrow-cache'

    After a month of use, I have not noticed any problems with these
    * regrow-cache:
      Execute reconstruct and -main with-regrow-cache
      Memoize expensive ns data transformations in a dynamic var
    guns committed Mar 14, 2014
Commits on Feb 20, 2014
  1. Fix LICENSE to actual EPL.

    committed Feb 20, 2014
Commits on Feb 6, 2014
  1. @guns

    Execute reconstruct and -main with-regrow-cache

    The two main entry points for Slamhound are slam.hound/reconstruct and
    slam.hound/-main. Binding slam.hound.regrow/*cache* in both places
    allows speed up of both single-file reconstruction (via an editor),
    as well as an even greater speed-up of recursive reconstruction of a
    One issue that may arise is that all data about namespaces is cached
    on first calculation, so any namespaces or classes created as a result
    of a newly evaluated namespace will not be visible in subsequent
    reconstructions while reconstructing all clojure files in a directory.
    It's unclear how utilizing this assumption about the behavior of
    recursive reconstruction could be regarded as anything but a bug, so I
    am unconcerned.
    guns committed Feb 6, 2014
  2. @guns

    Memoize expensive ns data transformations in a dynamic var

    Namespaces often contain more than one import/alias/refer. In these
    cases the repeated data transformations of (all-ns) in a single ns
    reconstruction is wasteful. Properly memoizing these calculations
    results in a considerable performance gain for namespaces with many
    A dynamic var is a suitable place for a cache:
        - The current compiler-failure algorithm forces us to work
          sequentially, so a thread binding is not a problem
        - Reconstruction _should_ work with and without a cache for testing
    A parallel reconstruction algorithm will require explicit
    parameterization of the cache, but we can cross that bridge when we get
    The *cache* var is not bound in slam.hound.regrow; that is up to the
    discretion of consuming code (tests and the main entry points in
    slam.hound). The with-regrow-cache macro can be nested, in which case
    the topmost cache is used.
    The performance benefit of this change depends on the namespace:
        - Namespaces with a single import/alias/refer are unaffected¹
        - Small namespaces with multiple references of each type experience
          relatively large gains (40% - 50% reduction of reconstruction time)
        - Large namespaces with multiple references experience the same
          absolute speedup as above, but since the time required for
          evaluation of the namespace now dominates, the relative reduction
          in reconstruction time is less dramatic (10% - 30%)
    It is unclear whether the size and use of this cache has negative
    effects on GC, so this branch is considered experimental. Intuitively,
    the reduction of object creation should help reduce GC hiccups, but
    tests should be done in larger projects.
    The overall effect of this change is that ns evaluation in
    check-for-failure is now the largest performance bottleneck by two
    orders of magnitude.
    ¹ Actually, commit d80d4a3 removed the inner loop in :refer candidate
      generation, but the new symbols->ns-syms re-adds one. The inner loops
      of both iterate through the public vars of each ns, so running time is
      only increased linearly by the average count of public vars per ns *
      ns, not geometrically by the number of namespaces.
    guns committed Feb 6, 2014
  3. @guns

    Move comment to correct location

    guns committed Feb 5, 2014
  4. @guns

    Avoid unnecessary work in :alias and :refer candidate search

    - The :alias expression no longer iterates through (all-ns) if no
      aliased symbols are present in the body
    - The :refer expression no longer iterates through every var of every
      namespace; (ns-publics ns) returns a map keyed by symbols so a simple
      contains? will do the same work
    While these optimizations offer minor performance gains, the gain in
    code clarity also merits their inclusion.
    guns committed Feb 5, 2014
Commits on Feb 5, 2014
  1. @guns

    Delay evaluation of available-classes-by-last-segment

    No need to pay the cost on ns load. A user who never imports classes
    also never needs to evaluate this.
    guns committed Feb 5, 2014
Commits on Feb 4, 2014
  1. @guns

    Improve performance of static :import candidate search

        - search/available-classes contains a seq of class symbols, not
        - A new var, search/available-classes-by-last-segment, contains the
          list above grouped by last segment
        - :import static candidate search is now O(1), from O(n)
    Every :import candidate search triggered a string/split + compare for
    every known static class. Within slamhound for instance, this is 32652
    iterations per import.
    Reducing each of these to a single map lookup is a significant
    performance boost for namespaces that contain many imports.
    guns committed Feb 3, 2014
Commits on Jan 30, 2014
  1. @guns

    Fix find-matching-ns for namespaces with underscores

    Problems fixed:
    1. find-matching-ns did not return a symbol when falling back to a
       linear search
    2. Namespaces with trailing underscores were undetectable
    guns committed Jan 29, 2014
  2. @guns

    Remove unused test data

    guns committed Jan 29, 2014
Commits on Jan 29, 2014
  1. @guns

    Release 1.5.1

    guns committed Jan 29, 2014
  2. @guns

    :require matching ns when importing classes created by deftype

    Classes created by deftype and defrecord are created on ns evaluation,
    therefore that ns must be required before referencing these classes.
    deftype and defrecord classes implement IType and IRecord in Clojure
    1.3.0+, so we can check the hierarchy to identify them.
    There is unfortunately no straightforward mapping of class package names
    to Clojure namespaces as deftype uses clojure.core/namespace-munge to
    simply change all \- to \_.
    Therefore a two step search for the matching ns is made:
        1. Try the simple case where all underscores are converted to dashes
        2. Search for the first namespace that matches the package name with
           dashes and/or underscores.
    Closes #64
    guns committed Jan 29, 2014