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

add Method_TextDocumentSemanticTokensFullDelta #4073

Merged
merged 28 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
43796d0
add Method_TextDocumentSemanticTokensFullDelta
soulomoon Feb 13, 2024
3f29007
fix cache and add test
soulomoon Feb 13, 2024
ff93475
cleanpu
soulomoon Feb 13, 2024
decd9e1
add tset
soulomoon Feb 13, 2024
e1fd84e
add delete tokens test
soulomoon Feb 13, 2024
41499b4
clean up
soulomoon Feb 13, 2024
9b373f3
clean up
soulomoon Feb 13, 2024
4f7546a
add delete tokens test
soulomoon Feb 13, 2024
8af3b99
cleanup
soulomoon Feb 13, 2024
181b10a
fix test
soulomoon Feb 13, 2024
9e7af72
cleanup
soulomoon Feb 13, 2024
cef51ed
remove persistentGetSemanticTokensRule
soulomoon Feb 14, 2024
fa908a0
fix export
soulomoon Feb 14, 2024
e3ed49b
cleanup
soulomoon Feb 14, 2024
82b1eaf
Update plugins/hls-semantic-tokens-plugin/test/SemanticTokensTest.hs
soulomoon Feb 14, 2024
e7a17e7
cleanup
soulomoon Feb 14, 2024
cc69775
add doc
soulomoon Feb 14, 2024
49fd150
cleanup
soulomoon Feb 14, 2024
dcdbb27
Update plugins/hls-semantic-tokens-plugin/src/Ide/Plugin/SemanticToke…
soulomoon Feb 14, 2024
7e7398a
fix
soulomoon Feb 14, 2024
e6ff123
Merge branch 'master' into 4072-textdocumentsemantictokensfulldelta
soulomoon Feb 14, 2024
9ef7796
Merge branch 'master' into 4072-textdocumentsemantictokensfulldelta
soulomoon Feb 19, 2024
b287639
neat
soulomoon Feb 19, 2024
154013b
add doc
soulomoon Feb 19, 2024
42f6284
Merge branch 'master' into 4072-textdocumentsemantictokensfulldelta
soulomoon Feb 21, 2024
699dab7
add doc about semanticTokensCache location
soulomoon Feb 21, 2024
a0b6ac7
add Note [Semantic Tokens Cache Location]
soulomoon Feb 21, 2024
4180c43
fix doc
soulomoon Feb 21, 2024
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
9 changes: 9 additions & 0 deletions ghcide/src/Development/IDE/Core/Shake.hs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
import Development.IDE.Core.ProgressReporting
import Development.IDE.Core.RuleTypes
import Development.IDE.Core.Tracing
import Development.IDE.GHC.Compat (NameCache,

Check warning on line 128 in ghcide/src/Development/IDE/Core/Shake.hs

View workflow job for this annotation

GitHub Actions / Hlint check run

Warning in module Development.IDE.Core.Shake: Use fewer imports ▫︎ Found: "import Development.IDE.GHC.Compat\n ( NameCache, NameCacheUpdater(..), initNameCache, knownKeyNames )\nimport Development.IDE.GHC.Compat\n ( mkSplitUniqSupply, upNameCache )\n" ▫︎ Perhaps: "import Development.IDE.GHC.Compat\n ( NameCache,\n NameCacheUpdater(..),\n initNameCache,\n knownKeyNames,\n mkSplitUniqSupply,\n upNameCache )\n"
NameCacheUpdater (..),
initNameCache,
knownKeyNames)
Expand Down Expand Up @@ -163,7 +163,8 @@
import Language.LSP.Diagnostics
import qualified Language.LSP.Protocol.Lens as L
import Language.LSP.Protocol.Message
import Language.LSP.Protocol.Types

Check warning on line 166 in ghcide/src/Development/IDE/Core/Shake.hs

View workflow job for this annotation

GitHub Actions / Hlint check run

