@@ -6,6 +6,7 @@ module Development.IDE.Types.HscEnvEq
6
6
newHscEnvEqWithImportPaths,
7
7
envImportPaths,
8
8
envPackageExports,
9
+ envVisibleModuleNames,
9
10
deps
10
11
) where
11
12
@@ -16,7 +17,7 @@ import Development.Shake.Classes
16
17
import Module (InstalledUnitId )
17
18
import System.Directory (canonicalizePath )
18
19
import Development.IDE.GHC.Compat
19
- import GhcPlugins (HscEnv (hsc_dflags ), PackageState (explicitPackages ), InstalledPackageInfo (exposedModules ), Module (.. ), packageConfigId )
20
+ import GhcPlugins (HscEnv (hsc_dflags ), PackageState (explicitPackages ), InstalledPackageInfo (exposedModules ), Module (.. ), packageConfigId , listVisibleModuleNames )
20
21
import System.FilePath
21
22
import Development.IDE.GHC.Util (lookupPackageConfig )
22
23
import Control.Monad.IO.Class
@@ -27,7 +28,10 @@ import OpenTelemetry.Eventlog (withSpan)
27
28
import Control.Monad.Extra (mapMaybeM , join , eitherM )
28
29
import Control.Concurrent.Extra (newVar , modifyVar )
29
30
import Control.Concurrent.Async (Async , async , waitCatch )
30
- import Control.Exception (throwIO , mask )
31
+ import Control.Exception (throwIO , mask , evaluate )
32
+ import Development.IDE.GHC.Error (catchSrcErrors )
33
+ import Control.DeepSeq (force )
34
+ import Data.Either (fromRight )
31
35
32
36
-- | An 'HscEnv' with equality. Two values are considered equal
33
37
-- if they are created with the same call to 'newHscEnvEq'.
@@ -42,6 +46,11 @@ data HscEnvEq = HscEnvEq
42
46
-- ^ If Just, import dirs originally configured in this env
43
47
-- If Nothing, the env import dirs are unaltered
44
48
, envPackageExports :: IO ExportsMap
49
+ , envVisibleModuleNames :: IO (Maybe [ModuleName ])
50
+ -- ^ 'listVisibleModuleNames' is a pure function,
51
+ -- but it could panic due to a ghc bug: https://github.com/haskell/haskell-language-server/issues/1365
52
+ -- So it's wrapped in IO here for error handling
53
+ -- If Nothing, 'listVisibleModuleNames' panic
45
54
}
46
55
47
56
-- | Wrap an 'HscEnv' into an 'HscEnvEq'.
@@ -58,12 +67,15 @@ newHscEnvEq cradlePath hscEnv0 deps = do
58
67
59
68
newHscEnvEqWithImportPaths :: Maybe [String ] -> HscEnv -> [(InstalledUnitId , DynFlags )] -> IO HscEnvEq
60
69
newHscEnvEqWithImportPaths envImportPaths hscEnv deps = do
70
+
71
+ let dflags = hsc_dflags hscEnv
72
+
61
73
envUnique <- newUnique
62
74
63
75
-- it's very important to delay the package exports computation
64
76
envPackageExports <- onceAsync $ withSpan " Package Exports" $ \ _sp -> do
65
77
-- compute the package imports
66
- let pkgst = pkgState (hsc_dflags hscEnv)
78
+ let pkgst = pkgState dflags
67
79
depends = explicitPackages pkgst
68
80
targets =
69
81
[ (pkg, mn)
@@ -82,6 +94,15 @@ newHscEnvEqWithImportPaths envImportPaths hscEnv deps = do
82
94
Maybes. Succeeded mi -> Just mi
83
95
modIfaces <- mapMaybeM doOne targets
84
96
return $ createExportsMap modIfaces
97
+
98
+ -- similar to envPackageExports, evaluated lazily
99
+ envVisibleModuleNames <- onceAsync $
100
+ fromRight Nothing
101
+ <$> catchSrcErrors
102
+ dflags
103
+ " listVisibleModuleNames"
104
+ (evaluate . force . Just $ listVisibleModuleNames dflags)
105
+
85
106
return HscEnvEq {.. }
86
107
87
108
-- | Wrap an 'HscEnv' into an 'HscEnvEq'.
@@ -108,8 +129,8 @@ instance Eq HscEnvEq where
108
129
a == b = envUnique a == envUnique b
109
130
110
131
instance NFData HscEnvEq where
111
- rnf (HscEnvEq a b c d _) =
112
- -- deliberately skip the package exports map
132
+ rnf (HscEnvEq a b c d _ _ ) =
133
+ -- deliberately skip the package exports map and visible module names
113
134
rnf (hashUnique a) `seq` b `seq` c `seq` rnf d
114
135
115
136
instance Hashable HscEnvEq where
0 commit comments