Google-Kythe-Kythe Schema Overview


本文档旨在作为KYTHE图形模式的高级概述,并解释构成整个图形结构的一些核心功能。
它不会取代KYTHE图形模式文档,后者仍应用作规范引用。
相反,这是为了帮助读者了解模式的各个部分的含义,以及如何解释它。

Terminology Overview

本文件采用以下基本术语:
在这里插入图片描述
An anchor(锚)表示文件的区域。例如,在kcd.go中,Reader类型/接口有许多锚点:

type Reader interface {
  Revisions(_ context.Context, filter *RevisionsFilter, f func(Revision) error) error
  ^^^^^^^^^
}

例如,将有一个锚点(上面用^标记表示)覆盖来自kcd.go的标识符Revisions(修订)。
锚点的范围是包含感兴趣的实体的文件区域。

语义节点表示可以与文件直接关联或不直接关联的抽象实体。
语义节点通过与锚相关联来获得位置。

从上面的同一个例子中,我们可以把修订看作是属于类型阅读器的语义节点(函数)的定义位置。
它在kcd.go中有一个锚,用于定义它在文件中的位置。
memdb.go中还有另一个锚点,其中为该文件中的(具体)数据库类型实现了修订函数。

fact是与节点关联的命名字节字符串值。
Kythe schema定义了各种事实的名称和预期格式,
例如,doc/uri fact 通常用于将对某些外部文档的引用附加到图中的节点。

边是两个节点之间的有向标记关系。
在上面的示例中,我们将绘制从修订点处的锚点到函数语义节点的define/binding(定义/绑定)边。
这表明锚点是函数的“定义”(具体来说,是将其绑定到标识符的定义)。

Note
在下图中,并未显示所有可能的锚点、语义节点、事实或边。
在可能的情况下,我们将继续参考相同的 kcd.go 文件。

Edge and Node Examples

现在,我们将解释您将在Kythe模式中看到的一些基本边和节点。

Jump-to-Definition

Jump-to-definition allows navigating from a usage of some entity (e.g., a variable or function) to its definition. To support this, the indexer must, at minimum, emit an anchor for a definition site, a semantic node to represent the entity that is defined, and an anchor for the usage site. In this example, we see one definition and two references for a variable named matchRevision (from kcd.go):
跳转到定义允许从某个实体(例如,变量或函数)的使用导航到其定义。
为了支持这一点,索引器必须 至少发出一个定义站点的锚、一个表示所定义的实体的语义节点和一个使用站点的锚。
在此示例中,我们看到名为matchRevision的变量的一个定义和两个引用from kcd.go):
在这里插入图片描述

func (rf *RevisionsFilter) Compile() (func(Revision) bool, error) {
  if rf == nil || (rf.Revision == "" && rf.Corpus == "" && rf.Until.IsZero() && rf.Since.IsZero()) {
    return func(Revision) bool { return true }, nil
  }
  var matchRevision, matchCorpus func(...string) bool // definition
  var err error
  if matchRevision, err = singleMatcher(rf.Revision); err != nil {  // reference 1
    return nil, err
  }
  if matchCorpus, err = singleMatcher(regexp.QuoteMeta(rf.Corpus)); err != nil {
    return nil, err
  }
  return func(rev Revision) bool {
    return matchRevision(rev.Revision) &&  // reference 2
      matchCorpus(rev.Corpus) &&
      (rf.Until.IsZero() || !rf.Until.Before(rev.Timestamp.In(time.UTC))) &&
      (rf.Since.IsZero() || !rev.Timestamp.In(time.UTC).Before(rf.Since))
  }, nil
}

第一次提到MatchRevision (注释为"definition") 记录了一个锚点,
该锚点具有到该变量的语义节点的定义/绑定边。
引用 (注释为"reference 1" and “reference 2”) 的锚点具有指向同一语义节点的引用边。

对于给定的语义节点,通常可能有一个以上的定义站点,
并且在某些情况下,可能根本没有定义。
当唯一定义确实存在时,我们将其称为节点的目标定义。

一个没有定义站点的例子是Java中的隐式构造函数。
如果您定义了一个类,但没有编写构造函数,则编译器会为您编写一个构造函数,
并且它会参与交叉引用,但它在程序的源文本中没有位置。

许多C++对象会出现多个定义站点,包括类或函数原型及其完成的前向声明。
类型的(re)声明的锚点也使用defines/binding边。

Callgraph

调用图由一组三元组组成,
每个三元组关联一个调用点、一个调用者和一个被调用者。
调用点是源中发生调用的位置 (通常是某种类型的调用表达式) 。
调用者是包含调用点的函数,被调用者是被调用的函数。

