packages feed

hsdev 0.3.3.2 → 0.3.3.3

raw patch · 11 files changed

+90/−49 lines, 11 filesdep ~Cabaldep ~hdocsdep ~lensPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: Cabal, hdocs, lens

API changes (from Hackage documentation)

+ HsDev.Inspect: fileMTime :: Path -> IO POSIXTime
- HsDev.Project.Types: entity :: forall a_a1wPD a_a1ygx. Lens (Extensions a_a1wPD) (Extensions a_a1ygx) a_a1wPD a_a1ygx
+ HsDev.Project.Types: entity :: forall a_a1wPJ a_a1ygD. Lens (Extensions a_a1wPJ) (Extensions a_a1ygD) a_a1wPJ a_a1ygD
- HsDev.Project.Types: extensions :: forall a_a1wPD. Lens' (Extensions a_a1wPD) [Extension]
+ HsDev.Project.Types: extensions :: forall a_a1wPJ. Lens' (Extensions a_a1wPJ) [Extension]
- HsDev.Project.Types: ghcOptions :: forall a_a1wPD. Lens' (Extensions a_a1wPD) [Text]
+ HsDev.Project.Types: ghcOptions :: forall a_a1wPJ. Lens' (Extensions a_a1wPJ) [Text]
- HsDev.Server.Message: message :: forall a_a1X3V a_a1X9j. Lens (Message a_a1X3V) (Message a_a1X9j) a_a1X3V a_a1X9j
+ HsDev.Server.Message: message :: forall a_a1X41 a_a1X9p. Lens (Message a_a1X41) (Message a_a1X9p) a_a1X41 a_a1X9p
- HsDev.Server.Message: messageId :: forall a_a1X3V. Lens' (Message a_a1X3V) (Maybe String)
+ HsDev.Server.Message: messageId :: forall a_a1X41. Lens' (Message a_a1X41) (Maybe String)
- HsDev.Symbols.Types: inspectedKey :: forall k_a2Dij t_a2Dik a_a2Dil k_a2GxH. Lens (Inspected k_a2Dij t_a2Dik a_a2Dil) (Inspected k_a2GxH t_a2Dik a_a2Dil) k_a2Dij k_a2GxH
+ HsDev.Symbols.Types: inspectedKey :: forall k_a2Dhz t_a2DhA a_a2DhB k_a2GwX. Lens (Inspected k_a2Dhz t_a2DhA a_a2DhB) (Inspected k_a2GwX t_a2DhA a_a2DhB) k_a2Dhz k_a2GwX
- HsDev.Symbols.Types: inspection :: forall k_a2Dij t_a2Dik a_a2Dil. Lens' (Inspected k_a2Dij t_a2Dik a_a2Dil) Inspection
+ HsDev.Symbols.Types: inspection :: forall k_a2Dhz t_a2DhA a_a2DhB. Lens' (Inspected k_a2Dhz t_a2DhA a_a2DhB) Inspection
- HsDev.Symbols.Types: inspectionResult :: forall k_a2Dij t_a2Dik a_a2Dil a_a2GxI. Lens (Inspected k_a2Dij t_a2Dik a_a2Dil) (Inspected k_a2Dij t_a2Dik a_a2GxI) (Either HsDevError a_a2Dil) (Either HsDevError a_a2GxI)
+ HsDev.Symbols.Types: inspectionResult :: forall k_a2Dhz t_a2DhA a_a2DhB a_a2GwY. Lens (Inspected k_a2Dhz t_a2DhA a_a2DhB) (Inspected k_a2Dhz t_a2DhA a_a2GwY) (Either HsDevError a_a2DhB) (Either HsDevError a_a2GwY)
- HsDev.Symbols.Types: inspectionTags :: forall k_a2Dij t_a2Dik a_a2Dil t_a2GxJ. Lens (Inspected k_a2Dij t_a2Dik a_a2Dil) (Inspected k_a2Dij t_a2GxJ a_a2Dil) (Set t_a2Dik) (Set t_a2GxJ)
+ HsDev.Symbols.Types: inspectionTags :: forall k_a2Dhz t_a2DhA a_a2DhB t_a2GwZ. Lens (Inspected k_a2Dhz t_a2DhA a_a2DhB) (Inspected k_a2Dhz t_a2GwZ a_a2DhB) (Set t_a2DhA) (Set t_a2GwZ)
- HsDev.Symbols.Types: scopeQualifier :: forall a_a2Dim. Lens' (Scoped a_a2Dim) (Maybe Text)
+ HsDev.Symbols.Types: scopeQualifier :: forall a_a2DhC. Lens' (Scoped a_a2DhC) (Maybe Text)
- HsDev.Symbols.Types: scoped :: forall a_a2Dim a_a2Gsz. Lens (Scoped a_a2Dim) (Scoped a_a2Gsz) a_a2Dim a_a2Gsz
+ HsDev.Symbols.Types: scoped :: forall a_a2DhC a_a2GrP. Lens (Scoped a_a2DhC) (Scoped a_a2GrP) a_a2DhC a_a2GrP
- HsDev.Tools.Types: note :: forall a_a20j8 a_a20v2. Lens (Note a_a20j8) (Note a_a20v2) a_a20j8 a_a20v2
+ HsDev.Tools.Types: note :: forall a_a20je a_a20v8. Lens (Note a_a20je) (Note a_a20v8) a_a20je a_a20v8
- HsDev.Tools.Types: noteLevel :: forall a_a20j8. Lens' (Note a_a20j8) (Maybe Severity)
+ HsDev.Tools.Types: noteLevel :: forall a_a20je. Lens' (Note a_a20je) (Maybe Severity)
- HsDev.Tools.Types: noteRegion :: forall a_a20j8. Lens' (Note a_a20j8) Region
+ HsDev.Tools.Types: noteRegion :: forall a_a20je. Lens' (Note a_a20je) Region
- HsDev.Tools.Types: noteSource :: forall a_a20j8. Lens' (Note a_a20j8) ModuleLocation
+ HsDev.Tools.Types: noteSource :: forall a_a20je. Lens' (Note a_a20je) ModuleLocation

