mirror of
https://github.com/jfmengels/elm-review.git
synced 2024-12-23 17:53:35 +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.NoUnusedTypeConstructors",
|
||||
"Lint.Rule.NoUnusedVariables",
|
||||
"Lint.Project",
|
||||
"Lint.Fix",
|
||||
"Lint.Test"
|
||||
],
|
||||
"elm-version": "0.19.0 <= v < 0.20.0",
|
||||
"dependencies": {
|
||||
"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",
|
||||
"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
|
||||
, newSchema, fromSchema
|
||||
, withSimpleModuleDefinitionVisitor, withSimpleImportVisitor, withSimpleDeclarationVisitor, withSimpleExpressionVisitor
|
||||
, withInitialContext, withModuleDefinitionVisitor, withImportVisitor, Direction(..), withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
||||
, withInitialContext, withProjectVisitor, withModuleDefinitionVisitor, withImportVisitor, Direction(..), withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
||||
, withFixes
|
||||
, Error, error, errorMessage, errorDetails, errorRange, errorFixes
|
||||
, name, analyzer
|
||||
@ -156,7 +156,7 @@ patterns you would want to forbid, but that are not handled by the example.
|
||||
|
||||
## Builder functions with context
|
||||
|
||||
@docs withInitialContext, withModuleDefinitionVisitor, withImportVisitor, Direction, withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
||||
@docs withInitialContext, withProjectVisitor, withModuleDefinitionVisitor, withImportVisitor, Direction, withDeclarationVisitor, withExpressionVisitor, withFinalEvaluation
|
||||
|
||||
|
||||
## Automatic fixing
|
||||
@ -184,6 +184,7 @@ import Elm.Syntax.Module exposing (Module)
|
||||
import Elm.Syntax.Node as Node exposing (Node)
|
||||
import Elm.Syntax.Range exposing (Range)
|
||||
import Lint.Fix exposing (Fix)
|
||||
import Lint.Project exposing (Project)
|
||||
|
||||
|
||||
{-| Represents a construct able to analyze a `File` and report unwanted patterns.
|
||||
@ -234,6 +235,7 @@ type
|
||||
= Schema
|
||||
{ name : String
|
||||
, initialContext : context
|
||||
, projectVisitor : Project -> context -> context
|
||||
, moduleDefinitionVisitor : Node Module -> context -> ( List Error, context )
|
||||
, importVisitor : Node Import -> context -> ( List Error, context )
|
||||
, expressionVisitor : Node Expression -> Direction -> context -> ( List Error, context )
|
||||
@ -309,6 +311,7 @@ newSchema name_ =
|
||||
Schema
|
||||
{ name = name_
|
||||
, initialContext = ()
|
||||
, projectVisitor = \project context -> context
|
||||
, moduleDefinitionVisitor = \node context -> ( [], context )
|
||||
, importVisitor = \node context -> ( [], context )
|
||||
, expressionVisitor = \direction node context -> ( [], context )
|
||||
@ -654,6 +657,7 @@ withInitialContext initialContext_ (Schema schema) =
|
||||
Schema
|
||||
{ name = schema.name
|
||||
, initialContext = initialContext_
|
||||
, projectVisitor = \project context -> context
|
||||
, moduleDefinitionVisitor = \node context -> ( [], context )
|
||||
, importVisitor = \node 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
|
||||
[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