packages feed

haskell-debugger 0.13.0.0 → 0.13.1.0

raw patch · 23 files changed

+281/−71 lines, 23 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ GHC.Debugger.Breakpoint.Map: instance GHC.Debugger.View.Class.DebugView (GHC.Debugger.Breakpoint.Map.BreakpointMap a)
+ GHC.Debugger.Utils: showModule :: Module -> String
+ GHC.Debugger.Utils.Orphans: instance GHC.Debugger.View.Class.DebugView (GHC.Unit.Module.Env.ModuleEnv a)
+ GHC.Debugger.Utils.Orphans: instance GHC.Debugger.View.Class.DebugView GHC.Unit.Types.Module

Files

CHANGELOG.md view
@@ -1,5 +1,11 @@ # Revision history for haskell-debugger +## 0.13.1.0 -- 2026-04-28++* Fix critical bug which caused certain breakpoints to be overwritten by or+  confused with breakpoints from separate modules.+* Fix: Make forcing a thunk invalidate all threads+ ## 0.13.0.0 -- 2026-04-24  Features:
haskell-debugger.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.12 name:               haskell-debugger-version:            0.13.0.0+version:            0.13.1.0 synopsis:     A step-through debugger for GHC Haskell @@ -243,7 +243,8 @@                       Test.Integration.Stdout,                       Test.Integration.Conditional,                       Test.Integration.Evaluate,-                      Test.Integration.StackTrace+                      Test.Integration.StackTrace,+                      Test.Integration.SelfDebug     build-depends:         base >=4.14,         async,
haskell-debugger/GHC/Debugger/Breakpoint.hs view
@@ -33,6 +33,7 @@ import GHC.Debugger.Utils import GHC.Debugger.Interface.Messages import qualified GHC.Debugger.Breakpoint.Map as BM+import Data.Function  -------------------------------------------------------------------------------- -- * Breakpoints@@ -192,14 +193,14 @@       mms <- getModuleByPath file       case mms of         Right ms -> do-          hsc_env    <- getSession-          imodBreaks <- liftIO $ expectJust <$> readIModBreaksMaybe (hsc_HUG hsc_env) (ms_mod ms)-          return-            [ ibi-            | ibi <- BM.keys bm-            , getBreakSourceMod ibi imodBreaks == ms_mod ms-            -- assert: status is always > disabled-            ]+          hug <- hsc_HUG <$> getSession+          -- Return all active IBIs whose occurrence (source) module+          -- matches the argument source module.+          map fst <$> filterM (\(ibi, info)  -> do+            ibi_occ_mod <- getBreakSourceMod ibi <$> readIModBreaks hug ibi & liftIO+            assert (bpInfoStatus info /= BreakpointDisabled) $+              return (ibi_occ_mod == ms_mod ms)+            ) (BM.toList bm)         Left e -> do           logSDoc Logger.Warning e           return []
haskell-debugger/GHC/Debugger/Breakpoint/Map.hs view
@@ -17,6 +17,8 @@ import GHC.ByteCode.Breakpoints import GHC.Utils.Outputable (Outputable) import qualified Data.IntMap as IM+import GHC.Debugger.View.Class+import GHC.Debugger.Utils (showModule)  -- | A map keyed by 'InternalBreakpointId' newtype BreakpointMap a = BreakpointMap (ModuleEnv (IM.IntMap a))@@ -77,3 +79,10 @@   | (m, im)  <- moduleEnvToList bm   , (bix, a) <- IM.toList im   ]++instance DebugView (BreakpointMap a) where+  debugValue (BreakpointMap b) = simpleValue "BreakpointMap" (not $ isEmptyModuleEnv b)+  debugFields bm = pure $ VarFields+    [ (showModule ibi_info_mod ++ "(" ++ show ibi_info_index ++ ")", VarFieldValue v)+    | (InternalBreakpointId{ibi_info_mod, ibi_info_index}, v) <- toList bm+    ]
haskell-debugger/GHC/Debugger/Session/Builtin.hs view
@@ -147,16 +147,16 @@  -- | The contents of GHC.Debugger.View.Class in memory debuggerViewClassContents :: StringBuffer-debuggerViewClassContents = stringToStringBuffer $(embedStringFile "haskell-debugger-view/src/GHC/Debugger/View/Class.hs")+debuggerViewClassContents = stringToStringBuffer $(embedStringFile =<< makeRelativeToProject "haskell-debugger-view/src/GHC/Debugger/View/Class.hs")  -- | The contents of GHC.Debugger.View.Containers in memory debuggerViewContainersContents :: StringBuffer-debuggerViewContainersContents = stringToStringBuffer $(embedStringFile "haskell-debugger-view/src/GHC/Debugger/View/Containers.hs")+debuggerViewContainersContents = stringToStringBuffer $(embedStringFile =<< makeRelativeToProject "haskell-debugger-view/src/GHC/Debugger/View/Containers.hs")  -- | GHC.Debugger.View.Text debuggerViewTextContents :: StringBuffer-debuggerViewTextContents = stringToStringBuffer $(embedStringFile "haskell-debugger-view/src/GHC/Debugger/View/Text.hs")+debuggerViewTextContents = stringToStringBuffer $(embedStringFile =<< makeRelativeToProject "haskell-debugger-view/src/GHC/Debugger/View/Text.hs")  -- | GHC.Debugger.View.ByteString debuggerViewByteStringContents :: StringBuffer-debuggerViewByteStringContents = stringToStringBuffer $(embedStringFile "haskell-debugger-view/src/GHC/Debugger/View/ByteString.hs")+debuggerViewByteStringContents = stringToStringBuffer $(embedStringFile =<< makeRelativeToProject "haskell-debugger-view/src/GHC/Debugger/View/ByteString.hs")
haskell-debugger/GHC/Debugger/Utils.hs view
@@ -105,3 +105,9 @@     num :: Parser Int     num = decimal +--------------------------------------------------------------------------------+-- * DebugView utils+--------------------------------------------------------------------------------++showModule :: Module -> String+showModule = showSDocUnsafe . withPprStyle (PprDump alwaysQualify) . ppr
haskell-debugger/GHC/Debugger/Utils/Orphans.hs view
@@ -1,9 +1,22 @@ {-# OPTIONS_GHC -Wno-orphans #-}-module GHC.Debugger.Utils.Orphans where+module GHC.Debugger.Utils.Orphans () where  import GHC.Debugger.View.Class import GHC.Data.FastString+import GHC.Unit.Module+import GHC.Debugger.Utils (showModule)  instance DebugView FastString where   debugValue  t = simpleValue (unpackFS t) False   debugFields _ = pure (VarFields [])++instance DebugView Module where+  debugValue  t = simpleValue (showModule t) False+  debugFields _ = pure (VarFields [])++instance DebugView (ModuleEnv a) where+  debugValue m = simpleValue "ModuleEnv" (not $ isEmptyModuleEnv m)+  debugFields m = pure $ VarFields+    [ (showModule k, VarFieldValue v)+    | (k, v) <- moduleEnvToList m+    ]
hdb/Development/Debug/Adapter/Stopped.hs view
@@ -148,7 +148,6 @@         ForcedVariable _           -> sendInvalidatedEvent defaultInvalidatedEvent               { invalidatedEventAreas = [InvalidatedAreasVariables]-              , invalidatedEventStackFrameId = Just 0 -- TODO: REVERSE LOOKUP OF (StackFrameIx threadId frameIx)               }         VariableFields _ -> return () 
test/golden/self-debug-cli/self-debug-cli.no-tmp-dir.external.ghc-914.hdb-stdout view
@@ -1,55 +1,3 @@-[ 1 of 53] Compiling Development.Debug.Adapter.Handles ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Handles.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[ 2 of 53] Compiling Development.Debug.Options ( <PROJECT-ROOT>/hdb/Development/Debug/Options.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[ 3 of 53] Compiling Development.Debug.Session.Setup ( <PROJECT-ROOT>/hdb/Development/Debug/Session/Setup.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[ 4 of 53] Compiling GHC.Debugger.Breakpoint.Map ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Breakpoint/Map.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[ 5 of 53] Compiling GHC.Debugger.Runtime.Compile.Cache ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Compile/Cache.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[ 6 of 53] Compiling GHC.Debugger.Runtime.Term.Key ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Term/Key.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[ 7 of 53] Compiling GHC.Debugger.Interface.Messages ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Interface/Messages.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[ 8 of 53] Compiling GHC.Debugger.Runtime.Interpreter.Custom ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Interpreter/Custom.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[ 9 of 53] Compiling Development.Debug.Adapter ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[10 of 53] Compiling Development.Debug.Adapter.Proxy ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Proxy.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[11 of 53] Compiling Development.Debug.Adapter.Output ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Output.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[12 of 53] Compiling Development.Debug.Adapter.Interface ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Interface.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[13 of 53] Compiling Development.Debug.Adapter.Stopped ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Stopped.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[14 of 53] Compiling Development.Debug.Adapter.Exit.Helpers ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Exit/Helpers.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[15 of 53] Compiling Development.Debug.Adapter.Exit ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Exit.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[16 of 53] Compiling Development.Debug.Adapter.ExceptionInfo ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/ExceptionInfo.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[17 of 53] Compiling Development.Debug.Adapter.Evaluation ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Evaluation.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[18 of 53] Compiling Development.Debug.Adapter.Stepping ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Stepping.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[19 of 53] Compiling Development.Debug.Adapter.Breakpoints ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Breakpoints.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[20 of 53] Compiling GHC.Debugger.Runtime.Thread.Map ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Thread/Map.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[21 of 53] Compiling GHC.Debugger.Session ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Session.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[22 of 53] Compiling GHC.Debugger.Session.Builtin ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Session/Builtin.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[23 of 53] Compiling GHC.Debugger.Session.Interactive ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Session/Interactive.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[24 of 53] Compiling GHC.Debugger.Utils ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Utils.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[25 of 53] Compiling GHC.Debugger.View.Class ( <PROJECT-ROOT>/haskell-debugger-view/src/GHC/Debugger/View/Class.hs, interpreted )[haskell-debugger-view-<VERSION>-inplace]-[26 of 53] Compiling GHC.Debugger.View.ByteString ( <PROJECT-ROOT>/haskell-debugger-view/src/GHC/Debugger/View/ByteString.hs, interpreted )[haskell-debugger-view-<VERSION>-inplace]-[27 of 53] Compiling GHC.Debugger.Utils.Orphans ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Utils/Orphans.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[28 of 53] Compiling GHC.Debugger.Runtime.Instances.Discover[boot] ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Instances/Discover.hs-boot, interpreted )[haskell-debugger-<VERSION>-inplace]-[29 of 53] Compiling GHC.Debugger.Monad ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Monad.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[30 of 53] Compiling GHC.Debugger.Runtime.Instances.Discover ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Instances/Discover.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[31 of 53] Compiling GHC.Debugger.Runtime.Eval ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Eval.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[32 of 53] Compiling GHC.Debugger.Runtime.Compile ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Compile.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[33 of 53] Compiling GHC.Debugger.Runtime.Eval.RemoteExpr ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Eval/RemoteExpr.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[34 of 53] Compiling GHC.Debugger.Runtime.Term.Parser ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Term/Parser.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[35 of 53] Compiling GHC.Debugger.Runtime.Instances ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Instances.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[36 of 53] Compiling GHC.Debugger.Runtime.Eval.RemoteExpr.Builtin ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Eval/RemoteExpr/Builtin.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[37 of 53] Compiling GHC.Debugger.Runtime.Thread.Stack ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Thread/Stack.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[38 of 53] Compiling GHC.Debugger.Runtime.Thread ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime/Thread.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[39 of 53] Compiling GHC.Debugger.Stopped.Exception ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Stopped/Exception.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[40 of 53] Compiling GHC.Debugger.Runtime ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Runtime.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[41 of 53] Compiling GHC.Debugger.Stopped.Variables ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Stopped/Variables.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[42 of 53] Compiling GHC.Debugger.Stopped ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Stopped.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[43 of 53] Compiling GHC.Debugger.Run ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Run.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[44 of 53] Compiling GHC.Debugger.Breakpoint ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger/Breakpoint.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[45 of 53] Compiling GHC.Debugger     ( <PROJECT-ROOT>/haskell-debugger/GHC/Debugger.hs, interpreted )[haskell-debugger-<VERSION>-inplace]-[46 of 53] Compiling Development.Debug.Interactive ( <PROJECT-ROOT>/hdb/Development/Debug/Interactive.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[47 of 53] Compiling Development.Debug.Adapter.Init ( <PROJECT-ROOT>/hdb/Development/Debug/Adapter/Init.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[48 of 53] Compiling GHC.Debugger.View.Containers ( <PROJECT-ROOT>/haskell-debugger-view/src/GHC/Debugger/View/Containers.hs, interpreted )[haskell-debugger-view-<VERSION>-inplace]-[49 of 53] Compiling GHC.Debugger.View.Text ( <PROJECT-ROOT>/haskell-debugger-view/src/GHC/Debugger/View/Text.hs, interpreted )[haskell-debugger-view-<VERSION>-inplace]-[50 of 53] Compiling Paths_haskell_debugger ( <AUTOGEN-DIR>/Paths_haskell_debugger.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[51 of 53] Compiling Development.Debug.Options.Parser ( <PROJECT-ROOT>/hdb/Development/Debug/Options/Parser.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb]-[52 of 53] Compiling Main             ( <PROJECT-ROOT>/hdb/Main.hs, interpreted )[haskell-debugger-<VERSION>-inplace-hdb] (hdb) Stopped at breakpoint (hdb) this FastString should be displayed pretty as a string (SHOULD NOT SEE ITS FULL INTERNALS). (hdb) We have a DebugView FastString instance at this breakpoint.
test/golden/self-debug-cli/self-debug-cli.no-tmp-dir.external.hdb-test view
@@ -9,6 +9,9 @@ # too prone to changing because it reports source lines of the actual debugger # source, which we change all the time (unlike testsuite programs). #+# 3.1) Grep out all `[27 of 53] Compiling ...` lines. Everytime we added a+# module it would force the test to be updated and was prone to conflicts.+# # 4) Normalize cabal autogen paths (e.g. `Paths_haskell_debugger.hs`). # It's not immediately clear why these go in .cache/hie-bios/... rather than in # $HDB_CACHE_DIR, but I guess it's an autogen thing rather than the actual@@ -24,6 +27,7 @@  $HDB -v0 hdb/Main.hs < "test/golden/self-debug-cli/self-debug-cli.hdb-stdin" 2>&1 \   | grep -v "BreakFound" \+  | grep -v "] Compiling" \   | sed \       -e 's|[^ ]*/Paths_haskell_debugger.hs|<AUTOGEN-DIR>/Paths_haskell_debugger.hs|g' \       -e 's|haskell-debugger-[0-9.][0-9.]*-inplace|haskell-debugger-<VERSION>-inplace|g' \
+ test/golden/standalone-multi-module/Helper.hs view
@@ -0,0 +1,5 @@+module Helper where++greet :: String -> IO ()+greet name = do+  putStrLn ("Hello, " ++ name ++ "!")
+ test/golden/standalone-multi-module/Main.hs view
@@ -0,0 +1,9 @@+module Main where++import Helper++main :: IO ()+main = do+  putStrLn "Starting..."+  greet "world"+  putStrLn "Done."
+ test/golden/standalone-multi-module/standalone-multi-module.ghc-914.hdb-stdout view
@@ -0,0 +1,9 @@+[1 of 4] Compiling GHC.Debugger.View.Class ( in-memory:GHC.Debugger.View.Class, interpreted )[haskell-debugger-view-in-memory]+[2 of 4] Compiling Helper           ( <TEMPORARY-DIRECTORY>/Helper.hs, interpreted )[main]+[3 of 4] Compiling Main             ( <TEMPORARY-DIRECTORY>/Main.hs, interpreted )[main]+(hdb) BreakFound {changed = True, breakId = [InternalBreakpointId Main 5], sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/Main.hs", startLine = 7, endLine = 7, startCol = 3, endCol = 25}}+(hdb) BreakFound {changed = True, breakId = [InternalBreakpointId Helper 4], sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/./Helper.hs", startLine = 5, endLine = 5, startCol = 3, endCol = 38}}+(hdb) Stopped at breakpoint+(hdb) Starting...+Stopped at breakpoint+(hdb) Exiting...
+ test/golden/standalone-multi-module/standalone-multi-module.hdb-stdin view
@@ -0,0 +1,4 @@+break Main.hs 7+break Helper.hs 5+run+continue
+ test/golden/standalone-multi-module/standalone-multi-module.hdb-test view
@@ -0,0 +1,1 @@+$HDB Main.hs -v 0 < standalone-multi-module.hdb-stdin
test/haskell/Main.hs view
@@ -38,6 +38,7 @@ import Test.Integration.Conditional (conditionalTests) import Test.Integration.Evaluate (evaluateTests) import Test.Integration.StackTrace (stackTraceTests)+import Test.Integration.SelfDebug (selfDebugTests) import Test.Utils import qualified Data.Char as C import qualified Data.Text as T@@ -102,6 +103,7 @@   , conditionalTests   , evaluateTests   , stackTraceTests+  , selfDebugTests   ]  -- | Receives as an argument the path to the @*.hdb-test@ which contains the
test/haskell/Test/Integration/Basic.hs view
@@ -27,6 +27,10 @@             , testCase "accepts internalInterpreter launch option" internalInterpreterOption             ]         ]+    , testGroup "Multi-module standalone (no cabal/hie.yaml)"+        [ testCase "breakpoints in two modules (#297)" multiModuleStandaloneBreakpoints+        , testCase "breakpoints in two modules (flipped) (#297)" multiModuleStandaloneBreakpoints2+        ]     ]  basicForConfig :: TestName -> FilePath -> FilePath -> TestTree@@ -88,4 +92,38 @@       let cfg = (mkLaunchConfig test_dir "Main.hs")             { lcInternalInterpreter = Just True } -- TODO: Automatically run all tests with internal interpreter too?       hitBreakpointWith cfg 6+      disconnect++-- | Two-module standalone project (no cabal, no hie.yaml): set a breakpoint in+-- each module, run, hit the first (Main.hs), continue, hit the second (Helper.hs).+-- (#297)+multiModuleStandaloneBreakpoints :: Assertion+multiModuleStandaloneBreakpoints =+  withTestDAPServer "test/integration/standalone-multi-module" [] $ \test_dir server ->+    withTestDAPServerClient server $ do+      let cfg = mkLaunchConfig test_dir "Main.hs"+      _ <- sync $ launchWith cfg+      waitFiltering_ EventTy "initialized"+      _ <- sync $ setLineBreakpoints test_dir "Main.hs"   [7]+      _ <- sync $ setLineBreakpoints test_dir "Helper.hs" [5]+      _ <- sync configurationDone+      assertStoppedLocation DAP.StoppedEventReasonBreakpoint 7+      continueThread 0+      assertStoppedLocation DAP.StoppedEventReasonBreakpoint 5+      disconnect++-- | Same as above, but flip the order of the setLineBreakpoints calls (#297)+multiModuleStandaloneBreakpoints2 :: Assertion+multiModuleStandaloneBreakpoints2 =+  withTestDAPServer "test/integration/standalone-multi-module" [] $ \test_dir server ->+    withTestDAPServerClient server $ do+      let cfg = mkLaunchConfig test_dir "Main.hs"+      _ <- sync $ launchWith cfg+      waitFiltering_ EventTy "initialized"+      _ <- sync $ setLineBreakpoints test_dir "Helper.hs" [5]+      _ <- sync $ setLineBreakpoints test_dir "Main.hs"   [7]+      _ <- sync configurationDone+      assertStoppedLocation DAP.StoppedEventReasonBreakpoint 7+      continueThread 0+      assertStoppedLocation DAP.StoppedEventReasonBreakpoint 5       disconnect
test/haskell/Test/Integration/Evaluate.hs view
@@ -1,15 +1,14 @@--- | Evaluate request tests (issue #116) ported from the NodeJS testsuite.+-- | Evaluate request tests ported from the NodeJS testsuite. {-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Test.Integration.Evaluate (evaluateTests) where  import Control.Monad.IO.Class (liftIO)+import Data.List (isInfixOf) import Test.DAP import Test.Tasty import Test.Tasty.HUnit-#ifdef mingw32_HOST_OS import Test.Tasty.ExpectedFailure-#endif import qualified DAP  evaluateTests :: TestTree@@ -20,6 +19,11 @@   testGroup "DAP.Integration.Evaluate"     [ testCase "Return structured representation for evaluated expressions (issue #116)"         evaluateStructured+    , testCase "Imported module bindings available in evaluate context (issue #233)"+        evaluateImportedBindings+    , expectFailBecause "#299" $+        testCase "Bindings from other modules not available in evaluate context (issue #233)"+          evaluateImportedBindingsNotInOtherModule     ]  evaluateStructured :: Assertion@@ -37,4 +41,56 @@         (v1:_) -> v1 @==? "\'b\'"         []     -> liftIO $ assertFailure $           "No variable named 1 in evaluation result: " ++ show respChildren+      disconnect++-- | Test that bindings from imported modules are available when evaluating+-- expressions at a breakpoint (issue #233).+evaluateImportedBindings :: Assertion+evaluateImportedBindings =+  withTestDAPServer "test/integration/T233" [] $ \test_dir server ->+    withTestDAPServerClient server $ do+      let cfg = mkLaunchConfig test_dir "T233.hs"+      hitBreakpointWith cfg 15++      -- sort is imported from Data.List+      sortResp <- evaluate "show (sort xs)"+      liftIO $ assertEqual "sort xs result" "\"[1,1,2,3,4,5,6,9]\"" (DAP.evaluateResponseResult sortResp)++      -- Map is a qualified import+      mapResp <- evaluate "show (Map.lookup \"a\" m)"+      liftIO $ assertEqual "Map.lookup result" "\"Just 1\"" (DAP.evaluateResponseResult mapResp)++      disconnect++-- | Test that bindings from modules not imported at the stopped location are+-- NOT available in the evaluate context (issue #233).+evaluateImportedBindingsNotInOtherModule :: Assertion+evaluateImportedBindingsNotInOtherModule =+  withTestDAPServer "test/integration/T233" [] $ \test_dir server ->+    withTestDAPServerClient server $ do+      let cfg = mkLaunchConfig test_dir "T233.hs"++      _ <- sync $ launchWith cfg+      waitFiltering_ EventTy "initialized"+      -- T233.hs imports Data.Map.Strict as Map; Other.hs does not+      _ <- sync $ setLineBreakpoints test_dir "T233.hs" [15]+      _ <- sync $ setLineBreakpoints test_dir "Other.hs" [4]+      _ <- sync configurationDone+      _ <- assertStoppedLocation DAP.StoppedEventReasonBreakpoint 15++      -- Stopped in T233.hs which imports Data.List and Data.Map.Strict as Map+      sortResp <- evaluate "show (sort xs)"+      liftIO $ assertEqual "sort xs result" "\"[1,1,2,3,4,5,6,9]\"" (DAP.evaluateResponseResult sortResp)++      -- Resume and stop at breakpoint in Other.hs, which does not import Map+      continueThread 0+      _ <- assertStoppedLocation DAP.StoppedEventReasonBreakpoint 4++      -- Map is not imported in Other.hs; evaluating Map.fromList should fail+      mapFailResp <- evaluate "Map.fromList [(1,'a')]"+      let result = DAP.evaluateResponseResult mapFailResp+      liftIO $ assertBool+        ("expected 'not in scope' error for Map.fromList, got: " ++ show result)+        ("not in scope" `isInfixOf` show result)+       disconnect
+ test/haskell/Test/Integration/SelfDebug.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+module Test.Integration.SelfDebug (selfDebugTests) where++import System.Directory+import System.FilePath+import Control.Monad+import Control.Monad.IO.Class (liftIO)+import Data.Aeson+import Test.DAP+import Test.DAP.Messages.Parser (Event(..))+import Test.Tasty+import Test.Tasty.HUnit+import qualified DAP+import DAP.Types (StoppedEvent(..))+#ifdef mingw32_HOST_OS+import Test.Tasty.ExpectedFailure+#endif++selfDebugTests :: TestTree+selfDebugTests =+#ifdef mingw32_HOST_OS+  ignoreTestBecause "Needs to be fixed for Windows (#199)" $+#endif+  testGroup "DAP.Integration.SelfDebug"+    [ testCase "debug the debugger itself via DAP" selfDebugDAPTest+    ]++selfDebugDAPTest :: Assertion+selfDebugDAPTest = do+  withTestDAPServer "." [] $ \test_dir server -> do -- Self-debug test copies project root to temp dir+    doesFileExist (test_dir </> "cabal.project") >>= \exists ->+      unless exists $ writeFile (test_dir </> "cabal.project")+        "packages: . haskell-debugger-view\nallow-newer: ghc-bignum,containers,time,ghc,base,template-haskell"+    doesFileExist (test_dir </> "hie.yaml") >>= \exists ->+      unless exists $ writeFile (test_dir </> "hie.yaml")+        "cradle:\n  cabal:\n    component: \"all\""+    withTestDAPServerClient server $ do+      let cfg = LaunchConfig+            { lcProjectRoot = test_dir+            , lcEntryFile = Just "hdb/Main.hs"+            , lcEntryPoint = Just "main"+            , lcEntryArgs = ["cli", "test/golden/self-debug-cli/Main.hs"]+            , lcExtraGhcArgs = []+            , lcInternalInterpreter = Nothing+            }++      _ <- sync $ launchWith cfg+      waitFiltering_ EventTy "initialized"++      _ <- sync $ setFunctionBreakpointsRequest @_ @Value $ object+        [ "breakpoints" .= [ object [ "name" .= ("runDebugger" :: String) ] ] ]++      _ <- sync configurationDone++      Event{eventBody = Just StoppedEvent{stoppedEventReason = reason}}+        <- waitFiltering EventTy "stopped"+      liftIO $ assertEqual "expected breakpoint stop"+        reason DAP.StoppedEventReasonBreakpoint+          -- fixme: should we reply with StoppedEventReasonFunctionBreakpoint instead?++      disconnect
+ test/integration/T233/Other.hs view
@@ -0,0 +1,6 @@+module Other where++process :: [Int] -> IO ()+process xs = do+  let n = length xs+  print n
+ test/integration/T233/T233.hs view
@@ -0,0 +1,17 @@+module Main where++import Data.List (sort, nub)+import qualified Data.Map.Strict as Map+import Other (process)++main :: IO ()+main = do+  let xs = [3, 1, 4, 1, 5, 9, 2, 6] :: [Int]+  let m = Map.fromList [("a", 1), ("b", 2)] :: Map.Map String Int+  check xs m+  process xs++check :: [Int] -> Map.Map String Int -> IO ()+check xs m = do+  print xs+  print m
+ test/integration/standalone-multi-module/Helper.hs view
@@ -0,0 +1,5 @@+module Helper where++greet :: String -> IO ()+greet name = do+  putStrLn ("Hello, " ++ name ++ "!")
+ test/integration/standalone-multi-module/Main.hs view
@@ -0,0 +1,9 @@+module Main where++import Helper++main :: IO ()+main = do+  putStrLn "Starting..."+  greet "world"+  putStrLn "Done."