Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autocomplete rsx #2421

Merged
merged 11 commits into from
May 22, 2024
5 changes: 1 addition & 4 deletions examples/rsx_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,7 @@ fn WithInline(text: String) -> Element {
}

#[component]
fn Label<T: Clone + PartialEq + 'static>(text: T) -> Element
where
T: Display,
{
fn Label<T: Clone + PartialEq + Display + 'static>(text: T) -> Element {
rsx! {
p { "{text}" }
}
Expand Down
6 changes: 5 additions & 1 deletion packages/autofmt/src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ impl Writer<'_> {
..
} = el;

let brace = brace
.as_ref()
.expect("braces should always be present in strict mode");

/*
1. Write the tag
2. Write the key
Expand Down Expand Up @@ -426,7 +430,7 @@ impl Writer<'_> {
}
}

fn get_expr_length(expr: &Expr) -> Option<usize> {
fn get_expr_length(expr: &impl Spanned) -> Option<usize> {
let span = expr.span();
let (start, end) = (span.start(), span.end());
if start.line == end.line {
Expand Down
8 changes: 4 additions & 4 deletions packages/autofmt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use collect_macros::byte_offset;
use dioxus_rsx::{BodyNode, CallBody, IfmtInput};
use proc_macro2::LineColumn;
use quote::ToTokens;
use syn::{ExprMacro, MacroDelimiter};
use syn::{parse::Parser, ExprMacro, MacroDelimiter};

mod buffer;
mod collect_macros;
Expand Down Expand Up @@ -77,7 +77,7 @@ pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
continue;
}

let body = item.parse_body::<CallBody>().unwrap();
let body = item.parse_body_with(CallBody::parse_strict).unwrap();

let rsx_start = macro_path.span().start();

Expand Down Expand Up @@ -153,7 +153,7 @@ fn write_body(buf: &mut Writer, body: &CallBody) {
}

pub fn fmt_block_from_expr(raw: &str, expr: ExprMacro) -> Option<String> {
let body = syn::parse2::<CallBody>(expr.mac.tokens).unwrap();
let body = CallBody::parse_strict.parse2(expr.mac.tokens).unwrap();

let mut buf = Writer::new(raw);

Expand All @@ -163,7 +163,7 @@ pub fn fmt_block_from_expr(raw: &str, expr: ExprMacro) -> Option<String> {
}

pub fn fmt_block(block: &str, indent_level: usize, indent: IndentOptions) -> Option<String> {
let body = syn::parse_str::<dioxus_rsx::CallBody>(block).unwrap();
let body = CallBody::parse_strict.parse_str(block).unwrap();

let mut buf = Writer::new(block);

Expand Down
29 changes: 29 additions & 0 deletions packages/core-macro/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,15 @@ impl ToTokens for ComponentBody {
}
};

let completion_hints = self.completion_hints();

tokens.append_all(quote! {
#props_struct

#[allow(non_snake_case)]
#comp_fn

#completion_hints
});
}
}
Expand Down Expand Up @@ -221,6 +225,31 @@ impl ComponentBody {

false
}

// We generate an extra enum to help us autocomplete the braces after the component.
// This is a bit of a hack, but it's the only way to get the braces to autocomplete.
fn completion_hints(&self) -> TokenStream {
let comp_fn = &self.item_fn.sig.ident;
let completions_mod = Ident::new(&format!("{}_completions", comp_fn), comp_fn.span());

let vis = &self.item_fn.vis;

quote! {
#[allow(non_snake_case)]
#[doc(hidden)]
mod #completions_mod {
#[doc(hidden)]
#[allow(non_camel_case_types)]
/// This enum is generated to help autocomplete the braces after the component. It does nothing
pub enum Component {
#comp_fn {}
}
}

#[allow(unused)]
#vis use #completions_mod::Component::#comp_fn;
}
}
}

struct DocField<'a> {
Expand Down
2 changes: 1 addition & 1 deletion packages/dioxus-lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub mod prelude {
pub use dioxus_html as dioxus_elements;

#[cfg(feature = "html")]
pub use dioxus_elements::{prelude::*, GlobalAttributes, SvgAttributes};
pub use dioxus_elements::{global_attributes, prelude::*, svg_attributes};

pub use dioxus_core;
}
2 changes: 1 addition & 1 deletion packages/dioxus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub mod prelude {

#[cfg(feature = "html")]
#[cfg_attr(docsrs, doc(cfg(feature = "html")))]
pub use dioxus_elements::{prelude::*, GlobalAttributes, SvgAttributes};
pub use dioxus_elements::{global_attributes, prelude::*, svg_attributes};

#[cfg(all(
not(any(target_arch = "wasm32", target_os = "ios", target_os = "android")),
Expand Down
22 changes: 2 additions & 20 deletions packages/html-internal-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub fn impl_extension_attributes(input: TokenStream) -> TokenStream {
}

struct ImplExtensionAttributes {
is_element: bool,
name: Ident,
attrs: Punctuated<Ident, Token![,]>,
}
Expand All @@ -23,16 +22,11 @@ impl Parse for ImplExtensionAttributes {
fn parse(input: ParseStream) -> syn::Result<Self> {
let content;

let element: Ident = input.parse()?;
let name = input.parse()?;
braced!(content in input);
let attrs = content.parse_terminated(Ident::parse, Token![,])?;

Ok(ImplExtensionAttributes {
is_element: element == "ELEMENT",
name,
attrs,
})
Ok(ImplExtensionAttributes { name, attrs })
}
}

Expand All @@ -44,22 +38,10 @@ impl ToTokens for ImplExtensionAttributes {
.strip_prefix("r#")
.unwrap_or(&name_string)
.to_case(Case::UpperCamel);
let impl_name = Ident::new(format!("{}Impl", &camel_name).as_str(), name.span());
let extension_name = Ident::new(format!("{}Extension", &camel_name).as_str(), name.span());

if !self.is_element {
tokens.append_all(quote! {
struct #impl_name;
impl #name for #impl_name {}
});
}

let impls = self.attrs.iter().map(|ident| {
let d = if self.is_element {
quote! { #name::#ident }
} else {
quote! { <#impl_name as #name>::#ident }
};
let d = quote! { #name::#ident };
quote! {
fn #ident(self, value: impl IntoAttributeValue) -> Self {
let d = #d;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use dioxus_html_internal_macro::impl_extension_attributes;
use crate::AttributeDiscription;

#[cfg(feature = "hot-reload-context")]
macro_rules! trait_method_mapping {
macro_rules! mod_method_mapping {
(
$matching:ident;
$(#[$attr:meta])*
Expand Down Expand Up @@ -68,30 +68,31 @@ macro_rules! html_to_rsx_attribute_mapping {
};
}

macro_rules! trait_methods {
macro_rules! mod_methods {
(
@base
$(#[$trait_attr:meta])*
$trait:ident;
$(#[$mod_attr:meta])*
$mod:ident;
$fn:ident;
$fn_html_to_rsx:ident;
$(
$(#[$attr:meta])*
$name:ident $(: $($arg:literal),*)*;
)+
) => {
$(#[$trait_attr])*
pub trait $trait {
$(#[$mod_attr])*
pub mod $mod {
use super::*;
$(
$(#[$attr])*
const $name: AttributeDiscription = trait_methods! { $name $(: $($arg),*)*; };
pub const $name: AttributeDiscription = mod_methods! { $name $(: $($arg),*)*; };
)*
}

#[cfg(feature = "hot-reload-context")]
pub(crate) fn $fn(attr: &str) -> Option<(&'static str, Option<&'static str>)> {
$(
trait_method_mapping! {
mod_method_mapping! {
attr;
$name$(: $($arg),*)*;
}
Expand All @@ -111,7 +112,7 @@ macro_rules! trait_methods {
None
}

impl_extension_attributes![GLOBAL $trait { $($name,)* }];
impl_extension_attributes![$mod { $($name,)* }];
};

// Rename the incoming ident and apply a custom namespace
Expand All @@ -124,10 +125,10 @@ macro_rules! trait_methods {
( $name:ident; ) => { (stringify!($name), None, false) };
}

trait_methods! {
mod_methods! {
@base

GlobalAttributes;
global_attributes;
map_global_attributes;
map_html_global_attributes_to_rsx;

Expand Down Expand Up @@ -1640,9 +1641,9 @@ trait_methods! {
aria_setsize: "aria-setsize";
}

trait_methods! {
mod_methods! {
@base
SvgAttributes;
svg_attributes;
map_svg_attributes;
map_html_svg_attributes_to_rsx;

Expand Down
41 changes: 26 additions & 15 deletions packages/html/src/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use dioxus_rsx::HotReloadingContext;

#[cfg(feature = "hot-reload-context")]
use crate::{map_global_attributes, map_svg_attributes};
use crate::{GlobalAttributes, SvgAttributes};

pub type AttributeDiscription = (&'static str, Option<&'static str>, bool);

Expand Down Expand Up @@ -115,9 +114,11 @@ macro_rules! impl_element {
) => {
#[allow(non_camel_case_types)]
$(#[$attr])*
pub struct $name;
pub mod $name {
#[allow(unused)]
use super::*;
pub use crate::attribute_groups::global_attributes::*;

impl $name {
pub const TAG_NAME: &'static str = stringify!($name);
pub const NAME_SPACE: Option<&'static str> = None;

Expand All @@ -128,8 +129,6 @@ macro_rules! impl_element {
);
)*
}

impl GlobalAttributes for $name {}
};

(
Expand All @@ -141,13 +140,12 @@ macro_rules! impl_element {
)*
}
) => {
#[allow(non_camel_case_types)]
$(#[$attr])*
pub struct $name;

impl SvgAttributes for $name {}
pub mod $name {
#[allow(unused)]
use super::*;
pub use crate::attribute_groups::svg_attributes::*;

impl $name {
pub const TAG_NAME: &'static str = stringify!($name);
pub const NAME_SPACE: Option<&'static str> = Some($namespace);

Expand All @@ -171,11 +169,11 @@ macro_rules! impl_element {
) => {
#[allow(non_camel_case_types)]
$(#[$attr])*
pub struct $element;

impl SvgAttributes for $element {}
pub mod $element {
#[allow(unused)]
use super::*;
pub use crate::attribute_groups::svg_attributes::*;

impl $element {
pub const TAG_NAME: &'static str = $name;
pub const NAME_SPACE: Option<&'static str> = Some($namespace);

Expand Down Expand Up @@ -384,10 +382,23 @@ macro_rules! builder_constructors {
);
)*

/// This module contains helpers for rust analyzer autocompletion
#[doc(hidden)]
pub mod completions {
/// This helper tells rust analyzer that it should autocomplete the element name with braces.
#[allow(non_camel_case_types)]
pub enum CompleteWithBraces {
$(
$(#[$attr])*
$name {}
),*
}
}

pub(crate) mod extensions {
use super::*;
$(
impl_extension_attributes![ELEMENT $name { $($fil,)* }];
impl_extension_attributes![$name { $($fil,)* }];
)*
}
};
Expand Down
Loading
Loading