在Kythe schema中,
该结构由三个节点和两条边表示: 一个位于调用点的锚,以及分别用于调用者和被调用者的语义节点。
调用位置定位点有一个指向调用者的 childof 边和一个指向被调用者的 ref/call 边:

在这里插入图片描述
kcd.go

func (rf *RevisionsFilter) Compile() (func(Revision) bool, error) {

memdb.go

type DB struct {
...
}
...

// Revisions implements a method of kcd.Reader.
func (db DB) Revisions(_ context.Context, want *kcd.RevisionsFilter, f func(kcd.Revision) error) error {
  revisionMatches, err := want.Compile()

Note
此图未显示由这些构造产生的所有节点和边。
特别是,完整的图将包括memdb.go中接口函数的覆盖(实现)的附加节点。
为了简洁起见,我们省略了图的该分支。

在这里,我们有kcd.go的另外两个部分,围绕 Compile (编译)函数的用法。
该函数在kcd.go中定义,然后在memdb.go中使用函数调用进行引用。
kcd.go中用于编译的代码的锚点具有指向修订的函数语义节点的childof边。

Class/Interface Hierarchy & Overrides

继承关系由扩展边和满足边捕获。
Override关系由 overrides 边表示。
Go的这个例子说明了这些关系(它使用满足边来表示Go的隐式接口满意度)。
在此示例中,ChildOf边捕获方法及其类型之间的包含关系:
在这里插入图片描述
kcd.go:

type Reader interface {
  Revisions(_ context.Context, filter *RevisionsFilter, f func(Revision) error) error
}

memdb.go:

type DB struct {
...
}
...
// Revisions implements a method of kcd.Reader.
func (db DB) Revisions(_ context.Context, want *kcd.RevisionsFilter, f func(kcd.Revision) error) error {

在这里,我们再次看到来自kcd.go的顶级读取器接口。
来自同一文件的接口函数修订有一个指向接口节点的childOf边。
位于memdb.go中的Reader的实现具有返回到父接口的satisfy边,
并且其自身的修订函数具有指向来自kcd.go的顶级修订函数的覆盖边。
对于C++和Java,接口、抽象类等在Kythe模式中具有类似的关系。

注意:
对于具有显式声明的继承和接口实现的语言(如Java),Kythe使用extends edge标签而不是satisfies。

Functions and Parameters

函数由语义节点表示,这些语义节点具有额外的边,以指示它们与函数参数的关系。
这些边被命名为param.0、param.1等,其中序数反映了声明的顺序。

如该示例所示,参数又可以具有它们自己的声明位置,遵循跳转到定义示例的约定:

在这里插入图片描述
kcd.go:

type Reader interface {
  Revisions(ctx context.Context, filter *RevisionsFilter, f func(Revision) error) error

回到kcd.go Revisions方法,我们可以看到它的函数参数在kythe模式中是如何工作的。
我们看到的修订版本的锚点和语义节点定义与以前相同,
但这次我们还看到函数的三个参数(_, filter, and f)的锚点和语义节点具有预期的定义/绑定边。
最后,从具有 param.N 边的修订节点指向每个函数param节点,指示它们是给定索引的函数参数。

Documentation

文档可以表示为具有包含描述性文本的文本事实的显式文档节点,
也可以表示为跨越文档的文字文本(例如,注释)的普通锚节点。
后者可能包括指向括号分隔的子串的参数边,这些子串应被视为对图中其他对象的引用。

Text Fact Style

在这里插入图片描述
FileDataCache.java:

/**
 * {@link FileDataProvider} that looks up file data from a given {@link Iterable}
 * of {@link FileData}.
 */

Here we look at FileDataCache.java to get the two different types of documents alluded to above. The left half of the graph describes the javadoc string for the top level FileDataCache class, with a text fact pointing to a node with the actual comment of the javadoc. It also has param.0 and param.1 edges pointing to the named bits of code in the doc string, the Iterable interface and the FileData class.
在这里,我们来看一下 FileDataCache.java,以获得上面提到的两种不同类型的文档。
图的左半部分描述了顶级FileDataCache类的Javadoc字符串,
其中一个文本事实指向具有Javadoc的实际注释的节点。
它还具有param.0param.1边,指向文档字符串、Iterable接口和FileData类中代码的命名位。

Anchor-Doc Style

在这里插入图片描述
kcd.go:

// Reader represents read-only access to an underlying storage layer used to
// implement a compilation database.
type Reader interface {

处理文档的第二种方法是通过整个注释文本的锚点,
文档边指向它正在记录的事物的语义节点。
此处显示了kcd.go Reader 界面的文本注释。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值