Skip to content

Semantic tokens: add module name support and improve performance and accuracy by traversing the hieAst along with source code #3958

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

Merged
merged 84 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
e60c7ae
add module name support for semantic tokens
soulomoon Jan 15, 2024
1379382
cleanup
soulomoon Jan 15, 2024
b2cbb8c
cleanup
soulomoon Jan 15, 2024
7896b67
fix docName
soulomoon Jan 15, 2024
422fc95
regenerate the config test result
soulomoon Jan 15, 2024
b2e0f31
stylish
soulomoon Jan 15, 2024
388ff4b
mend
soulomoon Jan 17, 2024
4b78555
rename
soulomoon Jan 17, 2024
445a825
fix module name
soulomoon Jan 17, 2024
04d08a5
add test for qualified names
soulomoon Jan 17, 2024
2cca23d
fix test
soulomoon Jan 17, 2024
c0bd67a
strip ()
soulomoon Jan 17, 2024
7a68ccd
stylish
soulomoon Jan 17, 2024
9758193
remove wrap '' () from tokens and add test
soulomoon Jan 17, 2024
8d27484
fix doc and rename
soulomoon Jan 17, 2024
6e69acb
improve test TQualifiedName
soulomoon Jan 17, 2024
10d92e6
rename
soulomoon Jan 17, 2024
8fe342e
add doc
soulomoon Jan 17, 2024
481a404
fix test
soulomoon Jan 17, 2024
16f7086
fix test
soulomoon Jan 17, 2024
72e8eee
fix test
soulomoon Jan 17, 2024
2a8855f
fix test
soulomoon Jan 17, 2024
511e670
stylish
soulomoon Jan 17, 2024
9072e7b
add tokenize
soulomoon Jan 22, 2024
6f588ca
clean up
soulomoon Jan 22, 2024
4236ca6
clean up
soulomoon Jan 22, 2024
65d493d
stylish
soulomoon Jan 22, 2024
017c848
Merge branch 'master' into add-module-name-support
soulomoon Jan 22, 2024
bb7f50d
cleanup
soulomoon Jan 22, 2024
d5dfaca
Merge branch 'master' into add-module-name-support
soulomoon Jan 22, 2024
d596876
cleaup
soulomoon Jan 22, 2024
d113778
add type signatures
soulomoon Jan 23, 2024
1ea88fb
cleanup
soulomoon Jan 23, 2024
5cc0c4d
cleanup
soulomoon Jan 23, 2024
b8a8ed3
cleanup
soulomoon Jan 23, 2024
84c8bcb
add type sig
soulomoon Jan 23, 2024
77b6210
fix
soulomoon Jan 23, 2024
0cd9540
fix
soulomoon Jan 23, 2024
a83a072
cleanup
soulomoon Jan 23, 2024
68a8d6b
Merge branch 'master' into add-module-name-support
soulomoon Jan 23, 2024
e296422
Merge branch 'master' into add-module-name-support
soulomoon Jan 23, 2024
b5e93e9
cleanup
soulomoon Jan 23, 2024
23d0d76
remove lengthFS
soulomoon Jan 23, 2024
a6e941a
cleanup
soulomoon Jan 23, 2024
c6f32d8
Merge branch 'master' into add-module-name-support
soulomoon Jan 24, 2024
68c187a
Merge branch 'master' into add-module-name-support
soulomoon Jan 24, 2024
19823dd
Merge branch 'master' into add-module-name-support
soulomoon Jan 24, 2024
622ac85
make ast traversing explicit
soulomoon Jan 24, 2024
b1f3fa0
cleanup
soulomoon Jan 24, 2024
811d0eb
optimize, splitRangeByText should not revert the work of focusTokenAt
soulomoon Jan 24, 2024
df48d37
clean up
soulomoon Jan 24, 2024
6fdff82
fix doc
soulomoon Jan 24, 2024
f76829e
rename Name to Id to fit the change
soulomoon Jan 24, 2024
c65d151
fix doc
soulomoon Jan 24, 2024
a0a1fb6
clean up
soulomoon Jan 24, 2024
43b70b9
clean up
soulomoon Jan 24, 2024
d77788e
clean up
soulomoon Jan 24, 2024
863ef26
only handle the leaf node with single column token
soulomoon Jan 24, 2024
e0a3ba7
cleanup
soulomoon Jan 24, 2024
f6ad967
fix
soulomoon Jan 24, 2024
7bd7514
clean up
soulomoon Jan 26, 2024
e87a9ba
fix sub
soulomoon Jan 26, 2024
ade5574
fix test for ghc92
soulomoon Jan 26, 2024
d89ced6
Merge branch 'master' into add-module-name-support
soulomoon Jan 26, 2024
06f55bc
Merge branch 'master' into add-module-name-support
soulomoon Jan 26, 2024
d9960e1
use strict map and make range and split explicit
soulomoon Jan 28, 2024
63fffa9
use strict map
soulomoon Jan 28, 2024
11e36ea
use strict map
soulomoon Jan 28, 2024
b473abc
cleanup
soulomoon Jan 28, 2024
c6d0023
add doc
soulomoon Jan 28, 2024
01c8099
handle more DerivedOccName
soulomoon Jan 28, 2024
14d6be8
use strict map
soulomoon Jan 28, 2024
dce593a
use strict map
soulomoon Jan 28, 2024
281850d
make field strict
soulomoon Jan 28, 2024
bef5a2a
cleanup
soulomoon Jan 28, 2024
47338cc
make rope strict in PTokenState
soulomoon Jan 28, 2024
72467a8
make map strict in PTokenState
soulomoon Jan 28, 2024
eea7f9f
use fromSet for importedIdSemanticMap
soulomoon Jan 28, 2024
eb5f9f0
add guard
soulomoon Jan 29, 2024
c605b26
cleanup
soulomoon Jan 29, 2024
fa8ca2c
fix
soulomoon Jan 29, 2024
73c9bbe
rename
soulomoon Jan 29, 2024
e2dd71c
Merge remote-tracking branch 'upstream/master' into add-module-name-s…
soulomoon Jan 29, 2024
9b717db
fix
soulomoon Jan 29, 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
52 changes: 27 additions & 25 deletions haskell-language-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ flag cabal

