Add documentation

This commit is contained in:
Jeroen Engels 2017-01-29 21:35:00 +01:00
parent fc93fad157
commit 0710792368
7 changed files with 209 additions and 54 deletions

View File

@ -1,6 +1,6 @@
# elm-lint
An [Elm](http://elm-lang.org/) linter written in Elm.
An [Elm](http://elm-lang.org/) linter written in Elm. Get your code from correct to better.
## Try it

View File

@ -1,12 +1,28 @@
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"summary": "A linter for Elm. Get your code from correct to better.",
"repository": "https://github.com/jfmengels/elm-lint.git",
"license": "BSD3",
"source-directories": [
"src"
],
"exposed-modules": [],
"exposed-modules": [
"Lint",
"Lint.Types",
"Lint.Rules.DefaultPatternPosition",
"Lint.Rules.NoConstantCondition",
"Lint.Rules.NoDebug",
"Lint.Rules.NoDuplicateImports",
"Lint.Rules.NoExposingEverything",
"Lint.Rules.NoImportingEverything",
"Lint.Rules.NoNestedLet",
"Lint.Rules.NoUnannotatedFunction",
"Lint.Rules.NoUnusedVariables",
"Lint.Rules.NoUselessIf",
"Lint.Rules.NoUselessPatternMatching",
"Lint.Rules.NoWarningComments",
"Lint.Rules.SimplifyPiping"
],
"dependencies": {
"elm-community/list-extra": "5.0.1 <= v < 6.0.0",
"elm-lang/core": "5.0.0 <= v < 6.0.0",

View File

@ -14,40 +14,40 @@ import Regex exposing (regex, escape)
-- Rules
import DefaultPatternPosition
import NoConstantCondition
import NoDebug
import NoDuplicateImports
import NoExposingEverything
import NoImportingEverything
import NoNestedLet
import NoUnannotatedFunction
import NoUnusedVariables
import NoUselessIf
import NoUselessPatternMatching
import NoWarningComments
import SimplifyPiping
import Lint.Rules.DefaultPatternPosition
import Lint.Rules.NoConstantCondition
import Lint.Rules.NoDebug
import Lint.Rules.NoDuplicateImports
import Lint.Rules.NoExposingEverything
import Lint.Rules.NoImportingEverything
import Lint.Rules.NoNestedLet
import Lint.Rules.NoUnannotatedFunction
import Lint.Rules.NoUnusedVariables
import Lint.Rules.NoUselessIf
import Lint.Rules.NoUselessPatternMatching
import Lint.Rules.NoWarningComments
import Lint.Rules.SimplifyPiping
type Msg
= Replace String
rules : List (String -> List Types.Error)
rules : List (String -> List Lint.Types.Error)
rules =
[ DefaultPatternPosition.rule { position = DefaultPatternPosition.Last }
, NoConstantCondition.rule
, NoDebug.rule
, NoDuplicateImports.rule
, NoExposingEverything.rule
, NoImportingEverything.rule
, NoNestedLet.rule
, NoUnannotatedFunction.rule
, NoUnusedVariables.rule
, NoUselessIf.rule
, NoUselessPatternMatching.rule
, NoWarningComments.rule
, SimplifyPiping.rule
[ Lint.Rules.DefaultPatternPosition.rule { position = Lint.Rules.DefaultPatternPosition.Last }
, Lint.Rules.NoConstantCondition.rule
, Lint.Rules.NoDebug.rule
, Lint.Rules.NoDuplicateImports.rule
, Lint.Rules.NoExposingEverything.rule
, Lint.Rules.NoImportingEverything.rule
, Lint.Rules.NoNestedLet.rule
, Lint.Rules.NoUnannotatedFunction.rule
, Lint.Rules.NoUnusedVariables.rule
, Lint.Rules.NoUselessIf.rule
, Lint.Rules.NoUselessPatternMatching.rule
, Lint.Rules.NoWarningComments.rule
, Lint.Rules.SimplifyPiping.rule
]

View File

@ -1,7 +1,7 @@
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"summary": "Online example for elm-lint",
"repository": "https://github.com/jfmengels/elm-lint.git",
"license": "BSD3",
"source-directories": [
".",

View File

@ -1,14 +1,67 @@
module Lint exposing (lint, visitExpression, doNothing)
{-| A linter for Elm.
See Lint.Rules for the implemented rules.
@docs lint, doNothing, visitExpression
-}
import Ast
import Ast.Expression exposing (Expression)
import Lint.Types exposing (Error, LintImplementation, LintRule, Direction, Visitor)
import Lint.Visitor exposing (transformStatementsIntoVisitors, expressionToVisitors)
doNothing : LintImplementation a context
doNothing ctx _ =
( [], ctx )
{-| Lints source code using a given rule implementation, and gives back a list of errors that were found.
rule : String -> List Error
rule input =
lint input implementation
implementation : LintRule Context
implementation =
{ statementFn = doNothing
, typeFn = doNothing
, expressionFn = expressionFn
, moduleEndFn = (\ctx -> ( [], ctx ))
, initialContext = Context
}
-}
lint : String -> LintRule context -> List Error
lint source =
source
|> Ast.parse
|> Result.map (\( _, _, statements ) -> statements)
|> Result.withDefault []
|> transformStatementsIntoVisitors
|> lintWithVisitors
{-| Visit an expression using a sub rule implementation. The use of this function is not encouraged, but it can make
part of the implementation of complex rules much easier. It gives back a list of errors and a context.
expressionFn : Context -> Direction Expression -> ( List Error, Context )
expressionFn ctx node =
case node of
Enter (Case expr patterns) ->
visitExpression subimplementation expr
_ ->
( [], ctx )
subimplementation : LintRule Subcontext
subimplementation =
{ statementFn = doNothing
, typeFn = doNothing
, expressionFn = subexpressionFn
, moduleEndFn = (\ctx -> ( [], ctx ))
, initialContext = Subcontext
}
-}
visitExpression : LintRule context -> Expression -> ( List Error, context )
visitExpression rule expression =
expressionToVisitors expression
|> List.foldl (visitAndAccumulate rule) ( [], rule.initialContext )
visitAndAccumulate : LintRule context -> Visitor context -> ( List Error, context ) -> ( List Error, context )
@ -24,17 +77,18 @@ lintWithVisitors visitors rule =
|> Tuple.first
visitExpression : LintRule context -> Expression -> ( List Error, context )
visitExpression rule expression =
expressionToVisitors expression
|> List.foldl (visitAndAccumulate rule) ( [], rule.initialContext )
{-| Basic implementation of a visitor function that does nothing, i.e. return an empty list of errors and an untouched
context. This is used to avoid a bit of boilerplate for visitor functions whose node types we are not interested in.
lint : String -> LintRule context -> List Error
lint source =
source
|> Ast.parse
|> Result.map (\( _, _, statements ) -> statements)
|> Result.withDefault []
|> transformStatementsIntoVisitors
|> lintWithVisitors
implementation : LintRule Context
implementation =
{ statementFn = doNothing
, typeFn = doNothing
, expressionFn = expressionFn
, moduleEndFn = (\ctx -> ( [], ctx ))
, initialContext = Context
}
-}
doNothing : LintImplementation a context
doNothing ctx _ =
( [], ctx )

View File

@ -1,24 +1,104 @@
module Lint.Types exposing (..)
module Lint.Types exposing (Error, LintImplementation, Direction(..), LintRule, Visitor)
{-| This module contains types that are used for writing rules.
# Elementary types
@docs Error, Direction
# Writing rules
@docs LintRule, LintImplementation
# Internal types
@docs Visitor
-}
import Ast.Expression exposing (..)
import Ast.Statement exposing (..)
{-| Value that describes an error found by a given rule, that contains the name of the rule that raised the error, and
a description of the error.
error : Error
error =
Error "NoDebug" "Forbidden use of Debug"
-}
type alias Error =
{ rule : String
, message : String
}
{-| A LintImplementation is a function that takes a given Context object, as defined by each rule, a node (with a
Direction) and returns a list of errors and an updated Context.
Every rule should implement three LintImplementation functions, one for every Node type (Statement, Type and
Expression).
The Context is there to accumulate information about the source code as the AST is being visited and is shared by all
the LintImplementation functions of your rule.
It must return a list of errors which will be reported to the user, that are violations of the thing the rule wants to
enforce.
rule : String -> List Error
rule input =
lint input implementation
implementation : LintRule Context
implementation =
{ statementFn = doNothing
, typeFn = doNothing
, expressionFn = expressionFn
, moduleEndFn = (\ctx -> ( [], ctx ))
, initialContext = Context
}
-}
type alias LintImplementation nodeType context =
context -> Direction nodeType -> ( List Error, context )
{-| When visiting the AST, nodes are visited twice:
- on Enter, before the children of the node will be visited
- on Exit, after the children of the node have been visited
expressionFn : Context -> Direction Expression -> ( List Error, Context )
expressionFn ctx node =
case node of
Enter (Variable names) ->
( [], markVariableAsUsed ctx names )
-- Find variables declared in `let .. in ..` expression
Enter (Let declarations body) ->
( [], registerVariables ctx declarations )
-- When exiting the `let .. in ..` expression, report the variables that were not used.
Exit (Let _ _) ->
( unusedVariables ctx |> List.map createError, ctx )
-}
type Direction node
= Enter node
| Exit node
type alias LintImplementation nodeType context =
context -> Direction nodeType -> ( List Error, context )
{-| A LintRule is the implementation of a rule. It is a record that contains:
- initialContext: An initial context
- statementFn: A LintImplementation for Statement nodes
- typeFn: A LintImplementation for Type nodes
- expressionFn: A LintImplementation for Expression nodes
- moduleEndFn: A function that takes a context and returns a list of error. Similar to a LintImplementation, but will
be called after visiting the whole AST.
rule : String -> List Error
rule input =
lint input implementation
implementation : LintRule Context
implementation =
{ statementFn = doNothing
, typeFn = doNothing
, expressionFn = expressionFn
, moduleEndFn = (\ctx -> ( [], ctx ))
, initialContext = Context
}
-}
type alias LintRule context =
{ statementFn : LintImplementation Statement context
, typeFn : LintImplementation Type context
@ -28,5 +108,10 @@ type alias LintRule context =
}
{-| Shorthand for a function that takes a rule's implementation, a context and returns ( List Error, context ).
A Visitor represents a node and calls the appropriate function for the given node type.
Note: this is internal API, and will be removed in a future version.
-}
type alias Visitor context =
LintRule context -> context -> ( List Error, context )

View File

@ -1,7 +1,7 @@
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"summary": "Tests for elm-lint",
"repository": "https://github.com/jfmengels/elm-lint.git",
"license": "BSD3",
"source-directories": [
".",