1
1
mirror of https://github.com/github/semantic.git synced 2024-12-22 06:11:49 +03:00

Build a resolution map along with creating a Package

This commit is contained in:
Timothy Clem 2018-05-15 15:50:09 -07:00
parent a0d24106a4
commit 7cd1d0ea99
6 changed files with 24 additions and 19 deletions

View File

@ -22,6 +22,7 @@ data PackageBody term = PackageBody
{ packageModules :: ModuleTable [Module term] { packageModules :: ModuleTable [Module term]
, packagePrelude :: Maybe (Module term) , packagePrelude :: Maybe (Module term)
, packageEntryPoints :: ModuleTable (Maybe Name) , packageEntryPoints :: ModuleTable (Maybe Name)
, packageResolutions :: Map.Map FilePath FilePath
} }
deriving (Eq, Functor, Ord, Show) deriving (Eq, Functor, Ord, Show)
@ -33,8 +34,8 @@ data Package term = Package
} }
deriving (Eq, Functor, Ord, Show) deriving (Eq, Functor, Ord, Show)
fromModules :: PackageName -> Maybe Version -> Maybe (Module term) -> Int -> [Module term] -> Package term fromModules :: PackageName -> Maybe Version -> Maybe (Module term) -> Int -> [Module term] -> Map.Map FilePath FilePath -> Package term
fromModules name version prelude entryPoints modules = fromModules name version prelude entryPoints modules resolutions =
Package (PackageInfo name version) (PackageBody (ModuleTable.fromModules modules) prelude entryPoints') Package (PackageInfo name version) (PackageBody (ModuleTable.fromModules modules) prelude entryPoints' resolutions)
where where
entryPoints' = ModuleTable . Map.fromList $ (,Nothing) . modulePath . moduleInfo <$> if entryPoints == 0 then modules else take entryPoints modules entryPoints' = ModuleTable . Map.fromList $ (,Nothing) . modulePath . moduleInfo <$> if entryPoints == 0 then modules else take entryPoints modules

View File

@ -16,6 +16,7 @@ data Project = Project
, projectFiles :: [File] , projectFiles :: [File]
, projectLanguage :: Language , projectLanguage :: Language
, projectEntryPoints :: [File] , projectEntryPoints :: [File]
, projectExcludeDirs :: [FilePath]
} }
deriving (Eq, Ord, Show) deriving (Eq, Ord, Show)

View File

@ -25,7 +25,7 @@ import Semantic.Task as Task
data GraphType = ImportGraph | CallGraph data GraphType = ImportGraph | CallGraph
graph :: Members '[Distribute WrappedTask, Files, Task, Exc SomeException, Telemetry, Trace] effs graph :: Members '[Distribute WrappedTask, Files, Resolution, Task, Exc SomeException, Telemetry, Trace] effs
=> GraphType => GraphType
-> GraphRenderer output -> GraphRenderer output
-> Project -> Project
@ -61,7 +61,7 @@ graph graphType renderer project
constrainingTypes = id constrainingTypes = id
-- | Parse a list of files into a 'Package'. -- | Parse a list of files into a 'Package'.
parsePackage :: Members '[Distribute WrappedTask, Files, Task, Trace] effs parsePackage :: Members '[Distribute WrappedTask, Files, Resolution, Task, Trace] effs
=> Parser term -- ^ A parser. => Parser term -- ^ A parser.
-> Maybe File -- ^ Prelude (optional). -> Maybe File -- ^ Prelude (optional).
-> Project -- ^ Project to parse into a package. -> Project -- ^ Project to parse into a package.
@ -69,7 +69,8 @@ parsePackage :: Members '[Distribute WrappedTask, Files, Task, Trace] effs
parsePackage parser preludeFile project@Project{..} = do parsePackage parser preludeFile project@Project{..} = do
prelude <- traverse (parseModule parser Nothing) preludeFile prelude <- traverse (parseModule parser Nothing) preludeFile
p <- parseModules parser project p <- parseModules parser project
let pkg = Package.fromModules n Nothing prelude (length projectEntryPoints) p resMap <- Task.resolutionMap project
let pkg = Package.fromModules n Nothing prelude (length projectEntryPoints) p resMap
pkg <$ trace ("project: " <> show pkg) pkg <$ trace ("project: " <> show pkg)
where where

View File