common cabal
if flag(cabal)
build-depends: hls-cabal-plugin
build-depends: hls-cabal-plugin
cpp-options: -Dhls_cabal

library hls-cabal-plugin
Expand Down Expand Up @@ -223,7 +223,7 @@ flag class

common class
if flag(class)
build-depends: hls-class-plugin
build-depends: hls-class-plugin
cpp-options: -Dhls_class

library hls-class-plugin
Expand Down Expand Up @@ -287,7 +287,7 @@ flag callHierarchy

common callHierarchy
if flag(callHierarchy)
build-depends: hls-call-hierarchy-plugin
build-depends: hls-call-hierarchy-plugin
cpp-options: -Dhls_callHierarchy

library hls-call-hierarchy-plugin
Expand Down Expand Up @@ -348,7 +348,7 @@ flag eval

common eval
if flag(eval)
build-depends: hls-eval-plugin
build-depends: hls-eval-plugin
cpp-options: -Dhls_eval

library hls-eval-plugin
Expand Down Expand Up @@ -429,7 +429,7 @@ test-suite hls-eval-plugin-tests

common importLens
if flag(importLens)
build-depends: hls-explicit-imports-plugin
build-depends: hls-explicit-imports-plugin
cpp-options: -Dhls_importLens

flag importLens
Expand Down Expand Up @@ -494,7 +494,7 @@ flag rename

common rename
if flag(rename)
build-depends: hls-rename-plugin
build-depends: hls-rename-plugin
cpp-options: -Dhls_rename

library hls-rename-plugin
Expand Down Expand Up @@ -550,7 +550,7 @@ flag retrie

common retrie
if flag(retrie)
build-depends: hls-retrie-plugin
build-depends: hls-retrie-plugin
cpp-options: -Dhls_retrie

library hls-retrie-plugin
Expand Down Expand Up @@ -615,7 +615,7 @@ flag hlint

common hlint
if flag(hlint) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))
build-depends: hls-hlint-plugin
build-depends: hls-hlint-plugin
cpp-options: -Dhls_hlint

library hls-hlint-plugin
Expand Down Expand Up @@ -695,7 +695,7 @@ flag stan

