packages feed

hsdev 0.1.7.0 → 0.1.7.1

raw patch · 21 files changed

+292/−217 lines, 21 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- HsDev.Symbols: passImportList :: ImportList -> Text -> Bool
- HsDev.Symbols.Resolve: exported :: Declaration -> Export -> Maybe Declaration
- HsDev.Symbols.Resolve: instance Control.Monad.Reader.Class.MonadReader HsDev.Database.Database HsDev.Symbols.Resolve.ResolveM
- HsDev.Symbols.Types: ExportAll :: ExportPart
- HsDev.Symbols.Types: ExportNothing :: ExportPart
- HsDev.Symbols.Types: ExportWith :: [Text] -> ExportPart
- HsDev.Symbols.Types: [_importSpec] :: ImportList -> [Text]
- HsDev.Symbols.Types: data ExportPart
- HsDev.Symbols.Types: importSpec :: Lens' ImportList [Text]
- HsDev.Symbols.Types: instance Control.DeepSeq.NFData HsDev.Symbols.Types.ExportPart
- HsDev.Symbols.Types: instance Data.Aeson.Types.Class.FromJSON HsDev.Symbols.Types.ExportPart
- HsDev.Symbols.Types: instance Data.Aeson.Types.Class.ToJSON HsDev.Symbols.Types.ExportPart
- HsDev.Symbols.Types: instance GHC.Classes.Eq HsDev.Symbols.Types.ExportPart
- HsDev.Symbols.Types: instance GHC.Classes.Ord HsDev.Symbols.Types.ExportPart
- HsDev.Symbols.Types: instance GHC.Show.Show HsDev.Symbols.Types.ExportPart
- HsDev.Symbols.Util: imported :: ModuleId -> [Import] -> Bool
+ HsDev.Database.Update: liftExceptT_ :: CommandMonad m => ExceptT String IO a -> m a
+ HsDev.Server.Commands: [serverSilent] :: ServerOpts -> Bool
+ HsDev.Server.Types: [serverSilent] :: ServerOpts -> Bool
+ HsDev.Symbols: exported :: Declaration -> Export -> Bool
+ HsDev.Symbols: imported :: Declaration -> ImportList -> Bool
+ HsDev.Symbols: passImportSpec :: Declaration -> ImportSpec -> Bool
+ HsDev.Symbols: passThingSpec :: Text -> ThingPart -> Bool
+ HsDev.Symbols.Resolve: instance Control.Monad.Reader.Class.MonadReader (HsDev.Database.Database, HsDev.Symbols.Resolve.ModuleMap) HsDev.Symbols.Resolve.ResolveM
+ HsDev.Symbols.Resolve: resolveImports :: Module -> [Import] -> ResolveM [Declaration]
+ HsDev.Symbols.Types: ImportSpec :: Text -> ThingPart -> ImportSpec
+ HsDev.Symbols.Types: ThingAll :: ThingPart
+ HsDev.Symbols.Types: ThingNothing :: ThingPart
+ HsDev.Symbols.Types: ThingWith :: [Text] -> ThingPart
+ HsDev.Symbols.Types: [_importSpecName] :: ImportSpec -> Text
+ HsDev.Symbols.Types: [_importSpecPart] :: ImportSpec -> ThingPart
+ HsDev.Symbols.Types: [_importSpecs] :: ImportList -> [ImportSpec]
+ HsDev.Symbols.Types: data ImportSpec
+ HsDev.Symbols.Types: data ThingPart
+ HsDev.Symbols.Types: importSpecName :: Lens' ImportSpec Text
+ HsDev.Symbols.Types: importSpecPart :: Lens' ImportSpec ThingPart
+ HsDev.Symbols.Types: importSpecs :: Lens' ImportList [ImportSpec]
+ HsDev.Symbols.Types: instance Control.DeepSeq.NFData HsDev.Symbols.Types.ImportSpec
+ HsDev.Symbols.Types: instance Control.DeepSeq.NFData HsDev.Symbols.Types.ThingPart
+ HsDev.Symbols.Types: instance Data.Aeson.Types.Class.FromJSON HsDev.Symbols.Types.ImportSpec
+ HsDev.Symbols.Types: instance Data.Aeson.Types.Class.FromJSON HsDev.Symbols.Types.ThingPart
+ HsDev.Symbols.Types: instance Data.Aeson.Types.Class.ToJSON HsDev.Symbols.Types.ImportSpec
+ HsDev.Symbols.Types: instance Data.Aeson.Types.Class.ToJSON HsDev.Symbols.Types.ThingPart
+ HsDev.Symbols.Types: instance GHC.Classes.Eq HsDev.Symbols.Types.ImportSpec
+ HsDev.Symbols.Types: instance GHC.Classes.Eq HsDev.Symbols.Types.ThingPart
+ HsDev.Symbols.Types: instance GHC.Classes.Ord HsDev.Symbols.Types.ImportSpec
+ HsDev.Symbols.Types: instance GHC.Classes.Ord HsDev.Symbols.Types.ThingPart
+ HsDev.Symbols.Types: instance GHC.Show.Show HsDev.Symbols.Types.ImportSpec
+ HsDev.Symbols.Types: instance GHC.Show.Show HsDev.Symbols.Types.ThingPart
+ HsDev.Symbols.Util: moduleImported :: ModuleId -> [Import] -> Bool
+ HsDev.Tools.Ghc.Worker: logToChan :: Chan (Note OutputMessage) -> DynFlags -> Severity -> SrcSpan -> PprStyle -> SDoc -> IO ()
+ HsDev.Tools.Ghc.Worker: logToNull :: DynFlags -> Severity -> SrcSpan -> PprStyle -> SDoc -> IO ()
- HsDev.Database.Update: liftExceptT :: CommandMonad m => ExceptT String IO a -> m a
+ HsDev.Database.Update: liftExceptT :: CommandMonad m => Format -> ExceptT String IO a -> m a
- HsDev.Project: entity :: Lens (Extensions a_aZFP) (Extensions a_a11PZ) a_aZFP a_a11PZ
+ HsDev.Project: entity :: Lens (Extensions a_a11gl) (Extensions a_a13oA) a_a11gl a_a13oA
- HsDev.Project: extensions :: Lens' (Extensions a_aZFP) [Extension]
+ HsDev.Project: extensions :: Lens' (Extensions a_a11gl) [Extension]
- HsDev.Project: ghcOptions :: Lens' (Extensions a_aZFP) [String]
+ HsDev.Project: ghcOptions :: Lens' (Extensions a_a11gl) [String]
- HsDev.Server.Commands: ServerOpts :: ConnectionPort -> Int -> Maybe FilePath -> String -> Maybe FilePath -> Bool -> ServerOpts
+ HsDev.Server.Commands: ServerOpts :: ConnectionPort -> Int -> Maybe FilePath -> String -> Maybe FilePath -> Bool -> Bool -> ServerOpts
- HsDev.Server.Message: message :: Lens (Message a_aG5g) (Message a_aGg3) a_aG5g a_aGg3
+ HsDev.Server.Message: message :: Lens (Message a_aG5h) (Message a_aGg4) a_aG5h a_aGg4
- HsDev.Server.Message: messageId :: Lens' (Message a_aG5g) (Maybe String)
+ HsDev.Server.Message: messageId :: Lens' (Message a_aG5h) (Maybe String)
- HsDev.Server.Types: ServerOpts :: ConnectionPort -> Int -> Maybe FilePath -> String -> Maybe FilePath -> Bool -> ServerOpts
+ HsDev.Server.Types: ServerOpts :: ConnectionPort -> Int -> Maybe FilePath -> String -> Maybe FilePath -> Bool -> Bool -> ServerOpts
- HsDev.Symbols.Resolve: ResolveM :: ReaderT Database (State ResolvedTree) a -> ResolveM a
+ HsDev.Symbols.Resolve: ResolveM :: ReaderT (Database, ModuleMap) (State ResolvedTree) a -> ResolveM a
- HsDev.Symbols.Resolve: [runResolveM] :: ResolveM a -> ReaderT Database (State ResolvedTree) a
+ HsDev.Symbols.Resolve: [runResolveM] :: ResolveM a -> ReaderT (Database, ModuleMap) (State ResolvedTree) a
- HsDev.Symbols.Resolve: resolveImport :: Module -> Import -> ResolveM [Declaration]
+ HsDev.Symbols.Resolve: resolveImport :: Set String -> Module -> Import -> ResolveM [Declaration]
- HsDev.Symbols.Types: ExportName :: Maybe Text -> Text -> ExportPart -> Export
+ HsDev.Symbols.Types: ExportName :: Maybe Text -> Text -> ThingPart -> Export
- HsDev.Symbols.Types: ImportList :: Bool -> [Text] -> ImportList
+ HsDev.Symbols.Types: ImportList :: Bool -> [ImportSpec] -> ImportList
- HsDev.Symbols.Types: [_exportPart] :: Export -> ExportPart
+ HsDev.Symbols.Types: [_exportPart] :: Export -> ThingPart
- HsDev.Symbols.Types: exportPart :: Traversal' Export ExportPart
+ HsDev.Symbols.Types: exportPart :: Traversal' Export ThingPart
- HsDev.Symbols.Types: inspectedId :: Lens (Inspected i_a1mg4 a_a1mg5) (Inspected i_a1obD a_a1mg5) i_a1mg4 i_a1obD
+ HsDev.Symbols.Types: inspectedId :: Lens (Inspected i_a1mg9 a_a1mga) (Inspected i_a1ogw a_a1mga) i_a1mg9 i_a1ogw
- HsDev.Symbols.Types: inspection :: Lens' (Inspected i_a1mg4 a_a1mg5) Inspection
+ HsDev.Symbols.Types: inspection :: Lens' (Inspected i_a1mg9 a_a1mga) Inspection
- HsDev.Symbols.Types: inspectionResult :: Lens (Inspected i_a1mg4 a_a1mg5) (Inspected i_a1mg4 a_a1obE) (Either String a_a1mg5) (Either String a_a1obE)
+ HsDev.Symbols.Types: inspectionResult :: Lens (Inspected i_a1mg9 a_a1mga) (Inspected i_a1mg9 a_a1ogx) (Either String a_a1mga) (Either String a_a1ogx)
- HsDev.Tools.Types: note :: Lens (Note a_a1Ofd) (Note a_a1OoE) a_a1Ofd a_a1OoE
+ HsDev.Tools.Types: note :: Lens (Note a_a1MW9) (Note a_a1N5A) a_a1MW9 a_a1N5A
- HsDev.Tools.Types: noteLevel :: Lens' (Note a_a1Ofd) (Maybe Severity)
+ HsDev.Tools.Types: noteLevel :: Lens' (Note a_a1MW9) (Maybe Severity)
- HsDev.Tools.Types: noteRegion :: Lens' (Note a_a1Ofd) Region
+ HsDev.Tools.Types: noteRegion :: Lens' (Note a_a1MW9) Region
- HsDev.Tools.Types: noteSource :: Lens' (Note a_a1Ofd) ModuleLocation
+ HsDev.Tools.Types: noteSource :: Lens' (Note a_a1MW9) ModuleLocation

