phoityne / hdx4vsc

Haskell Debugger Extension for Visual Studio Code.
https://marketplace.visualstudio.com/items?itemName=phoityne.phoityne-vscode
BSD 3-Clause "New" or "Revised" License
50 stars 9 forks source link

Feature request: support jumping into library #27

Closed forestaa closed 1 year ago

forestaa commented 1 year ago

Thank you for the awesome extension! I want the feature that the debugger jumps into library.

Problem

When I tried this extension, I found the following warning. This is because the current implementation does not support Source Request. スクリーンショット 2022_10_27 木 0_50_38

Below is the structure of sample app and cabal file.

.
├── app
│   └── Main.hs
├── haskell-dap-test.cabal
└── src
    ├── MyLib1.hs
    └── MyLib2.hs
library
    exposed-modules:
        MyLib1
        MyLib2
    build-depends:    base ^>=4.16.3.0
    hs-source-dirs:   src
    default-language: GHC2021

executable haskell-dap-test
    main-is:          Main.hs
    build-depends:
        base ^>=4.16.3.0,
        haskell-dap-test
    hs-source-dirs:   app
    default-language: GHC2021

Solution

Source request requests the content of the file which is the top of the stacktrace. GHCi keeps the content of the loaded modules, so we can retrieve the content from GHCi.

forestaa commented 1 year ago

I have submitted 3 PRs. https://github.com/phoityne/haskell-dap/pull/13 https://github.com/phoityne/ghci-dap/pull/8 https://github.com/phoityne/haskell-debug-adapter/pull/27 The debugger can jump into libraries with these PRs.

haskell-debug-adapter-test

Any comments and edits are welcome!

phoityne commented 1 year ago

Hi. Thank you for your PR.

I'm going to investigate. I think this jumping into other module worked before.

Additionary, now, ghci-dap can not put a breakpoint on source code in other module.

H>>= :load /work/haskell/sample-cabal/app/Main.hs
[1 of 1] Compiling Main             ( /work/haskell/sample-cabal/app/Main.hs, interpreted ) [flags changed]
Ok, one module loaded.
H>>= :dap-context-modules ...
[DAP][INFO]context modules. ["Main"]
H>>= :dap-set-breakpoints ...
H>>= [ERROR][APP] user error (<getModule> loaded module can not find from path. </work/haskell/sample-cabal/src/Lib.hs> [("Main","/work/haskell/sample-cabal/app/Main.hs")])
:dap-set-breakpoints ...

Lib.hs should be loaded while loading Main.hs, but not.

Regards.

forestaa commented 1 year ago

Hi, thank you for your investigating!

Additionary, now, ghci-dap can not put a breakpoint on source code in other module.

I faced the same error and also don't know why the module is not loaded. I forgot to say that I used :add instead of :load in the line below and then the breakpoint is set correctly. https://github.com/phoityne/haskell-debug-adapter/blob/955f72eb641d6bb569f4363e02b0416c44988856/src/Haskell/Debug/Adapter/State/Utility.hs#L323

But I'm not sure whether the behavior is expected.

And one more thing, I used cabal with ghciCmd cabal repl -w ghci-dap in launch.json. I didn't test it with stack.

phoityne commented 1 year ago

Could you show a value of "ghciCmd" in the launch.json ?

In my project, it works. This is a setting.

"ghciCmd": "cabal exec -- ghci-dap --interactive -i -i${workspaceFolder}/app -i${workspaceFolder}/src",

seems that the include path needs to be set to the subdirectory full path. Regards.

forestaa commented 1 year ago

Thank you for your investigation.

I tried your launch.json and it worked for my sample project. I firstly tried the generated launch.json and it didn't work for my main project. https://github.com/phoityne/hdx4vsc/blob/70af001f6d83d17fabedfa676ca9ca0fde9b0f78/configs/04_for_cabal_launch.json#L20 So, I used cabal repl -w ghci-dap as ghciCmd in the launch.json in my main project.

However, I found the next problem. cabal exec -- ghci-dap --interactive -i -i${workspaceFolder}/app -i${workspaceFolder}/src didn't work for my main project because I used some ghc extensions in my cabal file and ghci-dap cannot load those extensions. I created another sample project and you can test it. https://github.com/forestaa/haskell-debug-adapter-test