Files

hsdev.cabal view
@@ -1,5 +1,5 @@ name:                hsdev
-version:             0.3.3.2
+version:             0.3.3.3
 synopsis:            Haskell development library
 description:
   Haskell development library and tool with support of autocompletion, symbol info, go to declaration, find references, hayoo search etc.
@@ -134,7 +134,7 @@   if impl(ghc >= 8.6) && impl(ghc < 8.7)
     build-depends:
       ghc   == 8.6.*,
-      Cabal == 2.4.*
+      Cabal >= 2.4 && < 3.1
 
   if impl(ghc >= 8.4) && impl(ghc < 8.5)
     build-depends:
@@ -153,7 +153,7 @@ 
   if flag(docs)
     build-depends:
-      hdocs >= 0.5.2,
+      hdocs >= 0.5.3,
       haddock-api >= 2.17.4,
       haddock-library >= 1.4.3 && < 1.8
 
@@ -187,7 +187,7 @@     hformat                           >= 0.1.0.1 && < 0.4,
     hlint                             >= 2.0.11 && < 2.2,
     http-client                    >= 0.5 && < 0.7,
-    lens                              >= 4.14 && < 4.18,
+    lens                              >= 4.14 && < 4.19,
     lifted-base                       >= 0.2.3.10 && < 0.3,
     mmorph                            >= 1.0.9 && < 1.2,
     monad-control                     >= 1.0.1.0 && < 1.1,
@@ -256,6 +256,6 @@     filepath                          >= 1.4.1.0 && < 1.5,
     hformat                           >= 0.1.0.1 && < 0.4,
     hspec                             >= 2.2.4,
-    lens                              >= 4.14 && < 4.18,
+    lens                              >= 4.14 && < 4.19,
     mtl                               >= 2.2.1 && < 2.3,
     text                              >= 1.2.2.2 && < 1.3
src/HsDev/Client/Commands.hs view
@@ -403,19 +403,19 @@ 		"line" .= line,
 		"column" .= column]) rs
 runCommand (Lint fs lints) = toValue $ liftM concat $ forM fs $ \fsrc -> do
