ghc-tags-plugin 0.1.0.1 → 0.1.0.2
raw patch · 3 files changed
+99/−23 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +69/−17
- ghc-tags-plugin.cabal +1/−1
- lib/Plugin/GhcTags/Generate.hs +29/−5
README.md view
@@ -1,31 +1,83 @@ # Ghc Tags Compiler Plugin A [Ghc Compiler Plugin](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/extending_ghc.html#compiler-plugins)-which generates tags for each compiled module or component. The source tree is-[left unmodified](https://github.com/coot/ghc-tags-plugin/blob/master/lib/Plugin/GhcTags.hs#L79).+which generates tags for each compiled module or component. -# Usage+# vim configuration++Each generated tags file is put next to the corresponding `*.cabal` file. If+you just have a repo with a cabal file in the main directory `vim` default+`tags` setting will work, if you have some modules in subdirectories you will+need to set: ```+:set tags+=*/tags+```++# Plugin usage++Configuration of this plugin requires some familiarity with `ghc` packages.+Check out+[documentation](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/packages.html#packages)+how to use `-plugin-package` or `-plugin-package-id`. In the examples below we+us `-plugin-package=ghc-tags-plugin` but specifying version+`-package=ghc-tags-plugin-0.0.0.0` (where `0.0.0.0` is the version you+installed), might work better. You can use `ghc-pkg latest` (likely with+appropriate `--package-db` flag) to check which version is available.++## ghc++``` ghc -plugin-package=ghc-tags-plugin -fplugin=Plugin.GhcTags ``` -If you're using `cabal`, at this point you will need to add `ghctags` to every-'build-depends' in every `*.cabal` file. That's unfortunate state of the-eco-system right now. You can add `ghc-options` to your `cabal.project.local`-file for each cabal project, e.g. (note that you'll need to update the-`CURRENT_GIT_TAG` below)+## cabal +Install the `ghc-tags-plugin` to cabal store with: ```-project someproject- ghc-options: -fplugin=Plugin.GhcTags+cabal install ghc-tags-plugin+``` +In `cabal.project.local` file add `package` stanza for every local package :+```+project some-project+ ghc-options: -package-db=PACKAGE_DB -plugin-package=ghc-tags-plugin -fplugin=Plugin.GhcTags+``` -source-repository-package- type: git- location: /home/coot/repos/haskell/ghc-tags-plugin- tag: CURRENT_GIT_TAG- subdir: .+`PACKAGE_DB` is likely something to be something like (for `ghc-8.6.5`)+'${HOME}/.cabal/store/ghc-8.6.5/package.db' (all environment variables must be+expanded). +## stack++Install `ghc-tags-plugin` + ```+stack install ghc-tags-plugin+``` -A `tags` file will be created (or destructively updated) in each project-directory (the same as its `cabal` file).+In `stack.yaml` file add:+```+ghc-options:+ some-project: -package-db=PACKAGE_DB -plugin-package=ghc-tags-plugin -fplugin=Plugin.GhcTags+```++where `PACKAGE_DB` is the package db where `ghc-tags-plugin` was installed by+`stack`.++## modifying `cabal` files++You can always add `ghc-tags-plugin` as a build dependency in a cabal file (for+each component). You can hide it behind a flag and then use `cabal` or `stack`+to enable it (or `cabal.project.local` or `stack.yaml` files for that purpose).++# Security implications of compiler plugins++Such plugins can:++* run arbitrary `IO`;+* modify abstract syntax tree in some way; a malicious plugin could change+ some security parameter in your code exposing a security hole.++This plugin only reads & writes to `tags` file (and updates a shared mutable+state) as of `IO`, and does not+[modify/](https://github.com/coot/ghc-tags-plugin/blob/master/lib/Plugin/GhcTags.hs#L79)+the syntax tree.
ghc-tags-plugin.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: ghc-tags-plugin-version: 0.1.0.1+version: 0.1.0.2 synopsis: A compiler plugin which generates tags file from GHC syntax tree. description: A compiler source plugin which takes parsed Haskell syntax tree and saves
lib/Plugin/GhcTags/Generate.hs view
@@ -27,17 +27,23 @@ , FamilyDecl (..) , ForeignDecl (..) , LHsDecl+ , HsConDeclDetails , HsDecl (..) , HsDataDefn (..) , InstDecl (..) , TyClDecl (..) , TyFamInstDecl (..) )-import HsSyn ( GhcPs+import HsSyn ( FieldOcc (..)+ , GhcPs , HsModule (..)+ , LFieldOcc )-import HsTypes ( HsImplicitBndrs (..)+import HsTypes ( ConDeclField (..)+ , HsConDetails (..)+ , HsImplicitBndrs (..) , HsType (..)+ , LConDeclField , LHsType ) import SrcLoc ( GenLocated (..)@@ -125,7 +131,8 @@ DataDecl { tcdLName, tcdDataDefn } -> case tcdDataDefn of HsDataDefn { dd_cons } ->- mkGhcTag tcdLName : ((mkConsTags . unLoc) `concatMap` dd_cons) ++ tags+ mkGhcTag tcdLName : ((mkConsTags . unLoc) `concatMap` dd_cons)+ ++ tags XHsDataDefn {} -> tags@@ -212,9 +219,26 @@ -- tags of all constructors of a type mkConsTags :: ConDecl GhcPs -> GhcTags- mkConsTags ConDeclGADT { con_names } = mkGhcTag `map` con_names- mkConsTags ConDeclH98 { con_name } = [mkGhcTag con_name]+ mkConsTags ConDeclGADT { con_names, con_args } =+ mkGhcTag `map` con_names+ ++ mkHsConDeclDetails con_args+ mkConsTags ConDeclH98 { con_name, con_args } =+ mkGhcTag con_name+ : mkHsConDeclDetails con_args mkConsTags XConDecl {} = []++ mkHsConDeclDetails :: HsConDeclDetails GhcPs -> GhcTags+ mkHsConDeclDetails (RecCon (L _ fields)) = foldl' f [] fields+ where+ f :: GhcTags -> LConDeclField GhcPs -> GhcTags+ f ts (L _ ConDeclField { cd_fld_names }) = foldl' g ts cd_fld_names+ f ts _ = ts++ g :: GhcTags -> LFieldOcc GhcPs -> GhcTags+ g ts (L _ FieldOcc { rdrNameFieldOcc }) = mkGhcTag rdrNameFieldOcc : ts+ g ts _ = ts++ mkHsConDeclDetails _ = [] mkHsBindLRTags :: HsBindLR GhcPs GhcPs -> GhcTags mkHsBindLRTags hsBind =