Commit Graph

74 Commits

Author SHA1 Message Date
Joshua Clayton
1699c257c6
Bump version to 0.10.0.0 2019-10-29 20:45:23 -04:00
Joshua Clayton
f1f7382ae4
Update versions to enable installation via Cabal
What?
=====

This updates dependency requirements to enable compilation.
2019-10-29 20:32:54 -04:00
Joshua Clayton
514eb94e03
Bump version to 0.9.0.0 2018-08-28 20:55:54 -04:00
Joshua Clayton
2446faee64
Update copyright year to 2018 2018-08-28 20:52:52 -04:00
Joshua Clayton
30950ad00b
Update dependencies
What?
=====

This updates certain dependencies to ensure it can compile both via
Stack and Cabal (which impacts the ability to install via Homebrew).
2018-08-28 16:57:20 -04:00
Joshua Clayton
cd1b840368
Allow Stack to build the project and run the test suite
What?
=====

This bumps Stack dependencies and locks certain packages to ensure a
proper build.
2018-03-18 22:35:15 -04:00
Joshua Clayton
5c08c145a5
Extract app types 2017-05-02 10:25:59 -07:00
Joshua Clayton
0d9a89ae4b
Bump version to 0.8.0.0 2017-04-24 14:30:40 -07:00
Joshua Clayton
789d91b5d9
Bump years 2017-04-24 14:29:05 -07:00
Joshua Clayton
9300a1bc60
Configure default extensions (namely, OverloadedStrings) 2017-01-23 18:23:00 -05:00
Joshua Clayton
eddea2d65e
Bump version to 0.7.0.0 2017-01-12 08:38:00 -05:00
Joshua Clayton
8a16494a64
Update version dependencies for various packages
* Update the inflections package
* Better lock down megaparsec and cassava
2017-01-12 06:34:27 -05:00
Joshua Clayton
7d9c923bd1
Bump version to 0.6.1.1 2016-08-30 06:33:40 -04:00
Joshua Clayton
80aa7aa950
Ensure data/config.yml is distributed with the package
This resolves an issue where data/config.yml is unavailable with an
error similar to:

    /private/tmp/stack66398/unused-0.6.1.0/src/Unused/ResultsClassifier/Config.hs:22:23:
        Exception when trying to run compile-time code:
          data/config.yml: openBinaryFile: does not exist (No such file or directory)
        Code: FE.embedFile "data/config.yml"
        In the splice: $(FE.embedFile "data/config.yml")
2016-08-30 06:31:09 -04:00
Joshua Clayton
d81f32476d
Bump version to 0.6.1.0 2016-08-20 05:30:11 -04:00
Joshua Clayton
9cad495eb2
Conditionally import Data.Monoid.<> depending on version of base
Fixes #64
2016-08-20 05:22:51 -04:00
Joshua Clayton
fde9f69a64
Replace Cabal-managed config loading with FileEmbed
This uses the file-embed package and TemplateHaskell to load custom
configuration during compilation instead of loading it at runtime.
2016-08-18 17:59:12 -04:00
Joshua Clayton
77b887188d
Bump version to 0.6.0.1 2016-07-19 22:30:29 -04:00
Joshua Clayton
7e3b91dc24
Bump version to 0.6.0.0 2016-07-19 16:27:25 -04:00
Joshua Clayton
7fe32edc4d
Support projections-style transformations to reduce false-positives
Basic aliases (e.g. `admin?`/`be_admin`) can be represented easily with simple
wildcards, but more complex transformations require a different mechanism.

Instead of using `%s` to represent strings that can be replaced 1:1, this
introduces a syntax inspired by https://github.com/tpope/vim-projectionist, as
such:

    - name: Rails
      aliases:
      - from: "*Validator"
        to: "{snakecase}"

This would find `AbsoluteUriValidator` and also match `absolute_uri`, which
would be found if the validation was in use.

This currently supports the `camelcase` and `snakecase` transformations,
as well as no transformation.

Closes #18
2016-07-19 15:14:34 -04:00
Joshua Clayton
b852cff74c
Bump version to 0.5.0.2 2016-06-24 08:31:44 -04:00
Joshua Clayton
94bbd04f6a
Remove final -Werror setting 2016-06-24 08:31:14 -04:00
Joshua Clayton
f0c24682e4
Bump version to 0.5.0.1 2016-06-24 08:30:13 -04:00
Joshua Clayton
121775cbc6
Remove -O flag entirely for Hackage upload 2016-06-24 08:29:32 -04:00
Joshua Clayton
b0f8d7f620
Bump version to 0.5.0.0 2016-06-24 08:27:20 -04:00
Joshua Clayton
5d6ec8d611
Remove -Werror from compilation
To upload to hackage, -Wall -Werror cannot both be set. This can be
achieved by installing with stack's `--pedantic` flag.
2016-06-24 08:17:55 -04:00
Joshua Clayton
11ff583d3c
Convert from -O2 to -O 2016-06-24 08:15:57 -04:00
Joshua Clayton
240b5bbb19 Support digesting on Linux with md5sum
This introduces behavior searching for an available program to calculate
digests across directories. OS X ships with md5, but on *nix-based
systems, it's md5sum. The output is largely the same, apart from the
final digest calculation, which includes a "file path":

    da52a1a5d5a3c9672371746e4d32708a  -

