# Copyright (c) Meta Platforms, Inc. and affiliates. schema codemarkup.hack.2 { import src import code.24 import code.hack import hack import codemarkup.types import fbthrift predicate HackResolveLocation: { location: codemarkup.types.Location, entity: code.hack.Entity, } { { Name, File, { span = Span }, {just = {file = File, span = NameSpan}}}, { decl = Decl } } where hack.FileDeclarations { file = File, declarations = Ds }; Decl = Ds[..]; hack.DeclarationName Decl -> (hack.Name Name); hack.DeclarationSpan { declaration = Decl, file = File, span = Span }; hack.DeclarationLocation { declaration = Decl, file = File, span = NameSpan }; # Finding entities' locations predicate HackEntityLocation: { entity: code.hack.Entity, location: codemarkup.types.Location, } { { decl = D }, { Name, File, { span = Span }, nothing } } where hack.DeclarationName D -> (hack.Name Name); hack.DeclarationSpan { declaration = D, file = File, span = Span } # Finding references in a file predicate HackFileEntityXRefLocations: { file: src.File, xref: codemarkup.types.XRefLocation, entity: code.hack.Entity, } { File, { Location, { span = Src } }, { decl = D } } where hack.FileXRefs { file = File, xrefs = XRefs }; hack.XRef { target = { declaration = D }, ranges = Uses } = elements XRefs; hack.DeclarationName D -> (hack.Name TargetName); hack.DeclarationLocation { declaration = D, file = TargetFile, span = TargetSpan }; Location = codemarkup.types.Location { TargetName, TargetFile, { span = TargetSpan }, nothing }; Sources = prim.relToAbsByteSpans Uses; Src = Sources[..]; predicate HackFileEntityXRefSpans: { file: src.File, span: src.ByteSpan, entity: code.hack.Entity, } { File, Src, { decl = D } } where hack.FileXRefs { file = File, xrefs = XRefs }; hack.XRef { target = { declaration = D }, ranges = Uses } = elements XRefs; Sources = prim.relToAbsByteSpans Uses; Src = Sources[..] # # Language entity uses # predicate HackIdlEntityUses: { target: code.Entity, file: src.File, span: src.ByteSpan, } { Target, File, Span} where { fbthrift = { decl = Thrift } } = Target; hack.ThriftToHack { Thrift, Hack }; HackEntityUses { { decl = Hack }, File, Span } predicate HackEntityUses: { target: code.hack.Entity, file: src.File, span: src.ByteSpan, } { { decl = D }, File, Span } where hack.TargetUses { target = { declaration = D }, file = File, uses = Uses }; Spans = prim.relToAbsByteSpans Uses; Span = Spans[..]; predicate HackEntityKind: { entity: code.hack.Entity, kind: codemarkup.types.SymbolKind, } { {decl = Decl}, Kind } where ({ classConst = _ } = Decl; Constant = Kind) | ({ container = C } = Decl; ({ class_ = _ } = C; Class_ = Kind) | ({ enum_ = _ } = C; Enum_ = Kind) | ({ interface_ = _ } = C; Interface = Kind) | ({ trait = _ } = C; Trait = Kind) ) | ({ enumerator = _ } = Decl; Field = Kind) | ({ function_ = _ } = Decl; Function = Kind) | ({ globalConst = _ } = Decl; Constant = Kind) | ({ method = _ } = Decl; Method = Kind) | ({ namespace_ = _ } = Decl; Namespace = Kind) | ({ property_ = _ } = Decl; Property = Kind) | ({ typeConst = _ } = Decl; Type = Kind) | ({ typedef_ = _ } = Decl; Type = Kind) | ({ module = _ } = Decl; Module = Kind) predicate HackEntityInfo: { entity: code.hack.Entity, info: codemarkup.types.SymbolInfo, } { {decl = Decl}, { kind = Kind, isAbstract = Abs } } where HackEntityKind { {decl = Decl}, Kind }; ( Method = Kind; { method = M } = Decl; hack.MethodDefinition { declaration = M, isAbstract = Abs } ) | ( Property = Kind; { property_ = P } = Decl; hack.PropertyDefinition { declaration = P, isAbstract = Abs } ) | ( Constant = Kind; { classConst = C } = Decl; hack.ClassConstDefinition { declaration = C, value = V }; ( nothing = V; true = Abs ) | ( { just = _ } = V; false = Abs ) ) | ( Type = Kind; { typeConst = T } = Decl; hack.TypeConstDefinition { declaration = T, kind = TCKind }; ( Concrete = TCKind; false = Abs ) | ( Abstract = TCKind; true = Abs) | ( PartiallyAbstract = TCKind; true = Abs) ) | ( false = Abs; (Class_ = Kind) | (Constant = Kind; { globalConst = _ } = Decl) | (Enum_ = Kind) | (Interface = Kind) | (Trait = Kind) | (Function = Kind) | (Namespace = Kind) | (Type = Kind; { typedef_ = _ } = Decl) | (Module = Kind) | (Field = Kind) ) # # Annotations # predicate HackAnnotation : { entity: code.hack.Entity, anns: code.hack.Annotations, } { { decl = D }, { attributes = A }} where ( { container = C } = D; ( { class_ = Decl } = C; hack.ClassDefinition { declaration = Decl, attributes = A } ) | ( { enum_ = Decl } = C; hack.EnumDefinition { declaration = Decl, attributes = A } ) | ( { interface_ = Decl } = C; hack.InterfaceDefinition { declaration = Decl, attributes = A } ) | ( { trait = Decl } = C; hack.TraitDefinition { declaration = Decl, attributes = A } ) ) | ( { method = Decl } = D; hack.MethodDefinition { declaration = Decl, attributes = A } ) | ( { function_ = Decl } = D; hack.FunctionDefinition { declaration = Decl, attributes = A } ) | ( { property_ = Decl } = D; hack.PropertyDefinition {declaration = Decl, attributes = A } ) | ( { typeConst = Decl } = D; hack.TypeConstDefinition { declaration = Decl, attributes=A } ) | ( { typedef_ = Decl } = D; hack.TypedefDefinition { declaration = Decl, attributes = A } ) | ( { module = Decl } = D; hack.ModuleDefinition { declaration = Decl, attributes = A } ) # # Visibility # # just the visibility attributes predicate HackVisibility : { entity: code.hack.Entity, visibility: codemarkup.types.Visibility, } { { decl = D }, V } where ( { method = Decl } = D; hack.MethodDefinition { declaration = Decl, visibility = Vis} ) | ( { property_ = Decl } = D; hack.PropertyDefinition { declaration = Decl, visibility = Vis} ) | ( # optional `internal` modifier on things that are contained by a module ( { function_ = Decl } = D; hack.FunctionDefinition { declaration = Decl, module_ = M } ) | ( { typedef_ = Decl } = D; hack.TypedefDefinition { declaration = Decl, module_ = M } ) | ( { container = Decl } = D; ( { class_ = CDecl } = Decl; hack.ClassDefinition { declaration = CDecl, module_ = M } ) | ( { enum_ = CDecl } = Decl; hack.EnumDefinition { declaration = CDecl, module_ = M } ) | ( { interface_ = CDecl } = Decl; hack.InterfaceDefinition { declaration = CDecl, module_ = M } ) | ( { trait = CDecl } = Decl; hack.TraitDefinition { declaration = CDecl, module_ = M } ) ); { just = { internal = true } } = M; Internal = Vis; ) | ( { classConst = _ } = D; Public = Vis; ) | ( { typeConst = _ } = D; Public = Vis; ); FromHackVisibility { Vis, V }; # helper from Hack visibility to the codemarkup.types version predicate FromHackVisibility: { hack : hack.Visibility, out : codemarkup.types.Visibility } { In, Out } where ( Public = In; Public ) | ( Private = In; Private ) | ( Protected = In; Protected ) | ( Internal = In; Internal ) = Out; # Sets of modifier keywords on a symbol predicate HackModifiers: { entity: code.hack.Entity, modifiers: codemarkup.types.Modifiers } { { decl = Decl }, Modifiers } where ( { method = Method } = Decl; hack.MethodDefinition { declaration = Method, isAbstract = Abstract, isFinal = Final, isAsync = Async, isStatic = Static }; Readonly = false; Const = false; ) | ( { property_ = Property } = Decl; hack.PropertyDefinition { declaration = Property, isAbstract = Abstract, isFinal = Final, isStatic = Static }; Async = false; Readonly = false; Const = false; ) | ( { function_ = Func } = Decl; hack.FunctionDefinition { declaration = Func, isAsync = Async }; Abstract = false; Final = false; Static = false; Readonly = false; Const = false; ) | ( { container = { class_ = Class } } = Decl; hack.ClassDefinition { declaration = Class, isAbstract = Abstract, isFinal = Final }; Async = false; Static = false; Readonly = false; Const = false; ) | ( { classConst = _ } = Decl; Async = false; Static = false; Abstract = false; Final = false; Const = true; ) | ( { typeConst = _ } = Decl; Async = false; Static = false; Abstract = false; Final = false; Const = true; ) | ( { globalConst = _ } = Decl; Async = false; Static = true; Abstract = false; Final = false; Const = true; ); Volatile = false; Virtual = false; Inline = false; Readonly = false; Mutable = false; { Abstract, Final, Async, Static, Readonly, Const, Mutable, Volatile, Virtual, Inline } = Modifiers; # # Relations # # child `contained by` parent # # - classConst, method, property, typeConst -> container # - enumerator (field) -> enum # - direct member of any namespace -> namespace # predicate HackContainsParentEntity : { child: code.hack.Entity, parent: code.hack.Entity, } { { decl = Child }, { decl = Parent } } where ( ( { classConst = Decl } = Child; hack.ClassConstDeclaration { container = Container } = Decl; ) | ( { method = Decl } = Child; hack.MethodDeclaration { container = Container } = Decl; ) | ( { property_ = Decl } = Child; hack.PropertyDeclaration { container = Container } = Decl; ) | ( { typeConst = Decl } = Child; hack.TypeConstDeclaration { container = Container } = Decl; ); Parent = hack.Declaration { container = Container } ) | ( { enumerator = { enumeration = Enumeration } } = Child; Parent = hack.Declaration { container = {enum_ = Enumeration} } ) | ( hack.DeclarationNamespace { decl = Child, namespace_ = Name }; Parent = hack.Declaration { namespace_ = {name = Name }} ) | ( hack.ModuleParent { Child, Module }; { module = Module } = Parent ) # parent contains child # Enums inherits from HH\builtinEnum predicate HackContainsChildEntity : { parent: code.hack.Entity, child: code.hack.Entity } { { decl = Container }, { decl = Member } } where ( ( { container = { class_ = Class }} = Container; hack.ClassDefinition { declaration = Class, members = Members }; ) | ( { container = { interface_ = Interface }} = Container; hack.InterfaceDefinition { declaration = Interface, members = Members }; ) | ( { container = { trait = Trait }} = Container; hack.TraitDefinition { declaration = Trait, members = Members }; ); Member = Members[..] ) | ( { container = { enum_ = EnumDecl }} = Container; hack.EnumDefinition { declaration = EnumDecl, enumerators = Enumerators }; Enumerator = Enumerators[..]; Member = hack.Declaration {enumerator = Enumerator} ) | ( { namespace_ = {name=Name} } = Container; hack.NamespaceMember { namespace_ = Name, decl = Member} ) | ( { module = Module } = Container; hack.ModuleChild { Module, Member }; ) # parent extended by child predicate HackExtendsChildEntity : { parent : code.hack.Entity, child : code.hack.Entity } { { decl = Parent }, { decl = Child } } where ( { container = P } = Parent; hack.ContainerChild { container = P, child = C }; { container = C } = Child; ) | ( hack.MethodOverridden{base=P, derived=C}; { method = P } = Parent; { method = C } = Child ) | ( { container = { class_ = { name = { name = "BuiltinEnum", namespace_ = { just = { name = "HH" } } } } } } = Parent; { container = { enum_ = _ } } = Child ) # child extends parent predicate HackExtendsParentEntity : { child : code.hack.Entity, parent : code.hack.Entity } { { decl = Child }, { decl = Parent } } where ( { container = C } = Child; hack.ContainerParent { C, P }; { container = P } = Parent ) | ( hack.MethodOverrides { derived=C, base=P }; { method = C } = Child; { method = P } = Parent ) | ( { container = { enum_ = _ } } = Child; { container = { class_ = { name = { name = "BuiltinEnum", namespace_ = { just = { name = "HH" } } } } } } = Parent ) # All method in HH\builtinEnum which are inherited by enum types predicate HackEnumInheritedMembers : { member_ : hack.MethodDeclaration } { member_ = Md } where C : hack.ClassDefinition; C.declaration.name.name = "BuiltinEnum"; C.declaration.name.namespace_.just?.name = "HH"; C.members = Ms; { method = Md } = Ms[..] # Inherited parents but drop those with "HideFromDocs" annotations # Used to reduce the search space to "interesting" containers only predicate HackExtendsParentEntityConcise: { child : code.hack.Entity, parent : code.hack.Entity } { Child, Parent } where HackExtendsParentEntity { Child, Parent }; !(EntityHasHideFromDocsAttr Parent) # Asserts the entity has the "HideFromDocs" attribute # (this is an example of where efficient set membership would be useful) predicate EntityHasHideFromDocsAttr: code.hack.Entity Entity where HackAnnotation { Entity, { attributes = As } }; hack.UserAttribute { name = "HideFromDocs" } = As[..] # documentation spans predicate HackEntityDocumentation : { entity : code.hack.Entity, file : src.File, span : src.ByteSpan, } { E, F, S } where { decl = D } = E; ( hack.DeclarationComment{ D, F, S } ) | # if this is a method, also check for docs on the base of any override ( { method = Derived } = D; hack.MethodOverrides { Derived, Base, _ }; hack.DeclarationComment { { method = Base }, F, S } ) predicate HackFileCall : { file: src.File, callee_span: src.ByteSpan, call_args: [code.CallArgument], callee_xref: maybe code.Entity, dispatch_arg: maybe code.CallArgument, receiver_type: maybe code.Entity, } {File, Span, CodeArgs, CalleeEntity, DispatchArg, StaticType } where ( hack.FileCall { File, Span, HackArgs, CalleeXRef, HackDispatchArg, HackStaticType, _ }; ConvertCallArguments { HackArgs, CodeArgs}; ConvertMaybeCallArguments { HackDispatchArg, DispatchArg }; ConvertCalleeForFileCall { File, Span, CalleeXRef, CalleeEntity }; ConvertStaticType { HackStaticType, StaticType }; ) # (internal) helper predicate for CallArgument # Manually unrolled to lists of <=6 arguments predicate ConvertCallArguments : { hackCallArguments: [hack.CallArgument], codeCallArguments: [code.CallArgument] } {HackArgs, CodeArgs} where ( ( [] = HackArgs; [] = CodeArgs ) | ( [hack.CallArgument{Span_rel, Argument}] = HackArgs; ConvertArgument{Argument, CodeArgument}; [Span] = prim.relToAbsByteSpans [Span_rel]; CodeArgs = [code.CallArgument{nothing, Span, CodeArgument}] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2} ] = HackArgs; [Span, Span2] = prim.relToAbsByteSpans [Span_rel, Span2_rel]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3} ] = HackArgs; [Span, Span2, Span3] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4} ] = HackArgs; [Span, Span2, Span3, Span4] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4}, hack.CallArgument{Span5_rel, Argument5} ] = HackArgs; [Span, Span2, Span3, Span4, Span5] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel, Span5_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; ConvertArgument{Argument5, CodeArgument5}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4}, code.CallArgument{nothing, Span5, CodeArgument5} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4}, hack.CallArgument{Span5_rel, Argument5}, hack.CallArgument{Span6_rel, Argument6} ] = HackArgs; [Span, Span2, Span3, Span4, Span5, Span6] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel, Span5_rel, Span6_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; ConvertArgument{Argument5, CodeArgument5}; ConvertArgument{Argument6, CodeArgument6}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4}, code.CallArgument{nothing, Span5, CodeArgument5}, code.CallArgument{nothing, Span6, CodeArgument6} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4}, hack.CallArgument{Span5_rel, Argument5}, hack.CallArgument{Span6_rel, Argument6}, hack.CallArgument{Span7_rel, Argument7} ] = HackArgs; [Span, Span2, Span3, Span4, Span5, Span6, Span7] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel, Span5_rel, Span6_rel, Span7_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; ConvertArgument{Argument5, CodeArgument5}; ConvertArgument{Argument6, CodeArgument6}; ConvertArgument{Argument7, CodeArgument7}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4}, code.CallArgument{nothing, Span5, CodeArgument5}, code.CallArgument{nothing, Span6, CodeArgument6}, code.CallArgument{nothing, Span7, CodeArgument7} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4}, hack.CallArgument{Span5_rel, Argument5}, hack.CallArgument{Span6_rel, Argument6}, hack.CallArgument{Span7_rel, Argument7}, hack.CallArgument{Span8_rel, Argument8} ] = HackArgs; [Span, Span2, Span3, Span4, Span5, Span6, Span7, Span8] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel, Span5_rel, Span6_rel, Span7_rel, Span8_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; ConvertArgument{Argument5, CodeArgument5}; ConvertArgument{Argument6, CodeArgument6}; ConvertArgument{Argument7, CodeArgument7}; ConvertArgument{Argument8, CodeArgument8}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4}, code.CallArgument{nothing, Span5, CodeArgument5}, code.CallArgument{nothing, Span6, CodeArgument6}, code.CallArgument{nothing, Span7, CodeArgument7}, code.CallArgument{nothing, Span8, CodeArgument8} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4}, hack.CallArgument{Span5_rel, Argument5}, hack.CallArgument{Span6_rel, Argument6}, hack.CallArgument{Span7_rel, Argument7}, hack.CallArgument{Span8_rel, Argument8}, hack.CallArgument{Span9_rel, Argument9} ] = HackArgs; [Span, Span2, Span3, Span4, Span5, Span6, Span7, Span8, Span9] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel, Span5_rel, Span6_rel, Span7_rel, Span8_rel, Span9_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; ConvertArgument{Argument5, CodeArgument5}; ConvertArgument{Argument6, CodeArgument6}; ConvertArgument{Argument7, CodeArgument7}; ConvertArgument{Argument8, CodeArgument8}; ConvertArgument{Argument9, CodeArgument9}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4}, code.CallArgument{nothing, Span5, CodeArgument5}, code.CallArgument{nothing, Span6, CodeArgument6}, code.CallArgument{nothing, Span7, CodeArgument7}, code.CallArgument{nothing, Span8, CodeArgument8}, code.CallArgument{nothing, Span9, CodeArgument9} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4}, hack.CallArgument{Span5_rel, Argument5}, hack.CallArgument{Span6_rel, Argument6}, hack.CallArgument{Span7_rel, Argument7}, hack.CallArgument{Span8_rel, Argument8}, hack.CallArgument{Span9_rel, Argument9}, hack.CallArgument{Span10_rel, Argument10} ] = HackArgs; [Span, Span2, Span3, Span4, Span5, Span6, Span7, Span8, Span9, Span10] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel, Span5_rel, Span6_rel, Span7_rel, Span8_rel, Span9_rel, Span10_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; ConvertArgument{Argument5, CodeArgument5}; ConvertArgument{Argument6, CodeArgument6}; ConvertArgument{Argument7, CodeArgument7}; ConvertArgument{Argument8, CodeArgument8}; ConvertArgument{Argument9, CodeArgument9}; ConvertArgument{Argument10, CodeArgument10}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4}, code.CallArgument{nothing, Span5, CodeArgument5}, code.CallArgument{nothing, Span6, CodeArgument6}, code.CallArgument{nothing, Span7, CodeArgument7}, code.CallArgument{nothing, Span8, CodeArgument8}, code.CallArgument{nothing, Span9, CodeArgument9}, code.CallArgument{nothing, Span10, CodeArgument10} ] ) | ( [ hack.CallArgument{Span_rel, Argument}, hack.CallArgument{Span2_rel, Argument2}, hack.CallArgument{Span3_rel, Argument3}, hack.CallArgument{Span4_rel, Argument4}, hack.CallArgument{Span5_rel, Argument5}, hack.CallArgument{Span6_rel, Argument6}, hack.CallArgument{Span7_rel, Argument7}, hack.CallArgument{Span8_rel, Argument8}, hack.CallArgument{Span9_rel, Argument9}, hack.CallArgument{Span10_rel, Argument10}, hack.CallArgument{Span11_rel, Argument11} ] = HackArgs; [Span, Span2, Span3, Span4, Span5, Span6, Span7, Span8, Span9, Span10, Span11] = prim.relToAbsByteSpans [ Span_rel, Span2_rel, Span3_rel, Span4_rel, Span5_rel, Span6_rel, Span7_rel, Span8_rel, Span9_rel, Span10_rel, Span11_rel ]; ConvertArgument{Argument, CodeArgument}; ConvertArgument{Argument2, CodeArgument2}; ConvertArgument{Argument3, CodeArgument3}; ConvertArgument{Argument4, CodeArgument4}; ConvertArgument{Argument5, CodeArgument5}; ConvertArgument{Argument6, CodeArgument6}; ConvertArgument{Argument7, CodeArgument7}; ConvertArgument{Argument8, CodeArgument8}; ConvertArgument{Argument9, CodeArgument9}; ConvertArgument{Argument10, CodeArgument10}; ConvertArgument{Argument11, CodeArgument11}; CodeArgs = [ code.CallArgument{nothing, Span, CodeArgument}, code.CallArgument{nothing, Span2, CodeArgument2}, code.CallArgument{nothing, Span3, CodeArgument3}, code.CallArgument{nothing, Span4, CodeArgument4}, code.CallArgument{nothing, Span5, CodeArgument5}, code.CallArgument{nothing, Span6, CodeArgument6}, code.CallArgument{nothing, Span7, CodeArgument7}, code.CallArgument{nothing, Span8, CodeArgument8}, code.CallArgument{nothing, Span9, CodeArgument9}, code.CallArgument{nothing, Span10, CodeArgument10}, code.CallArgument{nothing, Span11, CodeArgument11} ] ) ) predicate ConvertArgument : { hackArgument : maybe hack.Argument , codeArgument : maybe code.Argument } {Hack, Code} where ( { just = { lit = hack.StringLiteral L } } = Hack; { just = { lit = L } } = Code; ) | ( { just = { xref = { declaration = L } } } = Hack; { just = { xref = { hack = code.hack.Entity { decl = L } } } } = Code; ) | ( { just = { xref = { occurrence = _ } } } = Hack; nothing = Code; ) | ( nothing = Hack ; nothing = Code; ) predicate ConvertMaybeCallArguments : { hackArgument : maybe hack.CallArgument , codeArgument : maybe code.CallArgument } { Hack, Code } where ( {just = {Span_rel, HArgument}} = Hack; [Span] = prim.relToAbsByteSpans [Span_rel]; ConvertArgument{HArgument, CArgument}; {just = {nothing, Span, CArgument}} = Code; ) | ( nothing = Hack; nothing = Code; ) predicate ConvertCallee : { hackCallee : maybe hack.XRefTarget , codeCallee : maybe code.Entity } (D : hack.Declaration; { { just = { declaration = D } }, { just = { hack = { decl = D } } } }) | { nothing, nothing } # T157708437: Unresolved calls with matching resolved entities # **Don't use this predicate as it will go away.** predicate ConvertCalleeForFileCall : { file: src.File, callee_span: src.ByteSpan, hackCallee : maybe hack.XRefTarget , codeCallee : maybe code.Entity } { File, Span, HackCallee, CodeCallee } where ({ just = { declaration = D } } = HackCallee; hack.FileCall { File, Span, _, HackCallee, _, _, _ }; { just = { hack = { decl = D } } } = CodeCallee ) | ({ just = O } = HackCallee; { occurrence = {method = {name = N} } } = O; hack.FileXRefs { File, XRefs }; # Look for resolved occurrences with the same method name in the call { target = {declaration = D }, ranges = Uses } = elements XRefs; { method = { name = N } } = D; Sources = prim.relToAbsByteSpans Uses; S = Sources[..]; src.ByteSpanContains { Span, S }; # Match them with the unresolved occurrence { target = O, ranges = OUses } = elements XRefs; OSources = prim.relToAbsByteSpans OUses; S = OSources[..]; { just = { hack = { decl = D } } } = CodeCallee ) | ( nothing = HackCallee; hack.FileCall { File, Span, _, nothing, _, _, _}; nothing = CodeCallee ) predicate ConvertStaticType : { hackCallee : maybe hack.Declaration , codeCallee : maybe code.Entity } ( D : hack.Declaration; {{ just = D }, { just = { hack = { decl = D } } } }) | { nothing, nothing } predicate HackEntitySource: { target: code.hack.Entity, source: code.hack.Entity, } { {decl=Decl}, {decl=Source}} where hack.DeclarationSource { Decl, Source }; type RequiredRelation = enum { implements_ | extends_ | class_ } predicate HackRequiredConstraint: { entity : code.hack.Entity, requiredRelation : RequiredRelation, required_ : code.hack.Entity } { E, Rel, R } where ( Rel = extends_; RE[..] = R.decl?.container?.class_?; hack.InterfaceDefinition { declaration = E.decl?.container?.interface_?, requireExtends = RE } ) | ( Rel = extends_; RE[..] = R.decl?.container?.class_?; hack.TraitDefinition { declaration = E.decl?.container?.trait?, requireExtends = RE } ) | ( Rel = implements_; RE[..] = R.decl?.container?.interface_?; hack.TraitDefinition { declaration = E.decl?.container?.trait?, requireImplements = RE } ) | ( Rel = class_; RE[..] = R.decl?.container?.class_?; hack.TraitDefinition { declaration = E.decl?.container?.trait?, requireClass = { just = RE } } ) predicate HackEntityModuleName: { entity : code.hack.Entity, name : string } { Decl, Name } where Decl.decl?.module?.name = hack.Name Name predicate HackEntityIdl: { ent : code.hack.Entity, idlEnt : code.IdlEntity, } { E, I } where hack.HackToThrift { from = Hack, to = Thrift }; fbthrift.DeclarationFile { Thrift, fbthrift.File F }; { lang = Thrift, file = F, entity = { just = { fbthrift = { decl = Thrift } } }, range = nothing } = I; { decl = Hack } = E predicate HackInheritedEntities : { container : hack.ContainerDeclaration, member : hack.Declaration, } { Container, Member } where hack.InheritedMembers { container = Container, inheritedMembers = InheritedMembers }; { members = Cluster } = InheritedMembers[..]; Member = Cluster[..] }