hlint-1.9.38: Source code suggestions

Safe Haskell | None
Language | Haskell2010

Language.Haskell.HLint2

Contents

- Idea data type
- Settings
- Hints
- Scopes
- Haskell-src-exts
- File encodings

Description

WARNING: This module represents the evolving second version of the HLint API. It will be deleted in favour of Language.Haskell.HLint3 in the next major version.

This module provides a way to apply HLint hints. As an example of approximating the `hlint` experience:

    (flags, classify, hint) <- autoSettings
    Right m <- parseModuleEx flags "MyFile.hs" Nothing
    print $ applyHints classify hint [m]

Synopsis

- applyHints :: [Classify] -> Hint -> [(Module SrcSpanInfo, [Comment])] -> [Idea]
- data Idea = Idea {
  - ideaModule :: String
  - ideaDecl :: String
  - ideaSeverity :: Severity
  - ideaHint :: String
  - ideaSpan :: SrcSpan
  - ideaFrom :: String
  - ideaTo :: Maybe String
  - ideaNote :: [Note]
  - ideaRefactoring :: [Refactoring SrcSpan]
  }
- data Severity
  - = Ignore
  - | Suggestion
  - | Warning
  - | Error
- data Note
  - = IncreasesLaziness
  - | DecreasesLaziness
  - | RemovesError String
  - | ValidInstance String String
  - | Note String
- data Classify = Classify {
  - classifySeverity :: Severity
  - classifyHint :: String
  - classifyModule :: String
  - classifyDecl :: String
  }
- getHLintDataDir :: IO FilePath
- autoSettings :: IO (ParseFlags, [Classify], Hint)
- autoSettings' :: FilePath -> IO (ParseFlags, [Classify], Hint)
- findSettings :: FilePath -> FilePath -> Maybe String -> IO ([String], [Module SrcSpanInfo])
- readSettings :: Module SrcSpanInfo -> ([Classify], [HintRule])
- data Hint = Hint {
  - hintModules :: [(Scope, Module SrcSpanInfo)] -> [Idea]
  - hintModule :: Scope -> Module SrcSpanInfo -> [Idea]
  - hintDecl :: Scope -> Module SrcSpanInfo -> Decl SrcSpanInfo -> [Idea]
  - hintComment :: Comment -> [Idea]
  }
- builtinHints :: [(String, Hint)]
- data HintRule = HintRule {
  - hintRuleSeverity :: Severity
  - hintRuleName :: String
  - hintRuleScope :: Scope
  - hintRuleLHS :: Exp SrcSpanInfo
  - hintRuleRHS :: Exp SrcSpanInfo
  - hintRuleSide :: Maybe (Exp SrcSpanInfo)
  - hintRuleNotes :: [Note]
  }
- hintRules :: [HintRule] -> Hint
- data Scope
- scopeCreate :: Module SrcSpanInfo -> Scope
- scopeMatch :: (Scope, QName SrcSpanInfo) -> (Scope, QName SrcSpanInfo) -> Bool
- scopeMove :: (Scope, QName SrcSpanInfo) -> Scope -> QName SrcSpanInfo
- parseModuleEx :: ParseFlags -> FilePath -> Maybe String -> IO (Either ParseError (Module SrcSpanInfo, [Comment]))
- defaultParseFlags :: ParseFlags
- data ParseError = ParseError {
  - parseErrorLocation :: SrcLoc
  - parseErrorMessage :: String
  - parseErrorContents :: String
  }
- data ParseFlags = ParseFlags {
  - encoding :: TextEncoding
  - cppFlags :: CppFlags
  - hseFlags :: ParseMode
  }
- data CppFlags
  - = NoCpp
  - | CppSimple
  - | Cpphs CpphsOptions
- type Encoding = TextEncoding
- defaultEncoding :: Encoding
- readEncoding :: String -> IO Encoding
- useEncoding :: Handle -> Encoding -> IO ()

# Documentation

applyHints :: [Classify] -> Hint -> [(Module SrcSpanInfo, [Comment])] -> [Idea] #