This strips the trailing whitespace and dash:

    da52a1a5d5a3c9672371746e4d32708a

Closes #49
2016-06-23 23:11:32 -04:00
Joshua Clayton
1892f8c0ba Extract error headers 2016-06-23 22:44:23 -04:00
Joshua Clayton
b65de02efc Display recent git SHAs per token
This creates a new "list" output format that includes a certain number
of git SHAs per token. This allows for perusal of the most recent
changes for a given token to understand what changed.
2016-06-21 23:02:37 -04:00
Joshua Clayton
cfa194b936 Roll up App into a monad transformer stack
This introduces a monad transformer stack to cover our reader (options
from the CLI) and except (for handling failure cases, initially missing
tags or invalid config).

This ensures errors are bubbled up appropriately (and halt program
execution) and the Options are available in the correct locations within
the app.

This also separates options parsing (which remains in app/Main.) from
translating those options into the correctly executed runner and
generated output.
2016-06-16 06:12:29 -04:00
Joshua Clayton
85b6914f11 Bump version to 0.4.0.0 2016-06-10 07:05:58 -04:00
Joshua Clayton
764b21b798 Update Cabal category to CLI 2016-06-10 07:04:14 -04:00
Joshua Clayton
58e219eb2e Allow developer-authored configurations
This enables per-user and per-project configs, located in:

* ~/.unused.yml
* APP_ROOT/.unused.yml

Configurations stack upon each other, not replace; unused provides a
very base config, but additional configurations can be defined.

Per-user configs are best used to suit common types of projects at a
generic level. For example, a developer commonly working in Rails
applications might have a config at ~/.unused.yml for patterns like
Policy objects from Pundit, ActiveModel::Serializers, etc.

Per-project config would be less-generic patterns, ones where re-use
isn't likely or applicable.

See unused's global config:
https://github.com/joshuaclayton/unused/blob/master/data/config.yml

The structure is as follows:

    - name: Rails
      autoLowLikelihood:
        - name: Pundit
          pathStartsWith: app/policies
          pathEndsWith: .rb
          termEndsWith: Policy
          classOrModule: true
        - name: Pundit Helpers
          pathStartsWith: app/policies
          allowedTerms:
            - Scope
            - index?
            - new?
            - create?
            - show?
            - edit?
            - destroy?
            - resolve
    - name: Other Language
      autoLowLikelihood:
        - name: Thing
          pathEndsWith: .ex
          classOrModule: true

Name each item, and include an autoLowLikelihood key with multiple named
matchers. Each matcher can look for various formatting aspects,
including termStartsWith, termEndsWith, pathStartsWith, pathEndsWith,
classOrModule, and allowedTerms.
2016-06-10 06:16:41 -04:00
Joshua Clayton
5590f5fc4c Update cabalfile to reflect correct version
Version 0.3.0.0 was released in
9cc640aef747b9179e35104610bb869398df31ac; however, unused.cabal wasn't
updated.
2016-06-10 05:33:52 -04:00
Joshua Clayton
9bf9499e67 Ensure results work when no config can be loaded
Why?
====

If no config can be loaded correctly, unused should still function
correctly, albeit with likely more false positives.
2016-06-05 08:09:02 -04:00
Joshua Clayton
54e55c46a2 Add missing spec name to unused.cabal 2016-06-05 07:42:18 -04:00
Joshua Clayton
6ffb098b20 Initial support of aliases based on wildcard matching
Why?
====

Dynamic languages, and Rails in particular, support some fun method
creation. One common pattern is, within RSpec, to create matchers
dynamically based on predicate methods. Two common examples are:

* `#admin?` gets converted to the matcher `#be_admin`
* `#has_active_todos?` gets converted to the matcher `#have_active_todos`

This especially comes into play when writing page objects with predicate
methods.

This change introduces the concept of aliases, a way to describe the
before/after for these transformations. This introduces a direct swap
with a wildcard value (%s), although this may change in the future to
support other transformations for pluralization, camel-casing, etc.

