add hover content

This commit is contained in:
davidsemakula 2023-05-27 23:42:37 +03:00
parent 03196163e7
commit 2b888dffbf
8 changed files with 2403 additions and 7 deletions

View file

@ -4,7 +4,7 @@ A collection of modular and reusable libraries and tools for semantic analysis o
ink! analyzer aims to improve [ink!](https://use.ink/) language support in [integrated development environments (IDEs)](https://en.wikipedia.org/wiki/Integrated_development_environment), [source code editors](https://en.wikipedia.org/wiki/Source-code_editor) and other development tools by providing modular and reusable building blocks for implementing features like diagnostics, code completion, code/intent actions and hover content for the [ink! programming language](https://use.ink/) which is used for writing smart contracts for blockchains built on [Substrate](https://substrate.io/).
**NOTE:** This project is still work in progress, check back over the next few weeks for regular updates.
**NOTE:** 🚧 This project is still work in progress, check back over the next few weeks for regular updates.
## Architecture
@ -19,6 +19,7 @@ It currently implements an [Analysis](/crates/analyzer/src/analysis.rs) entry po
- [diagnostics](/crates/analyzer/src/analysis/diagnostics.rs) - errors and warnings based on ink! semantic rules.
- [completions](/crates/analyzer/src/analysis/completions.rs) - completion suggestions for ink! attribute macros and arguments.
- [code/intent actions](/crates/analyzer/src/analysis/actions.rs) - contextual assists for adding relevant ink! attribute macros and arguments.
- [hover content](/crates/analyzer/src/analysis/hover.rs) - descriptive/informational text for ink! attribute macros and arguments.
### 2. [IR (ink-analyzer-ir)](/crates/ir)
This crate implements types, abstractions and utilities for parsing ink! smart contract code into ink! intermediate representations (IRs) and abstractions.

View file

@ -10,8 +10,9 @@ It currently implements an [Analysis](/crates/analyzer/src/analysis.rs) entry po
- [diagnostics](/crates/analyzer/src/analysis/diagnostics.rs) - errors and warnings based on ink! semantic rules.
- [completions](/crates/analyzer/src/analysis/completions.rs) - completion suggestions for ink! attribute macros and arguments.
- [code/intent actions](/crates/analyzer/src/analysis/actions.rs) - contextual assists for adding relevant ink! attribute macros and arguments.
- [hover content](/crates/analyzer/src/analysis/hover.rs) - descriptive/informational text for ink! attribute macros and arguments.
**NOTE:** This project is still work in progress, check back over the next few weeks for regular updates.
**NOTE:** 🚧 This project is still work in progress, check back over the next few weeks for regular updates.
## Installation

View file

@ -1,18 +1,20 @@
//! Types and abstractions for performing semantic analysis of ink! smart contract code.
use ink_analyzer_ir::syntax::TextSize;
use ink_analyzer_ir::syntax::{TextRange, TextSize};
use ink_analyzer_ir::InkFile;
pub use actions::Action;
pub use completions::Completion;
pub use diagnostics::{Diagnostic, Severity};
pub use hover::Hover;
mod actions;
mod completions;
mod diagnostics;
mod hover;
mod utils;
/// Analysis is the main entry point for asking for semantic information about ink! smart contract code.
/// Entry point for asking for semantic information about ink! smart contract code.
#[derive(Debug)]
pub struct Analysis {
/// The ink! smart contract code being analyzed.
@ -37,13 +39,18 @@ impl Analysis {
diagnostics::diagnostics(&self.file)
}
/// Computes completions at the given position.
/// Computes ink! attribute completions at the given position.
pub fn completions(&self, position: TextSize) -> Vec<Completion> {
completions::completions(&self.file, position)
}
/// Computes code/intent actions for the given position.
/// Computes ink! attribute code/intent actions for the given position.
pub fn actions(&self, position: TextSize) -> Vec<Action> {
actions::actions(&self.file, position)
}
/// Returns descriptive/informational text for the ink! attribute at the given position (if any).
pub fn hover(&self, range: TextRange) -> Option<Hover> {
hover::hover(&self.file, range)
}
}

View file

@ -0,0 +1,464 @@
//! ink! attribute hover content.
use ink_analyzer_ir::syntax::{AstNode, AstToken, SyntaxElement, TextRange};
use ink_analyzer_ir::{
ast, FromSyntax, InkArgKind, InkAttribute, InkAttributeKind, InkEntity, InkFile, InkMacroKind,
};
mod content;
/// An ink! attribute hover result.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Hover {
/// Range the hover content applies to.
pub range: TextRange,
/// Replacement text for the action.
pub content: String,
}
/// Returns descriptive/informational text for the ink! attribute at the given position (if any).
/// Returns documentation for the ink! attribute kind.
///
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L90-L516>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.chain_extension.html>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.1.0/crates/ink/macro/src/lib.rs#L848-L1280>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.storage_item.html>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.1.0/crates/ink/macro/src/lib.rs#L772-L799>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.test.html>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.1.0/crates/ink/macro/src/lib.rs#L805-L846>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.trait_definition.html>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.1.0/crates/ink/macro/src/lib.rs#L597-L643>.
pub fn hover(file: &InkFile, range: TextRange) -> Option<Hover> {
// Finds the covering ink! attribute for the text range (if any).
let covering_ink_attr = if range.is_empty() {
// Uses item at offset utility if the range start and end are equal.
file.item_at_offset(range.start()).parent_ink_attr()
} else {
file.syntax()
.text_range()
// Ensure the text range is in the bounds of the source code.
.contains_range(range)
.then(|| {
// Returns deepest ink! attribute that fully covers the text range.
let covering_element = file.syntax().covering_element(range);
let attr = if ast::Attr::can_cast(covering_element.kind()) {
// Casts cover element to `ast::Attr` node if it's an attribute.
covering_element.into_node().and_then(ast::Attr::cast)
} else {
// Finds the parent attribute (if any) of the covering element.
ink_analyzer_ir::closest_ancestor_ast_type::<SyntaxElement, ast::Attr>(
&covering_element,
)
};
// Converts to ink! attribute (if present).
attr.and_then(InkAttribute::cast)
})
.flatten()
};
// Returns hover content only if the text range is covered by an ink! attribute.
covering_ink_attr.and_then(|ink_attr| {
// Finds the covered ink! attribute argument (if any).
let ink_arg = ink_attr
.args()
.iter()
.find(|arg| arg.text_range().contains_range(range));
match ink_arg {
// Returns hover content for the covered ink! attribute argument if it's valid.
Some(ink_arg) => (*ink_arg.kind() != InkArgKind::Unknown).then_some(Hover {
range: ink_arg
.name()
.map(|ink_arg_name| ink_arg_name.syntax().text_range())
.unwrap_or(ink_arg.text_range()),
content: content::doc(&InkAttributeKind::Arg(*ink_arg.kind())).to_string(),
}),
// Returns hover content based on the macro or "primary" argument for the ink! attribute,
// See `ink_analyzer_ir::attrs::utils::sort_ink_args_by_kind` doc.
None => match ink_attr.kind() {
// Returns hover content based on the "primary" ink! attribute argument if it's valid,
// See `ink_analyzer_ir::attrs::utils::sort_ink_args_by_kind` doc.
InkAttributeKind::Arg(arg_kind) => {
(*arg_kind != InkArgKind::Unknown).then_some(Hover {
range: ink_attr
.ink_arg_name()
.map(|ink_arg_name| ink_arg_name.syntax().text_range())
.unwrap_or(ink_attr.syntax().text_range()),
content: content::doc(&InkAttributeKind::Arg(*arg_kind)).to_string(),
})
}
// Returns hover content based on the ink! attribute macro if it's valid.
InkAttributeKind::Macro(macro_kind) => (*macro_kind != InkMacroKind::Unknown)
.then_some(Hover {
range: ink_attr
.ink_macro()
.map(|ink_macro_name| ink_macro_name.syntax().text_range())
.unwrap_or(ink_attr.syntax().text_range()),
content: content::doc(&InkAttributeKind::Macro(*macro_kind)).to_string(),
}),
},
}
})
}
#[cfg(test)]
mod tests {
use super::*;
use ink_analyzer_ir::syntax::TextSize;
use test_utils::parse_offset_at;
#[test]
fn hover_works() {
for (code, scenarios) in [
// (code, pat, [(edit, pat_start, pat_end)]) where:
// code = source code,
// pat = substring used to find the cursor offset (see `test_utils::parse_offset_at` doc),
// edit = the text that will inserted (represented without whitespace for simplicity),
// pat_start = substring used to find the start of the edit offset (see `test_utils::parse_offset_at` doc),
// pat_end = substring used to find the end of the edit offset (see `test_utils::parse_offset_at` doc).
// ink! attribute macros.
(
"#[ink::contract]",
vec![
(
Some("<-#"),
Some("<-#"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-#"),
Some("ink"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-contract"),
Some("contract"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-#"),
Some("]"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
],
),
(
r#"
#[ink::contract(env=my::env::Types, keep_attr="foo,bar")]
"#,
vec![
(
Some("<-#"),
Some("<-#"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-#"),
Some("ink"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-contract"),
Some("contract"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-#"),
Some("]"),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-env="),
Some("(env"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Env)),
Some("<-env="),
Some("(env"),
)),
),
(
Some("<-my::env::Types"),
Some("my::env::Types"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Env)),
Some("<-env="),
Some("(env"),
)),
),
(
Some("<-,"),
Some(","),
Some((
content::doc(&InkAttributeKind::Macro(InkMacroKind::Contract)),
Some("<-contract"),
Some("contract"),
)),
),
(
Some("<-keep_attr"),
Some("keep_attr"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::KeepAttr)),
Some("<-keep_attr"),
Some("keep_attr"),
)),
),
(
Some(r#"<-"foo,bar""#),
Some(r#""foo,bar""#),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::KeepAttr)),
Some("<-keep_attr"),
Some("keep_attr"),
)),
),
],
),
// ink! attribute arguments.
(
"#[ink(storage)]",
vec![
(
Some("<-#"),
Some("<-#"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Storage)),
Some("<-storage"),
Some("storage"),
)),
),
(
Some("<-#"),
Some("ink"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Storage)),
Some("<-storage"),
Some("storage"),
)),
),
(
Some("<-storage"),
Some("storage"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Storage)),
Some("<-storage"),
Some("storage"),
)),
),
(
Some("<-#"),
Some("]"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Storage)),
Some("<-storage"),
Some("storage"),
)),
),
],
),
(
"#[ink(message, default, payable, selector=_)]",
vec![
(
Some("<-#"),
Some("<-#"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Message)),
Some("<-message"),
Some("message"),
)),
),
(
Some("<-#"),
Some("ink"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Message)),
Some("<-message"),
Some("message"),
)),
),
(
Some("<-message"),
Some("message"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Message)),
Some("<-message"),
Some("message"),
)),
),
(
Some("<-#"),
Some("]"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Message)),
Some("<-message"),
Some("message"),
)),
),
(
Some("<-payable"),
Some("payable"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Payable)),
Some("<-payable"),
Some("payable"),
)),
),
(
Some("<-selector"),
Some("selector"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Selector)),
Some("<-selector"),
Some("selector"),
)),
),
(
Some("<-_"),
Some("_"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Selector)),
Some("<-selector"),
Some("selector"),
)),
),
],
),
(
"#[ink(extension=1, handle_status=true)]",
vec![
(
Some("<-#"),
Some("<-#"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Extension)),
Some("<-extension"),
Some("extension"),
)),
),
(
Some("<-#"),
Some("ink"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Extension)),
Some("<-extension"),
Some("extension"),
)),
),
(
Some("<-extension"),
Some("extension"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Extension)),
Some("<-extension"),
Some("extension"),
)),
),
(
Some("<-#"),
Some("]"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Extension)),
Some("<-extension"),
Some("extension"),
)),
),
(
Some("<-1"),
Some("1"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::Extension)),
Some("<-extension"),
Some("extension"),
)),
),
(
Some("<-handle_status"),
Some("handle_status"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::HandleStatus)),
Some("<-handle_status"),
Some("handle_status"),
)),
),
(
Some("<-true"),
Some("true"),
Some((
content::doc(&InkAttributeKind::Arg(InkArgKind::HandleStatus)),
Some("<-handle_status"),
Some("handle_status"),
)),
),
],
),
] {
for (pat_start, pat_end, expect_result) in scenarios {
let range = TextRange::new(
TextSize::from(parse_offset_at(code, pat_start).unwrap() as u32),
TextSize::from(parse_offset_at(code, pat_end).unwrap() as u32),
);
let result = hover(&InkFile::parse(code), range);
assert_eq!(
result
.as_ref()
.map(|hover_result| (hover_result.content.as_str(), hover_result.range)),
expect_result.map(|(content, pat_start, pat_end)| (
content,
TextRange::new(
TextSize::from(parse_offset_at(code, pat_start).unwrap() as u32),
TextSize::from(parse_offset_at(code, pat_end).unwrap() as u32)
)
))
);
}
}
}
}

