Stabel

Check-in [8d4e3a7233]
Login
Overview
Comment:Detect required modules from type definitions, type signatures and type matches.
Timelines: family | ancestors | descendants | both | module-definition
Files: files | file ages | folders
SHA3-256: 8d4e3a723347d2ee25f9ed0aaac78c6a30b9132d482e2203e8289b8f06666f9a
User & Date: robin.hansen on 2021-05-26 17:53:27
Other Links: branch diff | manifest | tags
Context
2021-05-26
18:26
Add 'exposed' field to qualified ast types. check-in: a093546b3d user: robin.hansen tags: module-definition
17:53
Detect required modules from type definitions, type signatures and type matches. check-in: 8d4e3a7233 user: robin.hansen tags: module-definition
09:43
Imported types are now qualified when used in type match. check-in: 655d66871f user: robin.hansen tags: module-definition
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified src/Play/Qualifier.elm from [f67fc10ec5] to [001144993a].

1155
1156
1157
1158
1159
1160
1161






1162
1163
1164
1165
1166
1167
1168
....
1182
1183
1184
1185
1186
1187
1188

1189
1190
1191















1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
































1205
1206
1207
1208
1209
1210
1211
....
1215
1216
1217
1218
1219
1220
1221


1222
1223













1224
1225
1226
1227
1228
1229
1230
                    def.imports
                        |> Dict.keys
                        |> Set.fromList

                Parser.Undefined ->
                    Set.empty







        wordRequirements =
            config.ast.words
                |> Dict.foldl
                    (\_ w acc -> Set.union (requiredModulesOfWord topLevelAliases w) acc)
                    Set.empty

        fullyQualify mod acc =
................................................................................
                        acc

            else
                Set.insert (qualifyPackageModule config.packageName mod) acc
    in
    topLevelAliasTargets
        |> Set.union topLevelImports

        |> Set.union wordRequirements
        |> Set.foldl fullyQualify Set.empty

















requiredModulesOfWord : Dict String String -> Parser.WordDefinition -> Set String
requiredModulesOfWord topLevelAliases word =
    let
        wordAliases =
            word.aliases
                |> Dict.values
                |> Set.fromList

        wordImports =
            word.imports
                |> Dict.keys
                |> Set.fromList

































        impls =
            case word.implementation of
                Parser.SoloImpl impl ->
                    [ impl ]

                Parser.MultiImpl branches impl ->
................................................................................
            impls
                |> List.concat
                |> List.filterMap (extractModuleReferenceFromNode topLevelAliases word)
                |> Set.fromList
    in
    wordAliases
        |> Set.union wordImports


        |> Set.union wordReferences















