Skip to content

vocabulary.json

The words a corpus’s names are made of, counted per scope: the corpus, each module, each type. Written by vocabulary --out. The committed fixtures/<lang>/expected/vocabulary.json are its pretty form, one term and one scope per line, rebuilt byte for byte by the tests.

Words come from names, never from source. A name is split by the universal word boundaries and its language’s lexicon (the conventional names, file kinds, qualified kinds and interface marker profiles prints). Each word is classed, never filtered, and weighted by the role of what carries it.

Rows are array indexes. A term is its position in terms, a scope’s parent its position in scopes. A scope carries its entity’s id, opaque, so a city building or a navigator node finds its words.

Field names are those of VocabularyArtifact in packages/vocabulary/src/artifact.ts.

Top level

FieldTypeMeaning
kindstringalways codegraph.vocabulary/1
generatedBystringalways @codegraph/vocabulary
viewViewDescriptor{name, filters}
corpus{name, roots}
langsstring[]the languages of the union
weightsobjectthe weight of each role and of qualifier, as counted: module, type, operation, attribute, parameter, local, other, qualifier
classesstring[]domain, technical, keyword, short, in that order
technical{words, sha256}the shared technical list’s size and a sha256 over its sorted words joined by \n; each language’s own words apply on top
termsTerm[]sorted by text in UTF-16 code-unit order, then class
scopesScope[]the corpus first, then modules, then types, each level in id order
diagnostics{unplaced, withoutLexicon}kept entities no module contains (counted in the corpus alone), and languages core has no lexicon for (split by the universal rules alone); both sorted

terms[] — Term

One word in one class. A word two languages class differently (Go reserves type, Java does not) is two terms.

FieldTypeMeaning
textstringlowercased
class"domain" | "technical" | "keyword" | "short"keyword: the language reserves it; short: one letter or digit; technical: the shared list or the language’s own; else domain
modules, typesnumberhow many module scopes, and how many type scopes, say it
exclusivenumberthe one module scope that says it, when exactly one does

scopes[] — Scope

A type’s words are those of everything that folds into it (containingType), a module’s likewise, the corpus’s every kept entity’s. A nested type is its own scope. A stub never speaks.

FieldTypeMeaning
level"corpus" | "module" | "type"
idstringthe entity id; absent on the corpus
name, kindstringthe entity’s name and kind; the corpus has its display name and no kind
parentnumberthe nearest scope up the containment chain, else the corpus; absent on the corpus
entitiesnumberkept entities here; each is unnamed, conventional or counted in roles
rolesobjectthe entities that said words, by role
skipped{unnamed, conventional, numeric}names with no word: an unnamed entity, a name the language dictates (toString), and pieces of digits only, dropped
distinct, distinctDomainnumberterms in the table, and the domain ones among them: the cognitive-load proxy
weight, occurrencesnumbersums over the table
terms[term, weight, occurrences, carriers][]by weight descending, then term; carriers counts distinct entities, so a name saying a word twice is two occurrences and one carrier

Weights

RoleWeightCarried by
module, type8an entity with TModule or TType
attribute4a TStructural no entity lists as a parameter or local
operation3TInvocable
parameter, local1a TStructural listed in some entity’s parameters or localVariables
other1a named entity no role trait describes
qualifier1not a role: the words before the last separator of a qualified name (com.acme of com.acme.order), whatever carries it

Roles come from traits, never from the kind. --weights overrides them, and the artifact records the weights it was counted with.

Carriers

The artifact counts the names behind a row and never lists them, so it stays a few megabytes on a real corpus. serve answers the list one row at a time, at /carriers.json?term=WORD[&scope=ID][&class=CLASS][&limit=N], from the model it holds and under the artifact’s own counting:

FieldTypeMeaning
kind"codegraph.carriers/1"
status"found" | "unknown-scope" | "unknown-term" | "ambiguous"404 for the two unknowns; ambiguous (400) carries classes when the scope speaks the text as two terms
scope{level, id?, name}the corpus when the request names no scope
term{text, class}
weight, occurrences, totalnumberthe row: total is its carriers
carriersobject[]the first limit (200 by default), by weight descending, then id: name, kind, role, weight and occurrences (what this name added to the row), anchor, and id on a type or module, owner (its type, else its module) on a member

The carriers’ weights and occurrences add up to the row, and their number is its carriers.

Last updated on