Have Project store the dependencies of the project

This commit is contained in:
Jeroen Engels 2019-11-20 00:24:05 +01:00
parent f8632c20bc
commit 61ef16b345
4 changed files with 218 additions and 12 deletions

View File

@ -13,12 +13,12 @@
"elm/browser": "1.0.1",
"elm/core": "1.0.2",
"elm/html": "1.0.0",
"elm/json": "1.1.3",
"elm/project-metadata-utils": "1.0.0",
"jinjor/elm-diff": "1.0.6",
"stil4m/elm-syntax": "7.1.0"
},
"indirect": {
"elm/json": "1.1.3",
"elm/parser": "1.1.0",
"elm/random": "1.0.0",
"elm/time": "1.0.0",

View File

@ -15,6 +15,7 @@
"elm-version": "0.19.0 <= v < 0.20.0",
"dependencies": {
"elm/core": "1.0.2 <= v < 2.0.0",
"elm/json": "1.0.0 <= 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"

View File

@ -0,0 +1,179 @@
module Review.ModuleInterface exposing (Exposed(..), fromDocsJson)
import Elm.Interface as Interface
import Elm.Syntax.Infix as Infix exposing (InfixDirection)
import Elm.Syntax.Node as Node exposing (Node)
import Elm.Syntax.Range as Range
import Json.Decode as Decode
-- DEFINITION
type Exposed
= CustomType
{ name : String
, arguments : List String
, cases : List Case
}
| TypeAlias
{ name : String
, arguments : List String
, type_ : String
}
| Value
{ name : String
, type_ : String
}
| Operator
{ name : String
, type_ : String
, precedence : Int
, associativity : InfixDirection
}
type alias Case =
{ name : String
, arguments : List String
}
-- DECODE
fromDocsJson : Decode.Decoder (List ( String, List Exposed ))
fromDocsJson =
Decode.list decodeItem
decodeItem : Decode.Decoder ( String, List Exposed )
decodeItem =
Decode.map5
(\name customTypes aliases values operators ->
( name, List.concat [ customTypes, aliases, values, operators ] )
)
(Decode.field "name" Decode.string)
(Decode.field "unions" (Decode.list decodeCustomType))
(Decode.field "aliases" (Decode.list decodeTypeAlias))
(Decode.field "values" (Decode.list decodeValue))
(Decode.field "binops" (Decode.list decodeOperator))
decodeCustomType : Decode.Decoder Exposed
decodeCustomType =
Decode.map3
(\name arguments cases ->
CustomType
{ name = name
, arguments = arguments
, cases = cases
}
)
(Decode.field "name" Decode.string)
(Decode.field "args" (Decode.list Decode.string))
(Decode.field "cases" (Decode.list decodeCase))
decodeCase : Decode.Decoder Case
decodeCase =
Decode.map2 Case
(Decode.field "0" Decode.string)
(Decode.field "1" (Decode.list Decode.string))
decodeTypeAlias : Decode.Decoder Exposed
decodeTypeAlias =
Decode.map3
(\name arguments type_ ->
TypeAlias
{ name = name
, arguments = arguments
, type_ = type_
}
)
(Decode.field "name" Decode.string)
(Decode.field "args" (Decode.list Decode.string))
(Decode.field "type" Decode.string)
decodeValue : Decode.Decoder Exposed
decodeValue =
Decode.map2
(\name type_ ->
Value
{ name = name
, type_ = type_
}
)
(Decode.field "name" Decode.string)
(Decode.field "type" Decode.string)
decodeOperator : Decode.Decoder Exposed
decodeOperator =
Decode.map4
(\name type_ precedence associativity ->
Operator
{ name = name
, type_ = type_
, precedence = precedence
, associativity = associativity
}
)
(Decode.field "name" Decode.string)
(Decode.field "type" Decode.string)
(Decode.field "precedence" Decode.int)
(Decode.field "associativity" decodeAssociativity)
decodeAssociativity : Decode.Decoder InfixDirection
decodeAssociativity =
Decode.string
|> Decode.andThen
(\infix ->
case infix of
"left" ->
Decode.succeed Infix.Left
"non" ->
Decode.succeed Infix.Non
"right" ->
Decode.succeed Infix.Right
_ ->
Decode.fail "Unknown associativity for operator"
)
-- ELM-SYNTAX
toElmSyntaxInterface : List Exposed -> Interface.Interface
toElmSyntaxInterface exposedList =
List.map toElmSyntaxExposed exposedList
toElmSyntaxExposed : Exposed -> Interface.Exposed
toElmSyntaxExposed exposed =
case exposed of
CustomType { name, cases } ->
Interface.CustomType ( name, List.map .name cases )
TypeAlias { name } ->
Interface.Alias name
Value { name } ->
Interface.Function name
Operator { name, associativity, precedence } ->
Interface.Operator
{ operator = Node.Node Range.emptyRange name
, direction = Node.Node Range.emptyRange associativity
, precedence = Node.Node Range.emptyRange precedence
, function = Node.Node Range.emptyRange name
}

View File

@ -1,7 +1,7 @@
module Review.Project exposing
( Project, ElmJson
, elmJson, interfaces
, new, withElmJson
, new, withElmJson, withDependency
)
{-| Represents project-related data, that a rule can access to get more information.
@ -23,7 +23,7 @@ rules to have access to, to later pass it to the [`Review.review`](./Review#revi
# Build
@docs new, withElmJson
@docs new, withElmJson, withDependency
-}
@ -31,6 +31,7 @@ import Dict exposing (Dict)
import Elm.Interface exposing (Interface)
import Elm.Project
import Elm.Syntax.ModuleName exposing (ModuleName)
import Review.ModuleInterface as ModuleInterface
@ -43,12 +44,13 @@ the `elm.json` file.
type Project
= Project
{ elmJson : Maybe ElmJson
, interfaces : Dict ModuleName Interface
, interfaces : Dict ModuleName (List ModuleInterface.Exposed)
, moduleToDependency : Dict ModuleName String
}
{-| Contents of the `elm.json` file. Alias to
[`elm/project-metadata-utils`'s Project data structure](https://package.elm-lang.org/packages/elm/project-metadata-utils/latest/Elm-Project).
[`elm/project-metadata-utils`'s Project project structure](https://package.elm-lang.org/packages/elm/project-metadata-utils/latest/Elm-Project).
-}
type alias ElmJson =
Elm.Project.Project
@ -67,8 +69,8 @@ information inside the `elm.json` file.
-}
elmJson : Project -> Maybe ElmJson
elmJson (Project data) =
data.elmJson
elmJson (Project project) =
project.elmJson
{-| Get the interfaces for every dependency in the project.
@ -79,9 +81,9 @@ package, so you will need to install and use it to gain access to the
information inside the `elm.json` file.
-}
interfaces : Project -> Dict ModuleName Interface
interfaces (Project data) =
data.interfaces
interfaces : Project -> Dict ModuleName (List ModuleInterface.Exposed)
interfaces (Project project) =
project.interfaces
@ -95,11 +97,35 @@ new =
Project
{ elmJson = Nothing
, interfaces = Dict.empty
, moduleToDependency = Dict.empty
}
{-| Add the contents of the `elm.json` file to the project details.
-}
withElmJson : ElmJson -> Project -> Project
withElmJson elmJson_ (Project data) =
Project { data | elmJson = Just elmJson_ }
withElmJson elmJson_ (Project project) =
Project { project | elmJson = Just elmJson_ }
{-| Add a dependency to the project
-}
withDependency : { packageName : String, interfaces : List ( String, List ModuleInterface.Exposed ) } -> Project -> Project
withDependency dependency (Project project) =
Project
{ project
| interfaces =
dependency.interfaces
|> List.map (Tuple.mapFirst (String.split "."))
|> Dict.fromList
|> Dict.union project.interfaces
, moduleToDependency =
dependency.interfaces
|> List.map
(Tuple.mapBoth
(String.split ".")
(always dependency.packageName)
)
|> Dict.fromList
|> Dict.union project.moduleToDependency
}