Given a way of classifying results, and a `Hint`, apply to a set of modules generating a list of `Idea`s. The `Idea` values will be ordered within a file.

Given a set of modules, it may be faster pass each to `applyHints` in a singleton list. When given multiple modules at once this function attempts to find hints between modules, which is slower and often pointless (by default HLint passes modules singularly, using `--cross` to pass all modules together).

# Idea data type

data Idea #

An idea suggest by a `Hint`.

Constructors

Idea |
Fields ideaModule :: String The module the idea applies to, may be `""` if the module cannot be determined or is a result of cross-module hints. ideaDecl :: String The declaration the idea applies to, typically the function name, but may be a type name. ideaSeverity :: Severity The severity of the idea, e.g. `Warning`. ideaHint :: String The name of the hint that generated the idea, e.g. `"Use reverse"`. ideaSpan :: SrcSpan The source code the idea relates to. ideaFrom :: String The contents of the source code the idea relates to. ideaTo :: Maybe String The suggested replacement, or `Nothing` for no replacement (e.g. on parse errors). ideaNote :: [Note] Notes about the effect of applying the replacement. ideaRefactoring :: [Refactoring SrcSpan] How to perform this idea

Instances

Eq Idea # |
Methods (==) :: Idea -> Idea -> Bool # (/=) :: Idea -> Idea -> Bool #
Ord Idea # |
Methods compare :: Idea -> Idea -> Ordering # (<) :: Idea -> Idea -> Bool # (<=) :: Idea -> Idea -> Bool # (>) :: Idea -> Idea -> Bool # (>=) :: Idea -> Idea -> Bool # max :: Idea -> Idea -> Idea # min :: Idea -> Idea -> Idea #
Show Idea # |
Methods showsPrec :: Int -> Idea -> ShowS # show :: Idea -> String # showList :: [Idea] -> ShowS #

data Severity #

How severe an issue is.

Constructors

Ignore | The issue has been explicitly ignored and will usually be hidden (pass `--show` on the command line to see ignored ideas).
Suggestion | Suggestions are things that some people may consider improvements, but some may not.
Warning | Warnings are suggestions that are nearly always a good idea to apply.
Error | Available as a setting for the user.

Instances

Bounded Severity # |
Methods minBound :: Severity # maxBound :: Severity #
Enum Severity # |
Methods succ :: Severity -> Severity # pred :: Severity -> Severity # toEnum :: Int -> Severity # fromEnum :: Severity -> Int # enumFrom :: Severity -> [Severity] # enumFromThen :: Severity -> Severity -> [Severity] # enumFromTo :: Severity -> Severity -> [Severity] # enumFromThenTo :: Severity -> Severity -> Severity -> [Severity] #
Eq Severity # |
Methods (==) :: Severity -> Severity -> Bool # (/=) :: Severity -> Severity -> Bool #
Ord Severity # |
Methods compare :: Severity -> Severity -> Ordering # (<) :: Severity -> Severity -> Bool # (<=) :: Severity -> Severity -> Bool # (>) :: Severity -> Severity -> Bool # (>=) :: Severity -> Severity -> Bool # max :: Severity -> Severity -> Severity # min :: Severity -> Severity -> Severity #
Read Severity # |
Methods readsPrec :: Int -> ReadS Severity # readList :: ReadS [Severity] # readPrec :: ReadPrec Severity # readListPrec :: ReadPrec [Severity] #
Show Severity # |
Methods showsPrec :: Int -> Severity -> ShowS # show :: Severity -> String # showList :: [Severity] -> ShowS #

data Note #

A note describing the impact of the replacement.

Constructors

IncreasesLaziness | The replacement is increases laziness, for example replacing `reverse (reverse x)` with `x` makes the code lazier.
DecreasesLaziness | The replacement is decreases laziness, for example replacing `(fst x, snd x)` with `x` makes the code stricter.
RemovesError String | The replacement removes errors, for example replacing `foldr1 (+)` with `sum` removes an error on `[]`, and might contain the text `"on []"`.
ValidInstance String String | The replacement assumes standard type class lemmas, a hint with the note `ValidInstance "Eq" "x"` might only be valid if the `x` variable has a reflexive `Eq` instance.
Note String | An arbitrary note.