common stan
if flag(stan) && (impl(ghc > 8.8.1) && impl(ghc <= 9.2.3) || impl(ghc >= 9.4.0) && impl(ghc < 9.10.0))
build-depends: hls-stan-plugin
build-depends: hls-stan-plugin
cpp-options: -Dhls_stan

library hls-stan-plugin
Expand Down Expand Up @@ -769,7 +769,7 @@ flag moduleName

common moduleName
if flag(moduleName)
build-depends: hls-module-name-plugin
build-depends: hls-module-name-plugin
cpp-options: -Dhls_moduleName

library hls-module-name-plugin
Expand Down Expand Up @@ -814,7 +814,7 @@ flag pragmas

common pragmas
if flag(pragmas)
build-depends: hls-pragmas-plugin
build-depends: hls-pragmas-plugin
cpp-options: -Dhls_pragmas

library hls-pragmas-plugin
Expand Down Expand Up @@ -862,7 +862,7 @@ flag splice

common splice
if flag(splice)
build-depends: hls-splice-plugin
build-depends: hls-splice-plugin
cpp-options: -Dhls_splice

library hls-splice-plugin
Expand Down Expand Up @@ -1040,7 +1040,7 @@ flag codeRange

common codeRange
if flag(codeRange)
build-depends: hls-code-range-plugin
build-depends: hls-code-range-plugin
cpp-options: -Dhls_codeRange

library hls-code-range-plugin
Expand Down Expand Up @@ -1100,7 +1100,7 @@ flag changeTypeSignature

common changeTypeSignature
if flag(changeTypeSignature)
build-depends: hls-change-type-signature-plugin
build-depends: hls-change-type-signature-plugin
cpp-options: -Dhls_changeTypeSignature

library hls-change-type-signature-plugin
Expand Down Expand Up @@ -1160,7 +1160,7 @@ flag gadt

common gadt
if flag(gadt)
build-depends: hls-gadt-plugin
build-depends: hls-gadt-plugin
cpp-options: -Dhls_gadt

library hls-gadt-plugin
Expand Down Expand Up @@ -1213,7 +1213,7 @@ flag explicitFixity

common explicitFixity
if flag(explicitFixity)
build-depends: hls-explicit-fixity-plugin
build-depends: hls-explicit-fixity-plugin
cpp-options: -DexplicitFixity

library hls-explicit-fixity-plugin
Expand Down Expand Up @@ -1260,7 +1260,7 @@ flag explicitFields

common explicitFields
if flag(explicitFields)
build-depends: hls-explicit-record-fields-plugin
build-depends: hls-explicit-record-fields-plugin
cpp-options: -DexplicitFields

library hls-explicit-record-fields-plugin
Expand All @@ -1284,7 +1284,7 @@ library hls-explicit-record-fields-plugin
if flag(pedantic)
ghc-options: -Werror
-Wwarn=incomplete-record-updates

test-suite hls-explicit-record-fields-plugin-tests
import: warnings
default-language: Haskell2010
Expand All @@ -1309,7 +1309,7 @@ flag overloadedRecordDot

common overloadedRecordDot
if flag(overloadedRecordDot)
build-depends: hls-overloaded-record-dot-plugin
build-depends: hls-overloaded-record-dot-plugin
cpp-options: -Dhls_overloaded_record_dot

library hls-overloaded-record-dot-plugin
Expand Down Expand Up @@ -1356,7 +1356,7 @@ flag floskell

common floskell
if flag(floskell) && (impl(ghc < 9.7) || flag(ignore-plugins-ghc-bounds))
build-depends: hls-floskell-plugin
build-depends: hls-floskell-plugin
cpp-options: -Dhls_floskell

library hls-floskell-plugin
Expand Down Expand Up @@ -1398,7 +1398,7 @@ flag fourmolu

common fourmolu
if flag(fourmolu)
build-depends: hls-fourmolu-plugin
build-depends: hls-fourmolu-plugin
cpp-options: -Dhls_fourmolu

library hls-fourmolu-plugin
Expand Down Expand Up @@ -1451,7 +1451,7 @@ flag ormolu

common ormolu
if flag(ormolu)
build-depends: hls-ormolu-plugin
build-depends: hls-ormolu-plugin
cpp-options: -Dhls_ormolu