@ -99,7 +99,7 @@ readProjectFromPaths maybeRoot path lang excludeDirs = do
else (filter (/= path), [toFile path], fromMaybe (takeDirectory path) maybeRoot) else (filter (/= path), [toFile path], fromMaybe (takeDirectory path) maybeRoot)
paths <- liftIO $ filterFun <$> findFilesInDir rootDir exts excludeDirs paths <- liftIO $ filterFun <$> findFilesInDir rootDir exts excludeDirs
pure $ Project rootDir (toFile <$> paths) lang entryPoints pure $ Project rootDir (toFile <$> paths) lang entryPoints excludeDirs
where where
toFile path = File path (Just lang) toFile path = File path (Just lang)
exts = extensionsForLanguage lang exts = extensionsForLanguage lang

View File

@ -14,29 +14,30 @@ import Semantic.IO
import System.FilePath.Posix import System.FilePath.Posix
nodeJSResolutionMap :: Member Files effs => FilePath -> Language -> [FilePath] -> Eff effs (Map FilePath FilePath) nodeJSResolutionMap :: Member Files effs => FilePath -> Text -> [FilePath] -> Eff effs (Map FilePath FilePath)
nodeJSResolutionMap dir lang excludeDirs = do nodeJSResolutionMap dir prop excludeDirs = do
files <- findFiles dir [".json"] excludeDirs -- ["node_modules"] files <- findFiles dir [".json"] excludeDirs
let packageFiles = file <$> filter ((==) "package.json" . takeFileName) files let packageFiles = file <$> filter ((==) "package.json" . takeFileName) files
blobs <- readBlobs (Right packageFiles) blobs <- readBlobs (Right packageFiles)
pure $ fold (mapMaybe (lookup (propertyNameForLanguage lang)) blobs) pure $ fold (mapMaybe (lookup prop) blobs)
where where
-- Entrypoint property name is different for JavaScript vs. TypeScript module resolution.
propertyNameForLanguage TypeScript = "types"
propertyNameForLanguage _ = "main"
lookup :: Text -> Blob -> Maybe (Map FilePath FilePath) lookup :: Text -> Blob -> Maybe (Map FilePath FilePath)
lookup k Blob{..} = decodeStrict (sourceBytes blobSource) >>= lookupProp blobPath k lookup k Blob{..} = decodeStrict (sourceBytes blobSource) >>= lookupProp blobPath k
lookupProp :: FilePath -> Text -> Object -> Maybe (Map FilePath FilePath) lookupProp :: FilePath -> Text -> Object -> Maybe (Map FilePath FilePath)
lookupProp path k res = flip parseMaybe res $ \obj -> Map.singleton path <$> obj .: k lookupProp path k res = flip parseMaybe res $ \obj -> Map.singleton path <$> obj .: k
nodeResolution :: Member Resolution effs => FilePath -> Language -> [FilePath] -> Eff effs (Map FilePath FilePath) resolutionMap :: Member Resolution effs => Project -> Eff effs (Map FilePath FilePath)
nodeResolution dir prop = send . NodeJSResolution dir prop resolutionMap Project{..} = case projectLanguage of
TypeScript -> send (NodeJSResolution projectRootDir "types" projectExcludeDirs)
JavaScript -> send (NodeJSResolution projectRootDir "main" projectExcludeDirs)
_ -> send NoResolution
data Resolution output where data Resolution output where
NodeJSResolution :: FilePath -> Language -> [FilePath] -> Resolution (Map FilePath FilePath) NodeJSResolution :: FilePath -> Text -> [FilePath] -> Resolution (Map FilePath FilePath)
NoResolution :: Resolution (Map FilePath FilePath)
runResolution :: Members '[Files] effs => Eff (Resolution ': effs) a -> Eff effs a runResolution :: Members '[Files] effs => Eff (Resolution ': effs) a -> Eff effs a
runResolution = interpret $ \ res -> case res of runResolution = interpret $ \ res -> case res of
NodeJSResolution dir prop excludeDirs -> nodeJSResolutionMap dir prop excludeDirs NodeJSResolution dir prop excludeDirs -> nodeJSResolutionMap dir prop excludeDirs
NoResolution -> pure Map.empty

View File

@ -14,7 +14,8 @@ module Semantic.Task
, IO.findFiles , IO.findFiles
, IO.writeToOutput , IO.writeToOutput
-- * Module Resolution -- * Module Resolution
, nodeResolution , resolutionMap
, Resolution
-- * Telemetry -- * Telemetry
, writeLog , writeLog
, writeStat , writeStat