{- 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 TypeApplications #-} {-# OPTIONS_GHC -Wno-orphans #-} module Glean.Glass.Search.Flow ( {- instances -} ) where import Data.Text as Text ( Text ) import Glean.Angle as Angle import Glean.Glass.Search.Class import Glean.Glass.Query ( entityLocation ) import Glean.Glass.Utils ( joinFragments ) import qualified Glean.Schema.CodeFlow.Types as Flow import qualified Glean.Schema.Flow.Types as Flow import qualified Glean.Schema.Src.Types as Src import qualified Glean.Schema.CodemarkupTypes.Types as Code instance Search (ResultLocation Flow.Entity) where symbolSearch [] = return $ None "Flow.symbolSearch: empty" -- if it is a single token it is either a string_ or Haste module name symbolSearch toks@[module_] = do m <- searchSymbolId toks (searchByModuleName module_) return $ mapResultLocation Flow.Entity_module_ <$> m -- (string or lib) module , method -- module only, of any sort. symbolSearch ("m":toks) = do a <- searchSymbolId toks $ searchByModuleName (joinFragments toks) return $ mapResultLocation Flow.Entity_module_ <$> a -- (string or lib) module , method symbolSearch toks@[module_, name] = do a <- searchSymbolId toks $ searchByModule module_ name decl <- case a of None{} -> searchSymbolId toks $ searchTypeByModuleExport module_ name _ -> return a return $ mapResultLocation Flow.Entity_decl <$> decl -- inverse of T90301808 , if we don't have a short name use filepath symbolSearch toks = do let name = last toks path = joinFragments (init toks) a <- searchSymbolId toks $ searchByFileModule path name return $ mapResultLocation Flow.Entity_decl <$> a -- With the Haste short module name and an identifier, find the decl searchByModule :: Text -> Text -> Angle (ResultLocation Flow.SomeDeclaration) searchByModule module_ name = vars $ \(decl :: Angle Flow.SomeDeclaration) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (decl,file,rangespan,lname) `where_` [ wild .= predicate @Flow.SearchByModule ( rec $ field @"string_" (string module_) $ field @"name" (string name) $ field @"decl" decl end), entityLocation (alt @"flow" (alt @"decl" decl)) file rangespan lname ] -- With the repo-anchored filepath and an identifier, find the decl searchByFileModule :: Text -> Text -> Angle (ResultLocation Flow.SomeDeclaration) searchByFileModule path name = vars $ \(decl :: Angle Flow.SomeDeclaration) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (decl,file,rangespan,lname) `where_` [ file .= predicate @Src.File (string path), wild .= predicate @Flow.SearchByFileModule ( rec $ field @"file" (asPredicate file) $ field @"name" (string name) $ field @"decl" decl end), entityLocation (alt @"flow" (alt @"decl" decl)) file rangespan lname ] -- With the Haste name, find the type decl from a .js.flow file searchTypeByModuleExport :: Text -> Text -> Angle (ResultLocation Flow.SomeDeclaration) searchTypeByModuleExport module_ name = vars $ \(decl :: Angle Flow.SomeDeclaration) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (decl,file,rangespan,lname) `where_` [ wild .= predicate @Flow.SearchTypeByModuleExport ( rec $ field @"string_" (string module_) $ field @"name" (string name) $ field @"decl" decl end), entityLocation (alt @"flow" (alt @"decl" decl)) file rangespan lname ] -- Single token module name lookup searchByModuleName :: Text -> Angle (ResultLocation Flow.Module) searchByModuleName modstr = vars $ \(modent :: Angle Flow.Module) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (modent, file, rangespan, lname) `where_` [ wild .= predicate @Flow.SearchByModuleName ( rec $ field @"name" (string modstr) $ field @"module" (asPredicate modent) end), entityLocation (alt @"flow" (alt @"module_" (asPredicate modent))) file rangespan lname ]