Implement component name completion in html! for IntelliJ Rust plugin (#2972)

This commit is contained in:
Vlad Beskrovny 2023-02-02 16:36:51 +03:00 committed by GitHub
parent 7558cd2637
commit c7b7e45e4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 13 deletions

View File

@ -6,6 +6,7 @@ use syn::spanned::Spanned;
use syn::{Token, Type};
use super::{HtmlChildrenTree, TagTokens};
use crate::is_ide_completion;
use crate::props::ComponentProps;
pub struct HtmlComponent {
@ -25,13 +26,16 @@ impl Parse for HtmlComponent {
};
if trying_to_close() {
return match input.parse::<HtmlComponentClose>() {
Ok(close) => Err(syn::Error::new_spanned(
close.to_spanned(),
"this closing tag has no corresponding opening tag",
)),
Err(err) => Err(err),
};
let close = input.parse::<HtmlComponentClose>();
if !is_ide_completion() {
return match close {
Ok(close) => Err(syn::Error::new_spanned(
close.to_spanned(),
"this closing tag has no corresponding opening tag",
)),
Err(err) => Err(err),
};
}
}
let open = input.parse::<HtmlComponentOpen>()?;
@ -48,6 +52,9 @@ impl Parse for HtmlComponent {
let mut children = HtmlChildrenTree::new();
let close = loop {
if input.is_empty() {
if is_ide_completion() {
break None;
}
return Err(syn::Error::new_spanned(
open.to_spanned(),
"this opening tag has no corresponding closing tag",
@ -62,7 +69,7 @@ impl Parse for HtmlComponent {
}
let fork = input.fork();
break TagTokens::parse_end_content(&fork, |i_fork, tag| {
let close = TagTokens::parse_end_content(&fork, |i_fork, tag| {
let ty = i_fork.parse().map_err(|e| {
syn::Error::new(
e.span(),
@ -76,7 +83,7 @@ impl Parse for HtmlComponent {
)
})?;
if ty != open.ty {
if ty != open.ty && !is_ide_completion() {
let open_ty = &open.ty;
Err(syn::Error::new_spanned(
quote!(#open_ty #ty),
@ -92,6 +99,7 @@ impl Parse for HtmlComponent {
Ok(close)
}
})?;
break Some(close);
}
children.parse_child(input)?;
};
@ -109,7 +117,7 @@ impl Parse for HtmlComponent {
ty: open.ty,
props: open.props,
children,
close: Some(close),
close,
})
}
}

View File

@ -10,7 +10,7 @@ use syn::{Block, Expr, Ident, Lit, LitStr, Token};
use super::{HtmlChildrenTree, HtmlDashedName, TagTokens};
use crate::props::{ClassesForm, ElementProps, Prop, PropDirective};
use crate::stringify::{Stringify, Value};
use crate::{non_capitalized_ascii, Peek, PeekValue};
use crate::{is_ide_completion, non_capitalized_ascii, Peek, PeekValue};
pub struct HtmlElement {
pub name: TagName,
@ -72,6 +72,9 @@ impl Parse for HtmlElement {
let mut children = HtmlChildrenTree::new();
loop {
if input.is_empty() {
if is_ide_completion() {
break;
}
return Err(syn::Error::new_spanned(
open.to_spanned(),
"this opening tag has no corresponding closing tag",
@ -86,7 +89,9 @@ impl Parse for HtmlElement {
children.parse_child(input)?;
}
input.parse::<HtmlElementClose>()?;
if !input.is_empty() || !is_ide_completion() {
input.parse::<HtmlElementClose>()?;
}
Ok(Self {
name: open.name,

View File

@ -6,7 +6,7 @@ use syn::parse::{Parse, ParseStream};
use syn::spanned::Spanned;
use syn::{braced, token, Token};
use crate::PeekValue;
use crate::{is_ide_completion, PeekValue};
mod html_block;
mod html_component;
@ -101,6 +101,7 @@ impl HtmlTree {
Some(HtmlType::List)
} else if ident_str.chars().next().unwrap().is_ascii_uppercase()
|| input.peek(Token![::])
|| is_ide_completion() && ident_str.chars().any(|c| c.is_ascii_uppercase())
{
Some(HtmlType::Component)
} else {

View File

@ -98,6 +98,13 @@ fn join_errors(mut it: impl Iterator<Item = syn::Error>) -> syn::Result<()> {
})
}
fn is_ide_completion() -> bool {
match std::env::var_os("RUST_IDE_PROC_MACRO_COMPLETION_DUMMY_IDENTIFIER") {
None => false,
Some(dummy_identifier) => !dummy_identifier.is_empty(),
}
}
#[proc_macro_derive(Properties, attributes(prop_or, prop_or_else, prop_or_default))]
pub fn derive_props(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DerivePropsInput);