{- Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. This source code is licensed under the BSD-style license found in the LICENSE file in the root directory of this source tree. -} {-# LANGUAGE ApplicativeDo #-} module Glean.Indexer.Swift ( indexer ) where import qualified Data.ByteString as BS import Data.Proxy ( Proxy(..) ) import Options.Applicative import qualified Glean import Glean.Indexer import Glean.Indexer.External import Glean.Indexer.SCIP ( derive ) import qualified Glean.SCIP.Driver as SCIP import System.FilePath ( (), takeDirectory) import Glean.LocalOrRemote ( serializeInventory ) import Thrift.Protocol (deserializeGen) import Thrift.Protocol.Compact (Compact) data Swift = Swift { scipGen :: FilePath , target :: String , scipRustIndexer :: Maybe FilePath } options :: Parser Swift options = do scipGen <- strOption $ long "scip-gen" <> metavar "PATH" <> value "scip-gen" <> help "path to scip-gen binary" target <- strOption $ long "target" <> value "target" <> help "target to build and index" scipRustIndexer <- optional (strOption $ long "rust-indexer" <> help "Path to the rust indexer binary. If not provided, uses the haskell indexer instead") return Swift{..} indexer :: Indexer Swift indexer = Indexer { indexerShortName = "swift", indexerDescription = "Index Swift code", indexerOptParser = options, indexerRun = \Swift{..} backend repo IndexerParams{ indexerOutput, .. } -> do let tmpDir = indexerOutput inventoryFile = tmpDir "inventory.data" serializeInventory backend repo >>= BS.writeFile inventoryFile val <- SCIP.runIndexer SCIP.ScipIndexerParams { scipBinary = scipGen, scipArgs = \outFile -> let outDir = takeDirectory outFile in [ "--output-dir", outDir , "--target", target , "--output-type", "scip" , "--inventory", inventoryFile , "--isolation-dir", "index_store" , "--build-indexer" ], scipOutDir = Just tmpDir, scipRoot = indexerRoot, scipWritesLocal = False, scipLanguage = Just SCIP.Swift, scipRustIndexer = scipRustIndexer } sendJsonBatches backend repo (scipGen <> "/scip") val sendBatch backend repo (tmpDir "facts") derive backend repo } sendBatch :: forall be. Glean.Backend be => be -> Glean.Repo -> FilePath -> IO () sendBatch backend repo factFile = do dat <- BS.readFile factFile case deserializeGen (Proxy :: Proxy Compact) dat of Left parseError -> error parseError Right batch -> do _subst <- Glean.sendBatchAndWait backend repo batch return ()