Hello community,

here is the log from the commit of package ghc-haskell-tools-daemon for 
openSUSE:Factory checked in at 2017-08-31 20:55:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-haskell-tools-daemon (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-haskell-tools-daemon.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-haskell-tools-daemon"

Thu Aug 31 20:55:58 2017 rev:2 rq:513371 version:0.8.0.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/ghc-haskell-tools-daemon/ghc-haskell-tools-daemon.changes
        2017-04-12 18:06:44.546333345 +0200
+++ 
/work/SRC/openSUSE:Factory/.ghc-haskell-tools-daemon.new/ghc-haskell-tools-daemon.changes
   2017-08-31 20:55:58.975467845 +0200
@@ -1,0 +2,5 @@
+Thu Jul 27 14:06:15 UTC 2017 - [email protected]
+
+- Update to version 0.8.0.0.
+
+-------------------------------------------------------------------

Old:
----
  haskell-tools-daemon-0.5.0.0.tar.gz

New:
----
  haskell-tools-daemon-0.8.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-haskell-tools-daemon.spec ++++++
--- /var/tmp/diff_new_pack.hgiBmJ/_old  2017-08-31 20:56:00.067314437 +0200
+++ /var/tmp/diff_new_pack.hgiBmJ/_new  2017-08-31 20:56:00.083312189 +0200
@@ -19,7 +19,7 @@
 %global pkg_name haskell-tools-daemon
 %bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        0.5.0.0
+Version:        0.8.0.0
 Release:        0
 Summary:        Background process for Haskell-tools refactor that editors can 
connect to
 License:        BSD-3-Clause
@@ -28,6 +28,7 @@
 Source0:        
https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz
 BuildRequires:  chrpath
 BuildRequires:  ghc-Cabal-devel
+BuildRequires:  ghc-Diff-devel
 BuildRequires:  ghc-aeson-devel
 BuildRequires:  ghc-bytestring-devel
 BuildRequires:  ghc-containers-devel
@@ -44,6 +45,7 @@
 BuildRequires:  ghc-references-devel
 BuildRequires:  ghc-rpm-macros
 BuildRequires:  ghc-split-devel
+BuildRequires:  ghc-strict-devel
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 %if %{with tests}
 BuildRequires:  ghc-HUnit-devel

++++++ haskell-tools-daemon-0.5.0.0.tar.gz -> 
haskell-tools-daemon-0.8.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/Language/Haskell/Tools/Refactor/Daemon/PackageDB.hs
 
new/haskell-tools-daemon-0.8.0.0/Language/Haskell/Tools/Refactor/Daemon/PackageDB.hs
--- 
old/haskell-tools-daemon-0.5.0.0/Language/Haskell/Tools/Refactor/Daemon/PackageDB.hs
        2017-01-31 20:47:45.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/Language/Haskell/Tools/Refactor/Daemon/PackageDB.hs
        2017-05-03 22:13:55.000000000 +0200
@@ -1,11 +1,13 @@
 {-# LANGUAGE DeriveGeneric #-}
 module Language.Haskell.Tools.Refactor.Daemon.PackageDB where
 
+import Control.Applicative (Applicative(..), (<$>), Alternative(..))
+import Control.Monad
 import Data.Aeson (FromJSON(..))
 import Data.Char (isSpace)
 import Data.List
 import GHC.Generics (Generic(..))
-import System.Directory (withCurrentDirectory, doesFileExist, 
doesDirectoryExist)
+import System.Directory
 import System.FilePath (FilePath, (</>))
 import System.Process (readProcessWithExitCode)
 
@@ -18,9 +20,6 @@
 
 instance FromJSON PackageDB
 
-packageDBLocs :: PackageDB -> [FilePath] -> IO [FilePath]
-packageDBLocs pack = fmap concat . mapM (packageDBLoc pack) 
-
 packageDBLoc :: PackageDB -> FilePath -> IO [FilePath]
 packageDBLoc AutoDB path = (++) <$> packageDBLoc StackDB path <*> packageDBLoc 
CabalSandboxDB path
 packageDBLoc DefaultDB _ = return []
@@ -32,14 +31,43 @@
                                      else return ""
   return $ map (drop (length "package-db: ")) $ filter ("package-db: " 
`isPrefixOf`) $ lines config
 packageDBLoc StackDB path = withCurrentDirectory path $ do
-     (_, snapshotDB, snapshotDBErrs) <- readProcessWithExitCode "stack" 
["path", "--snapshot-pkg-db"] ""
-     (_, localDB, localDBErrs) <- readProcessWithExitCode "stack" ["path", 
"--local-pkg-db"] ""
+     (_, snapshotDB, snapshotDBErrs) <- readProcessWithExitCode "stack" 
["path", "--allow-different-user", "--snapshot-pkg-db"] ""
+     (_, localDB, localDBErrs) <- readProcessWithExitCode "stack" ["path", 
"--allow-different-user", "--local-pkg-db"] ""
      return $ [trim localDB | null localDBErrs] ++ [trim snapshotDB | null 
snapshotDBErrs]
 packageDBLoc (ExplicitDB dir) path = do
   hasDir <- doesDirectoryExist (path </> dir)
   if hasDir then return [path </> dir]
             else return []
 
+-- | Gets the (probable) location of autogen folder depending on which type of
+-- build we are using.
+detectAutogen :: FilePath -> PackageDB -> IO (Maybe FilePath)
+detectAutogen root AutoDB = do
+  defDB <- detectAutogen root DefaultDB
+  sandboxDB <- detectAutogen root CabalSandboxDB
+  stackDB <- detectAutogen root StackDB
+  return $ choose [ defDB, sandboxDB, stackDB ]
+detectAutogen root DefaultDB = ifExists (root </> "dist" </> "build" </> 
"autogen")
+detectAutogen root (ExplicitDB _) = ifExists (root </> "dist" </> "build" </> 
"autogen")
+detectAutogen root CabalSandboxDB = ifExists (root </> "dist" </> "build" </> 
"autogen")
+detectAutogen root StackDB = do
+  distExists <- doesDirectoryExist (root </> ".stack-work" </> "dist")
+  existing <- if distExists then (do
+    contents <- listDirectory (root </> ".stack-work" </> "dist")
+    let dirs = map ((root </> ".stack-work" </> "dist") </>) contents
+    subDirs <- mapM (\d -> map (d </>) <$> listDirectory d) dirs
+    mapM (ifExists . (</> "build" </> "autogen")) (dirs ++ concat subDirs)) 
else return []
+  return (choose existing)
+
+
 trim :: String -> String
 trim = f . f
-   where f = reverse . dropWhile isSpace
\ No newline at end of file
+   where f = reverse . dropWhile isSpace
+
+choose :: Alternative f => [f a] -> f a
+choose = foldl (<|>) empty
+
+ifExists :: FilePath -> IO (Maybe FilePath)
+ifExists fp = do exists <- doesDirectoryExist fp
+                 if exists then return (Just fp)
+                           else return Nothing
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/Language/Haskell/Tools/Refactor/Daemon/State.hs
 
new/haskell-tools-daemon-0.8.0.0/Language/Haskell/Tools/Refactor/Daemon/State.hs
--- 
old/haskell-tools-daemon-0.5.0.0/Language/Haskell/Tools/Refactor/Daemon/State.hs
    2017-01-31 20:47:45.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/Language/Haskell/Tools/Refactor/Daemon/State.hs
    2017-06-07 10:55:20.000000000 +0200
@@ -4,12 +4,14 @@
 import Control.Reference
 
 import Language.Haskell.Tools.Refactor.Daemon.PackageDB
+import Language.Haskell.Tools.Refactor.RefactorBase
 import Language.Haskell.Tools.Refactor.Session
 
-data DaemonSessionState 
+data DaemonSessionState
   = DaemonSessionState { _refactorSession :: RefactorSessionState
                        , _packageDB :: PackageDB
                        , _packageDBSet :: Bool
+                       , _packageDBLocs :: [FilePath]
                        , _exiting :: Bool
                        }
 
@@ -17,4 +19,4 @@
 
 instance IsRefactSessionState DaemonSessionState where
   refSessMCs = refactorSession & refSessMCs
-  initSession = DaemonSessionState initSession AutoDB False False
\ No newline at end of file
+  initSession = DaemonSessionState initSession AutoDB False [] False
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/Language/Haskell/Tools/Refactor/Daemon.hs 
new/haskell-tools-daemon-0.8.0.0/Language/Haskell/Tools/Refactor/Daemon.hs
--- old/haskell-tools-daemon-0.5.0.0/Language/Haskell/Tools/Refactor/Daemon.hs  
2017-01-31 20:47:45.000000000 +0100
+++ new/haskell-tools-daemon-0.8.0.0/Language/Haskell/Tools/Refactor/Daemon.hs  
2017-06-17 11:26:16.000000000 +0200
@@ -1,9 +1,11 @@
 {-# LANGUAGE ScopedTypeVariables
-           , OverloadedStrings 
+           , OverloadedStrings
            , DeriveGeneric
            , LambdaCase
            , TemplateHaskell
            , FlexibleContexts
+           , MultiWayIf
+           , TypeApplications
            #-}
 module Language.Haskell.Tools.Refactor.Daemon where
 
@@ -11,13 +13,16 @@
 import Control.Concurrent.MVar
 import Control.Exception
 import Control.Monad
-import Control.Monad.State
+import Control.Monad.State.Strict
 import Control.Reference
 import qualified Data.Aeson as A ((.=))
 import Data.Aeson hiding ((.=))
+import Data.Algorithm.Diff
+import qualified Data.ByteString.Char8 as StrictBS
 import Data.ByteString.Lazy.Char8 (ByteString)
 import Data.ByteString.Lazy.Char8 (unpack)
 import qualified Data.ByteString.Lazy.Char8 as BS
+import Data.Either
 import Data.IORef
 import Data.List hiding (insert)
 import qualified Data.Map as Map
@@ -29,6 +34,8 @@
 import System.Directory
 import System.Environment
 import System.IO
+import System.IO.Strict as StrictIO (hGetContents)
+import Data.Version
 
 import Bag
 import DynFlags
@@ -50,10 +57,7 @@
 import Language.Haskell.Tools.Refactor.Prepare
 import Language.Haskell.Tools.Refactor.RefactorBase
 import Language.Haskell.Tools.Refactor.Session
-
-import Debug.Trace
-
--- TODO: handle boot files
+import Paths_haskell_tools_daemon
 
 runDaemonCLI :: IO ()
 runDaemonCLI = getArgs >>= runDaemon
@@ -62,15 +66,14 @@
 runDaemon args = withSocketsDo $
     do let finalArgs = args ++ drop (length args) defaultArgs
            isSilent = read (finalArgs !! 1)
+       hSetBuffering stdout LineBuffering
+       hSetBuffering stderr LineBuffering
        when (not isSilent) $ putStrLn $ "Starting Haskell Tools daemon"
-       addrinfos <- getAddrInfo
-                    (Just (defaultHints {addrFlags = [AI_PASSIVE]}))
-                    Nothing (Just (finalArgs !! 0))
-       let serveraddr = head addrinfos
-       sock <- socket (addrFamily serveraddr) Stream defaultProtocol
+       sock <- socket AF_INET Stream 0
        setSocketOption sock ReuseAddr 1
-       bind sock (addrAddress serveraddr)
-       listen sock 1
+       when (not isSilent) $ putStrLn $ "Listening on port " ++ finalArgs !! 0
+       bind sock (SockAddrInet (read (finalArgs !! 0)) iNADDR_ANY)
+       listen sock 4
        clientLoop isSilent sock
 
 defaultArgs :: [String]
@@ -115,58 +118,41 @@
 
 -- | This function does the real job of acting upon client messages in a 
stateful environment of a client
 updateClient :: (ResponseMsg -> IO ()) -> ClientMessage -> StateT 
DaemonSessionState Ghc Bool
+updateClient resp (Handshake _) = liftIO (resp $ HandshakeResponse $ 
versionBranch version) >> return True
 updateClient resp KeepAlive = liftIO (resp KeepAliveResponse) >> return True
 updateClient resp Disconnect = liftIO (resp Disconnected) >> return False
-updateClient _ (SetPackageDB pkgDB) = modify (packageDB .= pkgDB) >> return 
True 
+updateClient _ (SetPackageDB pkgDB) = modify (packageDB .= pkgDB) >> return 
True
 updateClient resp (AddPackages packagePathes) = do
-    existingMCs <- gets (^. refSessMCs)
-    let existing = map ms_mod $ (existingMCs ^? traversal & filtered 
isTheAdded & mcModules & traversal & modRecMS)
-    needToReload <- (filter (\ms -> not $ ms_mod ms `elem` existing)) 
-                      <$> getReachableModules (\ms -> ms_mod ms `elem` 
existing)
-    modify $ refSessMCs .- filter (not . isTheAdded) -- remove the added 
package from the database
-    forM_ existing $ \mn -> removeTarget (TargetModule (GHC.moduleName mn))
-    modifySession (\s -> s { hsc_mod_graph = filter (not . (`elem` existing) . 
ms_mod) (hsc_mod_graph s) })
-    initializePackageDBIfNeeded
-    res <- loadPackagesFrom (return . getModSumOrig) packagePathes
-    case res of 
-      Right (modules, ignoredMods) -> do
-        mapM_ (reloadModule (\_ -> return ())) needToReload -- don't report 
consequent reloads (not expected)
-        liftIO $ resp 
-          $ if not (null ignoredMods) 
-              then ErrorMessage 
-                     $ "The following modules are ignored: " 
-                         ++ concat (intersperse ", " ignoredMods)
-                         ++ ". Multiple modules with the same qualified name 
are not supported."
-              else LoadedModules modules
-      Left err -> liftIO $ resp $ either ErrorMessage CompilationProblem 
(getProblems err) 
+    addPackages resp packagePathes
     return True
-  where isTheAdded mc = (mc ^. mcRoot) `elem` packagePathes
-        initializePackageDBIfNeeded = do
-          pkgDBAlreadySet <- gets (^. packageDBSet)
-          when (not pkgDBAlreadySet) $ do
-            pkgDB <- gets (^. packageDB)
-            pkgDBLocs <- liftIO $ packageDBLocs pkgDB packagePathes
-            usePackageDB pkgDBLocs
-            modify (packageDBSet .= True)
-
 updateClient _ (RemovePackages packagePathes) = do
     mcs <- gets (^. refSessMCs)
-    let existing = map ms_mod (mcs ^? traversal & filtered isRemoved & 
mcModules & traversal & modRecMS)
-    lift $ forM_ existing (\modName -> removeTarget (TargetModule 
(GHC.moduleName modName)))
+    let existingFiles = concatMap @[] (map (^. sfkFileName) . Map.keys) (mcs 
^? traversal & filtered isRemoved & mcModules)
+    lift $ forM_ existingFiles (\fs -> removeTarget (TargetFile fs Nothing))
     lift $ deregisterDirs (mcs ^? traversal & filtered isRemoved & 
mcSourceDirs & traversal)
     modify $ refSessMCs .- filter (not . isRemoved)
-    modifySession (\s -> s { hsc_mod_graph = filter (not . (`elem` existing) . 
ms_mod) (hsc_mod_graph s) })
+    modifySession (\s -> s { hsc_mod_graph = filter ((`notElem` existingFiles) 
. getModSumOrig) (hsc_mod_graph s) })
+    mcs <- gets (^. refSessMCs)
+    when (null mcs) $ modify (packageDBSet .= False)
     return True
   where isRemoved mc = (mc ^. mcRoot) `elem` packagePathes
 
-updateClient resp (ReLoad changed removed) =
-  do removedMods <- gets (map ms_mod . filter ((`elem` removed) . 
getModSumOrig) . (^? refSessMCs & traversal & mcModules & traversal & modRecMS))
-     lift $ forM_ removedMods (\modName -> removeTarget (TargetModule 
(GHC.moduleName modName)))
-     modify $ refSessMCs & traversal & mcModules 
-                .- Map.filter (\m -> maybe True (not . (`elem` removed) . 
getModSumOrig) (m ^? modRecMS))
-     modifySession (\s -> s { hsc_mod_graph = filter (not . (`elem` 
removedMods) . ms_mod) (hsc_mod_graph s) })
-     reloadRes <- reloadChangedModules (\ms -> resp (LoadedModules 
[getModSumOrig ms]))
+updateClient resp (ReLoad added changed removed) =
+  -- TODO: check for changed cabal files and reload their packages
+  do mcs <- gets (^. refSessMCs)
+     lift $ forM_ removed (\src -> removeTarget (TargetFile src Nothing))
+     -- remove targets deleted
+     modify $ refSessMCs & traversal & mcModules
+                .- Map.filter (\m -> maybe True ((`notElem` removed) . 
getModSumOrig) (m ^? modRecMS))
+     modifySession (\s -> s { hsc_mod_graph = filter (\mod -> getModSumOrig 
mod `notElem` removed) (hsc_mod_graph s) })
+     -- reload changed modules
+     -- TODO: filter those that are in reloaded packages
+     reloadRes <- reloadChangedModules (\ms -> resp (LoadedModules 
[(getModSumOrig ms, getModSumName ms)]))
+                                       (\mss -> resp (LoadingModules (map 
getModSumOrig mss)))
                                        (\ms -> getModSumOrig ms `elem` changed)
+     mcs <- gets (^. refSessMCs)
+     let mcsToReload = filter (\mc -> any ((mc ^. mcRoot) `isPrefixOf`) added 
&& isNothing (moduleCollectionPkgId (mc ^. mcId))) mcs
+     addPackages resp (map (^. mcRoot) mcsToReload) -- reload packages 
containing added modules
      liftIO $ case reloadRes of Left errs -> resp (either ErrorMessage 
CompilationProblem (getProblems errs))
                                 Right _ -> return ()
      return True
@@ -174,51 +160,135 @@
 updateClient _ Stop = modify (exiting .= True) >> return False
 
 updateClient resp (PerformRefactoring refact modPath selection args) = do
-    (Just actualMod, otherMods) <- getFileMods modPath
-    let cmd = analyzeCommand refact (selection:args)
-    res <- lift $ performCommand cmd actualMod otherMods
-    case res of
-      Left err -> liftIO $ resp $ ErrorMessage err
-      Right diff -> do changedMods <- catMaybes <$> applyChanges diff
-                       liftIO $ resp $ ModulesChanged (map snd changedMods)
-                       -- when a new module is added, we need to compile it 
with the correct package db
-                       void $ reloadChanges (map ((^. sfkModuleName) . fst) 
changedMods)
+    (selectedMod, otherMods) <- getFileMods modPath
+    case selectedMod of
+      Just actualMod -> do
+        case analyzeCommand refact (selection:args) of
+           Right cmd -> do res <- lift $ performCommand cmd actualMod otherMods
+                           case res of
+                             Left err -> liftIO $ resp $ ErrorMessage err
+                             Right diff -> do changedMods <- applyChanges diff
+                                              liftIO $ resp $ ModulesChanged 
(map (either id (\(_,_,ch) -> ch)) changedMods)
+                                              void $ reloadChanges (map ((^. 
sfkModuleName) . (\(key,_,_) -> key)) (rights changedMods))
+           Left err -> liftIO $ resp $ ErrorMessage err
+      Nothing -> liftIO $ resp $ ErrorMessage $ "The following file is not 
loaded to Haskell-tools: "
+                                                   ++ modPath ++ ". Please add 
the containing package."
     return True
-  where applyChanges changes = do 
-          forM changes $ \case 
-            ModuleCreated n m otherM -> do 
+
+  where applyChanges changes = do
+          forM changes $ \case
+            ModuleCreated n m otherM -> do
               mcs <- gets (^. refSessMCs)
               Just (_, otherMR) <- gets (lookupModInSCs otherM . (^. 
refSessMCs))
 
               let Just otherMS = otherMR ^? modRecMS
                   Just mc = lookupModuleColl (otherM ^. sfkModuleName) mcs
-              modify $ refSessMCs & traversal & filtered (\mc' -> (mc' ^. 
mcId) == (mc ^. mcId)) & mcModules 
-                         .- Map.insert (SourceFileKey NormalHs n) 
(ModuleNotLoaded False)
               otherSrcDir <- liftIO $ getSourceDir otherMS
               let loc = toFileName otherSrcDir n
-              liftIO $ withBinaryFile loc WriteMode (`hPutStr` prettyPrint m)
-              lift $ addTarget (Target (TargetModule (GHC.mkModuleName n)) 
True Nothing)
-              return $ Just (SourceFileKey NormalHs n, loc)
+              modify $ refSessMCs & traversal & filtered (\mc' -> (mc' ^. 
mcId) == (mc ^. mcId)) & mcModules
+                         .- Map.insert (SourceFileKey loc n) (ModuleNotLoaded 
False False)
+              liftIO $ withBinaryFile loc WriteMode $ \handle -> do
+                hSetEncoding handle utf8
+                hPutStr handle (prettyPrint m)
+              lift $ addTarget (Target (TargetFile loc Nothing) True Nothing)
+              return $ Right (SourceFileKey loc n, loc, RemoveAdded loc)
             ContentChanged (n,m) -> do
-              Just (_, mr) <- gets (lookupModInSCs n . (^. refSessMCs))
-              let Just ms = mr ^? modRecMS
-              liftIO $ withBinaryFile (getModSumOrig ms) WriteMode (`hPutStr` 
prettyPrint m)
-              return $ Just (n, getModSumOrig ms)
+              let newCont = prettyPrint m
+                  file = n ^. sfkFileName
+              origCont <- liftIO $ withBinaryFile file ReadMode $ \handle -> do
+                hSetEncoding handle utf8
+                StrictIO.hGetContents handle
+              let undo = createUndo 0 $ getGroupedDiff origCont newCont
+              origCont <- liftIO $ withBinaryFile file WriteMode $ \handle -> 
do
+                hSetEncoding handle utf8
+                hPutStr handle newCont
+              return $ Right (n, file, UndoChanges file undo)
             ModuleRemoved mod -> do
-              Just (_,m) <- gets (lookupModInSCs (SourceFileKey NormalHs mod) 
. (^. refSessMCs))
+              Just (_,m) <- gets (lookupModuleInSCs mod . (^. refSessMCs))
               let modName = GHC.moduleName $ fromJust $ fmap semanticsModule 
(m ^? typedRecModule) <|> fmap semanticsModule (m ^? renamedRecModule)
               ms <- getModSummary modName
-              lift $ removeTarget (TargetModule modName)
+              let file = getModSumOrig ms
+              origCont <- liftIO (StrictBS.unpack <$> StrictBS.readFile file)
+              lift $ removeTarget (TargetFile file Nothing)
               modify $ (refSessMCs .- removeModule mod)
-              liftIO $ removeFile (getModSumOrig ms)
-              return Nothing
-          
-        reloadChanges changedMods 
-          = do reloadRes <- reloadChangedModules (\ms -> resp (LoadedModules 
[getModSumOrig ms])) 
+              liftIO $ removeFile file
+              return $ Left $ RestoreRemoved file origCont
+
+        reloadChanges changedMods
+          = do reloadRes <- reloadChangedModules (\ms -> resp (LoadedModules 
[(getModSumOrig ms, getModSumName ms)]))
+                                                 (\mss -> resp (LoadingModules 
(map getModSumOrig mss)))
                                                  (\ms -> modSumName ms `elem` 
changedMods)
                liftIO $ case reloadRes of Left errs -> resp (either 
ErrorMessage (ErrorMessage . ("The result of the refactoring contains errors: " 
++) . show) (getProblems errs))
                                           Right _ -> return ()
 
+addPackages :: (ResponseMsg -> IO ()) -> [FilePath] -> StateT 
DaemonSessionState Ghc ()
+addPackages resp [] = return ()
+addPackages resp packagePathes = do
+  nonExisting <- filterM ((return . not) <=< liftIO . doesDirectoryExist) 
packagePathes
+  if (not (null nonExisting))
+    then liftIO $ resp $ ErrorMessage $ "The following packages are not found: 
" ++ concat (intersperse ", " nonExisting)
+    else do
+      -- clear existing removed packages
+      existingMCs <- gets (^. refSessMCs)
+      let existing = (existingMCs ^? traversal & filtered isTheAdded & 
mcModules & traversal & modRecMS)
+          existingModNames = map ms_mod existing
+      needToReload <- handleErrors $ (filter (\ms -> not $ ms_mod ms `elem` 
existingModNames))
+                                       <$> getReachableModules (\_ -> return 
()) (\ms -> ms_mod ms `elem` existingModNames)
+      modify $ refSessMCs .- filter (not . isTheAdded) -- remove the added 
package from the database
+      forM_ existing $ \ms -> removeTarget (TargetFile (getModSumOrig ms) 
Nothing)
+      modifySession (\s -> s { hsc_mod_graph = filter (not . (`elem` 
existingModNames) . ms_mod) (hsc_mod_graph s) })
+      -- load new modules
+      pkgDBok <- initializePackageDBIfNeeded
+      if pkgDBok then do
+        res <- loadPackagesFrom (\ms -> resp (LoadedModules [(getModSumOrig 
ms, getModSumName ms)]) >> return (getModSumOrig ms))
+                                (resp . LoadingModules . map getModSumOrig) 
(\st fp -> maybeToList <$> detectAutogen fp (st ^. packageDB)) packagePathes
+        case res of
+          Right modules -> do
+            mapM_ (reloadModule (\_ -> return ())) (either (const []) id 
needToReload) -- don't report consequent reloads (not expected)
+          Left err -> liftIO $ resp $ either ErrorMessage CompilationProblem 
(getProblems err)
+      else liftIO $ resp $ ErrorMessage $ "Attempted to load two packages with 
different package DB. "
+                                            ++ "Stack, cabal-sandbox and 
normal packages cannot be combined"
+  where isTheAdded mc = (mc ^. mcRoot) `elem` packagePathes
+        initializePackageDBIfNeeded = do
+          pkgDBAlreadySet <- gets (^. packageDBSet)
+          pkgDB <- gets (^. packageDB)
+          locs <- liftIO $ mapM (packageDBLoc pkgDB) packagePathes
+          case locs of
+            firstLoc:rest ->
+              if | not (all (== firstLoc) rest)
+                     -> return False
+                 | pkgDBAlreadySet -> do
+                     pkgDBLocs <- gets (^. packageDBLocs)
+                     return (pkgDBLocs == firstLoc)
+                 | otherwise -> do
+                     usePackageDB firstLoc
+                     modify ((packageDBSet .= True) . (packageDBLocs .= 
firstLoc))
+                     return True
+            [] -> return True
+
+
+data UndoRefactor = RemoveAdded { undoRemovePath :: FilePath }
+                  | RestoreRemoved { undoRestorePath :: FilePath
+                                   , undoRestoreContents :: String
+                                   }
+                  | UndoChanges { undoChangedPath :: FilePath
+                                , undoDiff :: FileDiff
+                                }
+  deriving (Show, Generic)
+
+instance ToJSON UndoRefactor
+
+type FileDiff = [(Int, Int, String)]
+
+createUndo :: Eq a => Int -> [Diff [a]] -> [(Int, Int, [a])]
+createUndo i (Both str _ : rest) = createUndo (i + length str) rest
+createUndo i (First rem : Second add : rest)
+  = (i, i + length add, rem) : createUndo (i + length add) rest
+createUndo i (First rem : rest) = (i, i, rem) : createUndo i rest
+createUndo i (Second add : rest)
+  = (i, i + length add, []) : createUndo (i + length add) rest
+createUndo _ [] = []
+
 initGhcSession :: IO Session
 initGhcSession = Session <$> (newIORef =<< runGhc (Just libdir) (initGhcFlags 
>> getSession))
 
@@ -226,9 +296,9 @@
 usePackageDB [] = return ()
 usePackageDB pkgDbLocs
   = do dfs <- getSessionDynFlags
-       dfs' <- liftIO $ fmap fst $ initPackages 
+       dfs' <- liftIO $ fmap fst $ initPackages
                  $ dfs { extraPkgConfs = (map PkgConfFile pkgDbLocs ++) . 
extraPkgConfs dfs
-                       , pkgDatabase = Nothing 
+                       , pkgDatabase = Nothing
                        }
        void $ setSessionDynFlags dfs'
 
@@ -238,6 +308,7 @@
 
 data ClientMessage
   = KeepAlive
+  | Handshake { clientVersion :: [Int] }
   | SetPackageDB { pkgDB :: PackageDB }
   | AddPackages { addedPathes :: [FilePath] }
   | RemovePackages { removedPathes :: [FilePath] }
@@ -248,19 +319,22 @@
                        }
   | Stop
   | Disconnect
