Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Last line removed unexpectly when doing whole file range formatting with stylish-haskell. #3847

Closed
BurningLutz opened this issue Oct 16, 2023 · 1 comment
Labels
component: formatters type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc..

Comments

@BurningLutz
Copy link
Contributor

BurningLutz commented Oct 16, 2023

Your environment

Which OS do you use?
Ubuntu on WSL2 on Windows
Which version of GHC do you use and how did you install it?
9.6.3 from ghcup
Which LSP client (editor/plugin) do you use?
Neovim + lspconfig
Which version of HLS do you use and how did you install it?
2.4.0.0 from ghcup

Steps to reproduce

  1. Config stylish-haskell as format provider.
  2. Select all lines and do a range formatting, you'll see the last line get removed.

Expected behaviour

The last line should not be removed.

Actual behaviour

The last line get removed unexpectly.

Debug information

After some investigation(took a look at messages passed between client & server and hls's source code), I'm quite sure it is caused by Ide.PluginUtils.extractTextInRange

-- | Extracts exact matching text in the range.
extractTextInRange :: Range -> T.Text -> T.Text
extractTextInRange (Range (Position sl sc) (Position el ec)) s = newS
  where
    focusLines = take (fromIntegral $ el - sl + 1) $ drop (fromIntegral sl) $ T.lines s
    -- NOTE: We have to trim the last line first to handle the single-line case
    newS =
      focusLines
        & _last %~ T.take (fromIntegral ec)
        & _head %~ T.drop (fromIntegral sc)
        -- NOTE: We cannot use unlines here, because we don't want to add trailing newline!
        & T.intercalate "\n"

Now, let me explain.

Suppose we have codes like:

module Main where

main :: IO ()
main = do
  putStrLn "Hello, World"

When I select all lines and call format in neovim, it sends a range formatting message with the range (0, 0) ~ (4, 25), and after range normalization, extractTextInRange received the range (0, 0) ~ (5, 0) along with the whole file content.

And then, T.lines returned a List with 5 Text inside an further been dropped by 0 and taken by 6. It's taken by 6 but there are only 5 Text available. And when creating newS the last Text is removed by (T.take (fromIntegral 0)).

Note that this bug is only triggered by a whole file range formatting, in the example above, if I select only the top 4 lines, T.lines will be dropped by 0 and taken by 5, and there are 5 Text available so no trouble at all.

@BurningLutz BurningLutz added status: needs triage type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc.. labels Oct 16, 2023
BurningLutz added a commit to BurningLutz/haskell-language-server that referenced this issue Oct 26, 2023
BurningLutz added a commit to BurningLutz/haskell-language-server that referenced this issue Oct 26, 2023
@michaelpj
Copy link
Collaborator

Thanks for the diagnosis, looks like you've got a fix in progress?

@mergify mergify bot closed this as completed in afac9b1 Nov 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: formatters type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc..
Projects
None yet
Development

No branches or pull requests

3 participants