Warning in module Development.IDE.Core.Shake: Use fewer imports ▫︎ Found: "import Language.LSP.Protocol.Types\nimport Language.LSP.Protocol.Types ( SemanticTokens )\nimport qualified Language.LSP.Protocol.Types as LSP\n" ▫︎ Perhaps: "import Language.LSP.Protocol.Types\nimport qualified Language.LSP.Protocol.Types as LSP\n"
import Language.LSP.Protocol.Types (SemanticTokens)
import qualified Language.LSP.Protocol.Types as LSP
import qualified Language.LSP.Server as LSP
import Language.LSP.VFS hiding (start)
Expand Down Expand Up @@ -243,6 +244,7 @@
-- with (currently) retry functionality
type IndexQueue = TQueue (((HieDb -> IO ()) -> IO ()) -> IO ())


-- information we stash inside the shakeExtra field
data ShakeExtras = ShakeExtras
{ --eventer :: LSP.FromServerMessage -> IO ()
Expand All @@ -259,6 +261,11 @@
,publishedDiagnostics :: STM.Map NormalizedUri [Diagnostic]
-- ^ This represents the set of diagnostics that we have published.
-- Due to debouncing not every change might get published.
,semanticTokensCache:: STM.Map NormalizedUri SemanticTokens
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these could probably be variables local to the plugin? I think we only need to put thing in here if they're really shared across multiple rules etc.

So the function that creates the plugin would run in IO or similar and create the TVars, which then get passed into the handlers.

Copy link
Collaborator Author

@soulomoon soulomoon Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that putting it in shakeExtras is suboptimal, but I am also not sure about local state to plugin too.
Since no other plugins have their own plugin state. It would mean we need to change idePlugins :: Recorder (WithPriority Log) -> IdePlugins IdeState to idePlugins :: Recorder (WithPriority Log) -> IO (IdePlugins IdeState).
And open a door to introduce state to plugins breaking the current centralized state management in the hls build system. 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think plugin-local state is inherently problematic. But I admit that it's not totally clear to me what stuff should be in ShakeExtras 🤔 thoughts @fendor ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a comment to the shakeExtra stating it might not be ideal to store the varaibles there, but we do not find a better place to store it yet.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not have any specific thoughts, if the variable could be easily plugin local, I think I would prefer that.

-- ^ Cache of last response of semantic tokens for each file,
-- so we can compute deltas for semantic tokens(SMethod_TextDocumentSemanticTokensFullDelta).
,semanticTokensId :: TVar Int
-- ^ semanticTokensId is used to generate unique ids for each lsp response of semantic tokens.
,positionMapping :: STM.Map NormalizedUri (EnumMap Int32 (PositionDelta, PositionMapping))
-- ^ Map from a text document version to a PositionMapping that describes how to map
-- positions in a version of that document to positions in the latest version
Expand Down Expand Up @@ -616,12 +623,14 @@
diagnostics <- STM.newIO
hiddenDiagnostics <- STM.newIO
publishedDiagnostics <- STM.newIO
semanticTokensCache <- STM.newIO
positionMapping <- STM.newIO
knownTargetsVar <- newTVarIO $ hashed HMap.empty
let restartShakeSession = shakeRestart recorder ideState
persistentKeys <- newTVarIO mempty
indexPending <- newTVarIO HMap.empty
indexCompleted <- newTVarIO 0
semanticTokensId <- newTVarIO 0
indexProgressToken <- newVar Nothing
let hiedbWriter = HieDbWriter{..}
exportsMap <- newTVarIO mempty
Expand Down
5 changes: 4 additions & 1 deletion haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -1574,14 +1574,16 @@ library hls-semantic-tokens-plugin
, hls-graph == 2.6.0.0
, template-haskell
, data-default
, stm
, stm-containers

default-extensions: DataKinds

test-suite hls-semantic-tokens-plugin-tests
import: defaults, pedantic, test-defaults, warnings
type: exitcode-stdio-1.0
hs-source-dirs: plugins/hls-semantic-tokens-plugin/test
main-is: Main.hs
main-is: SemanticTokensTest.hs

build-depends:
, aeson
Expand All @@ -1601,6 +1603,7 @@ test-suite hls-semantic-tokens-plugin-tests
, ghcide == 2.6.0.0
, hls-plugin-api == 2.6.0.0
, data-default
, row-types

-----------------------------
-- HLS
Expand Down
2 changes: 2 additions & 0 deletions hls-plugin-api/src/Ide/Plugin/ConfigUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pluginsToDefaultConfig IdePlugins {..} =
SMethod_TextDocumentCompletion -> ["completionOn" A..= plcCompletionOn]
SMethod_TextDocumentPrepareCallHierarchy -> ["callHierarchyOn" A..= plcCallHierarchyOn]
SMethod_TextDocumentSemanticTokensFull -> ["semanticTokensOn" A..= plcSemanticTokensOn]
SMethod_TextDocumentSemanticTokensFullDelta -> ["semanticTokensOn" A..= plcSemanticTokensOn]
_ -> []

-- | Generates json schema used in haskell vscode extension
Expand Down Expand Up @@ -125,6 +126,7 @@ pluginsToVSCodeExtensionSchema IdePlugins {..} = A.object $ mconcat $ singlePlug
SMethod_TextDocumentCompletion -> [toKey' "completionOn" A..= schemaEntry "completions" plcCompletionOn]
SMethod_TextDocumentPrepareCallHierarchy -> [toKey' "callHierarchyOn" A..= schemaEntry "call hierarchy" plcCallHierarchyOn]
SMethod_TextDocumentSemanticTokensFull -> [toKey' "semanticTokensOn" A..= schemaEntry "semantic tokens" plcSemanticTokensOn]
SMethod_TextDocumentSemanticTokensFullDelta -> [toKey' "semanticTokensOn" A..= schemaEntry "semantic tokens" plcSemanticTokensOn]
_ -> []
schemaEntry desc defaultVal =
A.object
Expand Down
6 changes: 6 additions & 0 deletions hls-plugin-api/src/Ide/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,9 @@ instance PluginMethod Request Method_TextDocumentRangeFormatting where
instance PluginMethod Request Method_TextDocumentSemanticTokensFull where
handlesRequest = pluginEnabledWithFeature plcSemanticTokensOn

instance PluginMethod Request Method_TextDocumentSemanticTokensFullDelta where
handlesRequest = pluginEnabledWithFeature plcSemanticTokensOn

instance PluginMethod Request Method_TextDocumentPrepareCallHierarchy where
handlesRequest = pluginEnabledWithFeature plcCallHierarchyOn

Expand Down Expand Up @@ -751,6 +754,9 @@ instance PluginRequestMethod (Method_CustomMethod m) where
instance PluginRequestMethod Method_TextDocumentSemanticTokensFull where
combineResponses _ _ _ _ (x :| _) = x

instance PluginRequestMethod Method_TextDocumentSemanticTokensFullDelta where
combineResponses _ _ _ _ (x :| _) = x

takeLefts :: [a |? b] -> [a]
takeLefts = mapMaybe (\x -> [res | (InL res) <- Just x])

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}


module Ide.Plugin.SemanticTokens (descriptor) where

Expand All @@ -12,8 +12,10 @@ import Language.LSP.Protocol.Message
descriptor :: Recorder (WithPriority SemanticLog) -> PluginId -> PluginDescriptor IdeState
descriptor recorder plId =
(defaultPluginDescriptor plId "Provides semantic tokens")
{ Ide.Types.pluginHandlers = mkPluginHandler SMethod_TextDocumentSemanticTokensFull (Internal.semanticTokensFull recorder),
Ide.Types.pluginRules = Internal.getSemanticTokensRule recorder <> Internal.persistentGetSemanticTokensRule,
{ Ide.Types.pluginHandlers =
mkPluginHandler SMethod_TextDocumentSemanticTokensFull (Internal.semanticTokensFull recorder)
<> mkPluginHandler SMethod_TextDocumentSemanticTokensFullDelta (Internal.semanticTokensFullDelta recorder),
Ide.Types.pluginRules = Internal.getSemanticTokensRule recorder,
pluginConfigDescriptor =
defaultConfigDescriptor
{ configInitialGenericConfig = (configInitialGenericConfig defaultConfigDescriptor) {plcGlobalOn = False}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@

-- |
-- This module provides the core functionality of the plugin.
module Ide.Plugin.SemanticTokens.Internal (semanticTokensFull, getSemanticTokensRule, persistentGetSemanticTokensRule, semanticConfigProperties) where
module Ide.Plugin.SemanticTokens.Internal (semanticTokensFull, getSemanticTokensRule, semanticConfigProperties, semanticTokensFullDelta) where

import Control.Concurrent.STM (stateTVar)
import Control.Concurrent.STM.Stats (atomically)
import Control.Lens ((^.))
import Control.Monad.Except (ExceptT, liftEither,
withExceptT)
import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Trans (lift)
import Control.Monad.Trans.Except (runExceptT)
import qualified Data.Map.Strict as M
import Data.Text (Text)
import qualified Data.Text as T
import Development.IDE (Action,
GetDocMap (GetDocMap),
GetHieAst (GetHieAst),
HieAstResult (HAR, hieAst, hieModule, refMap),
IdeResult, IdeState,
NormalizedUri,
Priority (..),
Recorder, Rules,
WithPriority,
Expand All @@ -31,10 +37,10 @@ import Development.IDE (Action,
hieKind, use_)
import Development.IDE.Core.PluginUtils (runActionE,
useWithStaleE)
import Development.IDE.Core.PositionMapping (idDelta)
import Development.IDE.Core.Rules (toIdeResult)
import Development.IDE.Core.RuleTypes (DocAndTyThingMap (..))
import Development.IDE.Core.Shake (addPersistentRule,
import Development.IDE.Core.Shake (ShakeExtras (..),
getShakeExtras,
getVirtualFile,
useWithStale_)
import Development.IDE.GHC.Compat hiding (Warning)
Expand All @@ -51,11 +57,14 @@ import Ide.Plugin.SemanticTokens.Tokenize (computeRangeHsSemanti
import Ide.Plugin.SemanticTokens.Types
import Ide.Types
import qualified Language.LSP.Protocol.Lens as L
import Language.LSP.Protocol.Message (Method (Method_TextDocumentSemanticTokensFull))
import Language.LSP.Protocol.Message (MessageResult,
Method (Method_TextDocumentSemanticTokensFull, Method_TextDocumentSemanticTokensFullDelta))
import Language.LSP.Protocol.Types (NormalizedFilePath,
SemanticTokens,
type (|?) (InL))
normalizedFilePathToUri,
type (|?) (InL, InR))
import Prelude hiding (span)
import qualified StmContainers.Map as STM


$mkSemanticConfigFunctions
Expand All @@ -68,14 +77,38 @@ computeSemanticTokens :: Recorder (WithPriority SemanticLog) -> PluginId -> IdeS
computeSemanticTokens recorder pid _ nfp = do
config <- lift $ useSemanticConfigAction pid
logWith recorder Debug (LogConfig config)
semanticId <- lift getAndIncreaseSemanticTokensId
soulomoon marked this conversation as resolved.
Show resolved Hide resolved
(RangeHsSemanticTokenTypes {rangeSemanticList}, mapping) <- useWithStaleE GetSemanticTokens nfp
withExceptT PluginInternalError $ liftEither $ rangeSemanticsSemanticTokens config mapping rangeSemanticList
withExceptT PluginInternalError $ liftEither $ rangeSemanticsSemanticTokens semanticId config mapping rangeSemanticList

semanticTokensFull :: Recorder (WithPriority SemanticLog) -> PluginMethodHandler IdeState 'Method_TextDocumentSemanticTokensFull
semanticTokensFull recorder state pid param = do
semanticTokensFull recorder state pid param = runActionE "SemanticTokens.semanticTokensFull" state computeSemanticTokensFullDelta
where
computeSemanticTokensFullDelta :: ExceptT PluginError Action (MessageResult Method_TextDocumentSemanticTokensFull)
soulomoon marked this conversation as resolved.
Show resolved Hide resolved
computeSemanticTokensFullDelta = do
nfp <- getNormalizedFilePathE (param ^. L.textDocument . L.uri)
items <- computeSemanticTokens recorder pid state nfp
lift $ setSemanticTokens (normalizedFilePathToUri nfp) items
soulomoon marked this conversation as resolved.
Show resolved Hide resolved
return $ InL items


semanticTokensFullDelta :: Recorder (WithPriority SemanticLog) -> PluginMethodHandler IdeState 'Method_TextDocumentSemanticTokensFullDelta
semanticTokensFullDelta recorder state pid param = do
nfp <- getNormalizedFilePathE (param ^. L.textDocument . L.uri)
items <- runActionE "SemanticTokens.semanticTokensFull" state $ computeSemanticTokens recorder pid state nfp
return $ InL items
let previousVersionFromParam = param ^. L.previousResultId
runActionE "SemanticTokens.semanticTokensFullDelta" state $ computeSemanticTokensFullDelta recorder previousVersionFromParam pid state nfp
where
computeSemanticTokensFullDelta :: Recorder (WithPriority SemanticLog) -> Text -> PluginId -> IdeState -> NormalizedFilePath -> ExceptT PluginError Action (MessageResult Method_TextDocumentSemanticTokensFullDelta)
computeSemanticTokensFullDelta recorder previousVersionFromParam pid state nfp = do
semanticTokens <- computeSemanticTokens recorder pid state nfp
previousSemanticTokensMaybe <- lift $ getPreviousSemanticTokens (normalizedFilePathToUri nfp)
lift $ setSemanticTokens (normalizedFilePathToUri nfp) semanticTokens
case previousSemanticTokensMaybe of
Nothing -> return $ InL semanticTokens
Just previousSemanticTokens ->
if Just previousVersionFromParam == previousSemanticTokens^.L.resultId
then return $ InR $ InL $ makeSemanticTokensDeltaWithId (semanticTokens^.L.resultId) previousSemanticTokens semanticTokens
else return $ InL semanticTokens
soulomoon marked this conversation as resolved.
Show resolved Hide resolved

-- | Defines the 'getSemanticTokensRule' function, compute semantic tokens for a Haskell source file.
--
Expand All @@ -98,9 +131,6 @@ getSemanticTokensRule recorder =
let hsFinder = idSemantic getTyThingMap (hieKindFunMasksKind hieKind) refMap
return $ computeRangeHsSemanticTokenTypeList hsFinder virtualFile ast

-- | Persistent rule to ensure that semantic tokens doesn't block on startup
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why drop this?

Copy link
Collaborator Author

@soulomoon soulomoon Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For semantic tokens,
lastValueIO return [](case with persistent key) or Nothing(case without persistent key).
Between faking a stale value [] and mark the semantic tokens rules' value actually Failed in shake state.
The former would hide the failure in both user of the rule and in the shake caching result(I don't think it is wise, we want to know if we fail in this case).

Also we are not using IdeAction with useWithStaleFastMT(Which look directly into the caching and demand instance response) for semantic tokens as in other IdeAction that requires instance response(e.g. hover, this fix startup of hover when the rule first compute without any stale value in the cach).

The persistent rule is rather useless for us and might shadow some actual failures.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so does this mean we have to wait quite a while to get responses when we start up?

Copy link
Collaborator Author

@soulomoon soulomoon Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, as we have been. Persistent rule won't help us here(Since it is not ideAction, the persistent rule serves only as a fall back when the actual computation of the rule failed and not already having a cache) .

persistentGetSemanticTokensRule :: Rules ()
persistentGetSemanticTokensRule = addPersistentRule GetSemanticTokens $ \_ -> pure $ Just (RangeHsSemanticTokenTypes mempty, idDelta, Nothing)

-- taken from /haskell-language-server/plugins/hls-code-range-plugin/src/Ide/Plugin/CodeRange/Rules.hs

Expand All @@ -113,3 +143,20 @@ handleError recorder action' = do
logWith recorder Warning msg
pure $ toIdeResult (Left [])
Right value -> pure $ toIdeResult (Right value)

-----------------------
-- helper functions
-----------------------

getAndIncreaseSemanticTokensId :: Action SemanticTokenId
getAndIncreaseSemanticTokensId = do
ShakeExtras{semanticTokensId} <- getShakeExtras
liftIO $ atomically $ do
i <- stateTVar semanticTokensId (\val -> (val, val+1))
return $ T.pack $ show i

getPreviousSemanticTokens :: NormalizedUri -> Action (Maybe SemanticTokens)
getPreviousSemanticTokens uri = getShakeExtras >>= liftIO . atomically . STM.lookup uri . semanticTokensCache

setSemanticTokens :: NormalizedUri -> SemanticTokens -> Action ()
setSemanticTokens uri tokens = getShakeExtras >>= liftIO . atomically . STM.insert tokens uri . semanticTokensCache
fendor marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}


-- |
-- This module provides mappings to convert token type information in the Haskell IDE plugin. It includes functions for:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}

-- |
-- The query module is used to query the semantic tokens from the AST
module Ide.Plugin.SemanticTokens.Query where
Expand All @@ -18,13 +15,16 @@ import Ide.Plugin.SemanticTokens.Mappings
import Ide.Plugin.SemanticTokens.Types (HieFunMaskKind,
HsSemanticTokenType (TModule),
RangeSemanticTokenTypeList,
SemanticTokenId,
SemanticTokensConfig)
import Language.LSP.Protocol.Types (Position (Position),
Range (Range),
SemanticTokenAbsolute (SemanticTokenAbsolute),
SemanticTokens,
SemanticTokens (SemanticTokens),
SemanticTokensDelta (SemanticTokensDelta),
defaultSemanticTokensLegend,
makeSemanticTokens)
makeSemanticTokens,
makeSemanticTokensDelta)
import Prelude hiding (length, span)

---------------------------------------------------------
Expand All @@ -47,8 +47,7 @@ idSemantic tyThingMap hieKind rm (Right n) =
---------------------------------------------------------

nameSemanticFromHie :: forall a. HieFunMaskKind a -> RefMap a -> Name -> Maybe HsSemanticTokenType
nameSemanticFromHie hieKind rm n = do
idSemanticFromRefMap rm (Right n)
nameSemanticFromHie hieKind rm n = idSemanticFromRefMap rm (Right n)
where
idSemanticFromRefMap :: RefMap a -> Identifier -> Maybe HsSemanticTokenType
idSemanticFromRefMap rm' name' = do
Expand All @@ -67,10 +66,9 @@ nameSemanticFromHie hieKind rm n = do

-------------------------------------------------

rangeSemanticsSemanticTokens :: SemanticTokensConfig -> PositionMapping -> RangeSemanticTokenTypeList -> Either Text SemanticTokens
rangeSemanticsSemanticTokens stc mapping =
makeSemanticTokens defaultSemanticTokensLegend
. mapMaybe (\(ran, tk) -> toAbsSemanticToken <$> toCurrentRange mapping ran <*> return tk)
rangeSemanticsSemanticTokens :: SemanticTokenId -> SemanticTokensConfig -> PositionMapping -> RangeSemanticTokenTypeList -> Either Text SemanticTokens
rangeSemanticsSemanticTokens sid stc mapping =
makeSemanticTokensWithId (Just sid) . mapMaybe (\(ran, tk) -> toAbsSemanticToken <$> toCurrentRange mapping ran <*> return tk)
where
toAbsSemanticToken :: Range -> HsSemanticTokenType -> SemanticTokenAbsolute
toAbsSemanticToken (Range (Position startLine startColumn) (Position _endLine endColumn)) tokenType =
Expand All @@ -81,3 +79,14 @@ rangeSemanticsSemanticTokens stc mapping =
(fromIntegral len)
(toLspTokenType stc tokenType)
[]

makeSemanticTokensWithId :: Maybe SemanticTokenId -> [SemanticTokenAbsolute] -> Either Text SemanticTokens
makeSemanticTokensWithId sid tokens = do
(SemanticTokens _ tokens) <- makeSemanticTokens defaultSemanticTokensLegend tokens
return $ SemanticTokens sid tokens

makeSemanticTokensDeltaWithId :: Maybe SemanticTokenId -> SemanticTokens -> SemanticTokens -> SemanticTokensDelta
makeSemanticTokensDeltaWithId sid previousTokens currentTokens =
let (SemanticTokensDelta _ stEdits) = makeSemanticTokensDelta previousTokens currentTokens
in SemanticTokensDelta sid stEdits

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Development.IDE.Graph.Classes (Hashable)
import GHC.Generics (Generic)
import Language.LSP.Protocol.Types
-- import template haskell
import Data.Text (Text)
import Language.Haskell.TH.Syntax (Lift)


Expand Down Expand Up @@ -150,3 +151,5 @@ instance Pretty SemanticLog where
LogConfig config -> "SemanticTokensConfig_: " <> pretty (show config)
LogMsg msg -> "SemanticLog Debug Message: " <> pretty msg


type SemanticTokenId = Text
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-orphans #-}


Expand Down
Loading
Loading