-  | ReLoad { changedModules :: [FilePath]
+  | ReLoad { addedModules :: [FilePath]
+           , changedModules :: [FilePath]
            , removedModules :: [FilePath]
            }
   deriving (Show, Generic)
 
-instance FromJSON ClientMessage 
+instance FromJSON ClientMessage
 
 data ResponseMsg
   = KeepAliveResponse
+  | HandshakeResponse { serverVersion :: [Int] }
   | ErrorMessage { errorMsg :: String }
   | CompilationProblem { errorMarkers :: [(SrcSpan, String)] }
-  | ModulesChanged { moduleChanges :: [FilePath] }
-  | LoadedModules { loadedModules :: [FilePath] }
+  | ModulesChanged { undoChanges :: [UndoRefactor] }
+  | LoadedModules { loadedModules :: [(FilePath, String)] }
+  | LoadingModules { modulesToLoad :: [FilePath] }
   | Disconnected
   deriving (Show, Generic)
 
@@ -268,9 +342,9 @@
 
 instance ToJSON SrcSpan where
   toJSON (RealSrcSpan sp) = object [ "file" A..= unpackFS (srcSpanFile sp)
-                                   , "startRow" A..= srcLocLine 
(realSrcSpanStart sp) 
-                                   , "startCol" A..= srcLocCol 
(realSrcSpanStart sp) 
-                                   , "endRow" A..= srcLocLine (realSrcSpanEnd 
sp) 
+                                   , "startRow" A..= srcLocLine 
(realSrcSpanStart sp)
+                                   , "startCol" A..= srcLocCol 
(realSrcSpanStart sp)
+                                   , "endRow" A..= srcLocLine (realSrcSpanEnd 
sp)
                                    , "endCol" A..= srcLocCol (realSrcSpanEnd 
sp)
                                    ]
   toJSON _ = Null
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/additional-files/A.hs 
new/haskell-tools-daemon-0.8.0.0/examples/Project/additional-files/A.hs
--- old/haskell-tools-daemon-0.5.0.0/examples/Project/additional-files/A.hs     
1970-01-01 01:00:00.000000000 +0100
+++ new/haskell-tools-daemon-0.8.0.0/examples/Project/additional-files/A.hs     
2017-05-03 22:13:55.000000000 +0200
@@ -0,0 +1,5 @@
+module A where
+
+import B
+
+a = b
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/additional-files/B.hs 
new/haskell-tools-daemon-0.8.0.0/examples/Project/additional-files/B.hs
--- old/haskell-tools-daemon-0.5.0.0/examples/Project/additional-files/B.hs     
1970-01-01 01:00:00.000000000 +0100
+++ new/haskell-tools-daemon-0.8.0.0/examples/Project/additional-files/B.hs     
2017-05-03 22:13:55.000000000 +0200
@@ -0,0 +1,3 @@
+module B where
+
+b = ()
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/additional-files/some-test-package.cabal
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/additional-files/some-test-package.cabal
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/additional-files/some-test-package.cabal
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/additional-files/some-test-package.cabal
  2017-05-03 22:13:55.000000000 +0200
@@ -0,0 +1,19 @@
+name:                some-test-package
+version:             1.2.3.4
+synopsis:            A package just for testing Haskell-tools support. Don't 
install it.
+description:         
+
+homepage:            https://github.com/nboldi/haskell-tools
+license:             BSD3
+license-file:        LICENSE
+author:              Boldizsar Nemeth
+maintainer:          [email protected]
+category:            Language
+build-type:          Simple
+cabal-version:       >=1.10
+extra-src-files:     B.hs
+
+library
+  exposed-modules:     A
+  build-depends:       base
+  default-language:    Haskell2010
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/UseGroups.hs 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/UseGroups.hs
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/UseGroups.hs    
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/UseGroups.hs    
    2017-04-01 13:42:30.000000000 +0200
@@ -0,0 +1,7 @@
+module UseGroups where
+
+import Data.Group
+import Data.Monoid
+
+x :: Sum Int
+x = 3 `pow` 5
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/LICENSE
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/LICENSE
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/LICENSE
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/LICENSE
      2017-04-01 13:42:30.000000000 +0200
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Nathan "Taneb" van Doorn
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Nathan "Taneb" van Doorn nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/Setup.hs
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/Setup.hs
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/Setup.hs
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/Setup.hs
     2017-04-01 13:42:30.000000000 +0200
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/groups.cabal
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/groups.cabal
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/groups.cabal
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/groups.cabal
 2017-04-01 13:42:31.000000000 +0200
@@ -0,0 +1,19 @@
+name:                groups
+version:             0.4.0.0
+synopsis:            Haskell 98 groups
+description:         
+  Haskell 98 groups. A group is a monoid with invertibility.
+license:             BSD3
+license-file:        LICENSE
+author:              Nathan "Taneb" van Doorn
+maintainer:          [email protected]
+copyright:           Copyright (C) 2013 Nathan van Doorn
+category:            Algebra, Data, Math
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:     Data.Group
+  -- other-modules:       
+  build-depends:       base <5
+  hs-source-dirs:      src
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/src/Data/Group.hs
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/src/Data/Group.hs
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/src/Data/Group.hs
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/groups-0.4.0.0/src/Data/Group.hs
    2017-04-01 13:42:30.000000000 +0200
@@ -0,0 +1,92 @@
+module Data.Group where
+
+import Data.Monoid
+
+-- |A 'Group' is a 'Monoid' plus a function, 'invert', such that: 
+--
+-- @a \<> invert a == mempty@
+--
+-- @invert a \<> a == mempty@
+class Monoid m => Group m where
+  invert :: m -> m
+  -- |@'pow' a n == a \<> a \<> ... \<> a @
+  --
+  -- @ (n lots of a) @
+  --
+  -- If n is negative, the result is inverted.
+  pow :: Integral x => m -> x -> m
+  pow x0 n0 = case compare n0 0 of
+    LT -> invert . f x0 $ negate n0
+    EQ -> mempty
+    GT -> f x0 n0
+    where
+      f x n 
+        | even n = f (x `mappend` x) (n `quot` 2)
+        | n == 1 = x
+        | otherwise = g (x `mappend` x) ((n - 1) `quot` 2) x
+      g x n c
+        | even n = g (x `mappend` x) (n `quot` 2) c
+        | n == 1 = x `mappend` c
+        | otherwise = g (x `mappend` x) ((n - 1) `quot` 2) (x `mappend` c)
+  
+instance Group () where
+  invert () = ()
+  pow () _ = ()
+
+instance Num a => Group (Sum a) where
+  invert = Sum . negate . getSum
+  {-# INLINE invert #-}
+  pow (Sum a) b = Sum (a * fromIntegral b)
+  
+instance Fractional a => Group (Product a) where
+  invert = Product . recip . getProduct
+  {-# INLINE invert #-}
+  pow (Product a) b = Product (a ^^ b)
+
+instance Group a => Group (Dual a) where
+  invert = Dual . invert . getDual
+  {-# INLINE invert #-}
+  pow (Dual a) n = Dual (pow a n)
+
+instance Group b => Group (a -> b) where
+  invert f = invert . f
+  pow f n e = pow (f e) n
+
+instance (Group a, Group b) => Group (a, b) where
+  invert (a, b) = (invert a, invert b)
+  pow (a, b) n = (pow a n, pow b n)
+  
+instance (Group a, Group b, Group c) => Group (a, b, c) where
+  invert (a, b, c) = (invert a, invert b, invert c)
+  pow (a, b, c) n = (pow a n, pow b n, pow c n)
+
+instance (Group a, Group b, Group c, Group d) => Group (a, b, c, d) where
+  invert (a, b, c, d) = (invert a, invert b, invert c, invert d)
+  pow (a, b, c, d) n = (pow a n, pow b n, pow c n, pow d n)
+
+instance (Group a, Group b, Group c, Group d, Group e) => Group (a, b, c, d, 
e) where
+  invert (a, b, c, d, e) = (invert a, invert b, invert c, invert d, invert e)
+  pow (a, b, c, d, e) n = (pow a n, pow b n, pow c n, pow d n, pow e n)
+
+-- |An 'Abelian' group is a 'Group' that follows the rule:
+-- 
+-- @a \<> b == b \<> a@
+class Group g => Abelian g
+
+instance Abelian ()
+
+instance Num a => Abelian (Sum a)
+
+instance Fractional a => Abelian (Product a)
+
+instance Abelian a => Abelian (Dual a)
+
+instance Abelian b => Abelian (a -> b)
+
+instance (Abelian a, Abelian b) => Abelian (a, b)
+
+instance (Abelian a, Abelian b, Abelian c) => Abelian (a, b, c)
+
+instance (Abelian a, Abelian b, Abelian c, Abelian d) => Abelian (a, b, c, d)
+
+instance (Abelian a, Abelian b, Abelian c, Abelian d, Abelian e) => Abelian 
(a, b, c, d, e)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/some-test-package.cabal
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/some-test-package.cabal
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/cabal-sandbox/some-test-package.cabal
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/cabal-sandbox/some-test-package.cabal
     2017-04-01 13:42:30.000000000 +0200
@@ -0,0 +1,18 @@
+name:                some-test-package
+version:             1.2.3.4
+synopsis:            A package just for testing Haskell-tools support. Don't 
install it.
+description:         
+
+homepage:            https://github.com/nboldi/haskell-tools
+license:             BSD3
+author:              Boldizsar Nemeth
+maintainer:          [email protected]
+category:            Language
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     UseGroups
+  build-depends:       base
+                     , groups
+  default-language:    Haskell2010
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/th-added-later/package1/package1.cabal
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/th-added-later/package1/package1.cabal
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/th-added-later/package1/package1.cabal
    2017-01-08 10:56:21.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/th-added-later/package1/package1.cabal
    2017-05-03 22:13:55.000000000 +0200
@@ -1,7 +1,7 @@
 name:                package1
 version:             1.2.3.4
 synopsis:            A package just for testing Haskell-tools support. Don't 
install it.
-description:         
+description:
 
 homepage:            https://github.com/nboldi/haskell-tools
 license:             BSD3
@@ -14,5 +14,5 @@
 
 library
   exposed-modules:     A
-  build-depends:       base
+  build-depends:       base, template-haskell
   default-language:    Haskell2010
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/th-added-later/package2/package2.cabal
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/th-added-later/package2/package2.cabal
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/th-added-later/package2/package2.cabal
    2017-01-08 10:56:21.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/th-added-later/package2/package2.cabal
    2017-05-03 22:13:55.000000000 +0200
@@ -1,7 +1,7 @@
 name:                package2
 version:             1.2.3.4
 synopsis:            A package just for testing Haskell-tools support. Don't 
install it.
-description:         
+description:
 
 homepage:            https://github.com/nboldi/haskell-tools
 license:             BSD3
@@ -14,5 +14,5 @@
 
 library
   exposed-modules:     B
-  build-depends:       base, package1
+  build-depends:       base, package1, template-haskell
   default-language:    Haskell2010
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/unused-mod/Main.hs 
new/haskell-tools-daemon-0.8.0.0/examples/Project/unused-mod/Main.hs
--- old/haskell-tools-daemon-0.5.0.0/examples/Project/unused-mod/Main.hs        
1970-01-01 01:00:00.000000000 +0100
+++ new/haskell-tools-daemon-0.8.0.0/examples/Project/unused-mod/Main.hs        
2017-06-07 10:55:20.000000000 +0200
@@ -0,0 +1,3 @@
+module Main where
+
+main = putStrLn "Hello World"
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/unused-mod/Unused.hs 
new/haskell-tools-daemon-0.8.0.0/examples/Project/unused-mod/Unused.hs
--- old/haskell-tools-daemon-0.5.0.0/examples/Project/unused-mod/Unused.hs      
1970-01-01 01:00:00.000000000 +0100
+++ new/haskell-tools-daemon-0.8.0.0/examples/Project/unused-mod/Unused.hs      
2017-06-07 10:55:20.000000000 +0200
@@ -0,0 +1 @@
+Not a valid haskell program
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/examples/Project/unused-mod/some-test-package.cabal
 
new/haskell-tools-daemon-0.8.0.0/examples/Project/unused-mod/some-test-package.cabal
--- 
old/haskell-tools-daemon-0.5.0.0/examples/Project/unused-mod/some-test-package.cabal
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/haskell-tools-daemon-0.8.0.0/examples/Project/unused-mod/some-test-package.cabal
        2017-06-07 10:55:20.000000000 +0200
@@ -0,0 +1,19 @@
+name:                some-test-package
+version:             1.2.3.4
+synopsis:            A package just for testing Haskell-tools support. Don't 
install it.
+description:
+
+homepage:            https://github.com/nboldi/haskell-tools
+license:             BSD3
+license-file:        LICENSE
+author:              Boldizsar Nemeth
+maintainer:          [email protected]
+category:            Language
+build-type:          Simple
+cabal-version:       >=1.10
+
+executable foo
+  main-is:             Main.hs
+  build-depends:       base
+  default-language:    Haskell2010
+  other-modules:       Unused
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haskell-tools-daemon-0.5.0.0/haskell-tools-daemon.cabal 
new/haskell-tools-daemon-0.8.0.0/haskell-tools-daemon.cabal
--- old/haskell-tools-daemon-0.5.0.0/haskell-tools-daemon.cabal 2017-01-31 
20:56:31.000000000 +0100
+++ new/haskell-tools-daemon-0.8.0.0/haskell-tools-daemon.cabal 2017-07-01 
12:39:07.000000000 +0200
@@ -1,5 +1,5 @@
 name:                haskell-tools-daemon
-version:             0.5.0.0
+version:             0.8.0.0
 synopsis:            Background process for Haskell-tools refactor that 
editors can connect to.
 description:         Background process for Haskell-tools refactor that 
editors can connect to.
 homepage:            https://github.com/haskell-tools/haskell-tools
@@ -50,13 +50,24 @@
                   , examples/Project/load-error/*.hs
                   , examples/Project/source-error/*.hs
                   , examples/Project/empty/*.hs
+                  , examples/Project/additional-files/*.hs
+                  , examples/Project/additional-files/*.cabal
+                  , examples/Project/cabal-sandbox/*.hs
+                  , examples/Project/cabal-sandbox/*.cabal
+                  , examples/Project/cabal-sandbox/groups-0.4.0.0/LICENSE
+                  , examples/Project/cabal-sandbox/groups-0.4.0.0/Setup.hs
+                  , examples/Project/cabal-sandbox/groups-0.4.0.0/groups.cabal
+                  , 
examples/Project/cabal-sandbox/groups-0.4.0.0/src/Data/Group.hs
+                  , examples/Project/unused-mod/*.hs
+                  , examples/Project/unused-mod/*.cabal
+
 
 library
-  ghc-options:         -O2
   build-depends:       base                      >= 4.9   && < 5.0
-                     , aeson                     >= 1.0  && < 1.2
+                     , aeson                     >= 1.0  && < 1.3
                      , bytestring                >= 0.10  && < 1.0
                      , filepath                  >= 1.4   && < 2.0
+                     , strict                    >= 0.3 && < 0.4
                      , containers                >= 0.5   && < 0.6
                      , mtl                       >= 2.2   && < 2.3
                      , split                     >= 0.2   && < 1.0
@@ -66,30 +77,32 @@
                      , ghc-paths                 >= 0.1   && < 0.2
                      , references                >= 0.3.2 && < 1.0
                      , network                   >= 2.6   && < 3.0
-                     , haskell-tools-ast         >= 0.5   && < 0.6
-                     , haskell-tools-prettyprint >= 0.5   && < 0.6
-                     , haskell-tools-refactor    >= 0.5   && < 0.6
+                     , Diff                      >= 0.3   && < 0.4
+                     , haskell-tools-ast         >= 0.8   && < 0.9
+                     , haskell-tools-prettyprint >= 0.8   && < 0.9
+                     , haskell-tools-refactor    >= 0.8   && < 0.9
   exposed-modules:     Language.Haskell.Tools.Refactor.Daemon
                      , Language.Haskell.Tools.Refactor.Daemon.State
                      , Language.Haskell.Tools.Refactor.Daemon.PackageDB
+                     , Paths_haskell_tools_daemon
   default-language:    Haskell2010
 
 
 executable ht-daemon
-  ghc-options:         -O2
+  ghc-options:         -rtsopts
   build-depends:       base                      >= 4.9 && < 5.0
-                     , haskell-tools-daemon      >= 0.5 && < 0.6
+                     , haskell-tools-daemon      >= 0.8 && < 0.9
   hs-source-dirs:      exe
   main-is:             Main.hs
   default-language:    Haskell2010
 
 test-suite haskell-tools-daemon-tests
   type:                exitcode-stdio-1.0
-  ghc-options:         -with-rtsopts=-M2.5g -O2
+  ghc-options:         -with-rtsopts=-M2.5g
   hs-source-dirs:      test
-  main-is:             Main.hs  
+  main-is:             Main.hs
   build-depends:       base                      >= 4.9  && < 4.10
-                     , HUnit                     >= 1.5  && < 1.6
+                     , HUnit                     >= 1.5  && < 1.7
                      , ghc                       >= 8.0   && < 8.1
                      , tasty                     >= 0.11 && < 0.12
                      , tasty-hunit               >= 0.9  && < 0.10
@@ -98,6 +111,6 @@
                      , filepath                  >= 1.4  && < 2.0
                      , bytestring                >= 0.10 && < 0.11
                      , network                   >= 2.6  && < 2.7
-                     , aeson                     >= 1.0 && < 1.2
-                     , haskell-tools-daemon      >= 0.5  && < 0.6
-  default-language:    Haskell2010
\ No newline at end of file
+                     , aeson                     >= 1.0 && < 1.3
+                     , haskell-tools-daemon      >= 0.8  && < 0.9
+  default-language:    Haskell2010
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haskell-tools-daemon-0.5.0.0/test/Main.hs 
new/haskell-tools-daemon-0.8.0.0/test/Main.hs
--- old/haskell-tools-daemon-0.5.0.0/test/Main.hs       2017-01-31 
20:34:13.000000000 +0100
+++ new/haskell-tools-daemon-0.8.0.0/test/Main.hs       2017-06-07 
10:55:20.000000000 +0200
@@ -17,6 +17,7 @@
 import Network.Socket.ByteString.Lazy as Sock
 import qualified Data.ByteString.Lazy.Char8 as BS
 import qualified Data.List as List
+import Data.List (sort)
 import Data.Aeson
 import Data.Maybe
 import System.IO
@@ -32,37 +33,38 @@
 
 main :: IO ()
 main = do unsetEnv "GHC_PACKAGE_PATH"
-          portCounter <- newMVar pORT_NUM_START 
+          portCounter <- newMVar pORT_NUM_START
           tr <- canonicalizePath testRoot
-          isStackRun <- isJust <$> lookupEnv "STACK_EXE"
-          defaultMain (allTests isStackRun tr portCounter)
+          hasStack <- isJust <$> findExecutable "stack"
+          hasCabal <- isJust <$> findExecutable "cabal"
+          defaultMain (allTests (hasStack && hasCabal) tr portCounter)
 
 allTests :: Bool -> FilePath -> MVar Int -> TestTree
 allTests isSource testRoot portCounter
-  = localOption (mkTimeout ({- 10s -} 1000 * 1000 * 10)) 
-      $ testGroup "daemon-tests" 
-          [ testGroup "simple-tests" 
-              $ map (makeDaemonTest portCounter . (\(label, input, output) -> 
(Nothing, label, input, output))) simpleTests
-          , testGroup "loading-tests" 
-              $ map (makeDaemonTest portCounter . (\(label, input, output) -> 
(Nothing, label, input, output))) loadingTests
-          , testGroup "refactor-tests" 
-              $ map (makeDaemonTest portCounter . (\(label, dir, input, 
output) -> (Just (testRoot </> dir), label, input, output))) (refactorTests 
testRoot)
-          , testGroup "reload-tests" 
+  = localOption (mkTimeout ({- 10s -} 1000 * 1000 * 20))
+      $ testGroup "daemon-tests"
+          [ testGroup "simple-tests"
+              $ map (makeDaemonTest portCounter) simpleTests
+          , testGroup "loading-tests"
+              $ map (makeDaemonTest portCounter) loadingTests
+          , testGroup "refactor-tests"
+              $ map (makeRefactorTest portCounter) (refactorTests testRoot)
+          , testGroup "reload-tests"
               $ map (makeReloadTest portCounter) reloadingTests
-          , testGroup "compilation-problem-tests" 
+          , testGroup "compilation-problem-tests"
               $ map (makeCompProblemTest portCounter) compProblemTests
           -- if not a stack build, we cannot guarantee that stack is on the 
path
           , if isSource
              then testGroup "pkg-db-tests" $ map (makePkgDbTest portCounter) 
pkgDbTests
              else testCase "IGNORED pkg-db-tests" (return ())
           -- cannot execute this when the source is not present
-          , if isSource then selfLoadingTest portCounter else testCase 
"IGNORED self-load" (return ())
+          -- , if isSource then selfLoadingTest portCounter else testCase 
"IGNORED self-load" (return ())
           ]
 
 testSuffix = "_test"
 
 simpleTests :: [(String, [ClientMessage], [ResponseMsg])]
-simpleTests = 
+simpleTests =
   [ ( "empty-test", [], [] )
   , ( "keep-alive", [KeepAlive], [KeepAliveResponse] )
   ]
@@ -71,199 +73,207 @@
 loadingTests =
   [ ( "load-package"
     , [AddPackages [testRoot </> "has-cabal"]]
-    , [LoadedModules [testRoot </> "has-cabal" </> "A.hs"]] )
+    , [ LoadingModules [testRoot </> "has-cabal" </> "A.hs"]
+      , LoadedModules [(testRoot </> "has-cabal" </> "A.hs", "A")]] )
   , ( "no-cabal"
     , [AddPackages [testRoot </> "no-cabal"]]
-    , [LoadedModules [testRoot </> "no-cabal" </> "A.hs"]] )
+    , [ LoadingModules [testRoot </> "no-cabal" </> "A.hs"]
+      , LoadedModules [(testRoot </> "no-cabal" </> "A.hs", "A")]] )
   , ( "source-dir"
     , [AddPackages [testRoot </> "source-dir"]]
-    , [LoadedModules [testRoot </> "source-dir" </> "src" </> "A.hs"]] )
+    , [ LoadingModules [testRoot </> "source-dir" </> "src" </> "A.hs"]
+      , LoadedModules [(testRoot </> "source-dir" </> "src" </> "A.hs", "A")]] 
)
   , ( "source-dir-outside"
     , [AddPackages [testRoot </> "source-dir-outside"]]
-    , [LoadedModules [testRoot </> "source-dir-outside" </> ".." </> "src" </> 
"A.hs"]] )
+    , [ LoadingModules [testRoot </> "source-dir-outside" </> ".." </> "src" 
</> "A.hs"]
+      , LoadedModules [(testRoot </> "source-dir-outside" </> ".." </> "src" 
</> "A.hs", "A")]] )
   , ( "multi-packages"
     , [ AddPackages [ testRoot </> "multi-packages" </> "package1"
                     , testRoot </> "multi-packages" </> "package2" ]]
-    , [ LoadedModules [ testRoot </> "multi-packages" </> "package2" </> "B.hs"
-                      , testRoot </> "multi-packages" </> "package1" </> 
"A.hs"]] )
+    , [ LoadingModules [ testRoot </> "multi-packages" </> "package2" </> 
"B.hs"
+                       , testRoot </> "multi-packages" </> "package1" </> 
"A.hs" ]
+      , LoadedModules [ (testRoot </> "multi-packages" </> "package2" </> 
"B.hs", "B") ]
+      , LoadedModules [ (testRoot </> "multi-packages" </> "package1" </> 
"A.hs", "A") ] ] )
   , ( "multi-packages-flags"
     , [ AddPackages [ testRoot </> "multi-packages-flags" </> "package1"
                     , testRoot </> "multi-packages-flags" </> "package2" ]]
-    , [ LoadedModules [ testRoot </> "multi-packages-flags" </> "package2" </> 
"B.hs"
-                      , testRoot </> "multi-packages-flags" </> "package1" </> 
"A.hs"]] )
+    , [ LoadingModules [ testRoot </> "multi-packages-flags" </> "package2" 
</> "B.hs"
+                       , testRoot </> "multi-packages-flags" </> "package1" 
</> "A.hs" ]
+      , LoadedModules [ (testRoot </> "multi-packages-flags" </> "package2" 
</> "B.hs", "B") ]
+      , LoadedModules [ (testRoot </> "multi-packages-flags" </> "package1" 
</> "A.hs", "A") ] ] )
   , ( "multi-packages-dependent"
     , [ AddPackages [ testRoot </> "multi-packages-dependent" </> "package1"
                     , testRoot </> "multi-packages-dependent" </> "package2" ]]
-    , [ LoadedModules [ testRoot </> "multi-packages-dependent" </> "package1" 
</> "A.hs"
-                      , testRoot </> "multi-packages-dependent" </> "package2" 
</> "B.hs"]] )
+    , [ LoadingModules [ testRoot </> "multi-packages-dependent" </> 
"package1" </> "A.hs"
+                       , testRoot </> "multi-packages-dependent" </> 
"package2" </> "B.hs" ]
+      , LoadedModules [ (testRoot </> "multi-packages-dependent" </> 
"package1" </> "A.hs", "A") ]
+      , LoadedModules [ (testRoot </> "multi-packages-dependent" </> 
"package2" </> "B.hs", "B") ] ] )
   , ( "has-th"
     , [AddPackages [testRoot </> "has-th"]]
-    , [LoadedModules [testRoot </> "has-th" </> "TH.hs", testRoot </> "has-th" 
</> "A.hs"]] )
+    , [ LoadingModules [ testRoot </> "has-th" </> "TH.hs", testRoot </> 
"has-th" </> "A.hs" ]
+      , LoadedModules [ (testRoot </> "has-th" </> "TH.hs", "TH") ]
+      , LoadedModules [ (testRoot </> "has-th" </> "A.hs", "A") ] ] )
   , ( "th-added-later"
     , [ AddPackages [testRoot </> "th-added-later" </> "package1"]
       , AddPackages [testRoot </> "th-added-later" </> "package2"]
       ]
-    , [ LoadedModules [testRoot </> "th-added-later" </> "package1" </> 
"A.hs"] 
-      , LoadedModules [testRoot </> "th-added-later" </> "package2" </> 
"B.hs"]] )
+    , [ LoadingModules [ testRoot </> "th-added-later" </> "package1" </> 
"A.hs" ]
+      , LoadedModules [(testRoot </> "th-added-later" </> "package1" </> 
"A.hs", "A")]
+      , LoadingModules [ testRoot </> "th-added-later" </> "package2" </> 
"B.hs" ]
+      , LoadedModules [(testRoot </> "th-added-later" </> "package2" </> 
"B.hs", "B")] ] )
+  , ( "unused-module"
+    , [ AddPackages [testRoot </> "unused-mod"] ]
+    , [ LoadingModules [ testRoot </> "unused-mod" </> "Main.hs" ]
+      , LoadedModules [ (testRoot </> "unused-mod" </> "Main.hs", "Main") ] ] )
   ]
 
 compProblemTests :: [(String, [Either (IO ()) ClientMessage], [ResponseMsg] -> 
Bool)]
-compProblemTests = 
+compProblemTests =
   [ ( "load-error"
-    , [ Right $ AddPackages [testRoot </> "load-error"] ] 
-    , \case [CompilationProblem {}] -> True; _ -> False)
+    , [ Right $ SetPackageDB DefaultDB, Right $ AddPackages [testRoot </> 
"load-error"] ]
+    , \case [LoadingModules{}, CompilationProblem {}] -> True; _ -> False)
   , ( "source-error"
-    , [ Right $ AddPackages [testRoot </> "source-error"] ] 
-    , \case [CompilationProblem {}] -> True; _ -> False)
+    , [ Right $ SetPackageDB DefaultDB, Right $ AddPackages [testRoot </> 
"source-error"] ]
+    , \case [LoadingModules{}, CompilationProblem {}] -> True; _ -> False)
   , ( "reload-error"
-    , [ Right $ AddPackages [testRoot </> "empty"] 
+    , [ Right $ SetPackageDB DefaultDB, Right $ AddPackages [testRoot </> 
"empty"]
       , Left $ appendFile (testRoot </> "empty" </> "A.hs") "\n\nimport 
No.Such.Module"
-      , Right $ ReLoad [testRoot </> "empty" </> "A.hs"] [] 
+      , Right $ ReLoad [] [testRoot </> "empty" </> "A.hs"] []
       , Left $ writeFile (testRoot </> "empty" </> "A.hs") "module A where"]
-    , \case [LoadedModules {}, CompilationProblem {}] -> True; _ -> False)
+    , \case [LoadingModules {}, LoadedModules {}, LoadingModules {}, 
CompilationProblem {}] -> True; _ -> False)
   , ( "reload-source-error"
-    , [ Right $ AddPackages [testRoot </> "empty"] 
+    , [ Right $ SetPackageDB DefaultDB, Right $ AddPackages [testRoot </> 
"empty"]
       , Left $ appendFile (testRoot </> "empty" </> "A.hs") "\n\naa = 3 + ()"
-      , Right $ ReLoad [testRoot </> "empty" </> "A.hs"] [] 
+      , Right $ ReLoad [] [testRoot </> "empty" </> "A.hs"] []
       , Left $ writeFile (testRoot </> "empty" </> "A.hs") "module A where"]
-    , \case [LoadedModules {}, CompilationProblem {}] -> True; _ -> False)
+    , \case [LoadingModules {}, LoadedModules {}, LoadingModules {}, 
CompilationProblem {}] -> True; _ -> False)
+  , ( "no-such-file"
+    , [ Right $ PerformRefactoring "RenameDefinition" (testRoot </> 
"simple-refactor" ++ testSuffix </> "A.hs") "3:1-3:2" ["y"] ]
+    , \case [ ErrorMessage _ ] -> True; _ -> False )
+  , ( "additional-files"
+    , [ Right $ SetPackageDB DefaultDB, Right $ AddPackages [testRoot </> 
"additional-files"] ]
+    , \case [ LoadingModules {}, ErrorMessage _ ] -> True; _ -> False )
   ]
 
 sourceRoot = ".." </> ".." </> "src"
 
 selfLoadingTest :: MVar Int -> TestTree
-selfLoadingTest port = localOption (mkTimeout ({- 5 min -} 1000 * 1000 * 60 * 
5)) $ testCase "self-load" $ do  
+selfLoadingTest port = localOption (mkTimeout ({- 5 min -} 1000 * 1000 * 60 * 
5)) $ testCase "self-load" $ do
     actual <- communicateWithDaemon port
-                [ Right $ AddPackages (map (sourceRoot </>) ["ast", 
"backend-ghc", "prettyprint", "rewrite", "refactor", "daemon"]) ]
-    assertBool ("The expected result is a nonempty response message list that 
does not contain errors. Actual result: " ++ show actual) 
+                [ Right $ AddPackages (map (sourceRoot </>) ["ast", 
"backend-ghc", "prettyprint", "rewrite", "refactor"]) ]
+    assertBool ("The expected result is a nonempty response message list that 
does not contain errors. Actual result: " ++ show actual)
                (not (null actual) && all (\case ErrorMessage {} -> False; _ -> 
True) actual)
 
 
-refactorTests :: FilePath -> [(String, FilePath, [ClientMessage], 
[ResponseMsg])]
+refactorTests :: FilePath -> [(String, FilePath, [ClientMessage], 
[ResponseMsg] -> Bool)]
 refactorTests testRoot =
-  [ ( "simple-refactor", "simple-refactor"
+  [ ( "simple-refactor", testRoot </> "simple-refactor"
     , [ AddPackages [ testRoot </> "simple-refactor" ++ testSuffix ]
       , PerformRefactoring "RenameDefinition" (testRoot </> "simple-refactor" 
++ testSuffix </> "A.hs") "3:1-3:2" ["y"]
       ]
-    , [ LoadedModules [ testRoot </> "simple-refactor" ++ testSuffix </> 
"A.hs" ]
-      , ModulesChanged [ testRoot </> "simple-refactor" ++ testSuffix </> 
"A.hs" ] 
-      , LoadedModules [ testRoot </> "simple-refactor" ++ testSuffix </> 
"A.hs" ]
-      ] )
-  , ( "hs-boots", "hs-boots"
+    , \case [ LoadingModules{}, LoadedModules [ (aPath, _) ], ModulesChanged 
_, LoadingModules{}, LoadedModules [ (aPath', _) ]]
+              -> aPath == testRoot </> "simple-refactor" ++ testSuffix </> 
"A.hs" && aPath == aPath'; _ -> False )
+  , ( "hs-boots", testRoot </> "hs-boots"
     , [ AddPackages [ testRoot </> "hs-boots" ++ testSuffix ]
       , PerformRefactoring "RenameDefinition" (testRoot </> "hs-boots" ++ 
testSuffix </> "A.hs") "5:1-5:2" ["aa"]
       ]
-    , [ LoadedModules [ testRoot </> "hs-boots" ++ testSuffix </> "B.hs-boot", 
testRoot </> "hs-boots" ++ testSuffix </> "A.hs-boot"
-                      , testRoot </> "hs-boots" ++ testSuffix </> "A.hs", 
testRoot </> "hs-boots" ++ testSuffix </> "B.hs" ]
-      , ModulesChanged [ testRoot </> "hs-boots" ++ testSuffix </> "A.hs", 
testRoot </> "hs-boots" ++ testSuffix </> "B.hs"
-                       , testRoot </> "hs-boots" ++ testSuffix </> "A.hs-boot" 
] 
-      , LoadedModules [ testRoot </> "hs-boots" ++ testSuffix </> "A.hs-boot" ]
-      , LoadedModules [ testRoot </> "hs-boots" ++ testSuffix </> "B.hs-boot" ]
-      , LoadedModules [ testRoot </> "hs-boots" ++ testSuffix </> "A.hs" ]
-      , LoadedModules [ testRoot </> "hs-boots" ++ testSuffix </> "B.hs" ]
-      ] )
-  , ( "remove-module", "simple-refactor"
+    , \case [ LoadingModules{}, LoadedModules _, LoadedModules _, 
LoadedModules _, LoadedModules _, ModulesChanged _
+              , LoadingModules{}, LoadedModules [ (path1, _) ], LoadedModules 
[ (path2, _) ]
+              , LoadedModules [ (path3, _) ], LoadedModules [ (path4, _) ]
+              ] -> let allPathes = map ((testRoot </> "hs-boots" ++ 
testSuffix) </>) ["A.hs","B.hs","A.hs-boot","B.hs-boot"]
+                    in sort [path1,path2,path3,path4] == sort allPathes
+            _ -> False )
+  , ( "remove-module", testRoot </> "simple-refactor"
     , [ AddPackages [ testRoot </> "simple-refactor" ++ testSuffix ]
       , PerformRefactoring "RenameDefinition" (testRoot </> "simple-refactor" 
++ testSuffix </> "A.hs") "1:8-1:9" ["AA"]
       ]
-    , [ LoadedModules [ testRoot </> "simple-refactor" ++ testSuffix </> 
"A.hs" ]
-      , ModulesChanged [ testRoot </> "simple-refactor" ++ testSuffix </> 
"AA.hs" ] 
-      , LoadedModules [ testRoot </> "simple-refactor" ++ testSuffix </> 
"AA.hs" ]
-      ] )
+    , \case [ LoadingModules{},LoadedModules [ (aPath, _) ], ModulesChanged _, 
LoadingModules{},LoadedModules [ (aaPath, _) ]]
+              -> aPath == testRoot </> "simple-refactor" ++ testSuffix </> 
"A.hs"
+                   && aaPath == testRoot </> "simple-refactor" ++ testSuffix 
</> "AA.hs"
+            _ -> False )
   ]
 
-reloadingTests :: [(String, FilePath, [ClientMessage], IO (), [ClientMessage], 
[ResponseMsg])]
+reloadingTests :: [(String, FilePath, [ClientMessage], IO (), [ClientMessage], 
[ResponseMsg] -> Bool)]
 reloadingTests =
   [ ( "reloading-module", testRoot </> "reloading", [ AddPackages [ testRoot 
</> "reloading" ++ testSuffix ]]
-    , writeFile (testRoot </> "reloading" ++ testSuffix </> "C.hs") "module C 
where\nc = ()" 
-    , [ ReLoad [testRoot </> "reloading" ++ testSuffix </> "C.hs"] []
-      , PerformRefactoring "RenameDefinition" (testRoot </> "reloading" ++ 
testSuffix </> "C.hs") "2:1-2:2" ["d"] 
-      ]
-    , [ LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "C.hs"
-                      , testRoot </> "reloading" ++ testSuffix </> "B.hs"
-                      , testRoot </> "reloading" ++ testSuffix </> "A.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "C.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "B.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "A.hs" ]
-      , ModulesChanged [ testRoot </> "reloading" ++ testSuffix </> "C.hs"
-                       , testRoot </> "reloading" ++ testSuffix </> "B.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "C.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "B.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "A.hs" ]
-      ]
-    )
+    , writeFile (testRoot </> "reloading" ++ testSuffix </> "C.hs") "module C 
where\nc = ()"
+    , [ ReLoad [] [testRoot </> "reloading" ++ testSuffix </> "C.hs"] []
+      , PerformRefactoring "RenameDefinition" (testRoot </> "reloading" ++ 
testSuffix </> "C.hs") "2:1-2:2" ["d"]
+      ]
+    , \case [ LoadingModules{}, LoadedModules [(pathC'',_)], LoadedModules 
[(pathB'',_)], LoadedModules [(pathA'',_)]
+              , LoadingModules{}, LoadedModules [(pathC,_)], LoadedModules 
[(pathB,_)], LoadedModules [(pathA,_)]
+              , ModulesChanged _, LoadingModules{},LoadedModules [(pathC',_)], 
LoadedModules [(pathB',_)], LoadedModules [(pathA',_)]
+              ] -> let allPathes = map ((testRoot </> "reloading" ++ 
testSuffix) </>) ["C.hs","B.hs","A.hs"]
+                    in [pathC,pathB,pathA] == allPathes
+                         && [pathC',pathB',pathA'] == allPathes
+                         && [pathC'',pathB'',pathA''] == allPathes
+            _ -> False )
   , ( "reloading-package", testRoot </> "changing-cabal"
     , [ AddPackages [ testRoot </> "changing-cabal" ++ testSuffix ]]
-    , appendFile (testRoot </> "changing-cabal" ++ testSuffix </> 
"some-test-package.cabal") ", B" 
+    , appendFile (testRoot </> "changing-cabal" ++ testSuffix </> 
"some-test-package.cabal") ", B"
     , [ AddPackages [testRoot </> "changing-cabal" ++ testSuffix]
-      , PerformRefactoring "RenameDefinition" (testRoot </> "changing-cabal" 
++ testSuffix </> "A.hs") "3:1-3:2" ["z"] 
-      ]
-    , [ LoadedModules [ testRoot </> "changing-cabal" ++ testSuffix </> "A.hs" 
]
-      , LoadedModules [ testRoot </> "changing-cabal" ++ testSuffix </> "A.hs"
-                      , testRoot </> "changing-cabal" ++ testSuffix </> "B.hs" 
]
-      , ModulesChanged [ testRoot </> "changing-cabal" ++ testSuffix </> "A.hs"
-                       , testRoot </> "changing-cabal" ++ testSuffix </> 
"B.hs" ]
-      , LoadedModules [ testRoot </> "changing-cabal" ++ testSuffix </> "A.hs" 
]
-      , LoadedModules [ testRoot </> "changing-cabal" ++ testSuffix </> "B.hs" 
]
+      , PerformRefactoring "RenameDefinition" (testRoot </> "changing-cabal" 
++ testSuffix </> "A.hs") "3:1-3:2" ["z"]
       ]
-    )
+    , \case [ LoadingModules{}, LoadedModules [(pathA,_)], LoadingModules{}, 
LoadedModules [(pathA',_)]
+              , LoadedModules [(pathB',_)], ModulesChanged _
+              , LoadingModules{}, LoadedModules [(pathA'',_)], LoadedModules 
[(pathB'',_)]
+              ] -> let [pA,pB] = map ((testRoot </> "changing-cabal" ++ 
testSuffix) </>) ["A.hs","B.hs"]
+                    in pA == pathA && pA == pathA' && pA == pathA'' && pB == 
pathB' && pB == pathB''
+            _ -> False )
+  , ( "adding-module", testRoot </> "reloading", [AddPackages [ testRoot </> 
"reloading" ++ testSuffix ]]
+    , writeFile (testRoot </> "reloading" ++ testSuffix </> "D.hs") "module D 
where\nd = ()"
+    , [ ReLoad [testRoot </> "reloading" ++ testSuffix </> "D.hs"] [] [] ]
+    , \case [ LoadingModules {}, LoadedModules {}, LoadedModules {}, 
LoadedModules {}, LoadingModules {}
+              , LoadingModules {}, LoadedModules {}, LoadedModules {}, 
LoadedModules {}, LoadedModules {}] -> True
+            _ -> False )
   , ( "reloading-remove", testRoot </> "reloading", [ AddPackages [ testRoot 
</> "reloading" ++ testSuffix ]]
     , do removeFile (testRoot </> "reloading" ++ testSuffix </> "A.hs")
          removeFile (testRoot </> "reloading" ++ testSuffix </> "B.hs")
-    , [ ReLoad [testRoot </> "reloading" ++ testSuffix </> "C.hs"] 
-               [testRoot </> "reloading" ++ testSuffix </> "A.hs", testRoot 
</> "reloading" ++ testSuffix </> "B.hs"]
-      , PerformRefactoring "RenameDefinition" (testRoot </> "reloading" ++ 
testSuffix </> "C.hs") "3:1-3:2" ["d"] 
-      ]
-    , [ LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "C.hs"
-                      , testRoot </> "reloading" ++ testSuffix </> "B.hs"
-                      , testRoot </> "reloading" ++ testSuffix </> "A.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "C.hs" ]
-      , ModulesChanged [ testRoot </> "reloading" ++ testSuffix </> "C.hs" ]
-      , LoadedModules [ testRoot </> "reloading" ++ testSuffix </> "C.hs" ]
-      ]
-    )
+    , [ ReLoad [] [testRoot </> "reloading" ++ testSuffix </> "C.hs"]
+                  [testRoot </> "reloading" ++ testSuffix </> "A.hs", testRoot 
</> "reloading" ++ testSuffix </> "B.hs"]
+      , PerformRefactoring "RenameDefinition" (testRoot </> "reloading" ++ 
testSuffix </> "C.hs") "3:1-3:2" ["d"]
+      ]
+    , \case [ LoadingModules{}, LoadedModules [(pathC,_)], LoadedModules 
[(pathB,_)], LoadedModules [(pathA,_)]
+              , LoadingModules{}, LoadedModules [(pathC',_)], ModulesChanged 
_, LoadingModules{}, LoadedModules [(pathC'',_)] ]
+              -> let [pC,pB,pA] = map ((testRoot </> "reloading" ++ 
testSuffix) </>) ["C.hs","B.hs","A.hs"]
+                  in pA == pathA && pB == pathB && pC == pathC && pC == pathC' 
&& pC == pathC''
+            _ -> False )
   , ( "remove-package", testRoot </> "multi-packages-dependent"
     , [ AddPackages [ testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package1"
                     , testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package2" ]]
     , removeDirectoryRecursive (testRoot </> "multi-packages-dependent" ++ 
testSuffix </> "package2")
-    , [ RemovePackages [testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package2"] 
-      , PerformRefactoring "RenameDefinition" (testRoot </> 
"multi-packages-dependent" ++ testSuffix </> "package1" </> "A.hs") 
-                                              "3:1-3:2" ["d"] 
-      ]
-    , [ LoadedModules [ testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package1" </> "A.hs"
-                      , testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package2" </> "B.hs" ]
-      , ModulesChanged [ testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package1" </> "A.hs" ]
-      , LoadedModules [ testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package1" </> "A.hs" ]
-      ]
-    )
+    , [ RemovePackages [testRoot </> "multi-packages-dependent" ++ testSuffix 
</> "package2"]
+      , PerformRefactoring "RenameDefinition" (testRoot </> 
"multi-packages-dependent" ++ testSuffix </> "package1" </> "A.hs")
+                                              "3:1-3:2" ["d"]
+      ]
+    , \case [ LoadingModules{}, LoadedModules [(pathA',_)], LoadedModules 
[(pathB',_)], ModulesChanged _, LoadingModules{}, LoadedModules [(pathA,_)] ]
+              -> let [pA,pB] = map ((testRoot </> "multi-packages-dependent" 
++ testSuffix) </>) [ "package1" </> "A.hs", "package2" </> "B.hs"]
+                  in pA == pathA && pA == pathA' && pB == pathB'
+            _ -> False )
   ]
 
 pkgDbTests :: [(String, IO (), [ClientMessage], [ResponseMsg])]
-pkgDbTests 
-  = [ {- ( "stack"
-       , withCurrentDirectory (testRoot </> "stack") initStack
-       , [SetPackageDB StackDB, AddPackages [testRoot </> "stack"]]
-       , [LoadedModules [testRoot </> "stack" </> "UseGroups.hs"]] )
-    , -} ( "cabal-sandbox"
+pkgDbTests
+  = [ ( "cabal-sandbox"
       , withCurrentDirectory (testRoot </> "cabal-sandbox") initCabalSandbox
       , [SetPackageDB CabalSandboxDB, AddPackages [testRoot </> 
"cabal-sandbox"]]
-      , [LoadedModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"]] )
+      , [ LoadingModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"]
+        , LoadedModules [(testRoot </> "cabal-sandbox" </> "UseGroups.hs", 
"UseGroups")]] )
     , ( "cabal-sandbox-auto"
       , withCurrentDirectory (testRoot </> "cabal-sandbox") initCabalSandbox
       , [SetPackageDB AutoDB, AddPackages [testRoot </> "cabal-sandbox"]]
-      , [LoadedModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"]] )
-    -- , ( "stack-auto"
-    --   , withCurrentDirectory (testRoot </> "stack") initStack
-    --   , [SetPackageDB AutoDB, AddPackages [testRoot </> "stack"]]
-    --   , [LoadedModules [testRoot </> "stack" </> "UseGroups.hs"]] )
+      , [ LoadingModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"]
+        , LoadedModules [(testRoot </> "cabal-sandbox" </> "UseGroups.hs", 
"UseGroups")]] )
     , ( "pkg-db-reload"
       , withCurrentDirectory (testRoot </> "cabal-sandbox") initCabalSandbox
       , [ SetPackageDB AutoDB
         , AddPackages [testRoot </> "cabal-sandbox"]
-        , ReLoad [testRoot </> "cabal-sandbox" </> "UseGroups.hs"] []]
-      , [ LoadedModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"]
-        , LoadedModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"] ])
-    ] 
+        , ReLoad [] [testRoot </> "cabal-sandbox" </> "UseGroups.hs"] []]
+      , [ LoadingModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"]
+        , LoadedModules [(testRoot </> "cabal-sandbox" </> "UseGroups.hs", 
"UseGroups")]
+        , LoadingModules [testRoot </> "cabal-sandbox" </> "UseGroups.hs"]
+        , LoadedModules [(testRoot </> "cabal-sandbox" </> "UseGroups.hs", 
"UseGroups")] ])
+    ]
   where initCabalSandbox = do
           sandboxExists <- doesDirectoryExist ".cabal-sandbox"
           when sandboxExists $ tryToExecute "cabal" ["sandbox", "delete"]
@@ -277,48 +287,50 @@
 
 
 execute :: String -> [String] -> IO ()
-execute cmd args 
+execute cmd args
   = do let command = (cmd ++ concat (map (" " ++) args))
        (_, Just stdOut, Just stdErr, handle) <- createProcess ((shell command) 
{ std_out = CreatePipe, std_err = CreatePipe })
        exitCode <- waitForProcess handle
-       when (exitCode /= ExitSuccess) $ do 
+       when (exitCode /= ExitSuccess) $ do
          output <- hGetContents stdOut
          errors <- hGetContents stdErr
          error ("Command exited with nonzero: " ++ command ++ " output:\n" ++ 
output ++ "\nerrors:\n" ++ errors)
 
 tryToExecute :: String -> [String] -> IO ()
-tryToExecute cmd args 
+tryToExecute cmd args
   = do let command = (cmd ++ concat (map (" " ++) args))
        (_, _, _, handle) <- createProcess ((shell command) { std_out = 
NoStream, std_err = NoStream })
        void $ waitForProcess handle
 
-makeDaemonTest :: MVar Int -> (Maybe FilePath, String, [ClientMessage], 
[ResponseMsg]) -> TestTree
-makeDaemonTest port (Nothing, label, input, expected) = testCase label $ do  
+makeDaemonTest :: MVar Int -> (String, [ClientMessage], [ResponseMsg]) -> 
TestTree
+makeDaemonTest port (label, input, expected) = testCase label $ do
     actual <- communicateWithDaemon port (map Right (SetPackageDB DefaultDB : 
input))
     assertEqual "" expected actual
-makeDaemonTest port (Just dir, label, input, expected) = testCase label $ do 
+
+makeRefactorTest :: MVar Int -> (String, FilePath, [ClientMessage], 
[ResponseMsg] -> Bool) -> TestTree
+makeRefactorTest port (label, dir, input, validator) = testCase label $ do
     exists <- doesDirectoryExist (dir ++ testSuffix)
     -- clear the target directory from possible earlier test runs
     when exists $ removeDirectoryRecursive (dir ++ testSuffix)
     copyDir dir (dir ++ testSuffix)
     actual <- communicateWithDaemon port (map Right (SetPackageDB DefaultDB : 
input))
-    assertEqual "" expected actual
+    assertBool ("The responses are not the expected: " ++ show actual) 
(validator actual)
   `finally` removeDirectoryRecursive (dir ++ testSuffix)
 
-makeReloadTest :: MVar Int -> (String, FilePath, [ClientMessage], IO (), 
[ClientMessage], [ResponseMsg]) -> TestTree
-makeReloadTest port (label, dir, input1, io, input2, expected) = testCase 
label $ do  
+makeReloadTest :: MVar Int -> (String, FilePath, [ClientMessage], IO (), 
[ClientMessage], [ResponseMsg] -> Bool) -> TestTree
+makeReloadTest port (label, dir, input1, io, input2, validator) = testCase 
label $ do
     exists <- doesDirectoryExist (dir ++ testSuffix)
     -- clear the target directory from possible earlier test runs
     when exists $ removeDirectoryRecursive (dir ++ testSuffix)
     copyDir dir (dir ++ testSuffix)
     actual <- communicateWithDaemon port (map Right (SetPackageDB DefaultDB : 
input1) ++ [Left io] ++ map Right input2)
-    assertEqual "" expected actual
+    assertBool ("The responses are not the expected: " ++ show actual) 
(validator actual)
   `finally` removeDirectoryRecursive (dir ++ testSuffix)
 
 makePkgDbTest :: MVar Int -> (String, IO (), [ClientMessage], [ResponseMsg]) 
-> TestTree
-makePkgDbTest port (label, prepare, inputs, expected) 
-  = localOption (mkTimeout ({- 30s -} 1000 * 1000 * 30)) 
-      $ testCase label $ do  
+makePkgDbTest port (label, prepare, inputs, expected)
+  = localOption (mkTimeout ({- 30s -} 1000 * 1000 * 30))
+      $ testCase label $ do
           actual <- communicateWithDaemon port ([Left prepare] ++ map Right 
inputs)
           assertEqual "" expected actual
 
@@ -344,14 +356,14 @@
     sendAll sock $ encode Stop
     close sock
     return (concat intermedRes ++ resps)
-  where waitToConnect sock addr 
+  where waitToConnect sock addr
           = connect sock addr `catch` \(e :: SomeException) -> waitToConnect 
sock addr
-        retryConnect port = do portNum <- readMVar port 
+        retryConnect port = do portNum <- readMVar port
                                forkIO $ runDaemon [show portNum, "True"]
                                return portNum
           `catch` \(e :: SomeException) -> do putStrLn ("exception caught: `" 
++ show e ++ "` trying with a new port")
-                                              modifyMVar_ port (\i -> if i < 
pORT_NUM_END 
-                                                                        then 
return (i+1) 
+                                              modifyMVar_ port (\i -> if i < 
pORT_NUM_END
+                                                                        then 
return (i+1)
                                                                         else 
error "The port number reached the maximum")
                                               retryConnect port
 
@@ -360,18 +372,20 @@
 readSockResponsesUntil sock rsp bs
   = do resp <- recv sock 2048
        let fullBS = bs `BS.append` resp
-       if BS.null resp 
+       if BS.null resp
          then return []
          else
            let splitted = BS.split '\n' fullBS
                recognized = catMaybes $ map decode splitted
-            in if rsp `elem` recognized 
-                 then return $ List.delete rsp recognized 
+            in if rsp `elem` recognized
+                 then return $ List.delete rsp recognized
                  else readSockResponsesUntil sock rsp fullBS
 
 testRoot = "examples" </> "Project"
 
+deriving instance Eq UndoRefactor
 deriving instance Eq ResponseMsg
+instance FromJSON UndoRefactor
 instance FromJSON ResponseMsg
 instance ToJSON ClientMessage
 instance ToJSON PackageDB
@@ -400,15 +414,15 @@
 longestCommonPrefix = foldl1 commonPrefix
 
 instance FromJSON SrcSpan where
-    parseJSON (Object v) = mkSrcSpanReal <$> v .: "file" 
-                                         <*> v .: "startRow" 
-                                         <*> v .: "startCol" 
+    parseJSON (Object v) = mkSrcSpanReal <$> v .: "file"
+                                         <*> v .: "startRow"
+                                         <*> v .: "startCol"
                                          <*> v .: "endRow"
                                          <*> v .: "endCol"
     parseJSON _          = fail "not an object"
 
 
 mkSrcSpanReal :: String -> Int -> Int -> Int -> Int -> SrcSpan
-mkSrcSpanReal file startRow startCol endRow endCol 
+mkSrcSpanReal file startRow startCol endRow endCol
   = mkSrcSpan (mkSrcLoc (mkFastString file) startRow startCol)
               (mkSrcLoc (mkFastString file) endRow endCol)


Reply via email to