The haskell-names package

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain]

Warnings:

For a high-level overview of this package, see http://documentup.com/haskell-suite/haskell-names


[Skip to ReadMe]

Properties

Versions0.1, 0.1.1, 0.1.2, 0.2, 0.2.1, 0.3, 0.3.1, 0.3.2, 0.3.2.1, 0.3.2.2, 0.3.2.3, 0.3.2.4, 0.3.2.5, 0.3.2.6, 0.3.2.7, 0.3.2.8, 0.3.3, 0.3.3.1, 0.3.3.2, 0.4, 0.4.1, 0.5.0, 0.5.1, 0.5.2, 0.5.3, 0.6.0, 0.6.0, 0.7.0, 0.8.0, 0.9.0
Change logCHANGELOG.md
Dependenciesaeson (>=0.8.0.2 && <0.11), base (==4.*), bytestring (>=0.10.4.0 && <0.11), containers (>=0.2 && <0.6), data-lens-light (>=0.1.2.1 && <0.2), filepath (>=1.1 && <1.5), haskell-src-exts (==1.17.*), mtl (>=2.2.1 && <2.3), transformers (>=0.4.2.0 && <0.5), traverse-with-class (>=0.2.0.3 && <0.3), uniplate (>=1.5.1 && <1.7) [details]
LicenseBSD3
AuthorPhilipp Schuster, Roman Cheplyaka, Lennart Augustsson
MaintainerPhilipp Schuster
CategoryLanguage
Home pagehttp://documentup.com/haskell-suite/haskell-names
Source repositoryhead: git clone git://github.com/haskell-suite/haskell-names.git
UploadedThu Dec 17 15:26:26 UTC 2015 by PhilippSchuster

Modules

[Index]

Downloads

Maintainers' corner

For package maintainers and hackage trustees


Readme for haskell-names-0.6.0

[back to package description]

haskell-names Build Status

haskell-names does name and module resolution for haskell-src-exts AST.

Namely, it can do the following:

Installation

If you're building a development version, then you might also need to install a development version of haskell-src-exts.

Environments

An environment is a map from module name to list of entities the module exports. Entities are for example types, class, functions etc. We store these lists in a JSON format. For example, here are a couple of entries from Prelude.names:

[
  {
    "name": "map",
    "entity": "value",
    "module": "GHC.Base"
  },
  {
    "name": "IO",
    "entity": "newtype",
    "module": "GHC.Types"
  },
  ...
]

As you see, each entity is annotated with the module where it was originally defined. Additionally, class methods, field selectors, and data constructors are annotated with the class or type they belong to.

haskell-names provides functions readSymbols and writeSymbols to read and write interface files.

Name resolution

The annotate function annotates the given module with scoping information.

Its essence is described in the article Open your name resolution.

Example

Let's say you have a module and you want to find out whether it uses Prelude.head.

module Main where

import Language.Haskell.Exts.Annotated (
  fromParseResult, parseModuleWithMode, defaultParseMode,
  parseFilename, prettyPrint, srcInfoSpan)
import Language.Haskell.Exts (
  Name(Ident), ModuleName(ModuleName))
import Language.Haskell.Names (
  loadBase, annotate, symbolName,
  Scoped(Scoped), NameInfo(GlobalSymbol))

import qualified Data.Map as Map (
  lookup)

import Data.Maybe (
  fromMaybe, listToMaybe)
import Data.List (
  nub)
import qualified Data.Foldable as Foldable (
  toList)
import Control.Monad (
  forM_, guard)

main :: IO ()
main = do

  -- read the program's source from stdin
  source <- getContents

  -- parse the program (using haskell-src-exts)
  let ast = fromParseResult (
        parseModuleWithMode defaultParseMode {parseFilename="stdin"} source)

  -- get base environment
  baseEnvironment <- loadBase

  -- get symbols defined in prelude
  let preludeSymbols = fromMaybe (error "Prelude not found") (
        Map.lookup (ModuleName "Prelude") baseEnvironment)

  -- find a Prelude symbol with name 'head' using the List monad
  let headSymbol = fromMaybe (error "Prelude.head not found") (
        listToMaybe (do
          preludeSymbol <- preludeSymbols
          guard (symbolName preludeSymbol == Ident "head")
          return preludeSymbol))

  -- annotate the AST
  let annotatedAST = annotate baseEnvironment ast

  -- get all annotations
  let annotations = Foldable.toList annotatedAST

  -- filter head Usages in List monad and remove duplicates
  let headUsages = nub (do
        Scoped (GlobalSymbol globalSymbol _) location <- annotations
        guard (globalSymbol == headSymbol)
        return location)

  case headUsages of
    [] ->
      putStrLn "Congratulations! Your code doesn't use Prelude.head"
    _ -> forM_ headUsages (\location ->
      putStrLn ("Prelude.head is used at " ++ (prettyPrint (srcInfoSpan location))))

Example invocation

% ./find-heads 
one = head [1]
^D
Prelude.head is used at stdin: (1:7) - (1:11)

% ./find-heads
import Prelude hiding (head)
import Data.Text

f = head (pack "foo")
^D
Congratulations! Your code doesn't use Prelude.head

API documentation

See haskell-names haddock documentation.

The core module you need is Language.Haskell.Names

Other modules are more experimental, less documented, and you probably don't need them anyway.

Known issues

See the list of all issues.

Maintainers

Philipp Schuster is the primary maintainer.

Adam Bergmark is the backup maintainer. Please get in touch with him if the primary maintainer cannot be reached.