extractModuleReferenceFromNode : Dict String String -> Parser.WordDefinition -> Parser.AstNode -> Maybe String
extractModuleReferenceFromNode topLevelAliases meta node =
    case node of
        Parser.PackageWord _ [ potentialAlias ] _ ->
            case
                ( Dict.get potentialAlias topLevelAliases







>
>
>
>
>
>







 







>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>


>
>
>
>
>
>
>
>
>
>
>
>
>







1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
....
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
....
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
                    def.imports
                        |> Dict.keys
                        |> Set.fromList

                Parser.Undefined ->
                    Set.empty

        typeRequirements =
            config.ast.types
                |> Dict.foldl
                    (\_ t acc -> Set.union (requiredModulesOfType t) acc)
                    Set.empty

        wordRequirements =
            config.ast.words
                |> Dict.foldl
                    (\_ w acc -> Set.union (requiredModulesOfWord topLevelAliases w) acc)
                    Set.empty

        fullyQualify mod acc =
................................................................................
                        acc

            else
                Set.insert (qualifyPackageModule config.packageName mod) acc
    in
    topLevelAliasTargets
        |> Set.union topLevelImports
        |> Set.union typeRequirements
        |> Set.union wordRequirements
        |> Set.foldl fullyQualify Set.empty


requiredModulesOfType : Parser.TypeDefinition -> Set String
requiredModulesOfType typeDef =
    case typeDef of
        Parser.CustomTypeDef _ _ _ members ->
            members
                |> List.map Tuple.second
                |> List.filterMap extractModuleReferenceFromType
                |> Set.fromList

        Parser.UnionTypeDef _ _ _ members ->
            members
                |> List.filterMap extractModuleReferenceFromType
                |> Set.fromList


requiredModulesOfWord : Dict String String -> Parser.WordDefinition -> Set String
requiredModulesOfWord topLevelAliases word =
    let
        wordAliases =
            word.aliases
                |> Dict.values
                |> Set.fromList

        wordImports =
            word.imports
                |> Dict.keys
                |> Set.fromList

        typeSignature =
            case word.typeSignature of
                Parser.NotProvided ->
                    Set.empty

                Parser.UserProvided wordType ->
                    moduleReferenceFromWordType wordType

                Parser.Verified wordType ->
                    moduleReferenceFromWordType wordType

        moduleReferenceFromWordType wordType =
            wordType.input
                ++ wordType.output
                |> List.filterMap extractModuleReferenceFromType
                |> Set.fromList

        matches =
            case word.implementation of
                Parser.SoloImpl _ ->
                    Set.empty

                Parser.MultiImpl branches _ ->
                    branches
                        |> List.map Tuple.first
                        |> List.map extractMatchType
                        |> List.filterMap extractModuleReferenceFromType
                        |> Set.fromList

        extractMatchType (Parser.TypeMatch _ tipe _) =
            tipe

        impls =
            case word.implementation of
                Parser.SoloImpl impl ->
                    [ impl ]

                Parser.MultiImpl branches impl ->
................................................................................
            impls
                |> List.concat
                |> List.filterMap (extractModuleReferenceFromNode topLevelAliases word)
                |> Set.fromList
    in
    wordAliases
        |> Set.union wordImports
        |> Set.union typeSignature
        |> Set.union matches
        |> Set.union wordReferences


extractModuleReferenceFromType : Parser.PossiblyQualifiedType -> Maybe String
extractModuleReferenceFromType ref =
    case ref of
        Parser.ExternalRef path _ _ ->
            Just <| "/" ++ String.join "/" path

        Parser.InternalRef path _ _ ->
            Just <| String.join "/" path

        _ ->
            Nothing


extractModuleReferenceFromNode : Dict String String -> Parser.WordDefinition -> Parser.AstNode -> Maybe String
extractModuleReferenceFromNode topLevelAliases meta node =
    case node of
        Parser.PackageWord _ [ potentialAlias ] _ ->
            case
                ( Dict.get potentialAlias topLevelAliases

Modified tests/Test/Qualifier.elm from [fdc23db8aa] to [bfbd7c2c30].

1085
1086
1087
1088
1089
1090
1091
1092








1093
1094
1095
1096




1097
1098
1099
1100
1101
1102
1103
1104



1105
1106
1107
1108
1109
1110
1111
....
1124
1125
1126
1127
1128
1129
1130


1131


1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144


1145
1146
1147
1148
1149
1150
1151
                                    Dict.fromList
                                        [ ( "html", "/external/html" ) ]
                                , imports =
                                    Dict.fromList
                                        [ ( "/external/module", [] ) ]
                                , exposes = Set.fromList []
                                }
                        , types = Dict.empty








                        , words =
                            Dict.fromListBy .name
                                [ { name = "call-external"
                                  , typeSignature = AST.NotProvided




                                  , sourceLocationRange = Nothing
                                  , aliases = Dict.empty
                                  , imports = Dict.empty
                                  , implementation =
                                        AST.MultiImpl
                                            [ ( AST.TypeMatch emptyRange (AST.LocalRef "Int" []) [ ( "value", AST.LiteralInt 1 ) ]
                                              , [ AST.PackageWord emptyRange [ "package", "module" ] "when-one"
                                                ]



                                              )
                                            ]
                                            [ AST.PackageWord emptyRange [ "package", "module" ] "when-other-one" ]
                                  }
                                , { name = "main"
                                  , typeSignature = AST.NotProvided
                                  , sourceLocationRange = Nothing
................................................................................

                    expectedRequiredModules =
                        Set.fromList
                            [ "/robheghan/dummy/list/of/names"
                            , "/robheghan/dummy/some/ext"
                            , "/robheghan/html/external/html"
                            , "/robheghan/html/external/module"


                            , "/package/test/internal/alias"


                            , "/package/test/package/module"
                            ]

                    actualRequiredModules =
                        requiredModules
                            { packageName = "package/test"
                            , ast = unqualifiedAst
                            , externalModules =
                                Dict.fromList
                                    [ ( "/list/of/names", "robheghan/dummy" )
                                    , ( "/some/ext", "robheghan/dummy" )
                                    , ( "/external/html", "robheghan/html" )
                                    , ( "/external/module", "robheghan/html" )


                                    ]
                            }
                in
                Expect.equal expectedRequiredModules actualRequiredModules
        , describe "Module resolution" <|
            let
                dummyWord name =







|
>
>
>
>
>
>
>
>



|
>
>
>
>








>
>
>







 







>
>

>
>













>
>







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
....
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
                                    Dict.fromList
                                        [ ( "html", "/external/html" ) ]
                                , imports =
                                    Dict.fromList
                                        [ ( "/external/module", [] ) ]
                                , exposes = Set.fromList []
                                }
                        , types =
                            Dict.fromList
                                [ ( "Tipe"
                                  , AST.CustomTypeDef emptyRange
                                        "Tipe"
                                        []
                                        [ ( "value", AST.ExternalRef [ "external", "double" ] "Tipe" [] ) ]
                                  )
                                ]
                        , words =
                            Dict.fromListBy .name
                                [ { name = "call-external"
                                  , typeSignature =
                                        AST.UserProvided
                                            { input = [ AST.InternalRef [ "internal", "types" ] "In" [] ]
                                            , output = [ AST.ExternalRef [ "external", "types" ] "Out" [] ]
                                            }
                                  , sourceLocationRange = Nothing
                                  , aliases = Dict.empty
                                  , imports = Dict.empty
                                  , implementation =
                                        AST.MultiImpl
                                            [ ( AST.TypeMatch emptyRange (AST.LocalRef "Int" []) [ ( "value", AST.LiteralInt 1 ) ]
                                              , [ AST.PackageWord emptyRange [ "package", "module" ] "when-one"
                                                ]
                                              )
                                            , ( AST.TypeMatch emptyRange (AST.InternalRef [ "internal", "match" ] "Some" []) []
                                              , [ AST.Word emptyRange "drop" ]
                                              )
                                            ]
                                            [ AST.PackageWord emptyRange [ "package", "module" ] "when-other-one" ]
                                  }
                                , { name = "main"
                                  , typeSignature = AST.NotProvided
                                  , sourceLocationRange = Nothing
................................................................................

                    expectedRequiredModules =
                        Set.fromList
                            [ "/robheghan/dummy/list/of/names"
                            , "/robheghan/dummy/some/ext"
                            , "/robheghan/html/external/html"
                            , "/robheghan/html/external/module"
                            , "/robheghan/html/external/types"
                            , "/robheghan/html/external/double"
                            , "/package/test/internal/alias"
                            , "/package/test/internal/types"
                            , "/package/test/internal/match"
                            , "/package/test/package/module"
                            ]

                    actualRequiredModules =
                        requiredModules
                            { packageName = "package/test"
                            , ast = unqualifiedAst
                            , externalModules =
                                Dict.fromList
                                    [ ( "/list/of/names", "robheghan/dummy" )
                                    , ( "/some/ext", "robheghan/dummy" )
                                    , ( "/external/html", "robheghan/html" )
                                    , ( "/external/module", "robheghan/html" )
                                    , ( "/external/types", "robheghan/html" )
                                    , ( "/external/double", "robheghan/html" )
                                    ]
                            }
                in
                Expect.equal expectedRequiredModules actualRequiredModules
        , describe "Module resolution" <|
            let
                dummyWord name =