mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-11-22 22:33:13 +03:00
Add withProjectVisitor function to go through the elm.json file
This commit is contained in:
parent
85e688dfc0
commit
c35cce2a90
2
elm.json
2
elm.json
@ -12,12 +12,14 @@
|
|||||||
"Lint.Rule.NoImportingEverything",
|
"Lint.Rule.NoImportingEverything",
|
||||||
"Lint.Rule.NoUnusedTypeConstructors",
|
"Lint.Rule.NoUnusedTypeConstructors",
|
||||||
"Lint.Rule.NoUnusedVariables",
|
"Lint.Rule.NoUnusedVariables",
|
||||||
|
"Lint.Project",
|
||||||
"Lint.Fix",
|
"Lint.Fix",
|
||||||
"Lint.Test"
|
"Lint.Test"
|
||||||
],
|
],
|
||||||
"elm-version": "0.19.0 <= v < 0.20.0",
|
"elm-version": "0.19.0 <= v < 0.20.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"elm/core": "1.0.2 <= v < 2.0.0",
|
"elm/core": "1.0.2 <= v < 2.0.0",
|
||||||
|
"elm/project-metadata-utils": "1.0.0 <= v < 2.0.0",
|
||||||
"elm-explorations/test": "1.2.2 <= v < 2.0.0",
|
"elm-explorations/test": "1.2.2 <= v < 2.0.0",
|
||||||
"stil4m/elm-syntax": "7.1.0 <= v < 8.0.0"
|
"stil4m/elm-syntax": "7.1.0 <= v < 8.0.0"
|
||||||
},
|
},
|
||||||
|
74
src/Lint/Project.elm
Normal file
74
src/Lint/Project.elm
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
module Lint.Project exposing
|
||||||
|
( Project
|
||||||
|
, elmJson
|
||||||
|
, new, withElmJson
|
||||||
|
)
|
||||||
|
|
||||||
|
{-| Represents project-related data, that a rule can access to get more information.
|
||||||
|
|
||||||
|
|
||||||
|
# Definition
|
||||||
|
|
||||||
|
@docs Project
|
||||||
|
|
||||||
|
|
||||||
|
# Access
|
||||||
|
|
||||||
|
@docs elmJson
|
||||||
|
|
||||||
|
|
||||||
|
# Build
|
||||||
|
|
||||||
|
@docs new, withElmJson
|
||||||
|
|
||||||
|
-}
|
||||||
|
|
||||||
|
-- TODO rename this module to avoid collisions and ambiguity
|
||||||
|
|
||||||
|
import Elm.Project
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- DEFINITION
|
||||||
|
|
||||||
|
|
||||||
|
{-| Represents all kinds of details about the project, such as the contents of
|
||||||
|
the `elm.json` file.
|
||||||
|
-}
|
||||||
|
type Project
|
||||||
|
= Project { elmJson : Maybe Elm.Project.Project }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- ACCESS
|
||||||
|
|
||||||
|
|
||||||
|
{-| Get the contents of the `elm.json` file, if available.
|
||||||
|
|
||||||
|
This will give you a `Project` type from the
|
||||||
|
[`elm/project-metadata-utils`](https://package.elm-lang.org/packages/elm/project-metadata-utils/1.0.0/Elm-Project)
|
||||||
|
package, so you will need to install and use it to gain access to the
|
||||||
|
information inside the `elm.json` file.
|
||||||
|
|
||||||
|
-}
|
||||||
|
elmJson : Project -> Maybe Elm.Project.Project
|
||||||
|
elmJson (Project data) =
|
||||||
|
data.elmJson
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- BUILD
|
||||||
|
|
||||||
|
|
||||||
|
{-| Create a new Project.
|
||||||
|
-}
|
||||||
|
new : Project
|
||||||
|
new =
|
||||||
|
Project { elmJson = Nothing }
|
||||||
|
|
||||||
|
|
||||||
|
{-| Add the contents of the `elm.json` file to the project details.
|
||||||
|
-}
|
||||||
|
withElmJson : Elm.Project.Project -> Project -> Project
|
||||||
|
withElmJson elmJson_ (Project data) =
|
||||||
|
Project { data | elmJson = Just elmJson_ }
|
@ -2,7 +2,7 @@ module Lint.Rule exposing
|
|||||||
( Rule, Schema
|
( Rule, Schema
|
||||||
, newSchema, fromSchema
|
, newSchema, fromSchema
|
||||||
, withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleDeclarationVisitor, withSimpleExpressionVisitor
|
, withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleDeclarationVisitor, withSimpleExpressionVisitor
|
||||||
, withInitialContext, withModuleDefinitionVisitor, withImportVisitor, Direction(..), withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
, withInitialContext, withProjectVisitor, withModuleDefinitionVisitor, withImportVisitor, Direction(..), withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
||||||
, withFixes
|
, withFixes
|
||||||
, Error, error, errorMessage, errorDetails, errorRange, errorFixes
|
, Error, error, errorMessage, errorDetails, errorRange, errorFixes
|
||||||
, name, analyzer
|
, name, analyzer
|
||||||
@ -156,7 +156,7 @@ patterns you would want to forbid, but that are not handled by the example.
|
|||||||
|
|
||||||
## Builder functions with context
|
## Builder functions with context
|
||||||
|
|
||||||
@docs withInitialContext, withModuleDefinitionVisitor, withImportVisitor, Direction, withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
@docs withInitialContext, withProjectVisitor, withModuleDefinitionVisitor, withImportVisitor, Direction, withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
||||||
|
|
||||||
|
|
||||||
## Automatic fixing
|
## Automatic fixing
|
||||||
@ -184,6 +184,7 @@ import Elm.Syntax.Module exposing (Module)
|
|||||||
import Elm.Syntax.Node as Node exposing (Node)
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
import Elm.Syntax.Range exposing (Range)
|
import Elm.Syntax.Range exposing (Range)
|
||||||
import Lint.Fix exposing (Fix)
|
import Lint.Fix exposing (Fix)
|
||||||
|
import Lint.Project exposing (Project)
|
||||||
|
|
||||||
|
|
||||||
{-| Represents a construct able to analyze a `File` and report unwanted patterns.
|
{-| Represents a construct able to analyze a `File` and report unwanted patterns.
|
||||||
@ -234,6 +235,7 @@ type
|
|||||||
= Schema
|
= Schema
|
||||||
{ name : String
|
{ name : String
|
||||||
, initialContext : context
|
, initialContext : context
|
||||||
|
, projectVisitor : Project -> context -> context
|
||||||
, moduleDefinitionVisitor : Node Module -> context -> ( List Error, context )
|
, moduleDefinitionVisitor : Node Module -> context -> ( List Error, context )
|
||||||
, importVisitor : Node Import -> context -> ( List Error, context )
|
, importVisitor : Node Import -> context -> ( List Error, context )
|
||||||
, expressionVisitor : Node Expression -> Direction -> context -> ( List Error, context )
|
, expressionVisitor : Node Expression -> Direction -> context -> ( List Error, context )
|
||||||
@ -309,6 +311,7 @@ newSchema name_ =
|
|||||||
Schema
|
Schema
|
||||||
{ name = name_
|
{ name = name_
|
||||||
, initialContext = ()
|
, initialContext = ()
|
||||||
|
, projectVisitor = \project context -> context
|
||||||
, moduleDefinitionVisitor = \node context -> ( [], context )
|
, moduleDefinitionVisitor = \node context -> ( [], context )
|
||||||
, importVisitor = \node context -> ( [], context )
|
, importVisitor = \node context -> ( [], context )
|
||||||
, expressionVisitor = \direction node context -> ( [], context )
|
, expressionVisitor = \direction node context -> ( [], context )
|
||||||
@ -654,6 +657,7 @@ withInitialContext initialContext_ (Schema schema) =
|
|||||||
Schema
|
Schema
|
||||||
{ name = schema.name
|
{ name = schema.name
|
||||||
, initialContext = initialContext_
|
, initialContext = initialContext_
|
||||||
|
, projectVisitor = \project context -> context
|
||||||
, moduleDefinitionVisitor = \node context -> ( [], context )
|
, moduleDefinitionVisitor = \node context -> ( [], context )
|
||||||
, importVisitor = \node context -> ( [], context )
|
, importVisitor = \node context -> ( [], context )
|
||||||
, expressionVisitor = \node direction context -> ( [], context )
|
, expressionVisitor = \node direction context -> ( [], context )
|
||||||
@ -662,6 +666,86 @@ withInitialContext initialContext_ (Schema schema) =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO Is having both withInitialContext and withProjectVisitor redundant?
|
||||||
|
-- Since withProjectVisitor doesn't really need an initial context and can set
|
||||||
|
-- one up itself.
|
||||||
|
-- Maybe have one or the other, using phantom types?
|
||||||
|
|
||||||
|
|
||||||
|
{-| Add a visitor to the [`Schema`](#Schema) which will visit the project's known
|
||||||
|
information, such as the contents of the `elm.json` file.
|
||||||
|
[module definition](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/Elm-Syntax-Module) (`module SomeModuleName exposing (a, b)`), collect data in the `context` and/or report patterns.
|
||||||
|
|
||||||
|
The following example forbids the use of `Html.button` except in the "Button" file.
|
||||||
|
THe example is simplified to only forbid the use of the `Html.button` expression.
|
||||||
|
|
||||||
|
import Elm.Module
|
||||||
|
import Elm.Project
|
||||||
|
import Elm.Syntax.Module as Module exposing (Module)
|
||||||
|
import Elm.Syntax.Node as Node exposing (Node)
|
||||||
|
import Lint.Project as Project exposing (Project)
|
||||||
|
import Lint.Rule as Rule exposing (Error, Rule)
|
||||||
|
|
||||||
|
type alias Context =
|
||||||
|
Maybe Elm.Project.Project
|
||||||
|
|
||||||
|
rule : Rule
|
||||||
|
rule =
|
||||||
|
Rule.newSchema "DoNoExposeInternalModules"
|
||||||
|
|> Rule.withInitialContext Nothing
|
||||||
|
|> Rule.withProjectVisitor projectVisitor
|
||||||
|
|> Rule.withModuleDefinitionVisitor moduleDefinitionVisitor
|
||||||
|
|> Rule.fromSchema
|
||||||
|
|
||||||
|
projectVisitor : Project -> Context -> Context
|
||||||
|
projectVisitor project context =
|
||||||
|
Project.elmJson project
|
||||||
|
|
||||||
|
moduleDefinitionVisitor : Node Module -> Context -> ( List Error, Context )
|
||||||
|
moduleDefinitionVisitor node context =
|
||||||
|
let
|
||||||
|
moduleName : List String
|
||||||
|
moduleName =
|
||||||
|
Node.value node |> Module.moduleName
|
||||||
|
in
|
||||||
|
if List.member "Internal" moduleName then
|
||||||
|
case context of
|
||||||
|
Just (Elm.Project.Package { exposed }) ->
|
||||||
|
let
|
||||||
|
exposedModules : List String
|
||||||
|
exposedModules =
|
||||||
|
case exposed of
|
||||||
|
Elm.Project.ExposedList names ->
|
||||||
|
names
|
||||||
|
|> List.map Elm.Module.toString
|
||||||
|
|
||||||
|
Elm.Project.ExposedDict fakeDict ->
|
||||||
|
fakeDict
|
||||||
|
|> List.concatMap Tuple.second
|
||||||
|
|> List.map Elm.Module.toString
|
||||||
|
in
|
||||||
|
if List.member (String.join "." moduleName) exposedModules then
|
||||||
|
( [ Rule.error "Do not expose modules in `Internal` as part of the public API" (Node.range node) ], context )
|
||||||
|
|
||||||
|
else
|
||||||
|
( [], context )
|
||||||
|
|
||||||
|
Just (Elm.Project.Application _) ->
|
||||||
|
( [], context )
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
( [], context )
|
||||||
|
|
||||||
|
else
|
||||||
|
( [], context )
|
||||||
|
|
||||||
|
-}
|
||||||
|
withProjectVisitor : (Project -> context -> context) -> Schema configurationState context -> Schema configurationState context
|
||||||
|
withProjectVisitor visitor (Schema schema) =
|
||||||
|
Schema { schema | projectVisitor = visitor }
|
||||||
|
|
||||||
|
|
||||||
{-| Add a visitor to the [`Schema`](#Schema) which will visit the `File`'s
|
{-| Add a visitor to the [`Schema`](#Schema) which will visit the `File`'s
|
||||||
[module definition](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/Elm-Syntax-Module) (`module SomeModuleName exposing (a, b)`), collect data in the `context` and/or report patterns.
|
[module definition](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/Elm-Syntax-Module) (`module SomeModuleName exposing (a, b)`), collect data in the `context` and/or report patterns.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user