Below is the error when I tried.

H>>= :load /home/foresta/playground/haskell-dap-test/app/Main.hs
[1 of 3] Compiling MyLib2           ( /home/foresta/playground/haskell-dap-test/src/MyLib2.hs, interpreted )

/home/foresta/playground/haskell-dap-test/src/MyLib2.hs:11:3: error:
    • A pattern match on a GADT requires the GADTs or TypeFamilies language extension
    • In the pattern: Const x
      In a case alternative: Const x -> x
      In the expression:
        case e of
          Const x -> x
          Add e1 e2 -> eval e1 + eval e2
          Equal e1 e2 -> eval e1 == eval e2
          IfThenElse cond then_ else_
            -> if eval cond then eval then_ else eval else_
   |
11 |   Const x ->
   |   ^^^^^^^
Failed, no modules loaded.

Thank you for your kind cooperation!

phoityne commented 1 year ago

Although there are warning messages, it works in my environment. (cabal, ghc-9.4.2)

Configuration read.
Starting GHCi.
Wait for a moment.
CWD: /home/cabal/work/haskell-debug-adapter-test
CMD: cabal exec -- ghci-dap --interactive -i -i/home/cabal/work/haskell-debug-adapter-test/app -i/home/cabal/work/haskell-debug-adapter-test/src

Now, waiting for an initial prompt("> ") from ghci.

Resolving dependencies...
[DAP][INFO] start ghci-dap-0.0.19.0.
Loaded package environment from /home/cabal/work/haskell-debug-adapter-test/dist-newstyle/tmp/environment.-97743/.ghc.environment.x86_64-linux-9.4.2
GHCi, version 9.4.2: https://www.haskell.org/ghc/  :? for help
ghci>:set prompt "<<DAP_CMD_END2>>\nH>>= "
H>>= :set prompt-cont "<<DAP_CMD_END2>>\nH>>= "
H>>= :dap-launch ...
H>>= :load /home/cabal/work/haskell-debug-adapter-test/app/Main.hs
[1 of 4] Compiling MyLib2           ( /home/cabal/work/haskell-debug-adapter-test/src/MyLib2.hs, interpreted )

/home/cabal/work/haskell-debug-adapter-test/src/MyLib2.hs:11:3: warning: [-Wgadt-mono-local-binds]
    Pattern matching on GADTs without MonoLocalBinds is fragile.
    Suggested fix:
      Enable any of the following extensions: GADTs, TypeFamilies
   |
11 |   Const x ->
   |   ^^^^^^^

/home/cabal/work/haskell-debug-adapter-test/src/MyLib2.hs:13:3: warning: [-Wgadt-mono-local-binds]
    Pattern matching on GADTs without MonoLocalBinds is fragile.
    Suggested fix:
      Enable any of the following extensions: GADTs, TypeFamilies
   |
13 |   Add e1 e2 ->
   |   ^^^^^^^^^

/home/cabal/work/haskell-debug-adapter-test/src/MyLib2.hs:15:3: warning: [-Wgadt-mono-local-binds]
    Pattern matching on GADTs without MonoLocalBinds is fragile.
    Suggested fix:
      Enable any of the following extensions: GADTs, TypeFamilies
   |
15 |   Equal e1 e2 ->
   |   ^^^^^^^^^^^
[2 of 4] Compiling MyLib1           ( /home/cabal/work/haskell-debug-adapter-test/src/MyLib1.hs, interpreted )
[3 of 4] Compiling Main             ( /home/cabal/work/haskell-debug-adapter-test/app/Main.hs, interpreted )
Ok, three modules loaded.
H>>= :dap-context-modules ...

