| // Copyright 2014 The Kythe Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| Kythe Schema Reference |
| ====================== |
| :Revision: 1.0 |
| :toc2: |
| :toclevels: 3 |
| :priority: 999 |
| |
| .This document is part of the Kythe test suite. |
| TIP: Successfully generating this document is part of the test suite for the |
| Kythe indexers. The assertions in the example code all verify and the |
| graphs provided are the graphs that are actually output. Feel free to add |
| examples from your own languages, but be sure to keep them up to date. |
| |
| Kythe Namespace |
| --------------- |
| |
| All fact names in this doc are implicitly prefixed by `/kythe`:: |
| e.g. `node/kind` is really `/kythe/node/kind` |
| |
| All edge kinds in this doc are implicitly prefixed by `/kythe/edge`:: |
| e.g. `aliases` is really `/kythe/edge/aliases` |
| |
| The verifier will automatically prepend the respective prefix |
| unless the fact name or edge kind starts with `/`. |
| |
| |
| VName conventions |
| ----------------- |
| |
| By default, assume that the VNames of nodes should be chosen according to the |
| following rules: |
| |
| * `language`: the source language. |
| * `corpus`: the node's containing corpus. |
| * `root`: a root path relative to the node's corpus. |
| * `path`: a path relative to the corpus *and* root of the node. |
| * `signature`: a unique string (per `corpus`, `root`, `path`, and `language`) |
| that should be consistently generated given the same input to the indexer, |
| but that does not necessarily need to be stable across different versions of |
| the input. |
| |
| Additional rules govern the generation of VNames for certain kinds of nodes, |
| most notably <<file,files>>. These nodes are frequently used as points |
| for linking together the output of discrete indexer runs and may have greater |
| stability properties than may be derived using the preceding VName rules. |
| |
| Absent additional rules, an indexer is permitted to encode the `signature` field |
| arbitrarily, as long as the chance of this encoding causing distinct field |
| values to become indistinguishable is vanishingly small. This is meant to permit |
| implementations to use one-way hash functions to crunch large `signature` values |
| down to manageable fingerprints. |
| |
| Edge kinds |
| ---------- |
| .Reverse Edges |
| TIP: The Kythe API uses `%` to denote a reverse edge. |
| For example, if NodeA `defines/binding` NodeB, then NodeB |
| `%/kythe/edge/defines/binding` NodeA. Reverse edges are constructed |
| during post-processing, and should not be emitted by indexers. |
| |
| [[aliases]] |
| aliases |
| ~~~~~~~ |
| |
| Brief description:: |
| A *aliases* T if A may be used in place of T. |
| Commonly arises from:: |
| typedefs |
| Points from:: |
| <<talias>> |
| Points toward:: |
| types |
| Ordinals are used:: |
| never |
| See also:: |
| <<aliasesroot, [aliases/root]>> |
| |
| [kythe,C++,"Typedefs are aliases."] |
| -------------------------------------------------------------------------------- |
| //- @Counter defines/binding TAlias |
| //- TAlias aliases TInt |
| typedef int Counter; |
| -------------------------------------------------------------------------------- |
| |
| [[aliasesroot]] |
| aliases/root |
| ~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *aliases/root* T if following all *aliases* edges from A may lead to T, |
| possibly with language-specific qualifiers applied. |
| Commonly arises from:: |
| typedefs |
| Points from:: |
| <<talias>> |
| Points toward:: |
| types |
| Ordinals are used:: |
| never |
| See also:: |
| <<aliasesroot, [aliases/root]>> |
| |
| [kythe,C++,"Following aliases."] |
| -------------------------------------------------------------------------------- |
| //- @T defines/binding AliasT |
| //- AliasT aliases TInt |
| //- AliasT aliases/root TInt |
| using T = int; |
| //- AliasS aliases AliasT |
| //- AliasS aliases/root TInt |
| using S = T; |
| //- AliasU aliases AliasS |
| //- AliasU aliases/root TInt |
| using U = S; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Following aliases and collecting qualifiers."] |
| -------------------------------------------------------------------------------- |
| //- @CInt defines/binding ConstIntAlias |
| //- ConstIntAlias aliases CInt |
| //- CInt.node/kind tapp |
| //- CInt param.0 Const |
| //- CInt param.1 TInt |
| using CInt = const int; |
| //- @T defines/binding AliasT |
| //- AliasT aliases TInt |
| //- AliasT aliases/root TInt |
| using T = int; |
| //- AliasS aliases ConstAliasT |
| //- ConstAliasT param.0 Const |
| //- ConstAliasT param.1 AliasT |
| //- AliasS aliases/root CInt |
| using S = const T; |
| //- AliasU aliases AliasS |
| //- AliasU aliases/root CInt |
| using U = S; |
| -------------------------------------------------------------------------------- |
| |
| [[annotatedby]] |
| annotatedby |
| ~~~~~~~~~~~ |
| |
| Brief description:: |
| A *annotatedby* B if A provides metadata for B. |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| |
| [kythe,Java,"Classes can be annotated."] |
| -------------------------------------------------------------------------------- |
| //- @Deprecated ref Deprecated |
| //- @E defines/binding Class |
| //- Class annotatedby Deprecated |
| @Deprecated public class E {} |
| -------------------------------------------------------------------------------- |
| |
| [[bounded]] |
| bounded/upper or bounded/lower |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| <<absvar>> A is *bounded/upper* by B when A is constrained to be a subtype |
| of B. <<absvar>> A is *bounded/lower* by B when A is constrained to be a |
| supertype of B. |
| See also:: |
| <<absvar>> |
| Commonly arises from:: |
| Type parameters |
| Notes:: |
| * Kythe leaves the interpretation of unbounded <<absvar>> nodes to each |
| language. For example, an <<absvar>> with no *bounded* edges in Java may be |
| assigned any subtype of Object, but no primitive type. |
| * It is possible for an <<absvar>> to have multiple bounds. For example, this |
| occurs in Java when a type parameter must implement several interfaces. |
| In cases where the order of the bounds matters (e.g., in Java, where the |
| order affects type erasure), the bound edge kind may be qualified by an ordinal, |
| so that A is *bounded/upper.N* by B if B is the Nth upper bound of A. |
| Code interpreting *bounded* edges should be able to handle both |
| ordered and unordered edges. |
| |
| [kythe,Java,"Generic type parameters can be bound."] |
| -------------------------------------------------------------------------------- |
| package pkg; |
| public class E { |
| //- @"Optional<?>" ref OptionalWild |
| //- OptionalWild.node/kind tapp |
| //- OptionalWild param.0 OptionalClass |
| //- OptionalWild param.1 Wildcard0 |
| //- Wildcard0.node/kind absvar |
| //- !{ Wildcard0 bounded/upper Anything0 |
| //- Wildcard0 bounded/lower Anything1 } |
| private static void wildcard(Optional<?> o) {} |
| |
| //- @"Optional<? extends String>" ref OptionalWildString |
| //- OptionalWildString.node/kind tapp |
| //- OptionalWildString param.0 OptionalClass |
| //- OptionalWildString param.1 Wildcard1 |
| //- Wildcard1.node/kind absvar |
| //- Wildcard1 bounded/upper Str |
| //- @String ref Str |
| //- !{ Wildcard1 bounded/lower Anything2 } |
| private static void wildcardBound(Optional<? extends String> o) {} |
| |
| //- @"Optional<? super String>" ref OptionalWildSuperString |
| //- OptionalWildSuperString.node/kind tapp |
| //- OptionalWildSuperString param.0 OptionalClass |
| //- OptionalWildSuperString param.1 WildcardSuper1 |
| //- WildcardSuper1.node/kind absvar |
| //- WildcardSuper1 bounded/lower Str |
| //- !{ WildcardSuper1 bounded/upper Anything1 } |
| //- @String ref Str |
| private static void wildcardSuperBound(Optional<? super String> o) {} |
| |
| //- @objAndOneIFaceBound defines/binding OIFunc |
| //- @S1 defines/binding S1Var |
| //- @List ref List |
| //- S1Var bounded/upper.0 Obj |
| //- S1Var bounded/upper.1 List |
| public <S1 extends Object & java.util.List> void objAndOneIFaceBound() {} |
| |
| } |
| -------------------------------------------------------------------------------- |
| |
| // TODO(salguarnieri) Add in Objective-C example once this feature is added to |
| // the Objective-C indexer. |
| |
| [[childof]] |
| childof |
| ~~~~~~~ |
| |
| Brief description:: |
| A *childof* B if A is contained in or dominated by B. |
| Commonly arises from:: |
| <<anchor>>s, block syntax, membership |
| Points from:: |
| any |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Enumerators are children of enumerations."] |
| -------------------------------------------------------------------------------- |
| //- @Enum defines/binding Enumeration |
| enum class Enum { |
| //- @Etor defines/binding Enumerator |
| Etor |
| }; |
| //- Enumerator childof Enumeration |
| -------------------------------------------------------------------------------- |
| |
| [[childofcontext]] |
| childof/context |
| ~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *childof/context* T if anchor A is associated with some instantiation T. |
| Commonly arises from:: |
| template instantiations |
| Points from:: |
| <<anchor>>s |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Template instantiations create new anchor contexts."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding CTemplate |
| //- CTemplateBody childof CTemplate |
| template <typename T> struct C { |
| //- @x=AnchorX defines/binding XBinding |
| //- XBinding childof CTemplateBody |
| //- @x=AnchorCX defines/binding CXBinding |
| int x; |
| }; |
| //- @C defines/binding CInst |
| //- AnchorCX childof/context CInst |
| //- CXBinding childof CInst |
| //- !{ AnchorX childof/context CInst } |
| template struct C<int>; |
| -------------------------------------------------------------------------------- |
| |
| [[completes]] |
| completes |
| ~~~~~~~~~ |
| |
| Brief description:: |
| Definition A *completes* declaration B if A fully specifies B, but |
| there may exist other definitions that may also fully specify B. |
| Commonly arises from:: |
| definitions of forward declarations |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes with `complete` facts set to `incomplete` or `complete` |
| See also:: |
| <<record>>, <<sum>>, <<completesuniquely,[completes/uniquely]>> |
| |
| [kythe,C++,"Definitions complete forward declarations in headers."] |
| -------------------------------------------------------------------------------- |
| #include "test.h" |
| //- @C completes Decl1 |
| //- @C completes Decl2 |
| //- @C defines/binding Defn |
| class C { }; |
| |
| #example test.h |
| //- @C defines/binding Decl1 |
| class C; |
| //- @C defines/binding Decl2 |
| class C; |
| -------------------------------------------------------------------------------- |
| |
| [[completesuniquely]] |
| completes/uniquely |
| ~~~~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| Definition A *completes/uniquely* declaration B if A fully specifies B |
| and there is no other definition that could possibly do so. |
| Commonly arises from:: |
| definitions of forward declarations |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes with `complete` facts set to `incomplete` or `complete` |
| See also:: |
| <<completes>>, <<record>>, <<sum>> |
| |
| [kythe,C++,"Definitions uniquely complete same-file forward declarations."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding Decl1 |
| class C; |
| //- @C defines/binding Decl2 |
| class C; |
| //- @C completes/uniquely Decl1 |
| //- @C completes/uniquely Decl2 |
| //- @C defines/binding Defn |
| class C { }; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Completeness links abs nodes for function templates."] |
| -------------------------------------------------------------------------------- |
| //- @id defines/binding Decl |
| template <typename T> T id(T x); |
| //- @id defines/binding Defn |
| //- @id completes/uniquely Decl |
| template <typename T> T id(T x) { return x; } |
| //- Defn.node/kind abs |
| //- Decl.node/kind abs |
| -------------------------------------------------------------------------------- |
| |
| [[defines]] |
| defines |
| ~~~~~~~ |
| |
| Brief description:: |
| A *defines* B if A generates the semantic object B. |
| Commonly arises from:: |
| definitions and declarations |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<definesbinding,[defines/binding]>> |
| Notes:: |
| It is valid for multiple anchors to define the same semantic object. These |
| anchors may even overlap. |
| |
| |
| [kythe,Java,"Class definitions span their entire body."] |
| -------------------------------------------------------------------------------- |
| //- ClassEDef defines ClassE |
| //- ClassEDef.node/kind anchor |
| //- ClassEDef.loc/start @^public |
| //- ClassEDef.loc/end @$+3"}" |
| public class E { |
| // class contents here... |
| } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Method definitions span their entire body."] |
| -------------------------------------------------------------------------------- |
| public class E { |
| //- MethodDef defines Method |
| //- MethodDef.node/kind anchor |
| //- MethodDef.loc/start @^public |
| //- MethodDef.loc/end @$+3"}" |
| public int methodName(int param) { |
| return 42; |
| } |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[definesbinding]] |
| defines/binding |
| ~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *defines/binding* B when A covers an identifier bound to B when that binding is established. |
| Commonly arises from:: |
| definitions |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<defines>> |
| Notes:: |
| Source anchors are not necessarily identifiers. For example, the $$C++$$ |
| indexer will start a *defines/binding* edge from an anchor spanning |
| the text `operator()`. |
| |
| [kythe,Java,"Class names bind their definitions."] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding ClassE |
| public class E {} |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Method names bind their definitions."] |
| -------------------------------------------------------------------------------- |
| public class E { |
| //- @main defines/binding MethodMain |
| public static void main(String[] args) {} |
| } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Variable definitions define bindings for variables."] |
| -------------------------------------------------------------------------------- |
| //- @x defines/binding VariableX |
| int x; |
| -------------------------------------------------------------------------------- |
| |
| [[depends]] |
| depends |
| ~~~~~~~ |
| |
| Brief description:: |
| A *depends* B if processing of A depends on the existence or presence of B. For example, if a |
| process depends a set of files and/or processes. Another example, a file depends upon a process |
| which outputs said file. |
| Commonly arises from:: |
| build dependencies |
| Points from:: |
| <<process>>, <<file>> |
| Points toward:: |
| <<process>>, <<file>> |
| Ordinals are used:: |
| never |
| |
| [[documents]] |
| documents |
| ~~~~~~~~~ |
| |
| Brief description:: |
| A *documents* B if A describes (in possibly marked up natural language) the |
| semantic object B. |
| Commonly arises from:: |
| documentation comments |
| Points from:: |
| anchors and <<doc>>s |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| Notes:: |
| Kythe does not specify a particular flavor of markup. Documentation comment |
| anchors include all of the characters of the comment, including (e.g.) the |
| $$///$$s. It is up to the language indexer to determine which comments to |
| treat as documentation comments. |
| See also:: |
| <<doc,refdoc,ref/doc>> |
| |
| In the $$C++$$ example below, there are really two documentation blocks: the |
| first comes from merging together the verification annotations; the second is |
| the Doxygen-style $$///$$ line. The Doxygen line is not merged with the verifier |
| lines owing to heuristics in Clang's comment parser. |
| |
| [kythe,C++,"Comments document objects."] |
| -------------------------------------------------------------------------------- |
| int v; //- @"/// An empty class." documents ClassC |
| //- ClassC.node/kind record |
| /// An empty class. |
| class C { }; |
| -------------------------------------------------------------------------------- |
| |
| [[exports]] |
| exports |
| ~~~~~~~~ |
| Brief description:: |
| A *exports* B if process node A exports process node B. |
| Commonly arises from:: |
| build rules |
| Points from:: |
| process nodes |
| Points toward:: |
| process nodes |
| Orginals are used:: |
| never |
| See also:: |
| <<process>> |
| Notes:: |
| Tools like bazel have cases where build rules export other build rules, wherein the closure of all |
| rules reached via exports attributes are considered direct dependencies of any rule that directly |
| depends on the target with exports. The exports are not direct dependencies of the rule they belong |
| to. |
| |
| [kythe,clike,"Process node exports other process node."] |
| -------------------------------------------------------------------------------- |
| //- ProcessNodeA.node/kind process |
| //- ProcessNodeB.node/kind process |
| //- ProcessNodeA exports ProcessNodeB |
| java_library( |
| name = "A", |
| exports = [ |
| ":B", |
| ], |
| ) |
| |
| java_library( |
| name = "B", |
| ) |
| -------------------------------------------------------------------------------- |
| |
| [[extends]] |
| extends |
| ~~~~~~~ |
| |
| Brief description:: |
| A *extends* B if A is a direct nominal subtype of B. |
| Commonly arises from:: |
| inheritance |
| Points from:: |
| semantic nodes |
| Points toward:: |
| type/semantic nodes |
| Ordinals are used:: |
| never |
| Notes:: |
| An indexer may emit more descriptive edges with the *extends* prefix. |
| For example, $$C++$$ will emit *extends/public*, *extends/public/virtual*, |
| *extends/protected*, *extends/protected/virtual*, *extends/private*, |
| *extends/private/virtual*, and *extends/virtual*. |
| |
| [kythe,Java,"Classes extend classes."] |
| -------------------------------------------------------------------------------- |
| package pkg; |
| public class E { |
| //- @A defines/binding ClassA |
| static class A { } |
| //- @B defines/binding ClassB |
| //- ClassB extends ClassA |
| static class B extends A { } |
| } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Classes extend classes."] |
| -------------------------------------------------------------------------------- |
| //- @A defines/binding ClassA |
| class A { }; |
| //- @B defines/binding ClassB |
| //- ClassB extends/public ClassA |
| class B : public A { }; |
| -------------------------------------------------------------------------------- |
| |
| |
| [[generates]] |
| generates |
| ~~~~~~~~~ |
| Brief description:: |
| A *generates* B if A is related to B through some extralingual process. |
| Commonly arises from:: |
| code generation |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<imputes>> |
| |
| Tools like RPC interface generators read specification languages and emit |
| code in one or more target languages. Although the specification language |
| and target languages do not share Kythe indexers, it is still semantically |
| useful to connect the nodes they emit. For example, one might want to list |
| all the $$C++$$ and Java uses of a particular service call, starting at the |
| specification of that service. The specification and its generated artifacts |
| may be joined by the *generates* edge. |
| |
| |
| [[instantiates]] |
| instantiates |
| ~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *instantiates* B if A is the result of monomorphizing B. |
| Commonly arises from:: |
| implicit template application |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes (<<tapp>>) |
| Ordinals are used:: |
| never |
| See also:: |
| <<instantiatesspeculative,[instantiates/speculative]>>, <<specializes>> |
| |
| In $$C++$$, *specialization* and *instantiation* capture distinct relationships. |
| Every template `T` has a primary template, which defines the number and kind |
| of template parameters that are written down whenever `T` is (normally) |
| expressed. Other templates *specialize* `T` by specifying alternate bodies |
| for the template depending on the values bound to the template parameters. |
| This *specializes* relationship is always between a more-specific (or implicit) |
| template and its primary template (applied to one or more arguments). We do not |
| attempt to model a subtyping relationship between template specializations. |
| |
| When `T<...>` is written down, an element from the set of *T* and its |
| specializations must be chosen for manifestation. This element may have free |
| type parameters. These are deduced during the process of *instantiating* the |
| chosen specialization of *T*. Some $$C++$$ _total specializations_ do not bind |
| any template parameters. Other $$C++$$ _partial specializations_ do, and may |
| bind different numbers of type parameters than the primary template. The |
| *instantiates* relationship records which total or partial specialization was |
| chosen (or if the primary template was chosen), and the template arguments that |
| were matched to that specialization's parameters. In contrast, the *specializes* |
| relationship for `T<...>` records the primary template for T, as well as which |
| template arguments were substituted for the primary template's parameters. |
| |
| When the primary template is chosen for the *instantiates* relationship, the |
| *specializes* edge points to the same node: |
| |
| [kythe,C++,"Instantiating the primary template"] |
| -------------------------------------------------------------------------------- |
| //- @t_equals_float defines/binding PrimaryTemplate |
| template<typename T, typename S> bool t_equals_float = false; |
| |
| //- @t_equals_float ref TEqualsFloatForLongLong |
| //- TEqualsFloatForLongLong instantiates TAppLongLong |
| //- TEqualsFloatForLongLong specializes TAppLongLong |
| //- TAppLongLong param.0 PrimaryTemplate |
| bool is_false = t_equals_float<long, long>; |
| -------------------------------------------------------------------------------- |
| |
| When a specialization of a template is chosen for *instantiates*, the |
| *specializes* edge still points to the primary template applied to the correct |
| number of arguments. The *instantiates* edge points to the specialization that |
| was used. It is applied to the template arguments appropriate for that |
| specialization. Note in the below example how we *specialize* |
| `PrimaryTemplate<float, long>` but *instantiate* `SpecificTemplate<long>`: |
| |
| [kythe,C++,"Instantiating a partial specialization"] |
| -------------------------------------------------------------------------------- |
| //- @t_equals_float defines/binding PrimaryTemplate |
| template<typename T, typename S> bool t_equals_float = false; |
| //- @int ref IntType @long ref LongType |
| int i; long l; |
| |
| //- @t_equals_float defines/binding SpecificTemplate |
| template <typename S> bool t_equals_float<float, S> = true; |
| //- @t_equals_float ref TEqualsFloatForFloatLong |
| //- TEqualsFloatForFloatLong instantiates TAppSpecificFloatLong |
| //- TAppSpecificFloatLong param.0 SpecificTemplate |
| //- TAppSpecificFloatLong param.1 LongType |
| //- TEqualsFloatForLongLong specializes TAppPrimaryFloatLong |
| //- TAppPrimaryFloatLong param.0 PrimaryTemplate |
| //- TAppPrimaryFloatLong param.1 FloatType |
| //- TAppPrimaryFloatLong param.2 LongType |
| bool is_true = t_equals_float<float, long>; |
| -------------------------------------------------------------------------------- |
| |
| Here is another similar example: |
| |
| [kythe,C++,"Instantiation versus specialization."] |
| -------------------------------------------------------------------------------- |
| //- @v defines/binding PrimaryTemplate |
| template <typename T, typename S, typename V> T v; |
| template <typename U> |
| //- @v defines/binding PartialSpecialization |
| U v<int, U, long>; |
| //- @v ref ImplicitSpecialization |
| float w = v<int, float, long>; |
| //- ImplicitSpecialization specializes TAppPrimaryTemplate |
| //- ImplicitSpecialization instantiates TAppPartialSpecialization |
| //- TAppPrimaryTemplate param.0 PrimaryTemplate |
| //- TAppPrimaryTemplate param.1 vname("int#builtin",_,_,_,_) |
| //- TAppPrimaryTemplate param.2 vname("float#builtin",_,_,_,_) |
| //- TAppPrimaryTemplate param.3 vname("long#builtin",_,_,_,_) |
| //- TAppPartialSpecialization param.0 PartialSpecialization |
| //- TAppPartialSpecialization param.1 vname("float#builtin",_,_,_,_) |
| -------------------------------------------------------------------------------- |
| |
| [[instantiatesspeculative]] |
| instantiates/speculative |
| ~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *instantiates/speculative* B if A could be the result of monomorphizing B. |
| Commonly arises from:: |
| implicit template application |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes (<<tapp>>) |
| Ordinals are used:: |
| never |
| See also:: |
| <<instantiates>>, <<specializes>> |
| |
| It may not be possible to decide whether a type instantiation actually occurs, |
| especially when dependent types are involved. The *instantiates/speculative* |
| and *specializes/speculative* edges are like the *instantiates* and |
| *specializes* edges, but they also record the fact that the instantiation |
| (specialization) did not occur when the code was indexed. |
| |
| [kythe,C++,"Speculative instantiation and specialization."] |
| -------------------------------------------------------------------------------- |
| // Checks indexing refs and defs of dependent function specializations. |
| //- @f defines/binding AbsF1 |
| template <typename S> long f(S s) { return 0; } |
| //- @f defines/binding AbsF2 |
| template <typename S> int f(S s) { return 0; } |
| template <typename T> struct S { |
| // Note that C++ doesn't even check the kindedness of these type applications. |
| friend |
| //- @f defines/binding DepSpecFT |
| //- DepSpecFT instantiates/speculative TAppAbsF1T |
| //- DepSpecFT specializes/speculative TAppAbsF1T |
| //- TAppAbsF1T param.0 AbsF1 |
| //- DepSpecFT instantiates/speculative TAppAbsF2T |
| //- DepSpecFT specializes/speculative TAppAbsF2T |
| //- TAppAbsF2T param.0 AbsF2 |
| long f<int, short>(T t) { return 1; } |
| }; |
| -------------------------------------------------------------------------------- |
| |
| [[imputes]] |
| imputes |
| ~~~~~~~ |
| |
| Brief description:: |
| A *imputes* B if the syntactic span at A is related to the semantic node B |
| through some extralingual process. |
| Commonly arises from:: |
| code generation |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<generates>> |
| |
| Mechanically, if A *defines/binding* A' and A *imputes* B, where A is an anchor |
| and both A' and B are semantic nodes, the *imputes* edge has the same effect as |
| though the edge A' *generates* B were produced. This edge is useful in cases |
| where it isn't otherwise possible to produce the VName for A' and where the |
| span A in source text can uniquely identify A' by the *defines/binding* edge. |
| |
| [[named]] |
| named |
| ~~~~~ |
| |
| Brief description:: |
| A *named* B if B is an external identifier for A. |
| Commonly arises from:: |
| definitions and declarations |
| Points from:: |
| semantic nodes |
| Points toward:: |
| names |
| Ordinals are used:: |
| never |
| See also:: |
| <<name>> |
| |
| [kythe,Java,"Classes have JVM binary names."] |
| -------------------------------------------------------------------------------- |
| package pkg; |
| //- @C defines/binding CClass |
| //- CClass named CClassName = vname("pkg.C", "", "", "", "jvm") |
| //- CClassName.node/kind name |
| public class C {} |
| -------------------------------------------------------------------------------- |
| |
| [[overrides]] |
| overrides |
| ~~~~~~~~~ |
| |
| Brief description:: |
| A *overrides* B if A directly overrides B in an inheritance-based relationship. |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<overridestransitive,[overrides/transitive]>>, <<overridesroot,[overrides/root]>> |
| |
| [kythe,Java,"Methods have overrides edges."] |
| -------------------------------------------------------------------------------- |
| package pkg; |
| public class E { |
| static class A implements I { |
| //- @method defines/binding AMethod |
| //- AMethod overrides IMethod |
| public void method() {} |
| } |
| static class B extends A implements I { |
| //- @method defines/binding BMethod |
| //- BMethod overrides AMethod |
| //- BMethod overrides IMethod |
| public void method() {} |
| } |
| static interface I { |
| //- @method defines/binding IMethod |
| public void method(); |
| } |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[overridesroot]] |
| overrides/root |
| ~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *overrides/root* B if following all *overrides* edges from A would lead to |
| B. |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<overrides>> |
| |
| [kythe,C++,"Override roots"] |
| -------------------------------------------------------------------------------- |
| //- @f defines/binding CF |
| class C { virtual void f() { } }; |
| //- @f defines/binding DF |
| class D : C { void f() override { } }; |
| //- @f defines/binding EF |
| class E : D { void f() override { } }; |
| |
| //- !{CF overrides _} |
| //- !{CF overrides/root _} |
| //- DF overrides CF |
| //- DF overrides/root CF |
| //- EF overrides DF |
| //- EF overrides/root CF |
| -------------------------------------------------------------------------------- |
| |
| [[overridestransitive]] |
| overrides/transitive |
| ~~~~~~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *overrides/transitive* B if A transitively overrides B, but the relationship |
| A <<overrides>> B doesn't exist. |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<overrides>> |
| |
| [kythe,Java,"Methods have overrides/transitive edges."] |
| -------------------------------------------------------------------------------- |
| package pkg; |
| public class E { |
| static class A { |
| //- @method defines/binding AMethod |
| public void method() {} |
| } |
| static class B extends A { |
| //- @method defines/binding BMethod |
| //- !{ BMethod overrides/transitive AMethod } |
| public void method() {} |
| } |
| static class C extends B { |
| //- @method defines/binding CMethod |
| //- !{ CMethod overrides/transitive BMethod } |
| //- CMethod overrides/transitive AMethod |
| public void method() {} |
| } |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[param]] |
| param |
| ~~~~~ |
| |
| Brief description:: |
| A *param.N* B if B is the Nth parameter of A. |
| Commonly arises from:: |
| ordered lists |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| always |
| |
| [kythe,C++,"Type applications have parameters."] |
| -------------------------------------------------------------------------------- |
| //- @T defines/binding AliasT |
| //- AliasT aliases PtrInt |
| //- PtrInt param.0 PointerConstructor |
| //- PtrInt param.1 IntType |
| using T = int*; |
| -------------------------------------------------------------------------------- |
| |
| [[ref]] |
| ref |
| ~~~ |
| |
| Brief description:: |
| A *ref* B if A refers to some previously-defined B. |
| Commonly arises from:: |
| expressions, spelled-out types |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| |
| [kythe,C++,"Mentions of variables are refs."] |
| -------------------------------------------------------------------------------- |
| //- @x defines/binding VariableX |
| int x; |
| //- @y defines/binding VariableY |
| //- @x ref VariableX |
| int y = x; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Go,"Mentions of variables are refs."] |
| -------------------------------------------------------------------------------- |
| package p |
| |
| //- @x defines/binding VarX = vname(_,"kythe",_,"schema","go") |
| //- VarX.node/kind variable |
| var x int |
| |
| //- @x ref VarX |
| var y = x |
| -------------------------------------------------------------------------------- |
| |
| [[refimplicit]] |
| ref/implicit |
| ~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/implicit* B if A refers to some previously-defined B, and the |
| expression spanned by A is implicit (e.g., the result of a template |
| instantiation). |
| Commonly arises from:: |
| expressions, spelled-out types |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| |
| [kythe,C++,"References inside template instantiations are implicit."] |
| -------------------------------------------------------------------------------- |
| template <typename T> class C { |
| //- @foo ref/implicit SFoo |
| int x = T::foo; |
| }; |
| //- @foo defines/binding SFoo |
| struct S { static constexpr int foo = 1; }; |
| C<S> cs; |
| -------------------------------------------------------------------------------- |
| |
| [[refcall]] |
| ref/call |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *ref/call* F if A is an anchor that calls F. |
| Points from:: |
| anchors |
| Points toward:: |
| <<function,functions>> |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Anchors inside functions call functions."] |
| -------------------------------------------------------------------------------- |
| //- @A defines/binding FnA |
| void A() { } |
| //- @B defines/binding FnB |
| //- ACall childof FnB |
| //- ACall.node/kind anchor |
| //- ACall ref/call FnA |
| void B() { A(); } |
| -------------------------------------------------------------------------------- |
| |
| [[refcallimplicit]] |
| ref/call/implicit |
| ~~~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/call/implicit* F if A is an anchor that calls F, and the calling |
| expression spanned by A is implicit (e.g., the result of a template |
| instantiation). |
| Points from:: |
| anchors |
| Points toward:: |
| <<function,functions>> |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Calls inside template instantiations are implicit."] |
| -------------------------------------------------------------------------------- |
| template <typename T> class C { |
| //- @"T::foo()" ref/call/implicit SFoo |
| int x = T::foo(); |
| }; |
| //- @foo defines/binding SFoo |
| struct S { static int foo(); }; |
| C<S> cs; |
| -------------------------------------------------------------------------------- |
| |
| [[refdoc]] |
| ref/doc |
| ~~~~~~~ |
| |
| Brief description:: |
| A *ref/doc* C if A is an anchor inside a block of documentation that refers |
| to C. |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| See also:: |
| <<documents,documents>> |
| |
| [kythe,C++,"Anchors in documentation can refer to semantic nodes."] |
| -------------------------------------------------------------------------------- |
| //- @param_a ref/doc FooParamA |
| //- FnFoo param.0 FooParamA |
| //- FnFoo.node/kind function |
| /// `param_a` is the first parameter. |
| void foo(int param_a) { } |
| -------------------------------------------------------------------------------- |
| |
| [[refexpands]] |
| ref/expands |
| ~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/expands* M if A is an anchor that expands macro M. |
| Points from:: |
| anchors |
| Points toward:: |
| <<macro,macros>> |
| Ordinals are used:: |
| never |
| Notes:: |
| This edge is used only for first-level macro expansions (where the macro |
| being expanded is spelled out in the source file). Subsequent expansions are |
| recorded using the <<refexpandstransitive,[ref/expands/transitive]>> edge. |
| |
| [kythe,C++,"Uttering the name of a macro expands it."] |
| -------------------------------------------------------------------------------- |
| //- @FOO defines/binding MacroFoo |
| #define FOO BAR |
| //- @FOO ref/expands MacroFoo |
| int FOO; |
| -------------------------------------------------------------------------------- |
| |
| [[refexpandstransitive]] |
| ref/expands/transitive |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/expands/transitive* M if A is an anchor that expands macro M', which |
| (after one or more additional expansions) expands macro M. |
| Points from:: |
| anchors |
| Points toward:: |
| <<macro,macros>> |
| Ordinals are used:: |
| never |
| Notes:: |
| First-level macro expansions (like those written down in the source file) |
| are recorded with the <<refexpands,[ref/expands]>> edge. |
| |
| [kythe,C++,"Macros can expand other macros."] |
| -------------------------------------------------------------------------------- |
| //- @MB defines/binding MacroB |
| #define MB x |
| //- @MA defines/binding MacroA |
| #define MA MB |
| //- @MA ref/expands/transitive MacroB |
| //- @MA ref/expands MacroA |
| //- !{ @MA ref/expands/transitive MacroA } |
| int MA; |
| -------------------------------------------------------------------------------- |
| |
| [[reffile]] |
| ref/file |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *ref/file* F if A is an anchor referencing a file F. This is distinct from |
| <<refincludes,[ref/includes]>>, which indicates that the anchor causes the contents of |
| `F` to be inserted into the surrounding file. *ref/file* should be used when the |
| anchor refers explicitly to the identity of `F`, as in a hardcoded path in a test or |
| build script. |
| Points from:: |
| <<anchor>> |
| Points toward:: |
| <<file>> |
| Ordinals are used:: |
| never |
| |
| [[refimports]] |
| ref/imports |
| ~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/imports* B if B is imported at the site of A. |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| |
| [kythe,Java,"Import references a class."] |
| -------------------------------------------------------------------------------- |
| //- @LinkedList ref/imports LL |
| import java.util.LinkedList; |
| public class E { |
| //- @LinkedList ref LL |
| LinkedList field; |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[refincludes]] |
| ref/includes |
| ~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/includes* F if A is an anchor that inlines the text of file F. |
| Points from:: |
| anchors |
| Points toward:: |
| <<file,files>> |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Includes include files."] |
| -------------------------------------------------------------------------------- |
| //- @"\"test.h\"" ref/includes HeaderFile |
| //- HeaderFile.node/kind file |
| #include "test.h" |
| |
| #example test.h |
| // ... |
| -------------------------------------------------------------------------------- |
| |
| [[refinit]] |
| ref/init |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *ref/init* B if A is an anchor attached to an expression that initializes B, |
| typically a field or variable. |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| |
| [kythe,Go,"Initializer expressions init their fields."] |
| -------------------------------------------------------------------------------- |
| package p |
| |
| type S struct { |
| //- @F defines/binding Field |
| F int |
| } |
| |
| // Positional |
| //- @"17" ref/init Field |
| var _ = S{17} |
| |
| // Key-value |
| //- @F ref Field |
| //- @"101" ref/init Field |
| var _ = S{F: 101} |
| -------------------------------------------------------------------------------- |
| |
| [[refinitimplicit]] |
| ref/init/implicit |
| ~~~~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/init/implicit* B if A is an anchor attached to an expression that |
| initializes B, typically a field or variable, and the expression spanned by A |
| is implicit (e.g., the result of a template instantiation). |
| Points from:: |
| anchors |
| Points toward:: |
| semantic nodes |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Initializers inside template instantiations are implicit."] |
| -------------------------------------------------------------------------------- |
| template<typename T> class C { |
| //- @x ref/init/implicit MemberX |
| T t = {.x = 1}; |
| }; |
| //- @x defines/binding MemberX |
| struct S { int x; }; |
| C<S> cs; |
| -------------------------------------------------------------------------------- |
| |
| [[refqueries]] |
| ref/queries |
| ~~~~~~~~~~~ |
| |
| Brief description:: |
| A *ref/queries* M if A is an anchor that queries whether macro M is bound. |
| Points from:: |
| anchors |
| Points toward:: |
| <<macro,macros>> |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Queries to bound macros are recorded."] |
| -------------------------------------------------------------------------------- |
| //- @FOO defines/binding MacroFoo |
| #define FOO BAR |
| //- @FOO ref/queries MacroFoo |
| //- MacroFoo.node/kind macro |
| #if defined(FOO) |
| #endif |
| //- !{@BAZ ref/queries _} |
| #ifdef BAZ |
| #endif |
| -------------------------------------------------------------------------------- |
| |
| [[satisfies]] |
| satisfies |
| ~~~~~~~~~ |
| |
| Brief description:: |
| A *satisfies* T if A is a type that implicitly satisfies a type T. |
| Points from:: |
| type nodes (<<record>>, <<tapp>>, etc.) |
| Points toward:: |
| type nodes (<<interface>>, <<tapp>>, etc.) |
| Ordinals are used:: |
| never |
| |
| [kythe,Go,"Concrete types satisfy nearby interfaces."] |
| -------------------------------------------------------------------------------- |
| package sat |
| |
| //- @Badger defines/binding Badger |
| //- Badger.node/kind interface |
| type Badger interface { HasBadge() bool } |
| |
| //- @SB defines/binding StaticBadger |
| //- StaticBadger satisfies Badger |
| type SB bool |
| |
| //- @HasBadge defines/binding HasBadge |
| //- HasBadge childof StaticBadger |
| func (s SB) HasBadge() bool { return bool(s) } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Go,"Types of overriding methods satisfy types of overridden interface methods."] |
| -------------------------------------------------------------------------------- |
| package sat |
| |
| //- @HasBadge defines/binding HasBadgeI |
| //- HasBadgeI typed HasBadgeIType |
| type Badger interface { HasBadge() bool } |
| |
| type SB bool |
| |
| //- @HasBadge defines/binding HasBadge |
| //- HasBadge typed HasBadgeType |
| //- HasBadgeType satisfies HasBadgeIType |
| //- ! { HasBadge typed HasBadgeIType } |
| func (s SB) HasBadge() bool { return bool(s) } |
| -------------------------------------------------------------------------------- |
| |
| [[specializes]] |
| specializes |
| ~~~~~~~~~~~ |
| |
| Brief description:: |
| A *specializes* B if A provides a declaration of a type specialization B. |
| Commonly arises from:: |
| template total and partial specialization |
| Points from:: |
| semantic nodes |
| Points toward:: |
| semantic nodes (<<tapp>>) |
| Ordinals are used:: |
| never |
| See also:: |
| <<instantiates>>, <<instantiatesspeculative,[instantiates/speculative]>> |
| |
| [kythe,C++,"Template specializations specialize."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding TemplateClassC |
| template <typename T> class C { }; |
| //- @C defines/binding SpecializedClassC |
| template <> class C<int> { }; |
| //- SpecializedClassC specializes TAppCInt |
| //- TAppCInt.node/kind tapp |
| //- TAppCInt param.0 TemplateClassC |
| //- TemplateClassC.node/kind abs |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Function templates specialize."] |
| -------------------------------------------------------------------------------- |
| //- @id defines/binding IdFn |
| template <typename T> T id(T x) { return x; } |
| //- @id defines/binding IdSpecFn |
| template <> bool id(bool x) { return !(!x); } |
| //- IdSpecFn specializes TAppIdFnBool |
| //- TAppIdFnBool.node/kind tapp |
| //- TAppIdFnBool param.0 IdFn |
| //- TAppIdFnBool param.1 vname("bool#builtin",_,_,_,_) |
| -------------------------------------------------------------------------------- |
| |
| |
| [[specializesspeculative]] |
| specializes/speculative |
| ~~~~~~~~~~~~~~~~~~~~~~~ |
| See <<instantiatesspeculative,[instantiates/speculative]>>. |
| |
| |
| [[tagged]] |
| tagged |
| ~~~~~~ |
| |
| Brief description:: |
| A *tagged* B if B labels A with a <<diagnostic>> message. |
| Commonly arises from:: |
| build/analysis errors |
| Points from:: |
| <<anchor>>, <<file>> |
| Points toward:: |
| <<diagnostic>> |
| Ordinals are used:: |
| never |
| |
| [[typed]] |
| typed |
| ~~~~~ |
| |
| Brief description:: |
| A is *typed* B if A has the type B. |
| Commonly arises from:: |
| terms with types; definitions and declarations |
| Points from:: |
| semantic nodes |
| Points toward:: |
| types |
| Ordinals are used:: |
| never |
| |
| [kythe,C++,"Enumerations can be ascribed types."] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding EnumE |
| //- EnumE typed IntType |
| enum E : int; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Java methods are type applications of the builtin fn type."] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding E |
| public class E { |
| //- @func defines/binding Func |
| //- Func typed FuncType |
| //- FuncType.node/kind tapp |
| //- FuncType param.0 FnBuiltin=vname("fn#builtin","","","","java") |
| //- FuncType param.1 IntBuiltin=vname("int#builtin","","","","java") |
| //- FuncType param.2 E |
| //- FuncType param.3 String |
| //- @String ref String |
| int func(String p) { return 0; } |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[undefines]] |
| undefines |
| ~~~~~~~~~ |
| |
| Brief description:: |
| A *undefines* M if A detaches M from M's binding. |
| Commonly arises from:: |
| macro undefinition |
| Points from:: |
| anchors |
| Points toward:: |
| <<macro,macros>> |
| |
| [kythe,C++,"Undef undefines macros."] |
| -------------------------------------------------------------------------------- |
| //- @FOO defines/binding MacroFoo |
| #define FOO BAR |
| //- @FOO undefines MacroFoo |
| #undef FOO |
| //- @FOO defines/binding DifferentMacroFoo |
| #define FOO BAZ |
| -------------------------------------------------------------------------------- |
| |
| Common node facts |
| ----------------- |
| |
| Some facts can be attached to many different kinds of nodes. A subset of these |
| (called tags) are interesting even if they have no associated values. |
| |
| [[nodekind]] |
| node/kind |
| ~~~~~~~~~ |
| |
| Brief description:: |
| A node's *node/kind* is a label describing the role of the node in the graph. |
| The kind is the one fact every node must have in order to participate in the |
| rest of the schema. |
| Attached to:: |
| all nodes |
| |
| [[code]] |
| code |
| ~~~~ |
| |
| Brief description:: |
| A node's *code* is a serialized link:marked-source.html[MarkedSource] |
| message that can be used to describe that node. |
| Attached to:: |
| semantic nodes |
| |
| [[docuri]] |
| doc/uri |
| ~~~~~~~ |
| |
| Brief description:: |
| If this node's primary documentation exists outside the graph, this fact can |
| hold a URI pointing to that documentation. For example, you may want to link |
| builtin functions to their definitions in a language's reference manual. |
| |
| Attached to:: |
| semantic nodes |
| |
| |
| [[tagdeprecated]] |
| tag/deprecated |
| ~~~~~~~~~~~~~~ |
| |
| Brief description:: |
| If this node should no longer be used, it should be marked with |
| `tag/deprecated`. If this fact has a nonempty value, that value should be |
| set to a UTF8-encoded human-readable reason why the node was deprecated, |
| and/or what should be done in the future. |
| Attached to:: |
| semantic nodes |
| |
| Node kinds |
| ---------- |
| |
| [[abs]] |
| abs |
| ~~~ |
| |
| Brief description:: |
| An *abs* abstracts over a subgraph by binding <<absvar>>s. |
| See also:: |
| <<absvar>>, <<specializes>>, <<tapp>> |
| |
| It is not necessarily the case that the child of the abs node be a type; |
| for example, in $$C++$$, it may be a variable or a function. |
| |
| [kythe,C++,"Templates are abs nodes."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding TemplateC |
| //- TemplateC.node/kind abs |
| //- TemplateCBody childof TemplateC |
| //- TemplateCBody.node/kind record |
| template <typename T, typename S> class C { }; |
| |
| //- @C defines/binding PartialSpecializationC |
| //- PartialSpecializationC.node/kind abs |
| template <typename U> class C<int, U> { }; |
| |
| //- @C defines/binding TotalSpecializationC |
| //- TotalSpecializationC.node/kind record |
| template <> class C<int, float> { }; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Generic classes are abs nodes."] |
| -------------------------------------------------------------------------------- |
| //- @Generics defines/binding GAbs |
| //- Class childof GAbs |
| //- GAbs.node/kind abs |
| //- GAbs param.0 TVar |
| //- @T defines/binding TVar |
| //- TVar.node/kind absvar |
| public class Generics<T> { |
| } |
| |
| -------------------------------------------------------------------------------- |
| |
| [[absvar]] |
| absvar |
| ~~~~~~ |
| |
| Brief description:: |
| An *absvar* is bound by an <<abs>> and valid in its children. |
| See also:: |
| <<abs>>, <<specializes>> |
| |
| [kythe,C++,"Type variables are absvars."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding TemplateC |
| //- @T defines/binding AbsVarT |
| //- AbsVarT.node/kind absvar |
| //- TemplateC param.0 AbsVarT |
| template <typename T> class C { |
| //- @T ref AbsVarT |
| using S = T; |
| }; |
| -------------------------------------------------------------------------------- |
| |
| [[anchor]] |
| anchor |
| ~~~~~~ |
| |
| Brief description:: |
| An *anchor* connects concrete syntax to abstract syntax. |
| Naming convention:: |
| Path::: |
| The *Path* of the <<file>> containing this anchor (or empty if there is no |
| such file). |
| Root::: |
| The *Root* of the <<file>> containing this anchor. |
| Corpus::: |
| The *Corpus* of the <<file>> containing this anchor. |
| Expected out-edges:: |
| <<defines>>, <<definesbinding,[defines/binding]>>, <<ref>>, |
| <<refcall,[ref/call]>> |
| Facts:: |
| loc/start::: |
| The starting byte offset (from 0) in the <<file>> containing this anchor. |
| loc/end::: |
| The ending byte offset (exclusive) in the <<file>> containing this anchor. |
| snippet/start::: |
| The starting byte offset (from 0) of the snippet for this anchor (optional). |
| snippet/end::: |
| The ending byte offset (from 0) of the snippet for this anchor (optional). |
| build/config::: |
| A short name describing the build configuration or platform this anchor |
| targets (optional). |
| subkind:: |
| If set to `implicit`, this anchor should not also have `loc/start` or |
| `loc/end` facts. It is an artifact of some internal process that may still |
| have important semantic effects. |
| See also:: |
| <<file>> |
| |
| Anchor VNames are specified such that one may determine the VName of the |
| <<file>> containing an anchor by dropping the anchor VName's *Language* and |
| *Signature* fields. |
| |
| [kythe,C++,"Anchors have byte offsets."] |
| -------------------------------------------------------------------------------- |
| int 錨; |
| //- VarNameAnchor.loc/start 4 |
| //- VarNameAnchor.loc/end 7 |
| // Note that the glyph 錨 is encoded in UTF-8 as [e9 8c a8]. |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Anchors have VName rules."] |
| -------------------------------------------------------------------------------- |
| //- @foo=vname(_,Corpus,Root,Path,"c++").node/kind anchor |
| //- File=vname("",Corpus,Root,Path,"").node/kind file |
| int foo; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Anchors can overlap."] |
| -------------------------------------------------------------------------------- |
| import java.util.Optional; |
| public class E { |
| //- @"Optional<String>" ref TSpecClass |
| //- @Optional ref OptClass |
| //- @String ref StrClass |
| Optional<String> f; |
| } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Implicit anchors arise from default constructors."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding ClassC |
| //- CCtor childof ClassC |
| //- CCtor.subkind constructor |
| //- CCtor.complete definition |
| class C { }; |
| //- @D defines/binding ClassD |
| //- DCtor childof ClassD |
| //- DCtor.subkind constructor |
| //- DCtor.complete definition |
| class D { C c; }; |
| D d; |
| //- ImplicitCallToCCtor.node/kind anchor |
| //- ImplicitCallToCCtor.subkind implicit |
| //- ImplicitCallToCCtor ref/call/implicit CCtor |
| //- ImplicitCallToCCtor childof DCtor |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Anchors have VName rules."] |
| -------------------------------------------------------------------------------- |
| public class E { |
| //- @foo=vname(_,Corpus,Root,Path,"java").node/kind anchor |
| int foo; |
| } |
| //- File=vname("",Corpus,Root,Path,"").node/kind file |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Go,"Anchors have VName rules."] |
| -------------------------------------------------------------------------------- |
| //- @anchor=vname(_,Corpus,Root,Path,"go").node/kind anchor |
| //- File=vname("",Corpus,Root,Path,"").node/kind file |
| package anchor |
| -------------------------------------------------------------------------------- |
| |
| [[constant]] |
| constant |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *constant* is a value that can be statically determined. |
| Facts:: |
| text::: |
| A string representation of the constant. |
| See also:: |
| <<sum>> |
| |
| [kythe,C++,"Enumerators are constants."] |
| -------------------------------------------------------------------------------- |
| enum E { |
| //- @EM defines/binding Enumerator |
| EM = 42 |
| }; |
| //- Enumerator.node/kind constant |
| //- Enumerator.text 42 |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Enumeration values are constants."] |
| -------------------------------------------------------------------------------- |
| public enum E { |
| //- @A defines/binding A |
| //- A.node/kind constant |
| A; |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[diagnostic]] |
| diagnostic |
| ~~~~~~~~~~ |
| |
| Brief description:: |
| A *diagnostic* is a node with a message concerning some aspect of the related |
| <<file>> or <<anchor>>. These can often result from errors while building or |
| analyzing a compilation and allow an analyzer to surface errors to end-users. |
| Facts:: |
| message::: |
| A relatively short, one-line, human-readable string explaining the |
| diagnostic. The encoding must be UTF-8. |
| details::: |
| Longer form of the message that exposes more detail concerning the |
| diagnostic. This could be very specialized to the particular diagnostic, |
| possibly even containing stack traces or build system logs (optional). |
| context/url::: |
| URL leading to more detailed information concerning this diagnostic or a |
| related group of diagnostics (optional). |
| |
| [[doc]] |
| doc |
| ~~~ |
| Brief description:: |
| A *doc* is text that documents a node. |
| Facts:: |
| text::: |
| The text of the document. The encoding must be UTF-8. |
| Notes:: |
| Embedded references inside a *doc* node's *text* are delimited using `[` |
| and `]`. Ordinary brackets are escaped as `\[` and `\[`; backslash is escaped |
| as `\\`. Targets of embedded references are stored as *param* edges on the |
| document, where the nth opening bracket is matched with the nth *param*. |
| Indexers should strip off comment delimiters. |
| |
| See also:: |
| <<documents>> |
| |
| In the following example, the `\n` in the assertion about `DocNode.text` is |
| stored as a newline in the graph. The escape is there for the verifier. |
| |
| [kythe,C++,"Doc nodes contain documentation text."] |
| -------------------------------------------------------------------------------- |
| /// A function. |
| /// It sums its parameters `x` and `y`. |
| int f(int x, int y) { |
| return x + y; |
| } |
| //- DocNode documents FnF |
| //- DocNode.node/kind doc |
| //- DocNode.text " A function.\n It sums its parameters `[x]` and `[y]`." |
| //- DocNode param.0 VarX |
| //- DocNode param.1 VarY |
| //- FnF param.0 VarX |
| //- FnF param.1 VarY |
| -------------------------------------------------------------------------------- |
| |
| [[file]] |
| file |
| ~~~~ |
| |
| Brief description:: |
| A *file* is an array of bytes with a significant external name. |
| Naming convention:: |
| Language::: |
| *empty* |
| Path::: |
| *External path to this file (or some other unique ID if this file is |
| virtual)* |
| Signature::: |
| *empty* |
| Facts:: |
| text::: |
| Uninterpreted content as an array of bytes. |
| text/encoding::: |
| Encoding of the text fact. See |
| http://www.w3.org/TR/encoding/#names-and-labels for standard values. If |
| empty, "UTF-8" is assumed. |
| See also:: |
| <<anchor>>, <<refincludes,[ref/includes]>> |
| |
| [kythe,C++,"File tickets are related to anchor tickets."] |
| -------------------------------------------------------------------------------- |
| int x; |
| //- XAnchor=vname(_,Corpus,Root,Path,"c++").node/kind anchor |
| //- XAnchor.loc/start 4 |
| //- XAnchor.loc/end 5 |
| //- SourceFile=vname("",Corpus,Root,Path,"").node/kind file |
| -------------------------------------------------------------------------------- |
| |
| [[interface]] |
| interface |
| ~~~~~~~~~ |
| |
| Brief description:: |
| An *interface* defines an implementable type. |
| |
| [kythe,Java,"Interfaces are interfaces."] |
| -------------------------------------------------------------------------------- |
| //- @I defines/binding Interface |
| //- Interface.node/kind interface |
| public interface I {} |
| -------------------------------------------------------------------------------- |
| |
| [[function]] |
| function |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *function* binds zero or more parameters and returns a result. |
| Facts:: |
| complete::: |
| `incomplete` if this is only a declaration; `definition` if it is a |
| definition. |
| subkind::: |
| `constructor` for constructors; `destructor` for destructors; |
| `none` or unspecified for normal or member functions. |
| |
| [kythe,C++,"Functions are functions."] |
| -------------------------------------------------------------------------------- |
| //- @F defines/binding FnF |
| //- FnF.node/kind function |
| //- FnF.complete incomplete |
| //- @X defines/binding VarX |
| //- VarX.complete incomplete |
| //- FnF param.0 VarX |
| void F(int X); |
| -------------------------------------------------------------------------------- |
| |
| [[lookup]] |
| lookup |
| ~~~~~~~ |
| |
| Brief description:: |
| A *lookup* is a structured name whose resolution cannot be completed |
| without additional context. |
| Facts:: |
| text::: |
| The deferred name to be resolved. |
| Notes:: |
| Name resolution can be a complicated problem. In $$C++$$ templates, the |
| meaning of a dependent name cannot be determined until the template |
| parameters it depends upon are supplied. Similarly, in dynamic languages |
| like Python, name resolution may depend on the runtime context. |
| Nevertheless, when we are unable to come up with a semantic representation |
| of one or more nodes in a path-structured name, we record this name as |
| a collection of *lookup* nodes. Each *lookup* node has some *text* (the |
| 'dynamic' lookup done at that node) as well as some *params* (to record the |
| semantic object into which *text* is being used as a key). |
| |
| [kythe,C++,"Dependent names are lookups."] |
| -------------------------------------------------------------------------------- |
| template |
| //- @T defines/binding DepT |
| <template <typename> class T> |
| struct C { |
| //- @D ref DepTIntD |
| using S = typename T<int>::D; |
| }; |
| //- DepTIntD.text D |
| //- DepTIntD.node/kind lookup |
| //- DepTIntD param.0 DepTInt |
| //- DepTInt.node/kind tapp |
| //- DepTInt param.0 DepT |
| //- DepTInt param.1 Int |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Lookups record paths."] |
| -------------------------------------------------------------------------------- |
| template |
| <template <typename> class T> |
| struct C { |
| //- @F ref DepTIntDEF |
| //- DepTIntDEF.text F |
| //- @E ref DepTIntDE |
| //- DepTIntDE.text E |
| //- @D ref DepTIntD |
| //- DepTIntD.text D |
| using S = typename T<int>::D::E::F; |
| }; |
| //- DepTIntDEF param.0 DepTIntDE |
| //- DepTIntDE param.0 DepTIntD |
| -------------------------------------------------------------------------------- |
| |
| [[macro]] |
| macro |
| ~~~~~ |
| Brief description:: |
| A *macro* is a metaprogram that operates on source text. |
| Notes:: |
| Macros are distinct from <<abs,abs>> because they do not |
| participate in the programming language proper. Instead, they are evaluated |
| separately, usually before semantic analysis takes place. |
| See also:: |
| <<refexpands,[ref/expands]>>, <<refexpandstransitive,[ref/expands/transitive]>>, |
| <<refqueries,[ref/queries]>>, <<undefines,[undefines]>> |
| |
| [kythe,C++,"Defines define macros."] |
| -------------------------------------------------------------------------------- |
| //- @FOO defines/binding MacroFoo |
| //- MacroFoo.node/kind macro |
| #define FOO BAR |
| -------------------------------------------------------------------------------- |
| |
| [[meta]] |
| meta |
| ~~~~ |
| Brief description:: |
| A *meta* is a node that describes details about a particular language. |
| Naming convention:: |
| Signature::: |
| *kythe-node-name*#meta |
| Language::: |
| See <<lsr,Language-specific rules>> for language identifiers. |
| |
| [kythe,C++,"C++ defines a meta node for tapps."] |
| -------------------------------------------------------------------------------- |
| //- vname("tapp#meta","","","","c++").node/kind meta |
| -------------------------------------------------------------------------------- |
| |
| [[name]] |
| name |
| ~~~~ |
| |
| Brief description:: |
| A *name* specifies an external identifier for a node, typically used for linking. |
| Naming convention:: |
| Signature::: |
| The name string. |
| Language::: |
| The namespace to which the name belongs. |
| Path::: |
| *empty* |
| Root::: |
| *empty* |
| Corpus::: |
| *empty* |
| Notes:: |
| The namespace is some domain in which the names are expected to be unique at linkage |
| time and/or runtime, such as JVM binary names, or the Itanium C++ ABI. |
| |
| [kythe,Java,"JVM binary class names, as used for classloading, are names."] |
| -------------------------------------------------------------------------------- |
| package pkg; |
| //- @C defines/binding CClass |
| //- CClass named CClassName = vname("pkg.C", "", "", "", "jvm") |
| //- CClassName.node/kind name |
| public class C { |
| //- @Inner defines/binding InnerClass |
| //- InnerClass named InnerClassName = vname("pkg.C$Inner", "", "", "", "jvm") |
| //- InnerClassName.node/kind name |
| public class Inner {} |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[package]] |
| package |
| ~~~~~~ |
| |
| Brief description:: |
| A *package* defines a module containing declarations. |
| |
| [kythe,Java,"Top-level declarations are children of package nodes."] |
| -------------------------------------------------------------------------------- |
| //- @pkg ref Pkg |
| //- Pkg.node/kind package |
| package pkg; |
| //- @E defines/binding ClassE |
| //- ClassE childof Pkg |
| public class E {} |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Go,"Files belonging to a package are children of that package."] |
| -------------------------------------------------------------------------------- |
| //- @foo defines/binding Pkg |
| //- Pkg.node/kind package |
| package foo |
| |
| //- File = vname("", _, _, "schema/example.go", "").node/kind file |
| //- File childof Pkg |
| -------------------------------------------------------------------------------- |
| |
| [[process]] |
| process |
| ~~~~~~~ |
| |
| Brief description:: |
| A *process* describes an abstract processing action in a workflow. |
| Facts:: |
| label::: |
| A string label used to identify the process (optional). |
| See also:: |
| <<depends>> |
| |
| A *process* defines a processing action such as a step in a build or the |
| execution of a continuous integration workflow. For workflows that assign |
| identifying labels to processing steps (such as target names), the `label` |
| should carry the name so assigned. |
| |
| [[record]] |
| record |
| ~~~~~~ |
| |
| Brief description:: |
| A *record* defines a type composed of a collection of elements. |
| Facts:: |
| subkind::: |
| <<lsr,Language-specific subkind>> for this record. |
| complete::: |
| `incomplete` if this is only a declaration; `definition` if it is a |
| definition. |
| Notes:: |
| This node is a nominal record such that two records with the same |
| children but different names should always be considered to be distinct. |
| |
| [kythe,C++,"Classes are records."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding ClassCDecl |
| //- ClassCDecl.node/kind record |
| //- ClassCDecl.complete incomplete |
| class C; |
| |
| //- @C defines/binding ClassCDefn |
| //- ClassCDefn.node/kind record |
| //- ClassCDefn.complete definition |
| class C { }; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Classes are records."] |
| -------------------------------------------------------------------------------- |
| package pkg; |
| //- @E defines/binding ClassE |
| //- ClassE.node/kind record |
| //- ClassE.subkind class |
| public class E { |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[sum]] |
| sum |
| ~~~ |
| |
| Brief description:: |
| A *sum* defines a type whose instances must choose one out of a set of |
| possible representations. |
| Facts:: |
| subkind::: |
| <<lsr,Language-specific subkind>> for this record. |
| complete::: |
| * `incomplete` if this is only a declaration. |
| * `complete` if this is a declaration that is considered usable by value. |
| * `definition` if this provides a full description of the type. |
| |
| [kythe,C++,"Enums are sums."] |
| -------------------------------------------------------------------------------- |
| //- @CE defines/binding EnumCE |
| //- EnumCE.node/kind sum |
| //- EnumCE.complete definition |
| enum CE { }; |
| |
| //- @E defines/binding EnumE |
| //- EnumE.node/kind sum |
| //- EnumE.complete incomplete |
| enum class E; |
| |
| //- @E defines/binding EnumETyped |
| //- EnumETyped.node/kind sum |
| //- EnumETyped.complete complete |
| enum class E : int; |
| |
| //- @E defines/binding EnumEDefn |
| //- EnumEDefn.node/kind sum |
| //- EnumEDefn.complete definition |
| enum class E : int { }; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Enums are sum/enumClasses."] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding EnumE |
| //- E.node/kind sum |
| //- E.subkind enumClass |
| public enum E {} |
| -------------------------------------------------------------------------------- |
| |
| [[symbol]] |
| symbol |
| ~~~~~~ |
| |
| Brief description:: |
| A *symbol* is a common name used by tools to refer to a set of objects. |
| The spelling of a symbol is defined per language, and should be constructible by |
| tools that do not necessarily have direct access to the compiler. |
| The rules for binding a symbol to a particular object from this set may depend on |
| external configuration (such as the list of libraries being linked together to produce |
| an executable). |
| Naming convention:: |
| Path::: |
| *empty* |
| Root::: |
| *empty* |
| Corpus::: |
| *empty* |
| |
| [[talias]] |
| talias |
| ~~~~~~ |
| |
| Brief description:: |
| A *talias* gives a new name to an existing type. |
| Expected out-edges:: |
| <<aliases>> |
| Notes:: |
| A *talias* may be virtually removed from the graph. Some languages may have |
| additional reduction rules. |
| |
| [kythe,C++,"Type aliases are taliases."] |
| -------------------------------------------------------------------------------- |
| //- @Counter defines/binding TAlias |
| //- TAlias.node/kind talias |
| using Counter = int; |
| -------------------------------------------------------------------------------- |
| |
| [[tapp]] |
| tapp |
| ~~~~ |
| |
| Brief description:: |
| A *tapp* applies a type constructor or <<abs>> to zero or more parameters. |
| Expected out-edges:: |
| <<param>> (at least ordinal 0) |
| |
| [kythe,C++,"Pointers are type constructors."] |
| -------------------------------------------------------------------------------- |
| //- @PtrInt defines/binding PtrIntAlias |
| //- PtrIntAlias aliases IntPtrType |
| using PtrInt = int*; |
| //- IntPtrType.node/kind tapp |
| //- IntPtrType param.0 vname("ptr#builtin",_,_,_,"c++") |
| //- IntPtrType param.1 vname("int#builtin",_,_,_,"c++") |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Generic classes are type constructors."] |
| -------------------------------------------------------------------------------- |
| import java.util.Optional; |
| public class E { |
| //- @f defines/binding Field |
| //- Field typed TSpecClass |
| //- TSpecClass.node/kind tapp |
| //- TSpecClass param.0 OptClass |
| //- TSpecClass param.1 StrClass |
| Optional<String> f; |
| } |
| -------------------------------------------------------------------------------- |
| |
| [[tbuiltin]] |
| tbuiltin |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *tbuiltin* is a type that is supplied by the language itself. |
| Naming convention:: |
| Signature::: |
| *language-specific-string*#builtin |
| Notes:: |
| See the <<lsr,Language-specific rules>> section below for enumerations of |
| these builtin types. |
| |
| [kythe,C++,"Int is a builtin."] |
| -------------------------------------------------------------------------------- |
| //- @int ref TInt |
| //- TInt.node/kind tbuiltin |
| using Int = int; |
| -------------------------------------------------------------------------------- |
| |
| [[tnominal]] |
| tnominal |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *tnominal* is a type that may be purely identified by its name. |
| Notes:: |
| When a `tnominal`'s definition is known, some <<lsr,language-specific rules>> |
| dictate that the definition node be used instead of a `tnominal` in the |
| type graph. |
| |
| [kythe,C++,"Forward-declared classes are tnominals."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding ClassC |
| //- ClassC.node/kind record |
| class C; |
| //- @Alias defines/binding Alias |
| //- Alias aliases PtrC |
| //- PtrC param.1 NominalC |
| //- NominalC.node/kind tnominal |
| using Alias = C*; |
| -------------------------------------------------------------------------------- |
| |
| |
| [[tsigma]] |
| tsigma |
| ~~~~ |
| |
| Brief description:: |
| A *tsigma* is an ordered list of types that is unpacked on substitution. |
| Expected out-edges:: |
| <<param>> (at least ordinal 0) |
| |
| [kythe,C++,"Parameter packs unpack tsigmas."] |
| -------------------------------------------------------------------------------- |
| template <typename... Ts> |
| //- @f defines/binding FnTF |
| void f(Ts... ts) { } |
| |
| //- @int ref IntType |
| //- @double ref DoubleType |
| //- @f ref AppFnTFSigma |
| int g(double x) { f(1, x); } |
| |
| //- FnF instantiates AppFnTFSigma |
| //- FnF.node/kind function |
| //- AppFnTFSigma param.0 FnTF |
| //- AppFnTFSigma param.1 Sigma |
| //- Sigma.node/kind tsigma |
| //- Sigma param.0 IntType |
| //- Sigma param.1 DoubleType |
| -------------------------------------------------------------------------------- |
| |
| |
| [[variable]] |
| variable |
| ~~~~~~~~ |
| |
| Brief description:: |
| A *variable* is a location for storing data. |
| Facts:: |
| complete::: |
| * `incomplete` if this is only a declaration. |
| * `definition` if this is a variable definition. |
| |
| [kythe,C++,"Variables are variables."] |
| -------------------------------------------------------------------------------- |
| //- @x defines/binding VariableX |
| //- VariableX.node/kind variable |
| int x; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Fields are variables."] |
| -------------------------------------------------------------------------------- |
| public class E { |
| //- @f defines/binding Field |
| //- Field.node/kind variable |
| Optional<String> f; |
| } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Parameters are variables."] |
| -------------------------------------------------------------------------------- |
| public class E { |
| //- @arg defines/binding Param |
| //- Param.node/kind variable |
| void f(String arg) {} |
| } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Locals are variables."] |
| -------------------------------------------------------------------------------- |
| public class E { |
| void f() { |
| //- @var defines/binding Local |
| //- Local.node/kind variable |
| String var; |
| } |
| } |
| -------------------------------------------------------------------------------- |
| |
| |
| [[vcs]] |
| vcs |
| ~~~ |
| |
| Brief description:: |
| A *vcs* is a reference to a particular revision stored in a version control |
| system. |
| Facts:: |
| vcs/id::: |
| A stable identifier for a revision in the repository. For example, a |
| Git repository uses commit hashes as identifiers. |
| vcs/type::: |
| * `darcs`: this is a Darcs repository. |
| * `git`: this is a Git repository. |
| * `hg`: this is a Mercurial repository. |
| * `perforce`: this is a Perforce repository. |
| * `svn`: this is a Subversion repository. |
| vcs/uri::: |
| A URI that points to the repository root. Acceptable values for this fact |
| depend on the `vcs/type`. |
| Naming convention:: |
| When naming a `vcs` node, it is a good idea to use only the `corpus` field |
| of a VName. You can then use that `corpus` value in the VNames of all nodes |
| that are generated from that revision. |
| Notes:: |
| It is important that the `vcs` uses a stable reference to a revision. For |
| example, using the name of a Git branch would not be a good idea, since |
| Git branches point to different commits over time. It is better to use the |
| (full) hash of the commit. |
| |
| [[variance]] |
| Variance |
| -------- |
| |
| Some languages (like Objective C) allow you to specify the variance of a |
| type argument as it relates to the typing relationship of the class it is a |
| parameter for. This is different than the bounds that may be placed on a type |
| variable. The bounds are represented with <<bounded>> edges. Variance is |
| stored as a fact in the node for the type variable. |
| |
| For example, `@interface G1<__covariant Type : P1*> : Root` states that `G1` is a |
| generic type, `G1` takes a single type parameter that has an upper bound of `P1*`, |
| and `G1<T>` is a subtype of `G1<U>` if and only if `T` is a subtype of `U`. |
| |
| Specifically for Objective C, the default variance is invariant, so |
| `@interface G1<Type : P1*> : Root` states that `G1<T>` is a subtype of `G2<U>` |
| if and only if T == U. |
| |
| The variance fact can be omitted, in which case covariance is assumed. |
| |
| [kythe,ObjC,"Variance for a generic type"] |
| -------------------------------------------------------------------------------- |
| @interface Root |
| @end |
| |
| @interface P1 : Root |
| @end |
| |
| @interface P2 : P1 |
| @end |
| |
| //- @Type defines/binding TypeVar1 |
| //- @G1 defines/binding G1Abs |
| //- TypeVar1.node/kind absvar |
| //- TypeVar1.variance covariant |
| //- G1Decl childof G1Abs |
| //- G1Abs.node/kind abs |
| //- G1Abs param.0 TypeVar1 |
| @interface G1<__covariant Type> : Root |
| @end |
| |
| //- @Type defines/binding TypeVar2 |
| //- @G2 defines/binding G2Abs |
| //- TypeVar2.node/kind absvar |
| //- TypeVar2.variance contravariant |
| //- G2Decl childof G2Abs |
| //- G2Abs.node/kind abs |
| //- G2Abs param.0 TypeVar2 |
| @interface G2<__contravariant Type> : Root |
| @end |
| |
| int main(int argc, char **argv) { |
| // Example of variance in action. |
| G1<P2*> *g1var = [[G1 alloc] init]; |
| G1<P1*> *g1var2 = g1var; |
| |
| G2<P1*> *g2var = [[G1 alloc] init]; |
| G2<P2*> *g2var2 = g2var; |
| |
| return 0; |
| } |
| -------------------------------------------------------------------------------- |
| |
| |
| [[lsr]] |
| Language-specific rules |
| ----------------------- |
| |
| $$C++$$ |
| ~~~~~~~ |
| |
| $$C++$$'s source language is spelled "`c++`". |
| |
| Builtin types |
| ^^^^^^^^^^^^^ |
| |
| $$C++$$ supplies the following <<tbuiltin>> nodes by default: |
| |
| [kythe,C++,"Builtin type nodes"] |
| -------------------------------------------------------------------------------- |
| //- @"void" ref vname("void#builtin","","","","c++") |
| using Void = void; |
| |
| //- @PtrVoid defines/binding AliasTappPtrVoid |
| //- AliasTappPtrVoid aliases TappPtrVoid |
| //- TappPtrVoid param.0 vname("ptr#builtin","","","","c++") |
| using PtrVoid = void*; |
| |
| //- @"int" ref vname("int#builtin","","","","c++") |
| using Int = int; |
| |
| //- @ConstVoid defines/binding TappConstVoidAlias |
| //- TappConstVoidAlias aliases TAppConstVoid |
| //- TAppConstVoid param.0 vname("const#builtin","","","","c++") |
| using ConstVoid = const void; |
| |
| //- @VolatileVoid defines/binding TappVolatileVoidAlias |
| //- TappVolatileVoidAlias aliases TAppVolatileVoid |
| //- TAppVolatileVoid param.0 vname("volatile#builtin","","","","c++") |
| using VolatileVoid = volatile void; |
| |
| ///- @RestrictPtrVoid defines/binding TappRestrictPtrVoidAlias |
| ///- TappRestrictPtrVoidAlias aliases TAppRestrictPtrVoid |
| ///- TAppRestrictPtrVoid param.0 vname("restrict#builtin","","","","c++") |
| using RestrictPtrVoid = void * __restrict__; |
| -------------------------------------------------------------------------------- |
| |
| Record and sum subkinds |
| ^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| $$C++$$ defines the following subkinds for <<record>> nodes: |
| |
| [kythe,C++,"Record subkinds"] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding ClassC |
| //- C.subkind class |
| class C; |
| |
| //- @S defines/binding StructS |
| //- S.subkind struct |
| struct S; |
| |
| //- @U defines/binding UnionU |
| //- U.subkind union |
| union U; |
| -------------------------------------------------------------------------------- |
| |
| $$C++$$ defines the following subkinds for <<sum>> nodes: |
| |
| [kythe,C++,"Sum subkinds"] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding EnumE |
| //- E.subkind enum |
| enum E { }; |
| |
| //- @EC defines/binding EnumClassEC |
| //- EnumClassEC.subkind enumClass |
| enum class EC; |
| -------------------------------------------------------------------------------- |
| |
| References to definitions and declarations of types |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| If the indexer has available a *definition* of a $$C++$$ node, edges should |
| be drawn directly to that node: |
| |
| [kythe,C++,"Refer to definitions directly."] |
| -------------------------------------------------------------------------------- |
| //- @C defines/binding ClassCDefn |
| class C { }; |
| //- @Alias defines/binding CAlias |
| //- CAlias aliases ClassCDefn |
| using Alias = C; |
| -------------------------------------------------------------------------------- |
| |
| If the indexer only has a *complete* $$C++$$ node, or if the node is |
| *incomplete*, edges should be drawn to a <<tnominal>> node: |
| |
| [kythe,C++,"Refer to complete or incomplete declarations indirectly."] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding CompleteEnumE |
| enum class E : int; |
| //- @Alias defines/binding EAlias |
| //- EAlias aliases EnumETNominal |
| //- EnumETNominal.node/kind tnominal |
| using Alias = E; |
| -------------------------------------------------------------------------------- |
| |
| When generating the name of a $$C++$$ type that requires looking down some |
| edge, the following should be kept in mind. If there are multiple possible |
| nodes connected by *edge*, consistently prefer one that has a `complete` |
| fact set to `definition`; failing that, prefer one that has a `complete` |
| fact set to `complete`; failing that, consistently prefer an arbitrary |
| node from the *edge*-connected set (see <<record>>, <<sum>>). |
| |
| Qualifiers on types |
| ^^^^^^^^^^^^^^^^^^^ |
| |
| The `const`, `restrict`, and `volatile` qualifiers may be applied to types. |
| These are represented as type constructors. The indexer always applies them |
| in the same order (`const` innermost, then `restrict`, then `volatile`) and |
| collapses redundant qualifiers should they arise (`const const` becomes |
| `const`). Tools should optimally canonicalize types according to these rules |
| (for instance, after removing a <<talias>> node). |
| |
| [kythe,C++,"Qualifiers have canonical order."] |
| -------------------------------------------------------------------------------- |
| //- @U defines/binding VRCAlias |
| //- VRCAlias aliases VRCInt |
| using U = int * __restrict__ const volatile; |
| //- @V defines/binding AnotherAlias |
| //- AnotherAlias aliases VRCInt |
| using V = int * volatile __restrict__ const; |
| -------------------------------------------------------------------------------- |
| |
| [kythe,C++,"Redundant CVR-qualifiers are dropped."] |
| -------------------------------------------------------------------------------- |
| #arguments -Wno-duplicate-decl-specifier |
| //- @U defines/binding CIAlias |
| //- CIAlias aliases CIType |
| using U = const const int; |
| //- @V defines/binding AnotherCIAlias |
| //- AnotherCIAlias aliases CIType |
| using V = const int; |
| -------------------------------------------------------------------------------- |
| |
| Function types |
| ^^^^^^^^^^^^^^ |
| |
| The `fn#builtin` type constructor is used to represent function types. Its |
| first parameter is the return type; its second parameter is the receiver type; |
| subsequent parameters are arguments. Functions without an explicit return type |
| will return a language-specific "void" type. Functions without a receiver type |
| will use a language-specific "empty" receiver type. |
| |
| [kythe,C++,"C++ function types use a builtin type constructor."] |
| -------------------------------------------------------------------------------- |
| //- @U defines/binding UAlias |
| //- UAlias aliases TAppFn |
| //- TAppFn param.0 vname("fn#builtin",_,_,_,_) |
| //- TAppFn param.1 vname("int#builtin",_,_,_,_) |
| //- TAppFn param.2 vname("short#builtin",_,_,_,_) |
| //- TAppFn param.3 vname("float#builtin",_,_,_,_) |
| using U = int(short, float); |
| // TODO(#3613): add receiver type to C++ function types |
| -------------------------------------------------------------------------------- |
| |
| For K&R-style prototypes in C, the indexer will use the `knrfn#builtin` type. |
| |
| [kythe,Go,"Function types use a builtin type constructor."] |
| -------------------------------------------------------------------------------- |
| package foo |
| |
| //- @fn defines/binding Func |
| //- Func typed FuncType |
| //- FuncType.node/kind tapp |
| //- FuncType param.0 FnBuiltin=vname("fn#builtin",_,_,_,_) |
| //- FnBuiltin.node/kind tbuiltin |
| func fn() {} |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Go,"Go void functions return the empty tuple type."] |
| -------------------------------------------------------------------------------- |
| package foo |
| |
| //- @fn defines/binding Func |
| //- Func typed FuncType |
| //- FuncType param.1 EmptyTuple |
| //- EmptyTuple.node/kind tapp |
| //- EmptyTuple param.0 TupleBuiltin=vname("tuple#builtin",_,_,_,_) |
| //- TupleBuiltin.node/kind tbuiltin |
| //- ! { EmptyTuple param.1 _ } |
| func fn() {} |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Go,"Go functions have an empty tuple type receiver."] |
| -------------------------------------------------------------------------------- |
| package foo |
| |
| //- @fn defines/binding Func |
| //- Func typed FuncType |
| //- FuncType param.2 EmptyTuple |
| //- EmptyTuple.node/kind tapp |
| //- EmptyTuple param.0 TupleBuiltin=vname("tuple#builtin",_,_,_,_) |
| //- TupleBuiltin.node/kind tbuiltin |
| //- ! { EmptyTuple param.1 _ } |
| func fn() {} |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Go,"Go methods have a non-empty receiver type."] |
| -------------------------------------------------------------------------------- |
| package foo |
| |
| //- @S defines/binding S |
| type S struct {} |
| |
| //- @Method defines/binding Method |
| //- Method typed MethodType |
| //- MethodType param.2 S |
| func (S) Method() {} |
| |
| //- @PMethod defines/binding PMethod |
| //- PMethod typed PMethodType |
| //- PMethodType param.2 SPointer |
| //- SPointer.node/kind tapp |
| //- SPointer param.0 vname("pointer#builtin",_,_,_,_) |
| //- SPointer param.1 S |
| func (*S) PMethod() {} |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Java constructors have their parent class as a return/receiver type."] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding E |
| public class E { |
| //- @E defines/binding ECtor |
| //- ECtor typed FnType |
| //- FnType.node/kind tapp |
| //- FnType param.0 vname("fn#builtin",_,_,_,_) |
| //- FnType param.1 E |
| //- FnType param.2 E |
| public E() {} |
| } |
| -------------------------------------------------------------------------------- |
| |
| [kythe,Java,"Java static methods have a void receiver type."] |
| -------------------------------------------------------------------------------- |
| public class E { |
| //- @f defines/binding F |
| //- F typed FnType |
| //- FnType.node/kind tapp |
| //- FnType param.0 vname("fn#builtin",_,_,_,_) |
| //- FnType param.1 vname("int#builtin",_,_,_,_) |
| //- FnType param.2 vname("void#builtin",_,_,_,_) |
| public static int f() { return 0; } |
| } |
| -------------------------------------------------------------------------------- |
| |
| Structural hashes |
| ^^^^^^^^^^^^^^^^^ |
| |
| <<record>> and <<sum>> definitions are given vnames with `signatures` composed |
| of their lexical names and their *structural hash*, which unifies equivalent |
| definitions that appear across distinct and unrelated translation units. |
| |
| Template template parameters |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| Template template parameters are stored as <<abs>>-dominated <<absvar>> |
| parameters of their binding abstractions. The name of the template template |
| parameter is given to the inner <<abs>>. |
| |
| [kythe,C++,"We do not represent higher kinds"] |
| -------------------------------------------------------------------------------- |
| //- @A defines/binding AbsvarA |
| //- @B defines/binding NestedAbs |
| //- @C defines/binding TemplateC |
| template <template <typename A> class B> class C; |
| //- TemplateC param.0 NestedAbs |
| //- NestedAbs.node/kind abs |
| //- NestedAbsvar childof NestedAbs |
| //- NestedAbs param.0 AbsvarA |
| -------------------------------------------------------------------------------- |
| |
| Special values for dependent lookups |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| Sometimes, the indexer must synthesize a <<lookup>> node to a constructor or |
| destructor without knowing the name of the type being constructed or destroyed. |
| In this case, the constructor (or destructor) is named `#ctor` (or `#dtor`): |
| |
| [kythe,C++,"Dependent ctors and dtors"] |
| -------------------------------------------------------------------------------- |
| //- @T defines/binding TyvarT |
| template <typename T> |
| class C : T { |
| //- @"T()" ref/call LookupTCtor |
| //- LookupTCtor.node/kind lookup |
| //- LookupTCtor param.0 TyvarT |
| //- LookupTCtor.text "#ctor" |
| C() : T() { } |
| |
| T *t; |
| //- @"delete t" ref/call LookupTDtor |
| //- LookupTDtor.node/kind lookup |
| //- LookupTDtor param.0 TyvarT |
| //- LookupTDtor.text "#dtor" |
| void f() { delete t; } |
| }; |
| -------------------------------------------------------------------------------- |
| |
| Go |
| ~~ |
| |
| The source language for Go is spelled "`go`". |
| |
| Type Definitions |
| ^^^^^^^^^^^^^^^^ |
| |
| A Go type definition like `type Foo Bar` creates a new named type `Foo` with |
| the same structure as `Bar` but with a distinct method set. In the Kythe schema |
| we model `Foo` as a <<record>> node. If the underlying type is not already a |
| struct this node is given the subkind `type`. |
| |
| [kythe,Go,"Type definitions"] |
| -------------------------------------------------------------------------------- |
| package tdef |
| |
| //- @Foo defines/binding Foo |
| //- Foo.node/kind record |
| //- Foo.subkind type |
| type Foo int |
| |
| type bar struct { z int } |
| |
| //- @Bar defines/binding Bar |
| //- Bar.node/kind record |
| //- Bar.subkind struct |
| type Bar bar |
| |
| //- @Pbar defines/binding Pbar |
| //- Pbar.node/kind record |
| //- Pbar.subkind type |
| type Pbar []bar |
| -------------------------------------------------------------------------------- |
| |
| Java |
| ~~~~ |
| |
| Java's source language is spelled "`java`". |
| |
| Builtin types |
| ^^^^^^^^^^^^^ |
| |
| Java supplies the following <<tbuiltin>> nodes by default: |
| |
| [kythe,Java,"Builtin type nodes"] |
| -------------------------------------------------------------------------------- |
| public class E { |
| //- @f defines/binding F |
| //- F typed FnType |
| //- FnType.node/kind tapp |
| //- FnType param.0 FnBuiltin = vname("fn#builtin","","","","java") |
| //- FnType param.1 VoidBuiltin = vname("void#builtin","","","","java") |
| public static void f( |
| //- FnType param.3 BooleanBuiltin = vname("boolean#builtin","","","","java") |
| boolean bool, |
| //- FnType param.4 ByteBuiltin = vname("byte#builtin","","","","java") |
| byte b, |
| //- FnType param.5 ShortBuiltin = vname("short#builtin","","","","java") |
| short s, |
| //- FnType param.6 IntBuiltin = vname("int#builtin","","","","java") |
| int i, |
| //- FnType param.7 LongBuiltin = vname("long#builtin","","","","java") |
| long l, |
| //- FnType param.8 CharBuiltin = vname("char#builtin","","","","java") |
| char c, |
| //- FnType param.9 FloatBuiltin = vname("float#builtin","","","","java") |
| float f, |
| //- FnType param.10 DoubleBuiltin = vname("double#builtin","","","","java") |
| double d, |
| //- FnType param.11 StrArray |
| //- StrArray.node/kind tapp |
| //- StrArray param.0 ArrayBuiltin = vname("array#builtin","","","","java") |
| //- StrArray param.1 String |
| String[] arry) {} |
| } |
| -------------------------------------------------------------------------------- |
| |
| |
| Node Subkinds |
| ^^^^^^^^^^^^^ |
| |
| Classes and Enums |
| +++++++++++++++++ |
| |
| In Java, classes are [[record]] nodes with a subkind of 'class'. Likewise, enum |
| classes are [[sum]] nodes with a subkind of 'enumClass'. |
| |
| [kythe,Java,"Classes and enums"] |
| -------------------------------------------------------------------------------- |
| //- @E defines/binding EClass |
| //- EClass.node/kind record |
| //- EClass.subkind class |
| public class E { |
| |
| //- @Enum defines/binding Enum |
| //- Enum.node/kind sum |
| //- Enum.subkind enumClass |
| static enum Enum {} |
| } |
| -------------------------------------------------------------------------------- |
| |
| Functions |
| +++++++++ |
| |
| All methods are [[function]] nodes, including class constructors. To |
| differentiate between constructors and other methods, [[function]] nodes for |
| constructors have the subkind 'constructor'. |
| |
| [kythe,Java,"Methods and constructors"] |
| -------------------------------------------------------------------------------- |
| public class E { |
| |
| //- @E defines/binding ECtor |
| //- ECtor.node/kind function |
| //- ECtor.subkind constructor |
| public E() {} |
| |
| //- @staticMethod defines/binding StaticMethod |
| //- StaticMethod.node/kind function |
| public static void staticMethod() {} |
| |
| //- @instanceMethod defines/binding InstanceMethod |
| //- InstanceMethod.node/kind function |
| public void instanceMethod() {} |
| } |
| -------------------------------------------------------------------------------- |
| |
| Variables |
| +++++++++ |
| |
| Java has 5 types of [[variable]] nodes, each with a distinct subkind: |
| |
| Fields:: 'field' subkind |
| Locals:: 'local' subkind |
| Exception Variables (see http://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html[catch blocks]):: 'local/exception' subkind |
| Parameters:: 'local/parameter' subkind |
| Resource Variables (see the http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html[try-with-resources statement]):: 'local/resource' subkind |
| |
| [kythe,Java,"Variables"] |
| -------------------------------------------------------------------------------- |
| import java.io.IOException; |
| import java.io.OutputStream; |
| |
| public class E { |
| |
| //- @field defines/binding Field |
| //- Field.node/kind variable |
| //- Field.subkind field |
| private final Object field = null; |
| |
| //- @param defines/binding Parameter |
| //- Parameter.node/kind variable |
| //- Parameter.subkind local/parameter |
| public static void m(String param) throws IOException { |
| |
| //- @local defines/binding Local |
| //- Local.node/kind variable |
| //- Local.subkind local |
| int local = 42; |
| |
| //- @resource defines/binding ResourceVar |
| //- ResourceVar.node/kind variable |
| //- ResourceVar.subkind local/resource |
| try (OutputStream resource = System.out) { |
| resource.write("hello"); |
| |
| //- @exception defines/binding ExceptionVar |
| //- ExceptionVar.node/kind variable |
| //- ExceptionVar.subkind local/exception |
| } catch (IOException exception) {} |
| } |
| } |
| -------------------------------------------------------------------------------- |
| |
| Protocol Buffers |
| ~~~~~~~~~~~~~~~~ |
| |
| The source language for Protocol Buffers is spelled `"protobuf"`. |
| |
| Common Lisp |
| ~~~~~~~~~~~ |
| |
| The source language for Common Lisp is spelled "`lisp`". |