Skip to content

Commit e0d82e7

Browse files
authored
Pedantic ghcide (#3751)
1 parent ccd4b11 commit e0d82e7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1360
-1225
lines changed

.github/workflows/flags.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ jobs:
7575
- name: Build `ghcide` with flags
7676
run: cabal v2-build ghcide --flags="ghc-patched-unboxed-bytecode test-exe executable bench-exe ekg"
7777

78-
# we have to clean up warnings for 9.0 and 9.2 before enable -Wall
79-
- if: matrix.ghc != '9.0' && matrix.ghc != '9.2'
78+
# wingman fails with flags on 9.0, so this can be removed when that's gone
79+
- if: matrix.ghc != '9.0'
8080
name: Build with pedantic (-WError)
8181
run: cabal v2-build --flags="pedantic"
8282

ghcide/ghcide.cabal

+26-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ flag ekg
3535
default: False
3636
manual: True
3737

38+
flag pedantic
39+
description: Enable -Werror
40+
default: False
41+
manual: True
42+
3843
library
3944
default-language: Haskell2010
4045
build-depends:
@@ -221,14 +226,34 @@ library
221226

222227
ghc-options:
223228
-Wall
224-
-Wno-name-shadowing
225229
-Wincomplete-uni-patterns
226230
-Wno-unticked-promoted-constructors
227231
-fno-ignore-asserts
228232

229233
if flag(ghc-patched-unboxed-bytecode)
230234
cpp-options: -DGHC_PATCHED_UNBOXED_BYTECODE
231235

236+
if flag(pedantic)
237+
-- We eventually want to build with Werror fully, but we haven't
238+
-- finished purging the warnings, so some are set to not be errors
239+
-- for now
240+
ghc-options: -Werror
241+
-Wwarn=unused-packages
242+
-Wwarn=unrecognised-pragmas
243+
-Wwarn=dodgy-imports
244+
-Wwarn=missing-signatures
245+
-Wwarn=duplicate-exports
246+
-Wwarn=dodgy-exports
247+
-Wwarn=incomplete-patterns
248+
-Wwarn=overlapping-patterns
249+
-Wwarn=incomplete-record-updates
250+
251+
-- ambiguous-fields is only understood by GHC >= 9.2, so we only disable it
252+
-- then. The above comment goes for here too -- this should be understood to
253+
-- be temporary until we can remove these warnings.
254+
if impl(ghc >= 9.2) && flag(pedantic)
255+
ghc-options: -Wwarn=ambiguous-fields
256+
232257
if impl(ghc >= 9)
233258
ghc-options: -Wunused-packages
234259

ghcide/session-loader/Development/IDE/Session.hs

+50-51
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,8 @@ import Data.Char (isLower)
3838
import Data.Default
3939
import Data.Either.Extra
4040
import Data.Function
41-
import Data.Hashable
41+
import Data.Hashable hiding (hash)
4242
import qualified Data.HashMap.Strict as HM
43-
import Data.IORef
4443
import Data.List
4544
import Data.List.Extra (dropPrefix, split)
4645
import qualified Data.Map.Strict as Map
@@ -51,11 +50,11 @@ import Data.Time.Clock
5150
import Data.Version
5251
import Development.IDE.Core.RuleTypes
5352
import Development.IDE.Core.Shake hiding (Log, Priority,
54-
withHieDb)
53+
knownTargets, withHieDb)
5554
import qualified Development.IDE.GHC.Compat as Compat
5655
import Development.IDE.GHC.Compat.Core hiding (Target,
5756
TargetFile, TargetModule,
58-
Var, Warning)
57+
Var, Warning, getOptions)
5958
import qualified Development.IDE.GHC.Compat.Core as GHC
6059
import Development.IDE.GHC.Compat.Env hiding (Logger)
6160
import Development.IDE.GHC.Compat.Units (UnitId)
@@ -111,6 +110,12 @@ import HieDb.Utils
111110
import qualified System.Random as Random
112111
import System.Random (RandomGen)
113112

