Skip to content

Commit

Permalink
Simplify implementation of eval plugin and make it work with GHC 9.4
Browse files Browse the repository at this point in the history
The plugin was implemented by calling "load" which circumvents all of
HLSs caching mechanisms for interface files and linkables. Instead we
should work like the other typechecking functions which get all the
stuff we need using HLS rules and setup the HscEnv with all the state in
the right places.

The key part to this is setting up all the HPT modules with linkables if
they are depenedencies of the module we are trying to run a function
from.

- ban load functions from GHC driver

- Enable CI for hls-eval-plugin and fix a bug due to clearing of mi_globals
  • Loading branch information
mpickering authored and wz1000 committed Feb 21, 2023
1 parent a73c07c commit f012e04
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 245 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ jobs:
name: Test hls-pragmas-plugin
run: cabal test hls-pragmas-plugin --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-pragmas-plugin --test-options="$TEST_OPTS"

- if: matrix.test && matrix.ghc != '9.4.4'
- if: matrix.test
name: Test hls-eval-plugin
run: cabal test hls-eval-plugin --test-options="$TEST_OPTS" || LSP_TEST_LOG_COLOR=0 LSP_TEST_LOG_MESSAGES=true LSP_TEST_LOG_STDERR=true cabal test hls-eval-plugin --test-options="$TEST_OPTS"

Expand Down
10 changes: 10 additions & 0 deletions .hlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@
- name: "GHC.Arr.!"
within: []

# We do not want to use functions from the
# GHC driver. Instead use hls rules to construct
# an appropriate GHC session
- name: "load"
within: []
- name: "load'"
within: []
- name: "loadWithCache"
within: []

# Tracing functions
# We ban an explicit list rather than the
# Debug.Trace, because that module also
Expand Down
22 changes: 0 additions & 22 deletions ghcide/src/Development/IDE/Core/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,28 +1008,6 @@ handleGenerationErrors' dflags source action =
. (("Error during " ++ T.unpack source) ++) . show @SomeException
]

