/**
 * An invocation of the compiler. Note that more than one file may be
 * compiled per invocation. For example, this command compiles three
 * source files:
 *
 *   javac A.java B.java C.java
 *
 * The `id` simply identifies the invocation, while `cwd` is the working
 * directory from which the compiler was invoked.
 */
compilations(
    /**
     * An invocation of the compiler. Note that more than one file may
     * be compiled per invocation. For example, this command compiles
     * three source files:
     *
     *   javac A.java B.java C.java
     */
    unique int id : @compilation,
    string cwd : string ref
);

/**
 * The arguments that were passed to the extractor for a compiler
 * invocation. If `id` is for the compiler invocation
 *
 *   javac A.java B.java C.java
 *
 * then typically there will be rows for
 *
 * num | arg
 * --- | ---
 * 0   | *path to extractor*
 * 1   | `--javac-args`
 * 2   | A.java
 * 3   | B.java
 * 4   | C.java
 */
#keyset[id, num]
compilation_args(
    int id : @compilation ref,
    int num : int ref,
    string arg : string ref
);

/**
 * The source files that are compiled by a compiler invocation.
 * If `id` is for the compiler invocation
 *
 *   javac A.java B.java C.java
 *
 * then there will be rows for
 *
 * num | arg
 * --- | ---
 * 0   | A.java
 * 1   | B.java
 * 2   | C.java
 */
#keyset[id, num]
compilation_compiling_files(
    int id : @compilation ref,
    int num : int ref,
    int file : @file ref
);

/**
 * The time taken by the extractor for a compiler invocation.
 *
 * For each file `num`, there will be rows for
 *
 * kind | seconds
 * ---- | ---
 * 1    | CPU seconds used by the extractor frontend
 * 2    | Elapsed seconds during the extractor frontend
 * 3    | CPU seconds used by the extractor backend
 * 4    | Elapsed seconds during the extractor backend
 */
#keyset[id, num, kind]
compilation_time(
    int id : @compilation ref,
    int num : int ref,
    /* kind:
       1 = frontend_cpu_seconds
       2 = frontend_elapsed_seconds
       3 = extractor_cpu_seconds
       4 = extractor_elapsed_seconds
    */
    int kind : int ref,
    float seconds : float ref
);

/**
 * An error or warning generated by the extractor.
 * The diagnostic message `diagnostic` was generated during compiler
 * invocation `compilation`, and is the `file_number_diagnostic_number`th
 * message generated while extracting the `file_number`th file of that
 * invocation.
 */
#keyset[compilation, file_number, file_number_diagnostic_number]
diagnostic_for(
    unique int diagnostic : @diagnostic ref,
    int compilation : @compilation ref,
    int file_number : int ref,
    int file_number_diagnostic_number : int ref
);

/**
 * If extraction was successful, then `cpu_seconds` and
 * `elapsed_seconds` are the CPU time and elapsed time (respectively)
 * that extraction took for compiler invocation `id`.
 */
compilation_finished(
    unique int id : @compilation ref,
    float cpu_seconds : float ref,
    float elapsed_seconds : float ref
);

diagnostics(
    unique int id: @diagnostic,
    int severity: int ref,
    string error_tag: string ref,
    string error_message: string ref,
    string full_error_message: string ref,
    int location: @location_default ref
);

/*
 * External artifacts
 */

externalData(
  int id : @externalDataElement,
  string path : string ref,
  int column: int ref,
  string value : string ref
);

snapshotDate(
  unique date snapshotDate : date ref
);

sourceLocationPrefix(
  string prefix : string ref
);

/*
 * Duplicate code
 */

duplicateCode(
  unique int id : @duplication,
  string relativePath : string ref,
  int equivClass : int ref
);

similarCode(
  unique int id : @similarity,
  string relativePath : string ref,
  int equivClass : int ref
);

@duplication_or_similarity = @duplication | @similarity

tokens(
  int id : @duplication_or_similarity ref,
  int offset : int ref,
  int beginLine : int ref,
  int beginColumn : int ref,
  int endLine : int ref,
  int endColumn : int ref
);

