Skip to content

Commit 1e68cb0

Browse files
authored
Group Imports in Outline into a single node (#443)
* Group Imports in Outline into a single node Makes it easier to see symbols in scope when you have lots of import statements. * Prefer explicit Maybe over List type
1 parent 3ca4005 commit 1e68cb0

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

src/Development/IDE/LSP/Outline.hs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ moduleOutline _lsp ideState DocumentSymbolParams { _textDocument = TextDocumentI
5050
, _kind = SkFile
5151
, _range = Range (Position 0 0) (Position maxBound 0) -- _ltop is 0 0 0 0
5252
}
53-
importSymbols = mapMaybe documentSymbolForImport hsmodImports
53+
importSymbols = maybe [] pure $
54+
documentSymbolForImportSummary
55+
(mapMaybe documentSymbolForImport hsmodImports)
5456
allSymbols = case moduleSymbol of
5557
Nothing -> importSymbols <> declSymbols
5658
Just x ->
@@ -167,6 +169,25 @@ documentSymbolForDecl (L l (ForD x)) = Just
167169

168170
documentSymbolForDecl _ = Nothing
169171

172+
-- | Wrap the Document imports into a hierarchical outline for
173+
-- a better overview of symbols in scope.
174+
-- If there are no imports, then no hierarchy will be created.
175+
documentSymbolForImportSummary :: [DocumentSymbol] -> Maybe DocumentSymbol
176+
documentSymbolForImportSummary [] = Nothing
177+
documentSymbolForImportSummary importSymbols =
178+
let
179+
-- safe because if we have no ranges then we don't take this branch
180+
mergeRanges xs = Range (minimum $ map _start xs) (maximum $ map _end xs)
181+
importRange = mergeRanges $ map (_range :: DocumentSymbol -> Range) importSymbols
182+
in
183+
Just (defDocumentSymbol empty :: DocumentSymbol)
184+
{ _name = "imports"
185+
, _kind = SkModule
186+
, _children = Just (List importSymbols)
187+
, _range = importRange
188+
, _selectionRange = importRange
189+
}
190+
170191
documentSymbolForImport :: Located (ImportDecl GhcPs) -> Maybe DocumentSymbol
171192
documentSymbolForImport (L l ImportDecl { ideclName, ideclQualified }) = Just
172193
(defDocumentSymbol l :: DocumentSymbol)

test/exe/Main.hs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1717,7 +1717,24 @@ outlineTests = testGroup
17171717
docId <- openDoc' "A.hs" "haskell" source
17181718
symbols <- getDocumentSymbols docId
17191719
liftIO $ symbols @?= Left
1720-
[docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)]
1720+
[docSymbolWithChildren "imports"
1721+
SkModule
1722+
(R 0 0 0 17)
1723+
[ docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)
1724+
]
1725+
]
1726+
, testSessionWait "multiple import" $ do
1727+
let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]
1728+
docId <- openDoc' "A.hs" "haskell" source
1729+
symbols <- getDocumentSymbols docId
1730+
liftIO $ symbols @?= Left
1731+
[docSymbolWithChildren "imports"
1732+
SkModule
1733+
(R 1 0 3 24)
1734+
[ docSymbol "import Data.Maybe" SkModule (R 1 0 1 17)
1735+
, docSymbol "import Control.Exception" SkModule (R 3 0 3 24)
1736+
]
1737+
]
17211738
, testSessionWait "foreign import" $ do
17221739
let source = T.unlines
17231740
[ "{-# language ForeignFunctionInterface #-}"

0 commit comments

Comments
 (0)