-- | Load modules, quickly. Input doesn't need to be desugared.
-- A module must be loaded before dependent modules can be typechecked.
-- This variant of loadModuleHome will *never* cause recompilation, it just
-- modifies the session.
-- The order modules are loaded is important when there are hs-boot files.
-- In particular you should make sure to load the .hs version of a file after the
-- .hs-boot version.
loadModulesHome
:: [HomeModInfo]
-> HscEnv
-> HscEnv
loadModulesHome mod_infos e =
#if MIN_VERSION_ghc(9,3,0)
hscUpdateHUG (\hug -> foldl' (flip addHomeModInfoToHug) hug mod_infos) (e { hsc_type_env_vars = emptyKnotVars })
#else
let !new_modules = addListToHpt (hsc_HPT e) [(mod_name x, x) | x <- mod_infos]
in e { hsc_HPT = new_modules
, hsc_type_env_var = Nothing
}
where
mod_name = moduleName . mi_module . hm_iface
#endif

-- Merge the HPTs, module graphs and FinderCaches
-- See Note [GhcSessionDeps] in Development.IDE.Core.Rules
Expand Down
1 change: 1 addition & 0 deletions ghcide/src/Development/IDE/Core/Rules.hs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ module Development.IDE.Core.Rules(
typeCheckRuleDefinition,
getRebuildCount,
getSourceFileSource,
currentLinkables,
GhcSessionDepsConfig(..),
Log(..),
DisplayTHWarning(..),
Expand Down
24 changes: 24 additions & 0 deletions ghcide/src/Development/IDE/GHC/Compat.hs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ module Development.IDE.GHC.Compat(
icInteractiveModule,
HomePackageTable,
lookupHpt,
loadModulesHome,
#if MIN_VERSION_ghc(9,3,0)
Dependencies(dep_direct_mods),
#else
Expand Down Expand Up @@ -653,3 +654,26 @@ combineRealSrcSpans span1 span2
(srcSpanEndLine span2, srcSpanEndCol span2)
file = srcSpanFile span1
#endif

-- | Load modules, quickly. Input doesn't need to be desugared.
-- A module must be loaded before dependent modules can be typechecked.
-- This variant of loadModuleHome will *never* cause recompilation, it just
-- modifies the session.
-- The order modules are loaded is important when there are hs-boot files.
-- In particular you should make sure to load the .hs version of a file after the
-- .hs-boot version.
loadModulesHome
:: [HomeModInfo]
-> HscEnv
-> HscEnv
loadModulesHome mod_infos e =
#if MIN_VERSION_ghc(9,3,0)
hscUpdateHUG (\hug -> foldl' (flip addHomeModInfoToHug) hug mod_infos) (e { hsc_type_env_vars = emptyKnotVars })
#else
let !new_modules = addListToHpt (hsc_HPT e) [(mod_name x, x) | x <- mod_infos]
in e { hsc_HPT = new_modules
, hsc_type_env_var = Nothing
}
where
mod_name = moduleName . mi_module . hm_iface
#endif
2 changes: 1 addition & 1 deletion ghcide/src/Development/IDE/GHC/Compat/Core.hs
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,7 @@ pattern ExposePackage s a mr = DynFlags.ExposePackage s a mr
pattern FunTy :: Type -> Type -> Type
pattern FunTy arg res <- TyCoRep.FunTy {ft_arg = arg, ft_res = res}

#if MIN_VERSION_ghc(9,0,0)
#if MIN_VERSION_ghc(8,10,0)
-- type HasSrcSpan x a = (GenLocated SrcSpan a ~ x)
-- type HasSrcSpan x = () :: Constraint

Expand Down
8 changes: 8 additions & 0 deletions ghcide/src/Development/IDE/GHC/Compat/Outputable.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ module Development.IDE.GHC.Compat.Outputable (
#if MIN_VERSION_ghc(9,3,0)
DiagnosticReason(..),
renderDiagnosticMessageWithHints,
pprMsgEnvelopeBagWithLoc,
Error.getMessages,
renderWithContext,
defaultSDocContext,
errMsgDiagnostic,
unDecorated,
diagnosticMessage,
#else
pprWarning,
pprError,
Expand All @@ -29,6 +36,7 @@ module Development.IDE.GHC.Compat.Outputable (
MsgEnvelope,
ErrMsg,
WarnMsg,
SourceError(..),
errMsgSpan,
errMsgSeverity,
formatErrorWithQual,
Expand Down
7 changes: 5 additions & 2 deletions ghcide/src/Development/IDE/GHC/Compat/Util.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ module Development.IDE.GHC.Compat.Util (
LBooleanFormula,
BooleanFormula(..),
-- * OverridingBool
#if !MIN_VERSION_ghc(9,3,0)
OverridingBool(..),
#endif
-- * Maybes
MaybeErr(..),
orElse,
Expand Down Expand Up @@ -104,6 +102,11 @@ import Unique
import Util
#endif

#if MIN_VERSION_ghc(9,3,0)
import GHC.Data.Bool
#endif


#if !MIN_VERSION_ghc(9,0,0)
type MonadCatch = Exception.ExceptionMonad

Expand Down
2 changes: 1 addition & 1 deletion haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ common haddockComments
cpp-options: -Dhls_haddockComments

common eval
if flag(eval) && (impl(ghc < 9.4.1) || flag(ignore-plugins-ghc-bounds))
if flag(eval)
build-depends: hls-eval-plugin ^>= 1.4
cpp-options: -Dhls_eval

Expand Down
8 changes: 0 additions & 8 deletions plugins/hls-eval-plugin/hls-eval-plugin.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ source-repository head
location: https://github.com/haskell/haskell-language-server

library
if impl(ghc >= 9.3)
buildable: False
else
buildable: True
exposed-modules:
Ide.Plugin.Eval
Ide.Plugin.Eval.Types
Expand Down Expand Up @@ -101,10 +97,6 @@ library
TypeOperators

test-suite tests
if impl(ghc >= 9.3)
buildable: False
else
buildable: True
type: exitcode-stdio-1.0
default-language: Haskell2010
hs-source-dirs: test
Expand Down
8 changes: 1 addition & 7 deletions plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Code.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{-# OPTIONS_GHC -Wwarn -fno-warn-orphans #-}

-- | Expression execution
module Ide.Plugin.Eval.Code (Statement, testRanges, resultRange, evalSetup, propSetup, testCheck, asStatements,myExecStmt) where
module Ide.Plugin.Eval.Code (Statement, testRanges, resultRange, propSetup, testCheck, asStatements,myExecStmt) where

import Control.Lens ((^.))
import Control.Monad.IO.Class
Expand Down Expand Up @@ -80,12 +80,6 @@ asStmts (Property t _ _) =
["prop11 = " ++ t, "(propEvaluation prop11 :: IO String)"]


-- |GHC declarations required for expression evaluation
evalSetup :: Ghc ()
evalSetup = do
preludeAsP <- parseImportDecl "import qualified Prelude as P"
context <- getContext
setContext (IIDecl preludeAsP : context)

-- | A wrapper of 'InteractiveEval.execStmt', capturing the execution result
myExecStmt :: String -> ExecOptions -> Ghc (Either String (Maybe String))
Expand Down
Loading

0 comments on commit f012e04

Please # to comment.