Register values from visited modules in Scope

This commit is contained in:
Jeroen Engels 2020-01-13 10:37:24 +01:00
parent 25601e6b24
commit 0362f5b3e3
2 changed files with 187 additions and 10 deletions

View File

@ -23,16 +23,22 @@ module Scope2 exposing
-} -}
-- TODO Re-add the nice "can't make mistakes" addVisitors
import Dict exposing (Dict) import Dict exposing (Dict)
import Elm.Docs import Elm.Docs
import Elm.Syntax.Declaration as Declaration exposing (Declaration) import Elm.Syntax.Declaration as Declaration exposing (Declaration)
import Elm.Syntax.Exposing as Exposing exposing (Exposing, TopLevelExpose) import Elm.Syntax.Exposing as Exposing exposing (Exposing, TopLevelExpose)
import Elm.Syntax.Expression as Expression exposing (Expression) import Elm.Syntax.Expression as Expression exposing (Expression)
import Elm.Syntax.Import exposing (Import) import Elm.Syntax.Import exposing (Import)
import Elm.Syntax.Module as Module exposing (Module)
import Elm.Syntax.ModuleName exposing (ModuleName) import Elm.Syntax.ModuleName exposing (ModuleName)
import Elm.Syntax.Node as Node exposing (Node(..)) import Elm.Syntax.Node as Node exposing (Node(..))
import Elm.Syntax.Pattern as Pattern exposing (Pattern) import Elm.Syntax.Pattern as Pattern exposing (Pattern)
import Elm.Syntax.Range as Range import Elm.Syntax.Range as Range exposing (Range)
import Elm.Syntax.Signature exposing (Signature)
import Elm.Syntax.TypeAnnotation as TypeAnnotation exposing (TypeAnnotation)
import Elm.Type
import NonemptyList exposing (Nonempty) import NonemptyList exposing (Nonempty)
import Review.Rule as Rule exposing (Direction, Error) import Review.Rule as Rule exposing (Direction, Error)
@ -82,9 +88,20 @@ type alias InnerModuleContext =
, dependencies : Dict String Elm.Docs.Module , dependencies : Dict String Elm.Docs.Module
, modules : Dict ModuleName Elm.Docs.Module , modules : Dict ModuleName Elm.Docs.Module
, exposesEverything : Bool , exposesEverything : Bool
, exposedNames : Dict String { range : Range, exposedElement : ExposedElement }
, exposedUnions : List Elm.Docs.Union
, exposedAliases : List Elm.Docs.Alias
, exposedValues : List Elm.Docs.Value
, exposedBinops : List Elm.Docs.Binop
} }
type ExposedElement
= Function
| TypeOrTypeAlias
| ExposedType Bool
type alias Scope = type alias Scope =
{ names : Dict String VariableInfo { names : Dict String VariableInfo
, cases : List ( Node Expression, Dict String VariableInfo ) , cases : List ( Node Expression, Dict String VariableInfo )
@ -124,16 +141,30 @@ fromGlobalToModule (GlobalContext globalContext) =
, dependencies = globalContext.dependencies , dependencies = globalContext.dependencies
, modules = globalContext.modules , modules = globalContext.modules
, exposesEverything = False , exposesEverything = False
, exposedNames = Dict.empty
, exposedUnions = []
, exposedAliases = []
, exposedValues = []
, exposedBinops = []
} }
|> registerPrelude |> registerPrelude
|> ModuleContext |> ModuleContext
fromModuleToGlobal : ModuleContext -> GlobalContext fromModuleToGlobal : Node ModuleName -> ModuleContext -> GlobalContext
fromModuleToGlobal (ModuleContext moduleContext) = fromModuleToGlobal moduleName (ModuleContext moduleContext) =
GlobalContext GlobalContext
{ dependencies = moduleContext.dependencies { dependencies = moduleContext.dependencies
, modules = moduleContext.modules , modules =
Dict.insert (Node.value moduleName)
{ name = String.join "." (Node.value moduleName)
, comment = ""
, unions = moduleContext.exposedUnions
, aliases = moduleContext.exposedAliases
, values = moduleContext.exposedValues
, binops = moduleContext.exposedBinops
}
moduleContext.modules
} }
@ -162,6 +193,8 @@ addGlobalVisitors setterGetter schema =
addModuleVisitors : ModuleSetterGetter moduleContext -> Rule.Schema anytype anything moduleContext -> Rule.Schema anytype { hasAtLeastOneVisitor : () } moduleContext addModuleVisitors : ModuleSetterGetter moduleContext -> Rule.Schema anytype anything moduleContext -> Rule.Schema anytype { hasAtLeastOneVisitor : () } moduleContext
addModuleVisitors setterGetter schema = addModuleVisitors setterGetter schema =
schema schema
|> Rule.withModuleDefinitionVisitor
(mapInnerModuleContext setterGetter moduleDefinitionVisitor |> pairWithNoErrors)
|> Rule.withImportVisitor |> Rule.withImportVisitor
(mapInnerModuleContext setterGetter importVisitor |> pairWithNoErrors) (mapInnerModuleContext setterGetter importVisitor |> pairWithNoErrors)
|> Rule.withDeclarationListVisitor |> Rule.withDeclarationListVisitor
@ -194,6 +227,29 @@ addModuleVisitors setterGetter schema =
-- scopedRule :
-- String
-- ->
-- { forGlobal :
-- { get : globalContext -> GlobalContext
-- , set : GlobalContext -> globalContext -> globalContext
-- }
-- , forModule :
-- { get : moduleContext -> ModuleContext
-- , set : ModuleContext -> moduleContext -> moduleContext
-- }
-- }
-- ->
-- { moduleVisitorSchema : Rule.Schema Rule.ForLookingAtSeveralFiles { hasNoVisitor : () } moduleContext -> Rule.Schema Rule.ForLookingAtSeveralFiles { hasAtLeastOneVisitor : () } moduleContext
-- , initGlobalContext : globalContext
-- , fromGlobalToModule : Rule.FileKey -> Node ModuleName -> globalContext -> moduleContext
-- , fromModuleToGlobal : Rule.FileKey -> Node ModuleName -> moduleContext -> globalContext
-- , foldGlobalContexts : globalContext -> globalContext -> globalContext
-- }
-- -> Rule.MultiSchema globalContext moduleContext
-- scopedRule name setterGetters context =
-- Rule.newMultiSchema name
mapInnerGlobalContext : GlobalSetterGetter context -> (visitedElement -> InnerGlobalContext -> InnerGlobalContext) -> visitedElement -> context -> context mapInnerGlobalContext : GlobalSetterGetter context -> (visitedElement -> InnerGlobalContext -> InnerGlobalContext) -> visitedElement -> context -> context
mapInnerGlobalContext { set, get } visitor visitedElement outerContext = mapInnerGlobalContext { set, get } visitor visitedElement outerContext =
@ -237,7 +293,7 @@ dependenciesVisitor dependencies innerContext =
registerPrelude : InnerModuleContext -> InnerModuleContext registerPrelude : InnerModuleContext -> InnerModuleContext
registerPrelude innerContext = registerPrelude innerContext =
List.foldl registerExposed innerContext elmCorePrelude List.foldl registerImportExposed innerContext elmCorePrelude
elmCorePrelude : List Import elmCorePrelude : List Import
@ -343,6 +399,7 @@ createFakeImport { moduleName, moduleAlias, exposingList } =
declarationListVisitor : List (Node Declaration) -> InnerModuleContext -> InnerModuleContext declarationListVisitor : List (Node Declaration) -> InnerModuleContext -> InnerModuleContext
declarationListVisitor declarations innerContext = declarationListVisitor declarations innerContext =
List.foldl registerDeclaration innerContext declarations List.foldl registerDeclaration innerContext declarations
|> (\newInnerContext -> List.foldl registerExposed newInnerContext declarations)
registerDeclaration : Node Declaration -> InnerModuleContext -> InnerModuleContext registerDeclaration : Node Declaration -> InnerModuleContext -> InnerModuleContext
@ -388,6 +445,79 @@ declarationNameNode (Node _ declaration) =
Nothing Nothing
registerExposed : Node Declaration -> InnerModuleContext -> InnerModuleContext
registerExposed declaration innerContext =
case Node.value declaration of
Declaration.FunctionDeclaration function ->
let
name : String
name =
function.declaration
|> Node.value
|> .name
|> Node.value
in
{ innerContext
| exposedValues =
{ name = name
, comment = ""
, tipe = convertTypeSignatureToDocsType function.signature
}
:: innerContext.exposedValues
}
Declaration.CustomTypeDeclaration type_ ->
innerContext
Declaration.AliasDeclaration alias_ ->
innerContext
Declaration.PortDeclaration port_ ->
innerContext
Declaration.InfixDeclaration _ ->
innerContext
Declaration.Destructuring _ _ ->
innerContext
convertTypeSignatureToDocsType : Maybe (Node Signature) -> Elm.Type.Type
convertTypeSignatureToDocsType maybeSignature =
case maybeSignature |> Maybe.map (Node.value >> .typeAnnotation) of
Just typeAnnotation ->
syntaxTypeAnnotationToDocsType typeAnnotation
Nothing ->
Elm.Type.Tuple []
syntaxTypeAnnotationToDocsType : Node TypeAnnotation -> Elm.Type.Type
syntaxTypeAnnotationToDocsType (Node _ typeAnnotation) =
case typeAnnotation of
TypeAnnotation.GenericType name ->
Elm.Type.Var name
TypeAnnotation.Typed (Node _ ( moduleName, typeName )) typeParameters ->
-- Elm.Type.Type (String.join "." moduleName ++ "." ++ typeName) (List.map syntaxTypeAnnotationToDocsType typeParameters)
Elm.Type.Tuple []
TypeAnnotation.Unit ->
Elm.Type.Tuple []
TypeAnnotation.Tupled typeAnnotationTypeAnnotationSyntaxElmNodeNodeSyntaxElmListList ->
Elm.Type.Tuple []
TypeAnnotation.Record recordDefinitionTypeAnnotationSyntaxElm ->
Elm.Type.Tuple []
TypeAnnotation.GenericRecord stringStringNodeNodeSyntaxElm recordDefinitionTypeAnnotationSyntaxElmNodeNodeSyntaxElm ->
Elm.Type.Tuple []
TypeAnnotation.FunctionTypeAnnotation typeAnnotationTypeAnnotationSyntaxElmNodeNodeSyntaxElm typeAnnotationTypeAnnotationSyntaxElmNodeNodeSyntaxElm2 ->
Elm.Type.Tuple []
registerVariable : VariableInfo -> String -> Nonempty Scope -> Nonempty Scope registerVariable : VariableInfo -> String -> Nonempty Scope -> Nonempty Scope
registerVariable variableInfo name scopes = registerVariable variableInfo name scopes =
NonemptyList.mapHead NonemptyList.mapHead
@ -400,11 +530,52 @@ updateScope context scopes =
{ context | scopes = scopes } { context | scopes = scopes }
-- MODULE DEFINITION VISITOR
moduleDefinitionVisitor : Node Module -> InnerModuleContext -> InnerModuleContext
moduleDefinitionVisitor node innerContext =
case Module.exposingList (Node.value node) of
Exposing.All _ ->
{ innerContext | exposesEverything = True }
Exposing.Explicit list ->
{ innerContext | exposedNames = exposedElements list }
exposedElements : List (Node Exposing.TopLevelExpose) -> Dict String { range : Range, exposedElement : ExposedElement }
exposedElements nodes =
nodes
|> List.filterMap
(\node ->
case Node.value node of
Exposing.FunctionExpose name ->
Just <| ( name, { range = Node.range node, exposedElement = Function } )
Exposing.TypeOrAliasExpose name ->
-- TODO
Nothing
Exposing.TypeExpose { name } ->
-- TODO
Nothing
Exposing.InfixExpose name ->
Nothing
)
|> Dict.fromList
-- IMPORT VISITOR
importVisitor : Node Import -> InnerModuleContext -> InnerModuleContext importVisitor : Node Import -> InnerModuleContext -> InnerModuleContext
importVisitor (Node range import_) innerContext = importVisitor (Node range import_) innerContext =
innerContext innerContext
|> registerImportAlias import_ |> registerImportAlias import_
|> registerExposed import_ |> registerImportExposed import_
registerImportAlias : Import -> InnerModuleContext -> InnerModuleContext registerImportAlias : Import -> InnerModuleContext -> InnerModuleContext
@ -423,8 +594,8 @@ registerImportAlias import_ innerContext =
} }
registerExposed : Import -> InnerModuleContext -> InnerModuleContext registerImportExposed : Import -> InnerModuleContext -> InnerModuleContext
registerExposed import_ innerContext = registerImportExposed import_ innerContext =
case import_.exposingList |> Maybe.map Node.value of case import_.exposingList |> Maybe.map Node.value of
Nothing -> Nothing ->
innerContext innerContext
@ -437,7 +608,13 @@ registerExposed import_ innerContext =
module_ : Elm.Docs.Module module_ : Elm.Docs.Module
module_ = module_ =
Dict.get (getModuleName moduleName) innerContext.dependencies (case Dict.get (getModuleName moduleName) innerContext.dependencies of
Just m ->
Just m
Nothing ->
Dict.get moduleName innerContext.modules
)
|> Maybe.withDefault |> Maybe.withDefault
{ name = getModuleName moduleName { name = getModuleName moduleName
, comment = "" , comment = ""

View File

@ -159,7 +159,7 @@ rule =
} }
, fromModuleToGlobal = , fromModuleToGlobal =
\fileKey moduleNameNode moduleContext -> \fileKey moduleNameNode moduleContext ->
{ scope = Scope.fromModuleToGlobal moduleContext.scope { scope = Scope.fromModuleToGlobal moduleNameNode moduleContext.scope
} }
, foldGlobalContexts = \a b -> { scope = Scope.foldGlobalContexts a.scope b.scope } , foldGlobalContexts = \a b -> { scope = Scope.foldGlobalContexts a.scope b.scope }
} }