Instances

Eq Note # |
Methods (==) :: Note -> Note -> Bool # (/=) :: Note -> Note -> Bool #
Ord Note # |
Methods compare :: Note -> Note -> Ordering # (<) :: Note -> Note -> Bool # (<=) :: Note -> Note -> Bool # (>) :: Note -> Note -> Bool # (>=) :: Note -> Note -> Bool # max :: Note -> Note -> Note # min :: Note -> Note -> Note #
Show Note # |
Methods showsPrec :: Int -> Note -> ShowS # show :: Note -> String # showList :: [Note] -> ShowS #

# Settings

data Classify #

How to classify an `Idea`. If any matching field is `""` then it matches everything.

Constructors

Classify |
Fields classifySeverity :: Severity Severity to set the `Idea` to. classifyHint :: String Match on `Idea` field `ideaHint`. classifyModule :: String Match on `Idea` field `ideaModule`. classifyDecl :: String Match on `Idea` field `ideaDecl`.

Instances

Show Classify # |
Methods showsPrec :: Int -> Classify -> ShowS # show :: Classify -> String # showList :: [Classify] -> ShowS #

getHLintDataDir :: IO FilePath #

Get the Cabal configured data directory of HLint

autoSettings :: IO (ParseFlags, [Classify], Hint) #

The function produces a tuple containg `ParseFlags` (for `parseModuleEx`), and `Classify` and `Hint` for `applyHints`. It approximates the normal HLint configuration steps, roughly:

1. Use `findSettings` to find and load the HLint settings files.
2. Use `readSettings` to interpret the settings files, producing `HintRule` values (`LHS ==> RHS` replacements) and `Classify` values to assign `Severity` ratings to hints.
3. Use `builtinHints` and `hintRules` to generate a `Hint` value.
4. Take all fixities from the `findSettings` modules and put them in the `ParseFlags`.

autoSettings' :: FilePath -> IO (ParseFlags, [Classify], Hint) #

Like `autoSettings` but with a custom data directory.

findSettings :: FilePath -> FilePath -> Maybe String -> IO ([String], [Module SrcSpanInfo]) #

Given the data directory (where the `hlint` data files reside, see `getHLintDataDir`), and a filename to read, and optionally that file's contents, produce a pair containing:

1. Builtin hints to use, e.g. `List`, which should be resolved using `builtinHints`.
2. A list of modules containing hints, suitable for processing with `readSettings`.

Any parse failures will result in an exception.

readSettings :: Module SrcSpanInfo -> ([Classify], [HintRule]) #

Given a module containing HLint settings information return the `Classify` rules and the `HintRule` expressions. Any fixity declarations will be discarded, but any other unrecognised elements will result in an exception.

# Hints

data Hint #

Functions to generate hints, combined using the `Monoid` instance.

Constructors

Hint |
Fields hintModules :: [(Scope, Module SrcSpanInfo)] -> [Idea] Given a list of modules (and their scope information) generate some `Idea`s. hintModule :: Scope -> Module SrcSpanInfo -> [Idea] Given a single module and its scope information generate some `Idea`s. hintDecl :: Scope -> Module SrcSpanInfo -> Decl SrcSpanInfo -> [Idea] Given a declaration (with a module and scope) generate some `Idea`s. This function will be partially applied with one module/scope, then used on multiple `Decl` values. hintComment :: Comment -> [Idea] Given a comment generate some `Idea`s.

Instances

Monoid Hint # |
Methods mempty :: Hint # mappend :: Hint -> Hint -> Hint # mconcat :: [Hint] -> Hint #

builtinHints :: [(String, Hint)] #

A list of builtin hints, currently including entries such as `"List"` and `"Bracket"`.

