Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog for rust-notebook-language-server

## 0.2.7.1

* Fix textDocument/selectionRange answering nothing, by cutting a selection range chain where it leaves the cell

## 0.2.7.0

* Transform textDocument/selectionRange, textDocument/semanticTokens and the goto family, which reached the client in shadow coordinates
Expand Down
2 changes: 1 addition & 1 deletion package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: rust-notebook-language-server
version: 0.2.7.0
version: 0.2.7.1

extra-source-files:
- README.md
Expand Down
3 changes: 2 additions & 1 deletion rust-notebook-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack

name: rust-notebook-language-server
version: 0.2.7.0
version: 0.2.7.1
build-type: Simple
extra-source-files:
README.md
Expand Down Expand Up @@ -104,6 +104,7 @@ test-suite rust-notebook-language-server-test
Test.CodeAction
Test.Formatting
Test.Hover
Test.SelectionRange
Test.Transformer.HeadTail
Test.Transformer.StripDirective
TestLib.Common
Expand Down
2 changes: 1 addition & 1 deletion stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ system-ghc: true

extra-deps:
- git: https://github.com/codedownio/notebook-language-server-core.git
commit: b10c0d26debbea7ed97327eb8fff9bdb95571921
commit: 92760aa38d1db665191073ecf68790d3b9797085

# - language-rust-0.2.0.27

Expand Down
6 changes: 3 additions & 3 deletions stack.yaml.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

packages:
- completed:
commit: b10c0d26debbea7ed97327eb8fff9bdb95571921
commit: 92760aa38d1db665191073ecf68790d3b9797085
git: https://github.com/codedownio/notebook-language-server-core.git
name: notebook-language-server-core
pantry-tree:
sha256: 0e014e799318cf86e866796395c8e50766903b11da434d895069831794748203
sha256: ee0b04b246be5673a83e04dd42ff484e4ec62ae76b90c360cce3651c6de967f9
size: 2721
version: 0.1.0.0
original:
commit: b10c0d26debbea7ed97327eb8fff9bdb95571921
commit: 92760aa38d1db665191073ecf68790d3b9797085
git: https://github.com/codedownio/notebook-language-server-core.git
snapshots:
- completed:
Expand Down
135 changes: 135 additions & 0 deletions test/Test/SelectionRange.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

