haskell-tools-refactor 0.4.1.1 → 0.4.1.2
raw patch · 70 files changed
+646/−290 lines, 70 filesdep −old-timedep −polyparsePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: old-time, polyparse
API changes (from Hackage documentation)
+ Language.Haskell.Tools.Refactor: annListAnnot :: RefMonads w r => Reference w r (MU *) (MU *) (AnnListG elem0 dom0 stage0) (AnnListG elem0 dom0 stage0) (NodeInfo (SemanticInfo dom0 (AnnListG elem0)) (ListInfo stage0)) (NodeInfo (SemanticInfo dom0 (AnnListG elem0)) (ListInfo stage0))
+ Language.Haskell.Tools.Refactor: class HasSourceInfo e where type SourceInfoType e :: * where {
+ Language.Haskell.Tools.Refactor: sourceTemplateListRange :: Simple Lens (ListInfo SrcTemplateStage) SrcSpan
+ Language.Haskell.Tools.Refactor: sourceTemplateNodeElems :: Simple Lens (SpanInfo SrcTemplateStage) [SourceTemplateElem]
+ Language.Haskell.Tools.Refactor: sourceTemplateNodeRange :: Simple Lens (SpanInfo SrcTemplateStage) SrcSpan
+ Language.Haskell.Tools.Refactor: sourceTemplateOptRange :: Simple Lens (OptionalInfo SrcTemplateStage) SrcSpan
+ Language.Haskell.Tools.Refactor: srcInfo :: HasSourceInfo e => Simple Lens e (SourceInfoType e)
+ Language.Haskell.Tools.Refactor: srcTmpDefaultSeparator :: Simple Lens (ListInfo SrcTemplateStage) String
+ Language.Haskell.Tools.Refactor: srcTmpIndented :: Simple Lens (ListInfo SrcTemplateStage) Bool
+ Language.Haskell.Tools.Refactor: srcTmpListAfter :: Simple Lens (ListInfo SrcTemplateStage) String
+ Language.Haskell.Tools.Refactor: srcTmpListBefore :: Simple Lens (ListInfo SrcTemplateStage) String
+ Language.Haskell.Tools.Refactor: srcTmpOptAfter :: Simple Lens (OptionalInfo SrcTemplateStage) String
+ Language.Haskell.Tools.Refactor: srcTmpOptBefore :: Simple Lens (OptionalInfo SrcTemplateStage) String
+ Language.Haskell.Tools.Refactor: srcTmpSeparators :: Simple Lens (ListInfo SrcTemplateStage) [String]
+ Language.Haskell.Tools.Refactor: type family SourceInfoType e :: *;
+ Language.Haskell.Tools.Refactor: }
+ Language.Haskell.Tools.Refactor.ListOperations: filterListIndexed :: (Int -> Ann e dom SrcTemplateStage -> Bool) -> AnnList e dom -> AnnList e dom
+ Language.Haskell.Tools.Refactor.ListOperations: zipWithSeparators :: AnnList e dom -> [(String, Ann e dom SrcTemplateStage)]
+ Language.Haskell.Tools.Refactor.Perform: ProjectOrganizeImports :: RefactorCommand
+ Language.Haskell.Tools.Refactor.Predefined.DataToNewtype: tryItOut :: String -> IO ()
+ Language.Haskell.Tools.Refactor.Predefined.DollarApp: tryItOut :: String -> String -> IO ()
+ Language.Haskell.Tools.Refactor.Predefined.ExtractBinding: tryItOut :: String -> String -> String -> IO ()
+ Language.Haskell.Tools.Refactor.Predefined.GenerateTypeSignature: tryItOut :: String -> String -> IO ()
+ Language.Haskell.Tools.Refactor.Predefined.IfToGuards: tryItOut :: String -> String -> IO ()
+ Language.Haskell.Tools.Refactor.Predefined.InlineBinding: tryItOut :: String -> String -> IO ()
+ Language.Haskell.Tools.Refactor.Predefined.OrganizeImports: projectOrganizeImports :: forall dom. OrganizeImportsDomain dom => Refactoring dom
+ Language.Haskell.Tools.Refactor.Session: handleErrors :: ExceptionMonad m => m a -> m (Either String a)
- Language.Haskell.Tools.Refactor.ListOperations: filterList :: (Ann e dom SrcTemplateStage -> Bool) -> AnnListG e dom SrcTemplateStage -> AnnListG e dom SrcTemplateStage
+ Language.Haskell.Tools.Refactor.ListOperations: filterList :: (Ann e dom SrcTemplateStage -> Bool) -> AnnList e dom -> AnnList e dom
- Language.Haskell.Tools.Refactor.ListOperations: insertWhere :: Ann e dom SrcTemplateStage -> (Maybe (Ann e dom SrcTemplateStage) -> Bool) -> (Maybe (Ann e dom SrcTemplateStage) -> Bool) -> AnnListG e dom SrcTemplateStage -> AnnListG e dom SrcTemplateStage
+ Language.Haskell.Tools.Refactor.ListOperations: insertWhere :: Ann e dom SrcTemplateStage -> (Maybe (Ann e dom SrcTemplateStage) -> Bool) -> (Maybe (Ann e dom SrcTemplateStage) -> Bool) -> AnnList e dom -> AnnList e dom
- Language.Haskell.Tools.Refactor.Predefined.DataToNewtype: dataToNewtype :: Domain dom => LocalRefactoring dom
+ Language.Haskell.Tools.Refactor.Predefined.DataToNewtype: dataToNewtype :: LocalRefactoring dom
- Language.Haskell.Tools.Refactor.Predefined.OrganizeImports: type OrganizeImportsDomain dom = (HasNameInfo dom, HasImportInfo dom)
+ Language.Haskell.Tools.Refactor.Predefined.OrganizeImports: type OrganizeImportsDomain dom = (HasNameInfo dom, HasImportInfo dom, HasModuleInfo dom)
- Language.Haskell.Tools.Refactor.RefactorBase: runRefactor :: (HasModuleInfo dom) => ModuleDom dom -> [ModuleDom dom] -> Refactoring dom -> Ghc (Either String [RefactorChange dom])
+ Language.Haskell.Tools.Refactor.RefactorBase: runRefactor :: ModuleDom dom -> [ModuleDom dom] -> Refactoring dom -> Ghc (Either String [RefactorChange dom])
- Language.Haskell.Tools.Refactor.Session: reloadChangedModules :: IsRefactSessionState st => (ModSummary -> IO a) -> (ModSummary -> Bool) -> StateT st Ghc [a]
+ Language.Haskell.Tools.Refactor.Session: reloadChangedModules :: IsRefactSessionState st => (ModSummary -> IO a) -> (ModSummary -> Bool) -> StateT st Ghc (Either String [a])
Files
- Language/Haskell/Tools/Refactor.hs +14/−9
- Language/Haskell/Tools/Refactor/BindingElem.hs +2/−3
- Language/Haskell/Tools/Refactor/GetModules.hs +11/−12
- Language/Haskell/Tools/Refactor/ListOperations.hs +37/−22
- Language/Haskell/Tools/Refactor/Perform.hs +10/−32
- Language/Haskell/Tools/Refactor/Predefined/DataToNewtype.hs +5/−4
- Language/Haskell/Tools/Refactor/Predefined/DollarApp.hs +10/−9
- Language/Haskell/Tools/Refactor/Predefined/ExtractBinding.hs +19/−20
- Language/Haskell/Tools/Refactor/Predefined/GenerateExports.hs +4/−4
- Language/Haskell/Tools/Refactor/Predefined/GenerateTypeSignature.hs +14/−13
- Language/Haskell/Tools/Refactor/Predefined/IfToGuards.hs +6/−4
- Language/Haskell/Tools/Refactor/Predefined/InlineBinding.hs +11/−14
- Language/Haskell/Tools/Refactor/Predefined/OrganizeImports.hs +118/−37
- Language/Haskell/Tools/Refactor/Predefined/RenameDefinition.hs +6/−12
- Language/Haskell/Tools/Refactor/Prepare.hs +20/−26
- Language/Haskell/Tools/Refactor/RefactorBase.hs +23/−18
- Language/Haskell/Tools/Refactor/Session.hs +27/−29
- examples/Decl/LocalBindingInDo.hs +7/−0
- examples/Module/Import.hs +1/−0
- examples/Module/PatternImport.hs +4/−0
- examples/Refactor/OrganizeImports/Class_res.hs +1/−1
- examples/Refactor/OrganizeImports/InstanceCarry/DataType.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportNonOrphan.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportNonOrphan_res.hs +2/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportOrphan.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/ImportOrphan_res.hs +3/−0
- examples/Refactor/OrganizeImports/InstanceCarry/OrphanInstance.hs +7/−0
- examples/Refactor/OrganizeImports/InstanceCarry/TCWithInst.hs +9/−0
- examples/Refactor/OrganizeImports/InstanceCarry/TypeClass.hs +4/−0
- examples/Refactor/OrganizeImports/KeepReexported.hs +3/−0
- examples/Refactor/OrganizeImports/KeepReexported_res.hs +3/−0
- examples/Refactor/OrganizeImports/KeepRenamedReexported.hs +4/−0
- examples/Refactor/OrganizeImports/KeepRenamedReexported_res.hs +4/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ClassSource.hs +11/−0
- examples/Refactor/OrganizeImports/MakeExplicit/FunSource.hs +3/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportClassFun.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportClassFun_res.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportCon.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportCon_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFour.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFour_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunHiddenClass.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunHiddenClass_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunOutOfClass.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportFunOutOfClass_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportOne.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportOne_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportRecordSel.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportRecordSel_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportThree.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportThree_res.hs +6/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnited.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnitedCount.hs +8/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnitedCount_res.hs +8/−0
- examples/Refactor/OrganizeImports/MakeExplicit/ImportUnited_res.hs +7/−0
- examples/Refactor/OrganizeImports/MakeExplicit/Source.hs +15/−0
- examples/Refactor/OrganizeImports/NarrowQual.hs +6/−0
- examples/Refactor/OrganizeImports/NarrowQual_res.hs +6/−0
- examples/Refactor/OrganizeImports/Removed.hs +1/−3
- examples/Refactor/OrganizeImports/Removed_res.hs +0/−2
- examples/Refactor/OrganizeImports/Reorder.hs +4/−2
- examples/Refactor/OrganizeImports/ReorderComment.hs +12/−0
- examples/Refactor/OrganizeImports/ReorderComment_res.hs +12/−0
- examples/Refactor/OrganizeImports/ReorderGroups.hs +12/−0
- examples/Refactor/OrganizeImports/ReorderGroups_res.hs +12/−0
- examples/Refactor/OrganizeImports/Reorder_res.hs +4/−2
- examples/Refactor/OrganizeImports/Unused.hs +0/−4
- examples/Refactor/OrganizeImports/Unused_res.hs +0/−4
- haskell-tools-refactor.cabal +3/−3
- test/Main.hs +19/−1
Language/Haskell/Tools/Refactor.hs view
@@ -10,21 +10,26 @@ , module Language.Haskell.Tools.Refactor.ListOperations , module Language.Haskell.Tools.Refactor.BindingElem , module Language.Haskell.Tools.IndentationUtils - , HasRange(..), annListElems, annList, annJust, annMaybe, isAnnNothing, Domain + , HasSourceInfo(..), HasRange(..), annListElems, annListAnnot, annList, annJust, annMaybe, isAnnNothing, Domain , shortShowSpan, SrcTemplateStage, SourceInfoTraversal(..) + -- elements of source templates + , sourceTemplateNodeRange, sourceTemplateNodeElems + , sourceTemplateListRange, srcTmpListBefore, srcTmpListAfter, srcTmpDefaultSeparator, srcTmpIndented, srcTmpSeparators + , sourceTemplateOptRange, srcTmpOptBefore, srcTmpOptAfter ) where -- Important: Haddock doesn't support the rename all exported modules and export them at once hack -import Language.Haskell.Tools.AST.SemaInfoClasses -import Language.Haskell.Tools.AST.Rewrite -import Language.Haskell.Tools.AST.References -import Language.Haskell.Tools.AST.Helpers -import Language.Haskell.Tools.Refactor.RefactorBase import Language.Haskell.Tools.AST.ElementTypes -import Language.Haskell.Tools.Refactor.Prepare -import Language.Haskell.Tools.Refactor.ListOperations -import Language.Haskell.Tools.Refactor.BindingElem +import Language.Haskell.Tools.AST.Helpers +import Language.Haskell.Tools.AST.References +import Language.Haskell.Tools.AST.Rewrite +import Language.Haskell.Tools.AST.SemaInfoClasses import Language.Haskell.Tools.IndentationUtils +import Language.Haskell.Tools.Refactor.BindingElem +import Language.Haskell.Tools.Refactor.ListOperations +import Language.Haskell.Tools.Refactor.Prepare +import Language.Haskell.Tools.Refactor.RefactorBase +import Language.Haskell.Tools.Transform import Language.Haskell.Tools.AST.Ann
Language/Haskell/Tools/Refactor/BindingElem.hs view
@@ -5,10 +5,9 @@ module Language.Haskell.Tools.Refactor.BindingElem where import Control.Reference -import Language.Haskell.Tools.AST.Rewrite -import Language.Haskell.Tools.AST.ElementTypes import Language.Haskell.Tools.AST -import SrcLoc +import Language.Haskell.Tools.AST.Rewrite +import SrcLoc (RealSrcSpan(..)) -- | A type class for handling definitions that can appear as both top-level and local definitions class NamedElement d => BindingElem d where
Language/Haskell/Tools/Refactor/GetModules.hs view
@@ -11,27 +11,26 @@ import Data.List (intersperse, find, sortBy) import qualified Data.Map as Map import Data.Maybe -import Distribution.Package (Dependency(..), PackageName(..), pkgName) -import Distribution.Verbosity (silent) import Distribution.ModuleName (components) import Distribution.ModuleName +import Distribution.Package (Dependency(..), PackageName(..), pkgName) import Distribution.PackageDescription import Distribution.PackageDescription.Configuration import Distribution.PackageDescription.Parse -import System.FilePath.Posix -import System.Directory +import Distribution.Verbosity (silent) import Language.Haskell.Extension +import System.Directory +import System.FilePath.Posix import DynFlags (DynFlags, xopt_set, xopt_unset) -import GHC hiding (ModuleName) import qualified DynFlags as GHC -import SrcLoc as GHC -import RdrName as GHC (RdrName) -import Name as GHC (Name) +import GHC hiding (ModuleName) import qualified Language.Haskell.TH.LanguageExtensions as GHC +import Name as GHC (Name) +import RdrName as GHC (RdrName) -import Language.Haskell.Tools.Refactor.RefactorBase import Language.Haskell.Tools.AST (Dom, IdDom) +import Language.Haskell.Tools.Refactor.RefactorBase -- | The modules of a library, executable, test or benchmark. A package contains one or more module collection. data ModuleCollection @@ -81,7 +80,7 @@ moduleCollectionIdString (BenchmarkMC _ id) = id moduleCollectionPkgId :: ModuleCollectionId -> Maybe String -moduleCollectionPkgId (DirectoryMC fp) = Nothing +moduleCollectionPkgId (DirectoryMC _) = Nothing moduleCollectionPkgId (LibraryMC id) = Just id moduleCollectionPkgId (ExecutableMC id _) = Just id moduleCollectionPkgId (TestSuiteMC id _) = Just id @@ -102,7 +101,7 @@ lookupModInSCs moduleName = find ((moduleName ==) . fst) . concatMap (Map.assocs . (^. mcModules)) removeModule :: String -> [ModuleCollection] -> [ModuleCollection] -removeModule moduleName = map (mcModules .- Map.filterWithKey (\k v -> moduleName /= (k ^. sfkModuleName))) +removeModule moduleName = map (mcModules .- Map.filterWithKey (\k _ -> moduleName /= (k ^. sfkModuleName))) hasGeneratedCode :: SourceFileKey -> [ModuleCollection] -> Bool hasGeneratedCode key = maybe False (\case (_, ModuleCodeGenerated {}) -> True; _ -> False) @@ -181,7 +180,7 @@ (map (normalise . (root </>)) $ hsSourceDirs bi) (Map.fromList $ map ((, ModuleNotLoaded False) . SourceFileKey NormalHs . moduleName) (getModuleNames tmc)) (flagsFromBuildInfo bi) - (map (\(Dependency pkgName _) -> LibraryMC (unPackageName pkgName)) (targetBuildDepends bi)) + (map (\(Dependency pkgName _) -> LibraryMC (unPackageName pkgName)) (targetBuildDepends bi)) moduleName = concat . intersperse "." . components
Language/Haskell/Tools/Refactor/ListOperations.hs view
@@ -1,36 +1,40 @@+{-# LANGUAGE TupleSections #-} +-- | Defines operation on AST lists. +-- AST lists carry source information so simple list modification is not enough. module Language.Haskell.Tools.Refactor.ListOperations where -import SrcLoc -import Data.String -import Data.List import Control.Reference -import Debug.Trace -import Data.Function (on) + import Language.Haskell.Tools.AST -import Language.Haskell.Tools.AST.Rewrite -import Language.Haskell.Tools.Transform +import Language.Haskell.Tools.AST.Rewrite (AnnMaybe(..), AnnList(..)) +import Language.Haskell.Tools.Transform (srcTmpDefaultSeparator, srcTmpSeparators) -filterList :: (Ann e dom SrcTemplateStage -> Bool) -> AnnListG e dom SrcTemplateStage -> AnnListG e dom SrcTemplateStage -filterList pred (AnnListG (NodeInfo sema src) elems) - = let (filteredElems, separators) = filterElems elems (src ^. srcTmpSeparators) +-- | Filters the elements of the list. By default it removes the separator before the element. +-- Of course, if the first element is removed, the following separator is removed as well. +filterList :: (Ann e dom SrcTemplateStage -> Bool) -> AnnList e dom -> AnnList e dom +filterList pred = filterListIndexed (const pred) + +filterListIndexed :: (Int -> Ann e dom SrcTemplateStage -> Bool) -> AnnList e dom -> AnnList e dom +filterListIndexed pred (AnnListG (NodeInfo sema src) elems) + = let (filteredElems, separators) = filterElems 0 elems (src ^. srcTmpSeparators) in AnnListG (NodeInfo sema (srcTmpSeparators .= separators $ src)) filteredElems - where filterElems (elem:ls) (sep:seps) - | pred elem = let (elems',seps') = filterElems' ls (sep:seps) in (elem:elems', seps') - | otherwise = filterElems ls seps - filterElems elems [] = (filter pred elems, []) - filterElems [] seps = ([], seps) + where filterElems i (elem:ls) (sep:seps) + | pred i elem = let (elems',seps') = filterElems' (i+1) ls (sep:seps) in (elem:elems', seps') + | otherwise = filterElems (i+1) ls seps + filterElems i elems [] = (filter (pred i) elems, []) + filterElems _ [] seps = ([], seps) - filterElems' (elem:ls) (sep:seps) - | pred elem = let (elems',seps') = filterElems' ls seps in (elem:elems', sep:seps') - | otherwise = filterElems' ls seps - filterElems' elems [] = (filter pred elems, []) - filterElems' [] seps = ([], seps) + filterElems' i (elem:ls) (sep:seps) + | pred i elem = let (elems',seps') = filterElems' (i+1) ls seps in (elem:elems', sep:seps') + | otherwise = filterElems' (i+1) ls seps + filterElems' i elems [] = (filter (pred i) elems, []) + filterElems' _ [] seps = ([], seps) -- | Inserts the element in the places where the two positioning functions (one checks the element before, one the element after) -- allows the placement. insertWhere :: Ann e dom SrcTemplateStage -> (Maybe (Ann e dom SrcTemplateStage) -> Bool) - -> (Maybe (Ann e dom SrcTemplateStage) -> Bool) -> AnnListG e dom SrcTemplateStage - -> AnnListG e dom SrcTemplateStage + -> (Maybe (Ann e dom SrcTemplateStage) -> Bool) -> AnnList e dom + -> AnnList e dom insertWhere e before after al = let index = insertIndex before after (al ^? annList) in case index of @@ -56,6 +60,17 @@ insertIndex' before after (curr:[]) | before (Just curr) && after Nothing = Just 0 | otherwise = Nothing + insertIndex' before after [] + | before Nothing && after Nothing = Just 0 + | otherwise = Nothing + +zipWithSeparators :: AnnList e dom -> [(String, Ann e dom SrcTemplateStage)] +zipWithSeparators (AnnListG (NodeInfo _ src) elems) + | [] <- src ^. srcTmpSeparators + = map (src ^. srcTmpDefaultSeparator ,) elems + | otherwise + = zip ("" : seps ++ repeat (last seps)) elems + where seps = src ^. srcTmpSeparators replaceWithJust :: Ann e dom SrcTemplateStage -> AnnMaybe e dom -> AnnMaybe e dom replaceWithJust e (AnnMaybeG temp _) = AnnMaybeG temp (Just e)
Language/Haskell/Tools/Refactor/Perform.hs view
@@ -13,46 +13,20 @@ -- | Defines common utilities for using refactorings. Provides an interface for both demo, command line and integrated tools. module Language.Haskell.Tools.Refactor.Perform where -import Language.Haskell.Tools.AST.FromGHC -import Language.Haskell.Tools.AST as AST -import Language.Haskell.Tools.Transform -import Language.Haskell.Tools.PrettyPrint - -import Data.List import Data.List.Split -import GHC.Generics hiding (moduleName) -import qualified Data.Map as Map -import Data.Maybe -import Data.Typeable -import Data.IORef -import Control.Monad -import Control.Monad.State -import Control.Monad.IO.Class -import Control.Reference -import Control.Exception -import System.Directory -import System.IO -import System.FilePath -import Data.Generics.Uniplate.Operations -import Language.Haskell.Tools.Refactor.Predefined.OrganizeImports -import Language.Haskell.Tools.Refactor.Predefined.GenerateTypeSignature -import Language.Haskell.Tools.Refactor.Predefined.GenerateExports -import Language.Haskell.Tools.Refactor.Predefined.RenameDefinition +import Language.Haskell.Tools.AST as AST import Language.Haskell.Tools.Refactor.Predefined.ExtractBinding +import Language.Haskell.Tools.Refactor.Predefined.GenerateExports +import Language.Haskell.Tools.Refactor.Predefined.GenerateTypeSignature import Language.Haskell.Tools.Refactor.Predefined.InlineBinding -import Language.Haskell.Tools.Refactor.RefactorBase -import Language.Haskell.Tools.Refactor.GetModules +import Language.Haskell.Tools.Refactor.Predefined.OrganizeImports +import Language.Haskell.Tools.Refactor.Predefined.RenameDefinition import Language.Haskell.Tools.Refactor.Prepare +import Language.Haskell.Tools.Refactor.RefactorBase -import Language.Haskell.TH.LanguageExtensions import GHC -import SrcLoc - -import Debug.Trace - - -- | Executes a given command on the selected module and given other modules performCommand :: (HasModuleInfo dom, DomGenerateExports dom, OrganizeImportsDomain dom, DomainRenameDefinition dom, ExtractBindingDomain dom, GenerateSignatureDomain dom) => RefactorCommand -> ModuleDom dom -- ^ The module in which the refactoring is performed @@ -61,6 +35,7 @@ performCommand rf mod mods = runRefactor mod mods $ selectCommand rf where selectCommand NoRefactor = localRefactoring return selectCommand OrganizeImports = localRefactoring organizeImports + selectCommand ProjectOrganizeImports = projectOrganizeImports selectCommand GenerateExports = localRefactoring generateExports selectCommand (GenerateSignature sp) = localRefactoring $ generateTypeSignature' (correctRefactorSpan (snd mod) sp) selectCommand (RenameDefinition sp str) = renameDefinition' (correctRefactorSpan (snd mod) sp) str @@ -70,6 +45,7 @@ -- | A refactoring command data RefactorCommand = NoRefactor | OrganizeImports + | ProjectOrganizeImports | GenerateExports | GenerateSignature RealSrcSpan | RenameDefinition RealSrcSpan String @@ -79,11 +55,13 @@ readCommand :: String -> RefactorCommand readCommand (splitOn " " -> refact:args) = analyzeCommand refact args +readCommand _ = error "panic: splitOn resulted empty" analyzeCommand :: String -> [String] -> RefactorCommand analyzeCommand "" _ = NoRefactor analyzeCommand "CheckSource" _ = NoRefactor analyzeCommand "OrganizeImports" _ = OrganizeImports +analyzeCommand "ProjectOrganizeImports" _ = ProjectOrganizeImports analyzeCommand "GenerateExports" _ = GenerateExports analyzeCommand "GenerateSignature" [sp] = GenerateSignature (readSrcSpan sp) analyzeCommand "RenameDefinition" [sp, newName] = RenameDefinition (readSrcSpan sp) newName
Language/Haskell/Tools/Refactor/Predefined/DataToNewtype.hs view
@@ -1,14 +1,15 @@-module Language.Haskell.Tools.Refactor.Predefined.DataToNewtype (dataToNewtype) where +module Language.Haskell.Tools.Refactor.Predefined.DataToNewtype (dataToNewtype, tryItOut) where +import Control.Reference ((.=), (.-), (&)) import Language.Haskell.Tools.Refactor -import Control.Reference +tryItOut :: String -> IO () tryItOut moduleName = tryRefactor (\_ -> localRefactoring dataToNewtype) moduleName "" -dataToNewtype :: Domain dom => LocalRefactoring dom +dataToNewtype :: LocalRefactoring dom dataToNewtype = return . (modDecl & annList .- changeDeclaration) changeDeclaration :: Decl dom -> Decl dom -changeDeclaration dd@(DataDecl DataKeyword ctx declHead (AnnList [ConDecl name (AnnList [arg])]) derivs) +changeDeclaration dd@(DataDecl DataKeyword _ _ (AnnList [ConDecl _ (AnnList [_])]) _) = declNewtype .= mkNewtypeKeyword $ dd changeDeclaration decl = decl
Language/Haskell/Tools/Refactor/Predefined/DollarApp.hs view
@@ -1,20 +1,20 @@ {-# LANGUAGE ViewPatterns, FlexibleContexts, ConstraintKinds #-} -module Language.Haskell.Tools.Refactor.Predefined.DollarApp (dollarApp, DollarDomain) where +module Language.Haskell.Tools.Refactor.Predefined.DollarApp (dollarApp, DollarDomain, tryItOut) where import Language.Haskell.Tools.Refactor -import SrcLoc (RealSrcSpan, SrcSpan) -import Unique (getUnique) +import BasicTypes (Fixity(..)) import Id (idName) -import PrelNames (dollarIdKey) +import qualified Name as GHC (Name) import PrelInfo (wiredInIds) -import BasicTypes (Fixity(..)) +import PrelNames (dollarIdKey) +import SrcLoc (RealSrcSpan, SrcSpan) +import Unique (getUnique) import Control.Monad.State -import Control.Reference -import Data.Generics.Uniplate.Data -import Debug.Trace +import Control.Reference ((^.), (!~), biplateRef) +tryItOut :: String -> String -> IO () tryItOut = tryRefactor (localRefactoring . dollarApp) type DollarMonad dom = StateT [SrcSpan] (LocalRefactor dom) @@ -25,7 +25,7 @@ >=> (biplateRef !~ parenExpr)) replaceExpr :: DollarDomain dom => Expr dom -> [SrcSpan] -> DollarMonad dom (Expr dom) -replaceExpr expr@(App fun (Paren (InfixApp _ op arg))) replacedRanges +replaceExpr expr@(App _ (Paren (InfixApp _ op arg))) replacedRanges | not (getRange arg `elem` replacedRanges) , semanticsName (op ^. operatorName) /= Just dollarName , case semanticsFixity (op ^. operatorName) of Just (Fixity _ p _) | p > 0 -> False; _ -> True @@ -45,4 +45,5 @@ else return expr parenDollar _ e = return e +dollarName :: GHC.Name [dollarName] = map idName $ filter ((dollarIdKey==) . getUnique) wiredInIds
Language/Haskell/Tools/Refactor/Predefined/ExtractBinding.hs view
@@ -7,25 +7,22 @@ , ConstraintKinds , TypeFamilies #-} -module Language.Haskell.Tools.Refactor.Predefined.ExtractBinding (extractBinding', ExtractBindingDomain) where +module Language.Haskell.Tools.Refactor.Predefined.ExtractBinding (extractBinding', ExtractBindingDomain, tryItOut) where import qualified GHC -import qualified Var as GHC -import qualified OccName as GHC hiding (varName) -import SrcLoc -import Unique +import qualified OccName as GHC (occNameString) +import SrcLoc (SrcSpan(..), RealSrcSpan(..)) -import Data.Char -import Data.Maybe -import Data.Generics.Uniplate.Data -import Control.Reference import Control.Monad.State -import Control.Monad.Identity +import Control.Reference +import Data.Generics.Uniplate.Data () +import Data.Maybe import Language.Haskell.Tools.Refactor type ExtractBindingDomain dom = ( HasNameInfo dom, HasDefiningInfo dom, HasScopeInfo dom ) +tryItOut :: String -> String -> String -> IO () tryItOut mod sp name = tryRefactor (localRefactoring . flip extractBinding' name) mod sp extractBinding' :: ExtractBindingDomain dom => RealSrcSpan -> String -> LocalRefactoring dom @@ -43,11 +40,10 @@ = let conflicting = any (isConflicting name) (mod ^? selectDecl & biplateRef :: [QualifiedName dom]) exprRange = getRange $ head (mod ^? selectDecl & selectExpr) decl = last (mod ^? selectDecl) - declRange = getRange $ last (mod ^? selectDecl) in if conflicting then refactError "The given name causes name conflict." else do (res, st) <- runStateT (selectDecl&selectExpr !~ extractThatBind name (head $ decl ^? actualContainingExpr exprRange) $ mod) Nothing - case st of Just def -> return $ evalState (selectDecl !~ addLocalBinding declRange exprRange def $ res) False + case st of Just def -> return $ evalState (selectDecl !~ addLocalBinding exprRange def $ res) False Nothing -> refactError "There is no applicable expression to extract." -- | Decides if a new name defined to be the given string will conflict with the given AST element @@ -67,22 +63,23 @@ | otherwise -> doExtract name cont (fromJust $ e ^? exprInner) Var {} -> lift $ refactError "The selected expression is too simple to be extracted." el | isParenLikeExpr el && hasParameter -> mkParen <$> doExtract name cont e - el -> doExtract name cont e + | otherwise -> doExtract name cont e where hasParameter = not (null (getExternalBinds cont e)) --- | Adds a local binding to the -addLocalBinding :: SrcSpan -> SrcSpan -> ValueBind dom -> ValueBind dom -> State Bool (ValueBind dom) +-- | Adds a local binding to the where clause of the enclosing binding +addLocalBinding :: SrcSpan -> ValueBind dom -> ValueBind dom -> State Bool (ValueBind dom) -- this uses the state monad to only add the local binding to the first selected element -addLocalBinding declRange exprRange local bind +addLocalBinding exprRange local bind = do done <- get if not done then do put True - return $ indentBody $ doAddBinding declRange exprRange local bind + return $ indentBody $ doAddBinding exprRange local bind else return bind where - doAddBinding declRng _ local sb@(SimpleBind {}) = valBindLocals .- insertLocalBind local $ sb - doAddBinding declRng (RealSrcSpan rng) local fb@(FunctionBind {}) + doAddBinding _ local sb@(SimpleBind {}) = valBindLocals .- insertLocalBind local $ sb + doAddBinding (RealSrcSpan rng) local fb@(FunctionBind {}) = funBindMatches & annList & filtered (isInside rng) & matchBinds .- insertLocalBind local $ fb + doAddBinding _ _ _ = error "doAddBinding: invalid expression range" indentBody = (valBindRhs .- updIndent) . (funBindMatches & annList & matchLhs .- updIndent) . (funBindMatches & annList & matchRhs .- updIndent) @@ -129,7 +126,7 @@ -- | Gets the values that have to be passed to the extracted definition getExternalBinds :: ExtractBindingDomain dom => Expr dom -> Expr dom -> [Name dom] getExternalBinds cont expr = map exprToName $ keepFirsts $ filter isApplicableName (expr ^? uniplateRef) - where isApplicableName name@(getExprNameInfo -> Just nm) = inScopeForOriginal nm && notInScopeForExtracted nm + where isApplicableName (getExprNameInfo -> Just nm) = inScopeForOriginal nm && notInScopeForExtracted nm isApplicableName _ = False getExprNameInfo :: ExtractBindingDomain dom => Expr dom -> Maybe GHC.Name @@ -139,6 +136,7 @@ exprToName :: Expr dom -> Name dom exprToName e | Just n <- e ^? exprName = n | Just op <- e ^? exprOperator & operatorName = mkParenName op + | otherwise = error "exprToName: name not found" notInScopeForExtracted :: GHC.Name -> Bool notInScopeForExtracted n = not $ n `inScope` semanticsScope cont @@ -155,6 +153,7 @@ accessRhs = valBindRhs &+& funBindMatches & annList & filtered (isInside rng) & matchRhs accessExpr :: Simple Traversal (Rhs dom) (Expr dom) accessExpr = rhsExpr &+& rhsGuards & annList & filtered (isInside rng) & guardExpr +actualContainingExpr _ = error "actualContainingExpr: not a real range" -- | Generates the expression that calls the local binding generateCall :: String -> [Name dom] -> Expr dom
Language/Haskell/Tools/Refactor/Predefined/GenerateExports.hs view
@@ -5,13 +5,13 @@ #-} module Language.Haskell.Tools.Refactor.Predefined.GenerateExports (generateExports, DomGenerateExports) where +import Control.Reference ((^?), (.=), (&)) import Language.Haskell.Tools.Refactor -import Control.Reference -import qualified GHC +import qualified GHC (NamedThing(..), Name(..)) -import Data.Maybe import Control.Applicative ((<|>)) +import Data.Maybe (Maybe(..), catMaybes) type DomGenerateExports dom = (Domain dom, HasNameInfo dom) @@ -32,7 +32,7 @@ exportContainOthers _ = False -- | Create the export for a give name. -createExports :: DomGenerateExports dom => [(GHC.Name, Bool)] -> ExportSpecs dom +createExports :: [(GHC.Name, Bool)] -> ExportSpecs dom createExports elems = mkExportSpecs $ map (mkExportSpec . createExport) elems where createExport (n, False) = mkIESpec (mkUnqualName' (GHC.getName n)) Nothing createExport (n, True) = mkIESpec (mkUnqualName' (GHC.getName n)) (Just mkSubAll)
Language/Haskell/Tools/Refactor/Predefined/GenerateTypeSignature.hs view
@@ -7,29 +7,29 @@ , ConstraintKinds , TupleSections #-} -module Language.Haskell.Tools.Refactor.Predefined.GenerateTypeSignature (generateTypeSignature, generateTypeSignature', GenerateSignatureDomain) where +module Language.Haskell.Tools.Refactor.Predefined.GenerateTypeSignature + (generateTypeSignature, generateTypeSignature', GenerateSignatureDomain, tryItOut) where import GHC hiding (Module) -import Type as GHC -import TyCon as GHC -import OccName as GHC -import Outputable as GHC -import TysWiredIn as GHC import Id as GHC -import Unique as GHC +import OccName as GHC (isSymOcc) +import Outputable as GHC (Outputable(..), showSDocUnsafe) +import TyCon as GHC (TyCon(..), isTupleTyCon) +import Type as GHC +import TysWiredIn as GHC (listTyCon, charTyCon) -import Data.List -import Data.Maybe -import Data.Data -import Data.Generics.Uniplate.Data import Control.Monad import Control.Monad.State import Control.Reference +import Data.Generics.Uniplate.Data (universeBi) +import Data.List +import Data.Maybe (Maybe(..), catMaybes) import Language.Haskell.Tools.Refactor as AST type GenerateSignatureDomain dom = ( HasModuleInfo dom, HasIdInfo dom, HasImportInfo dom, HasScopeInfo dom ) +tryItOut :: String -> String -> IO () tryItOut = tryRefactor (localRefactoring . generateTypeSignature') generateTypeSignature' :: GenerateSignatureDomain dom => RealSrcSpan -> LocalRefactoring dom @@ -74,7 +74,7 @@ else do put True -- checking for possible situations when we cannot generate signature because of -- an implicitly passed value - let dangerousTypeVars = dangerousTVs vb scopedSigs sigBinds + let dangerousTypeVars = dangerousTVs scopedSigs sigBinds myTvs = concatMap @[] (getExternalTVs . idType . semanticsId) (vb ^? bindingName) if not $ null @[] $ myTvs `intersect` dangerousTypeVars then refactError $ "Could not generate type signature: the type variable(s) " @@ -88,7 +88,7 @@ where isSimpleBinding vb = case vb of SimpleBind (AST.VarPat {}) _ _ -> True SimpleBind _ _ _ -> False _ -> True - dangerousTVs vb scopedSigs sigBinds + dangerousTVs scopedSigs sigBinds = let dangerousDecls = if scopedSigs then filter (\(_,ts,_) -> not $ isForalledTS ts) sigBinds else sigBinds dangerousNames = map (\(_,_,bn) -> bn ^? (valBindPats & biplateRef &+& bindingName)) dangerousDecls in concatMap (concatMap @[] (getExternalTVs . idType . semanticsId @(QualifiedName dom))) dangerousNames @@ -150,6 +150,7 @@ generateAssertionFor t | Just (tc, types) <- splitTyConApp_maybe t = mkClassAssert <$> referenceName (idName $ getTCId tc) <*> mapM (generateTypeFor 0) types + | otherwise = error "generateAssertionFor: type not supported yet." -- TODO: infix things -- | Check whether the definition already has a type signature
Language/Haskell/Tools/Refactor/Predefined/IfToGuards.hs view
@@ -1,11 +1,12 @@ {-# LANGUAGE RankNTypes, FlexibleContexts, ViewPatterns #-} -module Language.Haskell.Tools.Refactor.Predefined.IfToGuards (ifToGuards) where +module Language.Haskell.Tools.Refactor.Predefined.IfToGuards (ifToGuards, tryItOut) where +import Control.Reference ((^.), (.-), (&)) +import Data.Generics.Uniplate.Data () import Language.Haskell.Tools.Refactor -import Control.Reference -import SrcLoc -import Data.Generics.Uniplate.Data +import SrcLoc (RealSrcSpan(..)) +tryItOut :: String -> String -> IO () tryItOut = tryRefactor (localRefactoring . ifToGuards) ifToGuards :: Domain dom => RealSrcSpan -> LocalRefactoring dom @@ -19,6 +20,7 @@ where trfRhs :: Rhs dom -> Rhs dom trfRhs (UnguardedRhs (If pred thenE elseE)) = createSimpleIfRhss pred thenE elseE trfRhs e = e -- don't transform already guarded right-hand sides to avoid multiple evaluation of the same condition +changeBindings b = b createSimpleIfRhss :: Expr dom -> Expr dom -> Expr dom -> Rhs dom createSimpleIfRhss pred thenE elseE = mkGuardedRhss [ mkGuardedRhs [mkGuardCheck pred] thenE
Language/Haskell/Tools/Refactor/Predefined/InlineBinding.hs view
@@ -9,25 +9,22 @@ #-} -- | Defines the inline binding refactoring that removes a value binding and replaces all occurences -- with an expression equivalent to the body of the binding. -module Language.Haskell.Tools.Refactor.Predefined.InlineBinding (inlineBinding, InlineBindingDomain) where +module Language.Haskell.Tools.Refactor.Predefined.InlineBinding (inlineBinding, InlineBindingDomain, tryItOut) where -import Control.Reference -import Control.Monad.Writer hiding (Alt) import Control.Monad.State -import Data.Maybe +import Control.Monad.Writer hiding (Alt) +import Control.Reference +import Data.Generics.Uniplate.Data () +import Data.Generics.Uniplate.Operations (Uniplate(..), Biplate(..)) import Data.List (nub) -import Data.Either (isLeft) -import Data.Generics.Uniplate.Operations -import Data.Generics.Uniplate.Data +import Data.Maybe (Maybe(..), catMaybes) -import SrcLoc as GHC -import Name as GHC +import Name as GHC (NamedThing(..), Name(..), occNameString) +import SrcLoc as GHC (SrcSpan(..), RealSrcSpan(..), containsSpan) import Language.Haskell.Tools.Refactor as AST -import Language.Haskell.Tools.AST as AST -import Debug.Trace - +tryItOut :: String -> String -> IO () tryItOut = tryRefactor inlineBinding type InlineBindingDomain dom = ( HasNameInfo dom, HasDefiningInfo dom, HasScopeInfo dom, HasModuleInfo dom ) @@ -141,7 +138,7 @@ in parenIfNeeded $ createLambda (map mkVarPat newArgs) $ mkCase (mkTuple $ map mkVar newArgs ++ args) $ map replaceMatch (matches ^? annList) - where getArgNum (MatchLhs n (AnnList args)) = length args + where getArgNum (MatchLhs _ (AnnList args)) = length args getArgNum (InfixLhs _ _ _ (AnnList more)) = length more + 2 -- | Replaces names with expressions according to a mapping. @@ -179,7 +176,7 @@ | length pats == length args , Just subs <- sequence $ zipWith staticPatternMatch pats args = Just $ concat subs -staticPatternMatch p e = Nothing +staticPatternMatch _ _ = Nothing replaceMatch :: Match dom -> Alt dom replaceMatch (Match lhs rhs locals) = mkAlt (toPattern lhs) (toAltRhs rhs) (locals ^? annJust)
Language/Haskell/Tools/Refactor/Predefined/OrganizeImports.hs view
@@ -3,69 +3,148 @@ , FlexibleContexts , TypeFamilies , ConstraintKinds + , TupleSections #-} -module Language.Haskell.Tools.Refactor.Predefined.OrganizeImports (organizeImports, OrganizeImportsDomain) where +module Language.Haskell.Tools.Refactor.Predefined.OrganizeImports (organizeImports, OrganizeImportsDomain, projectOrganizeImports) where -import SrcLoc -import Name hiding (Name) -import GHC (Ghc, GhcMonad, lookupGlobalName, TyThing(..), moduleNameString, moduleName) +import ConLike (ConLike(..)) +import DataCon (FieldLbl(..), dataConTyCon) +import DynFlags (xopt) +import FamInstEnv (FamInst(..)) +import GHC (TyThing(..), lookupName) import qualified GHC -import TyCon -import ConLike -import DataCon -import Outputable (Outputable(..), ppr, showSDocUnsafe) +import Id +import IdInfo (RecSelParent(..)) +import InstEnv (ClsInst(..)) +import Language.Haskell.TH.LanguageExtensions (Extension(..)) +import Name (NamedThing(..)) +import TyCon (tyConFieldLabels, tyConDataCons, isClassTyCon) -import Control.Reference hiding (element) +import Control.Applicative ((<$>), Alternative(..)) import Control.Monad -import Control.Monad.IO.Class +import Control.Monad.Trans (MonadTrans(..)) +import Control.Reference hiding (element) import Data.Function hiding ((&)) -import Data.String -import Data.Maybe -import Data.Data +import Data.Generics.Uniplate.Data (universeBi) import Data.List -import Data.Generics.Uniplate.Data +import Data.Maybe (Maybe(..), maybe, catMaybes) import Language.Haskell.Tools.Refactor as AST -type OrganizeImportsDomain dom = ( HasNameInfo dom, HasImportInfo dom ) +type OrganizeImportsDomain dom = ( HasNameInfo dom, HasImportInfo dom, HasModuleInfo dom ) +projectOrganizeImports :: forall dom . OrganizeImportsDomain dom => Refactoring dom +projectOrganizeImports mod mods + = mapM (\(k, m) -> ContentChanged . (k,) <$> localRefactoringRes id m (organizeImports m)) (mod:mods) + organizeImports :: forall dom . OrganizeImportsDomain dom => LocalRefactoring dom organizeImports mod - = modImports&annListElems !~ narrowImports usedNames . sortImports $ mod - where usedNames = map getName $ catMaybes $ map semanticsName + = do ms <- lift $ GHC.getModSummary (GHC.moduleName $ semanticsModule mod) + let th = xopt TemplateHaskell $ GHC.ms_hspp_opts ms + if th + then -- don't change the imports for template haskell modules + -- (we don't know what definitions the generated code will use) + return $ modImports .- sortImports $ mod + else modImports !~ narrowImports exportedModules usedNames prelInstances prelFamInsts . sortImports $ mod + where prelInstances = semanticsPrelOrphanInsts mod + prelFamInsts = semanticsPrelFamInsts mod + usedNames = map getName $ catMaybes $ map semanticsName -- obviously we don't want the names in the imports to be considered, but both from -- the declarations (used), both from the module head (re-exported) will count as usage $ (universeBi (mod ^. modHead) ++ universeBi (mod ^. modDecl) :: [QualifiedName dom]) + exportedModules = mod ^? modHead & annJust & mhExports & annJust + & espExports & annList & exportModuleName & moduleNameString -- | Sorts the imports in alphabetical order -sortImports :: [ImportDecl dom] -> [ImportDecl dom] -sortImports = sortBy (compare `on` (^. importModule&AST.moduleNameString)) +sortImports :: forall dom . ImportDeclList dom -> ImportDeclList dom +sortImports ls = srcInfo & srcTmpSeparators .= filter (not . null) (concatMap (\(sep,elems) -> sep : map fst elems) reordered) + $ annListElems .= concatMap (map snd . snd) reordered + $ ls + where reordered :: [(String, [(String, ImportDecl dom)])] + reordered = map (_2 .- sortBy (compare `on` (^. _2 & importModule & AST.moduleNameString))) parts + parts = map (_2 .- reverse) $ reverse $ breakApart [] imports + + breakApart :: [(String, [(String, ImportDecl dom)])] -> [(String, ImportDecl dom)] -> [(String, [(String, ImportDecl dom)])] + breakApart res [] = res + breakApart res ((sep, e) : rest) | length (filter ('\n' ==) sep) > 1 + = breakApart ((sep, [("",e)]) : res) rest + breakApart ((lastSep, lastRes) : res) (elem : rest) + = breakApart ((lastSep, elem : lastRes) : res) rest + breakApart [] ((sep, e) : rest) + = breakApart [(sep, [("",e)])] rest + + imports = zipWithSeparators ls + -- | Modify an import to only import names that are used. narrowImports :: forall dom . OrganizeImportsDomain dom - => [GHC.Name] -> [ImportDecl dom] -> LocalRefactor dom [ImportDecl dom] -narrowImports usedNames imps = foldM (narrowOneImport usedNames) imps imps - where narrowOneImport :: [GHC.Name] -> [ImportDecl dom] -> ImportDecl dom -> LocalRefactor dom [ImportDecl dom] - narrowOneImport names all one = - (\case Just x -> map (\e -> if e == one then x else e) all - Nothing -> delete one all) <$> narrowImport names (map semanticsImportedModule all) one + => [String] -> [GHC.Name] -> [ClsInst] -> [FamInst] -> ImportDeclList dom -> LocalRefactor dom (ImportDeclList dom) +narrowImports exportedModules usedNames prelInsts prelFamInsts imps + = annListElems & traversal !~ narrowImport exportedModules usedNames + $ filterListIndexed (\i _ -> neededImps !! i) imps + where neededImps = neededImports exportedModules usedNames prelInsts prelFamInsts (imps ^. annListElems) -- | Reduces the number of definitions used from an import narrowImport :: OrganizeImportsDomain dom - => [GHC.Name] -> [GHC.Module] -> ImportDecl dom - -> LocalRefactor dom (Maybe (ImportDecl dom)) -narrowImport usedNames otherModules imp + => [String] -> [GHC.Name] -> ImportDecl dom -> LocalRefactor dom (ImportDecl dom) +narrowImport exportedModules usedNames imp + | (imp ^. importModule & moduleNameString) `elem` exportedModules + || maybe False (`elem` exportedModules) (imp ^? importAs & annJust & importRename & moduleNameString) + = return imp -- dont change an import if it is exported as-is (module export) | importIsExact imp - = Just <$> (importSpec&annJust&importSpecList !~ narrowImportSpecs usedNames $ imp) - | otherwise - = if null actuallyImported - then if length (filter (== importedMod) otherModules) > 1 - then pure Nothing - else Just <$> (importSpec !- replaceWithJust (mkImportSpecList []) $ imp) - else pure (Just imp) + = importSpec&annJust&importSpecList !~ narrowImportSpecs usedNames $ imp + | otherwise + = do namedThings <- mapM lookupName actuallyImported + let -- to explicitely import pattern synonyms we need to enable an extension, and the user might not expect this + hasPatSyn = any (\case Just (AConLike (PatSynCon _)) -> True; _ -> False) namedThings + groups = groupThings (semanticsImported imp) (catMaybes namedThings) + return $ if not hasPatSyn && length groups < 4 + then importSpec .- replaceWithJust (createImportSpec groups) $ imp + else imp where actuallyImported = semanticsImported imp `intersect` usedNames - importedMod = semanticsImportedModule imp - + +groupThings :: [GHC.Name] -> [TyThing] -> [(GHC.Name, Bool)] +groupThings importable = nub . sort . map createImportFromTyThing + where createImportFromTyThing :: TyThing -> (GHC.Name, Bool) + createImportFromTyThing tt | Just td <- getTopDef tt + = if (td `elem` importable) then (td, True) + else (getName tt, False) + | otherwise = (getName tt, False) + +getTopDef :: TyThing -> Maybe GHC.Name +getTopDef (AnId id) | isRecordSelector id + = Just $ case recordSelectorTyCon id of RecSelData tc -> getName tc + RecSelPatSyn ps -> getName ps +getTopDef (AnId id) = fmap (getName . dataConTyCon) (isDataConWorkId_maybe id <|> isDataConId_maybe id) + <|> fmap getName (isClassOpId_maybe id) +getTopDef (AConLike (RealDataCon dc)) = Just (getName $ dataConTyCon dc) +getTopDef (AConLike (PatSynCon _)) = error "getTopDef: should not be called with pattern synonyms" +getTopDef tc@(ATyCon _) = Just (getName tc) + +createImportSpec :: [(GHC.Name, Bool)] -> ImportSpec dom +createImportSpec elems = mkImportSpecList $ map createIESpec elems + where createIESpec (n, False) = mkIESpec (mkUnqualName' (GHC.getName n)) Nothing + createIESpec (n, True) = mkIESpec (mkUnqualName' (GHC.getName n)) (Just mkSubAll) + +-- | Check each import if it is actually needed +neededImports :: OrganizeImportsDomain dom + => [String] -> [GHC.Name] -> [ClsInst] -> [FamInst] -> [ImportDecl dom] -> [Bool] +neededImports exportedModules usedNames prelInsts prelFamInsts imps = neededImports' usedNames [] imps + where neededImports' _ _ [] = [] + -- keep the import if any definition is needed from it + neededImports' usedNames kept (imp : rest) + | not (null actuallyImported) + || (imp ^. importModule & moduleNameString) `elem` exportedModules + || maybe False (`elem` exportedModules) (imp ^? importAs & annJust & importRename & moduleNameString) + = True : neededImports' usedNames (imp : kept) rest + where actuallyImported = semanticsImported imp `intersect` usedNames + neededImports' usedNames kept (imp : rest) + = needed : neededImports' usedNames (if needed then imp : kept else kept) rest + where needed = any (`notElem` otherClsInstances) (map is_dfun $ semanticsOrphanInsts imp) + || any (`notElem` otherFamInstances) (map fi_axiom $ semanticsFamInsts imp) + otherClsInstances = map is_dfun (concatMap semanticsOrphanInsts kept ++ prelInsts) + otherFamInstances = map fi_axiom (concatMap semanticsFamInsts kept ++ prelFamInsts) + -- | Narrows the import specification (explicitely imported elements) narrowImportSpecs :: forall dom . OrganizeImportsDomain dom => [GHC.Name] -> IESpecList dom -> LocalRefactor dom (IESpecList dom) @@ -95,3 +174,5 @@ narrowImportSubspecs _ ss@SubAll = ss narrowImportSubspecs usedNames ss@(SubList {}) = essList .- filterList (\n -> fmap getName (semanticsName =<< (n ^? simpleName)) `elem` map Just usedNames) $ ss + +
Language/Haskell/Tools/Refactor/Predefined/RenameDefinition.hs view
@@ -9,22 +9,16 @@ #-} module Language.Haskell.Tools.Refactor.Predefined.RenameDefinition (renameDefinition, renameDefinition', DomainRenameDefinition) where -import Name hiding (Name) -import GHC (Ghc, TyThing(..), lookupName) -import qualified GHC -import OccName -import SrcLoc -import Outputable -import Unique +import qualified GHC (RealSrcSpan(..), NamedThing(..), Name(..)) +import Name (OccName(..), NamedThing(..), occNameString) +import SrcLoc (RealSrcSpan(..)) -import Control.Reference as Ref import Control.Monad.State -import Control.Monad.Trans.Except -import Data.Data -import Data.List.Split +import Control.Reference as Ref +import Data.Generics.Uniplate.Data () import Data.List +import Data.List.Split (splitOn) import Data.Maybe -import Data.Generics.Uniplate.Data import Language.Haskell.Tools.Refactor
Language/Haskell/Tools/Refactor/Prepare.hs view
@@ -13,38 +13,29 @@ -- | Defines utility methods that prepare Haskell modules for refactoring module Language.Haskell.Tools.Refactor.Prepare where +import CmdLineParser +import DynFlags +import FastString import GHC hiding (loadModule) import qualified GHC (loadModule) -import Panic (handleGhcException) -import Outputable -import BasicTypes -import Bag -import Var -import SrcLoc -import Module as GHC -import FastString -import HscTypes import GHC.Paths ( libdir ) -import CmdLineParser -import DynFlags -import StringBuffer +import SrcLoc import Control.Monad import Control.Monad.IO.Class -import System.FilePath -import Data.Maybe -import Data.List (isInfixOf, (\\)) -import Data.List.Split -import System.Info (os) -import System.Directory import Data.IntSet (member) +import Data.List ((\\)) +import Data.List.Split +import Data.Maybe import Language.Haskell.TH.LanguageExtensions +import System.Directory +import System.FilePath import Language.Haskell.Tools.AST as AST import Language.Haskell.Tools.AST.FromGHC import Language.Haskell.Tools.PrettyPrint -import Language.Haskell.Tools.Transform import Language.Haskell.Tools.Refactor.RefactorBase +import Language.Haskell.Tools.Transform tryRefactor :: (RealSrcSpan -> Refactoring IdDom) -> String -> String -> IO () tryRefactor refact moduleName span @@ -62,6 +53,7 @@ correctRefactorSpan mod sp = mkRealSrcSpan (updateSrcFile fileName $ realSrcSpanStart sp) (updateSrcFile fileName $ realSrcSpanEnd sp) where fileName = case srcSpanStart $ getRange mod of RealSrcLoc loc -> srcLocFile loc + _ -> error "correctRefactorSpan: no real span" updateSrcFile fn loc = mkRealSrcLoc fn (srcLocLine loc) (srcLocCol loc) -- | Set the given flags for the GHC session @@ -69,8 +61,9 @@ useFlags args = do let lArgs = map (L noSrcSpan) args dynflags <- getSessionDynFlags - let ((leftovers, errors, warnings), newDynFlags) = (runCmdLine $ processArgs flagsAll lArgs) dynflags - setSessionDynFlags newDynFlags + -- TODO: print errors and warnings? + let ((leftovers, _, _), newDynFlags) = (runCmdLine $ processArgs flagsAll lArgs) dynflags + void $ setSessionDynFlags newDynFlags return $ map unLoc leftovers -- | Initialize GHC flags to default values that support refactoring @@ -130,7 +123,7 @@ useDirs [workingDir] target <- guessTarget moduleName Nothing setTargets [target] - load (LoadUpTo $ mkModuleName moduleName) + void $ load (LoadUpTo $ mkModuleName moduleName) getModSummary $ mkModuleName moduleName -- | The final version of our AST, with type infromation added @@ -144,7 +137,7 @@ ms = if hasStaticFlags then forceAsmGen (modSumNormalizeFlags modSum) else (modSumNormalizeFlags modSum) p <- parseModule ms tc <- typecheckModule p - GHC.loadModule tc -- when used with loadModule, the module will be loaded twice + void $ GHC.loadModule tc -- when used with loadModule, the module will be loaded twice let annots = pm_annotations p srcBuffer = fromJust $ ms_hspp_buf $ pm_mod_summary p prepareAST srcBuffer . placeComments (getNormalComments $ snd annots) @@ -159,9 +152,9 @@ withAlteredDynFlags :: GhcMonad m => (DynFlags -> m DynFlags) -> m a -> m a withAlteredDynFlags modDFs action = do dfs <- getSessionDynFlags - setSessionDynFlags =<< modDFs dfs + void $ setSessionDynFlags =<< modDFs dfs res <- action - setSessionDynFlags dfs + void $ setSessionDynFlags dfs return res -- | Forces the code generation for a given module @@ -191,4 +184,5 @@ readSrcLoc :: String -> RealSrcLoc readSrcLoc s = case splitOn ":" s of - [line,col] -> mkRealSrcLoc (mkFastString "file-name-should-be-fixed") (read line) (read col)+ [line,col] -> mkRealSrcLoc (mkFastString "file-name-should-be-fixed") (read line) (read col) + _ -> error "readSrcLoc: panic: splitOn gives empty list"
Language/Haskell/Tools/Refactor/RefactorBase.hs view
@@ -13,25 +13,26 @@ import Language.Haskell.Tools.AST as AST import Language.Haskell.Tools.AST.Rewrite -import Language.Haskell.Tools.Transform -import GHC (Ghc, GhcMonad(..), TyThing(..), lookupName) -import Exception (ExceptionMonad(..)) + import DynFlags (HasDynFlags(..)) -import qualified Name as GHC +import Exception (ExceptionMonad(..)) +import GHC (Ghc, GhcMonad(..), TyThing(..), lookupName) import qualified Module as GHC +import qualified Name as GHC import qualified PrelNames as GHC import qualified TyCon as GHC import qualified TysWiredIn as GHC + +import Control.Monad.Reader +import Control.Monad.State +import Control.Monad.Trans.Except +import Control.Monad.Writer import Control.Reference hiding (element) +import Data.Char import Data.Function (on) import Data.List import Data.List.Split import Data.Maybe -import Data.Char -import Control.Monad.Reader -import Control.Monad.Trans.Except -import Control.Monad.Writer -import Control.Monad.State type UnnamedModule dom = Ann AST.UModule dom SrcTemplateStage @@ -67,7 +68,7 @@ show (ModuleCreated n _ other) = "ModuleCreated " ++ n ++ " (" ++ show other ++ ")" -- | Performs the given refactoring, transforming it into a Ghc action -runRefactor :: (HasModuleInfo dom) => ModuleDom dom -> [ModuleDom dom] -> Refactoring dom -> Ghc (Either String [RefactorChange dom]) +runRefactor :: ModuleDom dom -> [ModuleDom dom] -> Refactoring dom -> Ghc (Either String [RefactorChange dom]) runRefactor mod mods trf = runExceptT $ trf mod mods -- | Wraps a refactoring that only affects one module. Performs the per-module finishing touches. @@ -231,12 +232,13 @@ -- | Get which category does a given name belong to classifyName :: RefactorMonad m => GHC.Name -> m NameClass classifyName n = liftGhc (lookupName n) >>= return . \case - Just (AnId id) | isop -> ValueOperator - Just (AnId id) -> Variable - Just (AConLike id) | isop -> DataCtorOperator - Just (AConLike id) -> Ctor - Just (ATyCon id) | isop -> SynonymOperator - Just (ATyCon id) -> Ctor + Just (AnId {}) | isop -> ValueOperator + Just (AnId {}) -> Variable + Just (AConLike {}) | isop -> DataCtorOperator + Just (AConLike {}) -> Ctor + Just (ATyCon {}) | isop -> SynonymOperator + Just (ATyCon {}) -> Ctor + Just (ACoAxiom {}) -> error "classifyName: ACoAxiom" Nothing | isop -> ValueOperator Nothing -> Variable where isop = GHC.isSymOcc (GHC.getOccName n) @@ -247,8 +249,8 @@ -- | Check if a given name is valid for a given kind of definition nameValid :: NameClass -> String -> Bool -nameValid n "" = False -nameValid n str | str `elem` reservedNames = False +nameValid _ "" = False +nameValid _ str | str `elem` reservedNames = False where -- TODO: names reserved by extensions reservedNames = [ "case", "class", "data", "default", "deriving", "do", "else", "if", "import", "in", "infix" , "infixl", "infixr", "instance", "let", "module", "newtype", "of", "then", "type", "where", "_" @@ -271,7 +273,10 @@ = isLower c && isIdStartChar c && all (\c -> isIdStartChar c || isDigit c) nameRest nameValid _ _ = False +isIdStartChar :: Char -> Bool isIdStartChar c = (isLetter c && isAscii c) || c == '\'' || c == '_' + +isOperatorChar :: Char -> Bool isOperatorChar c = (isPunctuation c || isSymbol c) && isAscii c makeReferences ''SourceFileKey
Language/Haskell/Tools/Refactor/Session.hs view
@@ -3,30 +3,26 @@ #-} module Language.Haskell.Tools.Refactor.Session where -import qualified Data.Map as Map -import qualified Data.List as List -import Data.Maybe -import Data.Function (on) import Control.Monad.State import Control.Reference -import System.IO +import qualified Data.List as List +import qualified Data.Map as Map +import Data.Maybe import System.FilePath -import Debug.Trace -import GHC -import Outputable -import ErrUtils -import GhcMonad as GHC -import HscTypes as GHC +import Data.IntSet (member) import Digraph as GHC -import DynFlags as GHC +import ErrUtils +import Exception (ExceptionMonad) import FastString as GHC -import Data.IntSet (member) +import GHC +import HscTypes as GHC import Language.Haskell.TH.LanguageExtensions +import Outputable -import Language.Haskell.Tools.AST (IdDom, semanticsModule) -import Language.Haskell.Tools.Refactor.Prepare +import Language.Haskell.Tools.AST (IdDom) import Language.Haskell.Tools.Refactor.GetModules +import Language.Haskell.Tools.Refactor.Prepare import Language.Haskell.Tools.Refactor.RefactorBase data RefactorSessionState @@ -52,15 +48,14 @@ lift $ useDirs (modColls ^? traversal & mcSourceDirs & traversal) let (ignored, modNames) = extractDuplicates $ map (^. sfkModuleName) $ concat $ map Map.keys $ modColls ^? traversal & mcModules alreadyExistingMods = concatMap (map (^. sfkModuleName) . Map.keys . (^. mcModules)) (allModColls List.\\ modColls) - lift $ mapM addTarget $ map (\mod -> (Target (TargetModule (GHC.mkModuleName mod)) True Nothing)) modNames - handleSourceError (return . Left . concat . List.intersperse "\n\n" . map showSDocUnsafe . pprErrMsgBagWithLoc . srcErrorMessages) $ - withAlteredDynFlags (return . enableAllPackages allModColls) $ do - modsForColls <- lift $ depanal [] True - let modsToParse = flattenSCCs $ topSortModuleGraph False modsForColls Nothing - actuallyCompiled = filter (not . (`elem` alreadyExistingMods) . modSumName) modsToParse - checkEvaluatedMods report modsToParse - mods <- mapM (loadModule report) actuallyCompiled - return $ Right (mods, ignored) + lift $ mapM_ addTarget $ map (\mod -> (Target (TargetModule (GHC.mkModuleName mod)) True Nothing)) modNames + handleErrors $ withAlteredDynFlags (return . enableAllPackages allModColls) $ do + modsForColls <- lift $ depanal [] True + let modsToParse = flattenSCCs $ topSortModuleGraph False modsForColls Nothing + actuallyCompiled = filter (not . (`elem` alreadyExistingMods) . modSumName) modsToParse + void $ checkEvaluatedMods report modsToParse + mods <- mapM (loadModule report) actuallyCompiled + return (mods, ignored) where extractDuplicates :: Eq a => [a] -> ([a],[a]) extractDuplicates (a:rest) @@ -72,6 +67,10 @@ needsCodeGen <- gets (needsGeneratedCode (keyFromMS ms) . (^. refSessMCs)) reloadModule report (if needsCodeGen then forceCodeGen ms else ms) +handleErrors :: ExceptionMonad m => m a -> m (Either String a) +handleErrors action = handleSourceError (return . Left . errorsText) (Right <$> action) + where errorsText = concat . List.intersperse "\n\n" . map showSDocUnsafe . pprErrMsgBagWithLoc . srcErrorMessages + keyFromMS :: ModSummary -> SourceFileKey keyFromMS ms = SourceFileKey (case ms_hsc_src ms of HsSrcFile -> NormalHs; _ -> IsHsBoot) (modSumName ms) @@ -94,10 +93,10 @@ case sfs of sf:_ -> getMods (Just sf) [] -> getMods Nothing -reloadChangedModules :: IsRefactSessionState st => (ModSummary -> IO a) -> (ModSummary -> Bool) -> StateT st Ghc [a] -reloadChangedModules report isChanged = do +reloadChangedModules :: IsRefactSessionState st => (ModSummary -> IO a) -> (ModSummary -> Bool) -> StateT st Ghc (Either String [a]) +reloadChangedModules report isChanged = handleErrors $ do reachable <- getReachableModules isChanged - checkEvaluatedMods report reachable + void $ checkEvaluatedMods report reachable mapM (reloadModule report) reachable getReachableModules :: IsRefactSessionState st => (ModSummary -> Bool) -> StateT st Ghc [ModSummary] @@ -147,10 +146,9 @@ codeGenForModule report mcs ms = let modName = modSumName ms Just mc = lookupModuleColl modName mcs - Just rec = lookupModInSCs (keyFromMS ms) mcs in -- TODO: don't recompile, only load? do withAlteredDynFlags (liftIO . compileInContext mc mcs) - $ parseTyped (forceCodeGen ms) + $ void $ parseTyped (forceCodeGen ms) liftIO $ report ms -- | Check which modules can be reached from the module, if it uses template haskell.
+ examples/Decl/LocalBindingInDo.hs view
@@ -0,0 +1,7 @@+module Decl.LocalBindingInDo where + +x :: Maybe () +x = do let y = f a + where a = () + return y + where f = id
examples/Module/Import.hs view
@@ -8,3 +8,4 @@ import Data.List as List import Data.List(map,(++)) import Data.Function hiding ((&)) +import Control.Monad.Writer hiding (Alt)
+ examples/Module/PatternImport.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE PatternSynonyms #-} +module Module.PatternImport where + +import Decl.PatternSynonym (pattern Arrow)
examples/Refactor/OrganizeImports/Class_res.hs view
@@ -1,6 +1,6 @@ module Refactor.OrganizeImports.Class where import Decl.TypeClass (C(f)) -import Decl.TypeInstance +import Decl.TypeInstance (A(..)) test = f A
+ examples/Refactor/OrganizeImports/InstanceCarry/DataType.hs view
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.DataType where + +data A = A
+ examples/Refactor/OrganizeImports/InstanceCarry/ImportNonOrphan.hs view
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.ImportNonOrphan where + +import Refactor.OrganizeImports.InstanceCarry.TCWithInst ()
+ examples/Refactor/OrganizeImports/InstanceCarry/ImportNonOrphan_res.hs view
@@ -0,0 +1,2 @@+module Refactor.OrganizeImports.InstanceCarry.ImportNonOrphan where +
+ examples/Refactor/OrganizeImports/InstanceCarry/ImportOrphan.hs view
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.ImportOrphan where + +import Refactor.OrganizeImports.InstanceCarry.OrphanInstance ()
+ examples/Refactor/OrganizeImports/InstanceCarry/ImportOrphan_res.hs view
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.InstanceCarry.ImportOrphan where + +import Refactor.OrganizeImports.InstanceCarry.OrphanInstance ()
+ examples/Refactor/OrganizeImports/InstanceCarry/OrphanInstance.hs view
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.InstanceCarry.OrphanInstance where + +import Refactor.OrganizeImports.InstanceCarry.DataType +import Refactor.OrganizeImports.InstanceCarry.TypeClass + +instance C A where + f = id
+ examples/Refactor/OrganizeImports/InstanceCarry/TCWithInst.hs view
@@ -0,0 +1,9 @@+module Refactor.OrganizeImports.InstanceCarry.TCWithInst where + +import Refactor.OrganizeImports.InstanceCarry.DataType + +class D t where + g :: t -> t + +instance D A where + g = id
+ examples/Refactor/OrganizeImports/InstanceCarry/TypeClass.hs view
@@ -0,0 +1,4 @@+module Refactor.OrganizeImports.InstanceCarry.TypeClass where + +class C t where + f :: t -> t
+ examples/Refactor/OrganizeImports/KeepReexported.hs view
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.KeepReexported (module Control.Monad) where + +import Control.Monad
+ examples/Refactor/OrganizeImports/KeepReexported_res.hs view
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.KeepReexported (module Control.Monad) where + +import Control.Monad
+ examples/Refactor/OrganizeImports/KeepRenamedReexported.hs view
@@ -0,0 +1,4 @@+module Refactor.OrganizeImports.KeepRenamedReexported (module X) where + +import Control.Monad as X +import Data.Maybe as X
+ examples/Refactor/OrganizeImports/KeepRenamedReexported_res.hs view
@@ -0,0 +1,4 @@+module Refactor.OrganizeImports.KeepRenamedReexported (module X) where + +import Control.Monad as X +import Data.Maybe as X
+ examples/Refactor/OrganizeImports/MakeExplicit/ClassSource.hs view
@@ -0,0 +1,11 @@+module Refactor.OrganizeImports.MakeExplicit.ClassSource where + +class D a where + f :: a + +instance D () where + f = () + +g :: D a => a +g = f +
+ examples/Refactor/OrganizeImports/MakeExplicit/FunSource.hs view
@@ -0,0 +1,3 @@+module Refactor.OrganizeImports.MakeExplicit.FunSource (f) where + +import Refactor.OrganizeImports.MakeExplicit.ClassSource
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportClassFun.hs view
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportClassFun where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x :: () +x = f +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportClassFun_res.hs view
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportClassFun where + +import Refactor.OrganizeImports.MakeExplicit.Source (D(..)) + +x :: () +x = f +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportCon.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportCon where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = B +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportCon_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportCon where + +import Refactor.OrganizeImports.MakeExplicit.Source (A(..)) + +x = B +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportFour.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFour where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = (a,b,e,g) +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportFour_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFour where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = (a,b,e,g) +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportFunHiddenClass.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunHiddenClass where + +import Refactor.OrganizeImports.MakeExplicit.FunSource + +h :: () +h = f
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportFunHiddenClass_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunHiddenClass where + +import Refactor.OrganizeImports.MakeExplicit.FunSource (f) + +h :: () +h = f
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportFunOutOfClass.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunOutOfClass where + +import Refactor.OrganizeImports.MakeExplicit.ClassSource + +h :: () +h = g
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportFunOutOfClass_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportFunOutOfClass where + +import Refactor.OrganizeImports.MakeExplicit.ClassSource (g) + +h :: () +h = g
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportOne.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportOne where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = a +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportOne_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportOne where + +import Refactor.OrganizeImports.MakeExplicit.Source (a) + +x = a +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportRecordSel.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportRecordSel where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = b +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportRecordSel_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportRecordSel where + +import Refactor.OrganizeImports.MakeExplicit.Source (A(..)) + +x = b +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportThree.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportThree where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = (a,e,g) +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportThree_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.MakeExplicit.ImportThree where + +import Refactor.OrganizeImports.MakeExplicit.Source (a, e, g) + +x = (a,e,g) +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportUnited.hs view
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnited where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = B () +y = b x +
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportUnitedCount.hs view
@@ -0,0 +1,8 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnitedCount where + +import Refactor.OrganizeImports.MakeExplicit.Source + +x = B () +y = b x +z = a +w = e
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportUnitedCount_res.hs view
@@ -0,0 +1,8 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnitedCount where + +import Refactor.OrganizeImports.MakeExplicit.Source (A(..), a, e) + +x = B () +y = b x +z = a +w = e
+ examples/Refactor/OrganizeImports/MakeExplicit/ImportUnited_res.hs view
@@ -0,0 +1,7 @@+module Refactor.OrganizeImports.MakeExplicit.ImportUnited where + +import Refactor.OrganizeImports.MakeExplicit.Source (A(..)) + +x = B () +y = b x +
+ examples/Refactor/OrganizeImports/MakeExplicit/Source.hs view
@@ -0,0 +1,15 @@+module Refactor.OrganizeImports.MakeExplicit.Source where + +a = () +e = () +g = () + +data A = B { b :: () } + | C + +class D a where + f :: a + +instance D () where + f = () +
+ examples/Refactor/OrganizeImports/NarrowQual.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.NarrowQual where + +import Data.List +import Data.List as L + +test = intersperse 0 $ L.map (+1) [1..10]
+ examples/Refactor/OrganizeImports/NarrowQual_res.hs view
@@ -0,0 +1,6 @@+module Refactor.OrganizeImports.NarrowQual where + +import Data.List (map, intersperse) +import Data.List as L (map, intersperse) + +test = intersperse 0 $ L.map (+1) [1..10]
examples/Refactor/OrganizeImports/Removed.hs view
@@ -1,5 +1,3 @@ module Refactor.OrganizeImports.Removed where -import Control.Monad -import Control.Monad as Monad - +import Control.Monad ()
examples/Refactor/OrganizeImports/Removed_res.hs view
@@ -1,4 +1,2 @@ module Refactor.OrganizeImports.Removed where -import Control.Monad as Monad () -
examples/Refactor/OrganizeImports/Reorder.hs view
@@ -1,5 +1,7 @@ module Refactor.OrganizeImports.Reorder where -import Data.List () -import Control.Monad () +import Data.List (intersperse) +import Control.Monad ((>>=)) +x = intersperse '-' "abc" +y = Just () >>= \_ -> Nothing
+ examples/Refactor/OrganizeImports/ReorderComment.hs view
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderComment where + +import Data.List (intersperse) +import Control.Monad ((>>=)) +-- some comment +import Data.Tuple (swap) +import Data.Maybe (catMaybes) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
+ examples/Refactor/OrganizeImports/ReorderComment_res.hs view
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderComment where + +import Control.Monad ((>>=)) +import Data.List (intersperse) +import Data.Maybe (catMaybes) +-- some comment +import Data.Tuple (swap) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
+ examples/Refactor/OrganizeImports/ReorderGroups.hs view
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderGroups where + +import Data.List (intersperse) +import Control.Monad ((>>=)) + +import Data.Tuple (swap) +import Data.Maybe (catMaybes) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
+ examples/Refactor/OrganizeImports/ReorderGroups_res.hs view
@@ -0,0 +1,12 @@+module Refactor.OrganizeImports.ReorderGroups where + +import Control.Monad ((>>=)) +import Data.List (intersperse) + +import Data.Maybe (catMaybes) +import Data.Tuple (swap) + +a = intersperse '-' "abc" +b = Just () >>= \_ -> Nothing +c = catMaybes [Just ()] +d = swap ("a","b")
examples/Refactor/OrganizeImports/Reorder_res.hs view
@@ -1,5 +1,7 @@ module Refactor.OrganizeImports.Reorder where -import Control.Monad () -import Data.List () +import Control.Monad ((>>=)) +import Data.List (intersperse) +x = intersperse '-' "abc" +y = Just () >>= \_ -> Nothing
− examples/Refactor/OrganizeImports/Unused.hs
@@ -1,4 +0,0 @@-module Refactor.OrganizeImports.Unused where - -import Control.Monad -
− examples/Refactor/OrganizeImports/Unused_res.hs
@@ -1,4 +0,0 @@-module Refactor.OrganizeImports.Unused where - -import Control.Monad () -
haskell-tools-refactor.cabal view
@@ -1,5 +1,5 @@ name: haskell-tools-refactor -version: 0.4.1.1 +version: 0.4.1.2 synopsis: Refactoring Tool for Haskell description: Contains a set of refactorings based on the Haskell-Tools framework to easily transform a Haskell program. For the descriptions of the implemented refactorings, see the homepage. homepage: https://github.com/haskell-tools/haskell-tools @@ -30,6 +30,8 @@ , examples/Refactor/InlineBinding/*.hs , examples/Refactor/InlineBinding/AppearsInAnother/*.hs , examples/Refactor/OrganizeImports/*.hs + , examples/Refactor/OrganizeImports/MakeExplicit/*.hs + , examples/Refactor/OrganizeImports/InstanceCarry/*.hs , examples/Refactor/RenameDefinition/*.hs , examples/Refactor/RenameDefinition/MultiModule/*.hs , examples/Refactor/RenameDefinition/MultiModule_res/*.hs @@ -104,8 +106,6 @@ , references >= 0.3 && < 0.4 , split >= 0.2 && < 0.3 , time >= 1.6 && < 1.7 - , old-time >= 1.1 && < 1.2 - , polyparse >= 1.12 && < 1.13 , template-haskell >= 2.11 && < 2.12 , ghc >= 8.0 && < 8.1 , ghc-paths >= 0.1 && < 0.2
test/Main.hs view
@@ -102,6 +102,7 @@ , "Decl.InstanceOverlaps" , "Decl.InstanceSpec" , "Decl.LocalBindings" + , "Decl.LocalBindingInDo" , "Decl.LocalFixity" , "Decl.MultipleFixity" , "Decl.MultipleSigs" @@ -148,6 +149,7 @@ , "Module.Export" , "Module.NamespaceExport" , "Module.Import" + , "Module.PatternImport" , "Pattern.Backtick" , "Pattern.Constructor" , "Pattern.ImplicitParams" @@ -198,12 +200,28 @@ organizeImportTests = [ "Refactor.OrganizeImports.Narrow" , "Refactor.OrganizeImports.Reorder" - , "Refactor.OrganizeImports.Unused" , "Refactor.OrganizeImports.Ctor" , "Refactor.OrganizeImports.Class" , "Refactor.OrganizeImports.Operator" , "Refactor.OrganizeImports.SameName" , "Refactor.OrganizeImports.Removed" + , "Refactor.OrganizeImports.ReorderGroups" + , "Refactor.OrganizeImports.ReorderComment" + , "Refactor.OrganizeImports.KeepReexported" + , "Refactor.OrganizeImports.KeepRenamedReexported" + , "Refactor.OrganizeImports.MakeExplicit.ImportOne" + , "Refactor.OrganizeImports.MakeExplicit.ImportThree" + , "Refactor.OrganizeImports.MakeExplicit.ImportClassFun" + , "Refactor.OrganizeImports.MakeExplicit.ImportCon" + , "Refactor.OrganizeImports.MakeExplicit.ImportRecordSel" + , "Refactor.OrganizeImports.MakeExplicit.ImportUnited" + , "Refactor.OrganizeImports.MakeExplicit.ImportUnitedCount" + , "Refactor.OrganizeImports.MakeExplicit.ImportFour" + , "Refactor.OrganizeImports.MakeExplicit.ImportFunHiddenClass" + , "Refactor.OrganizeImports.MakeExplicit.ImportFunOutOfClass" + , "Refactor.OrganizeImports.InstanceCarry.ImportOrphan" + , "Refactor.OrganizeImports.InstanceCarry.ImportNonOrphan" + , "Refactor.OrganizeImports.NarrowQual" ] generateSignatureTests =