diff --git a/preview/src/ReviewConfig.elm b/preview/src/ReviewConfig.elm index 18427fb..220a541 100644 --- a/preview/src/ReviewConfig.elm +++ b/preview/src/ReviewConfig.elm @@ -26,16 +26,17 @@ import Review.Rule exposing (Rule) import String.Extra - -config = configMagicLinkAuth "Jim Carlson" "jxxcarlson" "jxxcarlson@gmail.com" +config = + configMagicLinkAuth "Jim Carlson" "jxxcarlson" "jxxcarlson@gmail.com" configMagicLinkAuth fullname username email = - configAll {fullname = fullname, username = username, email = email } + configAll { fullname = fullname, username = username, email = email } + stringifyAdminConfig : { fullname : String, username : String, email : String } -> String stringifyAdminConfig { fullname, username, email } = - "{ fullname = " ++ String.Extra.quote fullname ++ ", username = " ++ String.Extra.quote username ++ ", email = " ++ String.Extra.quote email ++"}" + "{ fullname = " ++ String.Extra.quote fullname ++ ", username = " ++ String.Extra.quote username ++ ", email = " ++ String.Extra.quote email ++ "}" configAll : { fullname : String, username : String, email : String } -> List Rule @@ -199,7 +200,7 @@ configAuthFrontend = configAuthBackend : { fullname : String, username : String, email : String } -> List Rule -configAuthBackend adminConfig= +configAuthBackend adminConfig = [ ClauseInCase.config "Backend" "update" "AuthBackendMsg authMsg" "Auth.Flow.backendUpdate (MagicLink.Auth.backendConfig model) authMsg" |> ClauseInCase.makeRule , ClauseInCase.config "Backend" "update" "AutoLogin sessionId loginData" "( model, Lamdera.sendToFrontend sessionId (AuthToFrontend <| Auth.Common.AuthSignInWithTokenResponse <| Ok <| loginData) )" |> ClauseInCase.makeRule , ClauseInCase.config "Backend" "update" "OnConnected sessionId clientId" "( model, Reconnect.connect model sessionId clientId )" |> ClauseInCase.makeRule @@ -238,7 +239,6 @@ configAuthBackend adminConfig= ] - configRoute : List Rule configRoute = [ -- ROUTE diff --git a/review/elm.json b/review/elm.json index 9556325..2fd6128 100644 --- a/review/elm.json +++ b/review/elm.json @@ -10,6 +10,7 @@ "elm/json": "1.1.3", "elm/project-metadata-utils": "1.0.2", "jfmengels/elm-review": "2.14.0", + "jfmengels/elm-review-common": "1.3.3", "jfmengels/elm-review-debug": "1.0.8", "jfmengels/elm-review-documentation": "2.0.4", "jfmengels/elm-review-unused": "1.2.3", @@ -17,15 +18,21 @@ "stil4m/elm-syntax": "7.3.2" }, "indirect": { + "BrianHicks/elm-trend": "2.1.3", + "elm/browser": "1.0.2", "elm/bytes": "1.0.8", "elm/html": "1.0.0", "elm/parser": "1.1.0", "elm/random": "1.0.0", "elm/regex": "1.0.0", "elm/time": "1.0.0", + "elm/url": "1.0.0", "elm/virtual-dom": "1.0.3", + "elm-explorations/benchmark": "1.0.2", "elm-explorations/test": "2.2.0", + "mdgriffith/style-elements": "5.0.2", "miniBill/elm-unicode": "1.1.1", + "robinheghan/murmur3": "1.0.0", "rtfeldman/elm-hex": "1.0.0", "stil4m/structured-writer": "1.0.3" } diff --git a/review/src/ReviewConfig.elm b/review/src/ReviewConfig.elm index 37de5bb..81c60ed 100644 --- a/review/src/ReviewConfig.elm +++ b/review/src/ReviewConfig.elm @@ -1,11 +1,12 @@ module ReviewConfig exposing (config) -import NoDebug.Log import Docs.NoMissing exposing (exposedModules, onlyExposed) import Docs.ReviewAtDocs import Docs.ReviewLinksAndSections import Docs.UpToDateReadmeLinks +import NoDebug.Log import NoDebug.TodoOrToString +import NoPrematureLetComputation import NoUnused.Dependencies import NoUnused.Variables import Review.Rule exposing (Rule) @@ -20,4 +21,5 @@ config = } , Docs.ReviewLinksAndSections.rule , Docs.ReviewAtDocs.rule + , NoPrematureLetComputation.rule ] diff --git a/src/Install/ClauseInCase.elm b/src/Install/ClauseInCase.elm index 4cd6b8f..8b7cad9 100644 --- a/src/Install/ClauseInCase.elm +++ b/src/Install/ClauseInCase.elm @@ -1,4 +1,8 @@ -module Install.ClauseInCase exposing (config, makeRule, withInsertAfter, withInsertAtBeginning, withCustomErrorMessage, Config, CustomError) +module Install.ClauseInCase exposing + ( Config, config, makeRule + , withInsertAfter, withInsertAtBeginning + , withCustomErrorMessage, CustomError + ) {-| Add a clause to a case expression in a specified function in a specified module. For example, if you put the code below in your @@ -6,10 +10,14 @@ in a specified module. For example, if you put the code below in your `ResetCounter` to the `updateFromFrontend` function in the `Backend` module. -- code for ReviewConfig.elm: - Install.ClauseInCase.config "Backend" "updateFromFrontend" "ResetCounter" "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" + Install.ClauseInCase.config + "Backend" + "updateFromFrontend" + "ResetCounter" + "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" |> Install.ClauseInCase.makeRule - Thus we will have +Thus we will have updateFromFrontend : SessionId -> ClientId -> ToBackend -> Model -> ( Model, Cmd BackendMsg ) updateFromFrontend sessionId clientId msg model = @@ -21,28 +29,14 @@ in a specified module. For example, if you put the code below in your ResetCounter -> ( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) ) - You also can add the clause after another clause of choice with the `withInsertAfter` function: - Install.ClauseInCase.config "Backend" "updateFromFrontend" "ResetCounter" "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" - |> Install.ClauseInCase.withInsertAfter "CounterIncremented" - |> Install.ClauseInCase.makeRule - - In this case we will have - updateFromFrontend : SessionId -> ClientId -> ToBackend -> Model -> ( Model, Cmd BackendMsg ) - updateFromFrontend sessionId clientId msg model = - case msg of - CounterIncremented -> - ... - ResetCounter -> - ( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) ) - - CounterDecremented -> - ... - You can also customize the error message with the `withCustomErrorMessage` function: - Install.ClauseInCase.config "Backend" "updateFromFrontend" "ResetCounter" "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" - |> Install.ClauseInCase.withCustomErrorMessage "Add handler for ResetCounter" [] - |> Install.ClauseInCase.makeRule - -@docs config, makeRule, withInsertAfter, withInsertAtBeginning, withCustomErrorMessage, Config, CustomError + ... + +@docs Config, config, makeRule + +By default, the clause will be inserted as the last clause. You can change the insertion location using the following functions: + +@docs withInsertAfter, withInsertAtBeginning +@docs withCustomErrorMessage, CustomError -} @@ -57,10 +51,9 @@ import List.Extra import Maybe.Extra import Review.Fix as Fix exposing (Fix) import Review.Rule as Rule exposing (Error, Rule) -import String.Extra -{-| Configuration for makeRule: add a clause to a case expression in a specified function in a specified module. +{-| Configuration for rule: add a clause to a case expression in a specified function in a specified module. -} type Config = Config @@ -87,9 +80,14 @@ type CustomError {-| Basic config to add a new clause to a case expression. If you just need to add a new clause at the end of the case, you can simply use it with the `makeRule` function like this: - Install.ClauseInCase.config "Backend" "updateFromFrontend" "ResetCounter" "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" + Install.ClauseInCase.config + "Backend" + "updateFromFrontend" + "ResetCounter" + "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" |> Install.ClauseInCase.makeRule - If you need additional configuration, check the `withInsertAfter` and `withCustomErrorMessage` functions. + +If you need additional configuration, check the `withInsertAfter` and `withCustomErrorMessage` functions. -} config : String -> String -> String -> String -> Config @@ -104,9 +102,13 @@ config moduleName functionName clause functionCall = } -{-| Create a makeRule that adds a clause to a case expression in a specified function. You can use it like this: +{-| Create a rule that adds a clause to a case expression in a specified function. You can use it like this: - Install.ClauseInCase.config "Backend" "updateFromFrontend" "ResetCounter" "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" + Install.ClauseInCase.config + "Backend" + "updateFromFrontend" + "ResetCounter" + "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" |> Install.ClauseInCase.makeRule -} @@ -151,12 +153,13 @@ declarationVisitor (Node _ declaration) moduleName functionName clause functionC isInCorrectModule = Install.Library.isInCorrectModule moduleName context - - functionDeclaration : FunctionImplementation - functionDeclaration = - Node.value function.declaration in if name == functionName && isInCorrectModule then + let + functionDeclaration : FunctionImplementation + functionDeclaration = + Node.value function.declaration + in visitFunction clause functionCall functionDeclaration.expression insertAt customError context else @@ -197,12 +200,12 @@ visitFunction clause functionCall expressionNode insertAt customError context = List.any (\pattern -> Install.Library.patternToString (Node.empty pattern) == clause_) (getPatterns cases_) - - isClauseStringPattern = - List.any isStringPattern (getPatterns allCases) in if not (findClause clause allCases) then let + isClauseStringPattern = + List.any isStringPattern (getPatterns allCases) + rangeToInsert : Maybe ( Range, Int, Int ) rangeToInsert = rangeToInsertClause insertAt isClauseStringPattern allCases patternMatchNode |> Just @@ -359,7 +362,11 @@ Given the following module: To add the clause `Aspasia` after the clause `Aristotle`, you can use the following configuration: - Install.ClauseInCase.config "Philosopher" "stringToPhilosopher" "Aspasia" "Just Aspasia" + Install.ClauseInCase.config + "Philosopher" + "stringToPhilosopher" + "Aspasia" + "Just Aspasia" |> Install.ClauseInCase.withInsertAfter "Aristotle" |> Install.ClauseInCase.makeRule @@ -393,6 +400,31 @@ withInsertAfter clauseToInsertAfter (Config config_) = {-| Add a clause at the beginning of the case expression. + +You also can add the clause after another clause of choice with the `withInsertAfter` function: + + Install.ClauseInCase.config + "Backend" + "updateFromFrontend" + "ResetCounter" + "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" + |> Install.ClauseInCase.withInsertAtBeginning + |> Install.ClauseInCase.makeRule + +In this case we will have + + updateFromFrontend : SessionId -> ClientId -> ToBackend -> Model -> ( Model, Cmd BackendMsg ) + updateFromFrontend sessionId clientId msg model = + case msg of + ResetCounter -> + ( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) ) + + CounterIncremented -> + ... + + CounterDecremented -> + ... + -} withInsertAtBeginning : Config -> Config withInsertAtBeginning (Config config_) = @@ -402,7 +434,16 @@ withInsertAtBeginning (Config config_) = } -{-| Customize the error message that will be displayed when running `elm-review --fix` or `elm-review --fix-all` +{-| Customize the error message that will be displayed when running `elm-review --fix` or `elm-review --fix-all`. + + Install.ClauseInCase.config + "Backend" + "updateFromFrontend" + "ResetCounter" + "( { model | counter = 0 }, broadcast (CounterNewValue 0 clientId) )" + |> Install.ClauseInCase.withCustomErrorMessage "Add handler for ResetCounter" [] + |> Install.ClauseInCase.makeRule + -} withCustomErrorMessage : String -> List String -> Config -> Config withCustomErrorMessage errorMessage details (Config config_) = diff --git a/src/Install/ElementToList.elm b/src/Install/ElementToList.elm index 4187d41..2a5805f 100644 --- a/src/Install/ElementToList.elm +++ b/src/Install/ElementToList.elm @@ -21,7 +21,10 @@ import String.Extra For example, the rule - Install.ElementToList.makeRule "User" "userTypes" [ "Admin", "SystemAdmin" ] + Install.ElementToList.makeRule + "User" + "userTypes" + [ "Admin", "SystemAdmin" ] results in the following fix for function `User.userTypes`: diff --git a/src/Install/FieldInTypeAlias.elm b/src/Install/FieldInTypeAlias.elm index b69b6e1..f77d904 100644 --- a/src/Install/FieldInTypeAlias.elm +++ b/src/Install/FieldInTypeAlias.elm @@ -44,14 +44,16 @@ import Set.Extra After running the rule with the following code: - Install.FieldInTypeAlias.makeRule "Types" "FrontendModel" ["clientName: String", "quot: String"] + Install.FieldInTypeAlias.makeRule "Types" "FrontendModel" [ "clientName: String", "quot: String" ] - type alias FrontendModel = - { counter : Int - , clientId : String - , clientName : String - , quot : String - } +we will have + + type alias FrontendModel = + { counter : Int + , clientId : String + , clientName : String + , quot : String + } -} makeRule : String -> String -> List String -> Rule diff --git a/src/Install/Function/InsertFunction.elm b/src/Install/Function/InsertFunction.elm index 825f991..5a15b31 100644 --- a/src/Install/Function/InsertFunction.elm +++ b/src/Install/Function/InsertFunction.elm @@ -37,7 +37,7 @@ import Review.ModuleNameLookupTable exposing (ModuleNameLookupTable) import Review.Rule as Rule exposing (Error, Rule) -{-| Configuration for makeRule: add a function in a specified module if it does not already exist. +{-| Configuration for rule: add a function in a specified module if it does not already exist. -} type Config = Config @@ -71,12 +71,12 @@ withInsertAfter previousDeclaration (Config config_) = {-| Initialize the configuration for the rule. -} config : String -> String -> String -> Config -config moduleNaeme functionName functionImplementation = +config moduleName functionName functionImplementation = Config - { moduleName = moduleNaeme + { moduleName = moduleName , functionName = functionName , functionImplementation = functionImplementation - , theFunctionNodeExpression = Install.Library.maybeNodeExpressionFromString { moduleName = String.split "." moduleNaeme } functionImplementation + , theFunctionNodeExpression = Install.Library.maybeNodeExpressionFromString { moduleName = String.split "." moduleName } functionImplementation , customErrorMessage = CustomError { message = "Add function \"" ++ functionName ++ "\".", details = [ "" ] } , insertAt = AtEnd } @@ -119,24 +119,23 @@ declarationVisitor context (Config config_) declaration = let declarationName = Install.Library.getDeclarationName declaration - - contextWithLastDeclarationRange = - case config_.insertAt of - After previousDeclaration -> - if Install.Library.getDeclarationName declaration == previousDeclaration then - { context | lastDeclarationRange = Node.range declaration } - - else - context - - AtEnd -> - { context | lastDeclarationRange = Node.range declaration } in if declarationName == config_.functionName then ( [], { context | appliedFix = True } ) else - ( [], contextWithLastDeclarationRange ) + ( [] + , case config_.insertAt of + After previousDeclaration -> + if Install.Library.getDeclarationName declaration == previousDeclaration then + { context | lastDeclarationRange = Node.range declaration } + + else + context + + AtEnd -> + { context | lastDeclarationRange = Node.range declaration } + ) finalEvaluation : Config -> Context -> List (Rule.Error {}) diff --git a/src/Install/Function/ReplaceFunction.elm b/src/Install/Function/ReplaceFunction.elm index cac2420..19533ce 100644 --- a/src/Install/Function/ReplaceFunction.elm +++ b/src/Install/Function/ReplaceFunction.elm @@ -31,15 +31,13 @@ import Elm.Syntax.Expression exposing (Expression, Function) import Elm.Syntax.ModuleName exposing (ModuleName) import Elm.Syntax.Node as Node exposing (Node) import Elm.Syntax.Range exposing (Range) -import Install.Infer as Infer import Install.Library -import Install.Normalize as Normalize import Review.Fix as Fix import Review.ModuleNameLookupTable exposing (ModuleNameLookupTable) import Review.Rule as Rule exposing (Error, Rule) -{-| Configuration for makeRule: replace a function in a specified module with a new implementation. +{-| Configuration for rule: replace a function in a specified module with a new implementation. -} type Config = Config @@ -60,12 +58,12 @@ type CustomError {-| Initialize the configuration for the rule. -} config : String -> String -> String -> Config -config moduleNaeme functionName functionImplementation = +config moduleName functionName functionImplementation = Config - { moduleName = moduleNaeme + { moduleName = moduleName , functionName = functionName , functionImplementation = functionImplementation - , theFunctionNodeExpression = Install.Library.maybeNodeExpressionFromString { moduleName = String.split "." moduleNaeme } functionImplementation + , theFunctionNodeExpression = Install.Library.maybeNodeExpressionFromString { moduleName = String.split "." moduleName } functionImplementation , customErrorMessage = CustomError { message = "Replace function \"" ++ functionName ++ "\" with new code.", details = [ "" ] } } @@ -111,9 +109,6 @@ declarationVisitor context (Config config_) declaration = isInCorrectModule = Install.Library.isInCorrectModule config_.moduleName context - resources = - { lookupTable = context.lookupTable, inferredConstants = ( Infer.empty, [] ) } - isInCorrectFunction = isInCorrectModule && name == config_.functionName diff --git a/src/Install/Import.elm b/src/Install/Import.elm index 32a6b4c..3b2ebea 100644 --- a/src/Install/Import.elm +++ b/src/Install/Import.elm @@ -4,17 +4,24 @@ module Install.Import exposing (config, ImportData, module_, withAlias, withExpo For example, to add `import Foo.Bar` to the `Frontend` module, you can use the following configuration: Install.Import.config "Frontend" - [ module_ "Foo.Bar" ] + [ Install.Import.module_ "Foo.Bar" ] |> Install.Import.makeRule To add the statement `import Foo.Bar as FB exposing (a, b, c)` to the `Frontend` module, do this: - Install.Import.config "Frontend" [ module_ "Foo.Bar" |> withAlias "FB" |> withExposedValues = [ "a", "b", "c" ] ] + Install.Import.config "Frontend" + [ Install.Import.module_ "Foo.Bar" + |> Install.Import.withAlias "FB" + |> Install.Import.withExposedValues [ "a", "b", "c" ] + ] |> Install.Import.makeRule -There is a short cut for importing modules with no alias or exposed values +There is a shortcut for importing modules with no alias or exposed values - Install.Import.qualified "Frontend" [ module_ "Foo.Bar", module_ "Baz.Qux" ] + Install.Import.qualified "Frontend" + [ Install.Import.module_ "Foo.Bar" + , Install.Import.module_ "Baz.Qux" + ] |> Install.Import.makeRule @docs config, ImportData, module_, withAlias, withExposedValues, qualified, makeRule @@ -30,10 +37,7 @@ import Review.Fix as Fix import Review.Rule as Rule exposing (Error, Rule) -{-| - - Configuration for the rule. - +{-| Configuration for the rule. -} type Config = Config diff --git a/src/Install/InitializerCmd.elm b/src/Install/InitializerCmd.elm index b6c04e4..32333e7 100644 --- a/src/Install/InitializerCmd.elm +++ b/src/Install/InitializerCmd.elm @@ -73,12 +73,13 @@ declarationVisitor moduleName functionName cmds (Node _ declaration) context = name : String name = Node.value (Node.value function.declaration).name - - namespace : String - namespace = - String.join "." context.moduleName ++ "." ++ name in if name == functionName then + let + namespace : String + namespace = + String.join "." context.moduleName ++ "." ++ name + in visitCmd namespace moduleName functionName cmds Set.empty function context else diff --git a/src/Install/Subscription.elm b/src/Install/Subscription.elm index 2d61940..257385c 100644 --- a/src/Install/Subscription.elm +++ b/src/Install/Subscription.elm @@ -23,7 +23,7 @@ import Review.Rule as Rule exposing (Error, Rule) and that you want to add `baz` to the list. To do this, say - Insall.Subscription.makeRule "Backend" [ "baz" ] + Install.Subscription.makeRule "Backend" [ "baz" ] The result is @@ -70,70 +70,57 @@ declarationVisitor moduleName items (Node _ declaration) context = implementation = Node.value function.declaration - expr = - implementation.expression - - endOfRange = - (Node.range expr).end - name : String name = Node.value implementation.name - - nameRange = - Node.range implementation.name - - data = - case Node.value implementation.expression of - Application (head :: rest) -> - Just ( head, rest ) - - _ -> - Nothing in if name /= "subscriptions" then ( [], context ) else - case data of - Nothing -> + case Node.value implementation.expression of + Application ((Node _ (FunctionOrValue [ "Sub" ] "batch")) :: rest) -> + let + listElements = + rest + |> List.head + |> Maybe.map Node.value + |> (\expression -> + case expression of + Just (ListExpr exprs) -> + exprs + + _ -> + [] + ) + + isAlreadyImplemented = + Install.Library.areItemsInList items listElements + in + if isAlreadyImplemented then + ( [], context ) + + else + let + expr = + implementation.expression + + endOfRange = + (Node.range expr).end + + nameRange = + Node.range implementation.name + + replacementCode = + items + |> List.map (\item -> ", " ++ item) + |> String.concat + in + ( [ errorWithFix replacementCode nameRange endOfRange rest ], context ) + + _ -> ( [], context ) - Just ( head, rest ) -> - case Node.value head of - FunctionOrValue [ "Sub" ] "batch" -> - let - listElements = - rest - |> List.head - |> Maybe.map Node.value - |> (\expression -> - case expression of - Just (ListExpr exprs) -> - exprs - - _ -> - [] - ) - - isAlreadyImplemented = - Install.Library.areItemsInList items listElements - in - if isAlreadyImplemented then - ( [], context ) - - else - let - replacementCode = - items - |> List.map (\item -> ", " ++ item) - |> String.concat - in - ( [ errorWithFix replacementCode nameRange endOfRange rest ], context ) - - _ -> - ( [], context ) - _ -> ( [], context ) diff --git a/src/Install/Type.elm b/src/Install/Type.elm index a759ecb..93b4180 100644 --- a/src/Install/Type.elm +++ b/src/Install/Type.elm @@ -85,12 +85,12 @@ fixError typeName_ variants_ context = declarationVisitor : String -> String -> Node Declaration -> Context -> ( List (Error {}), Context ) declarationVisitor moduleName_ typeName_ node context = - let - isInCorrectModule = - Install.Library.isInCorrectModule moduleName_ context - in case Node.value node of Declaration.CustomTypeDeclaration type_ -> + let + isInCorrectModule = + Install.Library.isInCorrectModule moduleName_ context + in if isInCorrectModule && Node.value type_.name == typeName_ then ( [], { context | typeIsPresent = True, lastNodeRange = Node.range node } ) diff --git a/src/Install/TypeVariant.elm b/src/Install/TypeVariant.elm index 7a4dde7..e4b8d3c 100644 --- a/src/Install/TypeVariant.elm +++ b/src/Install/TypeVariant.elm @@ -107,9 +107,6 @@ declarationVisitor moduleName typeName variantList node context = variantNames = List.map variantName variantList |> List.filterMap identity - variantCode = - List.map variantCodeItem variantList |> String.join "" - shouldFix : Node Declaration -> Context -> Bool shouldFix node_ context_ = let @@ -127,6 +124,10 @@ declarationVisitor moduleName typeName variantList node context = not <| Set.Extra.isSubsetOf variantsOfNode (Set.fromList variantNames) in if isInCorrectModule && Node.value type_.name == typeName && shouldFix node context then + let + variantCode = + List.map variantCodeItem variantList |> String.join "" + in ( [ errorWithFix typeName variantNames variantCode node (Just <| Node.range node) ] , context )