graph

package
v0.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 31, 2014 License: BSD-3-Clause, MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// An Unqualified name is just the symbol's name.
	//
	// Examples:
	//
	//   Go method         `MyMethod`
	//   Python method     `my_method`
	//   JavaScript method `myMethod`
	Unqualified Qualification = ""

	// A ScopeQualified name is the language-specific description of the
	// symbol's defining scope plus the symbol's unqualified name. It should
	// uniquely describe the symbol among all other symbols defined in the same
	// logical package (but this is not strictly defined or enforced).
	//
	// Examples:
	//
	//   Go method         `(*MyType).MyMethod`
	//   Python method     `MyClass.my_method`
	//   JavaScript method `MyConstructor.prototype.myMethod`
	ScopeQualified = "scope"

	// A DepQualified name is the package/module name (as seen by an external
	// library that imports/depends on the symbol's package/module) plus the
	// symbol's scope-qualified name. If there are nested packages, it should
	// describe enough of the package hierarchy to distinguish it from other
	// similarly named symbols (but this is not strictly defined or enforced).
	//
	// Examples:
	//
	//   Go method       `(*mypkg.MyType).MyMethod`
	//   Python method   `mypkg.MyClass.my_method`
	//   CommonJS method `mymodule.MyConstructor.prototype.myMethod`
	DepQualified = "dep"

	// A RepositoryWideQualified name is the full package/module name(s) plus
	// the symbol's scope-qualified name. It should describe enough of the
	// package hierarchy so that it is unique in its repository.
	// RepositoryWideQualified differs from DepQualified in that the former
	// includes the full nested package/module path from the repository root
	// (e.g., 'a/b.C' for a Go func C in the repository 'github.com/user/a'
	// subdirectory 'b'), while DepQualified would only be the last directory
	// component (e.g., 'b.C' in that example).
	//
	// Examples:
	//
	//   Go method       `(*mypkg/subpkg.MyType).MyMethod`
	//   Python method   `mypkg.subpkg.MyClass.my_method` (unless mypkg =~ subpkg)
	//   CommonJS method `mypkg.mymodule.MyConstructor.prototype.myMethod` (unless mypkg =~ mymodule)
	RepositoryWideQualified = "repo-wide"

	// A LanguageWideQualified name is the library/repository name plus the
	// package-qualified symbol name. It should describe the symbol so that it
	// is logically unique among all symbols that could reasonably exist for the
	// language that the symbol is written in (but this is not strictly defined
	// or enforced).
	//
	// Examples:
	//
	//   Go method       `(*github.com/user/repo/mypkg.MyType).MyMethod`
	//   Python method   `mylib.MyClass.my_method` (if mylib =~ mypkg, as for Django, etc.)
	//   CommonJS method `mylib.MyConstructor.prototype.myMethod` (if mylib =~ mymod, as for caolan/async, etc.)
	LanguageWideQualified = "lang-wide"
)
View Source
const (
	// StatXRefs is the number of external references to a symbol (i.e.,
	// references from other repositories). It is only computed for abstract
	// symbols (see the docs for SymbolKey) because it is not easy to determine
	// which specific commit a ref references (for external refs).
	StatXRefs = "xrefs"

	// StatRRefs is the number of references to a symbol from the same
	// repository in which the symbol is defined. It is inclusive of the
	// StatURefs count. It is only computed for concrete symbols (see the docs
	// for SymbolKey) because otherwise it would count 1 rref for each unique
	// revision of the repository that we have processed. (It is easy to
	// determine which specific commit an internal ref references; we just
	// assume it references a symbol in the same commit.)
	StatRRefs = "rrefs"

	// StatURefs is the number of references to a symbol from the same source
	// unit in which the symbol is defined. It is included in the StatRRefs
	// count. It is only computed for concrete symbols (see the docs for
	// SymbolKey) because otherwise it would count 1 uref for each revision of
	// the repository that we have processed.
	StatURefs = "urefs"

	// StatAuthors is the number of distinct resolved people who contributed
	// code to a symbol's definition (according to a VCS "blame" of the
	// version). It is only computed for concrete symbols (see the docs for
	// SymbolKey).
	StatAuthors = "authors"

	// StatClients is the number of distinct resolved people who have committed
	// refs that reference a symbol. It is only computed for abstract symbols
	// (see the docs for SymbolKey) because it is not easy to determine which
	// specific commit a ref references.
	StatClients = "clients"

	// StatDependents is the number of distinct repositories that contain refs
	// that reference a symbol. It is only computed for abstract symbols (see
	// the docs for SymbolKey) because it is not easy to determine which
	// specific commit a ref references.
	StatDependents = "dependents"

	// StatExportedElements is the number of exported symbols whose path is a
	// descendant of this symbol's path (and that is in the same repository and
	// source unit). It is only computed for concrete symbols (see the docs for
	// SymbolKey) because otherwise it would count 1 exported element for each
	// revision of the repository that we have processed.
	StatExportedElements = "exported_elements"

	// StatInterfaces is the number of interfaces that a symbol implements (in
	// its own repository or other repositories). TODO(sqs): it is not currently
	// being computed.
	StatInterfaces = "interfaces"

	// StatImplementations is the number of implementations of an interface
	// symbol (in its own repository or other repositories). TODO(sqs): it is
	// not currently being computed.
	StatImplementations = "implementations"
)
View Source
const (
	Const   SymbolKind = "const"
	Field              = "field"
	Func               = "func"
	Module             = "module"
	Package            = "package"
	Type               = "type"
	Var                = "var"
)

