{- 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.LSIF ( {- instances -} ) where import Data.Text as Text ( Text ) import Data.Coerce import Util.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.CodeLsif.Types as Lsif ( Entity(..) ) import qualified Glean.Schema.Lsif.Types as LSIF import qualified Glean.Schema.Src.Types as Src import qualified Glean.Schema.CodemarkupTypes.Types as Code instance Search (ResultLocation Lsif.Entity) where symbolSearch [] = return $ None "LSIF.symbolSearch: empty" -- case 2: purely a moniker symbolSearch toks@("lsif":rest) = searchSymbolId toks $ searchByMoniker (joinFragments rest) -- case 1a) with no identifier symbolSearch toks | ceT:leT:cbT:lbT:"":revpath <- reverse toks , Right lb <- textToInt lbT , Right cb <- textToInt cbT , Right le <- textToInt leT , Right ce <- textToInt ceT = searchSymbolId toks $ searchByExactLocation (joinFragments (reverse revpath)) lb cb le ce -- case 1b) with identifier symbolSearch toks | ceT:leT:cbT:lbT:name:"":revpath <- reverse toks , Right lb <- textToInt lbT , Right cb <- textToInt cbT , Right le <- textToInt leT , Right ce <- textToInt ceT = searchSymbolId toks $ searchByExactLocationAndName (joinFragments (reverse revpath)) name lb cb le ce -- case 3: only path and name | name:revpath <- rtoks = searchSymbolId toks $ searchNonLocalByLocation (joinFragments (reverse revpath)) name where rtoks = reverse toks -- anything else is malformed symbolSearch _ = return $ None "LSIF.symbolSearch: malformed symbol id" searchByMoniker :: Text -> Angle (ResultLocation Lsif.Entity) searchByMoniker ident = vars $ \(ent :: Angle Lsif.Entity) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (ent,file,rangespan,lname) `where_` [ wild .= predicate @LSIF.SearchByMoniker ( rec $ field @"ident" (string ident) $ field @"entity" (cast ent) end), entityLocation (alt @"lsif" ent) file rangespan lname ] searchNonLocalByLocation :: Text -> Text -> Angle (ResultLocation Lsif.Entity) searchNonLocalByLocation path name = vars $ \(ent :: Angle Lsif.Entity) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (ent,file,rangespan,lname) `where_` [ file .= predicate @Src.File (string path), wild .= predicate @LSIF.SearchNonLocalByLocation ( rec $ field @"file" (asPredicate file) $ field @"name" (string name) $ field @"entity" (cast ent) end), entityLocation (alt @"lsif" ent) file rangespan lname ] searchByExactLocation :: Text -> Int -> Int -> Int -> Int -> Angle (ResultLocation Lsif.Entity) searchByExactLocation path lb cb le ce = vars $ \(ent :: Angle Lsif.Entity) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (ent,file,rangespan,lname) `where_` [ file .= predicate @Src.File (string path), wild .= predicate @LSIF.SearchByExactLocation ( rec $ field @"file" (asPredicate file) $ field @"span" ( rec $ field @"lineBegin" (nat (fromIntegral lb)) $ field @"columnBegin" (nat (fromIntegral cb)) $ field @"lineEnd" (nat (fromIntegral le)) $ field @"columnEnd" (nat (fromIntegral ce - 1)) end) $ field @"entity" (cast ent) end), entityLocation (alt @"lsif" ent) file rangespan lname ] searchByExactLocationAndName :: Text -> Text -> Int -> Int -> Int -> Int -> Angle (ResultLocation Lsif.Entity) searchByExactLocationAndName path name lb cb le ce = vars $ \(ent :: Angle Lsif.Entity) (file :: Angle Src.File) (rangespan :: Angle Code.RangeSpan) (lname :: Angle Text) -> tuple (ent,file,rangespan,lname) `where_` [ file .= predicate @Src.File (string path), wild .= predicate @LSIF.SearchByExactLocationAndName ( rec $ field @"file" (asPredicate file) $ field @"name" (string name) $ field @"span" ( rec $ field @"lineBegin" (nat (fromIntegral lb)) $ field @"columnBegin" (nat (fromIntegral cb)) $ field @"lineEnd" (nat (fromIntegral le)) $ field @"columnEnd" (nat (fromIntegral ce - 1)) end) $ field @"entity" (cast ent) end), entityLocation (alt @"lsif" ent) file rangespan lname ] -- we are coercing (silently) lsif.Entity to code.lsif.Entity cast :: Angle Lsif.Entity -> Angle LSIF.Entity cast = coerce