Files

hsdev.cabal view
@@ -2,7 +2,7 @@ --  see http://haskell.org/cabal/users-guide/
 
 name:                hsdev
-version:             0.1.7.0
+version:             0.1.7.1
 synopsis:            Haskell development library and tool with support of autocompletion, symbol info, go to declaration, find references etc.
 description:
   Haskell development library and tool with support of autocompletion, symbol info, go to declaration, find references, hayoo search etc.
@@ -281,8 +281,10 @@     aeson-lens >= 0.5.0,
     async >= 2.0,
     data-default >= 0.5.0,
-    containers >= 0.5.0,
     deepseq >= 1.4.0,
+    directory >= 1.2.0,
+    filepath >= 1.4.0,
+    containers >= 0.5.0,
     hformat >= 0.1,
     hspec,
     lens >= 4.8,
src/HsDev/Cache.hs view
@@ -24,13 +24,11 @@ import Data.Char (isAlphaNum)
 import Data.List (intercalate)
 import System.FilePath
-import Text.Read (readMaybe)
 
 import HsDev.PackageDb
 import HsDev.Project
 import HsDev.Database (Database)
-import HsDev.Version
-import HsDev.Util (split, version)
+import HsDev.Util (version)
 
 -- | Escape path
 escapePath :: FilePath -> FilePath
src/HsDev/Client/Commands.hs view
@@ -39,7 +39,6 @@ import HsDev.Server.Types
 import HsDev.Sandbox hiding (findSandbox)
 import qualified HsDev.Sandbox as S (findSandbox)
-import HsDev.Stack
 import HsDev.Symbols
 import HsDev.Symbols.Resolve (resolveOne, scopeModule, exportsModule)
 import HsDev.Symbols.Util
@@ -55,7 +54,6 @@ import HsDev.Util
 import HsDev.Watcher
 
-import qualified HsDev.Scan as Scan
 import qualified HsDev.Scan.Browse as Scan
 import qualified HsDev.Database.Update as Update
 