Variables

View Source
var AllSymbolKinds = []SymbolKind{Const, Field, Func, Module, Package, Type, Var}
View Source
var ErrSymbolNotExist = errors.New("symbol does not exist")
View Source
var MakeSymbolFormatters = make(map[string]MakeSymbolFormatter)

MakeSymbolFormatter holds MakeSymbolFormatters that toolchains have registered with RegisterMakeSymbolFormatter.

Functions

func IsContainer

func IsContainer(symbolKind SymbolKind) bool

func IsNotExist

func IsNotExist(err error) bool

func RegisterMakeSymbolFormatter

func RegisterMakeSymbolFormatter(unitType string, f MakeSymbolFormatter)

RegisterMakeSymbolFormatter makes a SymbolFormatter constructor function (MakeSymbolFormatter) available for symbols with the specified unitType. If Register is called twice with the same unitType or if sf is nil, it panics

func UniqueRefSymbols

func UniqueRefSymbols(refs []*Ref, m map[RefSymbolKey]int) map[RefSymbolKey]int

UniqueRefSymbols groups refs by the RefSymbolKey field and returns a map of how often each RefSymbolKey appears. If m is non-nil, counts are incremented and a new map is not created.

Types

type Doc

type Doc struct {
	SymbolKey

	Format string
	Data   string

	File  string
	Start int
	End   int
}

Docstring

type DocPage

type DocPage struct {
	DocPageKey

	// Note: the contents of these fields is unsanitized. Any sanitization should be done in the UI.
	Title string // Doc title
	Body  string // HTML tags with the data-sg-doc-symbol attribute will be linked to symbol pages and vice-versa in the UI
	Toc   string // Table of contents in conjunction (in sidebar) with body

	SymbolPaths *db_common.StringSlice // symbols within the scope of this documentation page
}

type DocPageKey

type DocPageKey struct {
	Repo     repo.URI
	UnitType string `db:"unit_type"`
	Unit     string
	Path     string
}

type Docs

type Docs []*Doc

func (Docs) Len

func (vs Docs) Len() int

func (Docs) Less

func (vs Docs) Less(i, j int) bool

func (Docs) Swap

func (vs Docs) Swap(i, j int)

type GoInterfaceMethod

