From 9e869546c5689d344001e3108511ec82c022cbf2 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Fri, 7 Oct 2022 15:16:16 -0400 Subject: [PATCH 01/11] Filter names from hovertip documentation which match patterns of generated Core variables. --- ghcide/src/Development/IDE/Spans/AtPoint.hs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index cd55fbb979..671a37d4c5 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -227,10 +227,17 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) env pos = listToMaybe $ p wrapHaskell x = "\n```haskell\n"<>x<>"\n```\n" info = nodeInfoH kind ast names = M.assocs $ nodeIdentifiers info + isInternal :: (Identifier, IdentifierDetails a) -> Bool + isInternal (Right n, _) = + let name = printOutputable n + prefix = T.take 2 name + in elem prefix ["$d", "$c"] + isInternal (Left _, _) = False + filteredNames = filter (not . isInternal) names types = nodeType info prettyNames :: [T.Text] - prettyNames = map prettyName names + prettyNames = map prettyName filteredNames prettyName (Right n, dets) = T.unlines $ wrapHaskell (printOutputable n <> maybe "" (" :: " <>) ((prettyType <$> identType dets) <|> maybeKind)) : maybeToList (pretty (definedAt n) (prettyPackageName n)) From 4001aa346d079d7ee4e7019bc50e3f27eafd58b7 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Wed, 2 Nov 2022 15:09:48 -0600 Subject: [PATCH 02/11] Added comment for isInternal function. --- ghcide/src/Development/IDE/Spans/AtPoint.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index 671a37d4c5..0f4b447b13 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -227,6 +227,7 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) env pos = listToMaybe $ p wrapHaskell x = "\n```haskell\n"<>x<>"\n```\n" info = nodeInfoH kind ast names = M.assocs $ nodeIdentifiers info + -- Check if a name matches a pattern for a generated Core variable. isInternal :: (Identifier, IdentifierDetails a) -> Bool isInternal (Right n, _) = let name = printOutputable n From 27e9a1033ce47546e95e2475c88643d9f2bb1e3e Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Sat, 19 Nov 2022 14:17:13 -0700 Subject: [PATCH 03/11] Relocated list of OccName prefixes from the Completions plugin to the CoreFile module. Updated the check for GHC-generated OccName prefixes in AtPoint to use the shared list of OccName prefixes. --- ghcide/src/Development/IDE/GHC/CoreFile.hs | 46 ++++++++++++++++++- .../IDE/Plugin/Completions/Logic.hs | 46 +------------------ ghcide/src/Development/IDE/Spans/AtPoint.hs | 5 +- 3 files changed, 49 insertions(+), 48 deletions(-) diff --git a/ghcide/src/Development/IDE/GHC/CoreFile.hs b/ghcide/src/Development/IDE/GHC/CoreFile.hs index 737441f9ef..00a778afda 100644 --- a/ghcide/src/Development/IDE/GHC/CoreFile.hs +++ b/ghcide/src/Development/IDE/GHC/CoreFile.hs @@ -10,7 +10,8 @@ module Development.IDE.GHC.CoreFile , typecheckCoreFile , readBinCoreFile , writeBinCoreFile - , getImplicitBinds) where + , getImplicitBinds + , occNamePrefixes) where import Control.Monad import Control.Monad.IO.Class @@ -18,6 +19,7 @@ import Data.Foldable import Data.IORef import Data.List (isPrefixOf) import Data.Maybe +import qualified Data.Text as T import GHC.Fingerprint import Development.IDE.GHC.Compat @@ -228,3 +230,45 @@ tc_iface_bindings (TopIfaceNonRec v e) = do tc_iface_bindings (TopIfaceRec vs) = do vs' <- traverse (\(v, e) -> (,) <$> pure v <*> tcIfaceExpr e) vs pure $ Rec vs' + +-- | Prefixes that can occur in a GHC OccName +occNamePrefixes :: [T.Text] +occNamePrefixes = + [ + -- long ones + "$con2tag_" + , "$tag2con_" + , "$maxtag_" + + -- four chars + , "$sel:" + , "$tc'" + + -- three chars + , "$dm" + , "$co" + , "$tc" + , "$cp" + , "$fx" + + -- two chars + , "$W" + , "$w" + , "$m" + , "$b" + , "$c" + , "$d" + , "$i" + , "$s" + , "$f" + , "$r" + , "C:" + , "N:" + , "D:" + , "$p" + , "$L" + , "$f" + , "$t" + , "$c" + , "$m" + ] diff --git a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs index 92a4ea0320..362fb68993 100644 --- a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs +++ b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs @@ -41,6 +41,7 @@ import Development.IDE.Core.PositionMapping import Development.IDE.GHC.Compat hiding (ppr) import qualified Development.IDE.GHC.Compat as GHC import Development.IDE.GHC.Compat.Util +import Development.IDE.GHC.CoreFile (occNamePrefixes) import Development.IDE.GHC.Error import Development.IDE.GHC.Util import Development.IDE.Plugin.Completions.Types @@ -767,50 +768,7 @@ openingBacktick line prefixModule prefixText Position { _character=(fromIntegral -- TODO: Turn this into an alex lexer that discards prefixes as if they were whitespace. stripPrefix :: T.Text -> T.Text stripPrefix name = T.takeWhile (/=':') $ fromMaybe name $ - getFirst $ foldMap (First . (`T.stripPrefix` name)) prefixes - --- | Prefixes that can occur in a GHC OccName -prefixes :: [T.Text] -prefixes = - [ - -- long ones - "$con2tag_" - , "$tag2con_" - , "$maxtag_" - - -- four chars - , "$sel:" - , "$tc'" - - -- three chars - , "$dm" - , "$co" - , "$tc" - , "$cp" - , "$fx" - - -- two chars - , "$W" - , "$w" - , "$m" - , "$b" - , "$c" - , "$d" - , "$i" - , "$s" - , "$f" - , "$r" - , "C:" - , "N:" - , "D:" - , "$p" - , "$L" - , "$f" - , "$t" - , "$c" - , "$m" - ] - + getFirst $ foldMap (First . (`T.stripPrefix` name)) occNamePrefixes mkRecordSnippetCompItem :: Uri -> Maybe T.Text -> T.Text -> [T.Text] -> Provenance -> Maybe (LImportDecl GhcPs) -> CompItem mkRecordSnippetCompItem uri parent ctxStr compl importedFrom imp = r diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index 0f4b447b13..a97fba01a6 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -34,6 +34,7 @@ import Development.IDE.Core.PositionMapping import Development.IDE.Core.RuleTypes import Development.IDE.GHC.Compat import qualified Development.IDE.GHC.Compat.Util as Util +import Development.IDE.GHC.CoreFile (occNamePrefixes) import Development.IDE.GHC.Util (printOutputable) import Development.IDE.Spans.Common import Development.IDE.Types.Options @@ -231,12 +232,10 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) env pos = listToMaybe $ p isInternal :: (Identifier, IdentifierDetails a) -> Bool isInternal (Right n, _) = let name = printOutputable n - prefix = T.take 2 name - in elem prefix ["$d", "$c"] + in any (`T.isPrefixOf` name) occNamePrefixes isInternal (Left _, _) = False filteredNames = filter (not . isInternal) names types = nodeType info - prettyNames :: [T.Text] prettyNames = map prettyName filteredNames prettyName (Right n, dets) = T.unlines $ From 8ca04abfb95694b832282675c8038ded9b2a4bf0 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Sun, 20 Nov 2022 11:29:15 -0700 Subject: [PATCH 04/11] Added test data and test for ensuring Core-generated variables are not included in hover info. --- ghcide/test/data/hover/GotoHover.hs | 4 ++++ ghcide/test/exe/Main.hs | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/ghcide/test/data/hover/GotoHover.hs b/ghcide/test/data/hover/GotoHover.hs index e1802580e2..6ff3eeffed 100644 --- a/ghcide/test/data/hover/GotoHover.hs +++ b/ghcide/test/data/hover/GotoHover.hs @@ -64,3 +64,7 @@ hole = _ hole2 :: a -> Maybe a hole2 = _ + +-- A comment above a type defnition with a deriving clause +data Example = Example + deriving (Eq) diff --git a/ghcide/test/exe/Main.hs b/ghcide/test/exe/Main.hs index 32b52f31e8..3034c8d597 100644 --- a/ghcide/test/exe/Main.hs +++ b/ghcide/test/exe/Main.hs @@ -1026,6 +1026,7 @@ findDefinitionAndHoverTests = let ExpectRange expectedRange -> checkHoverRange expectedRange rangeInHover msg ExpectHoverRange expectedRange -> checkHoverRange expectedRange rangeInHover msg ExpectHoverText snippets -> liftIO $ traverse_ (`assertFoundIn` msg) snippets + ExpectHoverExcludeText snippets -> liftIO $ traverse_ (`assertNotFoundIn` msg) snippets ExpectHoverTextRegex re -> liftIO $ assertBool ("Regex not found in " <> T.unpack msg) (msg =~ re :: Bool) ExpectNoHover -> liftIO $ assertFailure $ "Expected no hover but got " <> show hover _ -> pure () -- all other expectations not relevant to hover @@ -1054,6 +1055,11 @@ findDefinitionAndHoverTests = let (T.unpack $ "failed to find: `" <> part <> "` in hover message:\n" <> whole) (part `T.isInfixOf` whole) + assertNotFoundIn :: T.Text -> T.Text -> Assertion + assertNotFoundIn part whole = assertBool + (T.unpack $ "found unexpected: `" <> part <> "` in hover message:\n" <> whole) + (not . T.isInfixOf part $ whole) + sourceFilePath = T.unpack sourceFileName sourceFileName = "GotoHover.hs" @@ -1130,6 +1136,7 @@ findDefinitionAndHoverTests = let imported = Position 56 13 ; importedSig = getDocUri "Foo.hs" >>= \foo -> return [ExpectHoverText ["foo", "Foo", "Haddock"], mkL foo 5 0 5 3] reexported = Position 55 14 ; reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar", "Haddock"], mkL bar 3 (if ghcVersion >= GHC94 then 5 else 0) 3 (if ghcVersion >= GHC94 then 8 else 14)] thLocL57 = Position 59 10 ; thLoc = [ExpectHoverText ["Identity"]] + cmtL68 = Position 67 0 ; lackOfdEq = [ExpectHoverExcludeText ["$dEq"]] in mkFindTests -- def hover look expect @@ -1173,6 +1180,7 @@ findDefinitionAndHoverTests = let , test no broken chrL36 litC "literal Char in hover info #1016" , test no broken txtL8 litT "literal Text in hover info #1016" , test no broken lstL43 litL "literal List in hover info #1016" + , test yes yes cmtL68 lackOfdEq "no Core symbols #3280" , if ghcVersion >= GHC90 then test no yes docL41 constr "type constraint in hover info #1012" else @@ -2390,6 +2398,7 @@ data Expect -- | ExpectDefRange Range -- Only gotoDef should report this range | ExpectHoverRange Range -- Only hover should report this range | ExpectHoverText [T.Text] -- the hover message must contain these snippets + | ExpectHoverExcludeText [T.Text] -- the hover message must _not_ contain these snippets | ExpectHoverTextRegex T.Text -- the hover message must match this pattern | ExpectExternFail -- definition lookup in other file expected to fail | ExpectNoDefinitions From 92d5a999dbe789b7175fc14daeec7a786d130654 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Fri, 3 Feb 2023 15:44:08 -0700 Subject: [PATCH 05/11] Switched to using isEvidenceContext to filter out evidence bindings. --- ghcide/src/Development/IDE/Spans/AtPoint.hs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index a97fba01a6..53df88d484 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -34,7 +34,6 @@ import Development.IDE.Core.PositionMapping import Development.IDE.Core.RuleTypes import Development.IDE.GHC.Compat import qualified Development.IDE.GHC.Compat.Util as Util -import Development.IDE.GHC.CoreFile (occNamePrefixes) import Development.IDE.GHC.Util (printOutputable) import Development.IDE.Spans.Common import Development.IDE.Types.Options @@ -230,9 +229,8 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) env pos = listToMaybe $ p names = M.assocs $ nodeIdentifiers info -- Check if a name matches a pattern for a generated Core variable. isInternal :: (Identifier, IdentifierDetails a) -> Bool - isInternal (Right n, _) = - let name = printOutputable n - in any (`T.isPrefixOf` name) occNamePrefixes + isInternal (Right _, dets) = + any isEvidenceContext $ identInfo dets isInternal (Left _, _) = False filteredNames = filter (not . isInternal) names types = nodeType info From 0cea12e80d0413090b388095bc99709eb0693ff4 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Sat, 19 Nov 2022 14:17:13 -0700 Subject: [PATCH 06/11] Relocated list of OccName prefixes from the Completions plugin to the CoreFile module. Updated the check for GHC-generated OccName prefixes in AtPoint to use the shared list of OccName prefixes. --- .../src/Development/IDE/Plugin/Completions/Logic.hs | 13 +++++++++++-- ghcide/src/Development/IDE/Spans/AtPoint.hs | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs index 362fb68993..3d99611e43 100644 --- a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs +++ b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs @@ -770,8 +770,17 @@ stripPrefix :: T.Text -> T.Text stripPrefix name = T.takeWhile (/=':') $ fromMaybe name $ getFirst $ foldMap (First . (`T.stripPrefix` name)) occNamePrefixes -mkRecordSnippetCompItem :: Uri -> Maybe T.Text -> T.Text -> [T.Text] -> Provenance -> Maybe (LImportDecl GhcPs) -> CompItem -mkRecordSnippetCompItem uri parent ctxStr compl importedFrom imp = r +safeTyThingForRecord :: TyThing -> Maybe (T.Text, [T.Text]) +safeTyThingForRecord (AnId _) = Nothing +safeTyThingForRecord (AConLike dc) = + let ctxStr = printOutputable . occName . conLikeName $ dc + field_names = T.pack . unpackFS . flLabel <$> conLikeFieldLabels dc + in + Just (ctxStr, field_names) +safeTyThingForRecord _ = Nothing + +mkRecordSnippetCompItem :: Uri -> Maybe T.Text -> T.Text -> [T.Text] -> Provenance -> SpanDoc -> Maybe (LImportDecl GhcPs) -> CompItem +mkRecordSnippetCompItem uri parent ctxStr compl importedFrom docs imp = r where r = CI { compKind = CiSnippet diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index 53df88d484..e55e8ad9e8 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -34,6 +34,7 @@ import Development.IDE.Core.PositionMapping import Development.IDE.Core.RuleTypes import Development.IDE.GHC.Compat import qualified Development.IDE.GHC.Compat.Util as Util +import Development.IDE.GHC.CoreFile (occNamePrefixes) import Development.IDE.GHC.Util (printOutputable) import Development.IDE.Spans.Common import Development.IDE.Types.Options From 7eebe950d9fb3b86b3b01362ec84cf524f441c52 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Fri, 3 Feb 2023 15:49:31 -0700 Subject: [PATCH 07/11] Removed unused import. --- ghcide/src/Development/IDE/Spans/AtPoint.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index e55e8ad9e8..53df88d484 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -34,7 +34,6 @@ import Development.IDE.Core.PositionMapping import Development.IDE.Core.RuleTypes import Development.IDE.GHC.Compat import qualified Development.IDE.GHC.Compat.Util as Util -import Development.IDE.GHC.CoreFile (occNamePrefixes) import Development.IDE.GHC.Util (printOutputable) import Development.IDE.Spans.Common import Development.IDE.Types.Options From 9b1cd25b860e78af9b898db690e7db45861541c6 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Sat, 19 Nov 2022 14:17:13 -0700 Subject: [PATCH 08/11] Relocated list of OccName prefixes from the Completions plugin to the CoreFile module. Updated the check for GHC-generated OccName prefixes in AtPoint to use the shared list of OccName prefixes. --- ghcide/src/Development/IDE/Spans/AtPoint.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index 53df88d484..e55e8ad9e8 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -34,6 +34,7 @@ import Development.IDE.Core.PositionMapping import Development.IDE.Core.RuleTypes import Development.IDE.GHC.Compat import qualified Development.IDE.GHC.Compat.Util as Util +import Development.IDE.GHC.CoreFile (occNamePrefixes) import Development.IDE.GHC.Util (printOutputable) import Development.IDE.Spans.Common import Development.IDE.Types.Options From bbd73daad1e56753de591798c127b0fee220c237 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Fri, 3 Feb 2023 15:49:31 -0700 Subject: [PATCH 09/11] Removed unused import. --- ghcide/src/Development/IDE/Spans/AtPoint.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index e55e8ad9e8..53df88d484 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -34,7 +34,6 @@ import Development.IDE.Core.PositionMapping import Development.IDE.Core.RuleTypes import Development.IDE.GHC.Compat import qualified Development.IDE.GHC.Compat.Util as Util -import Development.IDE.GHC.CoreFile (occNamePrefixes) import Development.IDE.GHC.Util (printOutputable) import Development.IDE.Spans.Common import Development.IDE.Types.Options From 488f23d9247611994b97d4f02a89e0111c00358f Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Sat, 4 Feb 2023 00:24:44 -0700 Subject: [PATCH 10/11] Fixed incorrect definition of mkRecordSnippetCompItem introduced when rebasing. --- .../src/Development/IDE/Plugin/Completions/Logic.hs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs index 3d99611e43..362fb68993 100644 --- a/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs +++ b/ghcide/src/Development/IDE/Plugin/Completions/Logic.hs @@ -770,17 +770,8 @@ stripPrefix :: T.Text -> T.Text stripPrefix name = T.takeWhile (/=':') $ fromMaybe name $ getFirst $ foldMap (First . (`T.stripPrefix` name)) occNamePrefixes -safeTyThingForRecord :: TyThing -> Maybe (T.Text, [T.Text]) -safeTyThingForRecord (AnId _) = Nothing -safeTyThingForRecord (AConLike dc) = - let ctxStr = printOutputable . occName . conLikeName $ dc - field_names = T.pack . unpackFS . flLabel <$> conLikeFieldLabels dc - in - Just (ctxStr, field_names) -safeTyThingForRecord _ = Nothing - -mkRecordSnippetCompItem :: Uri -> Maybe T.Text -> T.Text -> [T.Text] -> Provenance -> SpanDoc -> Maybe (LImportDecl GhcPs) -> CompItem -mkRecordSnippetCompItem uri parent ctxStr compl importedFrom docs imp = r +mkRecordSnippetCompItem :: Uri -> Maybe T.Text -> T.Text -> [T.Text] -> Provenance -> Maybe (LImportDecl GhcPs) -> CompItem +mkRecordSnippetCompItem uri parent ctxStr compl importedFrom imp = r where r = CI { compKind = CiSnippet From 30c42bb6d41a0e151690ab9ccc84a0b9b2a247a2 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Sat, 4 Feb 2023 10:21:46 -0700 Subject: [PATCH 11/11] Add preprocessor check for GHC version before using isEvidenceContext. Updated related comment. --- ghcide/src/Development/IDE/Spans/AtPoint.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ghcide/src/Development/IDE/Spans/AtPoint.hs b/ghcide/src/Development/IDE/Spans/AtPoint.hs index 53df88d484..fafb18af0e 100644 --- a/ghcide/src/Development/IDE/Spans/AtPoint.hs +++ b/ghcide/src/Development/IDE/Spans/AtPoint.hs @@ -227,10 +227,14 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) env pos = listToMaybe $ p wrapHaskell x = "\n```haskell\n"<>x<>"\n```\n" info = nodeInfoH kind ast names = M.assocs $ nodeIdentifiers info - -- Check if a name matches a pattern for a generated Core variable. + -- Check for evidence bindings isInternal :: (Identifier, IdentifierDetails a) -> Bool isInternal (Right _, dets) = +#if MIN_VERSION_ghc(9,0,1) any isEvidenceContext $ identInfo dets +#else + False +#endif isInternal (Left _, _) = False filteredNames = filter (not . isInternal) names types = nodeType info