/*
 * Locations and files
 */

@location = @location_default ;

locations_default(
  unique int id: @location_default,
  int file: @file ref,
  int beginLine: int ref,
  int beginColumn: int ref,
  int endLine: int ref,
  int endColumn: int ref
);

hasLocation(
  int locatableid: @locatable ref,
  int id: @location ref
);

@sourceline = @locatable ;

#keyset[element_id]
numlines(
  int element_id: @sourceline ref,
  int num_lines: int ref,
  int num_code: int ref,
  int num_comment: int ref
);

files(
  unique int id: @file,
  string name: string ref,
  string simple: string ref,
  string ext: string ref,
  int fromSource: int ref // deprecated
);

folders(
  unique int id: @folder,
  string name: string ref,
  string simple: string ref
);

@container = @folder | @file

containerparent(
  int parent: @container ref,
  unique int child: @container ref
);

/*
 * Java
 */

cupackage(
  unique int id: @file ref,
  int packageid: @package ref
);

#keyset[fileid,keyName]
jarManifestMain(
  int fileid: @file ref,
  string keyName: string ref,
  string value: string ref
);

#keyset[fileid,entryName,keyName]
jarManifestEntries(
  int fileid: @file ref,
  string entryName: string ref,
  string keyName: string ref,
  string value: string ref
);

packages(
  unique int id: @package,
  string nodeName: string ref
);

primitives(
  unique int id: @primitive,
  string nodeName: string ref
);

modifiers(
  unique int id: @modifier,
  string nodeName: string ref
);

classes(
  unique int id: @class,
  string nodeName: string ref,
  int parentid: @package ref,
  int sourceid: @class ref
);

interfaces(
  unique int id: @interface,
  string nodeName: string ref,
  int parentid: @package ref,
  int sourceid: @interface ref
);

fielddecls(
  unique int id: @fielddecl,
  int parentid: @reftype ref
);

#keyset[fieldId] #keyset[fieldDeclId,pos]
fieldDeclaredIn(
  int fieldId: @field ref,
  int fieldDeclId: @fielddecl ref,
  int pos: int ref
);

fields(
  unique int id: @field,
  string nodeName: string ref,
  int typeid: @type ref,
  int parentid: @reftype ref,
  int sourceid: @field ref
);

constrs(
  unique int id: @constructor,
  string nodeName: string ref,
  string signature: string ref,
  int typeid: @type ref,
  int parentid: @reftype ref,
  int sourceid: @constructor ref
);

methods(
  unique int id: @method,
  string nodeName: string ref,
  string signature: string ref,
  int typeid: @type ref,
  int parentid: @reftype ref,
  int sourceid: @method ref
);

#keyset[parentid,pos]
params(
  unique int id: @param,
  int typeid: @type ref,
  int pos: int ref,
  int parentid: @callable ref,
  int sourceid: @param ref
);

paramName(
  unique int id: @param ref,
  string nodeName: string ref
);

isVarargsParam(
  int param: @param ref
);

exceptions(
  unique int id: @exception,
  int typeid: @type ref,
  int parentid: @callable ref
);

isAnnotType(
  int interfaceid: @interface ref
);

isAnnotElem(
  int methodid: @method ref
);

annotValue(
  int parentid: @annotation ref,
  int id2: @method ref,
  unique int value: @expr ref
);

isEnumType(
  int classid: @class ref
);

isEnumConst(
  int fieldid: @field ref
);

#keyset[parentid,pos]
typeVars(
  unique int id: @typevariable,
  string nodeName: string ref,
  int pos: int ref,
  int kind: int ref, // deprecated
  int parentid: @typeorcallable ref
);

wildcards(
  unique int id: @wildcard,
  string nodeName: string ref,
  int kind: int ref
);

#keyset[parentid,pos]
typeBounds(
  unique int id: @typebound,
  int typeid: @reftype ref,
  int pos: int ref,
  int parentid: @boundedtype ref
);