113+
-- See Note [Guidelines For Using CPP In GHCIDE Import Statements]
114+
115+
#if !MIN_VERSION_ghc(9,4,0)
116+
import Data.IORef
117+
#endif
118+
114119
data Log
115120
= LogSettingInitialDynFlags
116121
| LogGetInitialGhcLibDirDefaultCradleFail !CradleError !FilePath !(Maybe FilePath) !(Cradle Void)
@@ -148,21 +153,21 @@ instance Pretty Log where
148153
, "Cradle:" <+> viaShow cradle ]
149154
LogGetInitialGhcLibDirDefaultCradleNone ->
150155
"Couldn't load cradle. Cradle not found."
151-
LogHieDbRetry delay maxDelay maxRetryCount e ->
156+
LogHieDbRetry delay maxDelay retriesRemaining e ->
152157
nest 2 $
153158
vcat
154159
[ "Retrying hiedb action..."
155160
, "delay:" <+> pretty delay
156161
, "maximum delay:" <+> pretty maxDelay
157-
, "retries remaining:" <+> pretty maxRetryCount
162+
, "retries remaining:" <+> pretty retriesRemaining
158163
, "SQLite error:" <+> pretty (displayException e) ]
159-
LogHieDbRetriesExhausted baseDelay maxDelay maxRetryCount e ->
164+
LogHieDbRetriesExhausted baseDelay maxDelay retriesRemaining e ->
160165
nest 2 $
161166
vcat
162167
[ "Retries exhausted for hiedb action."
163168
, "base delay:" <+> pretty baseDelay
164169
, "maximum delay:" <+> pretty maxDelay
165-
, "retries remaining:" <+> pretty maxRetryCount
170+
, "retries remaining:" <+> pretty retriesRemaining
166171
, "Exception:" <+> pretty (displayException e) ]
167172
LogHieDbWriterThreadSQLiteError e ->
168173
nest 2 $
@@ -199,7 +204,7 @@ instance Pretty Log where
199204
"Cradle:" <+> viaShow cradle
200205
LogNewComponentCache componentCache ->
201206
"New component cache HscEnvEq:" <+> viaShow componentCache
202-
LogHieBios log -> pretty log
207+
LogHieBios msg -> pretty msg
203208

204209
-- | Bump this version number when making changes to the format of the data stored in hiedb
205210
hiedbDataVersion :: String
@@ -263,17 +268,16 @@ loadWithImplicitCradle mHieYaml rootDir = do
263268

264269
getInitialGhcLibDirDefault :: Recorder (WithPriority Log) -> FilePath -> IO (Maybe LibDir)
265270
getInitialGhcLibDirDefault recorder rootDir = do
266-
let log = logWith recorder
267271
hieYaml <- findCradle def rootDir
268272
cradle <- loadCradle def hieYaml rootDir
269273
libDirRes <- getRuntimeGhcLibDir (toCologActionWithPrio (cmapWithPrio LogHieBios recorder)) cradle
270274
case libDirRes of
271275
CradleSuccess libdir -> pure $ Just $ LibDir libdir
272276
CradleFail err -> do
273-
log Error $ LogGetInitialGhcLibDirDefaultCradleFail err rootDir hieYaml cradle
277+
logWith recorder Error $ LogGetInitialGhcLibDirDefaultCradleFail err rootDir hieYaml cradle
274278
pure Nothing
275279
CradleNone -> do
276-
log Warning LogGetInitialGhcLibDirDefaultCradleNone
280+
logWith recorder Warning LogGetInitialGhcLibDirDefaultCradleNone
277281
pure Nothing
278282

279283
-- | Sets `unsafeGlobalDynFlags` on using the hie-bios cradle and returns the GHC libdir
@@ -301,28 +305,26 @@ retryOnException
301305
-> g -- ^ random number generator
302306
-> m a -- ^ action that may throw exception
303307
-> m a
304-
retryOnException exceptionPred recorder maxDelay !baseDelay !maxRetryCount rng action = do
308+
retryOnException exceptionPred recorder maxDelay !baseDelay !maxTimesRetry rng action = do
305309
result <- tryJust exceptionPred action
306310
case result of
307311
Left e
308-
| maxRetryCount > 0 -> do
312+
| maxTimesRetry > 0 -> do
309313
-- multiply by 2 because baseDelay is midpoint of uniform range
310314
let newBaseDelay = min maxDelay (baseDelay * 2)
311315
let (delay, newRng) = Random.randomR (0, newBaseDelay) rng
312-
let newMaxRetryCount = maxRetryCount - 1
316+
let newMaxTimesRetry = maxTimesRetry - 1
313317
liftIO $ do
314-
log Warning $ LogHieDbRetry delay maxDelay newMaxRetryCount (toException e)
318+
logWith recorder Warning $ LogHieDbRetry delay maxDelay newMaxTimesRetry (toException e)
315319
threadDelay delay
316-
retryOnException exceptionPred recorder maxDelay newBaseDelay newMaxRetryCount newRng action
320+
retryOnException exceptionPred recorder maxDelay newBaseDelay newMaxTimesRetry newRng action
317321

318322
| otherwise -> do
319323
liftIO $ do
320-
log Warning $ LogHieDbRetriesExhausted baseDelay maxDelay maxRetryCount (toException e)
324+
logWith recorder Warning $ LogHieDbRetriesExhausted baseDelay maxDelay maxTimesRetry (toException e)
321325
throwIO e
322326

323327
Right b -> pure b
324-
where
325-
log = logWith recorder
326328

