diff --git a/src/Analyser.elm b/src/Analyser.elm index cfbf8e7b..1706f580 100644 --- a/src/Analyser.elm +++ b/src/Analyser.elm @@ -4,6 +4,7 @@ import Analyser.CodeBase as CodeBase exposing (CodeBase) import Analyser.Configuration as Configuration exposing (Configuration) import Analyser.ContextLoader as ContextLoader exposing (Context) import Analyser.DependencyLoadingStage as DependencyLoadingStage +import Analyser.FileContext as FileContext exposing (FileContext) import Analyser.FileWatch as FileWatch exposing (FileChange(..)) import Analyser.Files.Types exposing (LoadedSourceFile) import Analyser.Fixer as Fixer @@ -18,6 +19,7 @@ import Elm.Version import Inspection import Json.Decode import Json.Encode exposing (Value) +import Maybe.Extra as Maybe import Platform exposing (worker) import Registry exposing (Registry) import Time @@ -45,6 +47,7 @@ type Msg | ReloadTick | Reset | OnFixMessage Int + | OnQuickFixMessage Int | FixerMsg Fixer.Msg @@ -141,6 +144,38 @@ update msg model = ) |> handleNextStep + OnQuickFixMessage messageId -> + let + applyFix message = + getFileContext message.file.path model.codeBase + |> Maybe.map (Fixer.getFixedFile message) + |> Maybe.withDefault + (Err ("Unable to fix messageId: " ++ String.fromInt messageId)) + in + case State.getMessage messageId model.state of + Just message -> + case applyFix message of + Ok fixedFile -> + ( model + , AnalyserPorts.sendFixedFile + { path = message.file.path + , content = fixedFile + } + ) + + Err err -> + ( model + , Logger.error err + ) + + Nothing -> + ( model + , Logger.info + ("Unable to apply fix, unable to find messageId: " + ++ String.fromInt messageId + ) + ) + Reset -> reset ( model, Cmd.none ) @@ -408,6 +443,14 @@ onSourceLoadingStageMsg x stage model = ) +getFileContext : String -> CodeBase -> Maybe FileContext +getFileContext path codeBase = + CodeBase.getFile path codeBase + |> Maybe.map + (FileContext.buildForFile (CodeBase.processContext codeBase)) + |> Maybe.join + + subscriptions : Model -> Sub Msg subscriptions model = Sub.batch @@ -419,6 +462,7 @@ subscriptions model = Sub.none , FileWatch.watcher Change , AnalyserPorts.onFixMessage OnFixMessage + , AnalyserPorts.onFixQuick OnQuickFixMessage , case model.stage of ContextLoadingStage -> ContextLoader.onLoadedContext OnContext diff --git a/src/Analyser/CodeBase.elm b/src/Analyser/CodeBase.elm index bd51d182..d03a2410 100644 --- a/src/Analyser/CodeBase.elm +++ b/src/Analyser/CodeBase.elm @@ -1,4 +1,4 @@ -module Analyser.CodeBase exposing (CodeBase, addSourceFiles, dependencies, init, mergeLoadedSourceFiles, processContext, setDependencies, sourceFiles) +module Analyser.CodeBase exposing (CodeBase, addSourceFiles, dependencies, getFile, init, mergeLoadedSourceFiles, processContext, setDependencies, sourceFiles) import Analyser.Files.Types exposing (LoadedSourceFile) import Dict exposing (Dict) @@ -62,3 +62,8 @@ addSourceFiles sources (CodeBase codeBase) = mergeLoadedSourceFiles : List LoadedSourceFile -> Dict String LoadedSourceFile -> Dict String LoadedSourceFile mergeLoadedSourceFiles newItems dict = List.foldl (\sourceFile -> Dict.insert (Tuple.first sourceFile).path sourceFile) dict newItems + + +getFile : String -> CodeBase -> Maybe LoadedSourceFile +getFile path (CodeBase codeBase) = + Dict.get path codeBase.sources diff --git a/src/Analyser/FileContext.elm b/src/Analyser/FileContext.elm index 0e74db05..2cb75c2d 100644 --- a/src/Analyser/FileContext.elm +++ b/src/Analyser/FileContext.elm @@ -1,4 +1,4 @@ -module Analyser.FileContext exposing (FileContext, build, moduleName) +module Analyser.FileContext exposing (FileContext, build, buildForFile, moduleName) import Analyser.CodeBase as CodeBase exposing (CodeBase) import Analyser.FileRef exposing (FileRef) diff --git a/src/Analyser/Fixer.elm b/src/Analyser/Fixer.elm index 35ca35a7..e6b4da37 100644 --- a/src/Analyser/Fixer.elm +++ b/src/Analyser/Fixer.elm @@ -1,6 +1,7 @@ -port module Analyser.Fixer exposing (Model, Msg, init, initWithMessage, isDone, message, subscriptions, succeeded, update) +port module Analyser.Fixer exposing (Model, Msg, getFixedFile, init, initWithMessage, isDone, message, subscriptions, succeeded, update) import Analyser.CodeBase as CodeBase exposing (CodeBase) +import Analyser.FileContext exposing (FileContext) import Analyser.FileRef exposing (FileRef) import Analyser.Fixers import Analyser.Fixes.Base exposing (Fixer, Patch(..)) @@ -71,6 +72,24 @@ initWithMessage mess state = ) +getFixedFile : Message -> FileContext -> Result String String +getFixedFile mess fileContext = + Analyser.Fixers.getFixer mess + |> Maybe.map + (\fixer -> + case fixer.fix ( fileContext.content, fileContext.ast ) mess.data of + Error e -> + Err e + + Patched p -> + Ok p + + IncompatibleData -> + Err ("Invalid message data for fixer, message id: " ++ String.fromInt mess.id) + ) + |> Maybe.withDefault (Err "Unable to find fixer") + + isDone : Model -> Bool isDone (Model m) = m.done diff --git a/src/AnalyserPorts.elm b/src/AnalyserPorts.elm index d4ba0093..a0c441a8 100644 --- a/src/AnalyserPorts.elm +++ b/src/AnalyserPorts.elm @@ -1,4 +1,4 @@ -port module AnalyserPorts exposing (onFixMessage, onReset, sendReport, sendStateValue) +port module AnalyserPorts exposing (onFixMessage, onFixQuick, onReset, sendFixedFile, sendReport, sendStateValue) import Analyser.Report as Report exposing (Report) import Analyser.State exposing (State, encodeState) @@ -11,12 +11,18 @@ port sendReportValue : Value -> Cmd msg port sendState : Value -> Cmd msg +port sendFixedFile : { path : String, content : String } -> Cmd msg + + port onReset : (Bool -> msg) -> Sub msg port onFixMessage : (Int -> msg) -> Sub msg +port onFixQuick : (Int -> msg) -> Sub msg + + sendReport : Report -> Cmd msg sendReport = sendReportValue << Report.encode diff --git a/ts/domain.ts b/ts/domain.ts index 3c673cca..00eb1e12 100644 --- a/ts/domain.ts +++ b/ts/domain.ts @@ -42,6 +42,10 @@ export interface AstStore { sha1: string; ast: JSON; } +export interface FixedFile { + path: string; + content: string; +} export interface LogMessage { level: string; @@ -52,6 +56,7 @@ interface ElmApp { log: Subscription; sendReportValue: Subscription; sendState: Subscription; + sendFixedFile: Subscription; loadContext: Subscription; loadDependencyFiles: Subscription; loadFile: Subscription; @@ -65,6 +70,7 @@ interface ElmApp { fileWatch: MailBox; onReset: MailBox; onFixMessage: MailBox; + onFixQuick: MailBox; onLoadedContext: MailBox; onDependencyFiles: MailBox; fileContent: MailBox; @@ -99,7 +105,8 @@ interface EditorElmApp { } interface Subscription { - subscribe: ((cb: ((d: T) => void)) => void); + subscribe: (cb: (d: T) => void) => void; + unsubscribe: (cb: (d: T) => void) => void; } interface FileContentSha { @@ -116,7 +123,7 @@ interface Context { configuration: string; } interface MailBox { - send: ((d: T) => void); + send: (d: T) => void; } interface Reporter {