forked from FuelLabs/sway
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add code actions to generate doc comments (FuelLabs#4642)
## Description Closes FuelLabs#4571 Following the directory structure for code actions that was there before, I've added new modules for: - function decls - enum variants - storage fields - configurable constants Following FuelLabs/sway-standards#5, the doc comment template is the same for all of these except for functions. For functions, the template includes the argument names & types, return value, and a generated example of usage which is just meant to be a starting point for the comment author. For the basic template that most of these use, I created `BasicDocCommentCodeAction`. I also refactored some of the "generate impl" code actions that were there before into a trait called `GenerateImplCodeAction` to keep their common functionality separate from the "generate doc comment" code actions. I updated the existing code action tests for enums & structs, and added a new one for functions. I didn't think it was necessary to test enum variants, storage fields, etc. since the template and underlying code is the same. ### Example generating docs for a function  ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [x] 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: Joshua Batty <[email protected]>
- Loading branch information
1 parent
2d23078
commit 733d9b5
Showing
23 changed files
with
732 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
sway-lsp/src/capabilities/code_actions/common/generate_doc.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
use sway_core::{Engines, TypeId}; | ||
use sway_types::Spanned; | ||
use tower_lsp::lsp_types::{Range, Url}; | ||
|
||
use crate::capabilities::code_actions::{CodeAction, CodeActionContext, CODE_ACTION_DOC_TITLE}; | ||
|
||
pub(crate) trait GenerateDocCodeAction<'a, T: Spanned>: CodeAction<'a, T> { | ||
/// Returns a placeholder description as a vector of strings. | ||
fn description_section(&self) -> Vec<String> { | ||
vec!["Add a brief description.".to_string()] | ||
} | ||
|
||
/// Returns a placeholder information section as a vector of strings. | ||
fn info_section(&self) -> Vec<String> { | ||
vec![ | ||
String::new(), | ||
"### Additional Information".to_string(), | ||
String::new(), | ||
"Provide information beyond the core purpose or functionality.".to_string(), | ||
] | ||
} | ||
|
||
fn default_template(&self) -> String { | ||
let lines: Vec<String> = vec![self.description_section(), self.info_section()] | ||
.into_iter() | ||
.flatten() | ||
.collect(); | ||
self.format_lines(lines) | ||
} | ||
|
||
/// Formats a vector of lines into a doc comment [String]. | ||
fn format_lines(&self, lines: Vec<String>) -> String { | ||
lines | ||
.iter() | ||
.map(|line| format!("{}/// {}\n", self.indentation(), line)) | ||
.collect() | ||
} | ||
|
||
/// Formats a list item with a name and type into a [String]. | ||
fn formatted_list_item( | ||
&self, | ||
engines: &'a Engines, | ||
name: Option<String>, | ||
type_id: TypeId, | ||
) -> String { | ||
let name_string = match name { | ||
Some(name) => format!("`{}`: ", name), | ||
None => String::new(), | ||
}; | ||
let type_string = match engines.te().get(type_id).is_unit() { | ||
true => "()".to_string(), | ||
false => format!("[{}]", engines.help_out(type_id)), | ||
}; | ||
format!("* {name_string}{type_string} - Add description here",) | ||
} | ||
} | ||
|
||
pub struct BasicDocCommentCodeAction<'a, T: Spanned> { | ||
decl: &'a T, | ||
uri: &'a Url, | ||
} | ||
|
||
impl<'a, T: Spanned> GenerateDocCodeAction<'a, T> for BasicDocCommentCodeAction<'a, T> {} | ||
|
||
impl<'a, T: Spanned> CodeAction<'a, T> for BasicDocCommentCodeAction<'a, T> { | ||
fn new(ctx: CodeActionContext<'a>, decl: &'a T) -> Self { | ||
Self { decl, uri: ctx.uri } | ||
} | ||
|
||
fn new_text(&self) -> String { | ||
self.default_template() | ||
} | ||
|
||
fn range(&self) -> Range { | ||
self.range_before() | ||
} | ||
|
||
fn title(&self) -> String { | ||
CODE_ACTION_DOC_TITLE.to_string() | ||
} | ||
|
||
fn decl(&self) -> &T { | ||
self.decl | ||
} | ||
|
||
fn uri(&self) -> &Url { | ||
self.uri | ||
} | ||
} |
103 changes: 103 additions & 0 deletions
103
sway-lsp/src/capabilities/code_actions/common/generate_impl.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
use sway_core::{ | ||
transform::{AttributeKind, AttributesMap}, | ||
TypeParameter, | ||
}; | ||
use sway_types::Spanned; | ||
|
||
use crate::capabilities::code_actions::CodeAction; | ||
|
||
pub(crate) const CONTRACT: &str = "Contract"; | ||
pub(crate) const TAB: &str = " "; | ||
|
||
pub(crate) trait GenerateImplCodeAction<'a, T: Spanned>: CodeAction<'a, T> { | ||
/// Returns a [String] holding the name of the declaration. | ||
fn decl_name(&self) -> String; | ||
|
||
/// Returns an optional [String] of the type parameters for the given [TypeParameter] vector. | ||
fn type_param_string(&self, type_params: &Vec<TypeParameter>) -> Option<String> { | ||
if type_params.is_empty() { | ||
None | ||
} else { | ||
Some( | ||
type_params | ||
.iter() | ||
.map(|param| param.name_ident.to_string()) | ||
.collect::<Vec<_>>() | ||
.join(", "), | ||
) | ||
} | ||
} | ||
|
||
/// Returns a [String] of a generated impl with the optional `for <for_name>` signature. | ||
/// Can be used for both ABI and Struct impls. | ||
fn impl_string( | ||
&self, | ||
type_params: Option<String>, | ||
body: String, | ||
for_name: Option<String>, | ||
) -> String { | ||
let for_string = match for_name { | ||
Some(name) => format!(" for {name}"), | ||
None => "".to_string(), | ||
}; | ||
let type_param_string = match type_params { | ||
Some(params) => format!("<{params}>"), | ||
None => "".to_string(), | ||
}; | ||
format!( | ||
"\nimpl{} {}{}{} {{{}}}\n", | ||
type_param_string, | ||
self.decl_name(), | ||
type_param_string, | ||
for_string, | ||
body | ||
) | ||
} | ||
|
||
/// Returns a [String] of a an attribute map, optionally excluding comments. | ||
fn attribute_string(&self, attr_map: &AttributesMap, include_comments: bool) -> String { | ||
let attr_string = attr_map | ||
.iter() | ||
.map(|(kind, attrs)| { | ||
attrs | ||
.iter() | ||
.filter_map(|attr| match kind { | ||
AttributeKind::DocComment { .. } => { | ||
if include_comments { | ||
return Some(format!("{}{}", TAB, attr.span.as_str())); | ||
} | ||
None | ||
} | ||
_ => Some(format!("{}{}", TAB, attr.span.as_str())), | ||
}) | ||
.collect::<Vec<String>>() | ||
.join("\n") | ||
}) | ||
.collect::<Vec<String>>() | ||
.join("\n"); | ||
let attribute_padding = match attr_string.len() > 1 { | ||
true => "\n", | ||
false => "", | ||
}; | ||
format!("{attr_string}{attribute_padding}") | ||
} | ||
|
||
/// Returns a [String] of a generated function signature. | ||
fn fn_signature_string( | ||
&self, | ||
fn_name: String, | ||
params_string: String, | ||
attr_map: &AttributesMap, | ||
return_type_string: String, | ||
body: Option<String>, | ||
) -> String { | ||
let attribute_string = self.attribute_string(attr_map, false); | ||
let body_string = match body { | ||
Some(body) => format!(" {body} "), | ||
None => String::new(), | ||
}; | ||
format!( | ||
"{attribute_string}{TAB}fn {fn_name}({params_string}){return_type_string} {{{body_string}}}", | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod generate_doc; | ||
pub mod generate_impl; |
12 changes: 12 additions & 0 deletions
12
sway-lsp/src/capabilities/code_actions/constant_decl/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use crate::capabilities::code_actions::{CodeAction, CodeActionContext}; | ||
use sway_core::language::ty; | ||
use tower_lsp::lsp_types::CodeActionOrCommand; | ||
|
||
use super::common::generate_doc::BasicDocCommentCodeAction; | ||
|
||
pub(crate) fn code_actions( | ||
decl: &ty::TyConstantDecl, | ||
ctx: CodeActionContext, | ||
) -> Option<Vec<CodeActionOrCommand>> { | ||
Some(vec![BasicDocCommentCodeAction::new(ctx, decl).code_action()]) | ||
} |
39 changes: 39 additions & 0 deletions
39
sway-lsp/src/capabilities/code_actions/enum_decl/doc_comment.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
use crate::capabilities::code_actions::{ | ||
common::generate_doc::GenerateDocCodeAction, CodeAction, CodeActionContext, | ||
CODE_ACTION_DOC_TITLE, | ||
}; | ||
use sway_core::language::ty::TyEnumDecl; | ||
use tower_lsp::lsp_types::{Range, Url}; | ||
|
||
pub(crate) struct DocCommentCodeAction<'a> { | ||
decl: &'a TyEnumDecl, | ||
uri: &'a Url, | ||
} | ||
|
||
impl<'a> GenerateDocCodeAction<'a, TyEnumDecl> for DocCommentCodeAction<'a> {} | ||
|
||
impl<'a> CodeAction<'a, TyEnumDecl> for DocCommentCodeAction<'a> { | ||
fn new(ctx: CodeActionContext<'a>, decl: &'a TyEnumDecl) -> Self { | ||
Self { decl, uri: ctx.uri } | ||
} | ||
|
||
fn new_text(&self) -> String { | ||
self.default_template() | ||
} | ||
|
||
fn range(&self) -> Range { | ||
self.range_before() | ||
} | ||
|
||
fn title(&self) -> String { | ||
CODE_ACTION_DOC_TITLE.to_string() | ||
} | ||
|
||
fn decl(&self) -> &TyEnumDecl { | ||
self.decl | ||
} | ||
|
||
fn uri(&self) -> &Url { | ||
self.uri | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
sway-lsp/src/capabilities/code_actions/enum_decl/enum_impl.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use crate::capabilities::code_actions::{ | ||
common::generate_impl::{GenerateImplCodeAction, TAB}, | ||
CodeAction, CodeActionContext, CODE_ACTION_IMPL_TITLE, | ||
}; | ||
use sway_core::language::ty::TyEnumDecl; | ||
use tower_lsp::lsp_types::{Range, Url}; | ||
|
||
pub(crate) struct EnumImplCodeAction<'a> { | ||
decl: &'a TyEnumDecl, | ||
uri: &'a Url, | ||
} | ||
|
||
impl<'a> GenerateImplCodeAction<'a, TyEnumDecl> for EnumImplCodeAction<'a> { | ||
fn decl_name(&self) -> String { | ||
self.decl.call_path.suffix.to_string() | ||
} | ||
} | ||
|
||
impl<'a> CodeAction<'a, TyEnumDecl> for EnumImplCodeAction<'a> { | ||
fn new(ctx: CodeActionContext<'a>, decl: &'a TyEnumDecl) -> Self { | ||
Self { decl, uri: ctx.uri } | ||
} | ||
|
||
fn new_text(&self) -> String { | ||
self.impl_string( | ||
self.type_param_string(&self.decl.type_parameters), | ||
format!("\n{TAB}\n"), | ||
None, | ||
) | ||
} | ||
|
||
fn title(&self) -> String { | ||
format!("{} `{}`", CODE_ACTION_IMPL_TITLE, self.decl_name()) | ||
} | ||
|
||
fn range(&self) -> Range { | ||
self.range_after() | ||
} | ||
|
||
fn decl(&self) -> &TyEnumDecl { | ||
self.decl | ||
} | ||
|
||
fn uri(&self) -> &Url { | ||
self.uri | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
pub(crate) mod doc_comment; | ||
pub(crate) mod enum_impl; | ||
|
||
use self::enum_impl::EnumImplCodeAction; | ||
use crate::capabilities::code_actions::{CodeAction, CodeActionContext}; | ||
use sway_core::{decl_engine::id::DeclId, language::ty}; | ||
use tower_lsp::lsp_types::CodeActionOrCommand; | ||
|
||
use super::common::generate_doc::BasicDocCommentCodeAction; | ||
|
||
pub(crate) fn code_actions( | ||
decl_id: &DeclId<ty::TyEnumDecl>, | ||
ctx: CodeActionContext, | ||
) -> Option<Vec<CodeActionOrCommand>> { | ||
let decl = ctx.engines.de().get_enum(decl_id); | ||
Some(vec![ | ||
EnumImplCodeAction::new(ctx.clone(), &decl).code_action(), | ||
BasicDocCommentCodeAction::new(ctx, &decl).code_action(), | ||
]) | ||
} |
Oops, something went wrong.