Skip to content

Commit afcd5c7

Browse files
committed
Swap out export contexts for module header snippet
1 parent 7a2bc65 commit afcd5c7

2 files changed

Lines changed: 24 additions & 33 deletions

File tree

ghcide/src/Development/IDE/Plugin/Completions/Context.hs

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@ module Development.IDE.Plugin.Completions.Context
1212
) where
1313

1414
import Control.DeepSeq (NFData (..), rwhnf)
15-
import Control.Monad (join)
1615
import Data.Hashable (Hashable)
17-
import Data.List (maximumBy, singleton)
18-
import Data.Maybe (catMaybes, mapMaybe,
19-
maybeToList)
16+
import Data.List (maximumBy)
17+
import Data.Maybe (catMaybes, mapMaybe)
2018
import Data.Ord (Down (..), comparing)
2119
import qualified Data.Text as T
2220
import Development.IDE
@@ -38,10 +36,11 @@ data Context
3836
ImportListContext T.Text
3937
| -- | import hiding context with module name.
4038
ImportHidingContext T.Text
41-
| -- | List of exported identifiers from the current module.
42-
ExportContext
4339
| -- | Top-level context, with context groups indicating what would be valid
44-
-- in that top-level context. NB: An empty list denotes _all_ contexts
40+
-- in that top-level context.
41+
--
42+
-- NB: An empty list denotes _all_ contexts, this occurs in splices which
43+
-- overlap with the top-level declaration snippets while typing.
4544
TopContext [ContextGroup]
4645
| -- | Unsupported context, a placeholder context where we give up being smart
4746
-- and show all known symbols.
@@ -61,7 +60,6 @@ instance Pretty Context where
6160
ImportContext mod -> "import context " <> pretty mod
6261
ImportListContext mod -> "import explicit context " <> pretty mod
6362
ImportHidingContext mod -> "import hiding context " <> pretty mod
64-
ExportContext -> "export context"
6563
TopContext cg -> "top context " <> pretty cg
6664
DefaultContext -> "unknown context"
6765

@@ -88,15 +86,6 @@ data ContextChunk = Chunk
8886
, items :: [(Range, Context)]
8987
}
9088

91-
-- | Build a single 'Chunk' from a flat list of entries, or 'ChunkEnd' if empty.
92-
singleChunk :: ContextGroup -> [(Range, Context)] -> ContextMap
93-
singleChunk _ [] = ContextMap mempty
94-
singleChunk group items = ContextMap $ singleton $ Chunk
95-
(minimum (map (_start . fst) items))
96-
(maximum (map (_end . fst) items))
97-
group
98-
items
99-
10089
-- | Build lazy 'ContextChunk' by processing @n@ source items at a time.
10190
groupedChunks :: Int -> ContextGroup -> (a -> Maybe Range) -> (a -> [(Range, Context)]) -> [a] -> ContextMap
10291
groupedChunks n group getPos getRanges xs = ContextMap $ go xs
@@ -126,21 +115,16 @@ instance NFData ContextMap where rnf = rwhnf
126115
-- as a Shake rule.
127116
getContextMap :: ParsedModule -> ContextMap
128117
getContextMap pm =
129-
singleChunk HeaderGroup exportEntry
130-
<> groupedChunks 10 ImportGroup rangeOf importEntry hsmodImports
118+
groupedChunks 10 ImportGroup rangeOf importEntry hsmodImports
131119
<> groupedChunks 10 DeclarationGroup rangeOf declEntry hsmodDecls
132120
where
133-
HsModule {hsmodExports, hsmodImports, hsmodDecls} =
121+
HsModule {hsmodImports, hsmodDecls} =
134122
unLoc (pm_parsed_source pm)
135123

136124
rangeOf :: HasLoc (Anno a) => XRec GhcPs a -> Maybe Range
137125
rangeOf (L (locA -> ss) _) = srcSpanToRange ss
138126
fromSpan context ss = (,context) <$> rangeOf ss
139127

140-
-- Export list -> ExportContext
141-
exportEntry :: [(Range, Context)]
142-
exportEntry = maybeToList $ join $ fmap (fromSpan ExportContext) hsmodExports
143-
144128
importEntry :: LImportDecl GhcPs -> [(Range, Context)]
145129
importEntry decl@(L _ impDecl) =
146130
let modName = T.pack $ moduleNameString $ unLoc $ ideclName impDecl
@@ -210,7 +194,7 @@ getContextMap pm =
210194
-- query position are forced; later chunks remain as unevaluated thunks.
211195
getContext :: ContextMap -> PositionResult Position -> Context
212196
getContext (ContextMap chunks) pos =
213-
case searchChunks chunks of
197+
case searchChunks True chunks of
214198
([], []) -> TopContext []
215199
(groups, []) -> TopContext groups
216200
(_, xs) -> snd $ maximumBy (comparing (\(Range s e, _) -> (s, Down e))) xs
@@ -222,12 +206,12 @@ getContext (ContextMap chunks) pos =
222206
dominates :: (Range, Context) -> Bool
223207
dominates (Range s e, _) = s <= qLo && qHi <= e
224208

225-
searchChunks :: [ContextChunk] -> ([ContextGroup], [(Range, Context)])
226-
searchChunks [] = ([], [])
227-
searchChunks (Chunk cLo cHi group items : rest)
209+
searchChunks :: Bool -> [ContextChunk] -> ([ContextGroup], [(Range, Context)])
210+
searchChunks _ [] = ([], [])
211+
searchChunks firstChunk (Chunk cLo cHi group items : rest)
228212
| -- query is past this chunk
229-
qLo > cHi = searchChunks rest
213+
qLo > cHi = searchChunks False rest
230214
| -- query is before this chunk
231-
qHi < cLo = ([], [])
215+
qHi < cLo = (if firstChunk then [HeaderGroup] else [], [])
232216
-- this chunk is relevant, emit the group and all relevant intervals
233-
| otherwise = ([group], filter dominates items) <> searchChunks rest
217+
| otherwise = ([group], filter dominates items) <> searchChunks False rest

ghcide/src/Development/IDE/Plugin/Completions/Snippet.hs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,15 @@ getContextSnippets groups = concatMap (fmap mkSnippetCompletion . concat . maybe
2424

2525
topContextSnippets :: [(ContextGroup, [SnippetCompletion])]
2626
topContextSnippets =
27-
[ ( ImportGroup
27+
[ ( HeaderGroup
28+
, [ SnippetCompletion "module" "module header" moduleHeaderSnippet
29+
]
30+
),
31+
( ImportGroup
2832
, [ SnippetCompletion "import" "import module" importUnqualifiedSnippet
2933
, SnippetCompletion "import" "import module (explicit list)" importExplicitSnippet
30-
, SnippetCompletion "import" "import module hiding" importHidingSnippet
3134
, SnippetCompletion "import" "import module qualified as" importQualifiedAsSnippet
35+
, SnippetCompletion "import" "import module hiding" importHidingSnippet
3236
]
3337
),
3438
( DeclarationGroup
@@ -47,6 +51,9 @@ mkSnippetCompletion SnippetCompletion {..} =
4751
& L.insertText ?~ snippetContents
4852
& L.insertTextFormat ?~ InsertTextFormat_Snippet
4953

54+
moduleHeaderSnippet :: (IsString s) => s
55+
moduleHeaderSnippet = "module ${1:name} where"
56+
5057
importUnqualifiedSnippet :: (IsString s) => s
5158
importUnqualifiedSnippet = "import ${1:module}"
5259

0 commit comments

Comments
 (0)