@@ -7,7 +7,8 @@ import Control.Lens (Identity (runIdentity))
7
7
import Control.Monad (foldM , guard )
8
8
import Control.Monad.State.Strict (MonadState (get ),
9
9
MonadTrans (lift ),
10
- evalStateT , modify , put )
10
+ evalStateT , gets , modify' ,
11
+ put )
11
12
import Control.Monad.Trans.State.Strict (StateT , runStateT )
12
13
import Data.Char (isAlphaNum )
13
14
import Data.DList (DList )
@@ -31,13 +32,27 @@ import Prelude hiding (length, span)
31
32
32
33
type Tokenizer m a = StateT PTokenState m a
33
34
type HsSemanticLookup = Identifier -> Maybe HsSemanticTokenType
35
+ type CachedHsSemanticLookup m = Identifier -> Tokenizer m (Maybe HsSemanticTokenType )
36
+
37
+ cacheLookup :: (Monad m ) => HsSemanticLookup -> CachedHsSemanticLookup m
38
+ cacheLookup _ (Left _) = return $ Just TModule
39
+ cacheLookup lk idt@ (Right n) = do
40
+ ne <- gets semanticLookupCache
41
+ case lookupNameEnv ne n of
42
+ Nothing -> do
43
+ let hsSemanticTy = lk idt
44
+ modify' (\ x -> x{ semanticLookupCache= extendNameEnv ne n hsSemanticTy })
45
+ return hsSemanticTy
46
+ Just x -> return x
47
+
34
48
35
49
36
50
data PTokenState = PTokenState
37
51
{
38
- rope :: ! Rope -- the remains of rope we are working on
39
- , cursor :: ! Char. Position -- the cursor position of the current rope to the start of the original file in code point position
40
- , columnsInUtf16 :: ! UInt -- the column of the start of the current rope in utf16
52
+ rope :: ! Rope -- the remains of rope we are working on
53
+ , cursor :: ! Char. Position -- the cursor position of the current rope to the start of the original file in code point position
54
+ , columnsInUtf16 :: ! UInt -- the column of the start of the current rope in utf16
55
+ , semanticLookupCache :: ! (NameEnv (Maybe HsSemanticTokenType )) -- the cache for semantic lookup result of the current file
41
56
}
42
57
43
58
data SplitResult
@@ -56,7 +71,8 @@ mkPTokenState vf =
56
71
{
57
72
rope = vf. _file_text,
58
73
cursor = Char. Position 0 0 ,
59
- columnsInUtf16 = 0
74
+ columnsInUtf16 = 0 ,
75
+ semanticLookupCache = emptyNameEnv
60
76
}
61
77
62
78
-- lift a Tokenizer Maybe a to Tokenizer m a,
@@ -77,10 +93,10 @@ computeRangeHsSemanticTokenTypeList lookupHsTokenType vf ast =
77
93
-- visit every leaf node in the ast in depth first order
78
94
foldAst :: (Monad m ) => HsSemanticLookup -> HieAST t -> Tokenizer m (DList (Range , HsSemanticTokenType ))
79
95
foldAst lookupHsTokenType ast = if null (nodeChildren ast)
80
- then liftMaybeM ( visitLeafIds lookupHsTokenType ast)
96
+ then visitLeafIds lookupHsTokenType ast
81
97
else foldMapM (foldAst lookupHsTokenType) $ nodeChildren ast
82
98
83
- visitLeafIds :: HsSemanticLookup -> HieAST t -> Tokenizer Maybe (DList (Range , HsSemanticTokenType ))
99
+ visitLeafIds :: ( Monad m ) => HsSemanticLookup -> HieAST t -> Tokenizer m (DList (Range , HsSemanticTokenType ))
84
100
visitLeafIds lookupHsTokenType leaf = liftMaybeM $ do
85
101
let span = nodeSpan leaf
86
102
(ran, token) <- focusTokenAt leaf
@@ -93,16 +109,15 @@ visitLeafIds lookupHsTokenType leaf = liftMaybeM $ do
93
109
foldMapM (combineNodeIds lookupHsTokenType ran splitResult) $ Map. filterWithKey (\ k _ -> k == SourceInfo ) $ getSourcedNodeInfo $ sourcedNodeInfo leaf
94
110
where
95
111
combineNodeIds :: (Monad m ) => HsSemanticLookup -> Range -> SplitResult -> NodeInfo a -> Tokenizer m (DList (Range , HsSemanticTokenType ))
96
- combineNodeIds lookupHsTokenType ran ranSplit (NodeInfo _ _ bd) =
112
+ combineNodeIds lookupHsTokenType ran ranSplit (NodeInfo _ _ bd) = do
113
+ maybeTokenType <- foldMapM (cacheLookup $ lookupIdentifier lookupHsTokenType ranSplit) (M. keys bd)
97
114
case (maybeTokenType, ranSplit) of
98
115
(Nothing , _) -> return mempty
99
116
(Just TModule , _) -> return $ DL. singleton (ran, TModule )
100
117
(Just tokenType, NoSplit (_, tokenRan)) -> return $ DL. singleton (tokenRan, tokenType)
101
118
(Just tokenType, Split (_, ranPrefix, tokenRan)) -> return $ DL. fromList [(ranPrefix, TModule ),(tokenRan, tokenType)]
102
- where maybeTokenType = foldMap (getIdentifier lookupHsTokenType ranSplit) (M. keys bd)
103
-
104
- getIdentifier :: HsSemanticLookup -> SplitResult -> Identifier -> Maybe HsSemanticTokenType
105
- getIdentifier lookupHsTokenType ranSplit idt = do
119
+ lookupIdentifier :: HsSemanticLookup -> SplitResult -> HsSemanticLookup
120
+ lookupIdentifier lookupHsTokenType ranSplit idt = do
106
121
case idt of
107
122
Left _moduleName -> Just TModule
108
123
Right name -> do
@@ -138,7 +153,7 @@ focusTokenAt leaf = do
138
153
let nce = newColumn ncs token
139
154
-- compute the new range for utf16, tuning the columns is enough
140
155
let ran = codePointRangeToRangeWith ncs nce $ realSrcSpanToCodePointRange span
141
- modify $ \ s -> s {columnsInUtf16 = nce, rope = remains, cursor = tokenEndPos}
156
+ modify' $ \ s -> s {columnsInUtf16 = nce, rope = remains, cursor = tokenEndPos}
142
157
return (ran, token)
143
158
where
144
159
srcSpanCharPositions :: RealSrcSpan -> (Char. Position , Char. Position )
0 commit comments