327329
-- | in microseconds
328330
oneSecond :: Int
@@ -377,21 +379,19 @@ runWithDb recorder fp k = do
377379
withAsync (writerThread withWriteDbRetryable chan) $ \_ -> do
378380
withHieDb fp (\readDb -> k (makeWithHieDbRetryable recorder rng readDb) chan)
379381
where
380-
log = logWith recorder
381-
382382
writerThread :: WithHieDb -> IndexQueue -> IO ()
383383
writerThread withHieDbRetryable chan = do
384384
-- Clear the index of any files that might have been deleted since the last run
385385
_ <- withHieDbRetryable deleteMissingRealFiles
386386
_ <- withHieDbRetryable garbageCollectTypeNames
387387
forever $ do
388-
k <- atomically $ readTQueue chan
388+
l <- atomically $ readTQueue chan
389389
-- TODO: probably should let exceptions be caught/logged/handled by top level handler
390-
k withHieDbRetryable
390+
l withHieDbRetryable
391391
`Safe.catch` \e@SQLError{} -> do
392-
log Error $ LogHieDbWriterThreadSQLiteError e
393-
`Safe.catchAny` \e -> do
394-
log Error $ LogHieDbWriterThreadException e
392+
logWith recorder Error $ LogHieDbWriterThreadSQLiteError e
393+
`Safe.catchAny` \f -> do
394+
logWith recorder Error $ LogHieDbWriterThreadException f
395395

396396

397397
getHieDbLoc :: FilePath -> IO FilePath
@@ -520,7 +520,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
520520
-- We will modify the unitId and DynFlags used for
521521
-- compilation but these are the true source of
522522
-- information.
523-
523+
524524
new_deps = RawComponentInfo (homeUnitId_ df) df targets cfp opts dep_info
525525
: maybe [] snd oldDeps
526526
-- Get all the unit-ids for things in this component
@@ -532,7 +532,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
532532
#if MIN_VERSION_ghc(9,3,0)
533533
let (df2, uids) = (rawComponentDynFlags, [])
534534
#else
535-
let (df2, uids) = removeInplacePackages fakeUid inplace rawComponentDynFlags
535+
let (df2, uids) = _removeInplacePackages fakeUid inplace rawComponentDynFlags
536536
#endif
537537
let prefix = show rawComponentUnitId
538538
-- See Note [Avoiding bad interface files]
@@ -554,11 +554,11 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
554554
-- scratch again (for now)
555555
-- It's important to keep the same NameCache though for reasons
556556
-- that I do not fully understand
557-
log Info $ LogMakingNewHscEnv inplace
558-
hscEnv <- emptyHscEnv ideNc libDir
557+
logWith recorder Info $ LogMakingNewHscEnv inplace
558+
hscEnvB <- emptyHscEnv ideNc libDir
559559
!newHscEnv <-
560560
-- Add the options for the current component to the HscEnv
561-
evalGhcEnv hscEnv $ do
561+
evalGhcEnv hscEnvB $ do
562562
_ <- setSessionDynFlags
563563
#if !MIN_VERSION_ghc(9,3,0)
564564
$ setHomeUnitId_ fakeUid
@@ -595,7 +595,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
595595
res <- loadDLL hscEnv "libm.so.6"
596596
case res of
597597
Nothing -> pure ()
598-
Just err -> log Error $ LogDLLLoadError err
598+
Just err -> logWith recorder Error $ LogDLLLoadError err
599599

600600

601601
-- Make a map from unit-id to DynFlags, this is used when trying to
@@ -637,21 +637,22 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
637637
let cs_exist = catMaybes (zipWith (<$) cfps' mmt)
638638
modIfaces <- uses GetModIface cs_exist
639639
-- update exports map
640-
extras <- getShakeExtras
640+
shakeExtras <- getShakeExtras
641641
let !exportsMap' = createExportsMap $ mapMaybe (fmap hirModIface) modIfaces
642-
liftIO $ atomically $ modifyTVar' (exportsMap extras) (exportsMap' <>)
642+
liftIO $ atomically $ modifyTVar' (exportsMap shakeExtras) (exportsMap' <>)
643643

644644
return (second Map.keys res)
645645

646646
let consultCradle :: Maybe FilePath -> FilePath -> IO (IdeResult HscEnvEq, [FilePath])
647647
consultCradle hieYaml cfp = do
648-
lfp <- flip makeRelative cfp <$> getCurrentDirectory
649-
log Info $ LogCradlePath lfp
648+
lfpLog <- flip makeRelative cfp <$> getCurrentDirectory
649+
logWith recorder Info $ LogCradlePath lfpLog
650650

651651
when (isNothing hieYaml) $
652-
log Warning $ LogCradleNotFound lfp
652+
logWith recorder Warning $ LogCradleNotFound lfpLog
653653

