A name cannot be dissected any further by means of a definition: it is a primitive sign -- Ludwig Wittgenstein
Powered by tree-sitter
, fully-qualified-names
lets you extract simple and fully qualified names from code written in JavaScript, TypeScript, Python or Java. Those names are further split into declarations and usages which provides a convenient simplification of more complex ASTs for static analysis.
The package offers a Rust and a JS API, the latter based on WASM. To get names from a Python code snippet in Rust you would use something like the following.
``` rust use fully-qualified-names::Python;
let code = r#"class Person: def init(self, name): self.name = name
def hello(self): return f"Hello, {self.name}" "#;
let names = Python::find_names(code).unwrap(); println!("{names:?}"); ```
The same in JS would look as follows.
``` javascript import { Python } from '@aws/fully-qualified-names';
const code = `class Person: def init(self, name): self.name = name
def hello(self): return f"Hello, {self.name}" `;
const names = await Python.findNames(code); console.log(JSON.stringify(names)); ```
In programming, identifers are used to refer to values, types and code passages.
Those all have simple names which are context-specific, and fully qualified names (subsequently abbreviated as FQNs), which are unambiguous and unique across projects.
Take e.g. the following Rust code snippet.
rust
let list = std::vec::Vec::new();
Here we have several simple names (list
, std
, vec
, Vec
, new
),
which include variable (list
), module (std
, vec
), type (Vec
) and method (new
) names.
All of those have FQNs as well, the new
method's FQN is explicitly stated as std::vec::Vec::new
,
the list
variable's FQN can only be determined with knowledge of the surrounding package
and module structure.
The names introduced above can be furthermore be separated into declarations (list
) and usages (std::vec::Vec::new
)
Declaration: A declaration is a statement which introduces a name into a scope.
Value Usage: A symbol name is used in an expression which requires evaluating (i.e. looking up) the symbol’s definition.
Type Usage: A type name is used by the compiler in a left-hand-side context to * ensure a value in a right-right-hand side context has the required type * avoid type propagation/inference across scopes
See CONTRIBUTING for more information.
This project is licensed under the Apache-2.0 License.