# Copyright (c) Meta Platforms, Inc. and affiliates. schema codemetrics.1 { import cxx1 import code.24 import code.cxx import code.hack import codemarkup.hack import hack # # 'target' is referenced in the definition of 'source' # # Note that this is the dual of codemarkup.EntitySource, which finds # references *to* an entity. # predicate ReferencesFrom : { source : code.Entity, target : code.Entity } ( { { cxx = S }, { cxx = T } } where CxxReferencesFrom { S, T } ) | ( { { hack = S }, { hack = T } } where HackReferencesFrom { S, T } ) # # For cxx we want to use cxx1.DeclarationTargets which efficiently # maps declarations to references, and we also want to account for # out-of-line parts of the definition (methods, in particular). # predicate CxxReferencesFrom : { source : code.cxx.Entity, target : code.cxx.Entity } ( { { defn = { record_ = R }}, { decl = T } } where CxxRecordReference { R, T } ) | ( { { defn = { objcContainer = C }}, { decl = T } } where CxxObjcContainerReference { C, T } ) predicate CxxObjcContainerReference : { source : cxx1.ObjcContainerDefinition, target : cxx1.Declaration } { { declaration = Decl, members = Members : [cxx1.Declaration] }, D } where # Include references from: # - the definition itself # - the members # - members in the implementation DeclOrMember = ( {objcContainer = Decl} : cxx1.Declaration | Members[..] | ( cxx1.ObjcInterfaceToImplementation { Decl, Impl }; cxx1.ObjcContainerDefinition { declaration = Impl, members = ImplMembers : [cxx1.Declaration] }; ImplMembers[..] ) ); cxx1.DeclarationTargets { source = DeclOrMember, targets = T }; D = T[..]; # We don't care about references to namespaces !({ namespace_ = _ } = D); # We don't care about references to things in this class { id = Id } = Decl; !({ objcMethod = { container = Id } } = D); !({ objcProperty = { container = Id } } = D); # We don't care about references to the class itself !({ objcContainer = Decl } = D); predicate CxxRecordReference : { source : cxx1.RecordDefinition, target : cxx1.Declaration } { Source, D } where cxx1.DefToBaseDecl { defn = { record_ = Source }, decl = { record_ = Decl } }; { name = QName } = Decl; { members = Members : [cxx1.Declaration] } = Source; # Look at the declaration itself and the members, because some of # them might be out-of-line DeclOrMember = ({record_ = Decl} : cxx1.Declaration | Members[..]); # Targets for each declaration cxx1.DeclarationTargets { source = DeclOrMember, targets = T }; D = T[..]; # We don't care about references to namespaces !({ namespace_ = _ } = D); # We don't care about references to things in this class cxx1.DeclarationScope { decl = D, scope = Scope }; !({ recordWithAccess = { record = QName }} = Scope); # We don't care about references to the class itself !({ record_ = Decl } = D); predicate HackReferencesFrom : { source : code.hack.Entity, target : code.hack.Entity } { { decl = Decl }, { decl = T } } where { container = { class_ = C } } = Decl; hack.DeclarationTarget { Decl, T }; # Filter out references to this class !(T = Decl); # Filter out references to members of this class !(codemarkup.hack.HackContainsParentEntity { child = { decl = T }, parent = { decl = Parent } }; { container = { class_ = C } } = Parent ) predicate ReferencesTo : { target : code.Entity, source : code.Entity } ( { { cxx = T }, { cxx = S } } where CxxReferencesTo { T, S } ) | ( { { hack = T }, { hack = S } } where HackReferencesTo { T, S } ) predicate CxxReferencesTo : { target : code.cxx.Entity, source : code.cxx.Entity } ( { { defn = { record_ = R }}, { decl = S } } where CxxRecordReferenceTo { R, S } ) | ( { { defn = { objcContainer = R }}, { decl = S } } where CxxObjcReferencesTo { R, S } ) predicate CxxRecordReferenceTo : { target : cxx1.RecordDefinition, source : cxx1.Declaration, } { Target, D } where cxx1.DefToBaseDecl { defn = { record_ = Target }, decl = { record_ = Decl } }; { name = QName } = Decl; cxx1.DeclarationSources { target = { record_ = Decl }, sources = S }; D = S[..]; # We don't care about references from things in this class cxx1.DeclarationScope { decl = D, scope = Scope }; !({ recordWithAccess = { record = QName }} = Scope); # We don't care about references from the class itself !({ record_ = Decl } = D); predicate CxxObjcReferencesTo : { target : cxx1.ObjcContainerDefinition, source : cxx1.Declaration, } { Target, D } where { declaration = Decl } = Target; cxx1.DeclarationSources { target = { objcContainer = Decl }, sources = S }; D = S[..]; # We don't care about references from things in this class { id = Id } = Decl; !({ objcMethod = { container = Id } } = D); !({ objcProperty = { container = Id } } = D); # We don't care about references from the class itself !({ objcContainer = Decl } = D); predicate HackReferencesTo : { target : code.hack.Entity, source : code.hack.Entity } { { decl = Decl }, { decl = S } } where { container = { class_ = C } } = Decl; hack.DeclarationSource { Decl, S }; # Filter out references from this class !(S = Decl); # Filter out references from members of this class !(codemarkup.hack.HackContainsParentEntity { child = { decl = S }, parent = { decl = Parent } }; { container = { class_ = C } } = Parent ); # Ignore references from methods, because they are already # counted as references from the enclosing class !({ method = _ } = S); }