Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
098882d
save some progress: add basic starter code for folding ranges
sloorush Jul 23, 2022
2e44b7a
save some progress: add function to traverse through coderange and fo…
sloorush Aug 6, 2022
fec1824
save some progress: add parsing of folding ranges
sloorush Aug 9, 2022
f9ffcc1
fix: maybe issue with foldingRanges
sloorush Aug 9, 2022
1d28a2c
add: generate folding ranges from coderange
sloorush Aug 9, 2022
60b2136
add: plugin request method instance for folding ranges
sloorush Aug 9, 2022
02a1e9d
ref: alter function and var names
sloorush Aug 9, 2022
a032c78
post review: cleanup crk to frk & fix typo
sloorush Aug 10, 2022
892a129
fix: find folding ranges function
sloorush Aug 12, 2022
e6a2b5c
format: run formatter and add comments
sloorush Aug 12, 2022
e21f5cb
fix: return all response results of folding range request
sloorush Aug 12, 2022
799db9b
Revert "format: run formatter and add comments"
sloorush Aug 13, 2022
5d0d159
add: removed comments after revert
sloorush Aug 13, 2022
332e953
fix: formatting
sloorush Aug 16, 2022
c4f386d
docs: add folding range to features section and cabal file
sloorush Aug 16, 2022
8eb7a30
refactor: use destructuring for createFoldingRange function and use c…
sloorush Aug 16, 2022
60e3fb2
test: add basic unit test for findFoldingRanges function
sloorush Sep 7, 2022
e3f0007
test: add tests for children and code kind
sloorush Sep 7, 2022
474ffef
test: add more test cases
sloorush Sep 7, 2022
6975302
test: add test for createFoldingRange
sloorush Sep 8, 2022
a430a43
test: add integration test for folding ranges
sloorush Sep 10, 2022
baf419e
fix: duplicate start line foldingranges and remove single line
sloorush Sep 11, 2022
d6a8666
Merge branch 'master' of github.com:sloorush/haskell-language-server …
sloorush Sep 12, 2022
e9dc569
refactor: duplicate folding range functionality
sloorush Sep 12, 2022
c46a7f4
fix: formatting in code range plugin
sloorush Sep 12, 2022
959a53b
added more descriptive comments and encorporate code review suggestions
sloorush Sep 14, 2022
e8ee9f9
revert: automatic formatting for selection range test case file
sloorush Sep 14, 2022
44c5819
fix: ignoring children if root fails to provide folding ranges
sloorush Sep 18, 2022
9181b04
remove: redundant match on crkToFrk
sloorush Sep 19, 2022
86f1068
revert: filtering same line foldings and multiple foldings on the sam…
sloorush Sep 19, 2022
c3f1c4a
Merge branch 'haskell:master' into folding-ranges
sloorush Sep 19, 2022
57cb482
revert: formatting change to selection range test file
sloorush Sep 19, 2022
ccd9fa5
fix: entire file folding because of root node
sloorush Sep 21, 2022
c023548
Merge branch 'master' into folding-ranges
Sep 21, 2022
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
revert: filtering same line foldings and multiple foldings on the sam…
…e line as it can be handled by clients
  • Loading branch information
sloorush committed Sep 19, 2022
commit 86f10689f1811d5382e8551fcd52b8a50525417c
53 changes: 17 additions & 36 deletions plugins/hls-code-range-plugin/src/Ide/Plugin/CodeRange.hs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ foldingRangeHandler ide _ FoldingRangeParams{..} = do
toNormalizedFilePath' <$> uriToFilePath' uri
foldingRanges <- ExceptT . liftIO . runIdeAction "FoldingRange" (shakeExtras ide) . runExceptT $
getFoldingRanges filePath
pure . List $ removeDupStartLineFoldings foldingRanges
pure . List $ foldingRanges
where
uri :: Uri
TextDocumentIdentifier uri = _textDocument
Expand Down Expand Up @@ -152,6 +152,21 @@ findPosition pos root = go Nothing root
--
-- It starts with the root node, converts that into a folding range then moves towards the children.
-- It converts each child of each root node and parses it to folding range and moves to its children.
--
-- Two cases to that are assumed to be taken care on the client side are:
--
-- 1. When a folding range starts and ends on the same line, it is upto the client if it wants to
-- fold a single line folding or not.
--
-- 2. As we are converting nodes of the ast into folding ranges, there are multiple nodes starting from a single line.
-- A single line of code doesn't mean a single node in AST, so this function removes all the nodes that have a duplicate
-- start line, ie. they start from the same line.
-- Eg. A multi-line function that also has a multi-line if statement starting from the same line should have the folding
-- according to the function.
--
-- We think the client can handle this, if not we could change to remove these in future
--
-- Discussion reference: https://github.com/haskell/haskell-language-server/pull/3058#discussion_r973737211
findFoldingRanges :: CodeRange -> [FoldingRange]
findFoldingRanges r@(CodeRange _ children _) =
let frChildren :: [FoldingRange] = concat $ V.toList $ fmap findFoldingRanges children
Expand All @@ -165,41 +180,7 @@ createFoldingRange (CodeRange (Range (Position lineStart charStart) (Position li
-- Type conversion of codeRangeKind to FoldingRangeKind
let frk = crkToFrk ck

-- Filtering code ranges that start and end on the same line as need/can not be folded.
--
-- Eg. A single line function will also generate a Folding Range but it cannot be folded
-- because it is already single line, so omiting it.
if lineStart == lineEnd
then Nothing
else Just (FoldingRange lineStart (Just charStart) lineEnd (Just charEnd) (Just frk))

-- | Removes all small foldings that start from the same line.
--
-- As we are converting nodes of the ast into folding ranges, there are multiple nodes starting from a single line.
-- A single line of code doesn't mean a single node in AST, so this function removes all the nodes that have a duplicate
-- start line, ie. they start from the same line.
--
-- This function preserves the largest folding range from the ranges that start from the same line.
--
-- Eg. A multi-line function that also has a multi-line if statement starting from the same line should have the folding
-- according to the function.
--
-- This is done by breaking the [FoldingRange] into parts -->
-- frx: Head
-- xs: rest of the array
-- fry(not shown as it is not used): head of xs
-- xs2: rest of the array other than the first two elements
-- slx and sly: start line of frx and fry
--
-- We compare the start line of the first two elements in the array and if the start line is the same we remove the
-- second one as it is the smaller one amoung the two.
-- otherwise frx is returned and the function runs recursively on xs.
removeDupStartLineFoldings :: [FoldingRange] -> [FoldingRange]
removeDupStartLineFoldings [] = []
removeDupStartLineFoldings [x] = [x]
removeDupStartLineFoldings (frx@(FoldingRange slx _ _ _ _):xs@((FoldingRange sly _ _ _ _):xs2))
| slx == sly = removeDupStartLineFoldings (frx:xs2)
| otherwise = frx : removeDupStartLineFoldings xs
Just (FoldingRange lineStart (Just charStart) lineEnd (Just charEnd) (Just frk))

-- | Likes 'toCurrentPosition', but works on 'SelectionRange'
toCurrentSelectionRange :: PositionMapping -> SelectionRange -> Maybe SelectionRange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ testTree =
)
],

-- TODO: Some more tests can be added on strange cases like
-- 1. lots of blank lines in between type signature and the body
-- 2. lots of blank lines in the function itself
-- etc.
testGroup "findFoldingRanges" $
let check :: CodeRange -> [FoldingRange] -> Assertion
check codeRange = (findFoldingRanges codeRange @?=)
Expand Down Expand Up @@ -88,7 +92,7 @@ testTree =
-- Single line returns [] because single line ranges need not be folded
testCase "Test Single Line" $ check
(mkCodeRange (Position 1 0) (Position 1 15) [] CodeKindRegion)
[],
[FoldingRange 1 (Just 0) 1 (Just 15) (Just FoldingRangeRegion)],

-- MultiLine imports
testCase "MultiLine Imports" $ check
Expand All @@ -110,6 +114,6 @@ testTree =
-- If a range has the same start and end line it need not be folded so Nothing is expected
testCase "Test Same Start Line" $ check
(mkCodeRange (Position 1 1) (Position 1 10) [] CodeKindRegion)
Nothing
(Just (FoldingRange 1 (Just 1) 1 (Just 10) (Just FoldingRangeRegion)))
]
]
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
((4, 0) : (7, 21)) : FoldingRangeRegion
((5, 0) : (7, 21)) : FoldingRangeRegion
((4, 0) : (4, 25)) : FoldingRangeRegion
((4, 0) : (4, 6)) : FoldingRangeRegion
((4, 10) : (4, 25)) : FoldingRangeRegion
((4, 10) : (4, 17)) : FoldingRangeRegion
((4, 21) : (4, 25)) : FoldingRangeRegion
((5, 0) : (7, 21)) : FoldingRangeRegion
((5, 0) : (5, 6)) : FoldingRangeRegion
((5, 7) : (5, 8)) : FoldingRangeRegion
((5, 9) : (7, 21)) : FoldingRangeRegion
((5, 11) : (7, 21)) : FoldingRangeRegion
((5, 14) : (5, 28)) : FoldingRangeRegion
((5, 14) : (5, 23)) : FoldingRangeRegion
((5, 14) : (5, 15)) : FoldingRangeRegion
((5, 16) : (5, 21)) : FoldingRangeRegion
((5, 22) : (5, 23)) : FoldingRangeRegion
((5, 24) : (5, 26)) : FoldingRangeRegion
((5, 27) : (5, 28)) : FoldingRangeRegion
((6, 16) : (6, 20)) : FoldingRangeRegion
((7, 16) : (7, 21)) : FoldingRangeRegion