on b9dfd49 help sign in
99 lines 3.8 kB history raw
1-- Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2-- SPDX-License-Identifier: Apache-2.0
4{-# LANGUAGE OverloadedStrings #-}
5-- | Gives information about symbols at a given point in DAML files.
6-- These are all pure functions that should execute quickly.
7module Development.IDE.Functions.AtPoint (
8 atPoint
9 , gotoDefinition
10 ) where
12import Development.IDE.Functions.Documentation
13import Development.IDE.Functions.GHCError
15-- DAML compiler and infrastructure
16import Development.IDE.Types.Diagnostics
17import Development.IDE.Types.LSP
18import Development.IDE.Types.SpanInfo as SpanInfo
20-- GHC API imports
21import GHC
22import DynFlags
23import Outputable hiding ((<>))
24import Name
26import Data.Maybe
27import Data.List
28import qualified Data.Text as T
30-- | Locate the definition of the name at a given position.
31gotoDefinition
32 :: [SpanInfo]
33 -> Position
34 -> Maybe Location
35gotoDefinition srcSpans pos =
36 listToMaybe $ locationsAtPoint pos srcSpans
38-- | Synopsis for the name at a given position.
39atPoint
40 :: [TypecheckedModule]
41 -> [SpanInfo]
42 -> Position
43 -> Maybe (Maybe Range, [HoverText])
44atPoint tcs srcSpans pos = do
45 SpanInfo{..} <- listToMaybe $ orderSpans $ spansAtPoint pos srcSpans
46 ty <- spaninfoType
47 let mbName = getNameM spaninfoSource
48 mbDefinedAt = HoverHeading . ("Defined " <>) . T.pack . showSDocUnsafe . pprNameDefnLoc <$> mbName
49 mbDocs = fmap (\name -> getDocumentation name tcs) mbName
50 docInfo = maybe [] (map HoverMarkdown . docHeaders) mbDocs
51 range = Range
52 (Position spaninfoStartLine spaninfoStartCol)
53 (Position spaninfoEndLine spaninfoEndCol)
54 typeSig = HoverDamlCode $ case mbName of
55 Nothing -> ": " <> showName ty
56 Just name ->
57 let modulePrefix = maybe "" (<> ".") (getModuleNameAsText name)
58 in modulePrefix <> showName name <> "\n : " <> showName ty
59 hoverInfo = docInfo <> [typeSig] <> maybeToList mbDefinedAt
60 return (Just range, hoverInfo)
61 where
62 -- NOTE(RJR): This is a bit hacky.
63 -- We don't want to show the user type signatures generated from Eq and Show
64 -- instances, as they do not appear in the source program.
65 -- However the user could have written an `==` or `show` function directly,
66 -- in which case we still want to show information for that.
67 -- Hence we just move such information later in the list of spans.
68 orderSpans :: [SpanInfo] -> [SpanInfo]
69 orderSpans = uncurry (++) . partition (not . isTypeclassDeclSpan)
70 isTypeclassDeclSpan :: SpanInfo -> Bool
71 isTypeclassDeclSpan spanInfo =
72 case getNameM (spaninfoSource spanInfo) of
73 Just name -> any (`isInfixOf` show name) ["==", "showsPrec"]
74 Nothing -> False
76locationsAtPoint :: Position -> [SpanInfo] -> [Location]
77locationsAtPoint pos = map srcSpanToLocation
78 . mapMaybe (SpanInfo.getSrcSpan . spaninfoSource)
79 . spansAtPoint pos
81spansAtPoint :: Position -> [SpanInfo] -> [SpanInfo]
82spansAtPoint pos = filter atp where
83 line = _line pos + 1
84 cha = _character pos + 1
85 atp SpanInfo{..} = spaninfoStartLine <= line
86 && spaninfoEndLine >= line
87 && spaninfoStartCol <= cha
88 && spaninfoEndCol >= cha
90showName :: Outputable a => a -> T.Text
91showName = T.pack . prettyprint
92 where
93 prettyprint x = renderWithStyle unsafeGlobalDynFlags (ppr x) style
94 style = mkUserStyle unsafeGlobalDynFlags neverQualify AllTheWay
96getModuleNameAsText :: Name -> Maybe T.Text
97getModuleNameAsText n = do
98 m <- nameModule_maybe n
99 return . T.pack . moduleNameString $ moduleName m