{"id":13788374,"url":"https://github.com/jonase/eastwood","last_synced_at":"2025-05-14T09:08:28.648Z","repository":{"id":2173271,"uuid":"3120010","full_name":"jonase/eastwood","owner":"jonase","description":"Clojure lint tool","archived":false,"fork":false,"pushed_at":"2024-07-10T21:23:02.000Z","size":3593,"stargazers_count":1083,"open_issues_count":36,"forks_count":66,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-05-03T00:04:42.650Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonase.png","metadata":{"files":{"readme":"README.md","changelog":"changes.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-01-06T18:33:14.000Z","updated_at":"2025-04-12T16:17:34.000Z","dependencies_parsed_at":"2024-01-08T18:03:38.730Z","dependency_job_id":"3a751497-5a94-46a8-8798-60062aa460cf","html_url":"https://github.com/jonase/eastwood","commit_stats":{"total_commits":1318,"total_committers":44,"mean_commits":"29.954545454545453","dds":0.3232169954476479,"last_synced_commit":"d289d0689734d0042b63eac49c82ef312acae0e6"},"previous_names":[],"tags_count":80,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonase%2Feastwood","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonase%2Feastwood/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonase%2Feastwood/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonase%2Feastwood/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonase","download_url":"https://codeload.github.com/jonase/eastwood/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254036843,"owners_count":22003654,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T21:00:44.406Z","updated_at":"2025-05-14T09:08:23.630Z","avatar_url":"https://github.com/jonase.png","language":"Clojure","funding_links":[],"categories":["tools","Code Analysis and Linter"],"sub_categories":[],"readme":"# eastwood - a Clojure lint tool\n\n[![Dependencies Status](https://versions.deps.co/jonase/eastwood/status.svg)](https://versions.deps.co/jonase/eastwood)\n[![Downloads](https://versions.deps.co/jonase/eastwood/downloads.svg)](https://versions.deps.co/jonase/eastwood)\n[![Build Status](https://circleci.com/gh/jonase/eastwood/tree/master.svg?style=shield\u0026circle-token=26d8d2fa593675196734ac6c28ee16e0a9183806)](https://circleci.com/gh/jonase/eastwood)\n[![Clojars Project](https://img.shields.io/clojars/v/jonase/eastwood.svg)](https://clojars.org/jonase/eastwood)\n\n\u003cimg src=\"doc/Clint_Eastwood_-_1960s_small.jpg\"\n alt=\"Picture of Clint Eastwood in 'A Fistful of Dollars' (1964)\" title=\"Clint Eastwood in 'A Fistful of Dollars' (1964)\"\n align=\"right\" /\u003e\n\n\u003e \"Now remember, things look bad and it looks like you're not gonna\n\u003e make it, then you gotta get mean.  I mean plumb, mad-dog mean.\n\u003e 'Cause if you lose your head and you give up then you neither live\n\u003e nor win.  That's just the way it is.\"\n\u003e - Josey Wales, played by Clint Eastwood in \"The Outlaw Josey Wales\"\n\nEastwood is a Clojure [linter](http://en.wikipedia.org/wiki/Lint_%28software%29); it inspects namespaces and reports possible problems.\n\nBecause it uses [tools.analyzer](https://github.com/clojure/tools.analyzer.jvm), its analysis and diagnostics tend to be particularly accurate, avoiding false positives and false negatives.\n\nIn particular it's about as accurate as the Clojure compiler itself - it prefers evaluation and macroexpansion over other approaches.\n\nThis approach is not free of tradeoffs. The use case where it shines is in CI environments, where a matrix of JDKs and/or Clojure versions can be leveraged, and where linter performance is not as critical as in editors or CLIs.\n\nEastwood's main area of focus is spotting bugs (as opposed to, say, helping following coding conventions). Other tools can complement or partly overlap with Eastwood's offering. \n\n\u003e Eastwood supports only JVM Clojure (\u003e= 1.7.0) , not ClojureScript or\n  Clojure/CLR. Consider using .cljc for obtaining certain degree of ClojureScript support.\n\n## Installation \u0026 Quick usage\n\nEastwood can be run from within a REPL, regardless of which build\ntools you may use.  See the [instructions\nhere](#running-eastwood-in-a-repl).\n\n### Leiningen\nEastwood can be run from the command line as a\n[Leiningen](http://leiningen.org) plugin.\n\nMerge the following into your `project.clj` or `~/.lein/profiles.clj`:\n\n```clojure\n:plugins [[jonase/eastwood \"1.4.3\"]]\n```\n\nTo run Eastwood with the default set of lint warnings on all of the\nClojure files in the source _and_ test paths of your project, use the\ncommand:\n\n    $ lein eastwood\n\n### deps.edn\n\nIf you're using `deps.edn`, you can set Eastwood options in an edn map, like this:\n```clojure\n{:aliases\n  {:eastwood\n    {:main-opts [\"-m\"\n                 \"eastwood.lint\"\n                 ;; Any Eastwood options can be passed here as edn:\n                 {}]\n     :extra-deps {jonase/eastwood {:mvn/version \"1.4.3\"}}}}}\n\n```\nto your `deps.edn`, and you should then be able to run Eastwood as\n\n```sh\nclojure -M:test:eastwood\n```\n\nFor deps.edn projects in particular, you don't need to set the `:source-paths` and `:test-paths`\nas configuration options; they will be accurately inferred at runtime.\n\nThe only requirement is that you enable all relevant deps.edn aliases - mainly `test` but possibly others,\ndepending on your project layout.\n\nAny `:paths` not present at runtime, as computed by the Clojure CLI, will not be analyzed by Eastwood. \n\n---\n\nIf it is not obvious what a warning message means, please check the\nnext section, which has a `[more]` link for each type of warning.\nMost types of warning messages have a page or more of text describing\nthe warning, why it occurs, and sometimes suggestions on what you can\ndo about it.  Also note that there are several types of warnings\nmarked as '(disabled)', meaning that by default no such warnings will\nbe checked for.  You may wish to enable those for your project.  See\nthe [Usage](#usage) section for options to enable or disable types of\nwarnings for your entire project.\n\nSee the [Usage](#usage) section below for more notes on side effects\nin test code, and instructions on [running Eastwood in a REPL\nsession](#running-eastwood-in-a-repl).\n\nEastwood can only finish linting a file if Clojure itself can compile\nit (unlike some other lint tools, which try to give meaningful error\nmessages for programs with syntax errors).  It is recommended to use a\ncommand like `lein check` to check for compiler errors before running\nEastwood.  Even better, `lein test` will compile files in your source\npaths and test paths, not merely your source paths as `lein check`\ndoes.\n\nIf you run Eastwood from a `lein` command line, it is perfectly normal\nto see the message `Subprocess failed` at the end if either the\nwarning or exception thrown counts are not 0.  Eastwood exits with a\nnon-0 [exit status](http://en.wikipedia.org/wiki/Exit_status) in this\nsituation, so that shell scripts or build tools running Eastwood will\nhave a simple way to check that something was not perfect.  If\nEastwood quits due to some internal error that throws an exception,\nyou will typically see much more voluminous output about what went\nwrong, often including a stack trace.\n\nYou can override the exit code with the `:forced-exit-code 0` option.\nThat can be helpful when wanting to see the results of linting merely for informative purposes. \n\n## What's there?\n\nEastwood warns when it finds the following kinds of things.  Each\nkeyword below is the name of the \"linter\".  That name can be used on\nthe command line to enable or disable the linter.  All linters are\nenabled by default unless they have '(disabled)' after their name.\n\n| Linter name | Description | Docs |\n| ----------- | ----------- | ---- |\n| no name* | Inconsistencies between file names and the namespaces declared within them.  * Cannot be disabled. | [[more]](#check-consistency-of-namespace-and-file-names) |\n| `:bad-arglists` | Function/macro `:arglists` metadata that does not match the number of args it is defined with. | [[more]](#bad-arglists) |\n| `:boxed-math` | Boxed math compiler warnings | [[more]](#boxed-math) |\n| `:constant-test` | A test expression always evaluates as true, or always false. | [[more]](#constant-test) |\n| `:def-in-def` | def's nested inside other def's. | [[more]](#def-in-def) |\n| `:deprecations` | Deprecated Clojure Vars, and deprecated Java constructors, methods, and fields. | [[more]](#deprecations) |\n| `:implicit-dependencies` | A fully-qualified var refers to a namespace that hasn't been listed in `:require`. | [[more]](#implicit-dependencies) |\n| `:keyword-typos` (disabled) | Keyword names that may be typos because they occur only once in the source code and are slight variations on other keywords. | [[more]](#keyword-typos) |\n| `:local-shadows-var` | A local name, e.g. a function arg or let binding, has the same name as a global Var, and is called as a function. | [[more]](#local-shadows-var) |\n| `:misplaced-docstrings` | Function or macro doc strings placed after the argument vector, instead of before the argument vector where they belong. | [[more]](#misplaced-docstrings) |\n| `:no-ns-form-found` | Warn about Clojure files where no `ns` form could be found. | [[more]](#no-ns-form-found) |\n| `:non-clojure-file` (disabled) | Warn about files that will not be linted because they are not Clojure source files, i.e. their name does not end with '.clj'. | [[more]](#non-clojure-file) |\n| `:non-dynamic-earmuffs` | Vars marked `^:dynamic` should follow the \"earmuff\" naming convention, and vice versa. | [[more]](#non-dynamic-earmuffs) |\n| `:performance` | Performance warnings | [[more]](#performance) |\n| `:redefd-vars` | Redefinitions of the same name in the same namespace. | [[more]](#redefd-vars) |\n| `:reflection` | Reflection warnings | [[more]](#reflection) |\n| `:suspicious-expression` | Suspicious expressions that appear incorrect, because they always return trivial values. | [[more]](#suspicious-expression) |\n| `:suspicious-test` | Tests using `clojure.test` that may be written incorrectly. | [[more]](#suspicious-test) |\n| `:unlimited-use` | Unlimited `(:use ...)` without `:refer` or `:only` to limit the symbols referred by it. | [[more]](#unlimited-use) |\n| `:unused-fn-args` (disabled) | Unused function arguments. | [[more]](#unused-fn-args) |\n| `:unused-locals` (disabled) | Symbols bound with `let` or `loop` that are never used. | [[more]](#unused-locals) |\n| `:unused-meta-on-macro` | Metadata on a macro invocation is ignored by Clojure. | [[more]](#unused-meta-on-macro) |\n| `:unused-namespaces` (disabled) | Warn if a namespace is given in an `ns` form after `:use` or `:require`, but the namespace is not actually used. | [[more]](#unused-namespaces) |\n| `:unused-private-vars` (disabled) | Unused private vars. | [[more]](#unused-private-vars) |\n| `:unused-ret-vals` and `:unused-ret-vals-in-try` | Unused values, including unused return values of pure functions, and some others functions where it rarely makes sense to discard its return value. | [[more]](#unused-ret-vals) |\n| `:wrong-arity` | Function calls that seem to have the wrong number of arguments. | [[more]](#wrong-arity) |\n| `:wrong-ns-form` | ns forms containing incorrect syntax or options. | [[more]](#wrong-ns-form) |\n| `:wrong-pre-post` | function has preconditions or postconditions that are likely incorrect. | [[more]](#wrong-pre-post) |\n| `:wrong-tag` | An incorrect type tag for which the Clojure compiler does not give an error. | [[more]](#wrong-tag) |\n\nThe following table gives some additional detail about each linter.\n\nThe 'debug' column indicates whether extra debug messages about a\nlinter's warnings can be enabled via the `:debug-warning` option.\nThis option can be given a value of `true` to enable all such\nwarnings, or it can be a set of keywords that also enables additional\ndetails to be printed.  The only keyword currently supported in this\nset is `:ast`, which prints AST contents related to issued warnings\nfor most linters that implement `:debug-warning`.\n\nThe 'suppress' column indicates whether warnings produced by the\nlinter can be selectively disabled via Eastwood config files.  See\n[Eastwood config files](#eastwood-config-files) for more details.\n\n| Linter name | debug | suppress |\n| ----------- | ----- | -------- |\n| no name*                 |  |  |\n| `:bad-arglists`          |  |  |\n| `:constant-test`         | yes | yes |\n| `:def-in-def`            |  | yes |\n| `:deprecations`          |  | yes |\n| `:keyword-typos`         |  |  |\n| `:local-shadows-var`     |  |  |\n| `:misplaced-docstrings`  |  |  |\n| `:no-ns-form-found`      |  |  |\n| `:non-clojure-file`      |  |  |\n| `:redefd-vars`           | yes | yes |\n| `:suspicious-expression` | yes, for those involving macros | yes |\n| `:suspicious-test`       |  | yes |\n| `:unlimited-use`         |  |  |\n| `:unused-fn-args`        |  | yes  |\n| `:unused-locals`         |  |  |\n| `:unused-meta-on-macro`  |  | yes |\n| `:unused-namespaces`     |  |  |\n| `:unused-private-vars`   |  |  |\n| `:unused-ret-vals` and `:unused-ret-vals-in-try` | yes | yes |\n| `:wrong-arity`           | yes | yes |\n| `:wrong-ns-form`         |  |  |\n| `:wrong-pre-post`        |  |  |\n| `:wrong-tag`             |  | yes |\n\n\n## Usage\n\n### From the command line as a Leiningen plugin\n\nRunning\n\n    $ lein eastwood\n\nin the root of your project will lint your project's namespaces -- all\nof those in your `:source-paths` and `:test-paths` directories and\ntheir subdirectories.  You can also lint individual namespaces in your\nproject, or your project's dependencies:\n\n    $ lein eastwood \"{:namespaces [compojure.handler compojure.core-test] :exclude-linters [:unlimited-use]}\"\n    == Linting compojure.handler ==\n    src/compojure/handler.clj:48:8: deprecations: Var '#'compojure.handler/api' is deprecated.\n    == Linting compojure.core-test ==\n    test/compojure/core_test.clj:112:21: suspicious-test: 'is' form has first arg that is a constant whose value is logical true.  This will always pass.  There is probably a mistake in this test\n    test/compojure/core_test.clj:117:21: suspicious-test: 'is' form has first arg that is a constant whose value is logical true.  This will always pass.  There is probably a mistake in this test\n    test/compojure/core_test.clj:109:1: constant-test: Test expression is always logical true or always logical false: false\n    test/compojure/core_test.clj:109:1: constant-test: Test expression is always logical true or always logical false: true\n    test/compojure/core_test.clj:114:1: constant-test: Test expression is always logical true or always logical false: false\n    test/compojure/core_test.clj:114:1: constant-test: Test expression is always logical true or always logical false: true\n    == Warnings: 7. Exceptions thrown: 0\n    Subprocess failed\n\nAdding `:out \"warn.txt\"` to the options map will cause all of the\nEastwood warning lines and 'Entering directory' lines, but no others,\nto be written to the file `warn.txt`.  This file is useful for\nstepping through warnings.\n\n    # This works on bash shell in Linux and Mac OS X, and also in\n    # Windows cmd shell\n    $ lein eastwood \"{:out \\\"warn.txt\\\"}\"\n\n    # This saves a little typing in bash shell, but does not work in\n    # Windows cmd shell.  For all example command lines, you can use\n    # single quotes in bash if you prefer.\n    $ lein eastwood '{:out \"warn.txt\"}'\n\nAvailable options for specifying namespaces and paths are:\n\n* `:namespaces` Vector of namespaces to lint.  A keyword\n  `:source-paths` in this vector will be replaced with a list of\n  namespaces in your Leiningen `:source-paths` and their\n  subdirectories.  These namespaces will be in an order that honors\n  inter-namespace dependencies as determined by `:require` and `:use`\n  keys in `ns` forms.  Similarly for a keyword `:test-paths`.  If you\n  do not specify `:namespaces`, it defaults to `[:source-paths\n  :test-paths]`.\n* `:exclude-namespaces` Vector of namespaces to exclude.\n  `:source-paths` and `:test-paths` may be used here as they can be\n  for `:namespaces`.  Defaults to an empty list if you do not specify\n  `:exclude-namespaces`.\n* `:source-paths` is normally taken from your Leiningen `project.clj`\n  file, which is `[ \"src\" ]` by default if not specified there.  You\n  can also specify `:source-paths` in the Eastwood option map to\n  override what Leiningen uses.\n* `:test-paths` is similar in behavior to `:source-paths`, except it\n  defaults to `[ \"test\" ]` if not specified in your `project.clj`\n  file.\n\nLinter names are given in the previous section.  Available options for\nspecifying which linters are enabled or disabled are:\n\n* `:linters` Linters to use.  If not specified, same as `[:default]`,\n  which is all linters except those documented as 'disabled by\n  default'.\n* `:exclude-linters` Linters (or [linter sub `:kind`s](#ignoring-linter-sub-kinds)) to exclude\n* `:add-linters` Linters to add. You can use to enable linters that are disabled by default. The final list of linters is the set\n  specified by `:linters`, taking away all in `:excluded-linters`,\n  then adding all in `:add-linters`.\n\nThe keyword `:all` in any of the collections of linters listed above\nwill be replace with the collection of all linters.  The keyword\n`:default` will be replaced with the collection of default linters.\nThus `:linters [:all]` enables all linters, even those disabled by\ndefault, and `:linters [:all] :exclude-linters [:default]` enables\nonly those that are disabled by default.\n\nNote that you can add Eastwood options to a user-wide Leiningen\n`profiles.clj` file or to your project's `project.clj` file if you\nwish.  See [How the Eastwood options map is\ndetermined](#how-the-eastwood-options-map-is-determined) for more\ndetails.\n\n\n## Only lint files modified since last run\n\nYou can now instruct eastwood to only lint the files\nchanged since the last run.\n\nIf passed `:only-modified` with the value true, Eastwood will only lint the \nfiles which are modified since the timestamp stored in `.eastwood`.\n\n```\n  :only-modified true\n```\n\n## Usage\n\nAs mentioned in the [Installation \u0026 Quick\nusage](#installation--quick-usage) section above, Eastwood causes any\nand all side effects that loading the file would cause (e.g. by doing\n`use` or `require` on the file's namespace).  Eastwood is able to find\npotential problems in test code, too.  If you wish to use Eastwood on\ntest files without such side effects, consider modifying your tests so\nthat merely performing `require`/`use` on the files does not cause the\nside effects.  If you can arrange things so that running your tests\nrequires loading the files and then calling some function(s) (e.g. as\ntests written using\n[`clojure.test/deftest`](http://clojure.github.io/clojure/#clojure.test)\ndo), then you can run Eastwood on those files without the side\neffects.\n\nIf you have a code base you do not trust to load, consider a sandbox,\nthrowaway virtual machine, etc.\n\nThere are also options that enable printing of additional debug\nmessages during linting.  These are only intended for tracking down\nthe cause of errors in Eastwood.  You specify the key `:debug` with a\nvalue that is a list or vector of keywords, e.g.\n\n    lein eastwood \"{:exclude-linters [:unlimited-use] :debug [:options :ns]}\"\n\n* `:all` - enable all debug messages.  This also enables showing the\n  list of namespaces near the beginning of the output, before linting\n  begins.\n* `:options` - print the contents of the options map at several steps\n  during startup.  May be useful to debug where options are coming\n  from.\n* `:config` - print the names of Eastwood config files just before\n  they are read.\n* `:time` - print messages about the elapsed time taken during\n  analysis, and for each individual linter.\n* `:forms` - print the forms as read, before they are analyzed\n* `:forms-pprint` - like `:forms` except pretty-print the forms\n* `:ast` - print ASTs as forms are analyzed and `eval`d.  These can be\n  quite long.\n* `:progress` - show a brief debug message after each top-level form\n  is read\n* `:compare-forms` - print all forms as read to a file\n  `forms-read.txt`, all forms after being analyzed to a file\n  `forms-analyzed.txt`, and all forms after being read, analyzed into\n  an AST, and converted back into a form from the AST, to a file\n  `forms-emitted.txt`.\n* `:ns` - print the initial set of namespaces loaded into the Clojure\n  run-time at the beginning of each file being linted.  (TBD: it used\n  to do the following, but this needs to be reimplemented if it is\n  desired: \"and then after each top level form print any changes to\n  that list of loaded namespaces (typically as the result of\n  evaluating a `require` or `use` form).\")\n* `:var-info` - print some info about Vars that exist in various\n  namespaces, and how many of them have data describing them in\n  Eastwood's `var-info.edn` resource file, and how many do not.\n  Useful when new releases of Clojure are made that add new Vars, to\n  determine which ones Eastwood does not know about yet.\n\n\n### Eastwood config files\n\nEastwood `eval`s several config files in\nits internal resources.  You can see the latest versions\n[here](https://github.com/jonase/eastwood/tree/master/resource/eastwood/config).\nIt also supports command line options to change which of these files\nare read, or to read user-written config files.\n\nCurrently Eastwood supports config files that contain code to\nselectively disable warnings of some linters.  For example, consider\nthis expression from config file `clojure.clj`:\n\n```clojure\n(disable-warning\n {:linter :suspicious-expression\n  ;; specifically, those detected in function suspicious-macro-invocations\n  :for-macro 'clojure.core/let\n  :if-inside-macroexpansion-of #{'clojure.core/when-first}\n  :within-depth 6\n  :reason \"when-first with an empty body is warned about, so warning about let with an empty body in its macroexpansion is redundant.\"})\n```\n\nThe `:deprecations` linter accepts a set of symbols which are marked as ok to be deprecated.\nThis is useful for when you're working on an old project and want to mark stuff\nas deprecated without breaking the build.\n\n```clojure\n(disable-warning\n  {:linter :deprecations\n   :symbol-matches #{#\"^#'my\\.old\\.project\\.*\"}})\n```\n\nEastwood would normally report a `:suspicious-expression` warning if\nit encounters a form `(let [x y])`, because the `let` has an empty\nbody.  It does so even if the `let` is the result of expanding some\nother macro.\n\nHowever, if such a `let` occurs because of a macro expansion of the\nexpression `(when-first [x y])`, the warning for the `let` will be\nsuppressed.  Eastwood already warns about the `(when-first [x y])`\nbecause it has an empty body, so warning about the `let` would be\nredundant.\n\nThe exact configurations supported are not documented yet, but will be\nin the documentation for each linter.\n\nYou can specify the key `:builtin-config-files` in the options map to\noverride the built-in config files read.  It defaults to\n`[\"clojure.clj\" \"clojure-contrib.clj\" \"third-party-libs.clj\"]`.  All\nsuch file names are only looked for in Eastwood's built-in config\nfiles.\n\nSimilarly you can specify `:config-files` in the options map to give\nadditional files to read.  These are filenames that can be anywhere\nin your file system, specified as strings, or if Eastwood is invoked\nfrom the REPL, anything that can be passed to\n`clojure.java.io/reader`.\n\n\n### Running Eastwood in a REPL\n\n\u003cdetails\u003e\n\nIf you use Leiningen, merge this into your project's `project.clj`\nfile first:\n\n```clojure\n:profiles {:dev {:dependencies [[jonase/eastwood \"1.4.3\" :exclusions [org.clojure/clojure]]]}}\n```\n\nIf you use a different build tool, you will need to add the dependency\nabove in the manner appropriate for it.  See\n[Clojars](https://clojars.org/jonase/eastwood) for Gradle and Maven\nsyntax.\n\nFrom within your REPL, there are two different functions you may call,\ndepending upon the kind of results you want.\n\n* `eastwood` prints output similar to when you run Eastwood from the\n  Leiningen command line, but it does not exit the JVM when it\n  finishes.\n\n* `lint` returns a map containing data structures describing any\n  warnings or errors encountered. For example, file\n  names, line numbers, and column numbers are all available\n  separately, requiring no parsing of strings containing those things\n  combined together.  See the doc string of `eastwood.lint/lint` for\n  details of the return value.\n\n```clojure\n(require '[eastwood.lint :as e])\n\n;; Replace the values of :source-paths and :test-paths with whatever\n;; is appropriate for your project.  You may omit them, and then the\n;; default behavior is to search all directories in your Java\n;; classpath, and their subdirectories recursively, for Clojure source\n;; files.\n(e/eastwood {:source-paths [\"src\"] :test-paths [\"test\"]})\n\n(e/with-memoization-bindings\n  (e/lint {:source-paths [\"src\"] :test-paths [\"test\"]}))\n```\n\nAll of the same options that can be given on a Leiningen command line\nmay be used in the map argument of the `eastwood` and `lint`\nfunctions.\n\nThere is a `:callback` key that can be added to the argument map for\nthe `eastwood` function.  Its value is a callback function that gives\nyou significant control of where warning and error messages appear --\nby default these all appear on the writer `*out*`.  This callback\nfunction should not be overridden for the `lint` function, since\n`lint` uses it in its implementation.\n\nThere is no documentation for this callback function yet.  You are\nwelcome to read Eastwood source code to see examples of how to write\none, but note that this is alpha-status code that will likely have API\nchanges in future Eastwood versions.\n\n\n#### Warnings about using Eastwood in a REPL\n\nEastwood behaves similarly to `clojure.core/require` while performing\nits analysis, in that it loads your code.  In particular, Eastwood\ndoes these things:\n\n* Reads and analyzes the source code you specify.\n* Generates _new_ forms from the analysis results.  Note: if there are\n  bugs, these new forms might not be identical to the original source\n  code.\n* Calls `eval` on the generated forms.\n\nHopefully you can see from this that Eastwood bugs, especially in the\nportion up to generating new forms to be evaluated, could lead to\nincorrect Clojure code being loaded into a running JVM.\n\nIt would be foolhardy to run Eastwood in a JVM running a live\nproduction system.  We recommend that you use a different JVM process\nfor Eastwood than the one where you do your ongoing testing and\ndevelopment work.\n\nWhen reporting problems with Eastwood when run from the REPL, please\nreproduce it in as few steps as possible after starting a new JVM\nprocess, and include those steps in your problem report.\n\nRunning Eastwood from the REPL more than once in the same JVM process\nrequires you to manage your namespaces manually.  Eastwood will not\nforce the removal of any namespaces, and I would guess if there are\nany issues from reloading a namespace that is already loaded with\nprotocols, `deftype`, etc. then they are yours to deal with.\n\nStuart Sierra's [component](https://github.com/stuartsierra/component)\nlibrary and workflow might be helpful in automatically removing old\nversions of namespaces from a JVM process.  If you have instructions\nthat you have used with Eastwood and component or a similar tool,\nplease file a GitHub issue so they can be included here.\n\n\u003c/details\u003e\n\n### How the Eastwood options map is determined\n\n\u003cdetails\u003e\n\nIf you start Eastwood from a REPL using the function\n`eastwood.lint/eastwood`, then the options map you supply is modified\nonly slightly before use.  Skip down to the section \"Last options map\nadjustments\".\n\nIf you start Eastwood from a Leiningen command line, there are two\nmain steps in the creation of the Eastwood options map before those\nlast adjustments.  First is what Leiningen itself does before Eastwood\nstarts, followed by some adjustments made by Eastwood.\n\n\n#### Options map calculation before Eastwood starts\n\nLeiningen creates a value for the `:eastwood` key in the effective\nproject map using its normal rules for combining profiles from\nmultiple possible files.  In case those are unfamiliar to you, here is\na quick summary that should be correct, but leaves out some cases that\nare recommended against in the Leiningen documentation, e.g.\nincluding a `:user` profile in your project's `project.clj` file.\n\nFrom lowest priority to highest, the sources are the value of an\n`:eastwood` key in:\n\n* the top level of the `defproject` in your `project.clj` file\n* the `:system` profile of a system-wide `/etc/leiningen/profiles.clj`\n  file.\n* the `:user` profile of a user-wide `$HOME/.lein/profiles.clj`, or\n  the top level of a `$HOME/.lein/profiles.d/user.clj` file.\n* the `:dev` profile of your project's `project.clj` file.\n* the `:dev` profile of your project's `profiles.clj` file\n  (recommended only for temporary overrides of your `project.clj`\n  file, not to be checked in to revision control).\n\nThe value associated with the `:eastwood` key in any of these\nlocations should be maps.  If there is more than one, they are merged\nsimilarly to how `clojure.core/merge` does, where later values for the\nsame key replace earlier values.  However, if the values in this map\nare collections, then they are combined.  Vectors and lists are\nconcatenated, sets are combined with `clojure.set/union`, and sub-maps\nare merged, recursing down to apply the same rules to their nested\nvalues.  See the section on\n[Merging](https://github.com/technomancy/leiningen/blob/stable/doc/PROFILES.md#merging)\nin the Leiningen documentation for more details and for metadata that\ncan be used to modify this merging behavior.\n\nFor example, if your user-wide `profiles.clj` file contains this:\n\n```clojure\n{:user {:plugins [[jonase/eastwood \"1.4.3\"]]\n        :eastwood {:exclude-linters [:unlimited-use]\n                   :debug [:time]}\n        }}\n```\n\nand your `project.clj` file's `defproject` contains this:\n\n```clojure\n  :profiles {:dev {:eastwood {:exclude-linters [:wrong-arity :bad-arglists]\n                              :debug [:progress]\n                              :warning-format :map-v2\n                              }}}\n```\n\nthen Leiningen will merge them to produce the following combined value\nfor the `:eastwood` key:\n\n```clojure\n  {:exclude-linters (:unlimited-use :wrong-arity :bad-arglists)\n   :debug (:time :progress)\n   :warning-format :map-v2}\n```\n\nWe will call this value the Leiningen option map.\n\nIndependently of this Leiningen option map that is a combination of\nthe values of the `:eastwood` key in various Leiningen files,\nLeiningen also calculates values for the `:source-paths` and\n`:test-paths` keys (and all other keys, but only these 3 are ever used\nlater to calculate Eastwood options).\n\n### Options map adjustments made by Eastwood when invoked from command line\n\nAfter the Leiningen option map is calculated, Eastwood starts making\nnew modified versions.\n\nIt 'normal merges' the three\nmaps below, in the order given.  Thus values for the same key in later\nmaps override earlier ones, with no special Leiningen merging behavior\nfor collections:\n\n1. Leiningen paths - a map containing only the keys `:source-paths`\n   and `:test-paths`, and the Leiningen-calculated values for them.\n   The value of `:source-paths` defaults to `[\"src\"]` even if you\n   never specify one.  Similarly `:test-paths` defaults to `[\"test\"]`.\n2. Leiningen options map - the map for the `:eastwood` key.  Note that\n   this may contain values for `:source-paths` and/or `:test-paths`\n   that override the ones above.\n3. command line option map\n\n#### Last options map adjustments\n\nIf you start Eastwood from a REPL, the only changes made to the\noptions map specified as an argument are to fill in default values for\nsome keys if you do not supply them, i.e. to merge a map like the\nfollowing _before_ the supplied options map.  See\n`eastwood.lint/last-options-map-adjustments` for details.\n\n* `:cwd` - the full path name to the current working directory at the\n  time the function is called.  This is used to cause file names\n  reported in warnings to be relative to this directory, and thus\n  shorter, if they are beneath it.\n* `:linters` - default value of all linters documented to be enabled\n  by default.\n* `:namespaces` - default value of `[:source-paths :test-paths]`\n* `:source-paths` - a list of all directories on the Java classpath.\n  This is a special case that cannot be implemented with `merge`,\n  because it is only used if neither of the keys `:source-paths` nor\n  `:test-paths` are present in the supplies options map, as a\n  convenience for use in the REPL.\n* `:callback` - a default message callback function, which simply\n  formats all callback data as strings and prints it to `*out*`, or\n  the writer specified by the value of the `:out` key in the options\n  map (e.g. if it is a string, the file named by that string will be\n  written).\n\n\u003c/details\u003e\n\n## Known issues\n\n\n### Code analysis engine is more picky than the Clojure compiler\n\nEastwood uses\n[`tools.analyzer`](https://github.com/clojure/tools.analyzer) and\n[`tools.analyzer.jvm`](https://github.com/clojure/tools.analyzer.jvm)\nto analyze Clojure source code.  It performs some sanity checks on the\nsource code that the Clojure compiler generally does not.\n\n\n### Explicit use of Clojure environment `\u0026env`\n\nCode that uses the **values of `\u0026env`** feature of the Clojure\ncompiler will cause errors when being analyzed.  Some known examples\nare the libraries\n[`immutable-bitset`](https://github.com/ztellman/immutable-bitset) and\n[`flatland/useful`](https://github.com/flatland/useful).\n\nNote that if a library uses simply `(keys \u0026env)` it will be analyzed with\nno problems, however because the values of `\u0026env` are `Compiler$LocalBinding`s,\nthere's no way for `tools.analyzer.jvm` to provide a compatible `\u0026env`\n\nThe following exception being thrown while linting is a symptom of\nthis issue:\n\n    Exception thrown during phase :analyze+eval of linting namespace immutable-bitset\n    ClassCastException clojure.lang.PersistentArrayMap cannot be cast to clojure.lang.Compiler$LocalBinding\n\n## Notes on linter warnings\n\n### Check consistency of namespace and file names\n\n\u003cdetails\u003e\n\nThis is not a linter like the others, in that it has no name, cannot\nbe disabled, and the check is always performed by Eastwood before any\nother linter checks are done.\n\nWhen doing `require` or `use` on a namespace like `foo.bar.baz-tests`,\nit is searched for in the Java classpath in a file named\n`foo/bar/baz_tests.clj` (on Unix-like systems) or\n`foo\\bar\\baz_tests.clj` (on Windows).  Dots become path separator\ncharacters and dashes become underscores.\n\nSuch a file will normally have an `ns` form with the specified\nnamespace.  If the namespace name is not consistent with the file\nname, then undesirable things can happen.  For example, `require`\ncould fail to find the namespace, or Leiningen could fail to run the\ntests defined in a test namespace.\n\nEastwood checks all Clojure files in `:source-paths` and `:test-paths`\nwhen starting up (or in whatever files are specified by the\n:namespaces option).  If there are any mismatches between file names\nand the namespace names in the `ns` forms, an error message will be\nprinted and no linting will be done at all.  This helps avoid some\ncases of printing error messages that make it difficult to determine\nwhat went wrong.  Fix the problems indicated and try again.\n\nLeiningen's `lein check` and `lein test` commands do not perform as\ncomplete a check as Eastwood does here.\n\nIf a file on the `:source-path` contains a non-matching namespace\nname, but that namespace name exists in another file in your project,\n`lein check` will compile the file containing that namespace again,\nnever compiling the file containing the wrong namespace name.\n\nIf a file on the `:test-path` contains a non-matching namespace name,\nbut that namespace name exists in another file, `lein test` will not\nrun the tests in that file at all, and will only run the tests in the\nwrongly-given namespace once, not multiple times.  In both cases, such\na wrong namespace is easy to create by copying a Clojure file and\nediting it, forgetting to edit the namespace.\n\n\u003c/details\u003e\n\n### `:non-clojure-file`\n\n#### Files that will not be linted because they are not Clojure source files\n\n\u003cdetails\u003e\n\nThis linter is disabled by default, because it warns even about\nClojureScript and Java source files it finds, and these are relatively\ncommon in projects with Clojure/Java source files.  You must\nexplicitly enable it if you wish to see these warnings.\n\nIf you specify `:source-paths` or `:test-paths`, or use the default\nEastwood options from the command line that cause it to scan these\npaths for Clojure source files, then with this linter enabled it will\nwarn about each file found that is not a Clojure/Java source file,\ni.e. if its file name does not end with '.clj'.\n\n\u003c/details\u003e\n\n### `:no-ns-form-found`\n\n#### Warn about Clojure files where no `ns` form could be found\n\n\u003cdetails\u003e\n\nIf you explicitly specify `:source-paths` or `:test-paths`, or use the\ndefault Eastwood options from the command line that cause it to scan\nthese paths for Clojure source files, with this linter enabled (the\ndefault), it will warn about each file where it could not find an `ns`\nform.  For each such file, its contents will not be linted, unless it\nis loaded from another linted file.\n\nEastwood uses the library `tools.namespace` to scan for Clojure source\nfiles, and in each Clojure source file it looks for a top-level `ns`\nform.  This form need not be the first form, but Eastwood will not\nfind it if it is not at the top level, e.g. if it is inside of a\n`let`, `if`, `compile-if`, etc.\n\nIt is somewhat unusual to have a file with no `ns` form at all, not\neven inside of a `let`, `compile-if`, etc.  However, there are valid\nreasons to have them, e.g. you have some code that you want to use in\ncommon between Clojure/Java and ClojureScript, and you use `load` to\ninclude it from two or more other source files.  Starting with Clojure\n1.7.0, this purpose is better satisfied with `.cljc` files (see\n[Reader Conditions](http://clojure.org/reader#The%20Reader--Reader%20Conditionals)).\n\n\u003c/details\u003e\n\n### `:misplaced-docstrings`\n\n#### Function or macro doc strings placed after the argument vector, instead of before the argument vector where they belong.\n\n\u003cdetails\u003e\n\nThe correct place to put a documentation string for a function or\nmacro is just before the arguments, like so:\n\n```clojure\n(defn my-function\n  \"Do the thing, with the stuff.  Fast.\"\n  [thing stuff]\n  (conj stuff thing))\n```\n\nIt is an easy mistake to accidentally put them in the opposite order,\nespecially if you like to place your arguments on the same line as the\nfunction name.\n\n```clojure\n(defn my-function [thing stuff]\n  \"Do the thing, with the stuff.  Fast.\"\n  (conj stuff thing))\n```\n\nThis function will still return the desired value.  The primary\ndisadvantage is that there is no doc string for a function defined\nthis way, so `(doc my-function)` will not show what you intended, and\ntools that extract documentation from Clojure code will not find it.\n\n\u003c/details\u003e\n\n### `:deprecations`\n\n#### Deprecated Clojure Vars, and deprecated Java instance methods, static fields, static methods, and constructors.\n\n\u003cdetails\u003e\n\nThe warnings issued are based upon the particular JDK you are using\nwhen running Eastwood, and can change between different JDK versions.\n\nClojure vars are considered deprecated if they have metadata with a\nkey `:deprecated`, and the value associated with that key is neither\n`false` nor `nil`.  Which vars are deprecated can change from one\nversion of Clojure, or a Clojure library you use, to the next.\n\nOne example of such a function is `clojure.core/replicate`, deprecated\nas of Clojure version 1.3 as you can see from its definition, copied\nbelow.\n\n```clojure\n(defn replicate\n  \"DEPRECATED: Use 'repeat' instead.\n   Returns a lazy seq of n xs.\"\n  {:added \"1.0\"\n   :deprecated \"1.3\"}\n  [n x] (take n (repeat x)))\n```\n\n\u003c/details\u003e\n\n### `:implicit-dependencies`\n\n#### Implicit dependencies\n\n\u003cdetails\u003e\n\nA qualified var like `some-namespace/foo` will resolve if `some-namespace`\nhas been loaded, regardless of whether or not `some-namespace` has been\nexplicitly required in the current namespace.\nThat is,\n\n```clojure\n(ns a)\n\n(some-namespace/foo)\n```\n\nmay work by accident, depending on load order.\n\nThis linter raises a warning in these cases, so you can list the dependency explicitly:\n```clojure\n(ns a\n  (:require some-namespace)\n\n(some-namespace/foo)\n```\n\n\u003c/details\u003e\n\n### `:redefd-vars`\n\n#### Redefinitions of the same name in the same namespace.\n\n\u003cdetails\u003e\n\nIt is possible to accidentally define the same var multiple times in\nthe same namespace.  Eastwood's `:redefd-vars` linter will warn about\nthese.\n\n```clojure\n(defn my-favorite-function-name [x]\n   ;; code here\n   )\n\n;; lots of other functions here\n\n(defn my-favorite-function-name [a b c]\n   ;; different code here\n   )\n```\n\nClojure's behavior in this situation is not to give any warnings, and\nfor the later definition to replace the first.  It is common practice\nfor many Clojure developers to reload namespaces after editing their\nsource code.  If Clojure issued warnings when reloading a modified\nsource file for every redefined var, it would be a significant\nannoyance.\n\nIf you use `clojure.test` to develop tests for your code, note that\n`deftest` statements create vars with the same name as you give to the\ntest.  If you accidentally create two `deftest`s with the same name,\nthe tests in the first `deftest` will never be run, and you will lose\ntest coverage.  There will be nothing in the source code to indicate\nthis other than the common name.  Below is an example where the first\n`deftest` contains tests that clearly should fail, but since they are\nnot run, all of the tests actually run could still pass.\n\n```clojure\n(deftest test-feature-a\n  ;; This test should cause test runs to fail, but IT DOES NOT.\n  (is (= 0 1)))\n\n;; lots of other tests here\n\n(deftest test-feature-a   ; perhaps written months after the earlier tests\n  (is (= 5 (+ 2 3))))\n```\n\nThe best fix here is simply to rename the tests so no two have the\nsame name.\n\nEastwood will treat a `declare` as if it were not there, for the\npurposes of issuing `:redefd-vars` warnings.  These are specifically\nintended to create a var but not yet give it a value, e.g. in cases\nwhere you want to write mutually recursive functions.\n\nThere are some macros that define a var multiple times, e.g. the\n`deftrace` macro in the\n[`tools.trace`](https://github.com/clojure/tools.trace) contrib\nlibrary.  Eastwood will issue a warning in such cases, and the reason\nwill not necessarily be obvious unless you read the macro definition.\nEastwood contains code specifically to avoid issuing a warning when\nthis is done in the implementation of Clojure's `defprotocol` and\n`defmulti` macros, but it is not possible for it to do this correctly\nin all cases, no matter how a macro might be written in the future.\n\nIf you want to write a macro that uses a similar technique as these\nothers, consider using `declare` for all but the last definition, if\npossible, and Eastwood will ignore all but that last definition.\n\n\u003c/details\u003e\n\n### `:def-in-def`\n\n#### `def` nested inside other `def`s\n\n\u003cdetails\u003e\n\nIf you come to Clojure having learned Scheme earlier, you may write\nClojure code with `def` statements inside of functions.  Or you might\nbe unfamiliar with functional programming style, and try writing code\nin imperative style using `def` like this:\n\n```clojure\n(defn count-up-to [n]\n  (def i 1)\n  (while (\u003c= i n)\n    (println i)\n    (def i (+ i 1))))\n```\n\nThis is bad form in Clojure.  It is written in imperative style, which\nis not encouraged, but that is not the worst thing about this example.\nThe worst part is the use of `def` inside of another `def` (the `defn\ncount-up-to` counts as the outer `def`).  `def`s always have an effect\non a globally visible var in the namespace, whether they are nested\ninside another `def` or not.\n\nUnless you really know what you are doing and looking for a very\nparticular effect, it is recommended to take `:def-in-def` warnings as\na sign to change your code.\n\nIf you want local functions that can only be used inside of an outer\nfunction, not visible or callable elsewhere, consider using `let`:\n\n```clojure\n(defn outer-fn-callable-elsewhere [n]\n  (let [helper-fn (fn [m] (* m m))]\n    (if (\u003e n 10)\n      (helper-fn n)\n      (helper-fn (+ n 17)))))\n```\n\nIf you need local functions that can all call each other, `let` will\nnot work, but [`letfn`](http://clojuredocs.org/clojure.core/letfn)\nwill.\n\nIf you want to write code in a style like you would in a language that\nuses mutable variables by default, e.g. most other languages, the\nfirst recommendation is to learn the functional style of doing things,\nif you can find a way that keeps the code understandable.\n[`loop`](http://clojuredocs.org/clojure.core/loop) may fit your\npurpose when other ways are not easy to find.\n\nIf you have considered that advice and still want local mutable\nvariables, other recommendations are:\n\n* [`atom`](http://clojuredocs.org/clojure.core/atom),\n  [`reset!`](http://clojuredocs.org/clojure.core/reset!),\n  [`swap!`](http://clojuredocs.org/clojure.core/swap!)\n* Clojure's\n  [`with-local-vars`](http://clojuredocs.org/clojure.core/with-local-vars)\n  or the [proteus](https://github.com/ztellman/proteus) library\n\n\u003c/details\u003e\n\n### `:wrong-arity`\n\n#### Function calls that seem to have the wrong number of arguments.\n\n\u003cdetails\u003e\n\nEastwood warns if a function call is found that has a number of\narguments not equal to any of the defined signatures (also called\narities) of the function.\n\nOften this is a mistake in your code, and it is a good idea to correct\nthe erroneous function call.  However, there are some projects with\nunit tests that intentionally make such calls, to verify that an\nexception is thrown.\n\nSome libraries explicitly set the `:arglists` metadata on their public\nfunctions for documentation purposes, because `:arglists` are what is\nshown by `doc` in the REPL.  This `:arglists` metadata is also used by\nEastwood to determine whether a function is being called with a wrong\narity, so such functions can lead to incorrect warnings from Eastwood.\nThis is known to affect several functions in\n[`java.jdbc`](https://github.com/clojure/java.jdbc) 0.3.x, the\n[Midje](https://github.com/marick/Midje) test library, and functions\ncreated with the [Hiccup](https://github.com/weavejester/hiccup)\nlibrary's macro `defelem`.\n\nYou can create a [config\nfile](#eastwood-config-files) for Eastwood that specifies the arglists\nto use for this linter.  An example for the function `query` in the\n[`java.jdbc`](https://github.com/clojure/java.jdbc) Clojure contrib\nlibrary is given below, copied from Eastwood's built-in config files\nthat it uses by default.  The value of the `:arglists-for-linting` key\nis a list of all argument vectors taken by the function, as the\nargument vectors are given in the function definition, not as modified\nvia metadata.\n\n```clojure\n(disable-warning\n {:linter :wrong-arity\n  :function-symbol 'clojure.java.jdbc/query\n  :arglists-for-linting\n  '([db sql-params \u0026 {:keys [result-set-fn row-fn identifiers as-arrays?]\n                      :or {row-fn identity\n                           identifiers str/lower-case}}])\n  :reason \"clojure.java.jdbc/query uses metadata to override the default value of :arglists for documentation purposes.  This configuration tells Eastwood what the actual :arglists is, i.e. would have been without that.\"})\n```\n\n\u003c/details\u003e\n\n### `:bad-arglists`\n\n#### Function/macro `:arglists` metadata that does not match the number of args it is defined with\n\n\u003cdetails\u003e\n\n\u003c!-- \n\nTBD: Give examples of function/macro definitions from Clojure and\nother libraries that will cause this warning, and some that will not,\neven though they explicitly specify a value for :arglists.\n\nTBD: Perhaps also give this example.  Is it possible for Eastwood to\never warn about a function defined in this way?  I am guessing it\nwould not be practical to do so, and whatever :arglists is specified\nwill never cause a :bad-arglists warning, but verify that.\n\n```clojure\n(def\n ^{:tag Boolean\n   :doc \"Returns false if (pred x) is logical true for every x in\n  coll, else true.\"\n   :arglists '([pred coll])\n   :added \"1.0\"}\n not-every? (comp not every?))\n```\n\n--\u003e\n\nThis linter was created because of the belief that it is better if\nthe value of `:arglists` for vars accurately represents the number of\narguments that can be used to call the function/macro, as opposed\nto some other thing used purely for documentation purposes.\n\nIt is true that even Clojure itself does not conform to this\nrestriction.  For example, the arglists of `defn`, `defmacro`, and\nseveral other macros override `:arglists` for purposes of clearer\ndocumentation.  However, all but these few exceptional macros\n\nOther facts supporting this belief are:\n\nThe value of metadata key :arglists is set automatically by macros\nlike defn and defmacro.\n\nThe Clojure compiler uses these arglists to determine things like\nthe type of the return value of a function call.\n\nIt would be nice if Eastwood (in particular its :wrong-arity\nlinter) and other Clojure development tools could rely upon\n:arglists matching the actual arities of the function or macro that\nhave been defined.\n\n\u003c/details\u003e\n\n### `:wrong-ns-form`\n\n#### ns forms containing incorrect syntax or options\n\n\u003cdetails\u003e\n\nClojure will accept and correctly execute `ns` forms with references\nin vectors, as shown in this example:\n\n```clojure\n(ns clojure.tools.test-trace\n  [:use [clojure.test]\n        [clojure.tools.trace]]\n  [:require [clojure.string :as s]])\n```\n\nHowever, Clojure does this despite the documentation of the `ns` macro\nshowing only parentheses around references.  The `tools.namespace`\nlibrary ignores references unless they are enclosed in parentheses,\nthus leading Eastwood and any other software using `tools.namespace`\nto detect incomplete dependencies between namespaces if they are\nenclosed in square brackets.  Thus Eastwood warns about all such\nreferences.\n\nEastwood also warns about ns forms:\n\n* if more than one `ns` form is found in a file\n* if a reference begins with anything except one of the documented\n  keywords `:require`, `:use`, `:import`, `:refer-clojure`, `:load`,\n  `:gen-class`\n* if a reference contains flag keywords that are not one of the\n  documented flags `:reload`, `:reload-all`, or `:verbose`\n* if a reference contains a valid flag keyword, because typically\n  those are only used during interactive use of `require` and `use`\n* if a `:require` or `:use` is followed by a list with only 1 item in\n  it, e.g. `(:require (eastwood.util))`.  This is a prefix list with\n  only a prefix, and no libspecs, so it does not do anything.\n* if a `:require` libspec has any of the option keys other than the\n  documented ones of `:as` and `:refer`.  Even though it is not\n  documented, Clojure's implementation of `require` correctly handles\n  options `:exclude` and `:rename`, if `:refer` is also used, so\n  Eastwood will not warn about these if `:refer` is present.\n* if a `:use` libspec has any option keys other than the documented\n  ones `:as` `:refer` `:exclude` `:rename` `:only`.\n* if any of the libspec option keys are followed by a value of the\n  wrong type, e.g. if `:refer` is followed by anything other than a\n  list of symbols or `:all`.\n\nNo warning is given if a prefix list is contained within a vector.\nClojure processes prefix lists in vectors, and `tools.namespace`\nrecognizes them as dependencies as Clojure does.  It is also somewhat\ncommon in the many Clojure projects on which Eastwood is tested.\n\n\u003c/details\u003e\n\n### `:wrong-pre-post`\n\n#### function has preconditions or postconditions that are likely incorrect\n\n\u003cdetails\u003e\n\nPreconditions and postconditions that throw exceptions if they are\nfalse can be specified for any Clojure function by putting a map after\nthe function's argument vector, with the key `:pre` for preconditions,\nor `:post` for postconditions, or both.  The value of these keys\nshould be a vector of expressions to evaluate, all of which are\nevaluated at run time when the function is called.  For example:\n\n```clojure\n(defn square-root [x]\n  {:pre [(\u003e= x 0)]}\n  (Math/sqrt x))\n\n;; AssertionError exception thrown when called with negative number\nuser=\u003e (square-root -5)\n\nAssertionError Assert failed: (\u003e= x 0)  user/square-root (file.clj:38)\n```\n\nIt is an easy mistake to forget that the conditions should be a vector\nof expressions, and to give one expression instead:\n\n```clojure\n(defn square-root [x]\n  {:pre (\u003e= x 0)}     ; should be [(\u003e= x 0)] like above\n  (Math/sqrt x))\n\n;; No exception when called with negative number!\nuser=\u003e (square-root -5)\nNaN\n```\n\nIn this case, Clojure does not give any error or warning when defining\n`square-root`.  It treats the precondition as three separate assertion\nexpressions: `\u003e=`, `x`, and `0`, each evaluated independently when the\nfunction is called.  Every value in Clojure is logical true except\n`nil` and `false`, so unless you call `square-root` with an argument\nequal to one of those values, all three of those expressions evaluate\nto logical true, and no exceptions are thrown.\n\nThe `:warn-pre-post` linter will warn about any precondition or\npostcondition that is not enclosed in a vector.  Even if you do\nenclose it in a vector, the linter will check whether any of the\nconditions appear to be values that are always logical true or always\nlogical false.  For example:\n\n```clojure\n(defn non-neg? [x]\n  (\u003e= x 0))\n\n(defn square-root [x]\n  {:pre [non-neg?]}     ; [(non-neg? x)] would be correct\n  (Math/sqrt x))\n\n;; No exception when called with negative number!\nuser=\u003e (square-root -5)\nNaN\n```\n\nHere Clojure also gives no warning or error.  The assert expression it\nevaluates is the value of `non-neg?` -- not the value when you call\n`non-neg?` with the argument `x`, but the value of the Var `non-neg?`.\nThat value is a function, and neither `nil` nor `false`, so logical\ntrue.\n\n\u003c/details\u003e\n\n### `:suspicious-test`\n\n#### Tests using `clojure.test` that may be written incorrectly.\n\n\u003cdetails\u003e\n\nIt is easy to misunderstand or forget the correct arguments to\n`clojure.test`'s `is` macro, and as a result write unit tests that do\nnot have the desired effect.  The `:suspicious-test` linter warns\nabout some kinds of tests that appear to be incorrect.\n\nThe form of correct tests written using `clojure.test`'s `is` macro\nare as follows:\n\n```clojure\n(is expr)\n(is expr message-string)\n(is (thrown? ExceptionClass expr1 ...))\n(is (thrown? ExceptionClass expr1 ...) message-string)\n(is (thrown-with-msg? ExceptionClass regex expr1 ...))\n(is (thrown-with-msg? ExceptionClass regex expr1 ...) message-string)\n```\n\nHere are some examples of tests that are not quite one of these forms,\nbut will silently pass.  The `:suspicious-test` linter will warn about\nall of them, but it may take some thought to learn how to correct the\ntest.\n\n```clojure\n(is [\"josh\"] names)    ; warns that first arg is a constant\n;; Any values except nil or false are treated as logical true in if\n;; conditions, so the test above will always pass.  Probably what was\n;; intended was:\n(is (= [\"josh\"] names))   ; probably intended\n\n\n(is (= #{\"josh\"}) (get-names x))   ; warns that second arg is not a string\n;; The warning message is true, but perhaps misleading.  It appears\n;; that the author intended to compare the set against the return\n;; value of get-names, but the extra parens are legal Clojure.  (= x)\n;; always returns true.\n(is (= #{\"josh\"} (get-names x)))   ; probably intended\n\n\n(is (= [\"josh\"] names) (str \"error when testing with josh and \" names))\n;; This linter has a special case that if the 2nd arg to 'is' is a\n;; form beginning with str, format, or a few other macros and\n;; functions commonly used to return strings, it will not issue a\n;; warning.  It does this with the assumption that this symbol has not\n;; been redefined to return something other than a string.\n\n\n(deftest test1\n  (= 5 (my-func 1))       ; warns that = expr occurs directly inside deftest\n  (contains? #{2 4 6} 4)) ; similar warning for contains? or any 'predicate'\n                          ; function in clojure.core\n;; The = and contains? expressions above will be evaluated during\n;; testing, but whether the results are true or false, the test will\n;; pass.\n(deftest test1\n  (is (= 5 (my-func 1)))        ; probably intended\n  (is (contains? #{2 4 6} 4)))\n\n\n(is (thrown? Throwable #\"There were 2 vertices returned.\"\n             (expr-i-expect-to-throw-exception)))\n;; The above warns that the second arg to thrown? is a regex, but that\n;; (is (thrown? ...)) ignores this regex.  Why is it ignored?  Because\n;; thrown? can take any number of expressions.  If any of them is a\n;; regex, it is evaluated, and then Clojure goes on to evaluate the\n;; other expressions.  The developer probably intended to use\n;; thrown-with-msg? so that not only is it verified that an exception\n;; is thrown, but also that the message in the exception matches the\n;; given regex.\n(is (thrown-with-msg? Throwable #\"There were 2 vertices returned.\"\n                      (expr-i-expect-to-throw-exception)))\n```\n\n\u003c/details\u003e\n\n### `:suspicious-expression`\n\n#### Suspicious expressions that appear incorrect, because they always return trivial values.\n\n### `:constant-test`\n\n#### A test expression always evaluates as true, or always false\n\n\u003cdetails\u003e\n\nWarn if you have a test expression in `if`, `cond`, `if-let`,\n`when-let`, etc. that is obviously a constant, or it is a literal\ncollection like a map, vector, or set that always evaluates as true.\n\nFor example:\n\n```clojure\n;; These all cause :constant-test warnings, because the test condition\n;; is a compile-time constant.\n(if false 1 2)\n(if-not [nil] 1 2)\n(when-first [x [1 2]] (println \"Goodbye\"))\n\n;; Even though Eastwood knows that the test condition is not a compile\n;; time constant here, it is a map, which always evaluate to logical\n;; true in a test condition.\n(defn foo [x]\n  (if {:a (inc x)} 1 2))\n```\n\nThe blanket approach to disabling all `:constant-test` warnings is to\nuse the `:exclude-linters` keyword in the Eastwood options map, or\nfrom Leiningen you can merge the following into your `project.Clj` or\n`$HOME/.lein/profiles.clj` file:\n\n```clojure\n:eastwood {:exclude-linters [:constant-test]}\n```\n\nStarting with Eastwood version 0.2.1, the more surgical approach is to\nadd expressions to a [config file](#eastwood-config-files)\nto disable these warnings, only when they occur within particular\nmacro expansions.  Search those config files for `:constant-test` to\nfind examples.\n\nIt is common across Clojure projects to use `:else` as the last\n'always do this' case at the end of a `cond` form.  It is also fairly\ncommon to use `true` or `:default` for this purpose, and Eastwood will\nnot warn about these.  If you use some other constant in that\nposition, Eastwood will warn.\n\nIt is somewhat common to use `(assert false \"msg\")` to throw\nexceptions in Clojure code.  This linter has a special check never to\nwarn about such forms.\n\n\u003c/details\u003e\n\n### `:unused-meta-on-macro`\n\n#### Metadata on a macro invocation is ignored by Clojure\n\n\u003cdetails\u003e\n\nWhen you invoke a macro and annotate it with metadata, in most cases\nthat metadata will be discarded when the macro is expanded, unless the\nmacro has been written explicitly to use that metadata.\n\nAs a simple example, the macro `my-macro` below will have all metadata\ndiscarded any time it is invoked:\n\n```clojure\n(require 'clojure.java.io)\n(import '(java.io Writer StringWriter))\n\n(defn my-fn [x]\n  (clojure.java.io/writer x))\n\n;; Example behavior below is for Clojure 1.5.0 through 1.7.0 alphas,\n;; at least.\n(defmacro my-macro [x]\n  (if (\u003e= (compare ((juxt :major :minor) *clojure-version*) [1 5])\n          0)\n    `(my-fn ~x)\n    'something-else))\n\n;; No metadata here, so nothing to lose, and no Eastwood warning.\n;; .close call will give reflection warning, though.\n(.close (my-macro (StringWriter.)))\n\n;; All metadata is discarded, including type tags like ^Writer, which\n;; is just a shorthand for ^{:tag Writer}.  Clojure will give a\n;; reflection warning, which is mightily confusing if you are not\n;; aware of this issue.  Eastwood will warn about it.\n(.close ^Writer (my-macro (StringWriter.)))\n```\n\nIf your purpose for annotating a macro invocation with metadata is to\ntype hint it, to avoid reflection in a Java interop call, you can work\naround this behavior by binding the macro invocation return value to a\nsymbol with `let`, and type hint that symbol.  For example:\n\n```clojure\n;; No reflection warning from Clojure, and no warning from Eastwood,\n;; for this.\n(let [^Writer w (my-macro (StringWriter.))]\n  (.close w))\n```\n\nA Clojure ticket has been filed for this behavior:\n[CLJ-865](http://dev.clojure.org/jira/browse/CLJ-865).  However, most\nways of changing it would change the behavior of at least some\nexisting Clojure code, so it seems unlikely to change.  Hence, this\nEastwood linter to alert people unaware of the behavior.\n\nMost Java interop forms are macro invocations, expand like them, and\nthus lose any metadata annotating their invocations.  However, there\nare special cases in the Clojure compiler where such Java interop\nforms will have `:tag` type hint metadata preserved for them.\nEastwood will warn if you try to use metadata on such a Java interop\nform that is discarded by the compiler.\n\nJava interop forms that remove _all_ metadata on them, even type\nhints:\n\n* constructor calls - `(ClassName. args)`\n\nJava interop forms that remove all metadata, except they explicitly\npreserve type hints:\n\n* class method calls - `(ClassName/staticMethod args)`\n* class field access - `(ClassName/staticField)`\n* instance method calls - `(.instanceMethod obj args)`\n* instance field access - `(.instanceField obj)`\n\nJava interop forms that are not macroexpanded, and thus do not lose\nany metadata annotating them:\n\n* constructor calls beginning with `new` - `(new ClassName args)`\n* calls beginning with a `.` (not `.close`, but just a `.` by itself) - `(. x close)`\n\nClojure's `clojure.core/fn` macro uses the hidden `\u0026form` argument to\nall Clojure macros to explicitly preserve the metadata on any `(fn\n...)` forms.  Eastwood has a special case not to warn about those\ncases.\n\n\u003c/details\u003e\n\n### `:unused-ret-vals`\n\n#### Unused values, including unused return values of pure functions, and some others functions where it rarely makes sense to discard its return value.\n\n\u003cdetails\u003e\n\nThe variant `:unused-ret-vals-in-try` is also documented here.\n\nValues which are unused are sometimes a sign of a problem in your\ncode.  These can be constant values, values of locally bound symbols\nlike let symbols or function arguments, values of vars, or return\nvalues of functions.\n\n```clojure\n(defn unused-val [a b]\n  a b)   ; b is returned.  a's value is ignored\n```\n\nCalling a side-effect-free function in a place where its return value is not used\nis likely to be a mistake, and Eastwood issues warnings for this.\n\n```clojure\n(defn unused-ret-val [k v]\n  (assoc {} k v)   ; return value of assoc is discarded\n  [k v])           ; [k v] is the only return value of the function\n```\n\nThere are many Clojure functions that are not pure functions, but for\nwhich it is probably a mistake to discard its return value.  For\nexample, `assoc!`, `rand`, and `read`.  Eastwood warns about these,\ntoo.\n\nDiscarding the return value of a lazy function such as `map`,\n`filter`, etc. is almost certainly a mistake, and Eastwood warns about\nthese.  If the return value is not used, these functions do almost\nnothing, and never call any functions passed to them as args, whether\nthose functions have side effects or not.\n\n```clojure\n;; This use of map calls print 4 times, because the REPL will print\n;; the return value of anything you evaluate in it, and thus force its\n;; evaluation.\nuser=\u003e (map print [1 2 3 4])\n(1234nil nil nil nil)\n\n;; The call to foo1 below will never call print, because nothing is\n;; forcing the evaluation of the return value of the lazy function map\nuser=\u003e (defn foo1 [coll]\n  #_=\u003e   (map print coll)\n  #_=\u003e   (count coll))\n#'user/foo1\nuser=\u003e (foo1 [1 2 3 4])\n4\n```\n\nThere are many Clojure functions that take other functions as\narguments.  These are often called higher order functions, or HOFs.\nSome of these HOFs are 'conditionally pure', meaning that if the\nfunctions passed as arguments are pure, then so is the HOF.  For\nexample, `mapv`, `group-by`, `every?`, and `apply` are conditionally\npure HOFs (and none of them are lazy).\n\nEastwood warns about discarding the return value of a conditionally\npure non-lazy HOF.  It is not sophisticated enough to check whether\nthe function arguments to the HOF are non-pure, e.g. it will warn\nabout a case like `(mapv print args)` if the return value is\ndiscarded, even though a person can easily see that discarding the\nreturn value still causes the side effects of `print` to occur.  As a\nspecial case, Eastwood only warns about the return value of `apply`\nbeing discarded based upon the properties of the function passed as\nits first argument, so `(apply print args)` will not cause a warning\nbecause `print` is known by Eastwood to have side effects.\n\nIt is not commonly done, but it can be useful to invoke what we have\ncalled a pure function, even if its return value is discarded.  The\nonly reason to do so (known to this author) is when the 'pure'\nfunction can throw an exception for some argument values judged to be\ninvalid, and you want to determine whether your data is valid by\ncalling the pure function and catching an exception if it is thrown.\nFor example, `str` can throw an exception if the value passed to it is\nunprintable.\n\nTechnically, a function that can throw an exception is not really pure\nin the mathematical sense of the term.  However, it is common to refer\nto it as a pure function if the only thing 'unpure' about it is the\npossibility of throwing an exception, since in most circumstances it\nis pure.\n\nIf you use `clojure.test`, this warning can also occur if such an\nexpression is evaluated in an `(is (thrown? ThrowableType\n(expression)))`.  This is another case of an expression's return value\nbeing discarded, in the expansion of the `is` macro.  The expression\nis being evaluated only to see if it will throw an exception.\n\nWhen such a discarded return value occurs directly within the body of\na `try` form, it is warned about with a linter having a different\nname, `:unused-ret-vals-in-try`.  The detection of an unused return\nvalue being done within a `try` form is done after macro expansion.\nThus since the `(is ...)` forms of `clojure.test` macro expand into\ntry blocks, unused return values _directly_ in their bodies will be\nreported by the `:unused-ret-vals-in-try` linter.  You can exclude\nthis linter, but keep `:unused-ret-vals`, or vice versa, if one or the\nother linter gives too many false warnings for your code.\n\nImplementation note: Eastwood does not automatically determine whether\na function is pure, conditionally pure, a HOF, etc.  All of these\nproperties were determined by manual inspection and recorded in a map\nof data about Clojure core functions.\n\n\u003c/details\u003e\n\n### `:local-shadows-var`\n\n#### A local name, e.g. a function arg, let binding, or record field name, has the same name as a global Var, and is called as a function\n\n\u003cdetails\u003e\n\nMany functions in `clojure.core` have names that you might like to use\nas local names, such as function arguments or let bindings.  This is\nnot necessarily a mistake, and Clojure certainly allows it, but it is\neasy to do so and accidentally introduce a bug.\n\nFor example, below the intent was to call `clojure.core/count` on the\ncollection `data`, but instead the `let` binds a value to `count`, and\nthat value is called as a function instead (or at least Clojure tries\nto call it as a function):\n\n```clojure\n(let [{count :count\n       data  :data} (fetch-data)\n      real-count (count data)]\n  ... )\n```\n\nIt is very common in Clojure code to 'shadow' the names of global Vars\nlike `name`, `list`, `symbol`, etc., so the `:local-shadows-var`\nlinter does not warn every time you use such a local name.  It only\ndoes so if:\n\n* The name is used as the first position in a form, as for a function\n  call, and\n* Eastwood cannot prove that the value bound to the name is a\n  function.\n\nFor example, this will not cause a warning, because it is assumed that\nthe developer has intentionally used the name `replace` as a locally\ndefined function.\n\n```clojure\n(let [replace #(str (biginteger %))]\n  (println (replace 5)))\n```\n\nThe following _will_ cause a warning, because Eastwood's analysis is\nnot sophisticated enough to determine that the value bound to\n`replace` is a function.\n\n```clojure\n(let [replace (comp str biginteger)]\n  (println (replace 5)))\n```\n\nThe following example will not cause a warning, because even though\n`pmap` is determined to have a non-function value, Eastwood does not\n'know' that the function call to `map` will use `pmap`'s value as a\nfunction.\n\n```clojure\n(let [pmap {:a 1 :b 2}]\n  (println (map pmap [1 2 3])))\n```\n\nEastwood also warns if a field of a Clojure record is called as a\nfunction, where there is a Var visible with the same name.\n\nNo matter what kind of local symbol is shadowing a Var, you can force\nuse of the Var by qualifying it with a namespace, or an alias of a\nnamespace as created by `:as` in a `require` form.\n\n\u003c/details\u003e\n\n### `:wrong-tag`\n\n#### An incorrect type tag for which the Clojure compiler does not give an error\n\n\u003cdetails\u003e\n\nYou can use a type tag on a Var name, like in the examples below.\nThis does not force the type of the value assigned to the Var, but\nClojure does use the type tag to avoid reflection in Java interop\ncalls where the Var name is used as an argument.\n\n```clojure\n;; Correct primitive/primitive-array type hints on Vars\n(def ^{:tag 'int} my-int -2)\n(def ^{:tag 'bytes} bytearr1 (byte-array [2 3 4]))\n(defn ^{:tag 'boolean} positive? [x] (\u003e x 0))\n```\n\nHowever, the following examples cause Clojure to use the values of the\nfunctions `clojure.core/int`, `clojure.core/bytes`, and\n`clojure.core/boolean` as (incorrect) type tags.  They will not help\nClojure avoid reflection in Java interop calls.  Clojure gives no\nerrors or warnings for such type hints, but Eastwood will.  This\nhappens because the Clojure compiler `eval`s metadata applied to a Var\nbeing `def`d, as documented [here](http://clojure.org/special_forms).\n\n```clojure\n;; Incorrect primitive/primitive-array type hints on Vars, for which\n;; Eastwood will warn\n(def ^int my-int -2)\n(def ^bytes bytearr1 (byte-array [2 3 4]))\n(defn ^boolean positive? [x] (\u003e x 0))\n```\n\nFor Java classes, it is correct to use type tags on Vars like in these\nexamples:\n\n```clojure\n;; Correct Java class type hints on Vars\n(def ^Integer my-int -2)\n(defn ^Boolean positive? [x] (\u003e x 0))\n(defn ^java.util.LinkedList ll [coll] (java.util.LinkedList. coll))\n\n;; For type tags on the Var name, you may even avoid fully qualifying\n;; the name, as long as you have imported the class.  Unlike some\n;; examples below with type tags on the argument vector, this does not\n;; cause problems for Clojure.\n(defn ^LinkedList l2 [coll] (java.util.LinkedList. coll))\n```\n\nYou can define functions that take primitive long or double values as\narguments, or that return a primitive long or double as its return\nvalue, as shown in the examples below.  Note that the return type tag\nmust be given immediately before the argument vector, _not_ before the\nname of the function.\n\n```clojure\n;; correct primitive type hints on function arguments and return value\n(defn add ^long [^long x ^long y] (+ x y))\n(defn reciprocal ^double [^long x] (/ 1.0 x))\n```\n\nClojure will give a compilation error with a clear message if you\nattempt to use any primitive type besides `long` or `double` in this\nway.\n\nYou can also type hint function arguments and return values with Java\nclass names.\n\nSuch type hints on function arguments can help avoid reflection in\nJava interop calls within the function body, and it does not matter\nwhether such type hints use fully qualified Java class names\n(e.g. `java.util.LinkedList`) or not (e.g. `LinkedList`), although\nusing the version that is not fully qualified only works if it is in\nthe `java.lang` package, or you have imported the package into the\nClojure namespace.\n\n#### `:wrong-tag` warnings in uses of `extend-type` and `extend-protocol` macro\n\n\n`extend-type` and `extend-protocol` convenience macros take the class\nname you specify and propagate them as type tags on the first argument\nof all functions.  This is handy, as long as the class name is a valid\ntype tag, as in this example:\n\n```clojure\n(defprotocol MyType\n  (get-type [x]))\n\n;; A more interesting example would avoid reflection only because of\n;; the auto-propagated type tags on the argument m.  Better example\n;; welcome.\n\n(extend-protocol MyType\n  Long\n  (get-type [m] :long)\n  Double\n  (get-type [m] :double))\n\n;; The extend-protocol expression above becomes the following after\n;; macro expansion, with valid type tags ^Long and ^Double.\n\n(do\n  (clojure.core/extend Long\n    MyType\n    {:get-type (fn ([^{:tag Long} m] :long))})\n  (clojure.core/extend Double\n    MyType\n    {:get-type (fn ([^{:tag Double} m] :double))}))\n\n(get-type 5)\n;; =\u003e :long\n\n(get-type 5.3)\n;; =\u003e :double\n```\n\n\nHowever, if you try to use `extend-type` or `extend-protocol` with an\nexpression that evaluates to a class at run time, e.g. `(Class/forName\n\"[D\")` as the type, most things will work correctly, but it will also\nexpand to code that has that expression as a type tag on the first\nargument of all functions.  That expression is not a valid type tag.\nClojure silently ignores such type tags, so there are no errors or\nwarnings during compilation.  Since the invalid type tag is ignored,\nyou will be disappointed if you were relying on it to avoid\nreflection.\n\nNote: `(Class/forName \"[D\")` evaluates to the Java class for an array\nof primitive doubles.  In places where you want to use such a type as\na type tag, you can use `^doubles` in Clojure.  However, that will not\nwork as an argument to `extend` or its variants.\n\n```clojure\n(defprotocol PGetElem\n  (get-elem [m idx]))\n\n;; This will cause reflection on the aget call, because m has an\n;; invalid, ignored type tag of (Class/forName \"[D\").  Eastwood will\n;; give a :wrong-tag warning on m.\n\n(extend-protocol PGetElem\n  (Class/forName \"[D\")\n    (get-elem [m idx] (aget m idx)))\n\n;; This also causes reflection on the aget call, because the ^doubles\n;; type tag is replaced by the invalid, ignored type tag when\n;; extend-protocol is macroexpanded.  Eastwood will give a :wrong-tag\n;; warning on m.\n\n(extend-protocol PGetElem\n  (Class/forName \"[D\")\n    (get-elem [^doubles m idx] (aget m idx)))\n\n;; No reflection here, because the valid type hint ^doubles is inside\n;; of the aget call, where extend-protocol does not overwrite it.\n;; Eastwood will give a :wrong-tag warning on m.\n\n(extend-protocol PGetElem\n  (Class/forName \"[D\")\n    (get-elem [m idx] (aget ^doubles m idx)))\n\n;; You will always get an Eastwood :wrong-tag warning if you use a\n;; run-time evaluated expression as a type in extend-protocol or\n;; extend-type.  You can suppress Eastwood's warning, or instead use\n;; the function extend.\n\n;; This is the only version that both (a) avoids reflection, and (b)\n;; Eastwood will not warn about.  It calls the function extend, and\n;; uses a correct type tag ^doubles on the first argument.  You could\n;; also put the type tag inside of the aget call if you prefer.\n\n(extend (Class/forName \"[D\")\n PGetElem\n {:get-elem\n  (fn ([^doubles m idx]\n    (aget m idx)))})\n```\n\nSee Clojure ticket\n[CLJ-1308](http://dev.clojure.org/jira/browse/CLJ-1308).  Vote on it\nif you are interested in Clojure changing its implementation and/or\nmake its documentation more explicit.\n\n\u003c/details\u003e\n\n### `:unused-fn-args`\n\n#### Unused arguments of functions, macros, methods\n\n\u003cdetails\u003e\n\nThis linter is disabled by default, because it often produces a large\nnumber of warnings that are not errors.  You must explicitly enable it\nif you wish to see these warnings.\n\nWriting a function that does not use some of its arguments is not\nnecessarily a mistake.  In particular, it is common for multimethods\ndefined with `defmulti` to have a dispatch function that only uses\nsome of its arguments.\n\nHowever, Eastwood warns about such unused function arguments, to\nsignal to a developer that there might be a problem.\n\nEastwood will not issue an `:unused-fn-args` warning for any argument\nwhose name begins with an underscore character, such as `_` or\n`_coll`.  It is a common convention in Clojure to use `_` as a name\nfor something that will not be used, and this convention is recognized\nand extended by Eastwood.  If you wish to enable the `:unused-fn-args`\nlinter, but have several unused arguments that are acceptable to you,\nconsider prepending an underscore to their names to silence the\nwarnings.\n\n\u003c/details\u003e\n\n### `:unused-locals`\n\n#### Symbols bound with `let` or `loop` that are never used\n\n\u003cdetails\u003e\n\nThis linter is disabled by default, because it often produces a large\nnumber of warnings, and even the ones that are correct can be\nannoying, and usually just vestigial code that isn't really a bug (it\nmight hurt your performance).\n\nHowever, for many projects tested, the warnings are correct.  If you\nwish to eliminate such symbols from your code using these warnings,\nyou must explicitly enable it.  You can specify it in `:add-linters`\non the command line or when invoked from a REPL.  To avoid specifying\nit each time when using Leiningen, you can merge a line like the\nfollowing into your `project.clj` file or user-wide\n`$HOME/.lein/profiles.clj` file.\n\n```clojure\n:eastwood {:add-linters [:unused-locals]}\n```\n\nIf you bind a value to a symbol in a `let` or `loop` binding, but then\nnever use that symbol, this linter will issue a warning for it.  You\ncan disable individual warnings by prepending the symbol name with a\n`_` character, as for the `:unused-fn-args` linter.\n\nThe warning occurs even if the `let` or `loop` is the result of\nexpanding a macro, so sometimes the source of the warning is not\nobvious.  If the symbol name looks like `somename__5103`, it is most\nlikely from a `let` introduced during macroexpansion.  Such warnings\nmay be split into a separate disabled-by-default linter in a future\nversion of Eastwood.\n\nDestructuring forms like `[x \u0026 xs]` and `{:keys [keyname1 keyname2\n...] :as mymap}` are macroexpanded into `let` forms, even when used as\nfunction arguments, and can thus cause these warnings.  You can\ndisable individual ones by prepending their names with a `_`\ncharacter.\n\nIt may seem a little odd to disable such destructuring warnings for\nkeys in a map, since it changes the name of the keyword in the\nmacroexpansion, and thus it will not be bound to the same value.  But\nhey, the value wasn't being used anyway, right?  Consider removing it\nfrom the list of keywords completely.\n\n\u003c/details\u003e\n\n### `:unused-namespaces`\n\n#### A namespace you use/require could be removed\n\n\u003cdetails\u003e\n\nThis linter is disabled by default, because it can be fairly noisy.\nYou must explicitly enable it if you wish to see these warnings.\n\nWarn if a namespace is given in an `ns` form after `:use` or\n`:require`, but the namespace is not actually used.  Thus the\nnamespace could be eliminated.\n\nThis linter is known to give false positives in a few cases.  See\nthese issues:\n\n* Issue [#192](https://github.com/jonase/eastwood/issues/192)\n* Issue [#210](https://github.com/jonase/eastwood/issues/210)\n\n\u003c/details\u003ev\n\n### `:unused-private-vars`\n\n#### A Var declared to be private is not used in the namespace where it is def'd\n\n\u003cdetails\u003e\n\nThis linter is disabled by default, but at least with a collection of\nprojects on which Eastwood is frequently tested, it is an uncommon\nwarning for most of them (Seesaw is an exception where it is common).\nYou must explicitly enable it if you wish to see these warnings.\n\nIf a Var is defined to be private using `^:private`, `^{:private\ntrue}`, `defn-`, etc., but is not used elsewhere in the same\nnamespace, it is likely to be dead code.  It is still possible to\nrefer to the Var in another namespace using syntax like\n`#'name.space/private-var-name`, but this is not checked for by this\nlinter.\n\nThis linter never warns for private Vars that also have `^:const` or\n`^{:const true}` metadata.  This is due to some uncertainty whether\nuses of such Vars can be reliably detected in the `tools.analyzer`\nASTs.\n\nIt will cause undesirable warnings in case like this, which have been\nseen in some namespaces:\n\n```clojure\n(defn- private-fn [x]\n  (inc x))\n\n(defmacro public-macro [y]\n  `(#'my.ns/private-fn ~y))\n```\n\nIt is not straightforward for Eastwood to determine from the ASTs that\nprivate-fn is used elsewhere in the namespace, since syntax quoting\nwith the backquote character causes the resulting code to not refer to\nthe Var directly, but to create a function that _only when evaluated_\ncontains `(var my.ns/private-fn)`.\n\n\u003c/details\u003e\n\n### `:unlimited-use`\n\n#### Unlimited `(:use ...)` without `:refer` or `:only` to limit the symbols referred by it.\n\n\u003cdetails\u003e\n\nAn `ns` statement like the one below will refer all of the public\nsymbols in the namespace `clojure.string`:\n\n```clojure\n(ns my.namespace\n  (:use clojure.string))\n```\n\nAny symbols you use from namespace `clojure.string` will typically\nhave no namespace qualifier before them, which is likely your reason\nfor using `use` instead of `require`.  This can make it difficult for\npeople to determine which namespace the symbols are defined in.  A\n`require` followed by `:refer` and a list of symbols makes it clearer\nto readers the origin of such symbols.  You can also put in an `:as\nstr` in the same `require` so you have an alias to prefix any other\nsymbols you need from the namespace:\n\n```clojure\n(ns my.namespace\n  (:require [clojure.string :as str :refer [replace join]]))\n```\n\nThe `:unlimited-use` linter will not warn about 'limited' `use`\nstatements, i.e. those with explicit `:only` or `:refer` keywords to\nlimit their effects, such as these:\n\n```clojure\n(ns my.namespace\n  (:use [clojure.string :as str :only [replace]]\n        [clojure.walk :refer [prewalk]]\n        [clojure [xml :only [emit]]]))\n```\n\nIn addition, since it is so common (and in my opinion, harmless) to do\nan unlimited use of namespace `clojure.test` in test files, this\nlinter never warns about `clojure.test`.\n\nFor an infrequently-changing namespace like `clojure.string`, the set\nof symbols referred by this `use` is pretty stable across Clojure\nversions, but even so, it only takes one symbol added to shadow an\nexisting symbol in your code to ruin your day.\n\n\u003c/details\u003e\n\n### `:non-dynamic-earmuffs`\n\n\u003cdetails\u003e\n\nVars marked `^:dynamic` should follow the \"earmuff\" naming convention, and vice versa:\n\n* `(def foo 42)` (OK: non-dynamic, non-earmuffed)\n* `(def ^:dynamic foo 42)` (NOK: dynamic, non-earmuffed)\n* `(def *foo* 42)` (NOK: earmuffed, non-dynamic)\n* `(def ^:dynamic *foo* 42)` (OK: dynamic, earmuffed)\n\n\u003c/details\u003e\n\n### `:boxed-math`\n\n#### Boxed math warnings from the Clojure compiler\n\n\u003cdetails\u003e\n\nSee: [`*unchecked-math*`](https://clojuredocs.org/clojure.core/*unchecked-math*)\n\nDisabled by default because it's not customary or necessarily justified to aim for a boxed-math-free codebase.\n\nNote that if enabling it, all code will be evaluated with a surrounding `*unchecked-math* :warn-on-boxed` binding,\nwhich not only enables the warnings but it actually affects the final code that will be emitted\n(although in minor ways, only concerned with unchecked math matters).\n\nGenerally this won't affect you in any way except in the case that you are invoking Eastwood in a REPL,\nsuch that namespaces re-compiled by Eastwood's analysis will be visible and used by your application.\n\n\u003c/details\u003e\n\n### `:performance`\n\n#### Performance warnings from the Clojure compiler\n\n\u003cdetails\u003e\n\nThe Clojure compiler optionally emits performance warnings related to the use of `case` and `recur` and their relationship with primitive numerics.\n\n\u003e Please refer to https://clojure.org/reference/java_interop for a guide on primive math\n(tldr: use `(long)`, or occasionally `^long` where it is permitted).\n\nEastwood wraps these warnings, enhancing them when needed (the reported file name can be misleading),\nrestricting them to _your project's_ source paths and allowing them to be omitted on a file/line basis.  \n\nThis linter is disabled by default because it's not customary or necessarily justified to address these warnings.\nFor some corner cases it might not be even possible (however the [`:ignored-faults`](https://github.com/jonase/eastwood#ignored-faults) would allow you to prevent that corner case from failing your build).\n\n\u003c/details\u003e\n\n### `:reflection`\n\n#### Reflection warnings from the Clojure compiler\n\n\u003cdetails\u003e\n\nAddressing reflection warnings systematically is a good idea for many reasons:\n\n* Performance will be improved\n* Performance will easier to measure\n  * Even assuming that JITs can emit optimizations akin to manual type hints, having one's code left unoptimized for an indefinite time (maybe forever, in your local JVM) makes it harder to accurately measure performance, as it can be potentially full of distractions caused by slow, reflective calls.\n* Code will be more maintainable, as anyone reading the code will know the class a given piece of code is dealing with\n  * e.g. some code may be dealing with a very unusual/specific Java class. By using a type hint, maintainers can quickly know of this class instead of having to reverse-engineer that info. \n* Increased compatibility with newer JDKs\n  * newer JDKs may emit warnings or even not work at all depending on reflective access.\n  * this has changed substantially how Clojure programmers deal with reflection - before it was more of an optimization only.\n* Increased compatibility with GraalVM native images [ref](https://www.graalvm.org/reference-manual/native-image/Reflection/)\n* Better integration with various Clojure tooling\n  * e.g. [compliment](https://github.com/alexander-yakushev/compliment) (used by CIDER) is able to perceive type hints and offer better completions accordingly.\n* They might be propagated downstream\n  * If you are a library or tooling author, reflective code you write will show up as warnings for your consumers.\n  * Consumers might be actually be negatively impacted in terms of performance - one never can know how other people use a given piece of code.\n  * Since consumers can't do anything to directly fix this, it's most considerate to avoid in advance any reflective calls. \n\nEastwood helps you systematically avoid reflection warnings by considering reflection warnings yet another lintable thing.\n\nIt generally doesn't matter whether a given ns uses `(set! warn-on-reflection ...)` - Eastwood analyses each top-level form with a `binding` overriding any surrounding choice.\n\nThe default behavior is only emitting warnings if the reflection happens inside your source paths or test paths: this way one doesn't have to pay a price for unrelated code.\n\nHowever if a third-party macro expands to reflective access within our source path, it will be reported.\nThis is because, in the end, one is creating reflective code in _one's_ codebase, which can be a severe problem and therefore should be fixed, even if it can take some extra effort. \n\nSibling linters such as `:wrong-tag` and `:unused-meta-on-macro` help guaranteeing that reflection is being addressed in a veridic way.\n\n\u003c/details\u003e\n\n### `:keyword-typos`\n\n#### Keywords that may have typographical errors\n\n\u003cdetails\u003e\n\nThis linter is disabled by default, because it often produces a large\nnumber of warnings that are not errors.  You must explicitly enable it\nif you wish to see these warnings.\n\nIf you use a keyword like `:frangible` in several places in your\nsource code, but then in one place you accidentally type `:frangable`\ninstead, that will likely lead to incorrect behavior of your program.\n\nThis linter cannot guarantee finding such misspelled keywords, but if\nthere is a keyword in your source code that appears only once, and is\nnearly the same spelling as keywords that appear elsewhere in the same\nsource file, this linter will warn about them.  It can of course\nreport keywords that are exactly what you intended them to be.\n\nAs implemented now, this linter only works if (a) there are no\nkeywords of the form `::ns-alias/name` in the file, or (b) the first\nexpression in the file is an `ns` expression, and the namespace\nremains the same throughout the file.  This is a common convention\nfollowed by most Clojure source code, and required by several other\nClojure development tools.\n\n\u003c/details\u003e\n\n## Ignored faults\n\nIf there are specific instances of linter faults that you need to supress\n(e.g. for making a CI build pass), you can use the `:ignored-faults` option.\n\nIt has the following shape:\n\n```clj\n;;linter-name            ns-name                target\n;;---                    ---                    ---\n{:implicit-dependencies {'example.namespace     [{:line 3 :column 2}]\n                         'another.namespace     [{:line 79}]\n                         'random.namespace      [{:line 89}, {:line 110}, {:line 543 :column 10}]} \n :unused-ret-vals       {'yet.another.namespace true}}\n```\n\nAn entry like `:implicit-dependencies {'example.namespace [{:line 3 :column 2}]` has the meaning\n\"the linter `:implicit-dependencies` should be ignored in line 3, column 2\".\n\nNote that the `target`s are expressed as vectors, since there may be multiple instances to ignore.\n\nThe following are acceptable `target`s:\n\n* `[{:line 1 :column 1}]`\n  * will only ignore a linter if line _and_ column do match\n* `[{:line 1}]`\n  * will match line, disregarding the column\n  * it's a bit more lenient than the previous syntax, while not too much\n* `true`\n  * will match any ocurrence within the given namespace, regardless of line/column\n  * this is the most lenient choce, which of course can create some false negatives.\n  * if passing `true`, you don't need to wrap it in a vector.\n\n\u003e Please, if encountering an issue in Eastwood, consider reporting it in addition to (or instead of) silencing it.\n\u003e This way Eastwood can continue to be a precise linter, having as few false positives as possible.\n\n## Ignoring linter sub `:kind`s\n\nA given linter may have different `:kind`s of emitted warnings. For example the `:suspicious-test` linter has the following kinds:\n\n\u003e `:first-arg-is-string, :first-arg-is-constant-true, :second-arg-is-not-string, :thrown-regex, :thrown-string-arg, :string-inside-thrown`\n\nThat `:kind` is reported to stdout when running Eastwood as a tool, and returned as data when invoking Eastwood programatically. \n\nYou can prevent a specific `:kind` from emitting warnings by using any of the following syntaxes:\n\n```clj\n;; simple pairs of [\u003clinter\u003e, \u003ckind\u003e]:\n:exclude-linters [[:suspicious-test :first-arg-is-constant-true], [:suspicious-test :thrown-regex]]\n;; or\n;; pairs of [\u003clinter\u003e, \u003cvector of kinds for that linter\u003e]:\n:exclude-linters [[:suspicious-test [:first-arg-is-constant-true :thrown-regex]]]\n\n;; You can mix and match both syntaxes.\n;; You can also mix them with single keywords which denote a whole linter to be omitted:\n:exclude-linters [:constant-test, [:suspicious-test :first-arg-is-constant-true]]\n```\n\nWith newer versions, Eastwood disables `[:suspicious-test :first-arg-is-constant-true]` by default.\n\nTo re-enable it, set `:exclude-linters` to `[]` or any custom value. Whatever value you provide will replace the default entirely.  \n\n## Changelog\n\nSee the [changes.md](https://github.com/jonase/eastwood/blob/master/changes.md) file.\n\n## For Eastwood developers\n\nTo be on the bleeding edge, install Eastwood in\nyour local Maven repository:\n\n    $ cd path/to/eastwood\n    $ lein with-profile -user,-dev,+eastwood-plugin install\n\nThen add `[jonase/eastwood \"1.4.3\"]` to\nyour `:plugins` vector in your `:user` profile, perhaps in your\n`$HOME/.lein/profiles.clj` file.\n\n\n## License\n\nCopyright (C) 2012-2023 Jonas Enlund, Nicola Mometto, and Andy Fingerhut\n\nDistributed under the Eclipse Public License, the same as Clojure.\n\nThe source code of the following libraries has been copied into\nEastwood's source code, and each of their copyright and license info\nis given below.  They are all distributed under the Eclipse Public\nLicense 1.0.\n\n\u003cdetails\u003e\n\n### core.cache\n\n[core.cache](https://github.com/clojure/core.cache)\n\nCopyright (c) Rich Hickey, Michael Fogus and contributors, 2012. 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.\n\n### core.memoize\n\n[core.memoize](https://github.com/clojure/core.memoize)\n\nCopyright (c) Rich Hickey and Michael Fogus, 2012, 2013. 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.\n\n### data.priority-map\n\nCopyright (C) 2013 Mark Engelberg\n\nDistributed under the Eclipse Public License, the same as Clojure.\n\n[data.priority-map](https://github.com/clojure/data.priority-map)\n\n### tools.analyzer\n\n[tools.analyzer](https://github.com/clojure/tools.analyzer)\n\nCopyright © 2013-2014 Nicola Mometto, Rich Hickey \u0026 contributors.\n\nDistributed under the Eclipse Public License, the same as Clojure.\n\n### tools.analyzer.jvm\n\n[tools.analyzer.jvm](https://github.com/clojure/tools.analyzer.jvm)\n\nCopyright © 2013-2014 Nicola Mometto, Rich Hickey \u0026 contributors.\n\nDistributed under the Eclipse Public License, the same as Clojure.\n\n### tools.namespace\n\n[tools.namespace](https://github.com/clojure/tools.namespace)\n\nCopyright © 2012 Stuart Sierra All rights reserved. The use and\ndistribution terms for this software are covered by the\n[Eclipse Public License 1.0] which can be found in the file\nepl-v10.html at the root of this distribution. By using this software\nin any fashion, you are agreeing to be bound by the terms of this\nlicense. You must not remove this notice, or any other, from this\nsoftware.\n\n[Eclipse Public License 1.0]: http://opensource.org/licenses/eclipse-1.0.php\n\n### tools.reader\n\n[tools.reader](https://github.com/clojure/tools.reader)\n\nCopyright © 2013-2014 Nicola Mometto, Rich Hickey \u0026 contributors.\n\nLicensed under the EPL. (See the file epl.html.)\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonase%2Feastwood","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonase%2Feastwood","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonase%2Feastwood/lists"}