Expand description
The sym: symbol-id grammar.
A SymbolId names a definition by where it sits in the program, never
by where it sits on disk: no file path, no line number. Moving an item
between files keeps its id; renaming it, or moving it to another module,
changes it. Whether the definition’s content changed is a separate
question, answered by content fingerprints kept beside the id: identity
and freshness are kept apart, as rustc keeps DefPath apart from its
query fingerprints.
The grammar follows SCIP’s symbol strings (descriptor suffixes make the
kind explicit), so a global id maps to a SCIP symbol by replacing the
sym: prefix with a scheme name.
§Grammar
id ::= 'sym:' ( global | path | unresolved )
global ::= manager ' ' package ' ' version ( ' ' descriptor+ )?
path ::= 'extern ' name ( '::' name )*
unresolved ::= '? ' name
manager ::= [a-z] [a-z0-9-]* -- not `extern`
package ::= field -- not `.`
version ::= '.' | field -- `.` = the current tree
field ::= any characters except control characters, non-empty,
no leading or trailing space; a space is written twice
descriptor ::= name '/' -- namespace (module)
| name '#' -- type (struct, enum, union, trait, alias)
| name '.' -- term (const, static)
| name '(' disambiguator? ').' -- method or function
| name ':' -- meta
| name '!' -- macro
| '[' name ']' -- type parameter (also: trait-impl block)
| '(' name ')' -- parameter
disambiguator ::= simple+
name ::= simple+ | '`' ( any character, '`' written '``' )* '`'
simple ::= [A-Za-z0-9_+$-]A name made only of simple characters is written bare; anything else
(including the empty name) is quoted in backticks, with backticks doubled.
A global id without descriptors names the package root (a crate’s root
module).
The three forms are:
- global: a definition with known kinds all the way down. Everything a
language adapter defines has a global id. The version is
.for “the tree being analysed”, so releasing a new version does not churn every id. - path: a path as written that could not be resolved to kinds, such
as a call into a dependency (
sym:extern serde_json::to_string). These are references, never definitions. - unresolved: a method called on a receiver of unknown type
(
sym:? insert).
§Examples
use sealmap_model::{Descriptor, Package, SymbolId};
let pkg = Package::current("cargo", "shop").unwrap();
let db = SymbolId::global(pkg, vec![Descriptor::namespace("db"), Descriptor::r#type("Db")]);
let put = db.child(Descriptor::type_parameter("Store")).unwrap().child(Descriptor::method("put")).unwrap();
assert_eq!(db.to_string(), "sym:cargo shop . db/Db#");
assert_eq!(put.to_string(), "sym:cargo shop . db/Db#[Store]put().");
// Methods in a trait-impl block belong to the type.
assert_eq!(put.parent(), Some(db.clone()));
// Parsing is the exact inverse of printing.
assert_eq!("sym:cargo shop . db/Db#[Store]put().".parse::<SymbolId>().unwrap(), put);
// Names outside the simple set are quoted.
let from = db.child(Descriptor::type_parameter("From<String>")).unwrap().child(Descriptor::method("from")).unwrap();
assert_eq!(from.to_string(), "sym:cargo shop . db/Db#[`From<String>`]from().");
// References that never resolved to kinds.
assert_eq!(SymbolId::path(["tokio", "spawn"]).unwrap().to_string(), "sym:extern tokio::spawn");
assert_eq!(SymbolId::unresolved("insert").to_string(), "sym:? insert");Structs§
- Descriptor
- One step of a global id: a name plus the kind-explicit suffix.
- Descriptor
View - One descriptor of a
GlobalView. - Global
View - The parts of a global id.
- Package
- The package part of a global id: manager, name and version.
- Symbol
Id - The canonical identity of a symbol. See the module docs for the grammar.
Enums§
- Descriptor
Kind - The kind of a descriptor, as in
Suffixwithout the payload. - IdError
- Why an id or one of its parts could not be built or parsed.
- IdView
- A borrowed view of a
SymbolId, fromSymbolId::view. - Suffix
- The kind of a
Descriptor, after SCIP’s descriptor suffixes. - Version
- The version component of a
Package.
Constants§
- SYM_
PREFIX - The prefix every printed id starts with.