Externally, aliases are not grouped together by term; however, the
underlying counts are summed together, increasing the total occurrences
and likely pushing the individual method out of "high" likelihood into
"medium" or "low" likelihood.

Closes #19.
2016-06-01 22:16:44 -04:00
Joshua Clayton
4dfd788318 Extract views to a Views module
Why?
====

View logic was scattered all over the place; this introduces a views
module to encapsulate any corresponding view work into one spot.
2016-05-27 06:11:52 -04:00
Joshua Clayton
0d2470815d Simplify parsing and caching of results
Why?
====

Parsec is overkill when all that's really needed is splitting on
semicolons and converting a string to a non-negative Int.

One side-effect of this is to convert the caching mechanism from flat
text to CSV, with cassava handling (de-)serialization.

Additional
==========

Introduce ReaderT to calculate sha once per cache interaction

Previously, we were calculating the fingerprint (SHA) for match results
potentially twice, once when reading from the cache, and a second time
if no cache was found. This introduces a ReaderT to manage cache
interaction with a single fingerprint calculation.

This also abstracts what's being cached to only care about the fact that
the data can be converted to/from csv.
2016-05-26 21:37:11 -04:00
Joshua Clayton
f618d8a796 Use .gitignore to determine files for fingerprinting a project
Why?
====

Because a .gitignore file captures a fair number of project-specific
directories and files to ignore, we can use this list to reduce the
number of files to look at when determining a fingerprint for a project.

Because the fingerprint should be based on files we care about changing,
the project-specific .gitignore is a great place to start.

This drastically reduces fingerprint timing - for larger projects, or
projects with a massive number of files (e.g. anything doing anything
significant with NPM and a front-end framework), this will help make
caching usable. For normal projects, this cuts fingerprint
calculation to 10%-20% of what it was previously.

Closes #38
2016-05-26 17:19:35 -04:00
Joshua Clayton
b7aefe66d0 Bump version to 0.2.0.0 2016-05-22 06:15:00 -04:00
Joshua Clayton
43edf288e2 Attempt to find and load tags automatically
Why?
====

Frequency of a tool's usage is determined by how easy it is to use the
tool. By having to pipe in ctags files all the time, and not provide any
guidance to the user, this program is merely a toy, since it's hard to
get right, and harder to explore.

This modifies the default behavior to look for a ctags file in a few
common locations, and lets the user choose a custom location if she so
chooses.

Resolves #35
2016-05-22 06:06:09 -04:00
Joshua Clayton
307dd2030f Introduce internal yaml configuration of auto low likelihood match handling
Why?
====

Handling low likelihood configuration was previously a huge pain,
because the syntax in Haskell was fairly terse. This introduces a yaml
format internally that ships with the app covering basic cases for
Rails, Phoenix, and Haskell. I could imagine getting baselines in here
for other languages and frameworks (especially ones I've used and am
comfortable with) as a baseline.

This also paves the way for searching for user-provided additions and
loading those configurations in addition to what we have here.
2016-05-21 05:34:18 -04:00
Joshua Clayton
44ab0a1435 Read unchanged results from the cache
At some point, this also needs to md5 the tags list itself and factor
that in (since if the tagging algorithm changes, and new tokens get
uncovered, it'd invalidate the cache)
2016-05-16 21:48:36 -04:00
Joshua Clayton
0e966c9302 Test Util.groupBy 2016-05-15 05:53:29 -04:00
Joshua Clayton
97f083fc2c Use regex in ag for simple words
Why?
====

ag supports using regular expressions for searches; however, the -Q
flag, which was previously always used, resulted in literal search
results.

By searching literal matches, it would potentially return too many
results. For example, with a `me` method in a controller, it'd match
words like `awesome` or `method`.

This introduces a check where, if the token being searched is only
composed of word characters (`[A-Za-z0-9_]`), it'll switch over to use
regular expressions with ag and surround the token with non-word matches
on either end. The goal here is to reduce false-positives in matches.
2016-05-14 08:14:54 -04:00
Joshua Clayton
bcbc1b6462 Allow search result grouping
Why?
====

Grouping results can be helpful to view information differently, e.g. to
see highest-offending files or to remove grouping entirely.

This introduces a flag to allow overriding the default group (two levels
of directory)
2016-05-14 06:36:01 -04:00
Joshua Clayton
a8a9d250e3 Parallelize search
Why?
====

Searching hundreds or thousands of tokens with ag can be slow; this
introduces parallel processing of search so results are returned more
quickly.
2016-05-13 14:46:23 -04:00
Joshua Clayton
2ec73ac3b3 Consolidate progress indicator handling 2016-05-13 14:18:23 -04:00