-	FileSource f c <- actualFileContents fsrc
+	FileSource f c <- getUpdateFileContents fsrc
 	liftIO $ hsdevLift $ HLint.hlint lints (view path f) c
 runCommand (Check fs ghcs' clear) = toValue $ Log.scope "check" $
 	liftM concat $ mapM (runCheck ghcs' clear) fs
 runCommand (CheckLint fs ghcs' lints clear) = toValue $ do
-	fs' <- mapM actualFileContents fs
+	fs' <- mapM getUpdateFileContents fs
 	checkMsgs <- liftM concat $ mapM (runCheck ghcs' clear) fs'
 	lintMsgs <- liftIO $ hsdevLift $ liftM concat $ mapM (\(FileSource f c) -> HLint.hlint lints (view path f) c) fs'
 	return $ checkMsgs ++ lintMsgs
 runCommand (Types fs ghcs' clear) = toValue $ do
 	liftM concat $ forM fs $ \fsrc@(FileSource file msrc) -> do
 		mcached' <- getCached file msrc
-		FileSource _ msrc' <- actualFileContents fsrc
+		FileSource _ msrc' <- getUpdateFileContents fsrc
 		maybe (updateTypes file msrc') return mcached'
 	where
 		getCached :: ServerMonadBase m => Path -> Maybe Text -> ClientM m (Maybe [Tools.Note Types.TypedExpr])
@@ -501,7 +501,7 @@ 				fmap snd mloc)
 			return $ map (makeNote (m ^. moduleId . moduleLocation)) localRegions]
 runCommand (GhcEval exprs mfile) = toValue $ do
-	mfile' <- traverse actualFileContents mfile
+	mfile' <- traverse getUpdateFileContents mfile
 	case mfile' of
 		Nothing -> inSessionGhc ghciSession
 		Just (FileSource f mcts) -> do
@@ -509,7 +509,7 @@ 			inSessionGhc $ interpretModule m mcts
 	inSessionGhc $ mapM (tryRepl . evaluate) exprs
 runCommand (GhcType exprs mfile) = toValue $ do
-	mfile' <- traverse actualFileContents mfile
+	mfile' <- traverse getUpdateFileContents mfile
 	case mfile' of
 		Nothing -> inSessionGhc ghciSession
 		Just (FileSource f mcts) -> do
@@ -586,7 +586,7 @@ 
 -- | Run check
 runCheck :: CommandMonad m => [String] -> Bool -> FileSource -> m [Tools.Note Tools.OutputMessage]
-runCheck ghcs' clear = actualFileContents >=> check' where
+runCheck ghcs' clear = getUpdateFileContents >=> check' where
 	check' (FileSource file mcts) = Log.scope "run-check" $ do
 		Log.sendLog Log.Trace $ "setting file source session for {}" ~~ file
 		sess <- getSession
@@ -598,6 +598,7 @@ 				Check.check m mcts
 		if null ns
 			then do
+				inSessionUpdater $ return () -- wait until cache updated
 				ns' <- Update.cachedWarnings [m ^. moduleId . moduleLocation]
 				unless (null ns') $
 					Log.sendLog Log.Trace $ "returning {} cached warnings for {}" ~~ length ns' ~~ file
@@ -670,10 +671,12 @@ 					proj' <- SQLite.loadProject cabal'
 					return $ set (moduleId . moduleLocation . moduleProject) (Just proj') m
 
--- | Get file contents
-actualFileContents :: CommandMonad m => FileSource -> m FileSource
-actualFileContents (FileSource fpath Nothing) = fmap (FileSource fpath . fmap snd) (getFileContents fpath)
-actualFileContents fcts = return fcts
+-- | Get update file contents
+getUpdateFileContents :: CommandMonad m => FileSource -> m FileSource
+getUpdateFileContents (FileSource fpath Nothing) = fmap (FileSource fpath . fmap snd) (getFileContents fpath)
+getUpdateFileContents fcts@(FileSource fpath mcts) = do
+	serverSetFileContents fpath mcts
+	return fcts
 
 -- | Set session by source
 setFileSourceSession :: CommandMonad m => [String] -> Path -> m Module
src/HsDev/Database/Update.hs view
@@ -637,20 +637,26 @@ 			where
 				initTemp :: SessionMonad m => m ()
 				initTemp = do
-					SQLite.execute_ "create temporary table updating_ids (id integer not null unique);"
+					SQLite.execute_ "create temporary table updating_files (file text not null, mtime real not null);"
+					SQLite.execute_ "create index updating_files_index on updating_files (file);"
+					SQLite.execute_ "create temporary table updating_ids (id integer not null unique, mtime real);"
 					SQLite.execute_ "create temporary table updating_messages as select * from messages where 0;"
 					SQLite.execute_ "create index update_messages_module_id_index on updating_messages (module_id);"
 
 				dropTemp :: SessionMonad m => m ()
 				dropTemp = do
+					SQLite.execute_ "drop table if exists updating_files;"
 					SQLite.execute_ "drop table if exists updating_ids;"
 					SQLite.execute_ "drop table if exists updating_messages;"
 
 				fillTemp :: SessionMonad m => m ()
 				fillTemp = do
-					SQLite.executeMany "insert into updating_ids select distinct m.id from modules as m where (m.file = ?);" $ (map SQLite.Only $ mlocs' ^.. each . moduleFile)
+					mtimes <- forM (mlocs' ^.. each . moduleFile) $ \file' -> (,) <$> pure file' <*> liftIO (fileMTime file')
+					SQLite.executeMany "insert into updating_files values (?, ?);" mtimes
+					SQLite.execute_ "update updating_files set mtime = coalesce(max(mtime, (select c.mtime from file_contents as c where c.file == updating_files.file)), mtime);"
+					SQLite.execute_ "insert into updating_ids select distinct m.id, coalesce(max(u.mtime, m.inspection_time), u.mtime) from modules as m, updating_files as u where m.file = u.file;"
 					SQLite.executeMany "insert into updating_messages select (select m.id from modules as m where (m.file = ?)), ?, ?, ?, ?, ?, ?, ?;" msgs'
-					SQLite.execute_ "insert into updating_ids select distinct umsgs.module_id from updating_messages as umsgs where umsgs.module_id not in (select id from updating_ids);"
+					SQLite.execute_ "insert into updating_ids select distinct umsgs.module_id, m.inspection_time from updating_messages as umsgs, modules as m where umsgs.module_id = m.id and umsgs.module_id not in (select id from updating_ids);"
 
 				removeOutdated :: SessionMonad m => m ()
 				removeOutdated = SQLite.execute_ $ fromString $ unlines [
@@ -658,18 +664,13 @@ 					"where",
 					" module_id in (",
 					"  select um.id",
-					"  from",
-					"   updating_ids as um, modules as m",
-					"  left outer join",
-					"   load_times as lt",
-					"  on",
-					"   lt.module_id = um.id",
+					"  from updating_ids as um",
+					"  left outer join load_times as lt",
+					"  on lt.module_id = um.id",
 					"  where",
-					"   um.id = m.id and (",
-					"    lt.load_time is null or",
-					"    lt.load_time <= m.inspection_time or",
-					"    um.id in (select distinct umsgs.module_id from updating_messages as umsgs)",
-					"   )",
+					"   lt.load_time is null or",
+					"   lt.load_time <= um.mtime or",
+					"   um.id in (select distinct umsgs.module_id from updating_messages as umsgs)",
 					" );"]
 
 				insertMessages :: SessionMonad m => m ()
src/HsDev/Inspect.hs view
@@ -6,7 +6,7 @@ 	analyzeResolve, analyzePreloaded,
 	inspectDocs, inspectDocsGhc,
 	inspectContents, contentsInspection,
-	inspectFile, sourceInspection, fileInspection, fileContentsInspection, fileContentsInspection_, installedInspection, moduleInspection,
+	inspectFile, sourceInspection, fileMTime, fileInspection, fileContentsInspection, fileContentsInspection_, installedInspection, moduleInspection,
 	projectDirs, projectSources,
 	getDefines,
 	preprocess, preprocess_,
@@ -238,11 +238,17 @@ sourceInspection f Nothing = fileInspection f
 sourceInspection _ (Just _) = fileContentsInspection
 
+-- | File modification time as posix time
+fileMTime :: Path -> IO POSIXTime
+fileMTime f = do
+	tm <- Dir.getModificationTime (view path f)
+	return $ utcTimeToPOSIXSeconds tm
+
 -- | File inspection data
 fileInspection :: Path -> [String] -> IO Inspection
 fileInspection f opts = do
-	tm <- Dir.getModificationTime (view path f)
-	return $ InspectionAt (utcTimeToPOSIXSeconds tm) $ map fromString $ sort $ ordNub opts
+	mtime <- fileMTime f
+	return $ InspectionAt mtime $ map fromString $ sort $ ordNub opts
 
 -- | File contents inspection data
 fileContentsInspection :: [String] -> IO Inspection
src/HsDev/PackageDb.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, CPP #-}
 
 module HsDev.PackageDb (
 		module HsDev.PackageDb.Types,
@@ -14,7 +14,7 @@ import Data.Traversable
 import Distribution.InstalledPackageInfo
 import Distribution.Package
-import Distribution.Text (disp)
+import Distribution.Text (display)
 import System.FilePath
 
 import GHC.Paths
@@ -52,18 +52,25 @@ 		confs <- fmap (filter isConf) $ directoryContents (p ^. path)
 		fmap M.unions $ forM confs $ \conf -> do
 				cts <- readFileUtf8 conf
-				case parseInstalledPackageInfo (unpack cts) of
-						ParseFailed _ -> return M.empty  -- FIXME: Should log as warning
-						ParseOk _ res -> mapM (mapM canonicalize) $
+				case parseResult (parseInstalledPackageInfo (unpack cts)) of
+						Left _ -> return M.empty  -- FIXME: Should log as warning
+						Right (_, res) -> mapM (mapM canonicalize) $
 							over (each . each . moduleInstallDirs . each) (subst mlibdir) $ listMods res
 		where
+#if MIN_VERSION_Cabal(3,0,0)
+				parseResult = id
+#else
+				parseResult (ParseFailed e) = Left [show e]
+				parseResult (ParseOk ws res) = Right (map show ws, res)
+#endif
+
 				isConf f = takeExtension f == ".conf"
 				listMods pinfo = M.singleton pname pmods where
 						pname = ModulePackage
-								(pack . show . disp . pkgName $ sourcePackageId pinfo)
-								(pack . show . disp . pkgVersion $ sourcePackageId pinfo)
+								(pack . display . pkgName $ sourcePackageId pinfo)
+								(pack . display . pkgVersion $ sourcePackageId pinfo)
 						pmods = [InstalledModule (map fromFilePath $ libraryDirs pinfo) pname nm exposed' | (nm, exposed') <- names]
-						names = zip (map (pack . show . disp) (exposedModules pinfo)) (repeat True) ++ zip (map (pack . show . disp) (hiddenModules pinfo)) (repeat False)
+						names = zip (map (pack . display) (exposedModules pinfo)) (repeat True) ++ zip (map (pack . display) (hiddenModules pinfo)) (repeat False)
 				subst Nothing f = f
 				subst (Just libdir') f = case splitPaths f of
 						("$topdir":rest) -> joinPaths (fromFilePath libdir' : rest)
src/HsDev/Project.hs view
@@ -25,6 +25,9 @@ import qualified Data.Text as T (intercalate)
 import Data.Text.Lens (unpacked)
 import Distribution.Compiler (CompilerFlavor(GHC))
+#if MIN_VERSION_Cabal(3,0,0)
+import Distribution.Compiler (perCompilerFlavorToList)
+#endif
 import qualified Distribution.Package as P
 import qualified Distribution.PackageDescription as PD
 import qualified Distribution.ModuleName as PD (toFilePath)
@@ -95,12 +98,18 @@ 			_infoDepends = map pkgName (PD.targetBuildDepends info),
 			_infoLanguage = PD.defaultLanguage info,
 			_infoExtensions = PD.defaultExtensions info ++ PD.otherExtensions info ++ PD.oldExtensions info,
-			_infoGHCOptions = maybe [] (map pack) $ lookup GHC (PD.options info),
+			_infoGHCOptions = maybe [] (map pack) $ lookup GHC (pkgOptions info),
 			_infoSourceDirs = map pack $ PD.hsSourceDirs info,
 			_infoOtherModules = map (map pack . components) (PD.otherModules info) }
 
+#if MIN_VERSION_Cabal(3,0,0)
+		pkgOptions = perCompilerFlavorToList . PD.options
+#else
+		pkgOptions = PD.options
+#endif
+
 		pkgName :: P.Dependency -> Text
-		pkgName (P.Dependency dep _) = pack $ P.unPackageName dep
+		pkgName = pack . P.unPackageName . P.depPkgName
 
 		flattenDescr :: PD.GenericPackageDescription -> PD.PackageDescription
 		flattenDescr gpkg = pkg {
src/HsDev/Project/Compat.hs view
@@ -14,8 +14,13 @@ 
 #if MIN_VERSION_Cabal(2,2,0)
 import Distribution.PackageDescription.Parsec
-import Distribution.Parsec.Common (showPError)
 import qualified Data.ByteString.Char8 as C8 (pack)
+#endif
+
+#if MIN_VERSION_Cabal(3,0,0)
+import Distribution.Parsec (showPError)
+#elif MIN_VERSION_Cabal(2,2,0)
+import Distribution.Parsec.Common (showPError)
 #else
 import Distribution.PackageDescription.Parse
 #endif
src/HsDev/Stack.hs view
@@ -21,6 +21,7 @@ import Data.Char
 import Data.Maybe
 import Data.Map.Strict (Map)
+import Data.Version (showVersion)
 import qualified Data.Map.Strict as M
 import Distribution.Compiler
 import Distribution.System
@@ -54,7 +55,7 @@ 			Compat.pkgDatabase $ df
 		compiler = T.display buildCompilerFlavor
 		CompilerId _ version' = buildCompilerId
-		ver = maybe (T.display version') T.display $ lookup compiler res
+		ver = maybe (T.display version') showVersion $ lookup compiler res
 	return $ compiler ++ "-" ++ ver
 
 -- | Get arch for stack
src/HsDev/Tools/Ghc/Base.hs view
@@ -149,7 +149,7 @@ withCurrentDirectory dir act = gbracket (liftIO getCurrentDirectory) (liftIO . setCurrentDirectory) $
 	const (liftIO (setCurrentDirectory dir) >> act)
 
--- | Log  ghc warnings and errors as to chan
+-- | Log ghc warnings and errors as to chan
 -- You may have to apply recalcTabs on result notes
 logToChan :: Chan (Note OutputMessage) -> LogAction
 logToChan ch fs sev src msg
src/HsDev/Tools/Ghc/System.hs view
@@ -10,8 +10,9 @@ import Control.Arrow
 import qualified Data.Map as M
 import Data.Maybe
-import Distribution.Text (display)
+import Data.Version (showVersion)
 import Distribution.System (buildOS)
+import Distribution.Text (display)
 import qualified System.Info as Sys
 import Text.Format
 
@@ -34,7 +35,7 @@ 
 examineCompilerVersion :: DynFlags -> String
 examineCompilerVersion =
-	display .
+	showVersion .
 	fromMaybe Sys.compilerVersion .
 	M.lookup Sys.compilerName .
 	M.fromList .
src/HsDev/Util.hs view
@@ -62,7 +62,11 @@ import qualified Data.Text.Lazy.Encoding as T
 import Data.Time.Clock.POSIX
 import Distribution.Text (simpleParse)
-import qualified Distribution.Text (Text)
+#if MIN_VERSION_Cabal(3,0,0)
+import qualified Distribution.Parsec as DT
+#else
+import qualified Distribution.Text as DT
+#endif
 import Options.Applicative
 import qualified System.Directory as Dir
 import System.FilePath
@@ -303,7 +307,11 @@ version = mapM readMaybe $ split (== '.') $cabalVersion
 
 -- | Parse Distribution.Text
-parseDT :: (Monad m, Distribution.Text.Text a) => String -> String -> m a
+#if MIN_VERSION_Cabal(3,0,0)
+parseDT :: (Monad m, DT.Parsec a) => String -> String -> m a
+#else
+parseDT :: (Monad m, DT.Text a) => String -> String -> m a
+#endif
 parseDT typeName v = maybe err return (simpleParse v) where
 	err = fail $ "Can't parse {}: {}" ~~ typeName ~~ v