Created
December 11, 2023 22:34
-
-
Save pete-murphy/5ead0bbea3bd2760caf5465adf80c3f5 to your computer and use it in GitHub Desktop.
Rule for generating dependency graph, based on https://github.com/SiriusStarr/elm-review-import-graph/blob/main/src/ExtractImportGraph.elm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ExtractImportGraph exposing (rule) | |
import Dict exposing (Dict) | |
import Elm.Syntax.Import exposing (Import) | |
import Elm.Syntax.ModuleName exposing (ModuleName) | |
import Elm.Syntax.Node as Node exposing (Node) | |
import Json.Encode as Encode | |
import Review.Project.Dependency as Dependency exposing (Dependency) | |
import Review.Rule as Rule exposing (Rule) | |
import Set exposing (Set) | |
rule : Rule | |
rule = | |
Rule.newProjectRuleSchema "ExtractImportGraph" initContext | |
|> Rule.withDependenciesProjectVisitor dependencyVisitor | |
|> Rule.withModuleVisitor moduleVisitor | |
|> Rule.withModuleContextUsingContextCreator | |
{ fromProjectToModule = fromProjectToModule | |
, fromModuleToProject = fromModuleToProject | |
, foldProjectContexts = foldProjectContexts | |
} | |
|> Rule.withDataExtractor dataExtractor | |
|> Rule.fromProjectRuleSchema | |
type alias ProjectContext = | |
{ imports : Dict ModuleName (List ModuleName) | |
, dependencyModules : Set ModuleName | |
} | |
type alias ModuleContext = | |
{ imports : List ModuleName | |
, dependencyModules : Set ModuleName | |
} | |
initContext : ProjectContext | |
initContext = | |
{ imports = Dict.empty | |
, dependencyModules = Set.empty | |
} | |
dependencyVisitor : Dict String Dependency -> ProjectContext -> ( List never, ProjectContext ) | |
dependencyVisitor ds context = | |
Dict.values ds | |
|> List.concatMap Dependency.modules | |
|> List.map (String.split "." << .name) | |
|> Set.fromList | |
|> (\dModules -> ( [], { context | dependencyModules = dModules } )) | |
fromProjectToModule : Rule.ContextCreator ProjectContext ModuleContext | |
fromProjectToModule = | |
Rule.initContextCreator | |
(\projectContext -> | |
{ imports = [] | |
, dependencyModules = projectContext.dependencyModules | |
} | |
) | |
fromModuleToProject : Rule.ContextCreator ModuleContext ProjectContext | |
fromModuleToProject = | |
Rule.initContextCreator | |
(\moduleName moduleContext -> | |
{ imports = | |
if not (List.isEmpty moduleContext.imports) then | |
moduleContext.imports | |
|> List.sort | |
|> Dict.singleton moduleName | |
else | |
Dict.empty | |
, dependencyModules = moduleContext.dependencyModules | |
} | |
) | |
|> Rule.withModuleName | |
foldProjectContexts : ProjectContext -> ProjectContext -> ProjectContext | |
foldProjectContexts newContext previousContext = | |
{ imports = Dict.union newContext.imports previousContext.imports | |
, dependencyModules = previousContext.dependencyModules | |
} | |
moduleVisitor : | |
Rule.ModuleRuleSchema {} ModuleContext | |
-> Rule.ModuleRuleSchema { hasAtLeastOneVisitor : () } ModuleContext | |
moduleVisitor schema = | |
schema | |
|> Rule.withImportVisitor importVisitor | |
dataExtractor : ProjectContext -> Encode.Value | |
dataExtractor projectContext = | |
Encode.object | |
[ ( "json", Encode.dict unwrapModuleName (Encode.list (unwrapModuleName >> Encode.string)) projectContext.imports ) | |
] | |
unwrapModuleName : ModuleName -> String | |
unwrapModuleName = | |
String.join "." | |
importVisitor : Node Import -> ModuleContext -> ( List never, ModuleContext ) | |
importVisitor imp context = | |
let | |
moduleName : ModuleName | |
moduleName = | |
Node.value imp | |
|> .moduleName | |
|> Node.value | |
in | |
( [] | |
, { context | |
| imports = moduleName :: context.imports | |
} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment