From b77681d208bcdf77d9d758b98c44b6562db7e6c5 Mon Sep 17 00:00:00 2001 From: antew Date: Fri, 3 May 2019 23:08:33 -0400 Subject: [PATCH 1/6] Initial "working" version, replaces the whole file content at the moment. --- src/Analyser.elm | 51 ++++++++++++++++++++++++++++++++++++ src/Analyser/CodeBase.elm | 8 +++++- src/Analyser/FileContext.elm | 2 +- src/Analyser/Fixer.elm | 20 +++++++++++++- src/AnalyserPorts.elm | 8 +++++- ts/domain.ts | 6 +++++ 6 files changed, 91 insertions(+), 4 deletions(-) diff --git a/src/Analyser.elm b/src/Analyser.elm index cfbf8e7b..1090c763 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 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,53 @@ update msg model = ) |> handleNextStep + OnQuickFixMessage messageId -> + let + processingContext = + CodeBase.processContext model.codeBase + + maybeMessage = + State.getMessage messageId model.state + + maybeFixedFile = + case maybeMessage of + Just message -> + CodeBase.getFile message.file.path model.codeBase + |> Maybe.map + (\loadedSourceFile -> + ( .content <| Tuple.first loadedSourceFile + , FileContext.buildForFile processingContext loadedSourceFile + |> Maybe.map .ast + ) + ) + |> Maybe.map + (\sources -> + case sources of + ( Just fileText, Just ast ) -> + Just <| Fixer.fixFast message ( fileText, ast ) + + _ -> + Nothing + ) + |> Maybe.join + + Nothing -> + Nothing + in + case ( maybeMessage, maybeFixedFile ) of + ( Just message, Just (Ok fixedFile) ) -> + ( model + , AnalyserPorts.sendFixedFile + { path = message.file.path + , content = fixedFile + } + ) + + _ -> + ( model + , Logger.info ("Unable to apply fix for message id: " ++ String.fromInt messageId) + ) + Reset -> reset ( model, Cmd.none ) @@ -419,6 +469,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..ec55e4b5 100644 --- a/src/Analyser/CodeBase.elm +++ b/src/Analyser/CodeBase.elm @@ -1,9 +1,10 @@ -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) import Elm.Dependency exposing (Dependency) import Elm.Processing as Processing exposing (ProcessContext) +import Elm.Syntax.File exposing (File) type CodeBase @@ -62,3 +63,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..e16062c0 100644 --- a/src/Analyser/Fixer.elm +++ b/src/Analyser/Fixer.elm @@ -1,4 +1,4 @@ -port module Analyser.Fixer exposing (Model, Msg, init, initWithMessage, isDone, message, subscriptions, succeeded, update) +port module Analyser.Fixer exposing (Model, Msg, fixFast, init, initWithMessage, isDone, message, subscriptions, succeeded, update) import Analyser.CodeBase as CodeBase exposing (CodeBase) import Analyser.FileRef exposing (FileRef) @@ -71,6 +71,24 @@ initWithMessage mess state = ) +fixFast : Message -> ( String, File ) -> Result String String +fixFast mess pathAndFile = + Analyser.Fixers.getFixer mess + |> Maybe.map + (\fixer -> + case fixer.fix pathAndFile 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..9c369e95 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; From d9fca2d47888f76c100af073cd03972f24a05b7c Mon Sep 17 00:00:00 2001 From: antew Date: Sat, 8 Jun 2019 21:23:46 -0400 Subject: [PATCH 2/6] Allow unsubscribing from subscriptions, it is used in the language server when we get a request to run a fix, we make the quick fix request and wait for the modified file to come back through the port, and then unsubscribe to complete the loop. --- ts/domain.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/domain.ts b/ts/domain.ts index 9c369e95..05fd998d 100644 --- a/ts/domain.ts +++ b/ts/domain.ts @@ -106,6 +106,7 @@ interface EditorElmApp { interface Subscription { subscribe: ((cb: ((d: T) => void)) => void); + unsubscribe: ((cb: ((d: T) => void)) => void); } interface FileContentSha { From 39d7ab4e6fe359363de1cb71120c97a9764f0938 Mon Sep 17 00:00:00 2001 From: antew Date: Sun, 9 Jun 2019 11:25:49 -0400 Subject: [PATCH 3/6] Simplify code a bit --- src/Analyser.elm | 76 +++++++++++++++++++----------------------- src/Analyser/Fixer.elm | 9 ++--- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/src/Analyser.elm b/src/Analyser.elm index 1090c763..1c3dadef 100644 --- a/src/Analyser.elm +++ b/src/Analyser.elm @@ -4,10 +4,11 @@ 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 +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 +import Analyser.Messages.Types exposing (Message) import Analyser.Messages.Util as Messages import Analyser.Modules import Analyser.SourceLoadingStage as SourceLoadingStage @@ -146,49 +147,34 @@ update msg model = OnQuickFixMessage messageId -> let - processingContext = - CodeBase.processContext model.codeBase - - maybeMessage = - State.getMessage messageId model.state - - maybeFixedFile = - case maybeMessage of - Just message -> - CodeBase.getFile message.file.path model.codeBase - |> Maybe.map - (\loadedSourceFile -> - ( .content <| Tuple.first loadedSourceFile - , FileContext.buildForFile processingContext loadedSourceFile - |> Maybe.map .ast - ) - ) - |> Maybe.map - (\sources -> - case sources of - ( Just fileText, Just ast ) -> - Just <| Fixer.fixFast message ( fileText, ast ) - - _ -> - Nothing - ) - |> Maybe.join - - Nothing -> - Nothing + 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 ( maybeMessage, maybeFixedFile ) of - ( Just message, Just (Ok fixedFile) ) -> - ( model - , AnalyserPorts.sendFixedFile - { path = message.file.path - , content = fixedFile - } - ) + 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 for message id: " ++ String.fromInt messageId) + , Logger.info + ("Unable to apply fix, unable to find messageId: " + ++ String.fromInt messageId + ) ) Reset -> @@ -458,6 +444,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 diff --git a/src/Analyser/Fixer.elm b/src/Analyser/Fixer.elm index e16062c0..e6b4da37 100644 --- a/src/Analyser/Fixer.elm +++ b/src/Analyser/Fixer.elm @@ -1,6 +1,7 @@ -port module Analyser.Fixer exposing (Model, Msg, fixFast, 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,12 +72,12 @@ initWithMessage mess state = ) -fixFast : Message -> ( String, File ) -> Result String String -fixFast mess pathAndFile = +getFixedFile : Message -> FileContext -> Result String String +getFixedFile mess fileContext = Analyser.Fixers.getFixer mess |> Maybe.map (\fixer -> - case fixer.fix pathAndFile mess.data of + case fixer.fix ( fileContext.content, fileContext.ast ) mess.data of Error e -> Err e From db9225c74eb9b9f9a1520fee7d62bf6242540c5d Mon Sep 17 00:00:00 2001 From: antew Date: Sun, 9 Jun 2019 17:50:16 -0400 Subject: [PATCH 4/6] Fix unused import --- src/Analyser.elm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Analyser.elm b/src/Analyser.elm index 1c3dadef..1706f580 100644 --- a/src/Analyser.elm +++ b/src/Analyser.elm @@ -8,7 +8,6 @@ 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 -import Analyser.Messages.Types exposing (Message) import Analyser.Messages.Util as Messages import Analyser.Modules import Analyser.SourceLoadingStage as SourceLoadingStage From 79bf45695476032dc12fac9b93ec457055e5f3e6 Mon Sep 17 00:00:00 2001 From: antew Date: Sun, 9 Jun 2019 17:51:32 -0400 Subject: [PATCH 5/6] Another unused import --- src/Analyser/CodeBase.elm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Analyser/CodeBase.elm b/src/Analyser/CodeBase.elm index ec55e4b5..d03a2410 100644 --- a/src/Analyser/CodeBase.elm +++ b/src/Analyser/CodeBase.elm @@ -4,7 +4,6 @@ import Analyser.Files.Types exposing (LoadedSourceFile) import Dict exposing (Dict) import Elm.Dependency exposing (Dependency) import Elm.Processing as Processing exposing (ProcessContext) -import Elm.Syntax.File exposing (File) type CodeBase From f0715e54e16a6adb2dfc32322909bd68dbda4e07 Mon Sep 17 00:00:00 2001 From: antew Date: Sun, 9 Jun 2019 18:01:15 -0400 Subject: [PATCH 6/6] Fix formatting --- ts/domain.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ts/domain.ts b/ts/domain.ts index 05fd998d..00eb1e12 100644 --- a/ts/domain.ts +++ b/ts/domain.ts @@ -43,8 +43,8 @@ export interface AstStore { ast: JSON; } export interface FixedFile { - path : string, - content: string + path: string; + content: string; } export interface LogMessage { @@ -105,8 +105,8 @@ interface EditorElmApp { } interface Subscription { - subscribe: ((cb: ((d: T) => void)) => void); - unsubscribe: ((cb: ((d: T) => void)) => void); + subscribe: (cb: (d: T) => void) => void; + unsubscribe: (cb: (d: T) => void) => void; } interface FileContentSha { @@ -123,7 +123,7 @@ interface Context { configuration: string; } interface MailBox { - send: ((d: T) => void); + send: (d: T) => void; } interface Reporter {