ghcide 1.10.0.0 → 2.0.0.0
raw patch · 6 files changed
+132/−108 lines, 6 filesdep ~hls-graphdep ~hls-plugin-apiPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hls-graph, hls-plugin-api
API changes (from Hackage documentation)
- Development.IDE.Main: LogOnlyPartialGhc94Support :: Log
+ Development.IDE.GHC.Compat.Core: groupOrigin :: MatchGroup p body -> Origin
Files
- ghcide.cabal +3/−3
- src/Development/IDE/GHC/Compat/Core.hs +3/−0
- src/Development/IDE/LSP/LanguageServer.hs +3/−0
- src/Development/IDE/Main.hs +0/−6
- src/Development/IDE/Plugin/TypeLenses.hs +108/−92
- test/exe/Main.hs +15/−7
ghcide.cabal view
@@ -2,7 +2,7 @@ build-type: Simple category: Development name: ghcide-version: 1.10.0.0+version: 2.0.0.0 license: Apache-2.0 license-file: LICENSE author: Digital Asset and Ghcide contributors@@ -65,7 +65,7 @@ haddock-library >= 1.8 && < 1.12, hashable, hie-compat ^>= 0.3.0.0,- hls-plugin-api ^>= 1.6,+ hls-plugin-api == 2.0.0.0, lens, list-t, hiedb == 0.4.3.*,@@ -80,7 +80,7 @@ regex-tdfa >= 1.3.1.0, text-rope, safe-exceptions,- hls-graph ^>= 1.9,+ hls-graph == 2.0.0.0, sorted-list, sqlite-simple, stm,
src/Development/IDE/GHC/Compat/Core.hs view
@@ -496,6 +496,7 @@ # if !MIN_VERSION_ghc(9,5,0) field_label, #endif+ groupOrigin, ) where import qualified GHC@@ -1197,9 +1198,11 @@ mkVisFunTys = mkScaledFunctionTys mapLoc :: (a -> b) -> SrcLoc.GenLocated l a -> SrcLoc.GenLocated l b mapLoc = fmap+groupOrigin = mg_ext #else mapLoc :: (a -> b) -> SrcLoc.GenLocated l a -> SrcLoc.GenLocated l b mapLoc = SrcLoc.mapLoc+groupOrigin = mg_origin #endif
src/Development/IDE/LSP/LanguageServer.hs view
@@ -61,6 +61,9 @@ instance Pretty Log where pretty = \case LogRegisteringIdeConfig ideConfig ->+ -- This log is also used to identify if HLS starts successfully in vscode-haskell,+ -- don't forget to update the corresponding test in vscode-haskell if the text in+ -- the next line has been modified. "Registering IDE configuration:" <+> viaShow ideConfig LogReactorThreadException e -> vcat
src/Development/IDE/Main.hs view
@@ -135,7 +135,6 @@ | LogLspStart [PluginId] | LogLspStartDuration !Seconds | LogShouldRunSubset !Bool- | LogOnlyPartialGhc94Support | LogSetInitialDynFlagsException !SomeException | LogService Service.Log | LogShake Shake.Log@@ -159,8 +158,6 @@ "Started LSP server in" <+> pretty (showDuration duration) LogShouldRunSubset shouldRunSubset -> "shouldRunSubset:" <+> pretty shouldRunSubset- LogOnlyPartialGhc94Support ->- "Currently, HLS supports GHC 9.4 only partially. See [issue #3190](https://github.com/haskell/haskell-language-server/issues/3190) for more detail." LogSetInitialDynFlagsException e -> "setInitialDynFlags:" <+> pretty (displayException e) LogService log -> pretty log@@ -341,9 +338,6 @@ , optRunSubset = runSubset } caps = LSP.resClientCapabilities env- -- FIXME: Remove this after GHC 9.4 gets fully supported- when (ghcVersion == GHC94) $- log Warning LogOnlyPartialGhc94Support monitoring <- argsMonitoring initialise (cmapWithPrio LogService recorder)
src/Development/IDE/Plugin/TypeLenses.hs view
@@ -13,65 +13,68 @@ Log(..) ) where -import Control.Concurrent.STM.Stats (atomically)-import Control.DeepSeq (rwhnf)-import Control.Monad (mzero)-import Control.Monad.Extra (whenMaybe)-import Control.Monad.IO.Class (MonadIO (liftIO))-import Data.Aeson.Types (Value (..), toJSON)-import qualified Data.Aeson.Types as A-import qualified Data.HashMap.Strict as Map-import Data.List (find)-import Data.Maybe (catMaybes)-import qualified Data.Text as T-import Development.IDE (GhcSession (..),- HscEnvEq (hscEnv),- RuleResult, Rules, define,- srcSpanToRange,- usePropertyAction)-import Development.IDE.Core.Compile (TcModuleResult (..))-import Development.IDE.Core.Rules (IdeState, runAction)-import Development.IDE.Core.RuleTypes (GetBindings (GetBindings),- TypeCheck (TypeCheck))-import Development.IDE.Core.Service (getDiagnostics)-import Development.IDE.Core.Shake (getHiddenDiagnostics, use)-import qualified Development.IDE.Core.Shake as Shake+import Control.Concurrent.STM.Stats (atomically)+import Control.DeepSeq (rwhnf)+import Control.Monad (mzero)+import Control.Monad.Extra (whenMaybe)+import Control.Monad.IO.Class (MonadIO (liftIO))+import Data.Aeson.Types (Value (..), toJSON)+import qualified Data.Aeson.Types as A+import qualified Data.HashMap.Strict as Map+import Data.List (find)+import Data.Maybe (catMaybes, mapMaybe)+import qualified Data.Text as T+import Development.IDE (GhcSession (..),+ HscEnvEq (hscEnv),+ RuleResult, Rules,+ define, srcSpanToRange,+ usePropertyAction,+ useWithStale)+import Development.IDE.Core.Compile (TcModuleResult (..))+import Development.IDE.Core.PositionMapping (PositionMapping,+ toCurrentRange)+import Development.IDE.Core.Rules (IdeState, runAction)+import Development.IDE.Core.RuleTypes (GetBindings (GetBindings),+ TypeCheck (TypeCheck))+import Development.IDE.Core.Service (getDiagnostics)+import Development.IDE.Core.Shake (getHiddenDiagnostics,+ use)+import qualified Development.IDE.Core.Shake as Shake import Development.IDE.GHC.Compat-import Development.IDE.GHC.Util (printName)+import Development.IDE.GHC.Util (printName) import Development.IDE.Graph.Classes-import Development.IDE.Spans.LocalBindings (Bindings, getFuzzyScope)-import Development.IDE.Types.Location (Position (Position, _character, _line),- Range (Range, _end, _start),- toNormalizedFilePath',- uriToFilePath')-import Development.IDE.Types.Logger (Pretty (pretty), Recorder,- WithPriority,- cmapWithPrio)-import GHC.Generics (Generic)-import Ide.Plugin.Config (Config)+import Development.IDE.Spans.LocalBindings (Bindings, getFuzzyScope)+import Development.IDE.Types.Location (Position (Position, _character, _line),+ Range (Range, _end, _start))+import Development.IDE.Types.Logger (Pretty (pretty),+ Recorder, WithPriority,+ cmapWithPrio)+import GHC.Generics (Generic) import Ide.Plugin.Properties-import Ide.PluginUtils (mkLspCommand)-import Ide.Types (CommandFunction,- CommandId (CommandId),- PluginCommand (PluginCommand),- PluginDescriptor (..),- PluginId,- configCustomConfig,- defaultConfigDescriptor,- defaultPluginDescriptor,- mkCustomConfig,- mkPluginHandler)-import qualified Language.LSP.Server as LSP-import Language.LSP.Types (ApplyWorkspaceEditParams (ApplyWorkspaceEditParams),- CodeLens (CodeLens),- CodeLensParams (CodeLensParams, _textDocument),- Diagnostic (..),- List (..), ResponseError,- SMethod (..),- TextDocumentIdentifier (TextDocumentIdentifier),- TextEdit (TextEdit),- WorkspaceEdit (WorkspaceEdit))-import Text.Regex.TDFA ((=~), (=~~))+import Ide.PluginUtils+import Ide.Types (CommandFunction,+ CommandId (CommandId),+ PluginCommand (PluginCommand),+ PluginDescriptor (..),+ PluginId,+ PluginMethodHandler,+ configCustomConfig,+ defaultConfigDescriptor,+ defaultPluginDescriptor,+ mkCustomConfig,+ mkPluginHandler)+import qualified Language.LSP.Server as LSP+import Language.LSP.Types (ApplyWorkspaceEditParams (ApplyWorkspaceEditParams),+ CodeLens (CodeLens),+ CodeLensParams (CodeLensParams, _textDocument),+ Diagnostic (..),+ List (..),+ Method (TextDocumentCodeLens),+ SMethod (..),+ TextDocumentIdentifier (TextDocumentIdentifier),+ TextEdit (TextEdit),+ WorkspaceEdit (WorkspaceEdit))+import Text.Regex.TDFA ((=~), (=~~)) data Log = LogShake Shake.Log deriving Show @@ -99,46 +102,56 @@ , (Diagnostics, "Follows error messages produced by GHC about missing signatures") ] Always -codeLensProvider ::- IdeState ->- PluginId ->- CodeLensParams ->- LSP.LspM Config (Either ResponseError (List CodeLens))-codeLensProvider ideState pId CodeLensParams{_textDocument = TextDocumentIdentifier uri} = do- mode <- liftIO $ runAction "codeLens.config" ideState $ usePropertyAction #mode pId properties- fmap (Right . List) $ case uriToFilePath' uri of- Just (toNormalizedFilePath' -> filePath) -> liftIO $ do- env <- fmap hscEnv <$> runAction "codeLens.GhcSession" ideState (use GhcSession filePath)- tmr <- runAction "codeLens.TypeCheck" ideState (use TypeCheck filePath)- bindings <- runAction "codeLens.GetBindings" ideState (use GetBindings filePath)- gblSigs <- runAction "codeLens.GetGlobalBindingTypeSigs" ideState (use GetGlobalBindingTypeSigs filePath)+codeLensProvider :: PluginMethodHandler IdeState TextDocumentCodeLens+codeLensProvider ideState pId CodeLensParams{_textDocument = TextDocumentIdentifier uri} = pluginResponse $ do+ mode <- liftIO $ runAction "codeLens.config" ideState $ usePropertyAction #mode pId properties+ nfp <- getNormalizedFilePath uri+ env <- hscEnv . fst+ <$> (handleMaybeM "Unable to get GhcSession"+ $ liftIO+ $ runAction "codeLens.GhcSession" ideState (useWithStale GhcSession nfp)+ )+ tmr <- fst <$> (+ handleMaybeM "Unable to TypeCheck"+ $ liftIO+ $ runAction "codeLens.TypeCheck" ideState (useWithStale TypeCheck nfp)+ )+ bindings <- fst <$> (+ handleMaybeM "Unable to GetBindings"+ $ liftIO+ $ runAction "codeLens.GetBindings" ideState (useWithStale GetBindings nfp)+ )+ (gblSigs@(GlobalBindingTypeSigsResult gblSigs'), gblSigsMp) <-+ handleMaybeM "Unable to GetGlobalBindingTypeSigs"+ $ liftIO+ $ runAction "codeLens.GetGlobalBindingTypeSigs" ideState (useWithStale GetGlobalBindingTypeSigs nfp) - diag <- atomically $ getDiagnostics ideState- hDiag <- atomically $ getHiddenDiagnostics ideState+ diag <- liftIO $ atomically $ getDiagnostics ideState+ hDiag <- liftIO $ atomically $ getHiddenDiagnostics ideState - let toWorkSpaceEdit tedit = WorkspaceEdit (Just $ Map.singleton uri $ List tedit) Nothing Nothing- generateLensForGlobal sig@GlobalBindingTypeSig{..} = do- range <- srcSpanToRange $ gbSrcSpan sig- tedit <- gblBindingTypeSigToEdit sig+ let toWorkSpaceEdit tedit = WorkspaceEdit (Just $ Map.singleton uri $ List tedit) Nothing Nothing+ generateLensForGlobal mp sig@GlobalBindingTypeSig{gbRendered} = do+ range <- toCurrentRange mp =<< srcSpanToRange (gbSrcSpan sig)+ tedit <- gblBindingTypeSigToEdit sig (Just gblSigsMp) let wedit = toWorkSpaceEdit [tedit] pure $ generateLens pId range (T.pack gbRendered) wedit- gblSigs' = maybe [] (\(GlobalBindingTypeSigsResult x) -> x) gblSigs- generateLensFromDiags f =- sequence- [ pure $ generateLens pId _range title edit+ generateLensFromDiags f =+ [ generateLens pId _range title edit | (dFile, _, dDiag@Diagnostic{_range = _range}) <- diag ++ hDiag- , dFile == filePath+ , dFile == nfp , (title, tedit) <- f dDiag , let edit = toWorkSpaceEdit tedit ]-- case mode of+ -- `suggestLocalSignature` relies on diagnostic, if diagnostics don't have the local signature warning,+ -- the `bindings` is useless, and if diagnostic has, that means we parsed success, and the `bindings` is fresh.+ pure $ List $ case mode of Always ->- pure (catMaybes $ generateLensForGlobal <$> gblSigs')- <> generateLensFromDiags (suggestLocalSignature False env tmr bindings) -- we still need diagnostics for local bindings- Exported -> pure $ catMaybes $ generateLensForGlobal <$> filter gbExported gblSigs'- Diagnostics -> generateLensFromDiags $ suggestSignature False env gblSigs tmr bindings- Nothing -> pure []+ mapMaybe (generateLensForGlobal gblSigsMp) gblSigs'+ <> generateLensFromDiags+ (suggestLocalSignature False (Just env) (Just tmr) (Just bindings)) -- we still need diagnostics for local bindings+ Exported -> mapMaybe (generateLensForGlobal gblSigsMp) (filter gbExported gblSigs')+ Diagnostics -> generateLensFromDiags+ $ suggestSignature False (Just env) (Just gblSigs) (Just tmr) (Just bindings) generateLens :: PluginId -> Range -> T.Text -> WorkspaceEdit -> CodeLens generateLens pId _range title edit =@@ -164,7 +177,7 @@ , Just sig <- find (\x -> sameThing (gbSrcSpan x) _range) sigs , signature <- T.pack $ gbRendered sig , title <- if isQuickFix then "add signature: " <> signature else signature- , Just action <- gblBindingTypeSigToEdit sig =+ , Just action <- gblBindingTypeSigToEdit sig Nothing = [(title, [action])] | otherwise = [] @@ -194,12 +207,15 @@ sameThing :: SrcSpan -> Range -> Bool sameThing s1 s2 = (_start <$> srcSpanToRange s1) == (_start <$> Just s2) -gblBindingTypeSigToEdit :: GlobalBindingTypeSig -> Maybe TextEdit-gblBindingTypeSigToEdit GlobalBindingTypeSig{..}+gblBindingTypeSigToEdit :: GlobalBindingTypeSig -> Maybe PositionMapping -> Maybe TextEdit+gblBindingTypeSigToEdit GlobalBindingTypeSig{..} mmp | Just Range{..} <- srcSpanToRange $ getSrcSpan gbName , startOfLine <- Position (_line _start) 0- , beforeLine <- Range startOfLine startOfLine =- Just $ TextEdit beforeLine $ T.pack gbRendered <> "\n"+ , beforeLine <- Range startOfLine startOfLine+ -- If `mmp` is `Nothing`, return the original range, it used by lenses from diagnostic,+ -- otherwise we apply `toCurrentRange`, and the guard should fail if `toCurrentRange` failed.+ , Just range <- maybe (Just beforeLine) (flip toCurrentRange beforeLine) mmp+ = Just $ TextEdit range $ T.pack gbRendered <> "\n" | otherwise = Nothing data Mode
test/exe/Main.hs view
@@ -969,6 +969,18 @@ [ sigSession "with GHC warnings" True "diagnostics" "" (second Just $ head cases) [] , sigSession "without GHC warnings" False "diagnostics" "" (second (const Nothing) $ head cases) [] ]+ , testSession "keep stale lens" $ do+ let content = T.unlines+ [ "module Stale where"+ , "f = _"+ ]+ doc <- createDoc "Stale.hs" "haskell" content+ oldLens <- getCodeLenses doc+ liftIO $ length oldLens @?= 1+ let edit = TextEdit (mkRange 0 4 0 5) "" -- Remove the `_`+ _ <- applyEdit doc edit+ newLens <- getCodeLenses doc+ liftIO $ newLens @?= oldLens ] linkToLocation :: [LocationLink] -> [Location]@@ -1204,10 +1216,6 @@ testM yes yes reexported reexportedSig "Imported symbol (reexported)" , if | ghcVersion == GHC90 && isWindows -> test no broken thLocL57 thLoc "TH Splice Hover"- | ghcVersion == GHC92 && (isWindows || isMac) ->- -- Some GHC 9.2 distributions ship without .hi docs- -- https://gitlab.haskell.org/ghc/ghc/-/issues/20903- test no broken thLocL57 thLoc "TH Splice Hover" | otherwise -> test no yes thLocL57 thLoc "TH Splice Hover" ]@@ -2049,14 +2057,14 @@ ] let expected = "*Imported from 'Prelude'*\n" test doc (Position 1 8) "odd" (Just $ T.length expected) [expected]- , brokenForMacGhc9 $ brokenForWinGhc9 $ testSession "extern single line doc without '\\n'" $ do+ , brokenForMacGhc9 $ brokenForWinGhc90 $ testSession "extern single line doc without '\\n'" $ do doc <- createDoc "A.hs" "haskell" $ T.unlines [ "module A where" , "foo = no" ] let expected = "*Imported from 'Prelude'*\n* * *\n\n\nBoolean \"not\"\n" test doc (Position 1 8) "not" (Just $ T.length expected) [expected]- , brokenForMacGhc9 $ brokenForWinGhc9 $ testSession "extern mulit line doc" $ do+ , brokenForMacGhc9 $ brokenForWinGhc90 $ testSession "extern mulit line doc" $ do doc <- createDoc "A.hs" "haskell" $ T.unlines [ "module A where" , "foo = i"@@ -2073,7 +2081,7 @@ ] where brokenForGhc9 = knownBrokenFor (BrokenForGHC [GHC90, GHC92, GHC94, GHC96]) "Completion doc doesn't support ghc9"- brokenForWinGhc9 = knownBrokenFor (BrokenSpecific Windows [GHC90, GHC92]) "Extern doc doesn't support Windows for ghc9.2"+ brokenForWinGhc90 = knownBrokenFor (BrokenSpecific Windows [GHC90]) "Extern doc doesn't support Windows for ghc9.2" -- https://gitlab.haskell.org/ghc/ghc/-/issues/20903 brokenForMacGhc9 = knownBrokenFor (BrokenSpecific MacOS [GHC90, GHC92, GHC94, GHC96]) "Extern doc doesn't support MacOS for ghc9" test doc pos label mn expected = do