mirror of
https://github.com/ink-analyzer/ink-analyzer.git
synced 2025-12-23 10:11:52 +00:00
add hover content
This commit is contained in:
parent
03196163e7
commit
2b888dffbf
8 changed files with 2403 additions and 7 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
464
crates/analyzer/src/analysis/hover.rs
Normal file
464
crates/analyzer/src/analysis/hover.rs
Normal 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)
|
||||
)
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
crates/analyzer/src/analysis/hover/content.rs
Normal file
39
crates/analyzer/src/analysis/hover/content.rs
Normal 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 => "",
|
||||
},
|
||||
}
|
||||
}
|
||||
686
crates/analyzer/src/analysis/hover/content/args.rs
Normal file
686
crates/analyzer/src/analysis/hover/content/args.rs
Normal 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-
|
||||
}
|
||||
```
|
||||
"#;
|
||||
1198
crates/analyzer/src/analysis/hover/content/macros.rs
Normal file
1198
crates/analyzer/src/analysis/hover/content/macros.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -26,6 +26,6 @@
|
|||
//! }
|
||||
//! ```
|
||||
|
||||
pub use self::analysis::{Analysis, Completion, Diagnostic, Severity};
|
||||
pub use self::analysis::{Action, Analysis, Completion, Diagnostic, Hover, Severity};
|
||||
|
||||
mod analysis;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue