content: {-
    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 #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# OPTIONS_GHC -Wno-orphans #-}
  -- Copyright 2004-present Facebook. All Rights Reserved.
  
  module Glean.Glass.Attributes.SymbolKind
    ( {- instances -}
      SymbolKindAttr(..)
    , symbolKindToSymbolKind
    , symbolKindFromSymbolKind
    ) where
  
  --
  -- Labels for entities, usually based on the constructor
  --
  
  import qualified Data.Map as Map
  
  import qualified Glean
  import Glean.Angle as Angle
  
  import qualified Glean.Glass.Utils as Utils
  import Glean.Glass.Attributes.Class
  import Glean.Glass.Types as Glass
      ( SymbolKind(..), Attribute(Attribute_aInteger), Attributes(Attributes) )
  
  import Thrift.Protocol ( fromThriftEnum, ThriftEnum (toThriftEnum) )
  
  import qualified Glean.Schema.Code.Types as Code
  import qualified Glean.Schema.CodemarkupTypes.Types as Code
  import qualified Glean.Schema.Codemarkup.Types as Code
  import qualified Glean.Schema.Src.Types as Src
  
  -- | Key of generic kind labels
  data SymbolKindAttr = SymbolKindAttr
  
  type EntityKindLabel = (Code.Entity, Code.SymbolKind)
  
  instance ToAttributes SymbolKindAttr where
    type AttrRep SymbolKindAttr = EntityKindLabel
    type AttrLog SymbolKindAttr = ()
    type FileAttrRep SymbolKindAttr = ()
  
    fileAttrsToAttributeList _ _ = undefined
  
  
    queryForFile _ lim fileId _ _ _ _ _ _ =
      fst <$> Utils.searchRecursiveWithLimit lim q
      where
      -- We actually make two queries!
      q = fileEntityKinds fileId .| fileEntityXRefKinds fileId
  
    augmentSymbols _ kinds refs defs _ =
        (refs_result, defs_result, ())
       where
       (refs_result, defs_result) =
        extendAttributes (\_ ent -> ent) attrMap refs defs
        where
        attrMap = Map.fromList
          [ (entity, toAttributes kind)
          | (entity, kind) <- kinds
          ]
        toAttributes kind = Attributes $ Map.singleton "symbolKind"
          (Attribute_aInteger (fromIntegral
            (fromThriftEnum $ symbolKindToSymbolKind kind)))
  
  
    queryMetadataForFile _ _ _ _ _ = pure []
  
  fileEntityKinds :: Glean.IdOf Src.File -> Angle.Angle EntityKindLabel
  fileEntityKinds fileId =
    vars $ \(entity :: Angle Code.Entity) (kind :: Angle Code.SymbolKind) ->
      tuple (entity, kind) `where_` [
        wild .= predicate @Code.FileEntityKinds (
              rec $
                field @"file" (asPredicate (factId fileId)) $
                field @"entity" entity $
                field @"kind" kind
              end
        )
      ]
  
  fileEntityXRefKinds :: Glean.IdOf Src.File -> Angle.Angle EntityKindLabel
  fileEntityXRefKinds fileId =
    vars $ \(entity :: Angle Code.Entity) (kind :: Angle Code.SymbolKind) ->
      tuple (entity, kind) `where_` [
        wild .= predicate @Code.FileEntityXRefKinds (
              rec $
                field @"file" (asPredicate (factId fileId)) $
                field @"entity" entity $
                field @"kind" kind
              end
        )
      ]
  
  -- | Type safe mapping from the SymbolKind type defined in codemarkup (which
  -- generates a thrift type), and the client-exposed kind.
  --
  -- We don't want to expose something that depends on how Glean represents enums
  --
  symbolKindToSymbolKind :: Code.SymbolKind -> Glass.SymbolKind
  symbolKindToSymbolKind k = case k of
    Code.SymbolKind_Package -> Glass.SymbolKind_Package
    Code.SymbolKind_Type -> Glass.SymbolKind_Type
    Code.SymbolKind_Value -> Glass.SymbolKind_Value
    Code.SymbolKind_File -> Glass.SymbolKind_File
    Code.SymbolKind_Module -> Glass.SymbolKind_Module
    Code.SymbolKind_Namespace -> Glass.SymbolKind_Namespace
    Code.SymbolKind_Class_ -> Glass.SymbolKind_Class_
    Code.SymbolKind_Method -> Glass.SymbolKind_Method
    Code.SymbolKind_Property -> Glass.SymbolKind_Property
    Code.SymbolKind_Field -> Glass.SymbolKind_Field
    Code.SymbolKind_Constructor -> Glass.SymbolKind_Constructor
    Code.SymbolKind_Enum_ -> Glass.SymbolKind_Enum
    Code.SymbolKind_Interface -> Glass.SymbolKind_Interface
    Code.SymbolKind_Function -> Glass.SymbolKind_Function
    Code.SymbolKind_Variable -> Glass.SymbolKind_Variable
    Code.SymbolKind_Constant -> Glass.SymbolKind_Constant
    Code.SymbolKind_String -> Glass.SymbolKind_String
    Code.SymbolKind_Number -> Glass.SymbolKind_Number
    Code.SymbolKind_Boolean -> Glass.SymbolKind_Boolean
    Code.SymbolKind_Array -> Glass.SymbolKind_Array
    Code.SymbolKind_Object_ -> Glass.SymbolKind_Object
    Code.SymbolKind_Key -> Glass.SymbolKind_Key
    Code.SymbolKind_Null -> Glass.SymbolKind_Null
    Code.SymbolKind_Enumerator -> Glass.SymbolKind_Enumerator
    Code.SymbolKind_Struct -> Glass.SymbolKind_Struct
    Code.SymbolKind_Event -> Glass.SymbolKind_Event
    Code.SymbolKind_Operator -> Glass.SymbolKind_Operator
    Code.SymbolKind_TypeParameter -> Glass.SymbolKind_TypeParameter
    Code.SymbolKind_Union -> Glass.SymbolKind_Union
    Code.SymbolKind_Macro -> Glass.SymbolKind_Macro
    Code.SymbolKind_Trait -> Glass.SymbolKind_Trait
    Code.SymbolKind_Fragment -> Glass.SymbolKind_Fragment
    Code.SymbolKind_Operation -> Glass.SymbolKind_Operation
    Code.SymbolKind_Directive -> Glass.SymbolKind_Directive
    Code.SymbolKind__UNKNOWN n -> Glass.SymbolKind__UNKNOWN n
  
  -- | Type safe mapping from the client-exposed SymbolKind type to the SymbolKind
  -- defined in codemarkup (which generates a thrift type).
  --
  -- We don't want to expose something that depends on how Glean represents enums
  --
  symbolKindFromSymbolKind :: Glass.SymbolKind -> Code.SymbolKind
  symbolKindFromSymbolKind k = case k of
    Glass.SymbolKind_Package -> Code.SymbolKind_Package
    Glass.SymbolKind_Type -> Code.SymbolKind_Type
    Glass.SymbolKind_Value -> Code.SymbolKind_Value
    Glass.SymbolKind_File -> Code.SymbolKind_File
    Glass.SymbolKind_Module -> Code.SymbolKind_Module
    Glass.SymbolKind_Namespace -> Code.SymbolKind_Namespace
    Glass.SymbolKind_Class_ -> Code.SymbolKind_Class_
    Glass.SymbolKind_Method -> Code.SymbolKind_Method
    Glass.SymbolKind_Property -> Code.SymbolKind_Property
    Glass.SymbolKind_Field -> Code.SymbolKind_Field
    Glass.SymbolKind_Constructor -> Code.SymbolKind_Constructor
    Glass.SymbolKind_Enum -> Code.SymbolKind_Enum_
    Glass.SymbolKind_Interface -> Code.SymbolKind_Interface
    Glass.SymbolKind_Function -> Code.SymbolKind_Function
    Glass.SymbolKind_Variable -> Code.SymbolKind_Variable
    Glass.SymbolKind_Constant -> Code.SymbolKind_Constant
    Glass.SymbolKind_String -> Code.SymbolKind_String
    Glass.SymbolKind_Number -> Code.SymbolKind_Number
    Glass.SymbolKind_Boolean -> Code.SymbolKind_Boolean
    Glass.SymbolKind_Array -> Code.SymbolKind_Array
    Glass.SymbolKind_Object -> Code.SymbolKind_Object_
    Glass.SymbolKind_Key -> Code.SymbolKind_Key
    Glass.SymbolKind_Null -> Code.SymbolKind_Null
    Glass.SymbolKind_Enumerator -> Code.SymbolKind_Enumerator
    Glass.SymbolKind_Struct -> Code.SymbolKind_Struct
    Glass.SymbolKind_Event -> Code.SymbolKind_Event
    Glass.SymbolKind_Operator -> Code.SymbolKind_Operator
    Glass.SymbolKind_TypeParameter -> Code.SymbolKind_TypeParameter
    Glass.SymbolKind_Union -> Code.SymbolKind_Union
    Glass.SymbolKind_Macro -> Code.SymbolKind_Macro
    Glass.SymbolKind_Trait -> Code.SymbolKind_Trait
    Glass.SymbolKind_Fragment -> Code.SymbolKind_Fragment
    Glass.SymbolKind_Operation -> Code.SymbolKind_Operation
    Glass.SymbolKind_Directive -> Code.SymbolKind_Directive
    Glass.SymbolKind__UNKNOWN x -> toThriftEnum x -- this might throw
  