#keyset[parentid,pos]
typeArgs(
  int argumentid: @reftype ref,
  int pos: int ref,
  int parentid: @typeorcallable ref
);

isParameterized(
  int memberid: @member ref
);

isRaw(
  int memberid: @member ref
);

erasure(
  unique int memberid: @member ref,
  int erasureid: @member ref
);

#keyset[classid] #keyset[parent]
isAnonymClass(
  int classid: @class ref,
  int parent: @classinstancexpr ref
);

#keyset[classid] #keyset[parent]
isLocalClass(
  int classid: @class ref,
  int parent: @localclassdeclstmt ref
);

isDefConstr(
  int constructorid: @constructor ref
);

#keyset[exprId]
lambdaKind(
  int exprId: @lambdaexpr ref,
  int bodyKind: int ref
);

arrays(
  unique int id: @array,
  string nodeName: string ref,
  int elementtypeid: @type ref,
  int dimension: int ref,
  int componenttypeid: @type ref
);

enclInReftype(
  unique int child: @reftype ref,
  int parent: @reftype ref
);

extendsReftype(
  int id1: @reftype ref,
  int id2: @classorinterface ref
);

implInterface(
  int id1: @classorarray ref,
  int id2: @interface ref
);

hasModifier(
  int id1: @modifiable ref,
  int id2: @modifier ref
);

imports(
  unique int id: @import,
  int holder: @typeorpackage ref,
  string name: string ref,
  int kind: int ref
);

#keyset[parent,idx]
stmts(
  unique int id: @stmt,
  int kind: int ref,
  int parent: @stmtparent ref,
  int idx: int ref,
  int bodydecl: @callable ref
);

@stmtparent = @callable | @stmt | @switchexpr;

case @stmt.kind of
  0 = @block
| 1 = @ifstmt
| 2 = @forstmt
| 3 = @enhancedforstmt
| 4 = @whilestmt
| 5 = @dostmt
| 6 = @trystmt
| 7 = @switchstmt
| 8 = @synchronizedstmt
| 9 = @returnstmt
| 10 = @throwstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @emptystmt
| 14 = @exprstmt
| 15 = @labeledstmt
| 16 = @assertstmt
| 17 = @localvariabledeclstmt
| 18 = @localclassdeclstmt
| 19 = @constructorinvocationstmt
| 20 = @superconstructorinvocationstmt
| 21 = @case
| 22 = @catchclause
| 23 = @yieldstmt
;

#keyset[parent,idx]
exprs(
  unique int id: @expr,
  int kind: int ref,
  int typeid: @type ref,
  int parent: @exprparent ref,
  int idx: int ref
);

callableEnclosingExpr(
  unique int id: @expr ref,
  int callable_id: @callable ref
);

statementEnclosingExpr(
  unique int id: @expr ref,
  int statement_id: @stmt ref
);

isParenthesized(
  unique int id: @expr ref,
  int parentheses: int ref
);

case @expr.kind of
   1  = @arrayaccess
