lsp-types-2.4.0.0: test/SemanticTokensSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module SemanticTokensSpec where
import Data.Either (isRight)
import Data.List (unfoldr)
import Language.LSP.Protocol.Types
import Test.Hspec
spec :: Spec
spec = do
let
allMods = [SemanticTokenModifiers_Abstract, SemanticTokenModifiers_Static]
exampleLegend =
SemanticTokensLegend
(fmap toEnumBaseType [SemanticTokenTypes_Property, SemanticTokenTypes_Type, SemanticTokenTypes_Class])
(fmap toEnumBaseType allMods)
exampleTokens1 =
[ SemanticTokenAbsolute 2 5 3 SemanticTokenTypes_Property allMods
, SemanticTokenAbsolute 2 10 4 SemanticTokenTypes_Type []
, SemanticTokenAbsolute 5 2 7 SemanticTokenTypes_Class []
]
exampleTokens2 =
[ SemanticTokenAbsolute 3 5 3 SemanticTokenTypes_Property allMods
, SemanticTokenAbsolute 3 10 4 SemanticTokenTypes_Type []
, SemanticTokenAbsolute 6 2 7 SemanticTokenTypes_Class []
]
bigNumber :: UInt
bigNumber = 100000
bigTokens =
unfoldr (\i -> if i == bigNumber then Nothing else Just (SemanticTokenAbsolute i 1 1 SemanticTokenTypes_Type allMods, i + 1)) 0
-- Relativized version of bigTokens
bigTokensRel =
unfoldr (\i -> if i == bigNumber then Nothing else Just (SemanticTokenRelative (if i == 0 then 0 else 1) 1 1 SemanticTokenTypes_Type allMods, i + 1)) 0
-- One more order of magnitude makes diffing more-or-less hang - possibly we need a better diffing algorithm, since this is only ~= 200 tokens at 5 ints per token
-- (I checked and it is the diffing that's slow, not turning it into edits)
smallerBigNumber :: UInt
smallerBigNumber = 1000
bigInts :: [UInt]
bigInts =
unfoldr (\i -> if i == smallerBigNumber then Nothing else Just (1, i + 1)) 0
bigInts2 :: [UInt]
bigInts2 =
unfoldr (\i -> if i == smallerBigNumber then Nothing else Just (if even i then 2 else 1, i + 1)) 0
describe "relativize/absolutizeTokens" $ do
it "round-trips" $ do
absolutizeTokens (relativizeTokens exampleTokens1) `shouldBe` exampleTokens1
absolutizeTokens (relativizeTokens exampleTokens2) `shouldBe` exampleTokens2
it "handles big tokens" $ relativizeTokens bigTokens `shouldBe` bigTokensRel
describe "encodeTokens" $ do
context "when running the LSP examples" $ do
it "encodes example 1 correctly" $
let encoded = encodeTokens exampleLegend (relativizeTokens exampleTokens1)
in encoded `shouldBe` Right [{- token 1 -} 2, 5, 3, 0, 3 {- token 2 -}, 0, 5, 4, 1, 0 {- token 3 -}, 3, 2, 7, 2, 0]
it "encodes example 2 correctly" $
let encoded = encodeTokens exampleLegend (relativizeTokens exampleTokens2)
in encoded `shouldBe` Right [{- token 1 -} 3, 5, 3, 0, 3 {- token 2 -}, 0, 5, 4, 1, 0 {- token 3 -}, 3, 2, 7, 2, 0]
it "handles big tokens" $ encodeTokens exampleLegend bigTokensRel `shouldSatisfy` isRight
describe "computeEdits" $ do
it "handles an edit in the middle" $
computeEdits @Int [1, 2, 3] [1, 4, 5, 3] `shouldBe` [Edit 1 1 [4, 5]]
it "handles an edit at the end" $
computeEdits @Int [1, 2, 3] [1, 2, 4, 5] `shouldBe` [Edit 2 1 [4, 5]]
it "handles an edit at the beginning" $
computeEdits @Int [1, 2, 3] [4, 5, 2, 3] `shouldBe` [Edit 0 1 [4, 5]]
it "handles an ambiguous edit" $
computeEdits @Int [1, 2, 3] [1, 3, 4, 3] `shouldBe` [Edit 1 1 [], Edit 3 0 [4, 3]]
it "handles a long edit" $
computeEdits @Int [1, 2, 3, 4, 5] [1, 7, 7, 7, 7, 7, 5] `shouldBe` [Edit 1 3 [7, 7, 7, 7, 7]]
it "handles multiple edits" $
computeEdits @Int [1, 2, 3, 4, 5] [1, 6, 3, 7, 7, 5] `shouldBe` [Edit 1 1 [6], Edit 3 1 [7, 7]]
it "handles big tokens" $
-- It's a little hard to specify a useful predicate here, the main point is that it should not take too long
computeEdits @UInt bigInts bigInts2 `shouldSatisfy` (not . null)