{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE DuplicateRecordFields #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Main where import Control.Exception ( try ) import Control.Monad.Logger ( runLoggingT ) import qualified Data.ByteString as BS import qualified Data.Generics.Uniplate.Data as U import qualified Data.HashMap.Strict as HM import qualified Data.IntMap as IM import qualified Data.IntervalMap.Strict as IVM import qualified Data.Set as S import qualified Data.Text as T import qualified Data.Text.Encoding as TE import qualified Data.Vector as V import Data.Version ( makeVersion ) import HaskellCodeExplorer.AST.TypecheckedSource ( removeOverlappingInterval ) import HaskellCodeExplorer.PackageInfo import HaskellCodeExplorer.Preprocessor import HaskellCodeExplorer.Types import qualified HaskellCodeExplorer.Types as HCE import System.Directory ( findExecutable , getCurrentDirectory , withCurrentDirectory ) import System.FilePath ( (>) ) import System.Process ( readProcess ) import Test.Hspec testPackageDir :: FilePath testPackageDir = "test/test-package" main :: IO () main = do currentDir <- getCurrentDirectory hspec $ do packageInfoSpec currentDir sourceCodeTransformationSpec currentDir tokenizeSpec removeOverlappingIntervalSpec packageInfoSpec :: FilePath -> Spec packageInfoSpec currentDir = do eitherPackageInfo <- runIO $ buildAndIndexTestPackage currentDir case eitherPackageInfo of Right HCE.PackageInfo { id = pkgId, ..} -> do describe "createPackageInfo" $ do it "returns valid package id" $ pkgId `shouldBe` PackageId "test-package" (makeVersion [0, 1, 0, 0]) it "returns valid list of module paths" $ do let paths = HM.fromList [ (HaskellModulePath { getHaskellModulePath = "app/Main.hs" }, ()) , ( HaskellModulePath { getHaskellModulePath = "src/Types.hs" } , () ) , ( HaskellModulePath { getHaskellModulePath = "test/Spec.hs" } , () ) , (HaskellModulePath { getHaskellModulePath = "src/Lib.hs" }, ()) ] (HM.map (const ())) moduleMap `shouldBe` paths it "returns valid list of module names" $ do let names = HM.fromList [ ( HaskellModuleName { getHaskellModuleName = "Types" } , HM.fromList [ ( ComponentId { getComponentId = "lib" } , HaskellModulePath { getHaskellModulePath = "src/Types.hs" } ) ] ) , ( HaskellModuleName { getHaskellModuleName = "Main" } , HM.fromList [ ( ComponentId { getComponentId = "exe-test-package-exe" } , HaskellModulePath { getHaskellModulePath = "app/Main.hs" } ) , ( ComponentId { getComponentId = "test-test-package-test" } , HaskellModulePath { getHaskellModulePath = "test/Spec.hs" } ) ] ) , ( HaskellModuleName { getHaskellModuleName = "Lib" } , HM.fromList [ ( ComponentId { getComponentId = "lib" } , HaskellModulePath { getHaskellModulePath = "src/Lib.hs" } ) ] ) ] moduleNameMap `shouldBe` names let mbModuleInfo = HM.lookup (HCE.HaskellModulePath "src/Lib.hs") moduleMap case mbModuleInfo of Just modInfo -> moduleInfoSpec modInfo Nothing -> return () Left e -> runIO $ putStrLn e >> return () moduleInfoSpec :: ModuleInfo -> Spec moduleInfoSpec HCE.ModuleInfo { id = _, ..} = describe "createModuleInfo" $ do it "returns valid module name" $ name `shouldBe` HCE.HaskellModuleName "Lib" it "returns valid list of declarations " $ declarations `shouldBe` testDeclarations it "returns valid source code " $ do let sourceCodeLines = V.fromList [ "module Lib" , " ( someFunc" , " ) where" , "" , "import Types(Test(..))" , "" , "-- | someFunc documentation" , "someFunc :: IO ()" , "someFunc = putStrLn \"someFunc\"" , "" , "-- | mkTest documentation" , "mkTest :: Int -> Test" , "mkTest i = Test i" , "" ] source `shouldBe` sourceCodeLines it "returns valid map of expressions" $ exprInfoMap `shouldBe` testExprInfoMap it "returns valid map of identifiers " $ let removeLocationInfo :: HCE.LocationInfo -> HCE.LocationInfo removeLocationInfo _ = HCE.UnknownLocation "" removePackageVersionFromExternalId :: HCE.ExternalId -> HCE.ExternalId removePackageVersionFromExternalId extId@(HCE.ExternalId textId) = case T.splitOn "|" textId of pId : rest -> case T.splitOn "-" pId of packageIdParts@(_ : _) -> HCE.ExternalId $ T.intercalate "|" ((T.intercalate "-" (init packageIdParts)) : rest) _ -> extId _ -> extId cleanup :: HCE.IdentifierInfoMap -> HCE.IdentifierInfoMap cleanup = U.transformBi removeLocationInfo . U.transformBi removePackageVersionFromExternalId in cleanup idInfoMap `shouldBe` cleanup testIdInfoMap it "returns valid map of identifier occurrences" $ idOccMap `shouldBe` testIdOccMap stackYamlArg :: [String] stackYamlArg = [] buildAndIndexTestPackage :: FilePath -> IO (Either String (PackageInfo ModuleInfo)) buildAndIndexTestPackage currentDir = do mbStackExecutable <- findExecutable "stack" case mbStackExecutable of Just stackExecutable -> do let removeEndOfLine str | null str = str | otherwise = init str (eitherDistDir :: Either IOError String) <- try . fmap removeEndOfLine . readProcess stackExecutable (["path", "--dist-dir"] ++ stackYamlArg) $ "" case eitherDistDir of Right distDir -> do packageInfo <- let testPackageDirectoryPath = currentDir > testPackageDir in withCurrentDirectory testPackageDirectoryPath $ do _ <- readProcess stackExecutable (["build", "--test", "--force-dirty"] ++ stackYamlArg) "" runLoggingT (createPackageInfo testPackageDirectoryPath (Just distDir) HCE.BeforePreprocessing [] [] ) (\_ _ _ _ -> return ()) return . Right $ packageInfo Left ex -> return . Left $ show ex Nothing -> return . Left $ "Cannot find stack executable. Stack executable is required to build the test package." sourceCodeTransformationSpec :: FilePath -> Spec sourceCodeTransformationSpec currentDir = do sourceCodeAfterPreprocessor <- runIO $ BS.readFile $ currentDir > "test/data/FileAfterPreprocessor.hs" let sourceCodeTransformation = fst $ createSourceCodeTransformation (HaskellModulePath "File.hs") (TE.decodeUtf8 sourceCodeAfterPreprocessor) (TE.decodeUtf8 sourceCodeAfterPreprocessor) describe "createSourceCodeTransformation" $ do it "returns valid list of pragmas" $ do let pragmas = S.fromList [ LinePragma (HaskellFilePath "File1.hs") 8 1 , LinePragma (HaskellFilePath "File1.hs") 11 14 , LinePragma (HaskellFilePath "File2.hs") 12 1 , LinePragma (HaskellFilePath "File1.hs") 18 15 , LinePragma (HaskellFilePath "File.hs") 21 9 , LinePragma (HaskellFilePath "File.hs") 23 18 , LinePragma (HaskellFilePath "File3.hs") 26 1 , LinePragma (HaskellFilePath "File.hs") 30 21 ] linePragmas sourceCodeTransformation `shouldBe` pragmas it "returns valid file index" $ let index = HM.fromList [ ( HaskellFilePath { getHaskellFilePath = "File1.hs" } , S.fromList [ FileLocation { lineStart = 1, lineEnd = 2, offset = 8 } , FileLocation { lineStart = 15, lineEnd = 16, offset = 4 } ] ) , ( HaskellFilePath { getHaskellFilePath = "File2.hs" } , S.fromList [FileLocation { lineStart = 1, lineEnd = 5, offset = 12 }] ) , ( HaskellFilePath { getHaskellFilePath = "File3.hs" } , S.fromList [FileLocation { lineStart = 1, lineEnd = 3, offset = 26 }] ) , ( HaskellFilePath { getHaskellFilePath = "File.hs" } , S.fromList [ FileLocation { lineStart = 1, lineEnd = 8, offset = 0 } , FileLocation { lineStart = 9, lineEnd = 9, offset = 13 } , FileLocation { lineStart = 18, lineEnd = 19, offset = 6 } , FileLocation { lineStart = 21, lineEnd = 21, offset = 10 } ] ) ] in fileIndex sourceCodeTransformation `shouldBe` index describe "fromOriginalLineNumber" $ do test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File.hs", 1) (Right 1) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File.hs", 4) (Right 4) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File1.hs", 1) (Right 9) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File1.hs", 2) (Right 10) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File2.hs", 1) (Right 13) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File2.hs", 3) (Right 15) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File2.hs", 5) (Right 17) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File1.hs", 15) (Right 19) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File1.hs", 16) (Right 20) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File3.hs", 1) (Right 27) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File3.hs", 2) (Right 28) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File3.hs", 3) (Right 29) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File.hs", 9) (Right 22) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File.hs", 18) (Right 24) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File.hs", 19) (Right 25) test fromOriginalLineNumber sourceCodeTransformation (HaskellFilePath "File.hs", 21) (Right 31) test :: forall a t t1 . (Show t1, Show t, Show a, Eq a) => (t1 -> t -> a) -> t1 -> t -> a -> Spec test fun arg1 arg2 result = it (show arg1 ++ " " ++ show arg2) $ fun arg1 arg2 `shouldBe` result tokenizeSpec :: Spec tokenizeSpec = describe "tokenize" $ do test tokenize "" ([] :: [((Int, Int), String)]) [] test tokenize "--comment" ([] :: [((Int, Int), String)]) [("--comment", (1, 10), Nothing)] test tokenize ("abcd" :: T.Text) [((1, 5), "abcdIdentifier")] [("abcd", (1, 5), Just "abcdIdentifier")] test tokenize ("data Test" :: T.Text) [((6, 10), "TestIdentifier")] [("data ", (1, 6), Nothing), ("Test", (6, 10), Just "TestIdentifier")] test tokenize ("abc = xyz" :: T.Text) [((1, 4), "abcIdentifier"), ((7, 10), "xyzIdentifier")] [ ("abc", (1, 4) , Just "abcIdentifier") , (" = ", (4, 7) , Nothing) , ("xyz", (7, 10), Just "xyzIdentifier") ] test tokenize ("abc = xyz --comment" :: T.Text) [((1, 4), "abcIdentifier"), ((7, 10), "xyzIdentifier")] [ ("abc" , (1, 4) , Just "abcIdentifier") , (" = " , (4, 7) , Nothing) , ("xyz" , (7, 10) , Just "xyzIdentifier") , (" --comment", (10, 20), Nothing) ] test tokenize (" abc = xyz --comment" :: T.Text) [((4, 7), "abcIdentifier"), ((10, 13), "xyzIdentifier")] [ (" " , (1, 4) , Nothing) , ("abc" , (4, 7) , Just "abcIdentifier") , (" = " , (7, 10) , Nothing) , ("xyz" , (10, 13), Just "xyzIdentifier") , (" --comment", (13, 23), Nothing) ] removeOverlappingIntervalSpec :: Spec removeOverlappingIntervalSpec = describe "removeOverlappingInterval" $ do test removeOverlappingInterval [((1, 2), "a")] [] [((1, 2), "a")] test removeOverlappingInterval [((3, 4), "b")] [((1, 2), "a")] [((1, 2), "a"), ((3, 4), "b")] test removeOverlappingInterval [((2, 3), "b")] [((1, 5), "a")] [((2, 3), "b")] test removeOverlappingInterval [((1, 5), "b")] [((2, 3), "a")] [((2, 3), "a")] test removeOverlappingInterval [((1, 5), "b")] [((2, 7), "a")] [((1, 5), "b")] test removeOverlappingInterval [((1, 3), "b")] [((1, 3), "a")] [((1, 3), "a")] testDeclarations :: [Declaration] testDeclarations = [ Declaration { sort = ValD , name = "someFunc" , declType = Just (Type { components = [ TyCon { internalId = HCE.InternalId "0" , name = "IO" } , Text " ()" ] , componentsExpanded = Nothing } ) , isExported = True , lineNumber = 9 } , Declaration { sort = ValD , name = "mkTest" , declType = Just (Type { components = [ TyCon { internalId = HCE.InternalId "9", name = "Int" } , Text " -> " , TyCon { internalId = HCE.InternalId "1", name = "Test" } ] , componentsExpanded = Nothing } ) , isExported = False , lineNumber = 13 } ] testExprInfoMap :: IVM.IntervalMap (Int, Int) HCE.ExpressionInfo testExprInfoMap = IVM.fromList [ ( IVM.OpenInterval (9, 12) (9, 31) , ExpressionInfo { description = "HsApp" , exprType = Just (Type { components = [ TyCon { internalId = InternalId { getInternalId = "0" } , name = "IO" } , Text " ()" ] , componentsExpanded = Nothing } ) } ) , ( IVM.OpenInterval (13, 12) (13, 18) , ExpressionInfo { description = "HsApp" , exprType = Just (Type { components = [ TyCon { internalId = InternalId { getInternalId = "1" } , name = "Test" } ] , componentsExpanded = Nothing } ) } ) ] testIdOccMap :: IM.IntMap [((Int, Int), IdentifierOccurrence)] testIdOccMap = IM.fromList [ ( 2 , [ ( (7, 15) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "2" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "3" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "IE" , sort = ValueId } ) ] ) , ( 5 , [ ( (8, 13) , IdentifierOccurrence { internalId = Nothing , internalIdFromRenamedSource = Nothing , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "ImportDecl" , sort = ModuleId (ExactLocation { packageId = PackageId { name = "test-package" , version = makeVersion [0, 1, 0, 0] } , modulePath = HaskellModulePath { getHaskellModulePath = "src/Types.hs" } , moduleName = HaskellModuleName { getHaskellModuleName = "Types" } , startLine = 1 , endLine = 1 , startColumn = 1 , endColumn = 1 } ) } ) , ( (14, 18) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "1" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "1" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "IE" , sort = TypeId } ) ] ) , ( 8 , [ ( (1, 9) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "2" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "3" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "TypeSig" , sort = ValueId } ) , ( (13, 15) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "0" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "0" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "HsTyVar" , sort = TypeId } ) , ( (16, 18) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "4" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "4" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "HsTupleTy" , sort = TypeId } ) ] ) , ( 9 , [ ( (1, 9) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "2" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "3" }) , isBinder = True , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "Match" , sort = ValueId } ) , ( (12, 20) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "5" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "5" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "HsVar" , sort = ValueId } ) , ( (21, 31) , IdentifierOccurrence { internalId = Nothing , internalIdFromRenamedSource = Nothing , isBinder = False , instanceResolution = Nothing , idOccType = Just (Type { components = [ Text "[" , TyCon { internalId = InternalId { getInternalId = "6" } , name = "Char" } , Text "]" ] , componentsExpanded = Nothing } ) , typeArguments = Nothing , description = "HsLit" , sort = ValueId } ) ] ) , ( 12 , [ ( (1, 7) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "7" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "8" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "TypeSig" , sort = ValueId } ) , ( (11, 14) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "9" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "9" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "HsTyVar" , sort = TypeId } ) , ( (18, 22) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "1" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "1" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "HsTyVar" , sort = TypeId } ) ] ) , ( 13 , [ ( (1, 7) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "7" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "8" }) , isBinder = True , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "Match" , sort = ValueId } ) , ( (8, 9) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "10" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "11" }) , isBinder = True , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "VarPat" , sort = ValueId } ) , ( (12, 16) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "12" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "13" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "HsVar" , sort = ValueId } ) , ( (17, 18) , IdentifierOccurrence { internalId = Just (InternalId { getInternalId = "10" }) , internalIdFromRenamedSource = Just (InternalId { getInternalId = "11" }) , isBinder = False , instanceResolution = Nothing , idOccType = Nothing , typeArguments = Nothing , description = "HsVar" , sort = ValueId } ) ] ) ] testIdInfoMap :: HM.HashMap InternalId IdentifierInfo testIdInfoMap = HM.fromList [ ( InternalId { getInternalId = "7" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "mkTest" } , demangledOccName = "mkTest" , nameSpace = VarName , locationInfo = ExactLocation { packageId = PackageId { name = "test-package" , version = makeVersion [0, 1, 0, 0] } , modulePath = HaskellModulePath { getHaskellModulePath = "src/Lib.hs" } , moduleName = HaskellModuleName { getHaskellModuleName = "Lib" } , startLine = 13 , endLine = 13 , startColumn = 1 , endColumn = 7 } , idType = Type { components = [ TyCon { internalId = InternalId { getInternalId = "9" } , name = "Int" } , Text " -> " , TyCon { internalId = InternalId { getInternalId = "1" } , name = "Test" } ] , componentsExpanded = Nothing } , details = Just VanillaId , doc = Just "
mkTest documentation
" , internalId = InternalId { getInternalId = "7" } , externalId = Just (ExternalId { getExternalId = "test-package-0.1.0.0|Lib|Val|mkTest" }) , isExported = False } ) , ( InternalId { getInternalId = "14" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "TYPE" } , demangledOccName = "TYPE" , nameSpace = TcClsName , locationInfo = ApproximateLocation { packageId = PackageId { name = "ghc-prim" , version = makeVersion [0, 5, 1, 1] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Prim" } , entity = Typ , name = "TYPE" , haddockAnchorId = Just "TYPE" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [ TyCon { internalId = InternalId { getInternalId = "15" } , name = "RuntimeRep" } , Text " -> *" ] , componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "14" } , externalId = Just (ExternalId { getExternalId = "ghc-prim-0.5.1.1|GHC.Prim|Typ|TYPE" }) , isExported = False } ) , ( InternalId { getInternalId = "0" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "IO" } , demangledOccName = "IO" , nameSpace = TcClsName , locationInfo = ApproximateLocation { packageId = PackageId { name = "ghc-prim" , version = makeVersion [0, 5, 1, 1] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Types" } , entity = Typ , name = "IO" , haddockAnchorId = Just "IO" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [Text "* -> *"] , componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "0" } , externalId = Just (ExternalId { getExternalId = "ghc-prim-0.5.1.1|GHC.Types|Typ|IO" }) , isExported = False } ) , ( InternalId { getInternalId = "12" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "Test" } , demangledOccName = "Test" , nameSpace = DataName , locationInfo = ExactLocation { packageId = PackageId { name = "test-package" , version = makeVersion [0, 1, 0, 0] } , modulePath = HaskellModulePath { getHaskellModulePath = "src/Types.hs" } , moduleName = HaskellModuleName { getHaskellModuleName = "Types" } , startLine = 5 , endLine = 5 , startColumn = 13 , endColumn = 21 } , idType = Type { components = [ TyCon { internalId = InternalId { getInternalId = "9" } , name = "Int" } , Text " -> " , TyCon { internalId = InternalId { getInternalId = "1" } , name = "Test" } ] , componentsExpanded = Nothing } , details = Just DataConWorkId , doc = Nothing , internalId = InternalId { getInternalId = "12" } , externalId = Just (ExternalId { getExternalId = "test-package-0.1.0.0|Types|Val|Test" }) , isExported = False } ) , ( InternalId { getInternalId = "17" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "[]" } , demangledOccName = "[]" , nameSpace = TcClsName , locationInfo = ApproximateLocation { packageId = PackageId { name = "ghc-prim" , version = makeVersion [0, 5, 1, 1] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Types" } , entity = Typ , name = "[]" , haddockAnchorId = Just "-91--93-" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [Text "* -> *"] , componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "17" } , externalId = Just (ExternalId { getExternalId = "ghc-prim-0.5.1.1|GHC.Types|Typ|[]" }) , isExported = False } ) , ( InternalId { getInternalId = "1" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "Test" } , demangledOccName = "Test" , nameSpace = TcClsName , locationInfo = ExactLocation { packageId = PackageId { name = "test-package" , version = makeVersion [0, 1, 0, 0] } , modulePath = HaskellModulePath { getHaskellModulePath = "src/Types.hs" } , moduleName = HaskellModuleName { getHaskellModuleName = "Types" } , startLine = 5 , endLine = 5 , startColumn = 1 , endColumn = 21 } , idType = Type { components = [Text "*"], componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "1" } , externalId = Just (ExternalId { getExternalId = "test-package-0.1.0.0|Types|Typ|Test" }) , isExported = False } ) , ( InternalId { getInternalId = "18" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "LiftedRep" } , demangledOccName = "LiftedRep" , nameSpace = DataName , locationInfo = ApproximateLocation { packageId = PackageId { name = "ghc-prim" , version = makeVersion [0, 5, 1, 1] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Types" } , entity = Val , name = "LiftedRep" , haddockAnchorId = Just "LiftedRep" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [ TyCon { internalId = InternalId { getInternalId = "15" } , name = "RuntimeRep" } ] , componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "18" } , externalId = Just (ExternalId { getExternalId = "ghc-prim-0.5.1.1|GHC.Types|Val|LiftedRep" } ) , isExported = False } ) , ( InternalId { getInternalId = "4" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "()" } , demangledOccName = "()" , nameSpace = TcClsName , locationInfo = ApproximateLocation { packageId = PackageId { name = "ghc-prim" , version = makeVersion [0, 5, 1, 1] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Tuple" } , entity = Typ , name = "()" , haddockAnchorId = Just "-40--41-" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [Text "*"], componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "4" } , externalId = Just (ExternalId { getExternalId = "ghc-prim-0.5.1.1|GHC.Tuple|Typ|()" }) , isExported = False } ) , ( InternalId { getInternalId = "16" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "String" } , demangledOccName = "String" , nameSpace = TcClsName , locationInfo = ApproximateLocation { packageId = PackageId { name = "base" , version = makeVersion [4, 10, 1, 0] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Base" } , entity = Typ , name = "String" , haddockAnchorId = Just "String" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [Text "*"], componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "16" } , externalId = Just (ExternalId { getExternalId = "base-4.10.1.0|GHC.Base|Typ|String" }) , isExported = False } ) , ( InternalId { getInternalId = "2" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "someFunc" } , demangledOccName = "someFunc" , nameSpace = VarName , locationInfo = ExactLocation { packageId = PackageId { name = "test-package" , version = makeVersion [0, 1, 0, 0] } , modulePath = HaskellModulePath { getHaskellModulePath = "src/Lib.hs" } , moduleName = HaskellModuleName { getHaskellModuleName = "Lib" } , startLine = 9 , endLine = 9 , startColumn = 1 , endColumn = 9 } , idType = Type { components = [ TyCon { internalId = InternalId { getInternalId = "0" } , name = "IO" } , Text " ()" ] , componentsExpanded = Nothing } , details = Just VanillaId , doc = Just "someFunc documentation
" , internalId = InternalId { getInternalId = "2" } , externalId = Just (ExternalId { getExternalId = "test-package-0.1.0.0|Lib|Val|someFunc" }) , isExported = True } ) , ( InternalId { getInternalId = "5" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "putStrLn" } , demangledOccName = "putStrLn" , nameSpace = VarName , locationInfo = ApproximateLocation { packageId = PackageId { name = "base" , version = makeVersion [4, 10, 1, 0] } , moduleName = HaskellModuleName { getHaskellModuleName = "System.IO" } , entity = Val , name = "putStrLn" , haddockAnchorId = Just "putStrLn" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [ TyCon { internalId = InternalId { getInternalId = "16" } , name = "String" } , Text " -> " , TyCon { internalId = InternalId { getInternalId = "0" } , name = "IO" } , Text " ()" ] , componentsExpanded = Just [ Text "[" , TyCon { internalId = InternalId { getInternalId = "6" } , name = "Char" } , Text "] -> " , TyCon { internalId = InternalId { getInternalId = "0" } , name = "IO" } , Text " ()" ] } , details = Just VanillaId , doc = Nothing , internalId = InternalId { getInternalId = "5" } , externalId = Just (ExternalId { getExternalId = "base-4.10.1.0|System.IO|Val|putStrLn" }) , isExported = False } ) , ( InternalId { getInternalId = "6" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "Char" } , demangledOccName = "Char" , nameSpace = TcClsName , locationInfo = ApproximateLocation { packageId = PackageId { name = "ghc-prim" , version = makeVersion [0, 5, 1, 1] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Types" } , entity = Typ , name = "Char" , haddockAnchorId = Just "Char" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [Text "*"], componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "6" } , externalId = Just (ExternalId { getExternalId = "ghc-prim-0.5.1.1|GHC.Types|Typ|Char" }) , isExported = False } ) , ( InternalId { getInternalId = "9" } , IdentifierInfo { sort = External , occName = OccName { getOccName = "Int" } , demangledOccName = "Int" , nameSpace = TcClsName , locationInfo = ApproximateLocation { packageId = PackageId { name = "ghc-prim" , version = makeVersion [0, 5, 1, 1] } , moduleName = HaskellModuleName { getHaskellModuleName = "GHC.Types" } , entity = Typ , name = "Int" , haddockAnchorId = Just "Int" , componentId = ComponentId { getComponentId = "lib" } } , idType = Type { components = [Text "*"], componentsExpanded = Nothing } , details = Nothing , doc = Nothing , internalId = InternalId { getInternalId = "9" } , externalId = Just (ExternalId { getExternalId = "ghc-prim-0.5.1.1|GHC.Types|Typ|Int" }) , isExported = False } ) , ( InternalId { getInternalId = "10" } , IdentifierInfo { sort = Internal , occName = OccName { getOccName = "i" } , demangledOccName = "i" , nameSpace = VarName , locationInfo = ExactLocation { packageId = PackageId { name = "test-package" , version = makeVersion [0, 1, 0, 0] } , modulePath = HaskellModulePath { getHaskellModulePath = "src/Lib.hs" } , moduleName = HaskellModuleName { getHaskellModuleName = "" } , startLine = 13 , endLine = 13 , startColumn = 8 , endColumn = 9 } , idType = Type { components = [ TyCon { internalId = InternalId { getInternalId = "9" } , name = "Int" } ] , componentsExpanded = Nothing } , details = Just VanillaId , doc = Nothing , internalId = InternalId { getInternalId = "10" } , externalId = Nothing , isExported = False } ) ]