on master help sign in
Clean up hie-core (#1815)

* Make atPoint generate either haskell or daml syntax, depending on options * Get rid of data HoverText * Move VirtualResource out from hie-core * Rename hie-core to the right name * Drop Types.LSP, merge it into LSP.Protocol * Remove orphans that aren't actually used in our code * Delete redundant newlines * Add a defaultIdeOptions function * Move ideTryIOException over to its one user * Delete unused exports * Delete the ProjectDiagnostic newtype - the type index was always Key * Don't reexport position information from Diagnostic * Delete the unused bits from Location * Delete unused stuff from getSrcSpan * Move URL stuff into Location from Diagnostic * Remove unnecessary CPP * Remove unnecessary extension * Change from stage being polymorphic to being a Text * Fix up the test suite too * Push the cleanup to the edges * More dependencies * Patch up the tests now they need to find the type signature inside a ```daml block

commit62704427430157272afbc31394c06f0883a33258 authorNeil Mitchell <35463327+neil-da@users.noreply.github.com> dateFri 21 Jun 2019, 22:19 (7 years ago) parent036e3d0
24 files changed+143−272
hie.cabal → hie-core.cabal−1 src/Development/IDE/Functions/AtPoint.hs+12−10 src/Development/IDE/Functions/Compile.hs+1 src/Development/IDE/Functions/DependencyInformation.hs+1 src/Development/IDE/Functions/FindImports.hs+1−1 src/Development/IDE/Functions/GHCError.hs+1 src/Development/IDE/Functions/SpanInfo.hs+1−1 src/Development/IDE/LSP/Definition.hs+1−1 src/Development/IDE/LSP/Hover.hs+2−12 src/Development/IDE/LSP/LanguageServer.hs+1−1 src/Development/IDE/LSP/Protocol.hs+12 src/Development/IDE/Orphans.hs−6 src/Development/IDE/State/FileStore.hs+8−2 src/Development/IDE/State/RuleTypes.hs+1−1 src/Development/IDE/State/Rules.hs+4−3 src/Development/IDE/State/Service.hs+1−1 src/Development/IDE/State/Shake.hs+5−4 src/Development/IDE/Types/Diagnostics.hs+13−111 src/Development/IDE/Types/LSP.hs−47 src/Development/IDE/Types/Location.hs+59−51 src/Development/IDE/Types/Options.hs+16−1 src/Development/IDE/Types/SpanInfo.hs−7 src/Development/IDE/UtilGHC.hs−1 test/Demo.hs+3−10
hie.cabal → hie-core.cabalrenamed−1
@@ -102,7 +102,6 @@ library
102102 Development.IDE.State.Shake
103103 Development.IDE.Types.Diagnostics
104104 Development.IDE.Types.Location
105− Development.IDE.Types.LSP
106105 Development.IDE.Types.SpanInfo
107106 other-modules:
108107 Data.Text.Prettyprint.Doc.Syntax
src/Development/IDE/Functions/AtPoint.hs+12−10
@@ -12,6 +12,7 @@ module Development.IDE.Functions.AtPoint (
1212import Development.IDE.Functions.Documentation
1313import Development.IDE.Functions.GHCError
1414import Development.IDE.Orphans()
15+import Development.IDE.Types.Location
1516
1617-- DAML compiler and infrastructure
1718import Development.Shake
@@ -19,8 +20,6 @@ import Development.IDE.UtilGHC
1920import Development.IDE.Compat
2021import Development.IDE.State.Shake
2122import Development.IDE.State.RuleTypes
22−import Development.IDE.Types.Diagnostics
23−import Development.IDE.Types.LSP
2423import Development.IDE.Types.Options
2524import Development.IDE.Types.SpanInfo as SpanInfo
2625
@@ -50,25 +49,28 @@ gotoDefinition ideOpts pkgState srcSpans pos =
5049
5150-- | Synopsis for the name at a given position.
5251atPoint
53− :: [TypecheckedModule]
52+ :: IdeOptions
53+ -> [TypecheckedModule]
5454 -> [SpanInfo]
5555 -> Position
56− -> Maybe (Maybe Range, [HoverText])
57−atPoint tcs srcSpans pos = do
56+ -> Maybe (Maybe Range, [T.Text])
57+atPoint IdeOptions{..} tcs srcSpans pos = do
5858 SpanInfo{..} <- listToMaybe $ orderSpans $ spansAtPoint pos srcSpans
5959 ty <- spaninfoType
6060 let mbName = getNameM spaninfoSource
61− mbDefinedAt = fmap (\name -> HoverMarkdown $ "**Defined " <> T.pack (showSDocUnsafe $ pprNameDefnLoc name) <> "**\n") mbName
61+ mbDefinedAt = fmap (\name -> "**Defined " <> T.pack (showSDocUnsafe $ pprNameDefnLoc name) <> "**\n") mbName
6262 mbDocs = fmap (\name -> getDocumentation name tcs) mbName
63− docInfo = maybe [] (map HoverMarkdown . docHeaders) mbDocs
63+ docInfo = maybe [] docHeaders mbDocs
6464 range = Range
6565 (Position spaninfoStartLine spaninfoStartCol)
6666 (Position spaninfoEndLine spaninfoEndCol)
67− typeSig = HoverDamlCode $ case mbName of
68− Nothing -> ": " <> showName ty
67+ colon = if optNewColonConvention then ":" else "::"
68+ wrapLanguageSyntax x = T.unlines [ "```" <> T.pack optLanguageSyntax, x, "```"]
69+ typeSig = wrapLanguageSyntax $ case mbName of
70+ Nothing -> colon <> " " <> showName ty
6971 Just name ->
7072 let modulePrefix = maybe "" (<> ".") (getModuleNameAsText name)
71− in modulePrefix <> showName name <> "\n : " <> showName ty
73+ in modulePrefix <> showName name <> "\n " <> colon <> " " <> showName ty
7274 hoverInfo = docInfo <> [typeSig] <> maybeToList mbDefinedAt
7375 return (Just range, hoverInfo)
7476 where
src/Development/IDE/Functions/Compile.hs+1
@@ -29,6 +29,7 @@ import Development.IDE.Functions.SpanInfo
2929import Development.IDE.UtilGHC
3030import Development.IDE.Compat
3131import Development.IDE.Types.Options
32+import Development.IDE.Types.Location
3233
3334import GHC hiding (parseModule, typecheckModule)
3435import qualified Parser
src/Development/IDE/Functions/DependencyInformation.hs+1
@@ -29,6 +29,7 @@ import Data.Tuple.Extra (fst3)
2929import GHC.Generics (Generic)
3030
3131import Development.IDE.Types.Diagnostics
32+import Development.IDE.Types.Location
3233import Development.IDE.UtilGHC ()
3334
3435import GHC
src/Development/IDE/Functions/FindImports.hs+1−1
@@ -11,7 +11,7 @@ module Development.IDE.Functions.FindImports
1111
1212import Development.IDE.Functions.GHCError as ErrUtils
1313import Development.IDE.Orphans()
14−import Development.IDE.Types.Diagnostics
14+import Development.IDE.Types.Location
1515-- GHC imports
1616import BasicTypes (StringLiteral(..))
1717import DynFlags
src/Development/IDE/Functions/GHCError.hs+1
@@ -30,6 +30,7 @@ module Development.IDE.Functions.GHCError
3030
3131import Development.IDE.Types.Diagnostics as D
3232import qualified Data.Text as T
33+import Development.IDE.Types.Location
3334import Development.IDE.Orphans()
3435import qualified FastString as FS
3536import GHC
src/Development/IDE/Functions/SpanInfo.hs+1−1
@@ -21,7 +21,7 @@ import Desugar
2121import GHC
2222import GhcMonad
2323import FastString (mkFastString)
24−import Development.IDE.Types.Diagnostics
24+import Development.IDE.Types.Location
2525import Development.IDE.Types.SpanInfo
2626import Development.IDE.Functions.GHCError (zeroSpan)
2727import Prelude hiding (mod)
src/Development/IDE/LSP/Definition.hs+1−1
@@ -9,7 +9,7 @@ module Development.IDE.LSP.Definition
99 ) where
1010
1111import Development.IDE.LSP.Protocol
12−import Development.IDE.Types.Diagnostics
12+import Development.IDE.Types.Location
1313
1414import qualified Development.IDE.Logger as Logger
1515import Development.IDE.State.Rules
src/Development/IDE/LSP/Hover.hs+2−12
@@ -10,6 +10,7 @@ module Development.IDE.LSP.Hover
1010
1111import Development.IDE.LSP.Protocol hiding (Hover)
1212import Language.Haskell.LSP.Types (Hover(..))
13+import Development.IDE.Types.Location
1314
1415import qualified Development.IDE.Logger as Logger
1516
@@ -18,8 +19,6 @@ import Data.Text.Prettyprint.Doc
1819import Data.Text.Prettyprint.Doc.Render.Text
1920
2021import Development.IDE.State.Rules
21−import Development.IDE.Types.LSP as Compiler
22−import Development.IDE.Types.Diagnostics
2322
2423-- | Display information on hover.
2524handle
@@ -40,16 +39,7 @@ handle loggerH compilerH (TextDocumentPositionParams (TextDocumentIdentifier uri
4039 case mbResult of
4140 Just (mbRange, contents) ->
4241 pure $ Just $ Hover
43− (HoverContents $ MarkupContent MkMarkdown $ T.intercalate sectionSeparator $ map showHoverInformation contents)
42+ (HoverContents $ MarkupContent MkMarkdown $ T.intercalate sectionSeparator contents)
4443 mbRange
4544
4645 Nothing -> pure Nothing
47− where
48− showHoverInformation :: Compiler.HoverText -> T.Text
49− showHoverInformation = \case
50− Compiler.HoverDamlCode damlCode -> T.unlines
51− [ "```daml"
52− , damlCode
53− , "```"
54− ]
55− Compiler.HoverMarkdown md -> md
src/Development/IDE/LSP/LanguageServer.hs+1−1
@@ -19,6 +19,7 @@ import qualified Development.IDE.LSP.Definition as LS.Definition
1919import qualified Development.IDE.LSP.Hover as LS.Hover
2020import qualified Development.IDE.Logger as Logger
2121import Development.IDE.State.Service
22+import Development.IDE.Types.Location
2223
2324import qualified Data.Aeson as Aeson
2425import qualified Data.Rope.UTF16 as Rope
@@ -26,7 +27,6 @@ import qualified Data.Set as S
2627import qualified Data.Text as T
2728
2829import Development.IDE.State.FileStore
29−import Development.IDE.Types.Diagnostics
3030
3131import qualified Network.URI as URI
3232
src/Development/IDE/LSP/Protocol.hs+12
@@ -1,15 +1,20 @@
11-- Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
22-- SPDX-License-Identifier: Apache-2.0
3+{-# LANGUAGE PatternSynonyms #-}
34
45module Development.IDE.LSP.Protocol
56 ( module Language.Haskell.LSP.Types
67 , ServerRequest(..)
78 , ServerNotification(..)
89 , prettyPosition
10+ , pattern EventFileDiagnostics
911 ) where
1012
1113import qualified Data.Aeson as Aeson
1214import qualified Data.Text as T
15+import Development.IDE.Types.Diagnostics
16+import Development.IDE.Types.Location
17+import Language.Haskell.LSP.Messages
1318import Data.Text.Prettyprint.Doc
1419
1520import Language.Haskell.LSP.Types hiding
@@ -51,3 +56,10 @@ data ServerNotification
5156
5257prettyPosition :: Position -> Doc a
5358prettyPosition Position{..} = pretty (_line + 1) <> colon <> pretty (_character + 1)
59+
60+-- | Pattern synonym to make it a bit more convenient to match on diagnostics
61+-- in things like damlc test.
62+pattern EventFileDiagnostics :: FilePath -> [Diagnostic] -> FromServerMessage
63+pattern EventFileDiagnostics fp diags <-
64+ NotPublishDiagnostics
65+ (NotificationMessage _ _ (PublishDiagnosticsParams (uriToFilePath' -> Just fp) (List diags)))
src/Development/IDE/Orphans.hs−6
@@ -30,11 +30,5 @@ instance NFData SB.StringBuffer where rnf = rwhnf
3030instance Show Module where
3131 show = moduleNameString . moduleName
3232
33−instance Show RdrName where show = prettyPrint
34−instance Show ComponentId where show = prettyPrint
35−instance Show SourcePackageId where show = prettyPrint
36−instance Show ModuleName where show = prettyPrint
3733instance Show (GenLocated SrcSpan ModuleName) where show = prettyPrint
38−instance Show PackageName where show = prettyPrint
39−instance Show PackageState where show _ = "PackageState"
4034instance Show Name where show = prettyPrint
src/Development/IDE/State/FileStore.hs+8−2
@@ -12,8 +12,6 @@ module Development.IDE.State.FileStore(
1212 makeLSPVFSHandle,
1313 ) where
1414
15−
16−
1715import StringBuffer
1816import Development.IDE.Orphans()
1917
@@ -29,10 +27,12 @@ import Development.Shake.Classes
2927import Development.IDE.State.Shake
3028import Control.Exception
3129import GHC.Generics
30+import Data.Either.Extra
3231import System.IO.Error
3332import qualified Data.ByteString.Char8 as BS
3433import qualified StringBuffer as SB
3534import Development.IDE.Types.Diagnostics
35+import Development.IDE.Types.Location
3636import qualified Data.Rope.UTF16 as Rope
3737import Data.Time
3838
@@ -134,6 +134,12 @@ getFileContentsRule vfs =
134134 Left err -> return ([err], Nothing)
135135 Right contents -> return ([], Just (time, contents))
136136
137+ideTryIOException :: NormalizedFilePath -> IO a -> IO (Either FileDiagnostic a)
138+ideTryIOException fp act =
139+ mapLeft
140+ (\(e :: IOException) -> ideErrorText fp $ T.pack $ show e)
141+ <$> try act
142+
137143
138144getFileContents :: NormalizedFilePath -> Action (FileVersion, StringBuffer)
139145getFileContents = use_ GetFileContents
src/Development/IDE/State/RuleTypes.hs+1−1
@@ -19,7 +19,7 @@ import Development.IDE.Functions.FindImports (Import(..))
1919import Development.IDE.Functions.DependencyInformation
2020import Data.Hashable
2121import Data.Typeable
22−import Development.IDE.Types.Diagnostics
22+import Development.IDE.Types.Location
2323import Data.Set(Set)
2424import Development.Shake hiding (Env, newCache)
2525import GHC.Generics (Generic)
src/Development/IDE/State/Rules.hs+4−3
@@ -31,6 +31,7 @@ import Development.IDE.Functions.DependencyInformation
3131import Development.IDE.Functions.FindImports
3232import Development.IDE.State.FileStore
3333import Development.IDE.Types.Diagnostics as Base
34+import Development.IDE.Types.Location
3435import qualified Data.ByteString.UTF8 as BS
3536import Control.Exception
3637import Control.Concurrent.Extra
@@ -43,7 +44,6 @@ import qualified Data.Set as Set
4344import qualified Data.Text as T
4445import Development.IDE.Functions.GHCError
4546import Development.Shake hiding (Diagnostic, Env, newCache)
46−import Development.IDE.Types.LSP as Compiler
4747import Development.IDE.State.RuleTypes
4848
4949import GHC
@@ -103,12 +103,13 @@ getDependencies :: NormalizedFilePath -> Action (Maybe [NormalizedFilePath])
103103getDependencies file = fmap transitiveModuleDeps <$> use GetDependencies file
104104
105105-- | Try to get hover text for the name under point.
106−getAtPoint :: NormalizedFilePath -> Position -> Action (Maybe (Maybe Range, [HoverText]))
106+getAtPoint :: NormalizedFilePath -> Position -> Action (Maybe (Maybe Range, [T.Text]))
107107getAtPoint file pos = fmap join $ runMaybeT $ do
108+ opts <- lift getOpts
108109 files <- transitiveModuleDeps <$> useE GetDependencies file
109110 tms <- usesE TypeCheck (file : files)
110111 spans <- useE GetSpanInfo file
111− return $ AtPoint.atPoint (map Compile.tmrModule tms) spans pos
112+ return $ AtPoint.atPoint opts (map Compile.tmrModule tms) spans pos
112113
113114-- | Goto Definition.
114115getDefinition :: NormalizedFilePath -> Position -> Action (Maybe Location)
src/Development/IDE/State/Service.hs+1−1
@@ -30,7 +30,7 @@ import qualified Data.Set as Set
3030import qualified Data.Text as T
3131import Data.Tuple.Extra
3232import Development.IDE.Functions.GHCError
33−import Development.IDE.Types.Diagnostics (NormalizedFilePath)
33+import Development.IDE.Types.Location (NormalizedFilePath)
3434import Development.Shake hiding (Diagnostic, Env, newCache)
3535import qualified Language.Haskell.LSP.Messages as LSP
3636
src/Development/IDE/State/Shake.hs+5−4
@@ -58,6 +58,7 @@ import qualified Data.Text as T
5858import Development.IDE.Logger as Logger
5959import Development.IDE.Types.Diagnostics hiding (getAllDiagnostics)
6060import qualified Development.IDE.Types.Diagnostics as D
61+import Development.IDE.Types.Location
6162import Control.Concurrent.Extra
6263import Control.Exception
6364import Control.DeepSeq
@@ -81,7 +82,7 @@ data ShakeExtras = ShakeExtras
8182 ,logger :: Logger.Handle
8283 ,globals :: Var (Map.HashMap TypeRep Dynamic)
8384 ,state :: Var Values
84− ,diagnostics :: Var (ProjectDiagnostics Key)
85+ ,diagnostics :: Var DiagnosticStore
8586 }
8687
8788getShakeExtras :: Action ShakeExtras
@@ -221,7 +222,7 @@ shakeOpen eventer logger opts rules = do
221222 shakeExtras <- do
222223 globals <- newVar Map.empty
223224 state <- newVar Map.empty
224− diagnostics <- newVar emptyDiagnostics
225+ diagnostics <- newVar mempty
225226 pure ShakeExtras{..}
226227 (shakeDb, shakeClose) <- shakeOpenDatabase opts{shakeExtra = addShakeExtra shakeExtras $ shakeExtra opts} rules
227228 shakeAbort <- newVar $ return ()
@@ -279,7 +280,7 @@ getAllDiagnostics IdeState{shakeExtras = ShakeExtras{diagnostics}} = do
279280-- | FIXME: This function is temporary! Only required because the files of interest doesn't work
280281unsafeClearAllDiagnostics :: IdeState -> IO ()
281282unsafeClearAllDiagnostics IdeState{shakeExtras = ShakeExtras{diagnostics}} =
282− writeVar diagnostics emptyDiagnostics
283+ writeVar diagnostics mempty
283284
284285-- | Clear the results for all files that do not match the given predicate.
285286garbageCollect :: (NormalizedFilePath -> Bool) -> Action ()
@@ -403,7 +404,7 @@ updateFileDiagnostics fp k ShakeExtras{diagnostics, state} current = do
403404 modTime <- join <$> getValues state GetModificationTime fp
404405 modifyVar diagnostics $ \old -> do
405406 let oldDiags = getFileDiagnostics fp old
406− let newDiagsStore = setStageDiagnostics fp (vfsVersion =<< modTime) k current old
407+ let newDiagsStore = setStageDiagnostics fp (vfsVersion =<< modTime) (T.pack $ show k) current old
407408 let newDiags = getFileDiagnostics fp newDiagsStore
408409 pure (newDiagsStore, (newDiags, oldDiags))
409410 when (newDiags /= oldDiags) $
src/Development/IDE/Types/Diagnostics.hs+13−111
@@ -7,38 +7,17 @@
77{-# LANGUAGE BlockArguments #-}
88module Development.IDE.Types.Diagnostics (
99 LSP.Diagnostic(..),
10− FileDiagnostics,
1110 FileDiagnostic,
12− Location(..),
13− Range(..),
1411 LSP.DiagnosticSeverity(..),
15− Position(..),
1612 DiagnosticStore,
1713 DiagnosticRelatedInformation(..),
1814 List(..),
1915 StoreItem(..),
20− Uri(..),
21− NormalizedUri,
22− LSP.toNormalizedUri,
23− LSP.fromNormalizedUri,
24− NormalizedFilePath,
25− toNormalizedFilePath,
26− fromNormalizedFilePath,
27− noLocation,
28− noRange,
29− noFilePath,
3016 ideErrorText,
3117 ideErrorPretty,
3218 errorDiag,
33− ideTryIOException,
3419 showDiagnostics,
3520 showDiagnosticsColored,
36− defDiagnostic,
37− filePathToUri,
38− filePathToUri',
39− uriToFilePath',
40− ProjectDiagnostics,
41− emptyDiagnostics,
4221 setStageDiagnostics,
4322 getAllDiagnostics,
4423 filterDiagnostics,
@@ -46,66 +25,24 @@ module Development.IDE.Types.Diagnostics (
4625 prettyDiagnostics
4726 ) where
4827
49−import Control.DeepSeq
50−import Control.Exception
51−import Data.Either.Combinators
5228import Data.Maybe as Maybe
5329import Data.Foldable
54−import Data.Hashable
5530import qualified Data.Map as Map
56−import Data.String
5731import qualified Data.Text as T
5832import Data.Text.Prettyprint.Doc.Syntax
5933import qualified Data.SortedList as SL
60−import System.FilePath
6134import qualified Text.PrettyPrint.Annotated.HughesPJClass as Pretty
6235import qualified Language.Haskell.LSP.Types as LSP
6336import Language.Haskell.LSP.Types as LSP (
6437 DiagnosticSeverity(..)
6538 , Diagnostic(..)
66− , filePathToUri
6739 , List(..)
6840 , DiagnosticRelatedInformation(..)
69− , NormalizedUri(..)
70− , Uri(..)
71− , toNormalizedUri
72− , fromNormalizedUri
7341 )
7442import Language.Haskell.LSP.Diagnostics
7543
7644import Development.IDE.Types.Location
7745
78−-- | Newtype wrapper around FilePath that always has normalized slashes.
79−newtype NormalizedFilePath = NormalizedFilePath FilePath
80− deriving (Eq, Ord, Show, Hashable, NFData)
81−
82−instance IsString NormalizedFilePath where
83− fromString = toNormalizedFilePath
84−
85−toNormalizedFilePath :: FilePath -> NormalizedFilePath
86−toNormalizedFilePath "" = NormalizedFilePath ""
87−toNormalizedFilePath fp = NormalizedFilePath $ normalise' fp
88− where
89− -- We do not use System.FilePath’s normalise here since that
90− -- also normalises things like the case of the drive letter
91− -- which NormalizedUri does not normalise so we get VFS lookup failures.
92− normalise' :: FilePath -> FilePath
93− normalise' = map (\c -> if isPathSeparator c then pathSeparator else c)
94−
95−fromNormalizedFilePath :: NormalizedFilePath -> FilePath
96−fromNormalizedFilePath (NormalizedFilePath fp) = fp
97−
98−-- | We use an empty string as a filepath when we don’t have a file.
99−-- However, haskell-lsp doesn’t support that in uriToFilePath and given
100−-- that it is not a valid filepath it does not make sense to upstream a fix.
101−-- So we have our own wrapper here that supports empty filepaths.
102−uriToFilePath' :: Uri -> Maybe FilePath
103−uriToFilePath' uri
104− | uri == filePathToUri "" = Just ""
105− | otherwise = LSP.uriToFilePath uri
106−
107−filePathToUri' :: NormalizedFilePath -> NormalizedUri
108−filePathToUri' = toNormalizedUri . filePathToUri . fromNormalizedFilePath
10946
11047ideErrorText :: NormalizedFilePath -> T.Text -> FileDiagnostic
11148ideErrorText fp = errorDiag fp "Ide Error"
@@ -133,25 +70,6 @@ diagnostic rng sev src msg
13370 _relatedInformation = Nothing
13471 }
13572
136−-- | Any optional field is instantiated to Nothing
137−defDiagnostic ::
138− Range ->
139− T.Text -> -- ^ error message
140− LSP.Diagnostic
141−defDiagnostic _range _message = LSP.Diagnostic {
142− _range
143− , _message
144− , _severity = Nothing
145− , _code = Nothing
146− , _source = Nothing
147− , _relatedInformation = Nothing
148− }
149−
150−ideTryIOException :: NormalizedFilePath -> IO a -> IO (Either FileDiagnostic a)
151−ideTryIOException fp act =
152− mapLeft
153− (\(e :: IOException) -> ideErrorText fp $ T.pack $ show e)
154− <$> try act
15573
15674-- | Human readable diagnostics for a specific file.
15775--
@@ -159,7 +77,6 @@ ideTryIOException fp act =
15977-- along with the related source location so that we can display the error
16078-- on either the console or in the IDE at the right source location.
16179--
162−type FileDiagnostics = (NormalizedFilePath, [Diagnostic])
16380type FileDiagnostic = (NormalizedFilePath, Diagnostic)
16481
16582prettyRange :: Range -> Doc SyntaxClass
@@ -202,55 +119,40 @@ getDiagnosticsFromStore :: StoreItem -> [Diagnostic]
202119getDiagnosticsFromStore (StoreItem _ diags) =
203120 toList =<< Map.elems diags
204121
205−-- | This represents every diagnostic in a LSP project, the stage type variable is
206−-- the type of the compiler stages, in this project that is always the Key data
207−-- type found in Development.IDE.State.Shake
208−newtype ProjectDiagnostics stage = ProjectDiagnostics {getStore :: DiagnosticStore}
209− deriving Show
210−
211−emptyDiagnostics :: ProjectDiagnostics stage
212−emptyDiagnostics = ProjectDiagnostics mempty
213122
214123-- | Sets the diagnostics for a file and compilation step
215124-- if you want to clear the diagnostics call this with an empty list
216125setStageDiagnostics ::
217− Show stage =>
218126 NormalizedFilePath ->
219127 Maybe Int ->
220128 -- ^ the time that the file these diagnostics originate from was last edited
221− stage ->
129+ T.Text ->
222130 [LSP.Diagnostic] ->
223− ProjectDiagnostics stage ->
224− ProjectDiagnostics stage
225−setStageDiagnostics fp timeM stage diags (ProjectDiagnostics ds) =
226− ProjectDiagnostics $ updateDiagnostics ds uri timeM diagsBySource
131+ DiagnosticStore ->
132+ DiagnosticStore
133+setStageDiagnostics fp timeM stage diags ds =
134+ updateDiagnostics ds uri timeM diagsBySource
227135 where
228− diagsBySource = Map.singleton (Just $ T.pack $ show stage) (SL.toSortedList diags)
136+ diagsBySource = Map.singleton (Just stage) (SL.toSortedList diags)
229137 uri = filePathToUri' fp
230138
231−fromUri :: LSP.NormalizedUri -> NormalizedFilePath
232−fromUri = toNormalizedFilePath . fromMaybe noFilePath . uriToFilePath' . fromNormalizedUri
233−
234139getAllDiagnostics ::
235− ProjectDiagnostics stage ->
140+ DiagnosticStore ->
236141 [FileDiagnostic]
237142getAllDiagnostics =
238− concatMap (\(k,v) -> map (fromUri k,) $ getDiagnosticsFromStore v) . Map.toList . getStore
143+ concatMap (\(k,v) -> map (fromUri k,) $ getDiagnosticsFromStore v) . Map.toList
239144
240145getFileDiagnostics ::
241146 NormalizedFilePath ->
242− ProjectDiagnostics stage ->
147+ DiagnosticStore ->
243148 [LSP.Diagnostic]
244149getFileDiagnostics fp ds =
245150 maybe [] getDiagnosticsFromStore $
246− Map.lookup (filePathToUri' fp) $
247− getStore ds
151+ Map.lookup (filePathToUri' fp) ds
248152
249153filterDiagnostics ::
250154 (NormalizedFilePath -> Bool) ->
251− ProjectDiagnostics stage ->
252− ProjectDiagnostics stage
155+ DiagnosticStore ->
156+ DiagnosticStore
253157filterDiagnostics keep =
254− ProjectDiagnostics .
255− Map.filterWithKey (\uri _ -> maybe True (keep . toNormalizedFilePath) $ uriToFilePath' $ fromNormalizedUri uri) .
256− getStore
158+ Map.filterWithKey (\uri _ -> maybe True (keep . toNormalizedFilePath) $ uriToFilePath' $ fromNormalizedUri uri)
src/Development/IDE/Types/LSP.hsdeleted−47
@@ -1,47 +0,0 @@
1−-- Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2−-- SPDX-License-Identifier: Apache-2.0
3−{-# LANGUAGE PatternSynonyms #-}
4−module Development.IDE.Types.LSP
5− ( HoverText(..)
6− , VirtualResource(..)
7− , getHoverTextContent
8− , pattern EventFileDiagnostics
9− ) where
10−
11−import Control.DeepSeq
12−import qualified Data.Text as T
13−import Development.IDE.Types.Diagnostics
14−import GHC.Generics
15−import Language.Haskell.LSP.Messages
16−import Language.Haskell.LSP.Types
17−
18−-- | Different types of content we can show on hover.
19−data HoverText
20− = HoverDamlCode !T.Text
21− -- ^ Highlighted DAML-Code
22− | HoverMarkdown !T.Text
23− -- ^ Markdown text.
24− deriving Show
25−
26−getHoverTextContent :: HoverText -> T.Text
27−getHoverTextContent = \case
28− HoverDamlCode t -> t
29− HoverMarkdown t -> t
30−
31−-- | Virtual resources
32−data VirtualResource = VRScenario
33− { vrScenarioFile :: !NormalizedFilePath
34− , vrScenarioName :: !T.Text
35− } deriving (Eq, Ord, Show, Generic)
36− -- ^ VRScenario identifies a scenario in a given file.
37− -- This virtual resource is associated with the HTML result of
38− -- interpreting the corresponding scenario.
39−
40−instance NFData VirtualResource
41−
42−-- | Pattern synonym to make it a bit more convenient to match on diagnostics
43−-- in things like damlc test.
44−pattern EventFileDiagnostics :: FilePath -> [Diagnostic] -> FromServerMessage
45−pattern EventFileDiagnostics fp diags <-
46− NotPublishDiagnostics
47− (NotificationMessage _ _ (PublishDiagnosticsParams (uriToFilePath' -> Just fp) (List diags)))
src/Development/IDE/Types/Location.hs+59−51
@@ -5,74 +5,82 @@
55
66-- | Types and functions for working with source code locations.
77module Development.IDE.Types.Location
8− ( genLocation
9− , inRange
10− , inRangeClosed
11− , isGenLocation
12− , Location(..)
13− , appendLocation
14− , noLocation
8+ ( Location(..)
159 , noFilePath
1610 , noRange
1711 , Position(..)
1812 , Range(..)
19− , appendRange
13+ , Uri(..)
14+ , NormalizedUri
15+ , LSP.toNormalizedUri
16+ , LSP.fromNormalizedUri
17+ , NormalizedFilePath
18+ , fromUri
19+ , toNormalizedFilePath
20+ , fromNormalizedFilePath
21+ , filePathToUri
22+ , filePathToUri'
23+ , uriToFilePath'
2024 ) where
2125
22−import Language.Haskell.LSP.Types (Location(..), Range(..), Position(..), Uri(..), filePathToUri)
26+import Language.Haskell.LSP.Types (Location(..), Range(..), Position(..))
2327
24−-- | A dummy location to use when location information is missing.
25−noLocation :: Location
26−noLocation = Location
27− { _uri = filePathToUri noFilePath
28− , _range = noRange
29− }
3028
31−noFilePath :: FilePath
32−noFilePath = "<unknown>"
33−
34−-- A dummy range to use when range is unknown
35−noRange :: Range
36−noRange = Range (Position 0 0) (Position 100000 0)
29+import Control.DeepSeq
30+import Data.Maybe as Maybe
31+import Data.Hashable
32+import Data.String
33+import System.FilePath
34+import qualified Language.Haskell.LSP.Types as LSP
35+import Language.Haskell.LSP.Types as LSP (
36+ filePathToUri
37+ , NormalizedUri(..)
38+ , Uri(..)
39+ , toNormalizedUri
40+ , fromNormalizedUri
41+ )
3742
3843
39−-- | A dummy location to use when location information is not present because
40−-- the code was generated.
41−genLocation :: Location
42−genLocation = Location
43− { _uri = Uri "<generated>"
44− , _range = Range (Position 0 0) (Position 0 0)
45− }
44+-- | Newtype wrapper around FilePath that always has normalized slashes.
45+newtype NormalizedFilePath = NormalizedFilePath FilePath
46+ deriving (Eq, Ord, Show, Hashable, NFData)
4647
48+instance IsString NormalizedFilePath where
49+ fromString = toNormalizedFilePath
4750
48−-- | Is a location generated.
49−isGenLocation :: Location -> Bool
50−isGenLocation x = _uri x == Uri "<generated>"
51+toNormalizedFilePath :: FilePath -> NormalizedFilePath
52+toNormalizedFilePath "" = NormalizedFilePath ""
53+toNormalizedFilePath fp = NormalizedFilePath $ normalise' fp
54+ where
55+ -- We do not use System.FilePath’s normalise here since that
56+ -- also normalises things like the case of the drive letter
57+ -- which NormalizedUri does not normalise so we get VFS lookup failures.
58+ normalise' :: FilePath -> FilePath
59+ normalise' = map (\c -> if isPathSeparator c then pathSeparator else c)
5160
61+fromNormalizedFilePath :: NormalizedFilePath -> FilePath
62+fromNormalizedFilePath (NormalizedFilePath fp) = fp
5263
53−-- | Check if a position is inside a range.
54−-- Our definition states that the start of the range is included, but not the end.
55−inRange :: Position -> Range -> Bool
56−inRange pos (Range start end) = start <= pos && pos < end
64+-- | We use an empty string as a filepath when we don’t have a file.
65+-- However, haskell-lsp doesn’t support that in uriToFilePath and given
66+-- that it is not a valid filepath it does not make sense to upstream a fix.
67+-- So we have our own wrapper here that supports empty filepaths.
68+uriToFilePath' :: Uri -> Maybe FilePath
69+uriToFilePath' uri
70+ | uri == filePathToUri "" = Just ""
71+ | otherwise = LSP.uriToFilePath uri
5772
73+filePathToUri' :: NormalizedFilePath -> NormalizedUri
74+filePathToUri' = toNormalizedUri . filePathToUri . fromNormalizedFilePath
5875
59−-- | Check if a position is inside a range, including the end.
60−-- Both start and end of the range are included.
61−inRangeClosed :: Position -> Range -> Bool
62−inRangeClosed pos (Range start end) = start <= pos && pos <= end
6376
77+fromUri :: LSP.NormalizedUri -> NormalizedFilePath
78+fromUri = toNormalizedFilePath . fromMaybe noFilePath . uriToFilePath' . fromNormalizedUri
6479
65−-- | Produce a new range where the minimum position is the min of both,
66−-- and the maximum position is the max of both.
67−appendRange :: Range -> Range -> Range
68−appendRange r1 r2
69− = Range { _start = min (_start r1) (_start r2)
70− , _end = max (_end r1) (_end r2) }
7180
81+noFilePath :: FilePath
82+noFilePath = "<unknown>"
7283
73−-- | Produce a new location where the ranges are the appended and we choose
74−-- the file path of the second.
75−appendLocation :: Location -> Location -> Location
76−appendLocation l1 l2
77− = Location { _uri = _uri l2
78− , _range = appendRange (_range l1) (_range l2) }
84+-- A dummy range to use when range is unknown
85+noRange :: Range
86+noRange = Range (Position 0 0) (Position 100000 0)
src/Development/IDE/Types/Options.hs+16−1
@@ -7,7 +7,7 @@
77module Development.IDE.Types.Options
88 ( IdeOptions(..)
99 , IdePkgLocationOptions(..)
10− , defaultIdePkgLocationOptions
10+ , defaultIdeOptions
1111 ) where
1212
1313import Development.Shake
@@ -26,8 +26,23 @@ data IdeOptions = IdeOptions
2626
2727 , optThreads :: Int
2828 , optShakeProfiling :: Maybe FilePath
29+ , optLanguageSyntax :: String -- ^ the ```language to use
30+ , optNewColonConvention :: Bool -- ^ whether to use new colon convention
2931 }
3032
33+defaultIdeOptions :: Action HscEnv -> IdeOptions
34+defaultIdeOptions session = IdeOptions
35+ {optPreprocessor = (,) []
36+ ,optWriteIface = False
37+ ,optGhcSession = session
38+ ,optExtensions = ["hs"]
39+ ,optPkgLocationOpts = defaultIdePkgLocationOptions
40+ ,optThreads = 0
41+ ,optShakeProfiling = Nothing
42+ ,optLanguageSyntax = "haskell"
43+ ,optNewColonConvention = False
44+ }
45+
3146
3247-- | The set of options used to locate files belonging to external packages.
3348data IdePkgLocationOptions = IdePkgLocationOptions
src/Development/IDE/Types/SpanInfo.hs−7
@@ -9,7 +9,6 @@ module Development.IDE.Types.SpanInfo(
99 SpanInfo(..)
1010 , SpanSource(..)
1111 , getNameM
12− , getSrcSpan
1312 ) where
1413
1514import GHC
@@ -55,9 +54,3 @@ getNameM :: SpanSource -> Maybe Name
5554getNameM = \case
5655 Named name -> Just name
5756 _ -> Nothing
58−
59−getSrcSpan :: SpanSource -> Maybe SrcSpan
60−getSrcSpan = \case
61− NoSource -> Nothing
62− Span sp -> Just sp
63− Named name -> Just $ nameSrcSpan name
src/Development/IDE/UtilGHC.hs−1
@@ -2,7 +2,6 @@
22-- SPDX-License-Identifier: Apache-2.0
33
44{-# OPTIONS_GHC -Wno-missing-fields #-} -- to enable prettyPrint
5−{-# LANGUAGE CPP #-}
65
76-- | GHC utility functions. Importantly, code using our GHC should never:
87--
test/Demo.hs+3−10
@@ -12,6 +12,8 @@ import Development.IDE.State.Service
1212import Development.IDE.State.Rules
1313import Development.IDE.State.Shake
1414import Development.IDE.State.RuleTypes
15+import Development.IDE.LSP.Protocol
16+import Development.IDE.Types.Location
1517import Data.String
1618import Development.IDE.Types.Diagnostics
1719import Development.IDE.Types.Options
@@ -22,7 +24,6 @@ import Development.IDE.LSP.LanguageServer
2224import System.Directory
2325import System.Environment
2426import System.IO
25−import Development.IDE.Types.LSP
2627import Development.Shake hiding (Env)
2728import qualified Data.Set as Set
2829
@@ -53,15 +54,7 @@ main = do
5354
5455 cradle <- findCradle (dir <> "/")
5556
56− let options = IdeOptions
57− {optPreprocessor = (,) []
58− ,optWriteIface = False
59− ,optGhcSession = liftIO $ newSession' cradle
60− ,optExtensions = ["hs"]
61− ,optPkgLocationOpts = defaultIdePkgLocationOptions
62− ,optThreads = 0
63− ,optShakeProfiling = Nothing -- Just "output.html"
64− }
57+ let options = defaultIdeOptions $ liftIO $ newSession' cradle
6558
6659 if "--lsp" `elem` args then do
6760 hPutStrLn stderr "Starting IDE server"