View file

@ -0,0 +1,39 @@
//! Hover content for ink! attributes.
use ink_analyzer_ir::{InkArgKind, InkAttributeKind, InkMacroKind};
mod args;
mod macros;
/// Returns documentation for the ink! attribute kind.
pub fn doc(attr_kind: &InkAttributeKind) -> &str {
match attr_kind {
InkAttributeKind::Arg(arg_kind) => match arg_kind {
InkArgKind::Anonymous => args::ANONYMOUS_DOC,
InkArgKind::Constructor => args::CONSTRUCTOR_DOC,
InkArgKind::Default => args::DEFAULT_DOC,
InkArgKind::Derive => args::DERIVE_DOC,
InkArgKind::Env => args::ENV_DOC,
InkArgKind::Event => args::EVENT_DOC,
InkArgKind::Extension => args::EXTENSION_DOC,
InkArgKind::HandleStatus => args::HANDLE_STATUS_DOC,
InkArgKind::Impl => args::IMPL_DOC,
InkArgKind::KeepAttr => args::KEEP_ATTR_DOC,
InkArgKind::Message => args::MESSAGE_DOC,
InkArgKind::Namespace => args::NAMESPACE_DOC,
InkArgKind::Payable => args::PAYABLE_DOC,
InkArgKind::Selector => args::SELECTOR_DOC,
InkArgKind::Storage => args::STORAGE_DOC,
InkArgKind::Topic => args::TOPIC_DOC,
InkArgKind::Unknown => "",
},
InkAttributeKind::Macro(macro_kind) => match macro_kind {
InkMacroKind::ChainExtension => macros::CHAIN_EXTENSION_DOC,
InkMacroKind::Contract => macros::CONTRACT_DOC,
InkMacroKind::StorageItem => macros::STORAGE_ITEM_DOC,
InkMacroKind::Test => macros::TEST_DOC,
InkMacroKind::TraitDefinition => macros::TRAIT_DEFINITION_DOC,
InkMacroKind::Unknown => "",
},
}
}

View file

@ -0,0 +1,686 @@
//! Hover content for ink! attribute arguments.
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const ANONYMOUS_DOC: &str = r#"
# Attribute
`#[ink(anonymous)]`
# Description
Tells the ink! codegen to treat the ink! event as anonymous which omits the event signature as topic upon emitting.
Very similar to anonymous events in Solidity.
# Usage
Applicable to ink! events.
# Example
```
#[ink::contract]
mod my_contract {
#[ink(event, anonymous)]
pub struct MyEvent {
value: bool,
}
// -snip-
}
```
OR
```
#[ink::contract]
mod my_contract {
#[ink(event)]
#[ink(anonymous)]
pub struct MyEvent {
value: bool,
}
// -snip-
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L235-L263>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const CONSTRUCTOR_DOC: &str = r#"
# Attribute
`#[ink(constructor)]`
# Description
Flags a method for the ink! storage `struct` as constructor making it available to the API for instantiating the contract.
# Usage
Applicable to methods.
# Example
```
#[ink::contract]
mod my_contract {
// -snip-
impl MyContract {
#[ink(constructor)]
pub fn new(initial_value: bool) -> Self {
MyContract { value: false }
}
// -snip-
}
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/issues/1703>.
pub const DEFAULT_DOC: &str = r#"
# Attribute
`#[ink(default)]`
# Description
Tells UI to treat the ink! message or ink! constructor as the default choice in selection widgets (e.g dropdowns).
It can be used exactly once for a constructor and once for a message.
# Usage
Applicable to ink! messages and ink! constructors.
# Example
```
#[ink::contract]
mod my_contract {
// -snip-
impl MyContract {
// -snip-
/// Update the current value.
#[ink(message)]
#[ink(default)] // You can either specify default out-of-line.
pub fn set(&mut self) {
self.value = !self.value;
}
}
}
```
OR
```
#[ink::contract]
mod my_contract {
// -snip-
impl MyContract {
// -snip-
/// Update the current value.
#[ink(message, default)] // ...or specify default inline.
pub fn set(&mut self) {
self.value = !self.value;
}
}
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L777-L799>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.storage_item.html>.
pub const DERIVE_DOC: &str = r#"
# Attribute
`#[ink::storage_item(derive = flag: bool)]`
# Description
A configuration parameter used to enable/disable auto deriving of all required storage traits.
# Usage
Additional argument for ink! storage item attribute macro.
**Default value:** `true`.
# Example
```
use ink::storage::Mapping;
use ink::storage::traits::{
StorableHint,
StorageKey,
Storable,
};
#[ink::storage_item(derive = false)]
#[derive(StorableHint, Storable, StorageKey)]
struct NonPackedGeneric<T: ink::storage::traits::Packed> {
s1: u32,
s2: Mapping<u128, T>,
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L143-L199>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const ENV_DOC: &str = r#"
# Attribute
`#[ink::contract(env = E: impl Environment)]`
# Description
Tells the ink! code generator which environment to use for the ink! smart contract.
The environment must implement the `Environment` (defined in `ink_env`) trait and provides all the necessary fundamental type definitions for `Balance`, `AccountId` etc.
# Usage
Additional argument for ink! contract attribute macro.
When using a custom `Environment` implementation for a smart contract all types that it exposes to the ink! smart contract and the mirrored types used in the runtime must be aligned with respect to SCALE encoding and semantics.
**Default value:** `DefaultEnvironment` defined in `ink_env` crate.
# Example
Given a custom `Environment` implementation:
```
pub struct MyEnvironment;
impl ink_env::Environment for MyEnvironment {
const MAX_EVENT_TOPICS: usize = 3;
type AccountId = [u8; 16];
type Balance = u128;
type Hash = [u8; 32];
type Timestamp = u64;
type BlockNumber = u32;
type ChainExtension = ::ink::env::NoChainExtension;
}
```
A user might implement their ink! smart contract using the above custom `Environment` implementation as demonstrated below:
```
#[ink::contract(env = MyEnvironment)]
mod my_contract {
// -snip-
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L429-L475>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const EVENT_DOC: &str = r#"
# Attribute
`#[ink(event)]`
# Description
Defines an ink! event.
A contract can define multiple such ink! events.
# Usage
On `struct` definitions.
# Example
```
#[ink::contract]
mod erc20 {
/// Defines an event that is emitted every time value is transferred.
#[ink(event)]
pub struct Transferred {
from: Option<AccountId>,
to: Option<AccountId>,
value: Balance,
}
// -snip-
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L877-L904>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.chain_extension.html>.
pub const EXTENSION_DOC: &str = r#"
# Attribute
`ink(extension = N:u32)`
# Description
Determines the unique function ID of the chain extension method.
# Usage
Required attribute for chain extension methods.
# Example
```
type Access = i32;
#[ink::chain_extension]
pub trait MyChainExtension {
type ErrorCode = i32;
#[ink(extension = 5)]
fn key_access_for_account(key: &[u8], account: &[u8]) -> Access;
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L906-L955>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.chain_extension.html>.
pub const HANDLE_STATUS_DOC: &str = r#"
# Attribute
`ink(handle_status = flag:bool)`
# Description
Assumes that the returned status code of the chain extension method always indicates success and therefore always loads and decodes the output buffer of the call.
# Usage
Applicable to chain extension methods.
**Default value:** `true`.
# Example
```
type Access = i32;
#[ink::chain_extension]
pub trait MyChainExtension {
type ErrorCode = i32;
#[ink(extension = 5, handle_status = false)]
fn key_access_for_account(key: &[u8], account: &[u8]) -> Access;
}
```
OR
```
type Access = i32;
#[ink::chain_extension]
pub trait MyChainExtension {
type ErrorCode = i32;
#[ink(extension = 5)]
#[ink(handle_status = false)]
fn key_access_for_account(key: &[u8], account: &[u8]) -> Access;
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/ir/src/ir/item_impl/mod.rs#L122-L155>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.1.0/crates/ink/ir/src/ir/item_mod.rs#L408-L470>.
pub const IMPL_DOC: &str = r#"
# Attribute
`#[ink(impl)]`
# Description
Tells the ink! codegen that some implementation block shall be granted access to ink! internals even without it containing any ink! messages or ink! constructors.
# Usage
Applicable to ink! implementation blocks.
# Example
```
#[ink(impl)]
impl MyContract {
fn my_function(&self) {
// inherent method implementation
unimplemented!()
}
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L116-L138>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L622-L640>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.trait_definition.html>.
pub const KEEP_ATTR_DOC: &str = r#"
# Attribute
`#[ink::contract(keep_attr = N:string)]` or `#[ink::trait_definition(keep_attr = N:string)]`
# Description
Tells the ink! code generator which attributes should be passed to call builders.
Call builders are used to doing cross-contract calls and are automatically generated for contracts.
# Usage
Additional argument for ink! contract and ink! trait definition attribute macros.
**Allowed attributes by default:** `cfg`, `cfg_attr`, `allow`, `warn`, `deny`, `forbid`, `deprecated`, `must_use`, `doc`, `rustfmt`.
# Example
```
#[ink::contract(keep_attr = "foo, bar")]
mod my_contract {
#[ink(storage)]
pub struct MyContract;
impl MyContract {
#[ink(constructor)]
#[bar]
pub fn new() -> Self { MyContract {} }
#[ink(message)]
#[foo]
pub fn message(&self) {}
}
// -snip-
}
```
OR
```
#[ink::trait_definition(keep_attr = "foo, bar")]
pub trait MyTrait {
#[ink(message)]
#[foo]
fn message1(&self);
#[ink(message)]
#[bar]
fn message2(&self);
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L265-L308>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const MESSAGE_DOC: &str = r#"
# Attribute
`#[ink(message)]`
# Description
Flags a method for the ink! storage `struct` as message making it available to the API for calling the contract.
# Usage
Applicable to methods.
# Example
```
#[ink::contract]
mod my_contract {
// -snip-
impl MyContract {
// -snip-
/// Updates the current value.
#[ink(message)]
pub fn set(&mut self) {
self.value = !self.value;
}
/// Returns the current value.
#[ink(message)]
pub fn get(&self) -> bool {
self.value
}
}
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L602-L620>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.trait_definition.html>.
pub const NAMESPACE_DOC: &str = r#"
# Attribute
`#[ink(namespace = N:string)]`
# Description
Changes the resulting selectors of all the ink! messages and ink! constructors within the trait implementation.
Allows to disambiguate between trait implementations with overlapping message or constructor names.
**Use only with great care and consideration!**
# Usage
Applicable to ink! trait implementation blocks.
**Default value:** Empty.
# Example
```
#[ink::trait_definition(namespace = "foo")]
pub trait TraitDefinition {
#[ink(message)]
fn message1(&self);
#[ink(message, selector = 42)]
fn message2(&self);
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L310-L345>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const PAYABLE_DOC: &str = r#"
# Attribute
`#[ink(payable)]`
# Description
Allows receiving value as part of the call of the ink! message.
ink! constructors are implicitly payable.
# Usage
Applicable to ink! messages.
# Example
```
#[ink::contract]
mod my_contract {
// -snip-
impl MyContract {
// -snip-
/// Update the current value.
#[ink(message)]
#[ink(payable)] // You can either specify payable out-of-line.
pub fn set(&mut self) {
self.value = !self.value;
}
/// Returns the current value.
#[ink(message, payable)] // ...or specify payable inline.
pub fn get(&self) -> bool {
self.value
}
}
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L347-L384>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const SELECTOR_DOC: &str = r#"
# Attribute
`#[ink(selector = S:u32 | _)]`
# Description
The `#[ink(selector = S:u32)]` variant specifies a concrete dispatch selector for the flagged entity.
This allows a contract author to precisely control the selectors of their APIs making it possible to rename their API without breakage.
While the `#[ink(selector = _)]` variant specifies a fallback message that is invoked if no other ink! message matches a selector.
# Usage
The `#[ink(selector = S:u32)]` variant is applicable to ink! messages and ink! constructors.
While the `#[ink(selector = _)]` variant is applicable to ink! messages.
# Example
```
#[ink::contract]
mod my_contract {
// -snip-
impl MyContract {
#[ink(constructor)]
#[ink(selector = 0xDEADBEEF)] // Works on constructors as well.
pub fn new(initial_value: bool) -> Self {
MyContract { value: false }
}
/// Updates the current value.
#[ink(message)]
#[ink(selector = 0xCAFEBABE)] // You can either specify selector out-of-line.
pub fn set(&mut self) {
self.value = !self.value;
}
/// Returns the current value.
#[ink(message, selector = 0xFEEDBEEF)] // ...or specify selector inline.
pub fn get(&self) -> bool {
self.value
}
}
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
///
/// Ref: <https://github.com/paritytech/ink/blob/v4.2.0/crates/ink/macro/src/lib.rs#L208-L233>.
///
/// Ref: <https://paritytech.github.io/ink/ink/attr.contract.html>.
pub const STORAGE_DOC: &str = r#"
# Attribute
`#[ink(storage)]`
# Description
Defines the ink! storage `struct`.
There can only be one ink! storage definition per contract.
# Usage
On `struct` definitions.
# Example
```
#[ink::contract]
mod my_contract {
#[ink(storage)]
pub struct MyContract {
value: bool,
}
// -snip-
}
```
"#;
/// Ref: <https://github.com/paritytech/ink/tree/v4.2.0#ink-macros--attributes-overview>.
pub const TOPIC_DOC: &str = r#"
# Attribute
`#[ink(topic)]`
# Description
Tells the ink! codegen to provide a topic hash for the given field.
Every ink! event can only have a limited number of such topic fields.
Similar semantics as to indexed event arguments in Solidity.
# Usage
Applicable on ink! event field.
# Example
```
#[ink::contract]
mod my_contract {
#[ink(event)]
pub struct MyEvent {
#[ink(topic)]
value: bool,
}
// -snip-
}
```
"#;

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,6 @@
//! }
//! ```
pub use self::analysis::{Analysis, Completion, Diagnostic, Severity};
pub use self::analysis::{Action, Analysis, Completion, Diagnostic, Hover, Severity};
mod analysis;