Skip to content

Commit 700fd81

Browse files
committed
Retrieve nameSet from renamedSource to prevent names not visible(Such as by instance deriving) being handled
1 parent 65e2abd commit 700fd81

File tree

9 files changed

+330
-372
lines changed

9 files changed

+330
-372
lines changed

plugins/hls-semantic-tokens-plugin/hls-semantic-tokens-plugin.cabal

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ library
3131
hs-source-dirs: src
3232
build-depends:
3333
, aeson
34-
, base >=4.12 && <5
34+
, base
3535
, containers
3636
, extra
3737
, hiedb
@@ -75,4 +75,5 @@ test-suite tests
7575
, data-default
7676
, bytestring
7777
, ghcide == 2.5.0.0
78+
-- , ghcide == 2.5.0.0
7879
, hls-plugin-api == 2.5.0.0

plugins/hls-semantic-tokens-plugin/src/Ide/Plugin/SemanticTokens/Internal.hs

+63-142
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import qualified Data.Set as Set
6969
import Data.Text (Text)
7070
import Data.Traversable (for)
7171
import Data.Typeable (cast)
72+
import Debug.Trace (trace)
7273
import Development.IDE (IdeAction, IdeState,
7374
Priority (..), ideLogger,
7475
logPriority, use, uses)
@@ -83,80 +84,15 @@ import Development.IDE.Types.Exports (ExportsMap (..),
8384
import Development.IDE.Types.HscEnvEq (hscEnv)
8485
import GHC.Conc (readTVar)
8586

86-
-- logWith :: (MonadIO m) => IdeState -> String -> m ()
87-
-- logWith st = liftIO . logPriority (ideLogger st) Info . T.pack . show
88-
8987
logWith :: (MonadIO m) => IdeState -> String -> m ()
90-
logWith st = liftIO . print
91-
92-
bytestringString :: ByteString -> String
93-
bytestringString = map (toEnum . fromEnum) . unpack
94-
95-
-- data TyThing
96-
-- = AnId Id
97-
-- | AConLike ConLike
98-
-- | ATyCon TyCon -- TyCons and classes; see Note [ATyCon for classes]
99-
-- | ACoAxiom (CoAxiom Branched)
100-
-- a :: IdDetails
101-
-- a = undefined
102-
103-
-- | Identifier Details
104-
--
105-
-- The 'IdDetails' of an 'Id' give stable, and necessary,
106-
-- information about the Id.
107-
-- data IdDetails
108-
-- = VanillaId
88+
logWith st = liftIO . logPriority (ideLogger st) Info . T.pack
10989

110-
-- -- | The 'Id' for a record selector
111-
-- | RecSelId
112-
-- { sel_tycon :: RecSelParent
113-
-- , sel_naughty :: Bool -- True <=> a "naughty" selector which can't actually exist, for example @x@ in:
114-
-- -- data T = forall a. MkT { x :: a }
115-
-- } -- See Note [Naughty record selectors] in GHC.Tc.TyCl
11690

117-
-- | DataConWorkId DataCon -- ^ The 'Id' is for a data constructor /worker/
118-
-- | DataConWrapId DataCon -- ^ The 'Id' is for a data constructor /wrapper/
119-
120-
-- -- [the only reasons we need to know is so that
121-
-- -- a) to support isImplicitId
122-
-- -- b) when desugaring a RecordCon we can get
123-
-- -- from the Id back to the data con]
124-
-- | ClassOpId Class -- ^ The 'Id' is a superclass selector,
125-
-- -- or class operation of a class
126-
127-
-- | PrimOpId PrimOp Bool -- ^ The 'Id' is for a primitive operator
128-
-- -- True <=> is representation-polymorphic,
129-
-- -- and hence has no binding
130-
-- -- This lev-poly flag is used only in GHC.Types.Id.hasNoBinding
131-
132-
-- | FCallId ForeignCall -- ^ The 'Id' is for a foreign call.
133-
-- -- Type will be simple: no type families, newtypes, etc
134-
135-
-- | TickBoxOpId TickBoxOp -- ^ The 'Id' is for a HPC tick box (both traditional and binary)
136-
137-
-- | DFunId Bool -- ^ A dictionary function.
138-
-- -- Bool = True <=> the class has only one method, so may be
139-
-- -- implemented with a newtype, so it might be bad
140-
-- -- to be strict on this dictionary
91+
-- logWith :: (MonadIO m) => IdeState -> String -> m ()
92+
-- logWith st = liftIO . print
14193