library hls-ormolu-plugin
Expand Down Expand Up @@ -1504,7 +1504,7 @@ flag stylishHaskell

common stylishHaskell
if flag(stylishHaskell) && (impl(ghc < 9.8.0) || flag(ignore-plugins-ghc-bounds))
build-depends: hls-stylish-haskell-plugin
build-depends: hls-stylish-haskell-plugin
cpp-options: -Dhls_stylishHaskell

library hls-stylish-haskell-plugin
Expand Down Expand Up @@ -1549,7 +1549,7 @@ flag refactor

common refactor
if flag(refactor)
build-depends: hls-refactor-plugin
build-depends: hls-refactor-plugin
cpp-options: -Dhls_refactor

library hls-refactor-plugin
Expand Down Expand Up @@ -1665,7 +1665,7 @@ flag semanticTokens

common semanticTokens
if flag(semanticTokens)
build-depends: hls-semantic-tokens-plugin
build-depends: hls-semantic-tokens-plugin
cpp-options: -Dhls_semanticTokens

library hls-semantic-tokens-plugin
Expand All @@ -1679,6 +1679,7 @@ library hls-semantic-tokens-plugin
Ide.Plugin.SemanticTokens.Query
Ide.Plugin.SemanticTokens.SemanticConfig
Ide.Plugin.SemanticTokens.Utils
Ide.Plugin.SemanticTokens.Tokenize
Ide.Plugin.SemanticTokens.Internal

