reorganize module
This commit is contained in:
@@ -1,184 +0,0 @@
|
||||
Generate Definition Files for Language Server
|
||||
=============================================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
Rhai's [language server][lsp] works with IDEs to provide integrated support for the Rhai scripting language.
|
||||
|
||||
Functions and [modules] registered with an [`Engine`] can output their [metadata][functions metadata]
|
||||
into _definition files_ which are used by the [language server][lsp].
|
||||
|
||||
Definitions are generated via the `Engine::definitions` and `Engine::definitions_with_scope` API.
|
||||
|
||||
This API requires the [`metadata`] and [`internals`] feature.
|
||||
|
||||
|
||||
Configurable Options
|
||||
--------------------
|
||||
|
||||
The `Definitions` type supports the following options in a fluent method-chaining style.
|
||||
|
||||
| Option | Method | Default |
|
||||
| ------------------------------------------------------------------- | --------------------------- | :-----: |
|
||||
| Write headers in definition files? | `with_headers` | `false` |
|
||||
| Include [standard packages][built-in packages] in definition files? | `include_standard_packages` | `true` |
|
||||
|
||||
```rust
|
||||
engine
|
||||
.definitions()
|
||||
.with_headers(true) // write headers in all files
|
||||
.include_standard_packages(false) // skip standard packages
|
||||
.write_to_dir("path/to/my/definitions")
|
||||
.unwrap();
|
||||
```
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```rust
|
||||
use rhai::{Engine, Scope};
|
||||
use rhai::plugin::*;
|
||||
|
||||
// Plugin module: 'general_kenobi'
|
||||
#[export_module]
|
||||
pub mod general_kenobi {
|
||||
use std::convert::TryInto;
|
||||
|
||||
/// Returns a string where "hello there" is repeated 'n' times.
|
||||
pub fn hello_there(n: i64) -> String {
|
||||
"hello there ".repeat(n.try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
// Create scripting engine
|
||||
let mut engine = Engine::new();
|
||||
|
||||
// Create custom Scope
|
||||
let mut scope = Scope::new();
|
||||
|
||||
// This variable will also show up in the generated definition file.
|
||||
scope.push("hello_there", "hello there");
|
||||
|
||||
// Static module namespaces will generate independent definition files.
|
||||
engine.register_static_module(
|
||||
"general_kenobi",
|
||||
exported_module!(general_kenobi).into()
|
||||
);
|
||||
|
||||
// Custom operators will also show up in the generated definition file.
|
||||
engine.register_custom_operator("minus", 100).unwrap();
|
||||
engine.register_fn("minus", |a: i64, b: i64| a - b);
|
||||
|
||||
engine.run_with_scope(&mut scope,
|
||||
"hello_there = general_kenobi::hello_there(4 minus 2);"
|
||||
)?;
|
||||
|
||||
// Output definition files in the specified directory.
|
||||
engine
|
||||
.definitions()
|
||||
.write_to_dir("path/to/my/definitions")
|
||||
.unwrap();
|
||||
|
||||
// Output definition files in the specified directory.
|
||||
// Variables in the provided 'Scope' are included.
|
||||
engine
|
||||
.definitions_with_scope(&scope)
|
||||
.write_to_dir("path/to/my/definitions")
|
||||
.unwrap();
|
||||
|
||||
// Output a single definition file with everything merged.
|
||||
// Variables in the provided 'Scope' are included.
|
||||
engine
|
||||
.definitions_with_scope(&scope)
|
||||
.write_to_file("path/to/my/definitions/all_in_one.d.rhai")
|
||||
.unwrap();
|
||||
|
||||
// Output functions metadata to a JSON string.
|
||||
// Functions in standard packages are skipped and not included.
|
||||
let json = engine
|
||||
.definitions()
|
||||
.include_standard_packages(false) // skip standard packages
|
||||
.unwrap();
|
||||
```
|
||||
|
||||
|
||||
Definition Files
|
||||
----------------
|
||||
|
||||
The generated definition files will look like the following.
|
||||
|
||||
```rust
|
||||
┌───────────────────────┐
|
||||
│ general_kenobi.d.rhai │
|
||||
└───────────────────────┘
|
||||
|
||||
module general_kenobi;
|
||||
|
||||
/// Returns a string where "hello there" is repeated 'n' times.
|
||||
fn hello_there(n: int) -> String;
|
||||
|
||||
|
||||
┌──────────────────┐
|
||||
│ __scope__.d.rhai │
|
||||
└──────────────────┘
|
||||
|
||||
module static;
|
||||
|
||||
let hello_there;
|
||||
|
||||
|
||||
┌───────────────────┐
|
||||
│ __static__.d.rhai │
|
||||
└───────────────────┘
|
||||
|
||||
module static;
|
||||
|
||||
op minus(int, int) -> int;
|
||||
|
||||
:
|
||||
:
|
||||
|
||||
|
||||
┌────────────────────┐
|
||||
│ __builtin__.d.rhai │
|
||||
└────────────────────┘
|
||||
|
||||
module static;
|
||||
|
||||
:
|
||||
:
|
||||
|
||||
|
||||
┌──────────────────────────────┐
|
||||
│ __builtin-operators__.d.rhai │
|
||||
└──────────────────────────────┘
|
||||
|
||||
module static;
|
||||
|
||||
:
|
||||
:
|
||||
|
||||
```
|
||||
|
||||
|
||||
All-in-One Definition File
|
||||
--------------------------
|
||||
|
||||
`Definitions::write_to_file` generates a single definition file with everything merged in, like the following.
|
||||
|
||||
```rust
|
||||
module static;
|
||||
|
||||
op minus(int, int) -> int;
|
||||
|
||||
:
|
||||
:
|
||||
|
||||
module general_kenobi {
|
||||
/// Returns a string where "hello there" is repeated 'n' times.
|
||||
fn hello_there(n: int) -> String;
|
||||
}
|
||||
|
||||
let hello_there;
|
||||
```
|
@@ -1,147 +0,0 @@
|
||||
Export Functions Metadata to JSON
|
||||
=================================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
|
||||
`Engine::gen_fn_metadata_to_json`<br/>`Engine::gen_fn_metadata_with_ast_to_json`
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
As part of a _reflections_ API, `Engine::gen_fn_metadata_to_json` and the corresponding
|
||||
`Engine::gen_fn_metadata_with_ast_to_json` export the full list of [custom types] and
|
||||
[functions metadata] in JSON format.
|
||||
|
||||
~~~admonish warning.small "Requires `metadata`"
|
||||
|
||||
The [`metadata`] feature is required for this API, which also pulls in the
|
||||
[`serde_json`](https://crates.io/crates/serde_json) crate.
|
||||
~~~
|
||||
|
||||
### Sources
|
||||
|
||||
Functions and [custom types] from the following sources are included:
|
||||
|
||||
1. Script-defined functions in an [`AST`] (for `Engine::gen_fn_metadata_with_ast_to_json`)
|
||||
2. Native Rust functions registered into the global namespace via the `Engine::register_XXX` API
|
||||
3. [Custom types] registered into the global namespace via the `Engine::register_type_with_name` API
|
||||
4. _Public_ (i.e. non-[`private`]) functions (native Rust or Rhai scripted) and [custom types] in static modules
|
||||
registered via `Engine::register_static_module`
|
||||
5. Native Rust functions and [custom types] in external [packages] registered via `Engine::register_global_module`
|
||||
6. Native Rust functions and [custom types] in [built-in packages] (optional)
|
||||
|
||||
|
||||
JSON Schema
|
||||
-----------
|
||||
|
||||
The JSON schema used to hold metadata is very simple, containing a nested structure of
|
||||
`modules`, a list of `customTypes` and a list of `functions`.
|
||||
|
||||
### Module Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"doc": "//! Module documentation",
|
||||
|
||||
"modules":
|
||||
{
|
||||
"sub_module_1": /* namespace 'sub_module_1' */
|
||||
{
|
||||
"modules":
|
||||
{
|
||||
"sub_sub_module_A": /* namespace 'sub_module_1::sub_sub_module_A' */
|
||||
{
|
||||
"doc": "//! Module documentation can also occur in any sub-module",
|
||||
|
||||
"customTypes": /* custom types exported in 'sub_module_1::sub_sub_module_A' */
|
||||
[
|
||||
{ ... custom type metadata ... },
|
||||
{ ... custom type metadata ... },
|
||||
{ ... custom type metadata ... }
|
||||
...
|
||||
],
|
||||
"functions": /* functions exported in 'sub_module_1::sub_sub_module_A' */
|
||||
[
|
||||
{ ... function metadata ... },
|
||||
{ ... function metadata ... },
|
||||
{ ... function metadata ... },
|
||||
{ ... function metadata ... }
|
||||
...
|
||||
]
|
||||
},
|
||||
"sub_sub_module_B": /* namespace 'sub_module_1::sub_sub_module_B' */
|
||||
{
|
||||
...
|
||||
}
|
||||
}
|
||||
},
|
||||
"sub_module_2": /* namespace 'sub_module_2' */
|
||||
{
|
||||
...
|
||||
},
|
||||
...
|
||||
},
|
||||
|
||||
"customTypes": /* custom types registered globally */
|
||||
[
|
||||
{ ... custom type metadata ... },
|
||||
{ ... custom type metadata ... },
|
||||
{ ... custom type metadata ... },
|
||||
...
|
||||
],
|
||||
|
||||
"functions": /* functions registered globally or in the 'AST' */
|
||||
[
|
||||
{ ... function metadata ... },
|
||||
{ ... function metadata ... },
|
||||
{ ... function metadata ... },
|
||||
{ ... function metadata ... },
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Type Metadata Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"typeName": "alloc::string::String", /* name of Rust type */
|
||||
"displayName": "MyType",
|
||||
"docComments": /* omitted if none */
|
||||
[
|
||||
"/// My super-string type.",
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Function Metadata Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"baseHash": 9876543210, /* partial hash with only number of parameters */
|
||||
"fullHash": 1234567890, /* full hash with actual parameter types */
|
||||
"namespace": "internal" | "global",
|
||||
"access": "public" | "private",
|
||||
"name": "fn_name",
|
||||
"isAnonymous": false,
|
||||
"type": "native" | "script",
|
||||
"numParams": 42, /* number of parameters */
|
||||
"params": /* omitted if no parameters */
|
||||
[
|
||||
{ "name": "param_1", "type": "type_1" },
|
||||
{ "name": "param_2" }, /* no type name */
|
||||
{ "type": "type_3" }, /* no parameter name */
|
||||
...
|
||||
],
|
||||
"thisType": "this_type", /* omitted if none */
|
||||
"returnType": "ret_type", /* omitted if () or unknown */
|
||||
"signature": "[private] fn_name(param_1: type_1, param_2, _: type_3) -> ret_type",
|
||||
"docComments": /* omitted if none */
|
||||
[
|
||||
"/// doc-comment line 1",
|
||||
"/// doc-comment line 2",
|
||||
"/** doc-comment block */",
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
@@ -1,93 +0,0 @@
|
||||
Get Native Function Signatures
|
||||
==============================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
|
||||
`Engine::gen_fn_signatures`
|
||||
---------------------------
|
||||
|
||||
As part of a _reflections_ API, `Engine::gen_fn_signatures` returns a list of function _signatures_
|
||||
(as `Vec<String>`), each corresponding to a particular native function available to that [`Engine`] instance.
|
||||
|
||||
> _name_ `(`_param 1_`:`_type 1_`,` _param 2_`:`_type 2_`,` ... `,` _param n_`:`_type n_`) ->` _return type_
|
||||
|
||||
The [`metadata`] feature must be used to turn on this API.
|
||||
|
||||
### Sources
|
||||
|
||||
Functions from the following sources are included, in order:
|
||||
|
||||
1. Native Rust functions registered into the global namespace via the `Engine::register_XXX` API
|
||||
2. _Public_ (i.e. non-[`private`]) functions (native Rust or Rhai scripted) in global sub-modules
|
||||
registered via `Engine::register_static_module`.
|
||||
3. Native Rust functions in external [packages] registered via `Engine::register_global_module`
|
||||
4. Native Rust functions in [built-in packages] (optional)
|
||||
|
||||
|
||||
Functions Metadata
|
||||
------------------
|
||||
|
||||
Beware, however, that not all function signatures contain parameters and return value information.
|
||||
|
||||
### `Engine::register_XXX`
|
||||
|
||||
For instance, functions registered via `Engine::register_XXX` contain no information on the names of
|
||||
parameter because Rust simply does not make such metadata available natively.
|
||||
|
||||
Type names, however, _are_ provided.
|
||||
|
||||
A function registered under the name `foo` with three parameters.
|
||||
|
||||
> `foo(_: i64, _: char, _: &str) -> String`
|
||||
|
||||
An [operator] function. Notice that function names do not need to be valid identifiers.
|
||||
|
||||
> `+=(_: &mut i64, _: i64)`
|
||||
|
||||
A [property setter][getters/setters].
|
||||
Notice that function names do not need to be valid identifiers.
|
||||
In this case, the first parameter should be `&mut T` of the custom type and the return value is `()`:
|
||||
|
||||
> `set$prop(_: &mut TestStruct, _: i64)`
|
||||
|
||||
### Script-Defined Functions
|
||||
|
||||
Script-defined [function] signatures contain parameter names.
|
||||
Since _all_ parameters, as well as the return value, are [`Dynamic`] the types are simply not shown.
|
||||
|
||||
> `foo(x, y, z)`
|
||||
|
||||
is probably defined simply as:
|
||||
|
||||
```rust
|
||||
/// This is a doc-comment, included in this function's metadata.
|
||||
fn foo(x, y, z) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
which is really the same as:
|
||||
|
||||
> `foo(x: Dynamic, y: Dynamic, z: Dynamic) -> Result<Dynamic, Box<EvalAltResult>>`
|
||||
|
||||
### Plugin Functions
|
||||
|
||||
Functions defined in [plugin modules] are the best.
|
||||
They contain all metadata describing the functions, including [doc-comments].
|
||||
|
||||
For example, a plugin function `combine`:
|
||||
|
||||
> `/// This is a doc-comment, included in this function's metadata.`
|
||||
> `combine(list: &mut MyStruct<i64>, num: usize, name: &str) -> bool`
|
||||
|
||||
Notice that function names do not need to be valid identifiers.
|
||||
|
||||
For example, an [operator] defined as a [fallible function] in a [plugin module] via
|
||||
`#[rhai_fn(name="+=", return_raw)]` returns `Result<bool, Box<EvalAltResult>>`:
|
||||
|
||||
> `+=(list: &mut MyStruct<i64>, value: &str) -> Result<bool, Box<EvalAltResult>>`
|
||||
|
||||
For example, a [property getter][getters/setters] defined in a [plugin module]:
|
||||
|
||||
> `get$prop(obj: &mut MyStruct<i64>) -> String`
|
@@ -1,49 +0,0 @@
|
||||
Functions and Custom Types Metadata
|
||||
===================================
|
||||
|
||||
{{#include ../../links.md}}
|
||||
|
||||
~~~admonish warning.small "Requires `metadata`"
|
||||
|
||||
Exporting metadata requires the [`metadata`] feature.
|
||||
~~~
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
The _metadata_ of a [function] means all relevant information related to a function's
|
||||
definition including:
|
||||
|
||||
1. Its callable name
|
||||
|
||||
2. Its access mode (public or [private][`private`])
|
||||
|
||||
3. Its parameter names and types (if any)
|
||||
|
||||
4. Its return value and type (if any)
|
||||
|
||||
5. Its nature (i.e. native Rust or Rhai-scripted)
|
||||
|
||||
6. Its [namespace][function namespace] ([module] or global)
|
||||
|
||||
7. Its purpose, in the form of [doc-comments]
|
||||
|
||||
8. Usage notes, warnings, examples etc., in the form of [doc-comments]
|
||||
|
||||
A function's _signature_ encapsulates the first four pieces of information in a single concise line
|
||||
of definition:
|
||||
|
||||
> `[private]` _name_ `(`_param 1_`:`_type 1_`,` _param 2_`:`_type 2_`,` ... `,` _param n_`:`_type n_`) ->` _return type_
|
||||
|
||||
|
||||
Custom Types
|
||||
------------
|
||||
|
||||
The _metadata_ of a [custom type] include:
|
||||
|
||||
1. Its full Rust type name
|
||||
|
||||
2. Its pretty-print _display name_ (which can be the same as its Rust type name)
|
||||
|
||||
3. Its purpose, in the form of [doc-comments]
|
Reference in New Issue
Block a user