-- | Expand-selection, run through the real 'RustNotebookTransformer'. A selection range is a
-- chain of ranges, each naming the wider one that contains it, and the widest links always reach
-- the @fn main() {@ that the shadow document wraps the cells in. Requiring the whole chain to map
-- back meant every chain was thrown away and the answer was always empty.
module Test.SelectionRange (tests, main) where

import Control.Monad.IO.Class
import Control.Monad.Logger
import Control.Monad.Reader
import Data.Text (Text)
import Language.LSP.NotebookLanguageServer.Transform.ClientReq
import Language.LSP.NotebookLanguageServer.Transform.ServerRsp
import Language.LSP.Protocol.Message
import Language.LSP.Protocol.Types
import Test.Sandwich
import TestLib.Transformers
import Transform.Config


tests :: TopSpec
tests = describe "SelectionRange" $ do
describe "the request" $ do
-- A selectionRange request carries a list of positions rather than one, and each moves on
-- its own.
it "moves every position into the shadow document" $ do
runRequest (askedAbout notebookUri [Position 7 4, Position 8 10])
>>= (`shouldBe` askedAbout notebookShadowUri [Position 8 4, Position 9 10])

it "leaves a document we aren't shadowing alone" $ do
let elsewhere = askedAbout (Uri "file:///home/other.rs") [Position 7 4]
runRequest elsewhere >>= (`shouldBe` elsewhere)

-- A plain .rs file takes idTransformerParams, so there's no wrapper and nothing to shift.
it "shifts a plain .rs file's positions by nothing at all" $ do
runRequest (askedAbout plainUri [Position 6 8])
>>= (`shouldBe` askedAbout plainShadowUri [Position 6 8])

describe "the response" $ do
-- The regression: expand-selection did nothing at all, because every chain reaches the
-- wrapper eventually and so every chain was dropped.
it "answers at all, rather than coming back empty" $ do
answered <- runResponse notebookUri (InL [piChain])
null (chainsOf answered) `shouldBe` False

-- The innermost range on the cell's line, and the chain cut before the two links that start
-- on the `fn main() {` we added.
it "cuts the chain where it leaves the cell" $ do
answered <- runResponse notebookUri (InL [piChain])
chainsOf answered
`shouldBe` [[Range (Position 7 4) (Position 7 6), Range (Position 7 0) (Position 7 14)]]

-- Shadow line 0 is in no cell, so there's no innermost range left to answer with.
it "drops a chain whose innermost range isn't in a cell" $ do
runResponse notebookUri (InL [chain [(0, 10, 11), (0, 0, 1)]]) >>= (`shouldBe` InL [])

it "leaves a null answer alone" $
runResponse notebookUri (InR Null) >>= (`shouldBe` InR Null)

it "shifts a plain .rs file's chain by nothing at all" $ do
let answered = chain [(6, 8, 10), (6, 4, 18)]
runResponse plainUri (InL [answered]) >>= (`shouldBe` InL [answered])

runRequest :: MonadIO m => SelectionRangeParams -> m SelectionRangeParams
runRequest params = liftIO $ do
state <- transformerStateWith [notebookDocumentState cellLines, plainDocumentState plainFileLines]
runNoLoggingT $ runReaderT
(transformClientReq' (rustNotebookConfig shadowDir 0) SMethod_TextDocumentSelectionRange params) state

runResponse :: MonadIO m
=> Uri
-> MessageResult Method_TextDocumentSelectionRange
-> m (MessageResult Method_TextDocumentSelectionRange)
runResponse u result = liftIO $ do
state <- transformerStateWith [notebookDocumentState cellLines, plainDocumentState plainFileLines]
runNoLoggingT $ runReaderT
(transformServerRsp' (rustNotebookConfig shadowDir 0) SMethod_TextDocumentSelectionRange
(askedAbout u [Position 7 4]) result) state

askedAbout :: Uri -> [Position] -> SelectionRangeParams
askedAbout u = SelectionRangeParams Nothing Nothing (TextDocumentIdentifier u)

-- | Roughly what rust-analyzer answers for the cursor inside @pi@ on shadow line 8: the
-- identifier, the statement it belongs to, then the block and the function, both of which begin
-- on the @fn main() {@ line the transformer added.
piChain :: SelectionRange
piChain = chain [(8, 4, 6), (8, 0, 14), (0, 10, 11), (0, 0, 1)]

-- | Innermost first, each one's parent being the next, given as (line, start column, end column).
chain :: [(UInt, UInt, UInt)] -> SelectionRange
chain [] = error "a selection range is at least one range"
chain ((l, s, e):rest) = SelectionRange (Range (Position l s) (Position l e)) $ case rest of
[] -> Nothing
_ -> Just (chain rest)

-- | Each answered chain flattened by walking @parent@, innermost first.
chainsOf :: MessageResult Method_TextDocumentSelectionRange -> [[Range]]
chainsOf (InL chains) = fmap rangesOf chains
where rangesOf (SelectionRange r parent) = r : maybe [] rangesOf parent
chainsOf (InR _) = []

-- | @let pi = 3.14;@ is notebook line 7, so shadow line 8. The @:dep@ line is there so the
-- composed @StripDirective :> HeadTailTransformer@ is the thing under test, not just the half
-- of it that shifts lines.
cellLines :: [Text]
cellLines = [
":dep rand = \"0.8\""
, ""
, "fn area(r: f64) -> f64 {"
, " 3.14159 * r * r"
, "}"
, ""
, "let r = 2.0;"
, "let pi = 3.14;"
, "println!(\"{} {}\", area(r), pi);"
]

-- | @let pi = 3.14;@ is line 6 here, and stays line 6 in the shadow document.
plainFileLines :: [Text]
plainFileLines = [
"fn area(r: f64) -> f64 {"
, " 3.14159 * r * r"
, "}"
, ""
, "fn main() {"
, " let r = 2.0;"
, " let pi = 3.14;"
, " println!(\"{} {}\", area(r), pi);"
, "}"
]

main :: IO ()
main = runSandwichWithCommandLineArgs defaultOptions tests
Loading