hs-source-dirs: plugins/hls-semantic-tokens-plugin/src
Expand All @@ -1688,6 +1689,7 @@ library hls-semantic-tokens-plugin
, containers
, extra
, hiedb
, text-rope
, mtl >= 2.2
, ghcide == 2.6.0.0
, hls-plugin-api == 2.6.0.0
Expand Down
1 change: 1 addition & 0 deletions hls-plugin-api/src/Ide/Plugin/Properties.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
module Ide.Plugin.Properties
( PropertyType (..),
ToHsType,
NotElem,
MetaData (..),
PropertyKey (..),
SPropertyKey (..),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
Expand All @@ -21,8 +23,9 @@ import Control.Monad.Except (ExceptT, liftEither,
withExceptT)
import Control.Monad.Trans (lift)
import Control.Monad.Trans.Except (runExceptT)
import Data.Aeson (ToJSON (toJSON))
import qualified Data.Map as Map
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import Development.IDE (Action,
GetDocMap (GetDocMap),
GetHieAst (GetHieAst),
Expand All @@ -34,7 +37,6 @@ import Development.IDE (Action,
cmapWithPrio, define,
fromNormalizedFilePath,
hieKind, logPriority,
usePropertyAction,
use_)
import Development.IDE.Core.PluginUtils (runActionE,
useWithStaleE)
Expand All @@ -54,6 +56,7 @@ import Ide.Plugin.Error (PluginError (PluginIn
import Ide.Plugin.SemanticTokens.Mappings
import Ide.Plugin.SemanticTokens.Query
import Ide.Plugin.SemanticTokens.SemanticConfig (mkSemanticConfigFunctions)
import Ide.Plugin.SemanticTokens.Tokenize (hieAstSpanIdentifiers)
import Ide.Plugin.SemanticTokens.Types
import Ide.Types
import qualified Language.LSP.Protocol.Lens as L
Expand Down Expand Up @@ -91,37 +94,36 @@ semanticTokensFull recorder state pid param = do
-- Local names token type from 'hieAst'
-- Name locations from 'hieAst'
-- Visible names from 'tmrRenamed'

--
-- It then combines this information to compute the semantic tokens for the file.
getSemanticTokensRule :: Recorder (WithPriority SemanticLog) -> Rules ()
getSemanticTokensRule recorder =
define (cmapWithPrio LogShake recorder) $ \GetSemanticTokens nfp -> handleError recorder $ do
(HAR {..}) <- lift $ use_ GetHieAst nfp
(DKMap {getTyThingMap}, _) <- lift $ useWithStale_ GetDocMap nfp
ast <- handleMaybe (LogNoAST $ show nfp) $ getAsts hieAst Map.!? (HiePath . mkFastString . fromNormalizedFilePath) nfp
ast <- handleMaybe (LogNoAST $ show nfp) $ getAsts hieAst M.!? (HiePath . mkFastString . fromNormalizedFilePath) nfp
virtualFile <- handleMaybeM LogNoVF $ getVirtualFile nfp
-- get current location from the old ones
let spanNamesMap = hieAstSpanNames virtualFile ast
let names = nameSetElemsStable $ unionNameSets $ Map.elems spanNamesMap
let localSemanticMap = mkLocalNameSemanticFromAst names (hieKindFunMasksKind hieKind) refMap
let spanIdMap = M.filter (not . null) $ hieAstSpanIdentifiers virtualFile ast
let names = S.unions $ M.elems spanIdMap
let localSemanticMap = mkLocalIdSemanticFromAst names (hieKindFunMasksKind hieKind) refMap
-- get imported name semantic map
let importedNameSemanticMap = foldr (getTypeExclude localSemanticMap getTyThingMap) emptyNameEnv names
let sMap = plusNameEnv_C (<>) importedNameSemanticMap localSemanticMap
let rangeTokenType = extractSemanticTokensFromNames sMap spanNamesMap
let importedIdSemanticMap = M.mapMaybe id
$ M.fromSet (getTypeThing getTyThingMap) (names `S.difference` M.keysSet localSemanticMap)
let sMap = M.unionWith (<>) importedIdSemanticMap localSemanticMap
let rangeTokenType = extractSemanticTokensFromNames sMap spanIdMap
return $ RangeHsSemanticTokenTypes rangeTokenType
where
-- ignore one already in discovered in local
getTypeExclude ::
NameEnv a ->
getTypeThing ::
NameEnv TyThing ->
Name ->
NameEnv HsSemanticTokenType ->
NameEnv HsSemanticTokenType
getTypeExclude localEnv tyThingMap n nameMap
| n `elemNameEnv` localEnv = nameMap
| otherwise =
let tyThing = lookupNameEnv tyThingMap n
in maybe nameMap (extendNameEnv nameMap n) (tyThing >>= tyThingSemantic)
Identifier ->
Maybe HsSemanticTokenType
getTypeThing tyThingMap n
| (Right name) <- n =
let tyThing = lookupNameEnv tyThingMap name
in (tyThing >>= tyThingSemantic)
| otherwise = Nothing

-- | Persistent rule to ensure that semantic tokens doesn't block on startup
persistentGetSemanticTokensRule :: Rules ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ module Ide.Plugin.SemanticTokens.Mappings where

import qualified Data.Array as A
import Data.List.Extra (chunksOf, (!?))
import qualified Data.Map as Map
import qualified Data.Map.Strict as Map
import Data.Maybe (mapMaybe)
import qualified Data.Set as Set
import Data.Text (Text, unpack)
Expand Down Expand Up @@ -45,6 +45,7 @@ toLspTokenType conf tk = case tk of
TTypeFamily -> stTypeFamily conf
TRecordField -> stRecordField conf
TPatternSynonym -> stPatternSynonym conf
TModule -> stModule conf

lspTokenReverseMap :: SemanticTokensConfig -> Map.Map SemanticTokenTypes HsSemanticTokenType
lspTokenReverseMap config
Expand Down Expand Up @@ -114,15 +115,15 @@ recoverFunMaskArray flattened = unflattened
-- The recursion in 'unflattened' is crucial - it's what gives us sharing
-- function indicator check.
unflattened :: A.Array TypeIndex Bool
unflattened = fmap (\flatTy -> go (fmap (unflattened A.!) flatTy)) flattened
unflattened = fmap (go . fmap (unflattened A.!)) flattened

-- Unfold an 'HieType' whose subterms have already been unfolded
-- Unfold an 'HieType' whose sub-terms have already been unfolded
go :: HieType Bool -> Bool
go (HTyVarTy _name) = False
go (HAppTy _f _x) = False
go (HLitTy _lit) = False
go (HForAllTy ((_n, _k), _af) b) = b
go (HFunTy _ _ _) = True
go (HFunTy {}) = True
go (HQualTy _constraint b) = b
go (HCastTy b) = b
go HCoercionTy = False
Expand Down
Loading