packages feed

ghc-tags 1.0 → 1.1

raw patch · 6 files changed

+302/−62 lines, 6 filesdep ~base

Dependency ranges changed: base

Files

CHANGELOG.md view
@@ -1,2 +1,8 @@+# ghc-tags-1.1 (2021-05-18)+* Fix compatibility with GHC 8.10.+* Drop support for GHC 8.8.+* Make output flag `ctags` compatible.+* Increase allocation area to 4MB for better performance.+ # ghc-tags-1.0 (2021-05-17) * Initial release.
README.md view
@@ -1,6 +1,7 @@ # ghc-tags  [![Build Status](https://github.com/arybczak/ghc-tags/workflows/Haskell-CI/badge.svg?branch=master)](https://github.com/arybczak/ghc-tags/actions?query=branch%3Amaster)+[![Hackage](https://img.shields.io/hackage/v/ghc-tags.svg)](https://hackage.haskell.org/package/ghc-tags)  A command line tool that generates etags (Emacs) and ctags (Vim and other editors) for efficient code navigation (jump to definition).
ghc-tags.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.4 name:                ghc-tags-version:             1.0+version:             1.1 synopsis:            Utility for generating ctags and etags with GHC API. description:         Utility for generating etags (Emacs) and ctags (Vim and other                      editors) with GHC API for efficient project navigation.@@ -14,7 +14,7 @@                      README.md homepage:            https://github.com/arybczak/ghc-tags bug-reports:         https://github.com/arybczak/ghc-tags/issues-tested-with:         GHC ==8.8.4 || ==8.10.4 || ==9.0.1+tested-with:         GHC ==8.10.4 || ==9.0.1  source-repository head   type:     git@@ -26,14 +26,14 @@   description: Use ghc-lib even when compiling with compatible GHC version.  executable ghc-tags-  ghc-options:         -Wall -threaded -rtsopts+  ghc-options:         -Wall -threaded -rtsopts -with-rtsopts=-A4m    if !flag(ghc-lib) && impl(ghc == 9.0.*)      build-depends:    ghc, ghc-boot   else      build-depends:    ghc-lib == 9.0.* -  build-depends:       base >=4.13 && <5+  build-depends:       base >=4.14 && <5                      , aeson                      , async                      , attoparsec@@ -61,6 +61,7 @@                        GhcTags.Config.Args                        GhcTags.Config.Project                        GhcTags.Ghc+                       GhcTags.GhcCompat                        GhcTags.Tag                        GhcTags.CTag                        GhcTags.CTag.Header
src/GhcTags/Config/Args.hs view
@@ -51,7 +51,7 @@                        <> help "Generate etags"      tagFile :: Parser FilePath-    tagFile = strOption $ long "output"+    tagFile = strOption $ short 'f'                        <> short 'o'                        <> metavar "FILE"                        <> help "Output file"
+ src/GhcTags/GhcCompat.hs view
@@ -0,0 +1,288 @@+{-# OPTIONS_GHC -Wno-missing-fields #-}+module GhcTags.GhcCompat+  ( runGhc+  , parseModule+  ) where++import Data.IORef+import GHC.Data.FastString+import GHC.Data.StringBuffer+import GHC.Driver.Main+import GHC.Driver.Monad+import GHC.Driver.Session+import GHC.Hs+import GHC.Parser.Lexer+import GHC.Paths+import GHC.Platform+import GHC.Settings+import GHC.Settings.Config+import GHC.Settings.Platform+import GHC.Settings.Utils+import GHC.SysTools+import GHC.SysTools.BaseDir+import GHC.Types.SrcLoc+import GHC.Unit.Module.Env+import GHC.Utils.Fingerprint+import System.Directory+import System.FilePath+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import qualified GHC+import qualified GHC.Parser as Parser++parseModule+  :: FilePath+  -> DynFlags+  -> StringBuffer+  -> ParseResult (Located HsModule)+parseModule filename flags buffer = unP Parser.parseModule parseState+  where+    location = mkRealSrcLoc (mkFastString filename) 1 1+    parseState = mkPState flags buffer location++runGhc :: Ghc a -> IO a+runGhc m = do+  env <- liftIO $ do+    mySettings <- compatInitSettings libdir+    myLlvmConfig <- lazyInitLlvmConfig libdir+    dflags <- threadSafeInitDynFlags (defaultDynFlags mySettings myLlvmConfig)+    newHscEnv dflags+  ref <- newIORef env+  unGhc (GHC.withCleanupSession m) (Session ref)++----------------------------------------+-- Internal++-- | Adjusted version of 'GHC.Driver.Session.initDynFlags' that doesn't check+-- for colors as it's not thread safe.+threadSafeInitDynFlags :: DynFlags -> IO DynFlags+threadSafeInitDynFlags dflags = do+  let -- We can't build with dynamic-too on Windows, as labels before the+      -- fork point are different depending on whether we are building+      -- dynamically or not.+      platformCanGenerateDynamicToo+          = platformOS (targetPlatform dflags) /= OSMinGW32+  refCanGenerateDynamicToo <- newIORef platformCanGenerateDynamicToo+  refNextTempSuffix <- newIORef 0+  refFilesToClean <- newIORef emptyFilesToClean+  refDirsToClean <- newIORef Map.empty+  refGeneratedDumps <- newIORef Set.empty+  refRtldInfo <- newIORef Nothing+  refRtccInfo <- newIORef Nothing+  wrapperNum <- newIORef emptyModuleEnv+  pure dflags+    { canGenerateDynamicToo = refCanGenerateDynamicToo+    , nextTempSuffix = refNextTempSuffix+    , filesToClean   = refFilesToClean+    , dirsToClean    = refDirsToClean+    , generatedDumps = refGeneratedDumps+    , nextWrapperNum = wrapperNum+    , rtldInfo       = refRtldInfo+    , rtccInfo       = refRtccInfo+    }++-- | Stripped version of 'GHC.Settings.IO.initSettings' that ignores the+-- @platformConstants@ file as it's irrelevant for parsing.+compatInitSettings :: FilePath -> IO Settings+compatInitSettings top_dir = do+  -- see Note [topdir: How GHC finds its files]+  -- NB: top_dir is assumed to be in standard Unix+  -- format, '/' separated+  mtool_dir <- findToolDir top_dir+        -- see Note [tooldir: How GHC finds mingw on Windows]++  let installed :: FilePath -> FilePath+      installed file = top_dir </> file+      libexec :: FilePath -> FilePath+      libexec file = top_dir </> "bin" </> file+      settingsFile = installed "settings"++      readFileSafe :: FilePath -> IO String+      readFileSafe path = doesFileExist path >>= \case+        True -> readFile path+        False -> error $ "Missing file: " ++ path++  settingsStr <- readFileSafe settingsFile+  settingsList <- case maybeReadFuzzy settingsStr of+    Just s -> pure s+    Nothing -> error $ "Can't parse " ++ show settingsFile+  let mySettings = Map.fromList settingsList+  -- See Note [Settings file] for a little more about this file. We're+  -- just partially applying those functions and throwing 'Left's; they're+  -- written in a very portable style to keep ghc-boot light.+  let getSetting key = either error pure $+        getFilePathSetting0 top_dir settingsFile mySettings key+      getToolSetting :: String -> IO String+      getToolSetting key = expandToolDir mtool_dir <$> getSetting key+      getBooleanSetting :: String -> IO Bool+      getBooleanSetting key = either error pure $+        getBooleanSetting0 settingsFile mySettings key+  myExtraGccViaCFlags <- getSetting "GCC extra via C opts"+  -- On Windows, mingw is distributed with GHC,+  -- so we look in TopDir/../mingw/bin,+  -- as well as TopDir/../../mingw/bin for hadrian.+  -- It would perhaps be nice to be able to override this+  -- with the settings file, but it would be a little fiddly+  -- to make that possible, so for now you can't.+  cc_prog <- getToolSetting "C compiler command"+  cc_args_str <- getSetting "C compiler flags"+  cxx_args_str <- getSetting "C++ compiler flags"+  gccSupportsNoPie <- getBooleanSetting "C compiler supports -no-pie"+  cpp_prog <- getToolSetting "Haskell CPP command"+  cpp_args_str <- getSetting "Haskell CPP flags"++  platform <- either error pure $ compatGetTargetPlatform settingsFile mySettings++  let unreg_cc_args = if platformUnregisterised platform+                      then ["-DNO_REGS", "-DUSE_MINIINTERPRETER"]+                      else []+      cpp_args = map Option (words cpp_args_str)+      cc_args  = words cc_args_str ++ unreg_cc_args+      cxx_args = words cxx_args_str+  ldSupportsCompactUnwind <- getBooleanSetting "ld supports compact unwind"+  ldSupportsBuildId       <- getBooleanSetting "ld supports build-id"+  ldSupportsFilelist      <- getBooleanSetting "ld supports filelist"+  ldIsGnuLd               <- getBooleanSetting "ld is GNU ld"++  let globalpkgdb_path = installed "package.conf.d"+      ghc_usage_msg_path  = installed "ghc-usage.txt"+      ghci_usage_msg_path = installed "ghci-usage.txt"++  -- For all systems, unlit, split, mangle are GHC utilities+  -- architecture-specific stuff is done when building Config.hs+  unlit_path <- getToolSetting "unlit command"++  windres_path <- getToolSetting "windres command"+  libtool_path <- getToolSetting "libtool command"+  ar_path <- getToolSetting "ar command"+  otool_path <- getToolSetting "otool command"+  install_name_tool_path <- getToolSetting "install_name_tool command"+  ranlib_path <- getToolSetting "ranlib command"++  -- TODO this side-effect doesn't belong here. Reading and parsing the settings+  -- should be idempotent and accumulate no resources.+  tmpdir <- liftIO $ getTemporaryDirectory++  touch_path <- getToolSetting "touch command"++  mkdll_prog <- getToolSetting "dllwrap command"+  let mkdll_args = []++  -- cpp is derived from gcc on all platforms+  -- HACK, see setPgmP below. We keep 'words' here to remember to fix+  -- Config.hs one day.+++  -- Other things being equal, as and ld are simply gcc+  cc_link_args_str <- getSetting "C compiler link flags"+  let   as_prog  = cc_prog+        as_args  = map Option cc_args+        ld_prog  = cc_prog+        ld_args  = map Option (cc_args ++ words cc_link_args_str)+  ld_r_prog <- getToolSetting "Merge objects command"+  ld_r_args <- getSetting "Merge objects flags"++  -- We just assume on command line+  lc_prog <- getSetting "LLVM llc command"+  lo_prog <- getSetting "LLVM opt command"+  lcc_prog <- getSetting "LLVM clang command"++  let iserv_prog = libexec "ghc-iserv"++  return $ Settings+    { sGhcNameVersion = GhcNameVersion+      { ghcNameVersion_programName = "ghc"+      , ghcNameVersion_projectVersion = cProjectVersion+      }++    , sFileSettings = FileSettings+      { fileSettings_tmpDir         = normalise tmpdir+      , fileSettings_ghcUsagePath   = ghc_usage_msg_path+      , fileSettings_ghciUsagePath  = ghci_usage_msg_path+      , fileSettings_toolDir        = mtool_dir+      , fileSettings_topDir         = top_dir+      , fileSettings_globalPackageDatabase = globalpkgdb_path+      }++    , sToolSettings = ToolSettings+      { toolSettings_ldSupportsCompactUnwind = ldSupportsCompactUnwind+      , toolSettings_ldSupportsBuildId       = ldSupportsBuildId+      , toolSettings_ldSupportsFilelist      = ldSupportsFilelist+      , toolSettings_ldIsGnuLd               = ldIsGnuLd+      , toolSettings_ccSupportsNoPie         = gccSupportsNoPie++      , toolSettings_pgm_L   = unlit_path+      , toolSettings_pgm_P   = (cpp_prog, cpp_args)+      , toolSettings_pgm_F   = ""+      , toolSettings_pgm_c   = cc_prog+      , toolSettings_pgm_a   = (as_prog, as_args)+      , toolSettings_pgm_l   = (ld_prog, ld_args)+      , toolSettings_pgm_lm  = (ld_r_prog, map Option $ words ld_r_args)+      , toolSettings_pgm_dll = (mkdll_prog,mkdll_args)+      , toolSettings_pgm_T   = touch_path+      , toolSettings_pgm_windres = windres_path+      , toolSettings_pgm_libtool = libtool_path+      , toolSettings_pgm_ar = ar_path+      , toolSettings_pgm_otool = otool_path+      , toolSettings_pgm_install_name_tool = install_name_tool_path+      , toolSettings_pgm_ranlib = ranlib_path+      , toolSettings_pgm_lo  = (lo_prog,[])+      , toolSettings_pgm_lc  = (lc_prog,[])+      , toolSettings_pgm_lcc = (lcc_prog,[])+      , toolSettings_pgm_i   = iserv_prog+      , toolSettings_opt_L       = []+      , toolSettings_opt_P       = []+      , toolSettings_opt_P_fingerprint = fingerprint0+      , toolSettings_opt_F       = []+      , toolSettings_opt_c       = cc_args+      , toolSettings_opt_cxx     = cxx_args+      , toolSettings_opt_a       = []+      , toolSettings_opt_l       = []+      , toolSettings_opt_lm      = []+      , toolSettings_opt_windres = []+      , toolSettings_opt_lcc     = []+      , toolSettings_opt_lo      = []+      , toolSettings_opt_lc      = []+      , toolSettings_opt_i       = []++      , toolSettings_extraGccViaCFlags = words myExtraGccViaCFlags+      }++    , sTargetPlatform = platform++    -- Lots of uninitialized fields here.+    , sPlatformMisc = PlatformMisc {}+    , sPlatformConstants = PlatformConstants { pc_DYNAMIC_BY_DEFAULT = False }++    , sRawSettings    = settingsList+    }++-- Stripped version of 'GHC.Settings.Platform.getTargetPlatform'. Arch info is+-- needed for CPP defines, the rest is irrelevant.+compatGetTargetPlatform+  :: FilePath -> RawSettings -> Either String Platform+compatGetTargetPlatform settingsFile mySettings = do+  let+    readSetting :: (Show a, Read a) => String -> Either String a+    readSetting = readSetting0 settingsFile mySettings++  targetArch <- readSetting "target arch"+  targetOS <- readSetting "target os"+  targetWordSize <- readSetting "target word size"++  pure $ Platform+    { platformMini = PlatformMini+      { platformMini_arch = targetArch+      , platformMini_os = targetOS+      }+    , platformWordSize = targetWordSize+    -- below is irrelevant+    , platformByteOrder = LittleEndian+    , platformUnregisterised = True+    , platformHasGnuNonexecStack = False+    , platformHasIdentDirective = False+    , platformHasSubsectionsViaSymbols = False+    , platformIsCrossCompiling = False+    , platformLeadingUnderscore = False+    , platformTablesNextToCode  = False+    }
src/Main.hs view
@@ -9,26 +9,19 @@ import Data.Bifunctor import Data.Char import Data.Function-import Data.IORef import Data.List import Data.Maybe (mapMaybe) import Data.Time import Data.Time.Format.ISO8601 import GHC.Conc (getNumProcessors) import GHC.Data.Bag-import GHC.Data.FastString import GHC.Data.StringBuffer-import GHC.Driver.Main import GHC.Driver.Monad import GHC.Driver.Session import GHC.Driver.Types (HscEnv(..)) import GHC.Hs import GHC.Parser.Lexer-import GHC.Paths-import GHC.Platform-import GHC.SysTools import GHC.Types.SrcLoc-import GHC.Unit.Module.Env import GHC.Utils.Error import System.Directory import System.Environment@@ -42,20 +35,19 @@ import qualified Data.ByteString.Char8 as BS import qualified Data.Foldable as F import qualified Data.Map.Strict as Map-import qualified Data.Set as Set import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.IO as T import qualified Data.Vector as V import qualified GHC import qualified GHC.Driver.Pipeline as DP-import qualified GHC.Parser as Parser import qualified GHC.Utils.Outputable as Out  import GhcTags import GhcTags.Config.Args import GhcTags.Config.Project import GhcTags.CTag.Header+import GhcTags.GhcCompat import qualified GhcTags.CTag as CTag import qualified GhcTags.ETag as ETag @@ -392,51 +384,3 @@     headers = if null tHeaders               then defaultHeaders               else tHeaders--------------------------------------------runGhc :: Ghc a -> IO a-runGhc m = do-  env <- liftIO $ do-    mySettings <- initSysTools libdir-    myLlvmConfig <- lazyInitLlvmConfig libdir-    dflags <- threadSafeInitDynFlags (defaultDynFlags mySettings myLlvmConfig)-    newHscEnv dflags-  ref <- newIORef env-  unGhc (GHC.withCleanupSession m) (Session ref)-  where-    threadSafeInitDynFlags dflags = do-      let -- We can't build with dynamic-too on Windows, as labels before the-          -- fork point are different depending on whether we are building-          -- dynamically or not.-          platformCanGenerateDynamicToo-              = platformOS (targetPlatform dflags) /= OSMinGW32-      refCanGenerateDynamicToo <- newIORef platformCanGenerateDynamicToo-      refNextTempSuffix <- newIORef 0-      refFilesToClean <- newIORef emptyFilesToClean-      refDirsToClean <- newIORef Map.empty-      refGeneratedDumps <- newIORef Set.empty-      refRtldInfo <- newIORef Nothing-      refRtccInfo <- newIORef Nothing-      wrapperNum <- newIORef emptyModuleEnv-      pure dflags-        { canGenerateDynamicToo = refCanGenerateDynamicToo-        , nextTempSuffix = refNextTempSuffix-        , filesToClean   = refFilesToClean-        , dirsToClean    = refDirsToClean-        , generatedDumps = refGeneratedDumps-        , nextWrapperNum = wrapperNum-        , rtldInfo       = refRtldInfo-        , rtccInfo       = refRtccInfo-        }--parseModule-  :: FilePath-  -> DynFlags-  -> StringBuffer-  -> ParseResult (Located HsModule)-parseModule filename flags buffer =-  unP Parser.parseModule parseState-  where-    location = mkRealSrcLoc (mkFastString filename) 1 1-    parseState = mkPState flags buffer location