From 0c8961271ff74c8f20cc62d2071aac91b1f29ab1 Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Tue, 12 Nov 2024 13:13:44 +0100 Subject: [PATCH] refactor(js_syntax): minor clean up (#4513) --- .../src/lint/a11y/no_access_key.rs | 2 +- .../src/lint/a11y/no_autofocus.rs | 4 +- .../src/lint/a11y/no_blank_target.rs | 2 +- .../src/lint/a11y/no_distracting_elements.rs | 2 +- .../src/lint/a11y/no_header_scope.rs | 2 +- .../src/lint/a11y/no_label_without_control.rs | 4 +- .../src/lint/a11y/no_redundant_alt.rs | 2 +- .../src/lint/a11y/no_svg_without_title.rs | 4 +- .../src/lint/a11y/use_alt_text.rs | 2 +- .../src/lint/a11y/use_anchor_content.rs | 2 +- .../src/lint/a11y/use_button_type.rs | 4 +- .../src/lint/a11y/use_heading_content.rs | 2 +- .../src/lint/a11y/use_html_lang.rs | 2 +- .../src/lint/a11y/use_iframe_title.rs | 2 +- .../lint/a11y/use_key_with_click_events.rs | 5 +- .../src/lint/a11y/use_media_caption.rs | 8 +- .../src/lint/a11y/use_semantic_elements.rs | 2 +- .../src/lint/a11y/use_valid_anchor.rs | 2 +- .../no_void_elements_with_children.rs | 13 +- .../src/lint/nursery/no_head_element.rs | 2 +- .../src/lint/nursery/no_img_element.rs | 4 +- .../lint/nursery/use_google_font_display.rs | 2 +- .../nursery/use_google_font_preconnect.rs | 4 +- .../lint/nursery/use_valid_autocomplete.rs | 8 +- ...angerously_set_inner_html_with_children.rs | 4 - crates/biome_js_analyze/src/services/aria.rs | 2 +- crates/biome_js_syntax/src/jsx_ext.rs | 123 ++++++++---------- crates/biome_service/src/file_handlers/mod.rs | 2 +- 28 files changed, 101 insertions(+), 116 deletions(-) diff --git a/crates/biome_js_analyze/src/lint/a11y/no_access_key.rs b/crates/biome_js_analyze/src/lint/a11y/no_access_key.rs index dbc739c28b37..8aaf6e6690c0 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_access_key.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_access_key.rs @@ -53,7 +53,7 @@ impl Rule for NoAccessKey { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - if node.name_value_token()?.text_trimmed() != "accessKey" { + if node.name_value_token().ok()?.text_trimmed() != "accessKey" { return None; } diff --git a/crates/biome_js_analyze/src/lint/a11y/no_autofocus.rs b/crates/biome_js_analyze/src/lint/a11y/no_autofocus.rs index 6867213b97cc..4f35b238af8b 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_autofocus.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_autofocus.rs @@ -86,11 +86,11 @@ fn find_kept_autofocus_mark(element: &AnyJsxElement) -> bool { // 2. inside the element with the popover attribute let is_dialog_element = match element.name_value_token() { - Some(syntax_token) => { + Ok(syntax_token) => { let tag_name = String::from(syntax_token.text_trimmed()); tag_name.to_lowercase_cow() == "dialog" } - None => false, + Err(_) => false, }; let has_popover_attr = element.has_truthy_attribute("popover"); diff --git a/crates/biome_js_analyze/src/lint/a11y/no_blank_target.rs b/crates/biome_js_analyze/src/lint/a11y/no_blank_target.rs index 56eaf57ed2d9..1b45e3fa5f79 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_blank_target.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_blank_target.rs @@ -93,7 +93,7 @@ impl Rule for NoBlankTarget { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - if node.name_value_token()?.text_trimmed() != "a" + if node.name_value_token().ok()?.text_trimmed() != "a" || node.find_attribute_by_name("href").is_none() { return None; diff --git a/crates/biome_js_analyze/src/lint/a11y/no_distracting_elements.rs b/crates/biome_js_analyze/src/lint/a11y/no_distracting_elements.rs index 9fcddffc1840..6da1ef45f240 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_distracting_elements.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_distracting_elements.rs @@ -54,7 +54,7 @@ impl Rule for NoDistractingElements { fn run(ctx: &RuleContext) -> Self::Signals { let element = ctx.query(); - let name = element.name_value_token()?; + let name = element.name_value_token().ok()?; match name.text_trimmed() { "marquee" | "blink" => Some(name), _ => None, diff --git a/crates/biome_js_analyze/src/lint/a11y/no_header_scope.rs b/crates/biome_js_analyze/src/lint/a11y/no_header_scope.rs index 731c56fa526b..e8c3989df3ae 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_header_scope.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_header_scope.rs @@ -56,7 +56,7 @@ impl Rule for NoHeaderScope { let element = ctx.query(); if element.is_element() - && element.name_value_token()?.text_trimmed() != "th" + && element.name_value_token().ok()?.text_trimmed() != "th" && element.has_truthy_attribute("scope") { return Some(()); diff --git a/crates/biome_js_analyze/src/lint/a11y/no_label_without_control.rs b/crates/biome_js_analyze/src/lint/a11y/no_label_without_control.rs index 76470398ec3d..497f126a81d0 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_label_without_control.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_label_without_control.rs @@ -102,7 +102,7 @@ impl Rule for NoLabelWithoutControl { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); let options = ctx.options(); - let element_name = node.name()?.name_value_token()?; + let element_name = node.name()?.name_value_token().ok()?; let element_name = element_name.text_trimmed(); let is_allowed_element = options.has_element_name(element_name) || DEFAULT_LABEL_COMPONENTS.contains(&element_name); @@ -237,7 +237,7 @@ impl NoLabelWithoutControlOptions { child_iter.skip_subtree(); continue; }; - let Some(element_name) = element_name.name_value_token() else { + let Ok(element_name) = element_name.name_value_token() else { continue; }; let element_name = element_name.text_trimmed(); diff --git a/crates/biome_js_analyze/src/lint/a11y/no_redundant_alt.rs b/crates/biome_js_analyze/src/lint/a11y/no_redundant_alt.rs index e378cd21d513..6e45b02e9724 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_redundant_alt.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_redundant_alt.rs @@ -57,7 +57,7 @@ impl Rule for NoRedundantAlt { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - if node.name_value_token()?.text_trimmed() != "img" { + if node.name_value_token().ok()?.text_trimmed() != "img" { return None; } let aria_hidden_attribute = node.find_attribute_by_name("aria-hidden"); diff --git a/crates/biome_js_analyze/src/lint/a11y/no_svg_without_title.rs b/crates/biome_js_analyze/src/lint/a11y/no_svg_without_title.rs index 55d4486b55a7..f6bf6818b619 100644 --- a/crates/biome_js_analyze/src/lint/a11y/no_svg_without_title.rs +++ b/crates/biome_js_analyze/src/lint/a11y/no_svg_without_title.rs @@ -114,7 +114,7 @@ impl Rule for NoSvgWithoutTitle { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - if node.name_value_token()?.text_trimmed() != "svg" { + if node.name_value_token().ok()?.text_trimmed() != "svg" { return None; } @@ -196,7 +196,7 @@ fn is_valid_attribute_value( .filter_map(|child| { let jsx_element = child.as_jsx_element()?; let opening_element = jsx_element.opening_element().ok()?; - let maybe_attribute = opening_element.find_attribute_by_name("id").ok()?; + let maybe_attribute = opening_element.find_attribute_by_name("id"); let child_attribute_value = maybe_attribute?.initializer()?.value().ok()?; let is_valid = attribute_value.as_static_value()?.text() == child_attribute_value.as_static_value()?.text(); diff --git a/crates/biome_js_analyze/src/lint/a11y/use_alt_text.rs b/crates/biome_js_analyze/src/lint/a11y/use_alt_text.rs index 89e293c53ff3..6cbd3c6e98c8 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_alt_text.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_alt_text.rs @@ -87,7 +87,7 @@ impl Rule for UseAltText { let has_aria_label = has_valid_label(element, "aria-label"); let has_aria_labelledby = has_valid_label(element, "aria-labelledby"); let aria_hidden = is_aria_hidden(element); - match element.name_value_token()?.text_trimmed() { + match element.name_value_token().ok()?.text_trimmed() { "object" => { let has_title = has_valid_label(element, "title"); diff --git a/crates/biome_js_analyze/src/lint/a11y/use_anchor_content.rs b/crates/biome_js_analyze/src/lint/a11y/use_anchor_content.rs index 3679e3e75dfd..7763b08eb85b 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_anchor_content.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_anchor_content.rs @@ -81,7 +81,7 @@ impl Rule for UseAnchorContent { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - let name = node.name().ok()?.name_value_token()?; + let name = node.name().ok()?.name_value_token().ok()?; if name.text_trimmed() == "a" { if node.has_truthy_attribute("aria-hidden") { diff --git a/crates/biome_js_analyze/src/lint/a11y/use_button_type.rs b/crates/biome_js_analyze/src/lint/a11y/use_button_type.rs index 8ed0e5b415b2..228b78ce8697 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_button_type.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_button_type.rs @@ -70,7 +70,7 @@ impl Rule for UseButtonType { if !is_button(&name)? { return None; } - let type_attribute = element.find_attribute_by_name("type").ok()?; + let type_attribute = element.find_attribute_by_name("type"); let Some(attribute) = type_attribute else { let has_spread_prop = element .attributes() @@ -92,7 +92,7 @@ impl Rule for UseButtonType { if !is_button(&name)? { return None; } - let type_attribute = element.find_attribute_by_name("type").ok()?; + let type_attribute = element.find_attribute_by_name("type"); let Some(attribute) = type_attribute else { let has_spread_prop = element .attributes() diff --git a/crates/biome_js_analyze/src/lint/a11y/use_heading_content.rs b/crates/biome_js_analyze/src/lint/a11y/use_heading_content.rs index b7b87ac17b24..1320fc28fdff 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_heading_content.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_heading_content.rs @@ -74,7 +74,7 @@ impl Rule for UseHeadingContent { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - let name = node.name().ok()?.name_value_token()?; + let name = node.name().ok()?.name_value_token().ok()?; if HEADING_ELEMENTS.contains(&name.text_trimmed()) { if node.has_truthy_attribute("aria-hidden") { diff --git a/crates/biome_js_analyze/src/lint/a11y/use_html_lang.rs b/crates/biome_js_analyze/src/lint/a11y/use_html_lang.rs index 7ca8f1403398..42a5c76d84fc 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_html_lang.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_html_lang.rs @@ -71,7 +71,7 @@ impl Rule for UseHtmlLang { fn run(ctx: &RuleContext) -> Self::Signals { let element = ctx.query(); - let name = element.name().ok()?.name_value_token()?; + let name = element.name().ok()?.name_value_token().ok()?; if name.text_trimmed() == "html" { if let Some(lang_attribute) = element.find_attribute_by_name("lang") { diff --git a/crates/biome_js_analyze/src/lint/a11y/use_iframe_title.rs b/crates/biome_js_analyze/src/lint/a11y/use_iframe_title.rs index ae92a070923e..80637dfa9c5f 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_iframe_title.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_iframe_title.rs @@ -77,7 +77,7 @@ impl Rule for UseIframeTitle { fn run(ctx: &RuleContext) -> Self::Signals { let element = ctx.query(); - let name = element.name().ok()?.name_value_token()?; + let name = element.name().ok()?.name_value_token().ok()?; if name.text_trimmed() == "iframe" { if let Some(lang_attribute) = element.find_attribute_by_name("title") { diff --git a/crates/biome_js_analyze/src/lint/a11y/use_key_with_click_events.rs b/crates/biome_js_analyze/src/lint/a11y/use_key_with_click_events.rs index 53da1f1412a2..bf16bed34034 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_key_with_click_events.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_key_with_click_events.rs @@ -95,10 +95,9 @@ impl Rule for UseKeyWithClickEvents { } let attributes = element.attributes(); - let on_click_attribute = attributes.find_by_name("onClick").ok()?; - #[allow(clippy::question_mark)] - if on_click_attribute.is_none() { + #[expect(clippy::question_mark)] + if attributes.find_by_name("onClick").is_none() { return None; } diff --git a/crates/biome_js_analyze/src/lint/a11y/use_media_caption.rs b/crates/biome_js_analyze/src/lint/a11y/use_media_caption.rs index f70c39444cbd..463352a2b404 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_media_caption.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_media_caption.rs @@ -49,8 +49,10 @@ impl Rule for UseMediaCaption { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - let has_audio_or_video = - matches!(node.name_value_token()?.text_trimmed(), "video" | "audio"); + let has_audio_or_video = matches!( + node.name_value_token().ok()?.text_trimmed(), + "video" | "audio" + ); let has_muted = node.find_attribute_by_name("muted").is_some(); let has_spread_prop = node .attributes() @@ -78,7 +80,7 @@ impl Rule for UseMediaCaption { _ => None, }?; - let has_track = any_jsx.name_value_token()?.text_trimmed() == "track"; + let has_track = any_jsx.name_value_token().ok()?.text_trimmed() == "track"; let has_valid_kind = &any_jsx .find_attribute_by_name("kind")? .initializer()? diff --git a/crates/biome_js_analyze/src/lint/a11y/use_semantic_elements.rs b/crates/biome_js_analyze/src/lint/a11y/use_semantic_elements.rs index 8f0304642062..07c323089c74 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_semantic_elements.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_semantic_elements.rs @@ -59,7 +59,7 @@ impl Rule for UseSemanticElements { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - let role_attribute = node.find_attribute_by_name("role").ok().flatten()?; + let role_attribute = node.find_attribute_by_name("role")?; let role_value = role_attribute.as_static_value()?; let role_value = role_value.as_string_constant()?; diff --git a/crates/biome_js_analyze/src/lint/a11y/use_valid_anchor.rs b/crates/biome_js_analyze/src/lint/a11y/use_valid_anchor.rs index d615ef49f9df..1b5a1af4bd3d 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_valid_anchor.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_valid_anchor.rs @@ -147,7 +147,7 @@ impl Rule for UseValidAnchor { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - let name = node.name().ok()?.name_value_token()?; + let name = node.name().ok()?.name_value_token().ok()?; if name.text_trimmed() == "a" { let anchor_attribute = node.find_attribute_by_name("href"); diff --git a/crates/biome_js_analyze/src/lint/correctness/no_void_elements_with_children.rs b/crates/biome_js_analyze/src/lint/correctness/no_void_elements_with_children.rs index f2af5d4ce506..e85651dfa7f4 100644 --- a/crates/biome_js_analyze/src/lint/correctness/no_void_elements_with_children.rs +++ b/crates/biome_js_analyze/src/lint/correctness/no_void_elements_with_children.rs @@ -208,11 +208,10 @@ impl Rule for NoVoidElementsWithChildren { let name = name.as_jsx_name()?.value_token().ok()?; let name = name.text_trimmed(); if is_void_dom_element(name) { - let dangerous_prop = opening_element - .find_attribute_by_name("dangerouslySetInnerHTML") - .ok()?; + let dangerous_prop = + opening_element.find_attribute_by_name("dangerouslySetInnerHTML"); let has_children = !element.children().is_empty(); - let children_prop = opening_element.find_attribute_by_name("children").ok()?; + let children_prop = opening_element.find_attribute_by_name("children"); if dangerous_prop.is_some() || has_children || children_prop.is_some() { let cause = NoVoidElementsWithChildrenCause::Jsx { children_prop, @@ -229,10 +228,8 @@ impl Rule for NoVoidElementsWithChildren { let name = name.as_jsx_name()?.value_token().ok()?; let name = name.text_trimmed(); if is_void_dom_element(name) { - let dangerous_prop = element - .find_attribute_by_name("dangerouslySetInnerHTML") - .ok()?; - let children_prop = element.find_attribute_by_name("children").ok()?; + let dangerous_prop = element.find_attribute_by_name("dangerouslySetInnerHTML"); + let children_prop = element.find_attribute_by_name("children"); if dangerous_prop.is_some() || children_prop.is_some() { let cause = NoVoidElementsWithChildrenCause::Jsx { children_prop, diff --git a/crates/biome_js_analyze/src/lint/nursery/no_head_element.rs b/crates/biome_js_analyze/src/lint/nursery/no_head_element.rs index ebd0adfe918e..b03b88e8448b 100644 --- a/crates/biome_js_analyze/src/lint/nursery/no_head_element.rs +++ b/crates/biome_js_analyze/src/lint/nursery/no_head_element.rs @@ -61,7 +61,7 @@ impl Rule for NoHeadElement { fn run(ctx: &RuleContext) -> Self::Signals { let element = ctx.query(); - let name = element.name().ok()?.name_value_token()?; + let name = element.name().ok()?.name_value_token().ok()?; if name.text_trimmed() == "head" { let is_in_app_dir = ctx diff --git a/crates/biome_js_analyze/src/lint/nursery/no_img_element.rs b/crates/biome_js_analyze/src/lint/nursery/no_img_element.rs index 109fe9fe462f..6a7d97ac4757 100644 --- a/crates/biome_js_analyze/src/lint/nursery/no_img_element.rs +++ b/crates/biome_js_analyze/src/lint/nursery/no_img_element.rs @@ -70,7 +70,7 @@ impl Rule for NoImgElement { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - if node.name().ok()?.name_value_token()?.text_trimmed() != "img" + if node.name().ok()?.name_value_token().ok()?.text_trimmed() != "img" || node.attributes().is_empty() { return None; @@ -86,7 +86,7 @@ impl Rule for NoImgElement { let Some(opening_element) = parent.opening_element().ok() else { return Some(()); }; - let name = opening_element.name().ok()?.name_value_token()?; + let name = opening_element.name().ok()?.name_value_token().ok()?; if name.text_trimmed() == "picture" { return None; diff --git a/crates/biome_js_analyze/src/lint/nursery/use_google_font_display.rs b/crates/biome_js_analyze/src/lint/nursery/use_google_font_display.rs index 5c4e6f1cc494..832724e854be 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_google_font_display.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_google_font_display.rs @@ -74,7 +74,7 @@ impl Rule for UseGoogleFontDisplay { fn run(ctx: &RuleContext) -> Self::Signals { let element = ctx.query(); - if element.name().ok()?.name_value_token()?.text_trimmed() != "link" { + if element.name().ok()?.name_value_token().ok()?.text_trimmed() != "link" { return None; } diff --git a/crates/biome_js_analyze/src/lint/nursery/use_google_font_preconnect.rs b/crates/biome_js_analyze/src/lint/nursery/use_google_font_preconnect.rs index 9c820952e2de..de2b82f730b5 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_google_font_preconnect.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_google_font_preconnect.rs @@ -65,7 +65,7 @@ impl Rule for UseGoogleFontPreconnect { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); - if node.name().ok()?.name_value_token()?.text_trimmed() != "link" { + if node.name().ok()?.name_value_token().ok()?.text_trimmed() != "link" { return None; } @@ -107,7 +107,7 @@ impl Rule for UseGoogleFontPreconnect { let mut attributes: Vec<_> = node.attributes().iter().collect(); let last_attr_token = match attributes.last()? { - AnyJsxAttribute::JsxAttribute(a) => a.name_value_token()?, + AnyJsxAttribute::JsxAttribute(a) => a.name_value_token().ok()?, AnyJsxAttribute::JsxSpreadAttribute(a) => a.l_curly_token().ok()?, }; diff --git a/crates/biome_js_analyze/src/lint/nursery/use_valid_autocomplete.rs b/crates/biome_js_analyze/src/lint/nursery/use_valid_autocomplete.rs index a9d7ca02de7e..7b13d8c645fc 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_valid_autocomplete.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_valid_autocomplete.rs @@ -154,7 +154,7 @@ impl Rule for UseValidAutocomplete { let input_components = &options.input_components; match ctx.query() { UseValidAutocompleteQuery::JsxOpeningElement(elem) => { - let elem_name = elem.name().ok()?.name_value_token()?; + let elem_name = elem.name().ok()?.name_value_token().ok()?; let elem_name = elem_name.text_trimmed(); if !(elem_name == "input" || input_components.iter().any(|x| x.as_ref() == elem_name)) @@ -162,7 +162,7 @@ impl Rule for UseValidAutocomplete { return None; } let attributes = elem.attributes(); - let autocomplete = attributes.find_by_name("autocomplete").ok()??; + let autocomplete = attributes.find_by_name("autocomplete")?; let _initializer = autocomplete.initializer()?; let extract_attrs = ctx.extract_attributes(&attributes)?; let autocomplete_values = extract_attrs.get("autocomplete")?; @@ -183,7 +183,7 @@ impl Rule for UseValidAutocomplete { Some(autocomplete.range()) } UseValidAutocompleteQuery::JsxSelfClosingElement(elem) => { - let elem_name = elem.name().ok()?.name_value_token()?; + let elem_name = elem.name().ok()?.name_value_token().ok()?; let elem_name = elem_name.text_trimmed(); if !(elem_name == "input" || input_components.iter().any(|x| x.as_ref() == elem_name)) @@ -191,7 +191,7 @@ impl Rule for UseValidAutocomplete { return None; } let attributes = elem.attributes(); - let autocomplete = attributes.find_by_name("autocomplete").ok()??; + let autocomplete = attributes.find_by_name("autocomplete")?; let _initializer = autocomplete.initializer()?; let extract_attrs = ctx.extract_attributes(&attributes)?; let autocomplete_values = extract_attrs.get("autocomplete")?; diff --git a/crates/biome_js_analyze/src/lint/security/no_dangerously_set_inner_html_with_children.rs b/crates/biome_js_analyze/src/lint/security/no_dangerously_set_inner_html_with_children.rs index 47fbb93ef6cb..d81e558044e9 100644 --- a/crates/biome_js_analyze/src/lint/security/no_dangerously_set_inner_html_with_children.rs +++ b/crates/biome_js_analyze/src/lint/security/no_dangerously_set_inner_html_with_children.rs @@ -110,12 +110,10 @@ impl AnyJsCreateElement { opening_element .find_attribute_by_name("dangerouslySetInnerHTML") - .ok()? .map(DangerousProp::from) } AnyJsCreateElement::JsxSelfClosingElement(element) => element .find_attribute_by_name("dangerouslySetInnerHTML") - .ok()? .map(DangerousProp::from), AnyJsCreateElement::JsCallExpression(call_expression) => { let react_create_element = @@ -135,12 +133,10 @@ impl AnyJsCreateElement { opening_element .find_attribute_by_name("children") - .ok()? .map(DangerousProp::from) } AnyJsCreateElement::JsxSelfClosingElement(element) => element .find_attribute_by_name("children") - .ok()? .map(DangerousProp::from), AnyJsCreateElement::JsCallExpression(call_expression) => { let react_create_element = diff --git a/crates/biome_js_analyze/src/services/aria.rs b/crates/biome_js_analyze/src/services/aria.rs index 14cff89e9f24..201124b2d7f8 100644 --- a/crates/biome_js_analyze/src/services/aria.rs +++ b/crates/biome_js_analyze/src/services/aria.rs @@ -35,7 +35,7 @@ impl AriaServices { if let Some(static_value) = initializer.as_static_value() { static_value .text() - .split_whitespace() + .split_ascii_whitespace() .map(|s| AttributeValue::StaticValue(s.to_string())) .collect() } else { diff --git a/crates/biome_js_syntax/src/jsx_ext.rs b/crates/biome_js_syntax/src/jsx_ext.rs index 7b005aebca9e..531653555357 100644 --- a/crates/biome_js_syntax/src/jsx_ext.rs +++ b/crates/biome_js_syntax/src/jsx_ext.rs @@ -3,12 +3,12 @@ use std::collections::HashSet; use crate::{ inner_string_text, static_value::StaticValue, AnyJsxAttribute, AnyJsxAttributeName, AnyJsxAttributeValue, AnyJsxChild, AnyJsxElementName, AnyJsxTag, JsSyntaxToken, JsxAttribute, - JsxAttributeList, JsxElement, JsxName, JsxOpeningElement, JsxSelfClosingElement, JsxString, + JsxAttributeList, JsxElement, JsxOpeningElement, JsxSelfClosingElement, JsxString, }; use biome_rowan::{declare_node_union, AstNode, AstNodeList, SyntaxResult, TokenText}; impl JsxString { - /// Get the inner text of a string not including the quotes + /// Returns the inner text of a string not including the quotes. /// /// ## Examples /// @@ -44,7 +44,7 @@ impl AnyJsxTag { } impl JsxOpeningElement { - /// Find and return the `JsxAttribute` that matches the given name + /// Find and return the [JsxAttribute] that matches the given name. /// /// ## Examples /// @@ -80,19 +80,16 @@ impl JsxOpeningElement { /// token(T![>]), /// ).build(); /// - /// assert_eq!(opening_element.find_attribute_by_name("div").unwrap().is_some(), true); - /// assert_eq!(opening_element.find_attribute_by_name("img").unwrap().is_some(), true); - /// assert_eq!(opening_element.find_attribute_by_name("p").unwrap().is_some(), false); + /// assert!(opening_element.find_attribute_by_name("div").is_some()); + /// assert!(opening_element.find_attribute_by_name("img").is_some()); + /// assert!(!opening_element.find_attribute_by_name("p").is_some()); /// ``` /// - pub fn find_attribute_by_name( - &self, - name_to_lookup: &str, - ) -> SyntaxResult> { + pub fn find_attribute_by_name(&self, name_to_lookup: &str) -> Option { self.attributes().find_by_name(name_to_lookup) } - /// It checks if current attribute has a trailing spread props + /// Returns `true` if the current attribute has a trailing spread props. /// /// ## Examples /// @@ -130,7 +127,7 @@ impl JsxOpeningElement { /// token(T![>]), /// ).build(); /// - /// let div = opening_element.find_attribute_by_name("div").unwrap().unwrap(); + /// let div = opening_element.find_attribute_by_name("div").unwrap(); /// assert!(opening_element.has_trailing_spread_prop(&div)); /// ``` pub fn has_trailing_spread_prop(&self, current_attribute: &JsxAttribute) -> bool { @@ -138,7 +135,7 @@ impl JsxOpeningElement { .has_trailing_spread_prop(current_attribute) } - /// Check if jsx element has a child that is accessible + /// Returns `true` if jsx element has a child that is accessible. pub fn has_accessible_child(&self) -> bool { self.parent::().map_or(false, |parent| { parent @@ -150,7 +147,7 @@ impl JsxOpeningElement { } impl JsxSelfClosingElement { - /// Find and return the `JsxAttribute` that matches the given name + /// Returns the [JsxAttribute] that matches `name_to_lookup`. /// /// ## Examples /// @@ -187,19 +184,16 @@ impl JsxSelfClosingElement { /// token(T![>]), /// ).build(); /// - /// assert_eq!(opening_element.find_attribute_by_name("div").unwrap().is_some(), true); - /// assert_eq!(opening_element.find_attribute_by_name("img").unwrap().is_some(), true); - /// assert_eq!(opening_element.find_attribute_by_name("p").unwrap().is_some(), false); + /// assert!(opening_element.find_attribute_by_name("div").is_some()); + /// assert!(opening_element.find_attribute_by_name("img").is_some()); + /// assert!(!opening_element.find_attribute_by_name("p").is_some()); /// ``` /// - pub fn find_attribute_by_name( - &self, - name_to_lookup: &str, - ) -> SyntaxResult> { + pub fn find_attribute_by_name(&self, name_to_lookup: &str) -> Option { self.attributes().find_by_name(name_to_lookup) } - /// It checks if current attribute has a trailing spread props + /// Returns `true` if the current attribute has a trailing spread props. /// /// ## Examples /// @@ -240,7 +234,7 @@ impl JsxSelfClosingElement { /// token(T![>]), /// ).build(); /// - /// let div = opening_element.find_attribute_by_name("div").unwrap().unwrap(); + /// let div = opening_element.find_attribute_by_name("div").unwrap(); /// assert!(opening_element.has_trailing_spread_prop(&div)); /// ``` pub fn has_trailing_spread_prop(&self, current_attribute: &JsxAttribute) -> bool { @@ -250,12 +244,12 @@ impl JsxSelfClosingElement { } impl JsxAttributeList { - /// Finds and returns attributes `JsxAttribute` that matches the given names like [Self::find_by_name]. + /// Returns the [JsxAttribute] that match the given `names_to_lookup`. /// Only attributes with name as [JsxName] can be returned. /// - /// Each name of "names_to_lookup" should be unique. + /// Each name of `names_to_lookup` must be unique. /// - /// Supports maximum of 16 names to avoid stack overflow. Each attribute will consume: + /// Supports a maximum of 16 names to avoid stack overflow. Each attribute will consume: /// /// - 8 bytes for the `Option` result; /// - plus 16 bytes for the [&str] argument. @@ -269,11 +263,10 @@ impl JsxAttributeList { const INIT: Option = None; let mut results = [INIT; N]; - let mut missing = N; - 'attributes: for att in self { - if let Some(attribute) = att.as_jsx_attribute() { + for att in self { + if let AnyJsxAttribute::JsxAttribute(attribute) = att { if let Some(name) = attribute .name() .ok() @@ -282,9 +275,9 @@ impl JsxAttributeList { let name = name.text_trimmed(); for i in 0..N { if results[i].is_none() && names_to_lookup[i] == name { - results[i] = Some(attribute.clone()); + results[i] = Some(attribute); if missing == 1 { - break 'attributes; + return results; } else { missing -= 1; break; @@ -298,19 +291,17 @@ impl JsxAttributeList { results } - pub fn find_by_name(&self, name_to_lookup: &str) -> SyntaxResult> { - let attribute = self.iter().find_map(|attribute| { - let attribute = JsxAttribute::cast(attribute.into_syntax())?; - let name = attribute.name().ok()?; - let name = JsxName::cast(name.into_syntax())?; - if name.value_token().ok()?.text_trimmed() == name_to_lookup { - Some(attribute) - } else { - None + pub fn find_by_name(&self, name_to_lookup: &str) -> Option { + self.iter().find_map(|attribute| { + if let AnyJsxAttribute::JsxAttribute(attribute) = attribute { + if let Ok(AnyJsxAttributeName::JsxName(name)) = attribute.name() { + if name.value_token().ok()?.text_trimmed() == name_to_lookup { + return Some(attribute); + } + } } - }); - - Ok(attribute) + None + }) } pub fn has_trailing_spread_prop(&self, current_attribute: &JsxAttribute) -> bool { @@ -331,12 +322,12 @@ impl JsxAttributeList { } impl AnyJsxElementName { - pub fn name_value_token(&self) -> Option { + pub fn name_value_token(&self) -> SyntaxResult { match self { - AnyJsxElementName::JsxMemberName(member) => member.member().ok()?.value_token().ok(), - AnyJsxElementName::JsxName(name) => name.value_token().ok(), - AnyJsxElementName::JsxNamespaceName(name) => name.name().ok()?.value_token().ok(), - AnyJsxElementName::JsxReferenceIdentifier(name) => name.value_token().ok(), + AnyJsxElementName::JsxMemberName(member) => member.member()?.value_token(), + AnyJsxElementName::JsxName(name) => name.value_token(), + AnyJsxElementName::JsxNamespaceName(name) => name.name()?.value_token(), + AnyJsxElementName::JsxReferenceIdentifier(name) => name.value_token(), } } } @@ -360,11 +351,11 @@ impl AnyJsxElement { } } - pub fn name_value_token(&self) -> Option { - self.name().ok()?.name_value_token() + pub fn name_value_token(&self) -> SyntaxResult { + self.name()?.name_value_token() } - /// Return true if the current element is actually a component + /// Returns `true` if the current element is actually a component. /// /// - `` is a component and it would return `true` /// - `` is **not** component and it returns `false` @@ -372,7 +363,7 @@ impl AnyJsxElement { self.name().map_or(false, |it| it.as_jsx_name().is_none()) } - /// Return true if the current element is an HTML element + /// Returns `true` if the current element is an HTML element. /// /// - `` is a component and it would return `false` /// - `` is **not** component and it returns `true` @@ -400,15 +391,15 @@ impl AnyJsxElement { pub fn find_attribute_by_name(&self, name_to_lookup: &str) -> Option { match self { AnyJsxElement::JsxSelfClosingElement(element) => { - element.find_attribute_by_name(name_to_lookup).ok()? + element.find_attribute_by_name(name_to_lookup) } AnyJsxElement::JsxOpeningElement(element) => { - element.find_attribute_by_name(name_to_lookup).ok()? + element.find_attribute_by_name(name_to_lookup) } } } - /// Returns the attribute value of JsxString attributes + /// Returns the attribute value of [JsxString] attributes. /// /// ``` /// use biome_js_syntax::jsx_ext::AnyJsxElement; @@ -453,18 +444,18 @@ impl AnyJsxElement { /// ).build() /// ); /// - /// assert_eq!(jsx_element.get_attribute_inner_string_text("unknown").is_none(), true); - /// assert_eq!(jsx_element.get_attribute_inner_string_text("disabled").is_none(), true); + /// assert!(jsx_element.get_attribute_inner_string_text("unknown").is_none()); + /// assert!(jsx_element.get_attribute_inner_string_text("disabled").is_none()); /// assert_eq!(jsx_element.get_attribute_inner_string_text("type").unwrap(), "button"); ///``` /// - pub fn get_attribute_inner_string_text(&self, name_to_lookup: &str) -> Option { + pub fn get_attribute_inner_string_text(&self, name_to_lookup: &str) -> Option { if let Some(attr) = self.find_attribute_by_name(name_to_lookup) { let initializer = attr.initializer()?.value().ok()?; - let binding = initializer.as_jsx_string()?.inner_string_text().ok()?; - return Some(binding.to_string()); - }; - None + initializer.as_jsx_string()?.inner_string_text().ok() + } else { + None + } } pub fn has_truthy_attribute(&self, name_to_lookup: &str) -> bool { @@ -488,10 +479,10 @@ impl JsxAttribute { self.initializer()?.value().ok()?.as_static_value() } - pub fn name_value_token(&self) -> Option { - match self.name().ok()? { - AnyJsxAttributeName::JsxName(name) => name.value_token().ok(), - AnyJsxAttributeName::JsxNamespaceName(name) => name.name().ok()?.value_token().ok(), + pub fn name_value_token(&self) -> SyntaxResult { + match self.name()? { + AnyJsxAttributeName::JsxName(name) => name.value_token(), + AnyJsxAttributeName::JsxNamespaceName(name) => name.name()?.value_token(), } } } diff --git a/crates/biome_service/src/file_handlers/mod.rs b/crates/biome_service/src/file_handlers/mod.rs index 1ccc9225445f..91fc69f9cde6 100644 --- a/crates/biome_service/src/file_handlers/mod.rs +++ b/crates/biome_service/src/file_handlers/mod.rs @@ -652,7 +652,7 @@ pub(crate) fn parse_lang_from_script_opening_tag( .ok()?; let tag = expression.as_jsx_tag_expression()?.tag().ok()?; let opening_element = tag.as_jsx_element()?.opening_element().ok()?; - let lang_attribute = opening_element.attributes().find_by_name("lang").ok()??; + let lang_attribute = opening_element.attributes().find_by_name("lang")?; let attribute_value = lang_attribute.initializer()?.value().ok()?; let attribute_inner_string = attribute_value.as_jsx_string()?.inner_string_text().ok()?;