data HintRule #

A `LHS ==> RHS` style hint rule.

Constructors

HintRule |
Fields hintRuleSeverity :: Severity Default severity for the hint. hintRuleName :: String Name for the hint. hintRuleScope :: Scope Module scope in which the hint operates. hintRuleLHS :: Exp SrcSpanInfo LHS hintRuleRHS :: Exp SrcSpanInfo RHS hintRuleSide :: Maybe (Exp SrcSpanInfo) Side condition, typically specified with `where _ = ...`. hintRuleNotes :: [Note] Notes about application of the hint.

Instances

Show HintRule # |
Methods showsPrec :: Int -> HintRule -> ShowS # show :: HintRule -> String # showList :: [HintRule] -> ShowS #

hintRules :: [HintRule] -> Hint #

Transform a list of `HintRule` into a `Hint`.

# Scopes

data Scope #

Data type representing the modules in scope within a module. Created with `scopeCreate` and queried with `scopeMatch` and `scopeMove`. Note that the `mempty` `Scope` is not equivalent to `scopeCreate` on an empty module, due to the implicit import of `Prelude`.

Instances

Show Scope # |
Methods showsPrec :: Int -> Scope -> ShowS # show :: Scope -> String # showList :: [Scope] -> ShowS #
Monoid Scope # |
Methods mempty :: Scope # mappend :: Scope -> Scope -> Scope # mconcat :: [Scope] -> Scope #

scopeCreate :: Module SrcSpanInfo -> Scope #

Create a `Scope` value from a module, based on the modules imports.

scopeMatch :: (Scope, QName SrcSpanInfo) -> (Scope, QName SrcSpanInfo) -> Bool #

Given a two names in scopes, could they possibly refer to the same thing. This property is reflexive.

scopeMove :: (Scope, QName SrcSpanInfo) -> Scope -> QName SrcSpanInfo #

Given a name in a scope, and a new scope, create a name for the new scope that will refer to the same thing. If the resulting name is ambiguous, it picks a plausible candidate.

# Haskell-src-exts

parseModuleEx :: ParseFlags -> FilePath -> Maybe String -> IO (Either ParseError (Module SrcSpanInfo, [Comment])) #

Parse a Haskell module. Applies the C pre processor, and uses best-guess fixity resolution if there are ambiguities. The filename `-` is treated as `stdin`. Requires some flags (often `defaultParseFlags`), the filename, and optionally the contents of that file.

defaultParseFlags :: ParseFlags #

Default value for `ParseFlags`.

data ParseError #

A parse error from `parseModuleEx`.

Constructors

ParseError |
Fields parseErrorLocation :: SrcLoc Location of the error. parseErrorMessage :: String Message about the cause of the error. parseErrorContents :: String Snippet of several lines (typically 5) including a `>` character pointing at the faulty line.

data ParseFlags #

Created with `defaultParseFlags`, used by `parseModuleEx`.

Constructors

ParseFlags |
Fields encoding :: TextEncoding How the file is read in (defaults to `utf8`). cppFlags :: CppFlags How the file is preprocessed (defaults to `NoCpp`). hseFlags :: ParseMode How the file is parsed (defaults to all fixities in the `base` package and most non-conflicting extensions).

data CppFlags #

What C pre processor should be used.

Constructors

NoCpp | No pre processing is done.
CppSimple | Lines prefixed with `#` are stripped.
Cpphs CpphsOptions | The `cpphs` library is used.

# File encodings

type Encoding = TextEncoding #

An `Encoding` represents how characters are stored in a file. Created with `defaultEncoding` or `readEncoding` and used with `useEncoding`.

defaultEncoding :: Encoding #

The system default encoding.

readEncoding :: String -> IO Encoding #

Create an encoding from a string, or throw an error if the encoding is not known. Accepts many encodings including `locale`, `utf-8` and all those supported by the GHC `mkTextEncoding` function.

useEncoding :: Handle -> Encoding -> IO () #

Apply an encoding to a `Handle`.