# # Copyright (c) Meta Platforms, Inc. and affiliates. # # # Schema for Java that interops with Kotlin. # Intentionally a breaking change from java.6 # schema java.alpha.1 { import src import javakotlin.alpha type Modifier = enum { abstract_ | default_ | final_ | native_ | private_ | protected_ | public_ | static_ | strictfp_ | synchronized_ | transient_ | volatile_ | } predicate PrimitiveType : { type : string, } predicate TypeVar : { type : javakotlin.alpha.Name, span : src.ByteSpan, } predicate ObjectType : { type : javakotlin.alpha.QName, span : src.ByteSpan, } predicate ArrayType : { contents : Type, span : src.ByteSpan, } # Giving a type structure type BaseType = { object : ObjectType | primitive : PrimitiveType | variable : TypeVar | array : ArrayType | } predicate Type : { baseType : BaseType, typeArgs : [TypeArg], interopType : javakotlin.alpha.Type, span : src.ByteSpan, } predicate TypeArg : { type: Type | wildcard: Wildcard | } # https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1 type Wildcard = { extends_: Type | super_: Type | unbounded: bool | } predicate TypeParam : { name: javakotlin.alpha.Name, extends_: [Type], span : src.ByteSpan, } predicate Annotation : { name : javakotlin.alpha.QName, constructor : javakotlin.alpha.MethodName, constant : maybe string, span : src.ByteSpan, } predicate ParameterDeclaration : { name: javakotlin.alpha.QName, type: Type, annotations: [Annotation], modifier : [Modifier], span : src.ByteSpan, } # A local variable, not parameter predicate LocalDeclaration : { name: javakotlin.alpha.QName, type: Type, annotations : [Annotation], # Maybe get a restricted set here modifier : [Modifier], container : ExecutableDefinition, span : src.ByteSpan, } predicate FieldDeclaration : { name: javakotlin.alpha.QName, type : Type, annotations : [Annotation], modifiers : [Modifier], container : Definition, span : src.ByteSpan, } # Will add a type combining Local and Field later # A constructor declaration predicate ConstructorDeclaration : { name: javakotlin.alpha.MethodName, parameters : [ParameterDeclaration], annotations : [Annotation], modifiers : [Modifier], typeParams: [TypeParam], throws_ : [Type], container : Definition, span : src.ByteSpan, } # A method declaration predicate MethodDeclaration : { name : javakotlin.alpha.MethodName, parameters : [ParameterDeclaration], returnType : Type, annotations : [Annotation], modifiers : [Modifier], typeParams: [TypeParam], throws_ : [Type], container : Definition, span : src.ByteSpan, } # An interface declaration predicate InterfaceDeclaration : { name: javakotlin.alpha.QName, annotations : [Annotation], modifiers : [Modifier], extends_ : [Type], container : maybe Definition, typeParams: [TypeParam], span : src.ByteSpan, file : src.File, } # A class declaration predicate ClassDeclaration : { name : javakotlin.alpha.QName, modifiers : [Modifier], extends_ : maybe Type, implements_ : [Type], annotations : [Annotation], container : maybe Definition, typeParams: [TypeParam], span : src.ByteSpan, file : src.File, } predicate EnumDeclaration : { name: javakotlin.alpha.QName, annotations : [Annotation], modifiers : [Modifier], implements_ : [Type], container : maybe Definition, span : src.ByteSpan, file : src.File, } # just container definitions type Definition = { class_ : ClassDeclaration | interface_ : InterfaceDeclaration | enum_ : EnumDeclaration | } type ExecutableDefinition = { constructor : ConstructorDeclaration | method : MethodDeclaration | } # helper for unwrapping the container Definition type predicate DeclOfDefn: { defn: Definition, decl: Declaration } { Defn, Decl } where ( { class_ = CDecl } = Defn; { class_ = CDecl } = Decl ) | ( { enum_ = CDecl } = Defn; { enum_ = CDecl } = Decl ) | ( { interface_ = CDecl } = Defn; { interface_ = CDecl } = Decl ); # helper for unwrapping the container ExecutableDefinition type predicate DeclOfExecutableDefn: { defn: ExecutableDefinition, decl: Declaration } { Defn, Decl } where ( { constructor = CDecl } = Defn; { ctor = CDecl } = Decl ) | ( { method = MDecl } = Defn; { method = MDecl } = Decl ); # An import, whether specific, an entire package, or static predicate ImportDeclaration : { name : javakotlin.alpha.Name, import_on_demand : bool, static_member : maybe string, path : javakotlin.alpha.Path, location: src.ByteSpan, } # The package specification for a file predicate PackageDeclaration : { name : javakotlin.alpha.Name, annotation: [Annotation], # Path is not required in a package path : maybe javakotlin.alpha.Path, location : src.ByteSpan, } # # Handling xrefs and uses # # Code that is referenced elsewhere, including by an import # Note: params and locals aren't yet xref-able # These are the unique QName/MethodName compoennt of a Declaration. type XRefTarget = { definition_: javakotlin.alpha.QName | ctor_: javakotlin.alpha.MethodName | method_: javakotlin.alpha.MethodName | field_: javakotlin.alpha.QName | } # Lookup the xref entity by its qname and kind predicate XRefTargetDeclaration: { xref: XRefTarget, decl : Declaration } { XRef, Decl } where ( { definition_ = QName } = XRef; QNameToDefinition { QName, Decl } ) | ( { ctor_ = MName } = XRef; CDecl = ConstructorDeclaration { name = MName }; { ctor = CDecl } = Decl ) | ( { method_ = MName } = XRef; MDecl = MethodDeclaration { name = MName }; { method = MDecl } = Decl ) | ( { field_ = QName } = XRef; FDecl = FieldDeclaration { name = QName }; { field = FDecl } = Decl ) # Given a declaration extract its XRefTarget key # Reverses the XRefTargetDeclaration mapping predicate DeclarationXRefTarget: { decl : Declaration, xref: XRefTarget } { Decl, XRef } where ( { field = { name = QName }} = Decl; { field_ = QName } = XRef ) | ( { ctor = { name = MName } } = Decl; { ctor_ = MName } = XRef ) | ( { method = { name = MName } } = Decl; { method_ = MName } = XRef ) | ( { interface_ = { name = QName } } = Decl; { definition_ = QName } = XRef ) | ( { enum_ = { name = QName } } = Decl; { definition_ = QName } = XRef ) | ( { class_ = { name = QName } } = Decl; { definition_ = QName } = XRef ); predicate QNameToDefinition: { name : javakotlin.alpha.QName, defn : java.alpha.Declaration } { QName, Decl } where ( CDecl = ClassDeclaration { name = QName }; { class_ = CDecl } = Decl ) | ( IDecl = InterfaceDeclaration { name = QName }; { interface_ = IDecl } = Decl ) | ( EDecl = EnumDeclaration { name = QName }; { enum_ = EDecl } = Decl ); # References to target code predicate XRef : { target: XRefTarget, ranges: [src.ByteSpan], } # Cross-references to a target within a file predicate FileXRefs : { file : src.File, xrefs : [XRef], } predicate XRefFile : { xref: XRef, file: src.File, } stored {Xref, File} where FileXRefs {file = File, xrefs = Xs}; Xref = Xs[..]; # # Extracting xref uses and targets from type signature components # predicate XRefOfType: { type: Type, decl: Declaration, use: src.ByteSpan, } { Type, Decl, Span } where { baseType = Base, typeArgs = _ } = Type; { object = ObjType } = Base; { type = QName , span = Span } = ObjType; QNameToDefinition { QName, Decl } # If you have a Type, it may also have types contained. # Extract all the types in a typeArgs predicate TypeOfTypeArgs: { typeWithArgs : Type, type: Type } { TypeWithArgs, Type } where { typeArgs = Tys } = TypeWithArgs; ArgTy = Tys[..]; ( { type = Type } = ArgTy ) | ( { wildcard = Wild } = ArgTy; ( { extends_ = Type } ) | ( { super_ = Type } ) = Wild; ); # # Extract type components of declarations. These are all uses (i.e. xrefs) # predicate DeclarationType: { decl: Declaration, type: Type } { Decl, Type } where ( { param = PDecl } = Decl; { type = Ty } = PDecl; ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ) ) | ( { local = LDecl } = Decl; { type = Ty } = LDecl; ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ) ) | ( { field = FDecl } = Decl; { type = Ty } = FDecl; ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ) ) | ( { ctor = CDecl } = Decl; { parameters = PDecls, throws_ = TTypes } = CDecl; Ty = ( { type = T } = PDecls[..]; T ) | ( T = TTypes[..]; T ); ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ); ) | ( { method = MDecl } = Decl; { parameters = PDecls, returnType = RType, throws_ = TTypes } = MDecl; Ty = ( { type = T } = PDecls[..]; T) | ( RType ) | ( T = TTypes[..]; T ); ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ); ) | ( { interface_ = IDecl } = Decl; { extends_ = Types } = IDecl; Ty = Types[..]; ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ); ) | ( { class_ = CDecl } = Decl; { extends_ = { just = ETy }, implements_ = ITys } = CDecl; Ty = ( ETy ) | ( ITys[..] ); ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ); ) | ( { enum_ = EDecl } = Decl; { implements_ = ITys } = EDecl; Ty = ITys[..]; ( Ty = Type ) | ( TypeOfTypeArgs { Ty, Type } ); ); # Uses predicate DeclarationUses : { target : Declaration, file : src.File, uses : [src.ByteSpan], } { Decl, File, Spans } where DeclarationXRefTarget { Decl, XRefTarget }; XRef = XRef { XRefTarget, Spans }; # all xrefs that mention this target XRefFile { XRef, File }; predicate AnnotatedClass : { annotation : Annotation, class_ : ClassDeclaration, } stored { Annotation, Class_ } where Class_ = ClassDeclaration { annotations = As }; Annotation = As[..] # base type has subclass predicate Inheritance : { base: Type, subclass: ClassDeclaration, } stored { Base, Subclass } where Subclass = ClassDeclaration { extends_ = { just = Base } } # interface type has these implemented classes predicate InterfaceInheritance : { interface_name: Type, subclass: ClassDeclaration, } stored { InterfaceName, Subclass } where Subclass = ClassDeclaration { implements_ = Implements_ }; InterfaceName = Implements_[..]; # generic scope "contains" relationship. # e.g. a class contains methods or inner clases predicate ContainsDeclaration: { container: Declaration, member: Declaration } stored { Container, Member } where ( { method = { container = Defn } } ) | ( { ctor = { container = Defn } } ) | ( { field = { container = Defn } } ) | ( { interface_ = { container = { just = Defn } } } ) | ( { enum_ = { container = { just = Defn } } } ) | ( { class_ = { container = { just = Defn } } } ) = Member; DeclOfDefn { Defn, Container } # # codemarkup/glass APIs # # All entities that we expose to navigation or search type Declaration = { param : ParameterDeclaration | local : LocalDeclaration | field : FieldDeclaration | ctor : ConstructorDeclaration | method : MethodDeclaration | interface_ : InterfaceDeclaration | class_ : ClassDeclaration | enum_ : EnumDeclaration } predicate DeclarationAnnotations: { decl : java.alpha.Declaration, annotations : [Annotation] } { Decl, Anns } where ( { param = PDecl } = Decl; { annotations = Anns } = PDecl ) | ( { local = LDecl } = Decl; { annotations = Anns } = LDecl ) | ( { field = FDecl } = Decl; { annotations = Anns } = FDecl ) | ( { ctor = CDecl } = Decl; { annotations = Anns } = CDecl ) | ( { method = MDecl } = Decl; { annotations = Anns } = MDecl ) | ( { interface_ = IDecl } = Decl; { annotations = Anns } = IDecl ) | ( { class_ = CDecl } = Decl; { annotations = Anns } = CDecl ) | ( { enum_ = EDecl } = Decl; { annotations = Anns } = EDecl ); predicate DefinitionLocation: { defn : Definition, name : string, file : src.File, span : src.ByteSpan } { Defn, NameStr, File, Span } where ( { interface_ = IDecl } = Defn; { name = QName, span = Span, file = File } = IDecl; ) | ( { class_ = CDecl } = Defn; { name = QName, span = Span, file = File } = CDecl; ) | ( { enum_ = EDecl } = Defn; { name = QName, span = Span, file = File } = EDecl; ); { name = javakotlin.alpha.Name NameStr } = QName; # Comment(s) that appears at the first of a Declaration predicate DeclarationComment: { declaration : Declaration, file : src.File, span : src.ByteSpan, } predicate DeclarationLocation: { decl : Declaration, name : string, file : src.File, span : src.ByteSpan, } { Decl, NameStr, File, Span } where ( ( { interface_ = IDecl } = Decl; DefinitionLocation { { interface_ = IDecl }, NameStr, File, Span } ) | ( { class_ = CDecl } = Decl; DefinitionLocation { { class_ = CDecl }, NameStr, File, Span } ) | ( { enum_ = EDecl } = Decl; DefinitionLocation { { enum_ = EDecl }, NameStr, File, Span } ) ) | ( ( { method = MDecl } = Decl; Defn = ExecutableDefinition { method = MDecl }; ) | ( { ctor = CDecl } = Decl; Defn = ExecutableDefinition { constructor = CDecl }; ); ExecutableDefnLocation { Defn, NameStr, File, Span } ) | ( { local = LDecl } = Decl; { name = QName, container = EDefn, span = Span } = LDecl; { name = javakotlin.alpha.Name NameStr } = QName; ExecutableDefnLocation { defn = EDefn, file = File } ) | ( { field = FDecl } = Decl; { name = QName, container = Defn, span = Span } = FDecl; { name = javakotlin.alpha.Name NameStr } = QName; DefinitionLocation { defn = Defn, file = File } ) # src.File of a method or constructor is the src.File of its parent container predicate ExecutableDefnLocation: { defn : ExecutableDefinition, name : string, file : src.File, span : src.ByteSpan } { EDefn, NameStr, File, Span } where ( { method = MDecl } = EDefn; { name = MName, span = Span, container = Defn } = MDecl; ) | ( { constructor = CDecl } = EDefn; { name = MName, span = Span, container = Defn } = CDecl; ); DefinitionLocation { defn = Defn, file = File }; javakotlin.alpha.MethodName { name = QName } = MName; { name = javakotlin.alpha.Name NameStr } = QName # decls keyed by file (i.e. file entities) predicate FileDeclarations: { file : src.File, decl : Declaration } stored { File, Decl } where DeclarationLocation { decl = Decl, file = File } # # container relationships # # Container parent (by scope) predicate ParentDeclaration: { child: Declaration, parent: Declaration } { Child, Parent } where # can't do param parents yet ( { local = LDecl } = Child; { container = Defn } = LDecl; DeclOfExecutableDefn { Defn, Parent } ) | ( ( ( { field = FDecl } = Child; { container = Defn } = FDecl ) | ( { ctor = CDecl } = Child; { container = Defn } = CDecl ) | ( { method = MDecl } = Child; { container = Defn } = MDecl ) | ( { class_ = CDecl } = Child; { container = { just = Defn }} = CDecl) | ( { enum_ = CDecl } = Child; { container = { just = Defn }} = CDecl ) | ( { interface_ = CDecl} = Child; { container = { just = Defn}} = CDecl); ); DeclOfDefn { Defn, Parent } ) # extends parent (by inheritance) predicate ExtendsDeclaration: { child: Declaration, parent: Declaration } { Child, Parent } where ( { class_ = CDecl } = Child; ( { extends_ = { just = T } } = CDecl ) | ( { implements_ = Ts } = CDecl; T = Ts[..]); ) | ( { interface_ = IDecl } = Child; ( { extends_ = Ts } = IDecl; T = Ts[..]); ) | ( { enum_ = EDecl } = Child; ( { implements_ = Ts } = EDecl; T = Ts[..]); ); Type { baseType = { object = { type = QName } } } = T; QNameToDefinition { QName, Parent } # extended by child (inheritance) predicate ExtendedByDeclaration: { parent: Declaration, child: Declaration } { Parent, Child } where ( { class_ = { name = QName } } = Parent; ) | ( { interface_ = { name = QName } } = Parent; ) | ( { enum_ = { name = QName } } = Parent; ); T = Type { baseType = { object = { type = QName } } }; Inheritance { base = T, subclass = CDecl } | InterfaceInheritance { interface_name = T, subclass = CDecl }; { class_ = CDecl } = Child } # schema