type GoInterfaceMethod struct {
	// OfSymbolPath refers to the Go interface symbol that defines this method, or the Go
	// type symbol that implements this method.
	OfSymbolPath SymbolPath `db:"of_symbol_path"`

	// OfSymbolUnit refers to the unit containing the symbol denoted in OfSymbolPath.
	OfSymbolUnit string `db:"of_symbol_unit"`

	// Repo refers to the repository in which this method was defined.
	Repo repo.URI

	// Key is the canonical signature of the method for the implements
	// operation. If a type's methods' keys are a superset of an interface's,
	// then the type implements the interface.
	CanonicalSignature string `db:"canonical_signature"`

	// Name is the method's name.
	Name string
}

GoInterfaceMethod represents a Go interface method defined by an Go interface symbol or implemented by a Go type symbol. It is used for finding all implementations of an interface.

type MakeSymbolFormatter

type MakeSymbolFormatter func(*Symbol) SymbolFormatter

A MakeSymbolFormatter is a function, typically implemented by toolchains, that creates a SymbolFormatter for a symbol.

type Propagate

type Propagate struct {
	// Src is the symbol whose type/value is being propagated to the dst symbol.
	SrcRepo     repo.URI
	SrcPath     SymbolPath
	SrcUnit     string
	SrcUnitType string

	// Dst is the symbol that is receiving a propagated type/value from the src symbol.
	DstRepo     repo.URI
	DstPath     SymbolPath
	DstUnit     string
	DstUnitType string
}

Propagate describes type/value propagation in code. A Propagate entry from A (src) to B (dst) indicates that the type/value of A propagates to B. In Tern, this is indicated by A having a "fwd" property whose value is an array that includes B.

## Motivation & example

For example, consider the following JavaScript code:

var a = Foo;
var b = a;

Foo, a, and b are each their own symbol. We could resolve all of them to the symbol of their original type (perhaps Foo), but there are occasions when you do want to see only the definition of a or b and examples thereof. Therefore, we need to represent them as distinct symbols.

Even though Foo, a, and b are distinct symbols, there are propagation relationships between them that are important to represent. The type of Foo propagates to both a and b, and the type of a propagates to b. In this case, we would have 3 Propagates: Propagate{Src: "Foo", Dst: "a"}, Propagate{Src: "Foo", Dst: "b"}, and Propagate{Src: "a", Dst: "b"}. (The propagation relationships could be described by just the first and last Propagates, but we explicitly include all paths as a denormalization optimization to avoid requiring an unbounded number of DB queries to determine which symbols a type propagates to or from.)

## Directionality

Propagation is unidirectional, in the general case. In the example above, if Foo referred to a JavaScript object and if the code were evaluated, any *runtime* type changes (e.g., setting a property) on Foo, a, and b would be reflected on all of the others. But this doesn't hold for static analysis; it's not always true that if a property "a.x" or "b.x" exists, then "Foo.x" exists. The simplest example is when Foo is an external definition. Perhaps this example file (which uses Foo as a library) modifies Foo to add a new property, but other libraries that use Foo would never see that property because they wouldn't be executed in the same context as this example file. So, in general, we cannot say that Foo receives all types applied to symbols that Foo propagates to.

## Hypothetical Python example

Consider the following 2 Python files:

"""file1.py"""
class Foo(object): end

"""file2.py"""
from .file1 import Foo
Foo2 = Foo

