mirror of
https://github.com/FuelLabs/sway.git
synced 2025-08-10 21:58:27 +00:00

Some checks failed
CI / build-mdbook (push) Has been cancelled
Codspeed Benchmarks / benchmarks (push) Has been cancelled
CI / check-dependency-version-formats (push) Has been cancelled
CI / check-forc-manifest-version (push) Has been cancelled
CI / get-fuel-core-version (push) Has been cancelled
CI / build-sway-lib-std (push) Has been cancelled
CI / build-sway-examples (push) Has been cancelled
CI / build-reference-examples (push) Has been cancelled
CI / forc-fmt-check-sway-lib-std (push) Has been cancelled
CI / forc-fmt-check-sway-examples (push) Has been cancelled
CI / forc-fmt-check-panic (push) Has been cancelled
CI / check-sdk-harness-test-suite-compatibility (push) Has been cancelled
CI / build-forc-doc-sway-lib-std (push) Has been cancelled
CI / build-forc-test-project (push) Has been cancelled
CI / cargo-build-workspace (push) Has been cancelled
CI / cargo-clippy (push) Has been cancelled
CI / cargo-toml-fmt-check (push) Has been cancelled
CI / cargo-fmt-check (push) Has been cancelled
CI / cargo-run-e2e-test-evm (push) Has been cancelled
CI / cargo-test-lib-std (push) Has been cancelled
CI / forc-run-benchmarks (push) Has been cancelled
CI / verifications-complete (push) Has been cancelled
CI / cargo-run-e2e-test (push) Has been cancelled
CI / cargo-run-e2e-test-release (push) Has been cancelled
CI / cargo-test-forc-debug (push) Has been cancelled
CI / cargo-test-forc-client (push) Has been cancelled
CI / forc-unit-tests (push) Has been cancelled
CI / forc-pkg-fuels-deps-check (push) Has been cancelled
CI / cargo-test-sway-lsp (push) Has been cancelled
CI / cargo-test-forc (push) Has been cancelled
CI / cargo-test-workspace (push) Has been cancelled
CI / cargo-unused-deps-check (push) Has been cancelled
CI / pre-publish-check (push) Has been cancelled
github pages / deploy (push) Has been cancelled
CI / cargo-test-forc-node (push) Has been cancelled
CI / notify-slack-on-failure (push) Has been cancelled
CI / publish (push) Has been cancelled
CI / publish-sway-lib-std (push) Has been cancelled
CI / Build and upload forc binaries to release (push) Has been cancelled
## Description Update all references in the README from the outdated src/tests/data path to the current tests/fixtures directory. This ensures that documentation and example commands accurately reflect the present project structure, preventing confusion and errors for users and contributors. ## Checklist - [ ] I have linked to any relevant issues. - [ ] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [ ] I have added tests that prove my fix is effective or that my feature works. - [ ] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. Co-authored-by: kaya <20915464+kayagokalp@users.noreply.github.com>
289 lines
13 KiB
Markdown
289 lines
13 KiB
Markdown
# Forc Doc
|
||
|
||
The Sway language documenter.
|
||
|
||
---
|
||
|
||
## Quick Start
|
||
|
||
### Prerequisites
|
||
|
||
- Must have [`forc`][forc-reference] installed.
|
||
- Must be in a directory, or parent directory containing a [`Forc.toml`][manifest-reference] and some Sway code that successfully compiles
|
||
- For documentation to appear you need only add doc attributes to documentable items, like so:
|
||
```sway
|
||
/// Defines my contract ABI...
|
||
abi MyContractABI {}
|
||
```
|
||
- You may also document at the module level with the module level doc attribute syntax:
|
||
> **Note:** This will only work at the beginning of Sway files
|
||
```sway
|
||
//! Library containing types used for...
|
||
library;
|
||
```
|
||
Check out the [doc attribute section][sway-reference-attributes-doc] of the Sway reference for more information on how to document Sway code.
|
||
|
||
If you've installed a distributed toolchain via [`fuelup`][fuelup-docs], you already have everything you need to run `forc doc`. Otherwise, you can install `forc` & `forc doc` via `cargo install`, or from `fuelup` directly.
|
||
|
||
The below commands check you have everything necessary to run `forc doc`.
|
||
|
||
```sh
|
||
$ cd my_fuel_project
|
||
$ ls # check Forc.toml exists
|
||
# src Forc.toml
|
||
$ forc --version # check forc is installed
|
||
$ forc doc --version # check forc doc is installed
|
||
$ forc doc --open # open docs in default browser
|
||
```
|
||
|
||
For usage, [see the docs][forc-doc-manual].
|
||
|
||
To install `forc doc` for development, see the [Getting Started](#getting-started) section under [Contributing](#contributing).
|
||
|
||
## Contributing
|
||
|
||
Welcome! We're glad you're here to help. Below is an overview of the program's design choices, as well as how to build `forc doc` and test your changes locally.
|
||
|
||
### Build Requirements
|
||
|
||
- [`cargo`][install-cargo]
|
||
- [`forc`][forc-reference]
|
||
- a default, modern browser (older browsers may cause issues)
|
||
|
||
> **Tip:** If you see no changes take effect, it may be due to multiple `forc doc` binaries. To prevent this, remove any pre-existing versions that take precedence, such as a `fuelup` binary. You can also avoid this by executing the `forc doc` binary via `cargo run`, see [Viewing Changes](#viewing-changes).
|
||
>
|
||
> ```sh
|
||
> $ which forc-doc
|
||
> # ~/.fuelup/bin/forc-doc
|
||
> $ rm ~/.fuelup/bin/forc-doc
|
||
> $ which forc-doc
|
||
> # if it displays nothing, you're good to go!
|
||
> ```
|
||
|
||
### Getting Started
|
||
|
||
Clone the `sway` repository into your preferred directory:
|
||
|
||
```sh
|
||
$ git clone https://github.com/FuelLabs/sway.git
|
||
```
|
||
|
||
Then move into the newly created `sway` directory, and install `forc doc`:
|
||
|
||
```sh
|
||
$ cd sway
|
||
$ cargo install --path forc-plugins/forc-doc
|
||
```
|
||
|
||
Great! Let's check everything is working as intended. Try running `forc doc` on one of the test directories:
|
||
|
||
```sh
|
||
$ forc doc --path src/tests/data/impl_traits --open
|
||
```
|
||
|
||
If it succeeded, you should be seeing the test docs in your browser.
|
||
|
||
### Development
|
||
|
||
New language keyword? Want to add a feature? Updating CSS? `forc doc` is setup to make development easy.
|
||
|
||
#### Design Overview
|
||
|
||
Each section of the project is labeled to its corresponding functionality.
|
||
|
||
- [`doc`](./src/doc/): The documenting phase. Handles analysis of a compiled typed Sway program and collects useful information into `Documents` that can be rendered to HTML. This is where to start if you are trying to implement a new Sway language feature, or make some information about an existing feature available for rendering.
|
||
- [`render`](./src/render/): Renders the information collected by the documenting phase into HTML and places them into the `out/doc` directory. This phase is intended to be especially friendly to those familiar with building static HTML webpages. The [`horrorshow` library][horrorshow] uses macros to write HTML that look strikingly similar to writing plain HTML.
|
||
- [`licenses`](./src/licenses/): Files that must be present in docs generated by `forc doc` for use of fonts, logos or anything pertaining to the project that requires a license.
|
||
- [`static.files`](./src/static.files/): Files that must be present in docs generated by `forc doc` in order for styling to take effect, eg CSS, icons & fonts.
|
||
- [`fixtures`](./tests/fixtures/): This is where edge case Sway code lives. If an edge case bug arises, write a minimal reproduction and place it here to start.
|
||
|
||
Try running `cargo doc` on the `forc-doc` project directory for an in-depth look at what each section is responsible for!
|
||
|
||
#### The Documenting Phase
|
||
|
||
##### Documentable Items
|
||
|
||
Adding new documentable items is very straight-forward. Documentable items take only two forms, declarations (`TyDecl`s) and context (everything else).
|
||
|
||
Declarations can be added directly to the description phase of the analysis, found in [`descriptor.rs`](./src/doc/descriptor.rs). Just add the new `TyDecl` to the match arm of `from_typed_decl` and fill in the necessary fields for the resulting `Descriptor` wrapped `Document`, then return it as `Documentable`.
|
||
|
||
Context items, eg fields on structs, variants of an enum etc, must be added to the `ContextType` enum, found in [`context.rs`](./src/render/item/context.rs) and collected at the time of its corresponding `TyDecl`'s analysis. The `ContextType` is wrapped by a `Context` struct which is later sorted and rendered to the `ItemContext` of a `RenderedDocument`.
|
||
|
||
Example:
|
||
|
||
Let's say that we want to have a new declaration type called `CoolNewDecl`, modeled after the `StructDecl` but with some special purpose.
|
||
|
||
First, we would add the context of the declaration to the `ContextType` as a variant:
|
||
|
||
```rust
|
||
// in context.rs
|
||
pub(crate) enum ContextType {
|
||
// Add in the new declaration's context type
|
||
CoolNewFields(Vec<TyCoolNewField>),
|
||
/* ... */
|
||
}
|
||
```
|
||
|
||
Then, match for the new declaration and return the `Document`.
|
||
|
||
```rust
|
||
// in descriptor.rs
|
||
pub(crate) enum Descriptor {
|
||
Documentable(Document),
|
||
NonDocumentable,
|
||
}
|
||
impl Descriptor {
|
||
pub(crate) fn from_typed_decl(/* ... */) -> Result<Self> {
|
||
match ty_decl {
|
||
// Add the new declaration to the match arm
|
||
ty::TyDecl::CoolNewDecl(ty::CoolNewDecl { decl_id, .. }) => {
|
||
let decl = decl_engine.get_cool_new_decl(decl_id);
|
||
if !document_private_items && decl.visibility.is_private() {
|
||
Ok(Descriptor::NonDocumentable)
|
||
} else {
|
||
let item_name = decl.call_path.suffix;
|
||
let attrs_opt = (!decl.attributes.is_empty())
|
||
.then(|| decl.attributes.to_html_string());
|
||
// Fill in the context of the new declaration
|
||
let context = (!decl.fields.is_empty()).then_some(Context::new(
|
||
module_info.clone(),
|
||
ContextType::CoolNewFields(decl.fields),
|
||
));
|
||
|
||
Ok(Descriptor::Documentable(Document {
|
||
module_info: module_info.clone(),
|
||
item_header: ItemHeader {
|
||
module_info: module_info.clone(),
|
||
friendly_name: ty_decl.friendly_type_name(),
|
||
item_name: item_name.clone(),
|
||
},
|
||
item_body: ItemBody {
|
||
module_info,
|
||
ty_decl: ty_decl.clone(),
|
||
item_name,
|
||
code_str: swayfmt::parse::parse_format::<sway_ast::ItemCoolNew>(
|
||
decl.span.as_str(),
|
||
)?,
|
||
attrs_opt: attrs_opt.clone(),
|
||
item_context: ItemContext {
|
||
context_opt: context,
|
||
impl_traits: None,
|
||
},
|
||
},
|
||
raw_attributes: attrs_opt,
|
||
}))
|
||
}
|
||
}
|
||
/* ... */
|
||
_ => Ok(Descriptor::NonDocumentable),
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Once the declarations are collected into a `Document`, the `Document` can then be rendered. Refer to the `from_raw_docs` method on `RenderedDocumentation` found in [`render/mod.rs`](./src/render/mod.rs) for the beginning of the rendering phase. There you can find plenty of examples on how to render `Document`s into `RenderedDocument`s if you are adding in a new documentable item.
|
||
|
||
##### Index File Generation
|
||
|
||
Index files, such as the `AllDocIndex`, `ProjectIndex` and `ModuleIndex`s, are rendered using only the information gathered from Sway modules. The process for their rendering can also be found in the `RenderedDocumentation::from_raw_docs` method. `ModuleInfo` is gathered from at point of generating the `Documentation` from a `TyProgram`, found in [`doc/mod.rs`](./src/doc/mod.rs). This is the starting point of the entire analytical process, where a `TyProgram` is compiled and passed to `Documentation::from_ty_program`.
|
||
|
||
#### The Rendering Phase
|
||
|
||
As stated before, rendering is fairly straight-forward in `forc doc`, as the HTML is that of a generic webpage.
|
||
|
||
Let's try writing a small render-side example together, using the `horrorshow` library.
|
||
|
||
Here is the HTML for the search bar on [`docs.rs`][docs.rs]:
|
||
|
||
```html
|
||
<nav class="sub">
|
||
<form class="search-form">
|
||
<div class="search-container">
|
||
<span></span>
|
||
<input
|
||
class="search-input"
|
||
name="search"
|
||
autocomplete="off"
|
||
spellcheck="false"
|
||
placeholder="Click or press ‘S’ to search, ‘?’ for more options…"
|
||
type="search"
|
||
/>
|
||
<div id="help-button" title="help" tabindex="-1">
|
||
<a href="../help.html">?</a>
|
||
</div>
|
||
<div id="settings-menu" tabindex="-1">
|
||
<a href="../settings.html" title="settings">
|
||
<img
|
||
width="22"
|
||
height="22"
|
||
alt="change settings"
|
||
src="../static.files/wheel-7b819b6101059cd0.svg"
|
||
/>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</nav>
|
||
```
|
||
|
||
Here is the corresponding `horrorshow` code that produces the same HTML:
|
||
|
||
```rust
|
||
mod search {
|
||
use horrorshow::{box_html, RenderBox};
|
||
|
||
pub(crate) fn generate_searchbar() -> Box<dyn RenderBox> {
|
||
box_html! {
|
||
nav(class="sub") {
|
||
form(class="search-form") {
|
||
div(class="search-container") {
|
||
span;
|
||
input(
|
||
class="search-input",
|
||
name="search",
|
||
autocomplete="off",
|
||
spellcheck="false",
|
||
placeholder="Click or press ‘S’ to search, ‘?’ for more options…",
|
||
type="search"
|
||
);
|
||
div(id="help-button", title="help", tabindex="-1") {
|
||
a(href="../help.html") { : "?" }
|
||
}
|
||
div(id="settings-menu", tabindex="-1") {
|
||
a(href="../settings.html", title="settings") {
|
||
img(
|
||
width="22",
|
||
height="22",
|
||
alt="change settings",
|
||
src="../static.files/wheel-7b819b6101059cd0.svg"
|
||
)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
Now we can call this function anytime we need to generate a searchbar for our webpage!
|
||
|
||
### Viewing Changes
|
||
|
||
Once you've made some changes, run the `forc doc` binary, passing it a path containing a `Forc.toml`:
|
||
|
||
```sh
|
||
cargo run -- --path path/to/manifest --open
|
||
```
|
||
|
||
> **Tip:** VS Code user? Try the Live Server plugin to make viewing changes even easier. It will reload a webpage on updates, so you only need to rebuild the docs (`cargo run -- --path path/to/manifest`). Just right click the index file of docs produced by `forc doc` which can be found in the `out/doc` directory, and choose the option "open with Live Server". Voila!
|
||
|
||
[forc-reference]: https://fuellabs.github.io/sway/master/book/forc/index.html "forc reference"
|
||
[manifest-reference]: https://fuellabs.github.io/sway/master/book/forc/manifest_reference.html "manifest reference"
|
||
[sway-reference-attributes-doc]: https://fuellabs.github.io/sway/master/book/reference/attributes.html#doc "the Sway reference - doc attribute usage"
|
||
[fuelup-docs]: https://install.fuel.network/master/ "fuelup docs"
|
||
[forc-doc-manual]: https://fuellabs.github.io/sway/master/book/forc/plugins/forc_doc.html "forc-doc manual"
|
||
[install-cargo]: https://doc.rust-lang.org/cargo/getting-started/installation.html "install cargo"
|
||
[horrorshow]: https://docs.rs/horrorshow/latest/horrorshow/ "horrorshow docs"
|
||
[docs.rs]: https://docs.rs/
|