654654
cradle <- loadCradle hieYaml dir
655+
-- TODO: Why are we repeating the same command we have on line 646?
655656
lfp <- flip makeRelative cfp <$> getCurrentDirectory
656657

657658
when optTesting $ mRunLspT lspEnv $
@@ -667,7 +668,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
667668
addTag "result" (show res)
668669
return res
669670

670-
log Debug $ LogSessionLoadingResult eopts
671+
logWith recorder Debug $ LogSessionLoadingResult eopts
671672
case eopts of
672673
-- The cradle gave us some options so get to work turning them
673674
-- into and HscEnv.
@@ -727,11 +728,9 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
727728
opts <- liftIO $ join $ mask_ $ modifyVar runningCradle $ \as -> do
728729
-- If the cradle is not finished, then wait for it to finish.
729730
void $ wait as
730-
as <- async $ getOptions file
731-
return (as, wait as)
731+
asyncRes <- async $ getOptions file
732+
return (asyncRes, wait asyncRes)
732733
pure opts
733-
where
734-
log = logWith recorder
735734

736735
-- | Run the specific cradle on a specific FilePath via hie-bios.
737736
-- This then builds dependencies or whatever based on the cradle, gets the
@@ -787,14 +786,14 @@ fromTargetId :: [FilePath] -- ^ import paths
787786
-> DependencyInfo
788787
-> IO [TargetDetails]
789788
-- For a target module we consider all the import paths
790-
fromTargetId is exts (GHC.TargetModule mod) env dep = do
791-
let fps = [i </> moduleNameSlashes mod -<.> ext <> boot
789+
fromTargetId is exts (GHC.TargetModule modName) env dep = do
790+
let fps = [i </> moduleNameSlashes modName -<.> ext <> boot
792791
| ext <- exts
793792
, i <- is
794793
, boot <- ["", "-boot"]
795794
]
796795
locs <- mapM (fmap toNormalizedFilePath' . makeAbsolute) fps
797-
return [TargetDetails (TargetModule mod) env dep locs]
796+
return [TargetDetails (TargetModule modName) env dep locs]
798797
-- For a 'TargetFile' we consider all the possible module names
799798
fromTargetId _ _ (GHC.TargetFile f _) env deps = do
800799
nf <- toNormalizedFilePath' <$> makeAbsolute f
@@ -1059,11 +1058,11 @@ getDependencyInfo :: [FilePath] -> IO DependencyInfo
10591058
getDependencyInfo fs = Map.fromList <$> mapM do_one fs
10601059

10611060
where
1062-
tryIO :: IO a -> IO (Either IOException a)
1063-
tryIO = Safe.try
1061+
safeTryIO :: IO a -> IO (Either IOException a)
1062+
safeTryIO = Safe.try
10641063

10651064
do_one :: FilePath -> IO (FilePath, Maybe UTCTime)
1066-
do_one fp = (fp,) . eitherToMaybe <$> tryIO (getModificationTime fp)
1065+
do_one fp = (fp,) . eitherToMaybe <$> safeTryIO (getModificationTime fp)
10671066

10681067
-- | This function removes all the -package flags which refer to packages we
10691068
-- are going to deal with ourselves. For example, if a executable depends
@@ -1073,12 +1072,12 @@ getDependencyInfo fs = Map.fromList <$> mapM do_one fs
10731072
-- There are several places in GHC (for example the call to hptInstances in
10741073
-- tcRnImports) which assume that all modules in the HPT have the same unit
10751074
-- ID. Therefore we create a fake one and give them all the same unit id.
1076-
removeInplacePackages
1075+
_removeInplacePackages --Only used in ghc < 9.4
10771076
:: UnitId -- ^ fake uid to use for our internal component
10781077
-> [UnitId]
10791078
-> DynFlags
10801079
-> (DynFlags, [UnitId])
1081-
removeInplacePackages fake_uid us df = (setHomeUnitId_ fake_uid $
1080+
_removeInplacePackages fake_uid us df = (setHomeUnitId_ fake_uid $
10821081
df { packageFlags = ps }, uids)
10831082
where
10841083
(uids, ps) = Compat.filterInplaceUnits us (packageFlags df)

ghcide/src/Development/IDE/Core/Actions.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ getAtPoint file pos = runMaybeT $ do
6767
!pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
6868
MaybeT $ liftIO $ fmap (first (toCurrentRange mapping =<<)) <$> AtPoint.atPoint opts hf dkMap env pos'
6969

70-
-- | For each Loacation, determine if we have the PositionMapping
70+
-- | For each Location, determine if we have the PositionMapping
7171
-- for the correct file. If not, get the correct position mapping
7272
-- and then apply the position mapping to the location.
7373
toCurrentLocations

0 commit comments

Comments
 (0)