142-
-- | CoVarId -- ^ A coercion variable
143-
-- -- This only covers /un-lifted/ coercions, of type
144-
-- -- (t1 ~# t2) or (t1 ~R# t2), not their lifted variants
145-
-- | JoinId JoinArity (Maybe [CbvMark])
146-
-- -- ^ An 'Id' for a join point taking n arguments
147-
-- -- Note [Join points] in "GHC.Core"
148-
-- -- Can also work as a WorkerLikeId if given `CbvMark`s.
149-
-- -- See Note [CBV Function Ids]
150-
-- -- The [CbvMark] is always empty (and ignored) until after Tidy.
151-
-- | WorkerLikeId [CbvMark]
152-
-- -- ^ An 'Id' for a worker like function, which might expect some arguments to be
153-
-- -- passed both evaluated and tagged.
154-
-- -- Worker like functions are create by W/W and SpecConstr and we can expect that they
155-
-- -- aren't used unapplied.
156-
-- -- See Note [CBV Function Ids]
157-
-- -- See Note [Tag Inference]
158-
-- -- The [CbvMark] is always empty (and ignored) until after Tidy for ids from the current
159-
-- -- module.
94+
bytestringString :: ByteString -> String
95+
bytestringString = map (toEnum . fromEnum) . unpack
16096

16197
tyThingSemantic :: TyThing -> SemanticTokenType
16298
tyThingSemantic ty = case ty of
@@ -171,11 +107,11 @@ tyThingSemantic ty = case ty of
171107
RealDataCon _ -> TDataCon
172108
PatSynCon _ -> TPatternSyn
173109
ATyCon tyCon
174-
| isDataTyCon tyCon -> TTypeCon
175-
| isPrimTyCon tyCon -> TTypeCon
176-
| isClassTyCon tyCon -> TClass
177110
| isTypeSynonymTyCon tyCon -> TTypeSyn
178111
| isTypeFamilyTyCon tyCon -> TTypeFamily
112+
| isClassTyCon tyCon -> TClass
113+
| isDataTyCon tyCon -> TTypeCon
114+
| isPrimTyCon tyCon -> TTypeCon
179115
| otherwise -> TNothing
180116
ACoAxiom _ -> TNothing
181117

@@ -185,48 +121,40 @@ tyThingSemantic ty = case ty of
185121

186122
computeSemanticTokens :: IdeState -> NormalizedFilePath -> Action (Maybe SemanticTokens)
187123
computeSemanticTokens state nfp =
188-
let dbg = logWith state in
189-
runMaybeT $ do
190-
-- HAR{hieAst, refMap} <- MaybeT $ use GetHieAst nfp
191-
[HAR{..}] <- usesMT GetHieAst [nfp]
192-
-- [TcModuleResult{..}]<- usesMT TypeCheck [nfp]
193-
[hscEnv -> hsc] <- usesMT (GhcSessionDeps_ True) [nfp]
194-
-- HAR{..} <- MaybeT $ useWithStaleFastMT GetHieAst nfp
195-
liftIO $ putStrLn $ "moduleName: " <> showSDocUnsafe (ppr hieModule)
196-
let xs = Map.toList $ getAsts hieAst
197-
liftIO $ putStrLn $ "hieAst size: " <> show (List.length xs)
198-
199-
case xs of
200-
((_,ast):_) -> do
201-
-- compute imported names from hieAst
202-
let importedNames = importedNameFromModule hieModule ast
203-
-- accumulate names from typechecked module
204-
-- km <- liftIO $ foldrM (getType hsc) (tcg_type_env tmrTypechecked) importedNames
205-
km <- liftIO $ foldrM (getType hsc) emptyNameEnv importedNames
206-
let importedModuleNameSemanticMap = Map.fromList $ flip mapMaybe (Set.toList importedNames) $ \name -> do
207-
ty <- lookupNameEnv km name
208-
return (name, tyThingSemantic ty)
209-
liftIO $ forM (Set.toList importedNames) $ \name -> do
210-
let ty = lookupNameEnv km name
211-
dbg $ "imported name: "
212-
<> showSDocUnsafe (ppr name)
213-
<> " :: " <> showSDocUnsafe (ppr ty)
214-
-- return (name, tyThingSemantic ty)
215-
ShakeExtras{..} <- MaybeT $ fmap Just getShakeExtras
216-
let originalModuleNameSemanticMap = toNameSemanticMap refMap
217-
let combineMap = Map.unionWith (<>) originalModuleNameSemanticMap importedModuleNameSemanticMap
218-
let names = identifierGetter ast
219-
124+
runMaybeT $ do
125+
-- let dbg = logWith state
126+
-- let getAst HAR{hieAst, refMap} = hieAst
127+
(HAR{hieAst, refMap, hieModule}, _) <- useWithStaleMT GetHieAst nfp
128+
(_, ast) <- MaybeT $ return $ listToMaybe $ Map.toList $ getAsts hieAst
129+
(TcModuleResult{..}, _) <- useWithStaleMT TypeCheck nfp
130+
(hscEnv -> hsc, _) <- useWithStaleMT GhcSessionDeps nfp
131+
-- because the names get from ast might contain derived name
132+
let nameSet = nameGetter tmrRenamed
133+
-- let nameSet = hieAstNameSet ast
134+
let names = hieAstSpanNames ast
135+
136+
-- ask hscEnv for none local types
137+
km <- liftIO $ foldrM (getType hsc) (tcg_type_env tmrTypechecked) nameSet
138+
-- name from type typecheck
139+
let importedModuleNameSemanticMap = Map.fromList $ flip mapMaybe (Set.toList nameSet) $ \name -> do
140+
ty <- lookupNameEnv km name
141+
return (name, tyThingSemantic ty)
142+
let localNameSemanticMap = toNameSemanticMap $ Map.filterWithKey (\k _ ->
143+
either (const False) (flip Set.member nameSet) k) refMap
144+
let combineMap = Map.unionWith (<>) localNameSemanticMap importedModuleNameSemanticMap
145+
-- print all names
146+
-- deriving method locate in the same position as the class name
147+
-- liftIO $ mapM_ (\ (name, tokenType) -> dbg ("debug semanticMap: " <> showClearName name <> ":" <> show tokenType )) $ Map.toList importedModuleNameSemanticMap
148+
-- liftIO $ mapM_ (\ (span, name) -> dbg ("debug names: " <> showClearName name <> ":" <> printCompactRealSrc span ) ) names
149+
let moduleAbsTks = extractSemanticTokensFromNames combineMap names
150+
case semanticTokenAbsoluteSemanticTokens moduleAbsTks of
151+
Right tokens -> do
220152
source :: ByteString <- lift $ getSourceFileSource nfp
221-
let moduleAbsTks = extractSemanticTokensFromNames combineMap names
222-
case semanticTokenAbsoluteSemanticTokens moduleAbsTks of
223-
Right tokens -> do
224-
liftIO $ mapM_ (\x -> mapM_ (dbg . show) x) $ recoverSemanticTokens (bytestringString source) tokens
225-
pure tokens
226-
Left err -> do
227-
liftIO $ putStrLn $ "computeSemanticTokens: " <> show err
228-
MaybeT . pure $ Nothing
229-
_ -> MaybeT . pure $ Nothing
153+
-- liftIO $ mapM_ (\x -> mapM_ (dbg . show) x) $ recoverSemanticTokens (bytestringString source) tokens
154+
pure tokens
155+
Left err -> do
156+
liftIO $ putStrLn $ "computeSemanticTokens: " <> show err
157+
MaybeT . pure $ Nothing
230158
where
231159
getType env n nameMap
232160
| Nothing <- lookupNameEnv nameMap n
@@ -239,9 +167,9 @@ computeSemanticTokens state nfp =
239167

240168
semanticTokensFull :: PluginMethodHandler IdeState 'Method_TextDocumentSemanticTokensFull
241169
semanticTokensFull state _ param = do
242-
let dbg = logWith state
170+
-- let dbg = logWith state
243171
nfp <- getNormalizedFilePathE (param ^. (L.textDocument . L.uri))
244-
dbg $ "semanticTokensFull: " <> show nfp
172+
-- dbg $ "semanticTokensFull: " <> show nfp
245173
-- source :: ByteString <- lift $ getSourceFileSource nfp
246174
items <- liftIO
247175
$ runAction "SemanticTokens.semanticTokensFull" state
@@ -258,32 +186,25 @@ semanticTokensFull state _ param = do
258186
---- recover tokens
259187
-----------------------
260188

189+
-- | recoverSemanticTokens
190+
-- used for debug and test
191+
-- this function is used to recover the original tokens(with token in haskell token type zoon)
192+
-- from the lsp semantic tokens(with token in lsp token type zoon)
261193
recoverSemanticTokens :: String -> SemanticTokens -> Either Text [SemanticTokenOriginal]
262194
recoverSemanticTokens sourceCode (SemanticTokens _ xs) = fmap (fmap $ tokenOrigin sourceCode) $ dataActualToken xs
263-
264-
265-
tokenOrigin :: [Char] -> ActualToken -> SemanticTokenOriginal
266-
tokenOrigin sourceCode (line, startChar, len, tokenType, _) =
267-
-- convert back to count from 1
268-
SemanticTokenOriginal tokenType (Loc (line+1) (startChar+1) len) name
269-
where tLine = lines sourceCode !? fromIntegral line
270-
name = maybe "no source" (take (fromIntegral len) . drop (fromIntegral startChar)) tLine
271-
272-
273-
dataActualToken :: [UInt] -> Either Text [ActualToken]
274-
dataActualToken xs = maybe decodeError (Right . fmap semanticTokenAbsoluteActualToken . absolutizeTokens)
275-
$ mapM fromTuple (chunksOf 5 $ map fromIntegral xs)
276195
where
277-
decodeError = Left "recoverSemanticTokenRelative: wrong token data"
278-
fromTuple [a, b, c, d, _] = Just $ SemanticTokenRelative a b c (fromInt $ fromIntegral d) []
279-
fromTuple _ = Nothing
280-
281-
-- span: /Users/ares/src/test/lib/SemanticTokens/Types.hs:(34,12)-(38,3)
282-
-- type RefMap a = M.Map Identifier [(Span, IdentifierDetails a)]
283-
computeImportedSemanticTokens :: IdeState -> [NormalizedFilePath] -> Set.Set Name -> MaybeT Action NameSemanticMap
284-
computeImportedSemanticTokens state nfps names =
285-
let dbg = logWith state in do
286-
dbg "heelo"
287-
let nameList = Set.toList names
288-
let moduleNamePairs = [(1, nameOccName name) | name <- nameList]
289-
return Map.empty
196+
tokenOrigin :: [Char] -> ActualToken -> SemanticTokenOriginal
197+
tokenOrigin sourceCode (line, startChar, len, tokenType, _) =
198+
-- convert back to count from 1
199+
SemanticTokenOriginal tokenType (Loc (line+1) (startChar+1) len) name
200+
where tLine = lines sourceCode !? fromIntegral line
201+
name = maybe "no source" (take (fromIntegral len) . drop (fromIntegral startChar)) tLine
202+
203+
204+
dataActualToken :: [UInt] -> Either Text [ActualToken]
205+
dataActualToken xs = maybe decodeError (Right . fmap semanticTokenAbsoluteActualToken . absolutizeTokens)
206+
$ mapM fromTuple (chunksOf 5 $ map fromIntegral xs)
207+
where
208+
decodeError = Left "recoverSemanticTokenRelative: wrong token data"
209+
fromTuple [a, b, c, d, _] = Just $ SemanticTokenRelative a b c (fromInt $ fromIntegral d) []
210+
fromTuple _ = Nothing

plugins/hls-semantic-tokens-plugin/src/Ide/Plugin/SemanticTokens/Types.hs

+17-27
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
{-# LANGUAGE StandaloneDeriving #-}
2+
{-# LANGUAGE StrictData #-}
3+
24
module Ide.Plugin.SemanticTokens.Types where
35

46

@@ -127,22 +129,11 @@ instance Show ContextInfo where
127129
EvidenceVarUse -> "EvidenceVarUse"
128130

129131

130-
printCompactSrcSpan :: SrcSpan -> String
131-
printCompactSrcSpan (RealSrcSpan x _buf) = printCompactRealSrc x
132-
printCompactSrcSpan x = "noSrc"
133132

134133
printCompactRealSrc :: RealSrcSpan -> String
135134
printCompactRealSrc x = show (srcSpanStartLine x) <> ":" <> show (srcSpanStartCol x) <> "-" <> show (srcSpanEndCol x)
136135

137136

138-
139-
type IdentifierItem = (Span, Name, NE.NonEmpty ContextInfo)
140-
newtype NIdentifier = NIdentifier IdentifierItem
141-
142-
identifierTokenType :: Identifier -> SemanticTokenType
143-
identifierTokenType (Right x) = toTokenType x
144-
identifierTokenType (Left x) = TNothing
145-
146137
toTokenType :: Name -> SemanticTokenType
147138
toTokenType locName = case occNameSpace $ occName locName of
148139
x | isDataConNameSpace x -> TDataCon
@@ -151,24 +142,8 @@ toTokenType locName = case occNameSpace $ occName locName of
151142
x | isVarNameSpace x -> TValBind
152143
_ -> TNothing
153144

154-
instance Show NIdentifier where
155-
show (NIdentifier (span, x, y)) =
156-
occNameString (nameOccName x)
157-
<> "&" <> (show $ break (==':') $ occNameString $ nameOccName x)
158-
<> "&" <> (show $ toTokenType x)
159-
<> " [" <> show y <> "]"
160-
<> " nameSrc: "<> printCompactSrcSpan (nameSrcSpan x) <> " " <> printCompactRealSrc span
161145

162146

163-
getOriginalTextFromId :: String -> NIdentifier -> String
164-
getOriginalTextFromId sourceCode (NIdentifier (span, _, _)) = fromMaybe "" $ do
165-
tLine <- lines sourceCode List.!? (line-1)
166-
return $ take len $ drop (startChar-1) tLine
167-
where
168-
line = srcSpanStartLine span
169-
startChar = srcSpanStartCol span
170-
len= srcSpanEndCol span - startChar
171-
172147

173148
-----------------------
174149
----- identifier token map
@@ -188,3 +163,18 @@ showIdentifierDetails x = show $ identInfo x
188163
showIdentifier :: Identifier -> String
189164
showIdentifier (Left x) = showSDocUnsafe (ppr x)
190165
showIdentifier (Right x) = nameStableString x
166+
167+
showLocatedNames :: [LIdP GhcRn] -> String
168+
showLocatedNames xs = unlines
169+
[ showSDocUnsafe (ppr locName) ++ " " ++ show (getLoc locName)
170+
| locName <- xs]
171+
172+
showClearName :: Name -> String
173+
showClearName name = occNameString (occName name) <> ":" <> showSDocUnsafe (ppr name) <> ":" <> showNameType name
174+
175+
showNameType :: Name -> String
176+
showNameType name
177+
| isInternalName name = "InternalName"
178+
| isExternalName name = "ExternalName"
179+
| isSystemName name = "SystemName"
180+
| isWiredInName name = "WiredInName"

0 commit comments

Comments
 (0)