module Language.Haskell.Tools.Refactor.Perform where
import Data.List.Split
import Language.Haskell.Tools.AST as AST
import Language.Haskell.Tools.Refactor.Predefined.ExtractBinding
import Language.Haskell.Tools.Refactor.Predefined.FloatOut
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.Predefined.OrganizeImports
import Language.Haskell.Tools.Refactor.Predefined.RenameDefinition
import Language.Haskell.Tools.Refactor.Prepare
import Language.Haskell.Tools.Refactor.RefactorBase
import GHC
performCommand :: (HasModuleInfo dom, DomGenerateExports dom, OrganizeImportsDomain dom, DomainRenameDefinition dom, ExtractBindingDomain dom, GenerateSignatureDomain dom)
=> RefactorCommand -> ModuleDom dom
-> [ModuleDom dom]
-> Ghc (Either String [RefactorChange dom])
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
selectCommand (ExtractBinding sp str) = localRefactoring $ extractBinding' (correctRefactorSpan (snd mod) sp) str
selectCommand (InlineBinding sp) = inlineBinding (correctRefactorSpan (snd mod) sp)
selectCommand (FloatOut sp) = localRefactoring $ floatOut (correctRefactorSpan (snd mod) sp)
data RefactorCommand = NoRefactor
| OrganizeImports
| ProjectOrganizeImports
| GenerateExports
| GenerateSignature RealSrcSpan
| RenameDefinition RealSrcSpan String
| ExtractBinding RealSrcSpan String
| InlineBinding RealSrcSpan
| FloatOut RealSrcSpan
deriving Show
readCommand :: String -> Either String RefactorCommand
readCommand (splitOn " " -> refact:args) = analyzeCommand refact args
readCommand _ = error "panic: splitOn resulted empty"
analyzeCommand :: String -> [String] -> Either String RefactorCommand
analyzeCommand "" _ = Right NoRefactor
analyzeCommand "CheckSource" _ = Right NoRefactor
analyzeCommand "OrganizeImports" _ = Right OrganizeImports
analyzeCommand "ProjectOrganizeImports" _ = Right ProjectOrganizeImports
analyzeCommand "GenerateExports" _ = Right GenerateExports
analyzeCommand "GenerateSignature" [sp] = Right $ GenerateSignature (readSrcSpan sp)
analyzeCommand "GenerateSignature" _ = Left $ "GenerateSignature needs one argument: the source range of the definition"
analyzeCommand "RenameDefinition" [sp, newName] = Right $ RenameDefinition (readSrcSpan sp) newName
analyzeCommand "RenameDefinition" _ = Left $ "RenameDefinition needs two arguments: the source range of the name and the new name"
analyzeCommand "ExtractBinding" [sp, newName] = Right $ ExtractBinding (readSrcSpan sp) newName
analyzeCommand "ExtractBinding" _ = Left $ "RenameDefinition needs two arguments: the source range of the expression and the new name"
analyzeCommand "InlineBinding" [sp] = Right $ InlineBinding (readSrcSpan sp)
analyzeCommand "InlineBinding" _ = Left $ "InlineBinding needs one argument: the source range of the definition"
analyzeCommand "FloatOut" [sp] = Right $ FloatOut (readSrcSpan sp)
analyzeCommand "FloatOut" _ = Left $ "FloatOut needs one argument: the source range of the definition"
analyzeCommand ref _ = Left $ "Unknown command: " ++ ref
refactorCommands :: [String]
refactorCommands
= [ "CheckSource", "OrganizeImports", "ProjectOrganizeImports", "GenerateExports"
, "GenerateSignature", "RenameDefinition", "ExtractBinding", "InlineBinding"
, "FloatOut" ]