@@ -87,7 +85,7 @@ 		map (Update.scanProject ghcs') projs,
 		map (Update.scanFile ghcs') fs,
 		map (Update.scanDirectory ghcs') paths',
-		if cabal then [Update.scanCabal ghcs'] else [],
+		[Update.scanCabal ghcs' | cabal],
 		map (Update.scanSandbox ghcs') sboxes']
 runCommand (RefineDocs projs fs ms) = toValue $ do
 	projects <- traverse findProject projs
@@ -164,7 +162,8 @@ runCommand (InfoSymbol sq fs locals') = toValue $ do
 	dbval <- liftM (localsDatabase locals') $ getDb
 	filter' <- targetFilters fs
-	return $ newestPackage $ filterMatch sq $ filter (checkModule filter') $ allDeclarations dbval
+	return $ newestPackage $ filterMatch sq $
+		concatMap moduleModuleDeclarations $ filter (filter' . view moduleId) $ allModules dbval
 runCommand (InfoModule sq fs) = toValue $ do
 	dbval <- getDb
 	filter' <- targetFilters fs
@@ -256,8 +255,8 @@ 		notes <- inWorkerWith (commandError_ . show) ghc
 			(runExceptT $ Types.fileTypes ghcs' pdbs m msrc)
 		either commandError_ return notes
-runCommand (GhcMod GhcModLang) = toValue $ mapCommandIO $ GhcMod.langs
-runCommand (GhcMod GhcModFlags) = toValue $ mapCommandIO $ GhcMod.flags
+runCommand (GhcMod GhcModLang) = toValue $ mapCommandIO GhcMod.langs
+runCommand (GhcMod GhcModFlags) = toValue $ mapCommandIO GhcMod.flags
 runCommand (GhcMod (GhcModType (Position line column) fpath ghcs')) = toValue $ do
 	ghcmod <- askSession sessionGhcMod
 	dbval <- getDb
@@ -325,7 +324,7 @@ 		toValue' (Left (SomeException e)) = object ["fail" .= show e]
 		toValue' (Right s) = toJSON s
 runCommand (Link hold) = toValue $ commandLink >> when hold commandHold
-runCommand Exit = toValue $ serverExit
+runCommand Exit = toValue serverExit
 
 targetFilters :: CommandMonad m => [TargetFilter] -> m (ModuleId -> Bool)
 targetFilters fs = do
@@ -425,9 +424,6 @@ 	dbval <- getDb
 	pdbs <- liftIO $ searchPackageDbStack fpath
 	return $ filterDB (restrictPackageDbStack pdbs) (const True) dbval
-
-mapCommandErrorStr :: CommandMonad m => ExceptT String m a -> m a
-mapCommandErrorStr act = runExceptT act >>= either commandError_ return
 
 mapCommandIO :: CommandMonad m => ExceptT String IO a -> m a
 mapCommandIO act = liftIO (runExceptT act) >>= either commandError_ return
src/HsDev/Database/Update.hs view
@@ -19,33 +19,32 @@ 	updateEvent, processEvent,
 
 	-- * Helpers
-	liftExceptT,
+	liftExceptT, liftExceptT_,
 
 	module HsDev.Watcher,
 
 	module Control.Monad.Except
 	) where
 
+import Control.Applicative ((<|>))
 import Control.Arrow
 import Control.Concurrent.Lifted (fork)
 import Control.DeepSeq
-import Control.Lens (preview, _Just, view, over, set, _1, mapMOf_, each, (^..), _head)
+import Control.Lens (preview, _Just, view, over, set, _1, mapMOf_, each, (^..), _head, _Right)
 import Control.Monad.Except
 import Control.Monad.Reader
 import Control.Monad.Writer
 import Data.Aeson
 import Data.Aeson.Types
-import Data.List ((\\))
 import Data.Foldable (toList)
 import qualified Data.Map as M
-import Data.Maybe (mapMaybe, isJust, fromMaybe, catMaybes)
-import Data.Maybe.JustIf
+import Data.Maybe (mapMaybe, isJust, fromMaybe)
 import qualified Data.Text as T (unpack)
 import System.Directory (canonicalizePath, doesFileExist)
 import System.FilePath
 import qualified System.Log.Simple as Log
 
-import Control.Concurrent.Worker (inWorker)
+import Control.Concurrent.Worker (inWorker, restartWorker)
 import qualified HsDev.Cache.Structured as Cache
 import HsDev.Database
 import HsDev.Database.Async hiding (Event)
@@ -55,7 +54,7 @@ import HsDev.Sandbox
 import HsDev.Stack
 import HsDev.Symbols
-import HsDev.Tools.Ghc.Worker (ghcWorker)
+import HsDev.Tools.Ghc.Worker (setCmdOpts)
 import HsDev.Tools.Ghc.Types (inferTypes)
 import HsDev.Tools.HDocs
 import qualified HsDev.Scan as S
@@ -112,13 +111,21 @@ 			return r
 		scanDocs_ :: UpdateMonad m => InspectedModule -> m ()
 		scanDocs_ im = do
-			im' <- liftExceptT $ S.scanModify (\opts _ -> inspectDocs opts) im
+			im' <-
+				liftExceptT
+					("Scanning docs for {} failed: {}" ~~ view inspectedId im)
+					(S.scanModify (\opts _ -> inspectDocs opts) im)
+				<|> return im
 			updater $ return $ fromModule im'
 		inferModTypes_ :: UpdateMonad m => InspectedModule -> m ()
 		inferModTypes_ im = do
 			-- TODO: locate sandbox
 			s <- getSession
-			im' <- liftExceptT $ S.scanModify (infer' s) im
+			im' <-
+				liftExceptT
+					("Inferring types for {} failed: {}" ~~ view inspectedId im)
+					(S.scanModify (infer' s) im)
+				<|> return im
 			updater $ return $ fromModule im'
 		infer' :: Session -> [String] -> PackageDbStack -> Module -> ExceptT String IO Module
 		infer' s opts pdbs m = case preview (moduleLocation . moduleFile) m of
@@ -203,7 +210,7 @@ scanModule :: UpdateMonad m => [String] -> ModuleLocation -> Maybe String -> m ()
 scanModule opts mloc mcts = runTask "scanning" mloc $ Log.scope "module" $ do
 	defs <- askSession sessionDefines
-	im <- liftExceptT $ S.scanModule defs opts mloc mcts
+	im <- liftExceptT_ $ S.scanModule defs opts mloc mcts
 	updater $ return $ fromModule im
 	_ <- return $ view inspectionResult im
 	return ()
@@ -255,8 +262,7 @@ 		scannedDbs = databasePackageDbs dbval
 		unscannedDbs = filter ((`notElem` scannedDbs) . topPackageDb) $ reverse $ packageDbStacks userDb
 	if null unscannedDbs
-		then do
-			Log.log Log.Trace $ "cabal (global-db and user-db) already scanned"
+		then Log.log Log.Trace $ "cabal (global-db and user-db) already scanned"
 		else runTasks $ map (scanPackageDb opts) unscannedDbs
 
 -- | Prepare sandbox for scanning. This is used for stack project to build & configure.
@@ -273,13 +279,12 @@ scanSandbox opts sbox = Log.scope "sandbox" $ do
 	dbval <- readDB
 	prepareSandbox sbox
-	pdbs <- liftExceptT $ sandboxPackageDbStack sbox
+	pdbs <- liftExceptT_ $ sandboxPackageDbStack sbox
 	let
 		scannedDbs = databasePackageDbs dbval
 		unscannedDbs = filter ((`notElem` scannedDbs) . topPackageDb) $ reverse $ packageDbStacks pdbs
 	if null unscannedDbs
-		then do
-			Log.log Log.Trace $ "sandbox already scanned"
+		then Log.log Log.Trace $ "sandbox already scanned"
 		else runTasks $ map (scanPackageDb opts) unscannedDbs
 
 -- | Scan top of package-db stack, usable for rescan
@@ -288,10 +293,10 @@ 	watch (\w -> watchPackageDb w pdbs opts)
 	mlocs <- liftM
 		(filter (\mloc -> preview modulePackageDb mloc == Just (topPackageDb pdbs))) $
-		liftExceptT $ listModules opts pdbs
+		liftExceptT_ $ listModules opts pdbs
 	scan (Cache.loadPackageDb (topPackageDb pdbs)) (packageDbDB (topPackageDb pdbs)) ((,,) <$> mlocs <*> pure [] <*> pure Nothing) opts $ \mlocs' -> do
-		ms <- liftExceptT $ browseModules opts pdbs (mlocs' ^.. each . _1)
-		docs <- liftExceptT $ hdocsCabal pdbs opts
+		ms <- liftExceptT_ $ browseModules opts pdbs (mlocs' ^.. each . _1)
+		docs <- liftExceptT_ $ hdocsCabal pdbs opts
 		updater $ return $ mconcat $ map (fromModule . fmap (setDocs' docs)) ms
 	where
 		setDocs' :: Map String (Map String String) -> Module -> Module
@@ -299,7 +304,7 @@ 
 -- | Scan project file
 scanProjectFile :: UpdateMonad m => [String] -> FilePath -> m Project
-scanProjectFile opts cabal = runTask "scanning" cabal $ liftExceptT $ S.scanProjectFile opts cabal
+scanProjectFile opts cabal = runTask "scanning" cabal $ liftExceptT_ $ S.scanProjectFile opts cabal
 
 -- | Scan project and related package-db stack
 scanProjectStack :: UpdateMonad m => [String] -> FilePath -> m ()
@@ -314,7 +319,7 @@ scanProject opts cabal = runTask "scanning" (project cabal) $ Log.scope "project" $ do
 	proj <- scanProjectFile opts cabal
 	watch (\w -> watchProject w proj opts)
-	S.ScanContents _ [(_, sources)] _ <- liftExceptT $ S.enumProject proj
+	S.ScanContents _ [(_, sources)] _ <- liftExceptT_ $ S.enumProject proj
 	scan (Cache.loadProject $ view projectCabal proj) (projectDB proj) sources opts $ \ms -> do
 		scanModules opts ms
 		updater $ return $ fromProject proj
@@ -322,7 +327,7 @@ -- | Scan directory for source files and projects
 scanDirectory :: UpdateMonad m => [String] -> FilePath -> m ()
 scanDirectory opts dir = runTask "scanning" dir $ Log.scope "directory" $ do
-	S.ScanContents standSrcs projSrcs pdbss <- liftExceptT $ S.enumDirectory dir
+	S.ScanContents standSrcs projSrcs pdbss <- liftExceptT_ $ S.enumDirectory dir
 	runTasks [scanProject opts (view projectCabal p) | (p, _) <- projSrcs]
 	runTasks $ map (scanPackageDb opts) pdbss -- TODO: Don't rescan
 	mapMOf_ (each . _1) (watch . flip watchModule) standSrcs
@@ -351,13 +356,23 @@ -- | Scan docs for inspected modules
 scanDocs :: UpdateMonad m => [InspectedModule] -> m ()
 scanDocs ims = do
-	w <- liftIO $ ghcWorker ["-haddock"] (return ())
+	-- w <- liftIO $ ghcWorker ["-haddock"] (return ())
+	w <- askSession sessionGhc
+	liftIO $ do
+		restartWorker w
+		inWorker w $ setCmdOpts ["-haddock"]
 	runTasks $ map (scanDocs' w) ims
 	where
 		scanDocs' w im = runTask "scanning docs" (view inspectedId im) $ Log.scope "docs" $ do
 			Log.log Log.Trace $ "Scanning docs for {}" ~~  view inspectedId im
-			im' <- liftExceptT $ S.scanModify (\opts _ -> inWorkerT w . inspectDocsGhc opts) im
-			Log.log Log.Trace $ "Docs for {} updated" ~~ view inspectedId im
+			im' <-
+				liftExceptT
+					("Scanning docs for {} failed: {}" ~~ view inspectedId im)
+					(S.scanModify (\opts _ -> inWorkerT w . inspectDocsGhc opts) im)
+				<|> return im
+			Log.log Log.Trace $ "Docs for {} updated: documented {} declarations" ~~
+				view inspectedId im' ~~
+				length (im' ^.. inspectionResult . _Right . moduleDeclarations . each . declarationDocs . _Just)
 			updater $ return $ fromModule im'
 		inWorkerT w = ExceptT . inWorker w . runExceptT 
 
@@ -366,7 +381,11 @@ 	inferModTypes' im = runTask "inferring types" (view inspectedId im) $ Log.scope "docs" $ do
 		w <- askSession sessionGhc
 		Log.log Log.Trace $ "Inferring types for {}" ~~ view inspectedId im
-		im' <- liftExceptT $ S.scanModify (\opts cabal m -> inWorkerT w (inferTypes opts cabal m Nothing)) im
+		im' <-
+			liftExceptT
+				("Inferring types for {} failed: {}" ~~ view inspectedId im)
+				(S.scanModify (\opts cabal m -> inWorkerT w (inferTypes opts cabal m Nothing)) im)
+			<|> return im
 		Log.log Log.Trace $ "Types for {} inferred" ~~ view inspectedId im
 		updater $ return $ fromModule im'
 	inWorkerT w = ExceptT . inWorker w . runExceptT
@@ -388,7 +407,7 @@ 	dbval <- getCache cache' part'
 	let
 		obsolete = filterDB (\m -> view moduleIdLocation m `notElem` (mlocs ^.. each . _1)) (const False) dbval
-	changed <- liftExceptT $ S.changedModules dbval opts mlocs
+	changed <- liftExceptT "Getting changed modules failed: {}" $ S.changedModules dbval opts mlocs
 	cleaner $ return obsolete
 	act changed
 
@@ -427,11 +446,17 @@ 		scanFile opts $ view eventPath e
 	| otherwise = return ()
 
-liftExceptT :: CommandMonad m => ExceptT String IO a -> m a
-liftExceptT act = liftIO (runExceptT act) >>= either commandError_ return
+liftExceptT_ :: CommandMonad m => ExceptT String IO a -> m a
+liftExceptT_ = liftExceptT "{}"
 
+liftExceptT :: CommandMonad m => Format -> ExceptT String IO a -> m a
+liftExceptT msg act = liftIO (runExceptT act) >>= either onError return where
+	onError e = do
+		Log.log Log.Error $ msg ~~ e
+		commandError_ $ msg ~~ e
+
 liftCIO ::CommandMonad m => IO a -> m a
-liftCIO = liftExceptT . liftE
+liftCIO = liftExceptT "Exception during IO action: {}" . liftE
 
 processEvent :: UpdateOptions -> Watched -> Event -> ClientM IO ()
 processEvent uopts w e = runUpdate uopts $ updateEvent w e
src/HsDev/Inspect.hs view
@@ -122,10 +122,10 @@ -- | Get exports getExports :: H.ExportSpec -> [Export] getExports (H.EModuleContents (H.ModuleName m)) = [ExportModule $ fromString m]-getExports (H.EVar n) = [uncurry ExportName (identOfQName n) ExportNothing]-getExports (H.EAbs _ n) = [uncurry ExportName (identOfQName n) ExportNothing]-getExports (H.EThingAll n) = [uncurry ExportName (identOfQName n) ExportAll]-getExports (H.EThingWith n ns) = [uncurry ExportName (identOfQName n) $ ExportWith (map toStr ns)] where+getExports (H.EVar n) = [uncurry ExportName (identOfQName n) ThingNothing]+getExports (H.EAbs _ n) = [uncurry ExportName (identOfQName n) ThingNothing]+getExports (H.EThingAll n) = [uncurry ExportName (identOfQName n) ThingAll]+getExports (H.EThingWith n ns) = [uncurry ExportName (identOfQName n) $ ThingWith (map toStr ns)] where 	toStr :: H.CName -> Text 	toStr (H.VarName cn) = identOfName cn 	toStr (H.ConName cn) = identOfName cn@@ -140,7 +140,11 @@ 	(Just $ toPosition $ H.importLoc d) 	where 		mname (H.ModuleName n) = fromString n-		importLst (hiding, specs) = ImportList hiding $ map identOfName (concatMap childrenBi specs :: [H.Name])+		importLst (hiding, specs) = ImportList hiding $ map impSpec specs+		impSpec (H.IVar n) = ImportSpec (identOfName n) ThingNothing+		impSpec (H.IAbs _ n) = ImportSpec (identOfName n) ThingNothing+		impSpec (H.IThingAll n) = ImportSpec (identOfName n) ThingAll+		impSpec (H.IThingWith n ns) = ImportSpec (identOfName n) $ ThingWith $ map identOfName (concatMap childrenBi ns :: [H.Name])  -- | Decl declarations getDecls :: [H.Decl] -> [Declaration]
src/HsDev/Project.hs view
@@ -23,7 +23,7 @@ 
 import Control.Arrow
 import Control.DeepSeq (NFData(..))
-import Control.Lens (makeLenses, Simple, Lens, view, lens, at)
+import Control.Lens (makeLenses, Simple, Lens, view, lens)
 import Control.Exception
 import Control.Monad.Except
 import Data.Aeson
src/HsDev/Sandbox.hs view
@@ -11,11 +11,10 @@ 	) where
 
 import Control.Arrow
-import Control.Applicative
 import Control.DeepSeq (NFData(..))
 import Control.Monad.Trans.Maybe
 import Control.Monad.Except
-import Control.Lens (view, makeLenses, Lens', lens)
+import Control.Lens (view, makeLenses)
 import Data.Aeson
 import Data.Maybe (isJust, fromMaybe)
 import Data.List ((\\))
@@ -85,9 +84,9 @@ 		else return Nothing
 	where
 		sandboxFromDir :: FilePath -> Maybe Sandbox
-		sandboxFromDir fpath
-			| takeFileName fpath == "stack.yaml" = sandboxFromPath (takeDirectory fpath </> ".stack-work")
-			| otherwise = sandboxFromPath fpath
+		sandboxFromDir fdir
+			| takeFileName fdir == "stack.yaml" = sandboxFromPath (takeDirectory fdir </> ".stack-work")
+			| otherwise = sandboxFromPath fdir
 
 -- | Search sandbox by parent directory
 searchSandbox :: FilePath -> IO (Maybe Sandbox)
@@ -108,8 +107,6 @@ 	case mbox of
 		Nothing -> return userDb
 		Just sbox -> liftM (either (const userDb) id) $ runExceptT $ sandboxPackageDbStack sbox
-	where
-		userDb = PackageDbStack [UserDb]
 
 -- | Restore package-db stack by package-db
 restorePackageDbStack :: PackageDb -> IO PackageDbStack
src/HsDev/Scan.hs view
@@ -16,16 +16,14 @@ 	module Control.Monad.Except,
 	) where
 
-import Control.Applicative ((<|>))
 import Control.DeepSeq
-import Control.Lens (view, preview, set, over, each, _Right, _1, _2, _3, (^.), (^..), at)
+import Control.Lens (view, preview, set, over, each, _Right, _1, _2, _3, (^.), (^..))
 import Control.Monad.Except
 import Data.Maybe (catMaybes, fromMaybe, isJust)
 import Data.List (intercalate)
 import System.Directory
 import Text.Format
 
-import Data.Deps
 import HsDev.Scan.Browse (browsePackages)
 import HsDev.Server.Types (FileContents(..))
 import HsDev.Sandbox
@@ -176,9 +174,9 @@ 		getDbs = maybe (return userDb) searchPackageDbStack . preview packageDb
 scanModule _ _ (ModuleSource _) _ = throwError "Can inspect only modules in file or cabal"
 
--- | Scan additional info and modify scanned module. Dones't fail on error, just left module unchanged
+-- | Scan additional info and modify scanned module
 scanModify :: ([String] -> PackageDbStack -> Module -> ExceptT String IO Module) -> InspectedModule -> ExceptT String IO InspectedModule
-scanModify f im = traverse f' im <|> return im where
+scanModify f im = traverse f' im where
 	f' m = do
 		pdbs <- liftIO $ case view moduleLocation m of
 			-- TODO: Get actual sandbox stack
src/HsDev/Scan/Browse.hs view
@@ -21,7 +21,6 @@ import Data.Version
 import System.Directory
 import System.FilePath
-import Text.Read (readMaybe)
 
 import Data.Deps
 import HsDev.PackageDb
@@ -93,7 +92,7 @@ 		_moduleName = fromString thisModule,
 		_moduleDocs = Nothing,
 		_moduleLocation = thisLoc,
-		_moduleExports = Just [ExportName Nothing (view declarationName d) ExportNothing | d <- ds],
+		_moduleExports = Just [ExportName Nothing (view declarationName d) ThingNothing | d <- ds],
 		_moduleImports = [import_ iname | iname <- ordNub (mapMaybe (preview definedModule) ds), iname /= fromString thisModule],
 		_moduleDeclarations = sortDeclarations ds }
 	where
src/HsDev/Server/Base.hs view
@@ -16,7 +16,6 @@ import Control.Monad.Except
 import Control.Monad.Reader
 import Data.Default
-import Data.List (intercalate)
 import qualified Data.Map as M
 import Data.Maybe
 import Data.String
@@ -55,7 +54,7 @@ initLog sopts = do
 	msgs <- F.newChan
 	l <- newLog (constant [rule']) $ concat [
-		[logger text console],
+		[logger text console | not $ serverSilent sopts],
 		[logger text (chaner msgs)],
 		maybeToList $ (logger text . file) <$> serverLog sopts]
 	Log.writeLog l Log.Info ("Log politics: low = {}, high = {}" ~~ logLow ~~ logHigh)
@@ -78,7 +77,7 @@ 		outputStr Log.Trace $ "Checking cache version in {}" ~~ cdir 
 		ver <- Cache.readVersion $ cdir </> Cache.versionCache
 		outputStr Log.Debug $ "Cache version: {}" ~~ strVersion ver
-		when (not $ sameVersion (cutVersion version) (cutVersion ver)) $ ignoreIO $ do
+		unless (sameVersion (cutVersion version) (cutVersion ver)) $ ignoreIO $ do
 			outputStr Log.Info $ "Cache version ({cache}) is incompatible with hsdev version ({hsdev}), removing cache ({dir})" ~~
 				("cache" %= strVersion ver) ~~
 				("hsdev" %= strVersion version) ~~
src/HsDev/Server/Types.hs view
@@ -37,7 +37,6 @@ import HsDev.Database
 import qualified HsDev.Database.Async as DB
 import HsDev.Project
-import HsDev.Sandbox
 import HsDev.Symbols
 import HsDev.Server.Message
 import HsDev.Watcher.Types (Watcher)
@@ -234,11 +233,12 @@ 	serverLog :: Maybe FilePath,
 	serverLogConfig :: String,
 	serverCache :: Maybe FilePath,
-	serverLoad :: Bool }
+	serverLoad :: Bool,
+	serverSilent :: Bool }
 		deriving (Show)
 
 instance Default ServerOpts where
-	def = ServerOpts def 0 Nothing "use default" Nothing False
+	def = ServerOpts def 0 Nothing "use default" Nothing False False
 
 -- | Client options
 data ClientOpts = ClientOpts {
@@ -269,7 +269,8 @@ 		optional logArg <*>
 		(logConfigArg <|> pure (serverLogConfig def)) <*>
 		optional cacheArg <*>
-		loadFlag
+		loadFlag <*>
+		serverSilentFlag
 
 instance FromCmd ClientOpts where
 	cmdP = ClientOpts <$>
@@ -288,6 +289,7 @@ noFileFlag :: Parser Bool
 loadFlag :: Parser Bool
 prettyFlag :: Parser Bool
+serverSilentFlag :: Parser Bool
 stdinFlag :: Parser Bool
 silentFlag :: Parser Bool
 
@@ -306,6 +308,7 @@ noFileFlag = switch (long "no-file" <> help "don't use mmap files")
 loadFlag = switch (long "load" <> help "force load all data from cache on startup")
 prettyFlag = switch (long "pretty" <> help "pretty json output")
+serverSilentFlag = switch (long "silent" <> help "no stdout/stderr")
 stdinFlag = switch (long "stdin" <> help "pass data to stdin")
 silentFlag = switch (long "silent" <> help "supress notifications")
 
@@ -316,7 +319,8 @@ 	marg "--log" (serverLog sopts),
 	["--log-config", serverLogConfig sopts],
 	marg "--cache" (serverCache sopts),
-	["--load" | serverLoad sopts]]
+	["--load" | serverLoad sopts],
+	["--silent" | serverSilent sopts]]
 	where
 		marg :: String -> Maybe String -> [String]
 		marg n (Just v) = [n, v]
@@ -613,6 +617,7 @@ inferFlag :: Parser Bool
 localsFlag :: Parser Bool
 moduleArg :: Parser String
+packageDbArg :: Parser PackageDb
 packageArg :: Parser String
 pathArg :: Mod OptionFields String -> Parser FilePath
 projectArg :: Parser String
src/HsDev/Stack.hs view
@@ -12,7 +12,7 @@ 	) where
 
 import Control.Arrow
-import Control.Lens (makeLenses, Lens', at, ix, lens, (^?), (^.), view)
+import Control.Lens (makeLenses, Lens', at, ix, lens, (^?), (^.))
 import Control.Monad
 import Control.Monad.Trans.Maybe
 import Control.Monad.IO.Class
@@ -26,7 +26,6 @@ import System.Process
 
 import HsDev.PackageDb
-import HsDev.Project
 import HsDev.Util (withCurrentDirectory)
 
 -- | Invoke stack command, we are trying to get actual stack near current hsdev executable
@@ -88,12 +87,12 @@ -- | Projects paths
 projectEnv :: FilePath -> MaybeT IO StackEnv
 projectEnv p = do
-	hasConfig <- liftIO $ doesFileExist yaml
+	hasConfig <- liftIO $ doesFileExist yaml'
 	guard hasConfig
-	paths' <- path (Just yaml)
+	paths' <- path (Just yaml')
 	MaybeT $ return $ getStackEnv paths'
 	where
-		yaml = p </> "stack.yaml"
+		yaml' = p </> "stack.yaml"
 
 -- | Get package-db stack for stack environment
 stackPackageDbStack :: Lens' StackEnv PackageDbStack
src/HsDev/Symbols.hs view
@@ -4,7 +4,7 @@ module HsDev.Symbols (
 	-- * Information
 	export,
-	passImportList,
+	passThingSpec, passImportSpec, imported, exported,
 	importNames, import_,
 	Symbol(..),
 	unnamedModuleId,
@@ -43,14 +43,12 @@ import Data.Function (on)
 import Data.List
 import Data.Maybe (fromMaybe)
-import qualified Data.Map as M
 import Data.Ord (comparing)
 import Data.Text (Text)
 import qualified Data.Text as T (concat)
 import System.Directory
 import System.FilePath
 
-import Data.Deps
 import System.Directory.Paths
 
 import HsDev.Symbols.Types
@@ -64,11 +62,37 @@ export (ExportName (Just q) n _) = T.concat [q, ".", n]
 export (ExportModule m) = m
 
--- | Check whether name pass import list
-passImportList :: ImportList -> Text -> Bool
-passImportList (ImportList hiding names) n
-	| hiding = n `notElem` names
-	| otherwise = n `elem` names
+-- | Does name pass thing spec
+passThingSpec :: Text -> ThingPart -> Bool
+passThingSpec _ ThingNothing = False
+passThingSpec _ ThingAll = True
+passThingSpec n (ThingWith ns) = n `elem` ns
+
+-- | Does declaration pass import-list spec
+passImportSpec :: Declaration -> ImportSpec -> Bool
+passImportSpec decl' (ImportSpec n p)
+	| view declarationName decl' == n = True
+	| preview (declaration . related . _Just) decl' == Just n = view declarationName decl' `passThingSpec` p
+	| otherwise = False
+
+-- | Check whether declaration passes import list
+imported :: Declaration -> ImportList -> Bool
+imported decl' (ImportList hiding specs) = invert $ any (decl' `passImportSpec`) specs where
+	invert = if hiding then not else id
+
+-- | Check whether declaration passes export
+exported :: Declaration -> Export -> Bool
+exported decl' (ExportName q n p)
+	| view declarationName decl' == n = checkImport
+	| preview (declaration . related . _Just) decl' == Just n = view declarationName decl' `passThingSpec` p
+	| otherwise = False
+	where
+		checkImport = case q of
+			Nothing -> any (not . view importIsQualified) $ fromMaybe [] $ view declarationImported decl'
+			Just q' -> any ((q' `elem`) . importNames) $ fromMaybe [] $ view declarationImported decl'
+exported decl' (ExportModule m) = any (unqualBy m) . fromMaybe [] . view declarationImported $ decl' where
+	unqualBy :: Text -> Import -> Bool
+	unqualBy m' i = m' `elem` importNames i && not (view importIsQualified i)
 
 -- | Get import module names - full and synonym
 importNames :: Import -> [Text]
src/HsDev/Symbols/Resolve.hs view
@@ -3,7 +3,7 @@ module HsDev.Symbols.Resolve (
 	ResolveM(..),ResolvedTree, ResolvedModule(..), resolvedModule, resolvedScope, resolvedExports,
 	scopeModule, exportsModule, resolvedTopScope,
-	resolve, resolveOne, resolveModule, exported, resolveImport,
+	resolve, resolveOne, resolveModule, resolveImports, resolveImport,
 	mergeImported
 	) where
 
@@ -12,21 +12,26 @@ import Control.Monad.Reader
 import Control.Monad.State
 import Data.Function (on)
-import Data.List (sortBy, groupBy, delete, nubBy)
+import Data.List (sortBy, groupBy, delete)
 import qualified Data.Map as M
 import Data.Maybe (fromMaybe, listToMaybe, catMaybes)
 import Data.Maybe.JustIf
 import Data.Ord (comparing)
+import qualified Data.Set as S
 import Data.String (fromString)
 import Data.Text (Text)
 
 import HsDev.Database
 import HsDev.Symbols
 import HsDev.Symbols.Util
+import HsDev.Util (uniqueBy)
 
+-- | Map from name to modules
+type ModuleMap = M.Map Text [Module]
+
 -- | Resolve monad uses existing @Database@ and @ResolvedTree@ as state.
-newtype ResolveM a = ResolveM { runResolveM :: ReaderT Database (State ResolvedTree) a }
-	deriving (Functor, Applicative, Monad, MonadState ResolvedTree, MonadReader Database)
+newtype ResolveM a = ResolveM { runResolveM :: ReaderT (Database, ModuleMap) (State ResolvedTree) a }
+	deriving (Functor, Applicative, Monad, MonadState ResolvedTree, MonadReader (Database, ModuleMap))
 
 -- | Tree of resolved modules
 type ResolvedTree = Map ModuleId ResolvedModule
@@ -55,7 +60,11 @@ 
 -- | Resolve modules, function is not IO, so all file names must be canonicalized
 resolve :: (Traversable t, Foldable t) => Database -> t Module -> t ResolvedModule
-resolve db = flip evalState M.empty . flip runReaderT db . runResolveM . traverse resolveModule
+resolve db = flip evalState M.empty . flip runReaderT (db, m) . runResolveM . traverse resolveModule where
+	m :: ModuleMap
+	m = M.fromList $ map ((view moduleName . head) &&& id) $
+		groupBy ((==) `on` view moduleName) $
+		sortBy (comparing (view moduleName)) $ allModules db
 
 -- | Resolve one module
 resolveOne :: Database -> Module -> ResolvedModule
@@ -71,14 +80,14 @@ 			_resolvedExports = view moduleDeclarations m }
 		_ -> do
 			scope' <-
-				liftM ((thisDecls ++) . mergeImported . concat) .
-				mapM (resolveImport m) .
+				liftM (thisDecls ++) .
+				resolveImports m .
 				(import_ (fromString "Prelude") :) .
 				view moduleImports $ m
 			let
 				exported' = case view moduleExports m of
 					Nothing -> thisDecls
-					Just exports' -> unique $ catMaybes $ exported <$> scope' <*> exports'
+					Just exports' -> unique $ catMaybes $ mexported <$> scope' <*> exports'
 			return $ ResolvedModule m (sortDeclarations scope') (sortDeclarations exported')
 	thisDecls :: [Declaration]
 	thisDecls = map (selfDefined . selfImport) $ view moduleDeclarations m
@@ -92,34 +101,31 @@ 		modify $ M.insert (view (resolvedModule . moduleId) rm) rm
 		return rm
 	unique :: [Declaration] -> [Declaration]
-	unique = nubBy ((==) `on` declId) . sortBy (comparing declId)
+	unique = uniqueBy declId
 	declId :: Declaration -> (Text, Maybe ModuleId)
 	declId = view declarationName &&& view declarationDefined
+	mexported decl' e' = decl' `justIf` exported decl' e'
 
-exported :: Declaration -> Export -> Maybe Declaration
-exported decl' (ExportName q n p)
-	| view declarationName decl' == n = decl' `justIf` checkImport
-	| preview (declaration . related . _Just) decl' == Just n = case p of
-		ExportNothing -> Nothing
-		ExportAll -> Just decl'
-		ExportWith ns -> decl' `justIf` (view declarationName decl' `elem` ns)
-	| otherwise = Nothing
-	where
-		checkImport = case q of
-			Nothing -> any (not . view importIsQualified) $ fromMaybe [] $ view declarationImported decl'
-			Just q' -> any ((q' `elem`) . importNames) $ fromMaybe [] $ view declarationImported decl'
-exported decl' (ExportModule m) = decl' `justWhen` (any (unqualBy m) . fromMaybe [] . view declarationImported) where
-	unqualBy :: Text -> Import -> Bool
-	unqualBy m' i = m' `elem` importNames i && not (view importIsQualified i)
+-- | Bring declarations into scope by imports
+resolveImports :: Module -> [Import] -> ResolveM [Declaration]
+resolveImports m is = do
+	db <- asks fst
+	let
+		deps = maybe S.empty S.fromList $ do
+			f <- preview (moduleLocation . moduleFile) m
+			p <- preview (moduleLocation . moduleProject . _Just) m
+			p' <- refineProject db p
+			return $ delete (view projectName p') $ concatMap (view infoDepends) $ fileTargets p' f
+	liftM (mergeImported . concat) $ mapM (resolveImport deps m) is
 
--- | Bring declarations into scope
-resolveImport :: Module -> Import -> ResolveM [Declaration]
-resolveImport m i = liftM (map $ setImport i) resolveImport' where
+-- | Bring declarations into scope, first parameter is set of visible packages
+resolveImport :: S.Set String -> Module -> Import -> ResolveM [Declaration]
+resolveImport deps m i = liftM (map $ setImport i) resolveImport' where
 	resolveImport' :: ResolveM [Declaration]
 	resolveImport' = do
 		ms <- case view moduleLocation m of
 			FileModule file proj -> do
-				db <- ask
+				db <- asks fst
 				let
 					proj' = proj >>= refineProject db
 				case proj' of
@@ -128,29 +134,28 @@ 						installed]
 					Just p -> selectImport i [
 						inProject p,
-						inDepsOf' file p]
-			InstalledModule cabal _ _ -> selectImport i [inPackageDb cabal]
+						inDeps]
+			InstalledModule pdb _ _ -> selectImport i [inPackageDb pdb]
 			ModuleSource _ -> selectImport i [installed]
 		fromMaybe [] <$> traverse (liftM (filterImportList . view resolvedExports) . resolveModule) ms
 	setImport :: Import -> Declaration -> Declaration
 	setImport i' = set declarationImported (Just [i'])
 	selectImport :: Import -> [ModuleId -> Bool] -> ResolveM (Maybe Module)
 	selectImport i' fs = do
-		db <- ask
+		modsMap <- asks snd
+		let
+			mods = fromMaybe [] $ M.lookup (view importModuleName i') modsMap
 		return $
 			listToMaybe $
 			newestPackage $
 			fromMaybe [] $
 			listToMaybe $ dropWhile null
-				[selectModules (select' f) db | f <- fs]
-		where
-			select' f md  = view moduleName md == view importModuleName i' && f (view moduleId md)
+				[filter (f . view moduleId) mods | f <- fs]
 	filterImportList :: [Declaration] -> [Declaration]
 	filterImportList = case view importList i of
 		Nothing -> id
-		Just il -> filter (passImportList il . view declarationName)
-	deps f p = delete (view projectName p) $ concatMap (view infoDepends) $ fileTargets p f
-	inDepsOf' f p m' = any (`inPackage` m') (deps f p)
+		Just il -> filter (`imported` il)
+	inDeps = maybe False (`S.member` deps) . preview (moduleIdLocation . modulePackage . _Just . packageName)
 
 -- | Merge imported declarations
 mergeImported :: [Declaration] -> [Declaration]
src/HsDev/Symbols/Types.hs view
@@ -2,32 +2,22 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module HsDev.Symbols.Types (
-	ExportPart(..),
-	Export(..),
-	ImportList(..),
-	Import(..),
-	ModuleId(..),
-	Module(..), moduleContents, moduleId,
-	Declaration(..), minimalDecl,
-	TypeInfo(..), showTypeInfo,
-	DeclarationInfo(..), declarationInfo, declarationTypeCtor, declarationTypeName,
-	ModuleDeclaration(..),
-	ExportedDeclaration(..),
-	Inspection(..),
-	Inspected(..),
+	ThingPart(..),
+	Export(..), exportQualified, exportName, exportPart, exportModule,
+	ImportSpec(..), importSpecName, importSpecPart,
+	ImportList(..), hidingList, importSpecs,
+	Import(..), importModuleName, importIsQualified, importAs, importList, importPosition,
+	ModuleId(..), moduleIdName, moduleIdLocation,
+	Module(..), moduleName, moduleDocs, moduleLocation, moduleExports, moduleImports, moduleDeclarations, moduleContents, moduleId,
+	Declaration(..), declarationName, declarationDefined, declarationImported, declarationDocs, declarationPosition, declaration, minimalDecl,
+	TypeInfo(..), typeInfoContext, typeInfoArgs, typeInfoDefinition, typeInfoFunctions, showTypeInfo,
+	DeclarationInfo(..), functionType, localDeclarations, related, typeInfo, declarationInfo, declarationTypeCtor, declarationTypeName,
+	ModuleDeclaration(..), declarationModuleId, moduleDeclaration,
+	ExportedDeclaration(..), exportedBy, exportedDeclaration,
+	Inspection(..), inspectionAt, inspectionOpts,
+	Inspected(..), inspection, inspectedId, inspectionResult,
 	InspectedModule,
 
-	exportQualified, exportName, exportPart, exportModule,
-	hidingList, importSpec, importModuleName, importIsQualified, importAs, importList, importPosition,
-	moduleIdName, moduleIdLocation,
-	moduleName, moduleDocs, moduleLocation, moduleExports, moduleImports, moduleDeclarations,
-	declarationName, declarationDefined, declarationImported, declarationDocs, declarationPosition, declaration,
-	typeInfoContext, typeInfoArgs, typeInfoDefinition, typeInfoFunctions,
-	functionType, localDeclarations, related, typeInfo,
-	declarationModuleId, moduleDeclaration,
-	exportedBy, exportedDeclaration,
-	inspectionAt, inspectionOpts, inspection, inspectedId, inspectionResult,
-
 	module HsDev.PackageDb,
 	module HsDev.Project,
 	module HsDev.Symbols.Class,
@@ -52,40 +42,40 @@ import HsDev.Symbols.Documented
 import HsDev.Util (tab, tabs, (.::), (.::?), (.::?!), noNulls)
 
--- | What to export for data/class etc
-data ExportPart = ExportNothing | ExportAll | ExportWith [Text] deriving (Eq, Ord)
+-- | What to export/import for data/class etc
+data ThingPart = ThingNothing | ThingAll | ThingWith [Text] deriving (Eq, Ord)
 
-instance NFData ExportPart where
-	rnf ExportNothing = ()
-	rnf ExportAll = ()
-	rnf (ExportWith ns) = rnf ns
+instance NFData ThingPart where
+	rnf ThingNothing = ()
+	rnf ThingAll = ()
+	rnf (ThingWith ns) = rnf ns
 
-instance Show ExportPart where
-	show ExportNothing = ""
-	show ExportAll = "(..)"
-	show (ExportWith ns) = "(" ++ intercalate ", " (map unpack ns) ++ ")"
+instance Show ThingPart where
+	show ThingNothing = ""
+	show ThingAll = "(..)"
+	show (ThingWith ns) = "(" ++ intercalate ", " (map unpack ns) ++ ")"
 
-instance ToJSON ExportPart where
-	toJSON ExportNothing = toJSON ("nothing" :: String)
-	toJSON ExportAll = toJSON ("all" :: String)
-	toJSON (ExportWith ns) = object [
+instance ToJSON ThingPart where
+	toJSON ThingNothing = toJSON ("nothing" :: String)
+	toJSON ThingAll = toJSON ("all" :: String)
+	toJSON (ThingWith ns) = object [
 		"with" .= ns]
 
-instance FromJSON ExportPart where
+instance FromJSON ThingPart where
 	parseJSON v = parse' <|> parseWith v where
 		parse' = do
 			s <- parseJSON v
 			mplus
-				(guard (s == ("nothing" :: String)) >> return ExportNothing)
-				(guard (s == ("all" :: String)) >> return ExportAll)
-		parseWith = withObject "export part" $ \v' -> ExportWith <$> v' .:: "with"
+				(guard (s == ("nothing" :: String)) >> return ThingNothing)
+				(guard (s == ("all" :: String)) >> return ThingAll)
+		parseWith = withObject "export part" $ \v' -> ThingWith <$> v' .:: "with"
 
 -- | Module export
 data Export =
 	ExportName {
 		_exportQualified :: Maybe Text,
 		_exportName :: Text,
-		_exportPart :: ExportPart } |
+		_exportPart :: ThingPart } |
 	ExportModule { _exportModule :: Text }
 		deriving (Eq, Ord)
 
@@ -107,27 +97,45 @@ 		(ExportName <$> (v .:: "module") <*> (v .:: "name") <*> (v .:: "part")) <|>
 		(ExportModule <$> (v .:: "module"))
 
+-- | Import spec
+data ImportSpec = ImportSpec {
+	_importSpecName :: Text,
+	_importSpecPart :: ThingPart }
+		deriving (Eq, Ord)
+
+instance NFData ImportSpec where
+	rnf (ImportSpec n p) = rnf n `seq` rnf p
+
+instance Show ImportSpec where
+	show (ImportSpec n p) = unpack n ++ show p
+
+instance ToJSON ImportSpec where
+	toJSON (ImportSpec n p) = object ["name" .= n, "part" .= p]
+
+instance FromJSON ImportSpec where
+	parseJSON = withObject "import-spec" $ \v -> ImportSpec <$> (v .:: "name") <*> (v .:: "part")
+
 -- | Import list
 data ImportList = ImportList {
 	_hidingList :: Bool,
-	_importSpec :: [Text] }
+	_importSpecs :: [ImportSpec] }
 		deriving (Eq, Ord)
 
 instance NFData ImportList where
 	rnf (ImportList h ls) = rnf h `seq` rnf ls
 
 instance Show ImportList where
-	show (ImportList h ls) = (if h then ("hiding " ++) else id) $ "(" ++ intercalate ", " (map unpack ls) ++ ")"
+	show (ImportList h ls) = (if h then ("hiding " ++) else id) $ "(" ++ intercalate ", " (map show ls) ++ ")"
 
 instance ToJSON ImportList where
 	toJSON (ImportList h ls) = object [
 		"hiding" .= h,
-		"spec" .= ls]
+		"specs" .= ls]
 
 instance FromJSON ImportList where
 	parseJSON = withObject "import-list" $ \v -> ImportList <$>
 		v .:: "hiding" <*>
-		v .:: "spec"
+		v .:: "specs"
 
 -- | Module import
 data Import = Import {
@@ -551,6 +559,7 @@ 	brief = brief . _moduleDeclaration
 
 makeLenses ''Export
+makeLenses ''ImportSpec
 makeLenses ''ImportList
 makeLenses ''Import
 makeLenses ''ModuleId
src/HsDev/Symbols/Util.hs view
@@ -1,7 +1,7 @@ module HsDev.Symbols.Util (
 	projectOf, packageDbOf, packageOf,
 	inProject, inDepsOfTarget, inDepsOfFile, inDepsOfProject, inPackageDb, inPackageDbStack, inPackage, inVersion, inFile, inModuleSource, inModule, byFile, installed, standalone,
-	imports, qualifier, imported, visible, inScope,
+	imports, qualifier, moduleImported, visible, inScope,
 	newestPackage,
 	sourceModule, visibleModule, preferredModule, uniqueModules,
 	allOf, anyOf
@@ -125,8 +125,8 @@ 	imports m
 
 -- | Check if module imported via imports specified
-imported :: ModuleId -> [Import] -> Bool
-imported m = any (\i -> view moduleIdName m == view importModuleName i)
+moduleImported :: ModuleId -> [Import] -> Bool
+moduleImported m = any (\i -> view moduleIdName m == view importModuleName i)
 
 -- | Check if module visible from this module within this project
 visible :: Project -> ModuleId -> ModuleId -> Bool
@@ -138,7 +138,7 @@ 
 -- | Check if module is in scope with qualifier
 inScope :: Module -> Maybe String -> ModuleId -> Bool
-inScope this q m = m `imported` qualifier this q
+inScope this q m = m `moduleImported` qualifier this q
 
 -- | Select symbols with last package version
 newestPackage :: Symbol a => [a] -> [a]
src/HsDev/Tools/Ghc/Check.hs view
@@ -15,24 +15,20 @@ 
 import Control.Lens (preview, view, each, _Just, (^..))
 import Control.Monad.Except
-import Control.Concurrent.FiniteChan
 import Data.Maybe (fromMaybe)
-import HsDev.Tools.Ghc.Worker
 import System.FilePath (makeRelative)
 import System.Directory (doesDirectoryExist)
 
 import GHC hiding (Warning, Module, moduleName)
-import Outputable
-import FastString (unpackFS)
-import qualified ErrUtils as E
 
-import System.Directory.Paths
+import Control.Concurrent.FiniteChan
 import HsDev.PackageDb
 import HsDev.Scan.Browse (browsePackages)
 import HsDev.Symbols (moduleOpts)
 import HsDev.Symbols.Location
 import HsDev.Symbols.Types
 import HsDev.Tools.Base
+import HsDev.Tools.Ghc.Worker
 import HsDev.Tools.Types
 import HsDev.Util (readFileUtf8, ordNub)
 
@@ -41,7 +37,7 @@ checkFiles opts pdbs files _ = do
 	ch <- liftIO newChan
 	withFlags $ do
-		modifyFlags (\fs -> fs { log_action = logAction ch })
+		modifyFlags (\fs -> fs { log_action = logToChan ch })
 		_ <- setCmdOpts ("-Wall" : (packageDbStackOpts pdbs ++ opts))
 		clearTargets
 		mapM (`makeTarget` Nothing) files >>= loadTargets
@@ -65,7 +61,7 @@ 				packageDbStackOpts pdbs,
 				moduleOpts pkgs m,
 				opts]
-			modifyFlags (\fs -> fs { log_action = logAction ch })
+			modifyFlags (\fs -> fs { log_action = logToChan ch })
 			clearTargets
 			target <- makeTarget (makeRelative dir file) msrc
 			loadTargets [target]
@@ -80,29 +76,6 @@ -- | Check module and collect warnings and errors
 checkSource :: [String] -> PackageDbStack -> Module -> String -> ExceptT String Ghc [Note OutputMessage]
 checkSource opts pdbs m src = check opts pdbs m (Just src)
-
--- | Log  ghc warnings and errors as to chan
--- You may have to apply recalcTabs on result notes
-logAction :: Chan (Note OutputMessage) -> DynFlags -> E.Severity -> SrcSpan -> PprStyle -> SDoc -> IO ()
-logAction ch fs sev src _ msg
-	| Just sev' <- checkSev sev = do
-		src' <- canonicalize srcMod
-		putChan ch $ Note {
-			_noteSource = src',
-			_noteRegion = spanRegion src,
-			_noteLevel = Just sev',
-			_note = OutputMessage {
-				_message = showSDoc fs msg,
-				_messageSuggestion = Nothing } }
-	| otherwise = return ()
-	where
-		checkSev SevWarning = Just Warning
-		checkSev SevError = Just Error
-		checkSev SevFatal = Just Error
-		checkSev _ = Nothing
-		srcMod = case src of
-			RealSrcSpan s' -> FileModule (unpackFS $ srcSpanFile s') Nothing
-			_ -> ModuleSource Nothing
 
 -- Recalc tabs for notes
 recalcNotesTabs :: [Note OutputMessage] -> IO [Note OutputMessage]
src/HsDev/Tools/Ghc/Worker.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE PatternGuards #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module HsDev.Tools.Ghc.Worker (
@@ -12,6 +13,7 @@ 	-- * Utils
 	listPackages, spanRegion,
 	withCurrentDirectory,
+	logToChan, logToNull,
 
 	Ghc,
 
@@ -25,16 +27,22 @@ import Data.Maybe
 import Data.Time.Clock (getCurrentTime)
 import Data.Version (showVersion)
-import GHC
-import GHC.Paths
 import Packages
 import StringBuffer
 import System.Directory (getCurrentDirectory, setCurrentDirectory)
 import Text.Read
 
-import Control.Concurrent.Worker
+import GHC hiding (Warning, Module, moduleName)
+import GHC.Paths
+import Outputable
+import qualified ErrUtils as E
+import FastString (unpackFS)
 
-import HsDev.Symbols.Location (Position(..), Region(..), region, ModulePackage)
+import Control.Concurrent.FiniteChan
+import Control.Concurrent.Worker
+import System.Directory.Paths
+import HsDev.Symbols.Location (Position(..), Region(..), region, ModulePackage, ModuleLocation(..))
+import HsDev.Tools.Types
 
 -- | Ghc worker. Pass options and initializer action
 ghcWorker :: [String] -> Ghc () -> IO (Worker Ghc)
@@ -87,7 +95,10 @@ 
 -- | Set options after session reinit
 setCmdOpts :: [String] -> Ghc ()
-setCmdOpts opts = initGhcMonad (Just libdir) >> addCmdOpts opts
+setCmdOpts opts = do
+	initGhcMonad (Just libdir)
+	addCmdOpts opts
+	modifyFlags (\fs -> fs { log_action = logToNull })
 
 -- | Import some modules
 importModules :: [String] -> Ghc ()
@@ -134,6 +145,33 @@ withCurrentDirectory :: FilePath -> Ghc a -> Ghc a
 withCurrentDirectory dir act = gbracket (liftIO getCurrentDirectory) (liftIO . setCurrentDirectory) $
 	const (liftIO (setCurrentDirectory dir) >> act)
+
+-- | Log  ghc warnings and errors as to chan
+-- You may have to apply recalcTabs on result notes
+logToChan :: Chan (Note OutputMessage) -> DynFlags -> E.Severity -> SrcSpan -> PprStyle -> SDoc -> IO ()
+logToChan ch fs sev src _ msg
+	| Just sev' <- checkSev sev = do
+		src' <- canonicalize srcMod
+		putChan ch $ Note {
+			_noteSource = src',
+			_noteRegion = spanRegion src,
+			_noteLevel = Just sev',
+			_note = OutputMessage {
+				_message = showSDoc fs msg,
+				_messageSuggestion = Nothing } }
+	| otherwise = return ()
+	where
+		checkSev SevWarning = Just Warning
+		checkSev SevError = Just Error
+		checkSev SevFatal = Just Error
+		checkSev _ = Nothing
+		srcMod = case src of
+			RealSrcSpan s' -> FileModule (unpackFS $ srcSpanFile s') Nothing
+			_ -> ModuleSource Nothing
+
+-- | Don't log ghc warnings and errors
+logToNull :: DynFlags -> E.Severity -> SrcSpan -> PprStyle -> SDoc -> IO ()
+logToNull _ _ _ _ _ = return ()
 
 -- TODO: Load target by @ModuleLocation@, which may cause updating @DynFlags@
 
src/HsDev/Tools/GhcMod.hs view
@@ -84,7 +84,7 @@ 			_moduleName = fromString mname,
 			_moduleDocs = Nothing,
 			_moduleLocation = thisLoc,
-			_moduleExports = Just [ExportName Nothing (view declarationName d) ExportNothing | d <- ds],
+			_moduleExports = Just [ExportName Nothing (view declarationName d) ThingNothing | d <- ds],
 			_moduleImports = [import_ iname |
 				iname <- ordNub (mapMaybe (preview definedModule) ds),
 				iname /= fromString mname],
tests/Test.hs view
@@ -10,10 +10,12 @@ import Data.Default
 import HsDev
 import Test.Hspec
+import System.FilePath
+import System.Directory
 
 call :: Server -> Command -> IO (Maybe Value)
 call srv c = do
-	r <- inServer srv c
+	r <- inServer srv def c
 	case r of
 		Result v -> return $ Just v
 		Error e _ -> do
@@ -27,12 +29,13 @@ main = hspec $ do
 	describe "scan project" $ do
 		it "should scan project" $ do
-			s <- startServer def
-			_ <- call s $ Scan ["tests\\test-package"] [] [] [] [] [] False False
-			one <- call s $ InfoResolve "tests\\test-package\\ModuleOne.hs" True
+			dir <- getCurrentDirectory
+			s <- startServer (def { serverSilent = True })
+			_ <- call s $ Scan [dir </> "tests/test-package"] False [] [] [] [] [] False False
+			one <- call s $ InfoResolve (dir </> "tests/test-package/ModuleOne.hs") True
 			when (["test", "forkIO", "f"] /= exports one) $
 				expectationFailure "invalid exports of ModuleOne.hs"
-			two <- call s $ InfoResolve "tests\\test-package\\ModuleTwo.hs" True
+			two <- call s $ InfoResolve (dir </> "tests/test-package/ModuleTwo.hs") True
 			when (["f", "twice"] /= exports two) $
 				expectationFailure "invalid exports of ModuleTwo.hs"
 			_ <- call s Exit
tools/hsinspect.hs view
@@ -41,10 +41,11 @@ 		ghc <- liftIO $ ghcWorker ghcs (return ())
 		let
 			scanAdditional =
-				scanModify (\opts' _ -> inspectDocs opts') >=>
-				scanModify (\opts' pdbs m -> ExceptT (inWorker ghc (runExceptT $ inferTypes opts' pdbs m Nothing)))
+				scanModify' (\opts' _ -> inspectDocs opts') >=>
+				scanModify' (\opts' pdbs m -> ExceptT (inWorker ghc (runExceptT $ inferTypes opts' pdbs m Nothing)))
 		toJSON <$> scanAdditional im
 	inspect' (Opts (Just fcabal@(takeExtension -> ".cabal")) _) = do
 		fcabal' <- liftIO $ canonicalizePath fcabal
 		toJSON <$> readProject fcabal'
 	inspect' (Opts (Just mname) ghcs) = toJSON <$> scanModule [] ghcs (InstalledModule UserDb Nothing mname) Nothing
+	scanModify' f im = scanModify f im <|> return im