In this example, there would be one Propagate: Propagate{Src: "file1/Foo", Dst: "file2/Foo2}.

type Qualification

type Qualification string

A Qualification specifies how much to qualify names when formatting symbols and their type information.

type Ref

type Ref struct {
	SymbolRepo     repo.URI   `db:"symbol_repo"`
	SymbolUnitType string     `db:"symbol_unit_type"`
	SymbolUnit     string     `db:"symbol_unit"`
	SymbolPath     SymbolPath `db:"symbol_path"`

	// Def is true if this ref is to a definition of the target symbol.
	Def bool

	Repo repo.URI

	// CommitID is the immutable commit ID (not the branch name) of the VCS
	// revision that this ref was found in.
	CommitID string `db:"commit_id" json:",omitempty"`

	UnitType string `db:"unit_type" json:",omitempty"`
	Unit     string `json:",omitempty"`

	File  string
	Start int
	End   int
}

Ref represents a reference from source code to a symbol.

func (*Ref) RefKey

func (r *Ref) RefKey() RefKey

func (*Ref) RefSymbolKey

func (r *Ref) RefSymbolKey() RefSymbolKey

func (*Ref) SetFromSymbolKey

func (r *Ref) SetFromSymbolKey(k SymbolKey)

func (*Ref) SymbolKey

func (r *Ref) SymbolKey() SymbolKey

type RefKey

type RefKey struct {
	SymbolRepo     repo.URI   `db:"symbol_repo" json:",omitempty"`
	SymbolUnitType string     `db:"symbol_unit_type" json:",omitempty"`
	SymbolUnit     string     `db:"symbol_unit" json:",omitempty"`
	SymbolPath     SymbolPath `db:"symbol_path" json:",omitempty"`
	Def            bool       `json:",omitempty"`
	Repo           repo.URI   `json:",omitempty"`
	UnitType       string     `db:"unit_type" json:",omitempty"`
	Unit           string     `json:",omitempty"`
	File           string     `json:",omitempty"`
	CommitID       string     `db:"commit_id" json:",omitempty"`
	Start          int        `json:",omitempty"`
	End            int        `json:",omitempty"`
}

func (*RefKey) RefSymbolKey

func (r *RefKey) RefSymbolKey() RefSymbolKey

type RefSet

type RefSet struct {
	// contains filtered or unexported fields
}

RefSet is a set of Refs. It can used to determine whether a grapher emits duplicate refs.

func NewRefSet

func NewRefSet() *RefSet

func (*RefSet) AddAndCheckUnique

func (c *RefSet) AddAndCheckUnique(ref Ref) (duplicate bool)

AddAndCheckUnique adds ref to the set of seen refs, and returns whether the ref already existed in the set.

type RefSymbolKey

type RefSymbolKey struct {
	SymbolRepo     repo.URI   `db:"symbol_repo" json:",omitempty"`
	SymbolUnitType string     `db:"symbol_unit_type" json:",omitempty"`
	SymbolUnit     string     `db:"symbol_unit" json:",omitempty"`
	SymbolPath     SymbolPath `db:"symbol_path" json:",omitempty"`
}

type Refs

type Refs []*Ref

func (Refs) Len

func (vs Refs) Len() int

func (Refs) Less

func (vs Refs) Less(i, j int) bool

func (Refs) Swap

func (vs Refs) Swap(i, j int)

type RepositoryListingSymbol

type RepositoryListingSymbol struct {
	// Name is the full name shown on the page.
	Name string

	// NameLabel is a label displayed next to the Name, such as "(main package)"
	// to denote that a package is a Go main package.
	NameLabel string

	// Language is the source language of the symbol, with any additional
	// specifiers, such as "JavaScript (node.js)".
	Language string

	// SortKey is the key used to lexicographically sort all of the symbols on
	// the page.
	SortKey string
}

RepositoryListingSymbol holds rendered display text to show on the "package" listing page of a repository.

type SID

type SID int64

func ParseSIDs

func ParseSIDs(sidstrs []string) (sids []SID)

func (*SID) Scan

func (x *SID) Scan(v interface{}) error

func (SID) Value

func (x SID) Value() (driver.Value, error)

type StatType

type StatType string

StatType is the name of a symbol statistic (see below for a listing).

func (StatType) IsAbstract

func (x StatType) IsAbstract() bool

func (*StatType) Scan

func (x *StatType) Scan(v interface{}) error

Scan implements database/sql.Scanner.

func (StatType) Value

func (x StatType) Value() (driver.Value, error)

Value implements database/sql/driver.Valuer.

type Stats

type Stats map[StatType]int

Stats holds statistics for a symbol.

type Symbol

type Symbol struct {
	// SID is a unique, sequential ID for a symbol. It is regenerated each time
	// the symbol is emitted by the grapher and saved to the database. The SID
	// is used as an optimization (e.g., joins are faster on SID than on
	// SymbolKey).
	SID SID `db:"sid" json:",omitempty" elastic:"type:integer,index:no"`

	// SymbolKey is the natural unique key for a symbol. It is stable
	// (subsequent runs of a grapher will emit the same symbols with the same
	// SymbolKeys).
	SymbolKey

	// TreePath is a structurally significant path descriptor for a symbol. For
	// many languages, it may be identical or similar to SymbolKey.Path.
	// However, it has the following constraints, which allow it to define a
	// symbol tree.
	//
	// A tree-path is a chain of '/'-delimited components. A component is either a
	// symbol name or a ghost component.
	// - A symbol name satifies the regex [^/-][^/]*
	// - A ghost component satisfies the regex -[^/]*
	// Any prefix of a tree-path that terminates in a symbol name must be a valid
	// tree-path for some symbol.
	// The following regex captures the children of a tree-path X: X(/-[^/]*)*(/[^/-][^/]*)
	TreePath TreePath `db:"treepath" json:",omitempty"`

	// Kind is the language-independent kind of this symbol.
	Kind SymbolKind `elastic:"type:string,index:analyzed"`

	Name string

	// Callable is true if this symbol may be called or invoked, such as in the
	// case of functions or methods.
	Callable bool `db:"callable"`

	File string `elastic:"type:string,index:no"`

	DefStart int `db:"def_start" elastic:"type:integer,index:no"`
	DefEnd   int `db:"def_end" elastic:"type:integer,index:no"`

	Exported bool `elastic:"type:boolean,index:not_analyzed"`

	// Test is whether this symbol is defined in test code (as opposed to main
	// code). For example, definitions in Go *_test.go files have Test = true.
	Test bool `elastic:"type:boolean,index:not_analyzed" json:",omitempty"`

	// Data contains additional language- and toolchain-specific information
	// about the symbol. Data is used to construct function signatures,
	// import/require statements, language-specific type descriptions, etc.
	Data types.JsonText `json:",omitempty" elastic:"type:object,enabled:false"`
}

func (*Symbol) Fmt

func (s *Symbol) Fmt() SymbolPrintFormatter

func (*Symbol) HasImplementations

func (s *Symbol) HasImplementations() bool

HasImplementations returns true if this symbol is a Go interface and false otherwise. It is used for the interface implementations queries. TODO(sqs): run this through the golang toolchain instead of doing it here.

func (Symbol) String

func (x Symbol) String() string

type SymbolFormatter

type SymbolFormatter interface {
	// Name formats the symbol's name with the specified level of qualification.
	Name(qual Qualification) string

	// Type is the type of the symbol s, if s is not itself a type. If s is
	// itself a type, then Type returns its underlying type.
	//
	// Outputs:
	//
	//   TYPE OF s          RESULT
	//   ------------   -----------------------------------------------------------------
	//   named type     the named type's name
	//   primitive      the primitive's name
	//   function       `(arg1, arg2, ..., argN)` with language-specific type annotations
	//   package        empty
	//   anon. type     the leading keyword (or similar) of the anonymous type definition
	//
	// These rules are not strictly defined or enforced. Language toolchains
	// should freely bend the rules (after noting important exceptions here) to
	// produce sensible output.
	Type(qual Qualification) string

	// NameAndTypeSeparator is the string that should be inserted between the
	// symbol's name and type. This is typically empty for functions (so that
	// they are formatted with the left paren immediately following the name,
	// like `F(a)`) and a single space for other symbols (e.g., `MyVar string`).
	NameAndTypeSeparator() string

	// Language is the name of the programming language that s is in; e.g.,
	// "Python" or "Go".
	Language() string

	// DefKeyword is the language keyword used to define the symbol (e.g.,
	// 'class', 'type', 'func').
	DefKeyword() string

	// Kind is the language-specific kind of this symbol (e.g., 'package', 'field', 'CommonJS module').
	Kind() string
}

SymbolFormatter formats a symbol.

type SymbolKey

type SymbolKey struct {
	// Repo is the VCS repository that defines this symbol. Its Elasticsearch mapping is defined
	// separately.
	Repo repo.URI `json:",omitempty"`

	// CommitID is the ID of the VCS commit that this symbol was defined in. The
	// CommitID is always a full commit ID (40 hexadecimal characters for git
	// and hg), never a branch or tag name.
	CommitID string `db:"commit_id" json:",omitempty"`

	// UnitType is the type name of the source unit (obtained from unit.Type(u))
	// that this symbol was defined in.
	UnitType string `db:"unit_type" json:",omitempty"`

	// Unit is the name of the source unit (obtained from u.Name()) that this
	// symbol was defined in.
	Unit string `json:",omitempty"`

	// Path is a unique identifier for the symbol, relative to the source unit.
	// It should remain stable across commits as long as the symbol is the
	// "same" symbol. Its Elasticsearch mapping is defined separately (because
	// it is a multi_field, which the struct tag can't currently represent).
	//
	// Path encodes no structural semantics. Its only meaning is to be a stable
	// unique identifier within a given source unit. In many languages, it is
	// convenient to use the namespace hierarchy (with some modifications) as
	// the Path, but this may not always be the case. I.e., don't rely on Path
	// to find parents or children or any other structural propreties of the
	// symbol hierarchy). See Symbol.TreePath instead.
	Path SymbolPath
}

SymbolKey specifies a symbol, either concretely or abstractly. A concrete symbol key has a non-empty CommitID and refers to a symbol defined in a specific commit. An abstract symbol key has an empty CommitID and is considered to refer to symbols from any number of commits (so long as the Repo, UnitType, Unit, and Path match).

You can think of CommitID as the time dimension. With an empty CommitID, you are referring to a symbol that may or may not exist at various times. With a non-empty CommitID, you are referring to a specific definition of a symbol at the time specified by the CommitID.

func (SymbolKey) String

func (s SymbolKey) String() string

type SymbolKind

type SymbolKind string

func (*SymbolKind) Scan

func (x *SymbolKind) Scan(v interface{}) error

func (SymbolKind) Valid

func (k SymbolKind) Valid() bool

Returns true iff k is a known symbol kind.

func (SymbolKind) Value

func (x SymbolKind) Value() (driver.Value, error)

type SymbolPath

type SymbolPath string

func (*SymbolPath) Scan

func (x *SymbolPath) Scan(v interface{}) error

func (SymbolPath) Value

func (x SymbolPath) Value() (driver.Value, error)

type SymbolPrintFormatter

type SymbolPrintFormatter interface {
	SymbolFormatter
	fmt.Formatter
}

func PrintFormatter

func PrintFormatter(s *Symbol) SymbolPrintFormatter

Formatter creates a string formatter for a symbol.

The verbs:

%n     qualified name
%w     language keyword used to define the symbol (e.g., 'class', 'type', 'func')
%k     language-specific kind of this symbol (e.g., 'package', 'field', 'CommonJS module')
%t     type

The flags:

' '    (in `% t`) prepend the language-specific delimiter between a symbol's name and type

See SymbolFormatter for more information.

type Symbols

type Symbols []*Symbol

func (Symbols) Keys

func (syms Symbols) Keys() (keys []SymbolKey)

func (Symbols) Len

func (vs Symbols) Len() int

func (Symbols) Less

func (vs Symbols) Less(i, j int) bool

func (Symbols) SIDs

func (syms Symbols) SIDs() (ids []SID)

func (Symbols) Swap

func (vs Symbols) Swap(i, j int)

type TreePath

type TreePath string

func (TreePath) IsValid

func (p TreePath) IsValid() bool

func (*TreePath) Scan

func (x *TreePath) Scan(v interface{}) error

func (TreePath) Value

func (x TreePath) Value() (driver.Value, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL