Skip to content

Commit

Permalink
Store attributes in the ParseProgram declaration types. (#2792)
Browse files Browse the repository at this point in the history
This PR carries over any attributes that were parsed and stored in
`sway_ast::Module` into the `ParseProgram` decl types.

My primary motivation for adding this was so the language server could
access:
1. the attribute tokens so we can assign correct semantic information to
them for correct syntax highlighting
2. allow access to the doc attribute so we can provide in-editor
documentation pop-ups for hover requests.

See `sway-lsp/src/utils/attributes.rs` mod for the intended API for
accessing these tokens.

I did notice that in #1488 @ortho mentioned the next step would be to
pass the attributes into the AST. Feel free to let me know if you had
another idea for how these would be stored. I'm converting the
`AttributeDecl` into the `Attribute` type below which basically throws
away bracket & punctuation tokens and retains each of the `Ident`s. Then
the `AttributesMap` is what is stored in the AST. Similar to how it
worked before but now instead of having the map just store the vec of
args, it also stores the attribute name.

```rust
pub enum AttributeKind {
    Doc,
    Storage,
}

pub struct Attribute {
    pub name: Ident,
    pub args: Vec<Ident>,
}

pub type AttributesMap = HashMap<AttributeKind, Vec<Attribute>>;
```
  • Loading branch information
JoshuaBatty authored Sep 26, 2022
1 parent d5115ae commit 4a0b313
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 59 deletions.
135 changes: 99 additions & 36 deletions sway-core/src/convert_parse_tree.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions sway-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub use asm_generation::from_ir::compile_ir_to_asm;
use asm_generation::FinalizedAsm;
pub use build_config::BuildConfig;
use control_flow_analysis::ControlFlowGraph;
pub use convert_parse_tree::{Attribute, AttributeKind, AttributesMap};
use metadata::MetadataManager;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
Expand Down
3 changes: 2 additions & 1 deletion sway-core/src/parse_tree/declaration/constant.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use crate::{
parse_tree::{Expression, Visibility},
type_system::TypeInfo,
AttributesMap,
};

use sway_types::{Ident, Span};

#[derive(Debug, Clone)]
pub struct ConstantDeclaration {
pub name: Ident,
pub attributes: AttributesMap,
pub type_ascription: TypeInfo,
pub type_ascription_span: Option<Span>,
pub value: Expression,
Expand Down
5 changes: 3 additions & 2 deletions sway-core/src/parse_tree/declaration/enum.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::{parse_tree::Visibility, type_system::*};

use crate::{parse_tree::Visibility, type_system::*, AttributesMap};
use sway_types::{ident::Ident, span::Span};

#[derive(Debug, Clone)]
pub struct EnumDeclaration {
pub name: Ident,
pub attributes: AttributesMap,
pub type_parameters: Vec<TypeParameter>,
pub variants: Vec<EnumVariant>,
pub(crate) span: Span,
Expand All @@ -14,6 +14,7 @@ pub struct EnumDeclaration {
#[derive(Debug, Clone)]
pub struct EnumVariant {
pub name: Ident,
pub attributes: AttributesMap,
pub type_info: TypeInfo,
pub type_span: Span,
pub(crate) tag: usize,
Expand Down
4 changes: 2 additions & 2 deletions sway-core/src/parse_tree/declaration/function.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{parse_tree::*, type_system::*};

use crate::{parse_tree::*, type_system::*, AttributesMap};
use sway_types::{ident::Ident, span::Span};

mod purity;
Expand All @@ -8,6 +7,7 @@ pub use purity::{promote_purity, Purity};
#[derive(Debug, Clone)]
pub struct FunctionDeclaration {
pub purity: Purity,
pub attributes: AttributesMap,
pub name: Ident,
pub visibility: Visibility,
pub body: CodeBlock,
Expand Down
5 changes: 3 additions & 2 deletions sway-core/src/parse_tree/declaration/storage.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::{parse_tree::Expression, type_system::*};

use crate::{parse_tree::Expression, type_system::*, AttributesMap};
use sway_types::{ident::Ident, span::Span};

#[derive(Debug, Clone)]
/// A declaration of contract storage. Only valid within contract contexts.
/// All values in this struct are mutable and persistent among executions of the same contract deployment.
pub struct StorageDeclaration {
pub attributes: AttributesMap,
pub fields: Vec<StorageField>,
pub span: Span,
}
Expand All @@ -17,6 +17,7 @@ pub struct StorageDeclaration {
#[derive(Debug, Clone)]
pub struct StorageField {
pub name: Ident,
pub attributes: AttributesMap,
pub type_info: TypeInfo,
pub type_info_span: Span,
pub initializer: Expression,
Expand Down
4 changes: 3 additions & 1 deletion sway-core/src/parse_tree/declaration/struct.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use crate::{
parse_tree::Visibility,
type_system::{TypeInfo, TypeParameter},
AttributesMap,
};

use sway_types::{ident::Ident, span::Span};

#[derive(Debug, Clone)]
pub struct StructDeclaration {
pub name: Ident,
pub attributes: AttributesMap,
pub fields: Vec<StructField>,
pub type_parameters: Vec<TypeParameter>,
pub visibility: Visibility,
Expand All @@ -17,6 +18,7 @@ pub struct StructDeclaration {
#[derive(Debug, Clone)]
pub struct StructField {
pub name: Ident,
pub attributes: AttributesMap,
pub type_info: TypeInfo,
pub(crate) span: Span,
pub type_span: Span,
Expand Down
6 changes: 4 additions & 2 deletions sway-core/src/parse_tree/declaration/trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use crate::{
function::Purity,
parse_tree::{CallPath, Visibility},
type_system::TypeInfo,
AttributesMap,
};

use sway_types::{ident::Ident, span::Span, Spanned};

#[derive(Debug, Clone)]
pub struct TraitDeclaration {
pub name: Ident,
pub attributes: AttributesMap,
pub interface_surface: Vec<TraitFn>,
pub methods: Vec<FunctionDeclaration>,
pub(crate) supertraits: Vec<Supertrait>,
Expand All @@ -28,9 +29,10 @@ impl Spanned for Supertrait {
}
}

#[derive(Debug, Clone, Eq, PartialEq)]
#[derive(Debug, Clone)]
pub struct TraitFn {
pub name: Ident,
pub attributes: AttributesMap,
pub purity: Purity,
pub parameters: Vec<FunctionParameter>,
pub return_type: TypeInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl TypedEnumDeclaration {
variants,
span,
visibility,
..
} = decl;

// create a namespace for the decl, used to create a scope for generics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl TypedStructDeclaration {
type_parameters,
visibility,
span,
..
} = decl;

// create a namespace for the decl, used to create a scope for generics
Expand Down
8 changes: 7 additions & 1 deletion sway-core/src/semantic_analysis/ast_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,13 +389,18 @@ impl TypedAstNode {
ctx.namespace.insert_symbol(name, decl.clone());
decl
}
Declaration::StorageDeclaration(StorageDeclaration { span, fields }) => {
Declaration::StorageDeclaration(StorageDeclaration {
span,
fields,
..
}) => {
let mut fields_buf = Vec::with_capacity(fields.len());
for StorageField {
name,
type_info,
initializer,
type_info_span,
..
} in fields
{
let type_id = check!(
Expand Down Expand Up @@ -503,6 +508,7 @@ fn type_check_interface_surface(
parameters,
return_type,
return_type_span,
..
}| TypedTraitFn {
name,
purity,
Expand Down
25 changes: 13 additions & 12 deletions sway-core/src/semantic_analysis/namespace/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,20 @@ impl Module {

// perform the conversions from parser code to parse tree types
let name = const_item.name.clone();
let attributes = std::collections::HashMap::new();
// convert to const decl
let const_decl =
match crate::convert_parse_tree::item_const_to_constant_declaration(ec, const_item)
{
Ok(o) => o,
Err(_emit_signal) => {
// if an error was emitted, grab errors from the error context
errors.append(&mut ec.errors.clone());
warnings.append(&mut ec.warnings.clone());

return err(warnings, errors);
}
};
let const_decl = match crate::convert_parse_tree::item_const_to_constant_declaration(
ec, const_item, attributes,
) {
Ok(o) => o,
Err(_emit_signal) => {
// if an error was emitted, grab errors from the error context
errors.append(&mut ec.errors.clone());
warnings.append(&mut ec.warnings.clone());

return err(warnings, errors);
}
};

// Temporarily disallow non-literals. See https://github.com/FuelLabs/sway/issues/2647.
if !matches!(const_decl.value.kind, ExpressionKind::Literal(_)) {
Expand Down
29 changes: 29 additions & 0 deletions sway-lsp/src/utils/attributes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#![allow(dead_code)]
use crate::core::token::{AstToken, Token};
use sway_core::{Attribute, AttributeKind, AttributesMap, Declaration};

pub(crate) fn attributes_map(token: &Token) -> Option<AttributesMap> {
match &token.parsed {
AstToken::Declaration(declaration) => match declaration {
Declaration::EnumDeclaration(decl) => Some(decl.attributes.clone()),
Declaration::FunctionDeclaration(decl) => Some(decl.attributes.clone()),
Declaration::StructDeclaration(decl) => Some(decl.attributes.clone()),
Declaration::ConstantDeclaration(decl) => Some(decl.attributes.clone()),
Declaration::StorageDeclaration(decl) => Some(decl.attributes.clone()),
_ => None,
},
AstToken::StorageField(field) => Some(field.attributes.clone()),
AstToken::StructField(field) => Some(field.attributes.clone()),
AstToken::TraitFn(trait_fn) => Some(trait_fn.attributes.clone()),
AstToken::EnumVariant(variant) => Some(variant.attributes.clone()),
_ => None,
}
}

pub(crate) fn doc_attributes(token: &Token) -> Option<Vec<Attribute>> {
attributes_map(token).and_then(|mut attributes| attributes.remove(&AttributeKind::Doc))
}

pub(crate) fn storage_attributes(token: &Token) -> Option<Vec<Attribute>> {
attributes_map(token).and_then(|mut attributes| attributes.remove(&AttributeKind::Storage))
}
1 change: 1 addition & 0 deletions sway-lsp/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub(crate) mod attributes;
pub(crate) mod common;
pub mod debug;
pub(crate) mod function;
Expand Down

0 comments on commit 4a0b313

Please sign in to comment.