Coder Social home page Coder Social logo

kowainik / smuggler Goto Github PK

View Code? Open in Web Editor NEW
71.0 11.0 8.0 57 KB

🚣 Smuggle all imports

Home Page: https://kowainik.github.io/projects/smuggler

License: Mozilla Public License 2.0

Haskell 100.00%
haskell refactoring compiler-plugin imports source-plugin unused-imports

smuggler's Introduction

smuggler

smuggler-logo Hackage Build MPL-2.0 license

“So many people consider their work a daily punishment. Whereas I love my work as a translator. Translation is a journey over a sea from one shore to the other. Sometimes I think of myself as a smuggler: I cross the frontier of language with my booty of words, ideas, images, and metaphors.”

― Amara Lakhous, Clash of Civilizations Over an Elevator in Piazza Vittorio

Haskell Source Plugin which removes unused imports automatically.

How to use

Add smuggler to the dependencies of your project. Then add the following compiler options:

-fplugin=Smuggler.Plugin

Lovely addition to this package is that it automatically supports on-the-fly feature if you use it with ghcid. Smuggler doesn't perform file changes when there are no unused imports. So you can just run ghcid as usual:

ghcid --command='cabal repl'

For contributors

Requirements:

  • ghc-8.6.5
  • cabal >= 3.0 or stack >= 2.0

Cabal: How to build?

cabal update
cabal build

Stack: How to build?

stack build

Run tests

cabal test --enable-tests

smuggler's People

Contributors

chshersh avatar qoelet avatar vrom911 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

smuggler's Issues

Add tests for implicit imports

I would like to have two tests:

  1. When the implicit import is used and not deleted by smuggler
  2. When the implicit import is not used and got deleted by smuggler

Some infelicities

This is just the plugin I was looking for, and I have been giving it a whirl.

I used ghc 8.8.3 (by adjusting the cabal bounds).

-  build-depends:       base ^>= 4.12
+  build-depends:       base ^>= 4.13
   ghc-options:         -Wall
                        -Wincomplete-uni-patterns
                        -Wincomplete-record-updates
@@ -62,8 +62,8 @@ library
   build-depends:       bytestring ^>= 0.10
                      , containers >= 0.5 && < 0.7
                      , filepath ^>= 1.4
-                     , ghc ^>= 8.6.0
-                     , ghc-exactprint ^>= 0.6
+                     , ghc ^>= 8.8.3
+                     , ghc-exactprint ^>= 0.6.2
                      , unordered-containers ^>= 0.2.7

This doesn't compile, so I also have to

diff --git a/src/Smuggler/Loc.hs b/src/Smuggler/Loc.hs
index 6580578..b2ae1f2 100644
--- a/src/Smuggler/Loc.hs
+++ b/src/Smuggler/Loc.hs
@@ -4,8 +4,7 @@ module Smuggler.Loc
        , unL
        ) where
 
-import SrcLoc (GenLocated (L), Located, SrcSpan (RealSrcSpan), srcSpanStartCol, srcSpanStartLine,
-               unLoc)
+import SrcLoc (GenLocated (L), Located, SrcSpan (RealSrcSpan), srcSpanStartCol, srcSpanStartLine)
 
 -- | Returns location in the way of @line:col@.
 showLoc :: SrcSpan -> String
@@ -18,4 +17,4 @@ showL name showA (L l nm) = "(" ++ showLoc l ++ name ++ showA nm ++ ")"
 
 -- | Shorter synonim for 'unLoc'.
 unL :: GenLocated l e -> e
-unL = unLoc
+unL (L _ e) = e

Perhaps the answer is to use ghc-lib.

The tests now don't pass

Linking /Users/xxx/Documents/Haskell/smuggler/dist-newstyle/build/x86_64-osx/ghc-8.8.3/smuggler-0.2.0.0/t/smuggler-test/build/smuggler-test/smuggler-test ...
Running 1 test suites...
Test suite smuggler-test: RUNNING...

Test test/Test/BoolPartlyUsedLast failed:
Expected:
- import Data.Bool ( not)
But got:


Test test/Test/TypeConstructorUsed failed:
Expected:
- import Data.Bool (Bool (True))
But got:


Test test/Test/TypeUsed failed:
Expected:
- import Data.Bool (Bool)
But got:


Test test/Test/WildcardUsed failed:
Expected:
- import Data.Bool (Bool (..))
But got:


Test test/Test/TypeConstructorUnused failed:
Expected:
- import Data.Bool (Bool ( True))
But got:


Test test/Test/TypeConstructorUnusedComma failed:
Expected:
- import Data.Bool (Bool (False))
But got:


Test test/Test/WildcardUnused failed:
Expected:
- import Data.Bool ( not)
But got:


Test test/Test/ConstructorsUnused failed:
Expected:
- import Data.Bool ( not)
But got:


Test test/Test/TypeUnused failed:
Expected:
- import Data.Bool ( not)
But got:

Cleaning tests
Some tests failed

Test suite smuggler-test: FAIL

I tried running the plugin on a large project with a lot of redundant imports, https://github.com/agda/agda. There were several issues:

  • because smuggler reads files using ByteString it mangles Unicode characters in the code. Eg:
--- | Get the next version of the concrete name. For instance, @nextName "x" = "x₁"@.
+-- | Get the next version of the concrete name. For instance, @nextName "x" = "xâ<U+0082><U+0081>"@.
  • a good number of redundant imports get zapped, but there is a fair bit of mangling (where two adjacent imports get joined into a single line, with the second import keyword missing). I am not sure how close the result is to the minimal imports that GHC sees with -ddump-minimal-imports
  • some imports are redundant, but needed for backward compatibility (eg, around Monad.Fail and Data.Monoid and Data.Semigroup.

To make this app even more useful, it would be helpful to have it generate a minimal exports list (based on what is used elsewhere in the project)!

Thanks for all the hard work that has clearly gone into all this.

Fix stack.yaml

Provided stack.yaml yields:

λ ~/code/smuggler/ master STACK_YAML=stack-mac-8.6.1.yaml stack build
Getting project config file from STACK_YAML environment
Error parsing targets: The project contains no local packages (packages not marked with 'extra-dep')

Compress imports

Sometimes we have imports like these:

import Foo (Foo)
import Foo.Bar (Bar)

And often they can be compressed to something like this:

import Foo (Bar, Foo)

I think it would be good to implement this feature.

Improve tests output messages

Currently, we have

smuggler/test/Test.hs

Lines 24 to 26 in 7746b69

if result
then putStrLn "Success"
else putStrLn "Fail" >> exitFailure

which is not informative at all. We need somehow show which tests are failing, what was the expected and real result of the smuggler work.

Include dependencies in the hash

Let's say I have three modules: A, B, and C:

module A (X) where
data X
module B (Y) where
data Y
module C where
import A
import B
data Z = MkZ X Y

Then I change B:

module B (X, Y) where
import A (X)
data Y

Now import A in C is redundant, because B reexports X. However, C itself hasn't changed.

This means that using hash-store to decide whether recompilation is needed is not sufficient, because redundancy of imports is not a property of a particular module, but a property of this module and all its dependencies.

Check if cache directory exists

Tests sometimes fail locally with

smuggler-test: .smuggler: removeDirectoryRecursive:getSymbolicLinkStatus: does not exist (No such file or directory)

We should run removeDirectoryRecursive only if .smuggler exists?

Stack extra-deps

I am not sure if this should be merged in or provided by each user individually but I had to add some extra-deps to my stack.yaml in order to build:

allow-newer: true
extra-deps:
 - ghc-exactprint-0.5.8.1@sha256:f76eed0976b854ce03928796e9cff97769e304618ca99bc0f6cdccab31e539d0
 - hash-store-0.1.0@sha256:aa7a3e9c1e4d6eb426a0682b8d2164c3d954b23d34e9ca33c9f04fbc9e5198a3
 - unordered-containers-0.2.9.0@sha256:124a5241860711a0e5c10e94d8aec8a127f0094df7a537cc1786e198d7571dfe
 - base16-bytestring-0.1.1.6@sha256:ead535a30f93189068b3457496e30e3cb8a55d48b2d46f39325233d0d9987d2c
 - blake2-0.2.0@sha256:2175e66e5f4a72b47407cb79b252b0adc5d82f34a958418b75e1d7871187b507
 - free-5.1@sha256:71aa48c5a5dde71ed2a7f3d1d23c6d3a66580859444f55c8b38dd1bb205aa298
 - ghc-paths-0.1.0.9@sha256:ed18df7b53699446dabd66f6e019e5b156820f0301d8dec0d6385f13b797e0ba
 - hashable-1.2.7.0@sha256:03b6836ca9cd3ad0e5a2f3cce989b001dd0e05f306a873db3196037adb30e0a4
 - syb-0.7@sha256:9c559edeef6b9eb1362d7e16fbb15e786be871050cf085a46fcead282bb86e89
 - comonad-5.0.4@sha256:522ca45fedc212d86b3f628275974378e821e7f3caf8055a64189ae4f8c59dbf
 - distributive-0.6@sha256:26507cf231eb10db1eb54bc358477418ce87d5077ff76c66743925fb49494b54
 - exceptions-0.10.0@sha256:ef6066c13de2dfd191dc810f9dfa9a474318abc9bb458413ffbdd2ece482312a
 - profunctors-5.3@sha256:ce641b72fd014b1f7b42a438f8c0360cb93fd277c7b843b7ef94a7c083c31ded
 - semigroupoids-5.3.1@sha256:ed631b231bf49ee972482aa98b3ba1487041328f7168c8773e473b2fa4ebe4a4
 - transformers-base-0.4.5.2@sha256:e4d8155470905ba2942033a1537fc4cf91927d1c9b34693fd57ddf3bc02334af
 - base-orphans-0.8@sha256:4885caa82ab94fa5cb841d6d06a43a97cdc7e835f346be4f11c1cc5707b886db
 - bifunctors-5.5.3@sha256:8f6e90c3ae7a04dba36669e4fad5b9fbc973dbfc6978b4c7d410f9875e0e9d00
 - cabal-doctest-1.0.6@sha256:c0b4a5b1ff38d2867e7003b4be59f3bd7e8e204ab8c988d96d3a77472ae671cd
 - contravariant-1.5@sha256:83f4d20073414561f2352aeb8f48207def31cc933eb058c141968fbbefaeb0d5
 - semigroups-0.18.5@sha256:aaf0d3d5050aa120b2eb98682bc7f8aeed947c1eb51a80375f32775af3d2ff68
 - tagged-0.8.6@sha256:b5e1de3b14ff198b548928f686e5e8783301dc231413f751c23f4ee10cd47a7c
 - transformers-compat-0.6.2@sha256:3569e3a38065c66c99eca44ce67fba2747628d1b87d8c1b6bba2e910d79f0df1
 - StateVar-1.1.1.1@sha256:cd3b516a49faf0627ea31885e012611e63600824976dcb276bcb2e92cdb0790f
 - th-abstraction-0.2.8.0@sha256:db5a2ee91cce9afbe7e251c925c2d2b78725b515f6655eb5079aaeeb935c247b

Stack build osx for 8.6+ failing

I tried to follow the instructions to get things built:
STACK_YAML=stack-mac-8.6.1.yaml stack build

but I get this error:

Getting project config file from STACK_YAML environment
Error parsing targets: The project contains no local packages (packages not marked with 'extra-dep')

Any idea what I might be doing wrong, I've deleted my .stack-work/ but still seems that I'm running on ghc 8.4.3 🤔

Remove duplicate imports

Simpler version of #41 issue. Consider the following situation:

import App.Db (WithDb, query)
import App.Db (WithDb, execute)

It would be really good if smuggler can group modules with same names with join their import lists, like in the following snippet:

import App.Db (WithDb, execute, query)

Such situation often happen after resolving conflicts when rebasing over some branch. If such feature is implemented, then people will be able to just remove >>>>> git markers and smuggler will compress imports for them.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.