"-XGADTs" ghci option or {-# LANGUAGE GADTs #-} might need. https://gitlab.haskell.org/ghc/ghc/-/issues/8815

$ cabal exec  -- ghci-dap --interactive -i -isrc:app -XGADTs
[DAP][INFO] start ghci-dap-0.0.19.0.
Loaded package environment from /home/cabal/work/haskell-debug-adapter-test/dist-newstyle/tmp/environment.-98481/.ghc.environment.x86_64-linux-9.4.2
GHCi, version 9.4.2: https://www.haskell.org/ghc/  :? for help
ghci> :l app/Main.hs
[1 of 4] Compiling MyLib2           ( src/MyLib2.hs, interpreted )
[2 of 4] Compiling MyLib1           ( src/MyLib1.hs, interpreted )
[3 of 4] Compiling Main             ( app/Main.hs, interpreted )
Ok, three modules loaded.
ghci> 
forestaa commented 1 year ago

Thank you for your response.

Although there are warning messages, it works in my environment. (cabal, ghc-9.4.2)

Thanks, I didn't know that. I tried ghc-9.2.4, but didn't try ghc-9.4.2. Actually it worked for GADTs, but it didn't work for OverloadedRecordDot. (I pushed the commit which uses OverloadedRecordDot to the test repository.)

"-XGADTs" ghci option or {-# LANGUAGE GADTs #-} might need.

Yes, you are right. It works if I pass the option. But in that case, we need to manage ghc extensions among both the .cabal file and launch.json. I think it is better to use cabal repl -w ghci-dap as GhciCmd because cabal repl automatically enables the ghc extensions in .cabal file. But the choice is up to users.

I understood that my problem can be resolved by the appropriate GhciCmd. Should I close the PRs which I submitted? Or, might it still be useful?

phoityne commented 1 year ago

Hi.

I would like to merge your PR, this is a missing feature of ghci-dap. I reviewd and commented to PR of haskell-debug-adapter.

And also, I'm going to fix ghci-dap for this issue later. As you say, using cabal repl would be better than cabal exec. I think needs fix to numeric version message of ghci-dap.
(working in your enviroment? not mine.)

Anyway thanks a lot! for your contribution to this project. Regards.

forestaa commented 1 year ago

Thank you for your response and reviewing!

As you say, using cabal repl would be better than cabal exec.

Thank you for your understanding. I think it's better too.

I think needs fix to numeric version message of ghci-dap. (working in your enviroment? not mine.)

Yes. I just commented those lines out in my environment. I added the commit that fix the version message. Please look at it when you have time. https://github.com/phoityne/ghci-dap/pull/8/commits/e7308c258652f4905f76866d26166227fdfd4bc5

I'm glad to contribute this awesome project! This debugger helped me a lot.

phoityne commented 1 year ago

Hi.

I have merged your pr. I'm preparing for the next release.

While building check, there are some warnings occurred. Could you remove these warnings ?

Building executable 'ghci-dap' for ghci-dap-0.0.20.0..
[11 of 14] Compiling GHCi.DAP.Command ( app/GHCi/DAP/Command.hs, dist/build/ghci-dap/ghci-dap-tmp/GHCi/DAP/Command.o )

app/GHCi/DAP/Command.hs:1125:7: warning: [-Wincomplete-uni-patterns]
    Pattern match(es) are non-exhaustive
    In a pattern binding:
        Patterns of type ‘Maybe D.Source’ not matched: Nothing
     |
1125 |   let Just srcInfo =  D.sourceSourceRequestArguments args
     |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Building library for haskell-debug-adapter-0.0.38.0..
[17 of 31] Compiling Haskell.Debug.Adapter.State.Contaminated ( src/Haskell/Debug/Adapter/State/Contaminated.hs, /work/haskell/haskell-debug-adapter/dist-newstyle/build/x86_64-linux/ghc-9.4.2/haskell-debug-adapter-0.0.38.0/build/Haskell/Debug/Adapter/State/Contaminated.o, /work/haskell/haskell-debug-adapter/dist-newstyle/build/x86_64-linux/ghc-9.4.2/haskell-debug-adapter-0.0.38.0/build/Haskell/Debug/Adapter/State/Contaminated.dyn_o )

src/Haskell/Debug/Adapter/State/Contaminated.hs:35:3: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘doActivity’:
        Patterns of type ‘AppState ContaminatedStateData’,
                         ‘WrapRequest’ not matched:
            _ (WrapRequest (SourceRequest _))
   |
35 |   doActivity s (WrapRequest r@InitializeRequest{})              = action s r
forestaa commented 1 year ago

Thanks for merging and reporting warning. I fixed the above warning. Cloud you take a look? https://github.com/phoityne/ghci-dap/pull/9 https://github.com/phoityne/haskell-debug-adapter/pull/28

phoityne commented 1 year ago

Released.

Thank you for your contribution.