|  2  = @arraycreationexpr
|  3  = @arrayinit
|  4  = @assignexpr
|  5  = @assignaddexpr
|  6  = @assignsubexpr
|  7  = @assignmulexpr
|  8  = @assigndivexpr
|  9  = @assignremexpr
| 10  = @assignandexpr
| 11  = @assignorexpr
| 12  = @assignxorexpr
| 13  = @assignlshiftexpr
| 14  = @assignrshiftexpr
| 15  = @assignurshiftexpr
| 16  = @booleanliteral
| 17  = @integerliteral
| 18  = @longliteral
| 19  = @floatingpointliteral
| 20  = @doubleliteral
| 21  = @characterliteral
| 22  = @stringliteral
| 23  = @nullliteral
| 24  = @mulexpr
| 25  = @divexpr
| 26  = @remexpr
| 27  = @addexpr
| 28  = @subexpr
| 29  = @lshiftexpr
| 30  = @rshiftexpr
| 31  = @urshiftexpr
| 32  = @andbitexpr
| 33  = @orbitexpr
| 34  = @xorbitexpr
| 35  = @andlogicalexpr
| 36  = @orlogicalexpr
| 37  = @ltexpr
| 38  = @gtexpr
| 39  = @leexpr
| 40  = @geexpr
| 41  = @eqexpr
| 42  = @neexpr
| 43  = @postincexpr
| 44  = @postdecexpr
| 45  = @preincexpr
| 46  = @predecexpr
| 47  = @minusexpr
| 48  = @plusexpr
| 49  = @bitnotexpr
| 50  = @lognotexpr
| 51  = @castexpr
| 52  = @newexpr
| 53  = @conditionalexpr
| 54  = @parexpr         // deprecated
| 55  = @instanceofexpr
| 56  = @localvariabledeclexpr
| 57  = @typeliteral
| 58  = @thisaccess
| 59  = @superaccess
| 60  = @varaccess
| 61  = @methodaccess
| 62  = @unannotatedtypeaccess
| 63  = @arraytypeaccess
| 64  = @packageaccess
| 65  = @wildcardtypeaccess
| 66  = @declannotation
| 67  = @uniontypeaccess
| 68  = @lambdaexpr
| 69  = @memberref
| 70  = @annotatedtypeaccess
| 71  = @typeannotation
| 72  = @intersectiontypeaccess
| 73  = @switchexpr
;

@classinstancexpr = @newexpr | @lambdaexpr | @memberref

@annotation = @declannotation | @typeannotation
@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess

@assignment = @assignexpr
             | @assignop;

@unaryassignment = @postincexpr
                 | @postdecexpr
                 | @preincexpr
                 | @predecexpr;

@assignop = @assignaddexpr
             | @assignsubexpr
             | @assignmulexpr
             | @assigndivexpr
             | @assignremexpr
             | @assignandexpr
             | @assignorexpr
             | @assignxorexpr
             | @assignlshiftexpr
             | @assignrshiftexpr
             | @assignurshiftexpr;

@literal = @booleanliteral
             | @integerliteral
             | @longliteral
             | @floatingpointliteral
             | @doubleliteral
             | @characterliteral
             | @stringliteral
             | @nullliteral;

@binaryexpr = @mulexpr
             | @divexpr
             | @remexpr
             | @addexpr
             | @subexpr
             | @lshiftexpr
             | @rshiftexpr
             | @urshiftexpr
             | @andbitexpr
             | @orbitexpr
             | @xorbitexpr
             | @andlogicalexpr
             | @orlogicalexpr
             | @ltexpr
             | @gtexpr
             | @leexpr
             | @geexpr
             | @eqexpr
             | @neexpr;

@unaryexpr =   @postincexpr
             | @postdecexpr
             | @preincexpr
             | @predecexpr
             | @minusexpr
             | @plusexpr
             | @bitnotexpr
             | @lognotexpr;

@caller =  @classinstancexpr
         | @methodaccess
         | @constructorinvocationstmt
         | @superconstructorinvocationstmt;

callableBinding(
  unique int callerid: @caller ref,
  int callee: @callable ref
);

memberRefBinding(
  unique int id: @expr ref,
  int callable: @callable ref
);

@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable;

variableBinding(
  unique int expr: @varaccess ref,
  int variable: @variable ref
);

@variable = @localscopevariable | @field;

@localscopevariable = @localvar | @param;

localvars(
  unique int id: @localvar,
  string nodeName: string ref,
  int typeid: @type ref,
  int parentid: @localvariabledeclexpr ref
);

@namedexprorstmt = @breakstmt
                 | @continuestmt
                 | @labeledstmt
                 | @literal;

namestrings(
  string name: string ref,
  string value: string ref,
  unique int parent: @namedexprorstmt ref
);

/*
 * Modules
 */

#keyset[name]
modules(
  unique int id: @module,
  string name: string ref
);

isOpen(
  int id: @module ref
);

#keyset[fileId]
cumodule(
  int fileId: @file ref,
  int moduleId: @module ref
);

@directive = @requires
           | @exports
           | @opens
           | @uses
           | @provides

