packages feed

glean-0.2.0.0: glean/schema/source/erlang.angle

# Copyright (c) Meta Platforms, Inc. and affiliates.

# much of this schema is cargo-culted from ./python.angle

schema erlang.1 {
import src

# Collects all reference to names in a single file.
# There is only one fact of this predicate per source file in the repo.
predicate XRefsViaFqnByFile :
  {
    file : src.File,
    xrefs : [XRefViaFqn],
  }

predicate FunctionDeclaration :
  {
    fqn : Fqn,
    file : src.File,
    span : src.ByteSpan,
  }

predicate DeclarationComment:
  {
    declaration : FunctionDeclaration,
    file : src.File,
    span : src.ByteSpan,
    text : maybe string,
  }

predicate Module :
  {
    file : src.File,
    name : string,
    oncall : maybe string,
    exports : maybe [string],
    behaviours : maybe [string],
    module_doc : maybe string,
    exdoc_link: maybe string,
  }

## types

type Declaration =
  {
    func : FunctionDeclaration |
  }

# fully-qualified name
type Fqn =
  {
    module : string,
    name : string,
    arity : nat,
  }

# A cross reference, or access to a symbol
type XRefViaFqn =
  {
    target : Fqn,
    source : src.ByteSpan,
  }

## derived predicates

predicate DeclarationWithFqn :
  {
    fqn : Fqn,
    declaration : Declaration
  }
  {F, D} where
  D = (
    Declaration { func = { fqn = F } }
  )

predicate DeclarationToFqn: Declaration -> Fqn
D -> Fqn where
{func = { fqn = Fqn }} = D

# All uses of a declaration in a particular file.
# This predicate does not follow references, so if a symbol is used through
# a chain of imports, only the first hop will be present as a fact.
# Querying this predicate by declaration is an efficient way to find immediate
# references
predicate DeclarationUses :
  {
    declaration : Declaration,
    file : src.File,
    span : src.ByteSpan,
  }
  stored {Decl, File, Span} where
  XRefsViaFqnByFile { File, XRefs };
  { target = Fqn, source = Span } = XRefs[..];
  DeclarationWithFqn { fqn = Fqn, declaration = Decl };

predicate DeclarationsByFile :
  {
  file : src.File,
  span : src.ByteSpan,
  declaration : Declaration,
  }
  stored {File, Span, D} where
  D = (
    Declaration { func = { file = File, span = Span } }
  )

predicate DeclarationLocation :
  {
  declaration : Declaration,
  file : src.File,
  span : src.ByteSpan,
  }
  {D, File, Span} where
  D = (
    Declaration { func = { file = File, span = Span } }
  )

predicate DeclarationReference :
  {
    target : Declaration,
    source : Declaration
  }
  { target = T, source = S } where
  DeclarationUses {declaration=T, file=F, span=LittleSpan};
  DeclarationsByFile {declaration=S, file=F, span=BigSpan};
  src.ByteSpanContains {byteSpan=BigSpan, contains=LittleSpan}

predicate NameLowerCase :
  {
    nameLowercase : string,
    name : string,
  }
  stored
  { prim.toLower Str, N } where
   erlang.FunctionDeclaration { fqn = { name = N }};
   N = Str

# identifier to decl index for fast search, makes the name a prefix
predicate SearchByName:
  {
    name : string, # local identifier
    func : Declaration
  } stored
  { Name, { func = Decl } } where
    Decl = erlang.FunctionDeclaration { fqn = { name = Name } };

}