{- 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. -} {-# OPTIONS_GHC -Wno-orphans #-} {-# LANGUAGE TypeApplications #-} module Glean.Glass.SymbolId.Python () where import Data.Text (Text, splitOn) import Data.List (nub) import Data.Maybe ( maybeToList ) import qualified Glean import Glean.Angle as Angle import qualified Glean.Haxl.Repos as Glean import qualified Glean.Schema.Python.Types as Py import Glean.Util.ToAngle import Glean.Glass.SymbolId.Class import Glean.Glass.Types (Name(..)) import Glean.Glass.Utils ( fetchData ) instance Symbol Py.Name where toSymbol k = do v <- Glean.keyOf k return [v] instance Symbol Py.Declaration where toSymbol d = do locations <- maybeToList <$> fetchData (declarationLocation $ toAngle d) let loc = case nub $ map (head . splitOn "/") locations of [location] -> location _ -> "." sym <- case d of Py.Declaration_cls x -> toSymbolPredicate x Py.Declaration_func x -> toSymbolPredicate x Py.Declaration_module x -> toSymbolPredicate x Py.Declaration_variable x -> toSymbolPredicate x Py.Declaration_imp x -> toSymbolPredicate x Py.Declaration_EMPTY -> return [] return $ loc:sym instance Symbol Py.ImportStatement_key where toSymbol (Py.ImportStatement_key _ asName) = toSymbol asName instance Symbol Py.VariableDeclaration_key where toSymbol (Py.VariableDeclaration_key n) = toSymbol n instance Symbol Py.FunctionDeclaration_key where toSymbol (Py.FunctionDeclaration_key n) = toSymbol n instance Symbol Py.ClassDeclaration_key where toSymbol (Py.ClassDeclaration_key n _) = toSymbol n instance Symbol Py.Module_key where toSymbol (Py.Module_key n) = toSymbol n declarationLocation :: Angle Py.Declaration -> Angle Text declarationLocation decl = var $ \file -> file `where_` [ wild .= predicate @Py.DeclarationLocation ( rec $ field @"declaration" decl $ field @"file" (sig file) end) ] instance ToQName Py.Declaration where toQName (Py.Declaration_cls x) = Glean.keyOf x >>= toQName toQName (Py.Declaration_func x) = Glean.keyOf x >>= toQName toQName (Py.Declaration_module x) = Glean.keyOf x >>= toQName toQName (Py.Declaration_variable x) = Glean.keyOf x >>= toQName toQName (Py.Declaration_imp x) = Glean.keyOf x >>= toQName toQName Py.Declaration_EMPTY = return $ Left "unknown Declaration" instance ToQName Py.ImportStatement_key where toQName (Py.ImportStatement_key _ asName) = toQName asName instance ToQName Py.VariableDeclaration_key where toQName (Py.VariableDeclaration_key x) = toQName x instance ToQName Py.FunctionDeclaration_key where toQName (Py.FunctionDeclaration_key x) = toQName x instance ToQName Py.ClassDeclaration_key where toQName (Py.ClassDeclaration_key x _) = toQName x instance ToQName Py.Module_key where toQName (Py.Module_key x) = toQName x instance ToQName Py.Name where toQName name = do let nameId = Glean.getId name (mr :: Maybe (Py.Name, Py.Name)) <- fetchData $ qNameQuery nameId case mr of Nothing -> Left . ("No qualified names found for " <>) <$> Glean.keyOf name Just (local, container) -> fmap Right $ (,) <$> pyNameToName local <*> pyNameToName container pyNameToName :: Py.Name -> Glean.RepoHaxl u w Name pyNameToName name = Name <$> Glean.keyOf name qNameQuery :: Glean.IdOf Py.Name -> Angle (Py.Name, Py.Name) qNameQuery nameId = vars $ \ (lname :: Angle Py.Name) (pname :: Angle Py.Name) (psname :: Angle Py.SName) (maybe_psname :: Angle (Maybe Py.SName)) -> tuple (lname, pname) `where_` [ wild .= predicate @Py.NameToSName (factId nameId .-> predicate @Py.SName (rec $ field @"local_name" (asPredicate lname) $ field @"parent" maybe_psname end)) , wild .= or_ [ just psname .= maybe_psname, wild .= (predicate @Py.SNameToName $ psname .-> pname) ] [ nothing .= maybe_psname, pname .= predicate @Py.Name "" ] ]