#keyset[directive]
directives(
  int id: @module ref,
  int directive: @directive ref
);

requires(
  unique int id: @requires,
  int target: @module ref
);

isTransitive(
  int id: @requires ref
);

isStatic(
  int id: @requires ref
);

exports(
  unique int id: @exports,
  int target: @package ref
);

exportsTo(
  int id: @exports ref,
  int target: @module ref
);

opens(
  unique int id: @opens,
  int target: @package ref
);

opensTo(
  int id: @opens ref,
  int target: @module ref
);

uses(
  unique int id: @uses,
  string serviceInterface: string ref
);

provides(
  unique int id: @provides,
  string serviceInterface: string ref
);

providesWith(
  int id: @provides ref,
  string serviceImpl: string ref
);

/*
 * Javadoc
 */

javadoc(
  unique int id: @javadoc
);

isNormalComment(
  int commentid : @javadoc ref
);

isEolComment(
  int commentid : @javadoc ref
);

hasJavadoc(
  int documentableid: @member ref,
  int javadocid: @javadoc ref
);

#keyset[parentid,idx]
javadocTag(
  unique int id: @javadocTag,
  string name: string ref,
  int parentid: @javadocParent ref,
  int idx: int ref
);

#keyset[parentid,idx]
javadocText(
  unique int id: @javadocText,
  string text: string ref,
  int parentid: @javadocParent ref,
  int idx: int ref
);

@javadocParent = @javadoc | @javadocTag;
@javadocElement = @javadocTag | @javadocText;

@typeorpackage = @type | @package;

@typeorcallable = @type | @callable;
@classorinterface = @interface | @class;
@boundedtype = @typevariable | @wildcard;
@reftype = @classorinterface | @array | @boundedtype;
@classorarray = @class | @array;
@type = @primitive | @reftype;
@callable = @method | @constructor;
@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field |
           @annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl;

@modifiable = @member_modifiable| @param | @localvar ;

@member_modifiable = @class | @interface | @method | @constructor | @field ;

@member = @method | @constructor | @field | @reftype ;

@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception
             | @boundedtype | @typebound | @array | @primitive
             | @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText
             | @xmllocatable;

@top = @element | @locatable | @folder;

/*
 * XML Files
 */

xmlEncoding(
  unique int id: @file ref,
  string encoding: string ref
);

xmlDTDs(
  unique int id: @xmldtd,
  string root: string ref,
  string publicId: string ref,
  string systemId: string ref,
  int fileid: @file ref
);

xmlElements(
  unique int id: @xmlelement,
  string name: string ref,
  int parentid: @xmlparent ref,
  int idx: int ref,
  int fileid: @file ref
);

xmlAttrs(
  unique int id: @xmlattribute,
  int elementid: @xmlelement ref,
  string name: string ref,
  string value: string ref,
  int idx: int ref,
  int fileid: @file ref
);

xmlNs(
  int id: @xmlnamespace,
  string prefixName: string ref,
  string URI: string ref,
  int fileid: @file ref
);

xmlHasNs(
  int elementId: @xmlnamespaceable ref,
  int nsId: @xmlnamespace ref,
  int fileid: @file ref
);

xmlComments(
  unique int id: @xmlcomment,
  string text: string ref,
  int parentid: @xmlparent ref,
  int fileid: @file ref
);

xmlChars(
  unique int id: @xmlcharacters,
  string text: string ref,
  int parentid: @xmlparent ref,
  int idx: int ref,
  int isCDATA: int ref,
  int fileid: @file ref
);

@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;

xmllocations(
  int xmlElement: @xmllocatable ref,
  int location: @location_default ref
);

@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;

/*
 * configuration files with key value pairs
 */

configs(
  unique int id: @config
);

configNames(
  unique int id: @configName,
  int config: @config ref,
  string name: string ref
);

configValues(
  unique int id: @configValue,
  int config: @config ref,
  string value: string ref
);

configLocations(
  int locatable: @configLocatable ref,
  int location: @location_default ref
);

@configLocatable = @config | @configName | @configValue;
