diff --git a/.changeset/public-walls-buy.md b/.changeset/public-walls-buy.md new file mode 100644 index 000000000000..d2e85a553346 --- /dev/null +++ b/.changeset/public-walls-buy.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Added the nursery rule [`useUniqueVariableNames`](https://biomejs.dev/linter/rules/use-unique-variable-names/). Enforce unique variable names for GraphQL operations. diff --git a/crates/biome_configuration/src/analyzer/linter/rules.rs b/crates/biome_configuration/src/analyzer/linter/rules.rs index 5b176964a694..9d0c2e282def 100644 --- a/crates/biome_configuration/src/analyzer/linter/rules.rs +++ b/crates/biome_configuration/src/analyzer/linter/rules.rs @@ -467,6 +467,7 @@ pub enum RuleName { UseUnifiedTypeSignatures, UseUniqueElementIds, UseUniqueGraphqlOperationName, + UseUniqueVariableNames, UseValidAnchor, UseValidAriaProps, UseValidAriaRole, @@ -874,6 +875,7 @@ impl RuleName { Self::UseUnifiedTypeSignatures => "useUnifiedTypeSignatures", Self::UseUniqueElementIds => "useUniqueElementIds", Self::UseUniqueGraphqlOperationName => "useUniqueGraphqlOperationName", + Self::UseUniqueVariableNames => "useUniqueVariableNames", Self::UseValidAnchor => "useValidAnchor", Self::UseValidAriaProps => "useValidAriaProps", Self::UseValidAriaRole => "useValidAriaRole", @@ -1279,6 +1281,7 @@ impl RuleName { Self::UseUnifiedTypeSignatures => RuleGroup::Style, Self::UseUniqueElementIds => RuleGroup::Correctness, Self::UseUniqueGraphqlOperationName => RuleGroup::Nursery, + Self::UseUniqueVariableNames => RuleGroup::Nursery, Self::UseValidAnchor => RuleGroup::A11y, Self::UseValidAriaProps => RuleGroup::A11y, Self::UseValidAriaRole => RuleGroup::A11y, @@ -1691,6 +1694,7 @@ impl std::str::FromStr for RuleName { "useUnifiedTypeSignatures" => Ok(Self::UseUnifiedTypeSignatures), "useUniqueElementIds" => Ok(Self::UseUniqueElementIds), "useUniqueGraphqlOperationName" => Ok(Self::UseUniqueGraphqlOperationName), + "useUniqueVariableNames" => Ok(Self::UseUniqueVariableNames), "useValidAnchor" => Ok(Self::UseValidAnchor), "useValidAriaProps" => Ok(Self::UseValidAriaProps), "useValidAriaRole" => Ok(Self::UseValidAriaRole), @@ -4848,7 +4852,7 @@ impl From for Correctness { #[cfg_attr(feature = "schema", derive(JsonSchema))] #[serde(rename_all = "camelCase", default, deny_unknown_fields)] #[doc = r" A list of rules that belong to this group"] -pub struct Nursery { # [doc = r" Enables the recommended rules for this group"] # [serde (skip_serializing_if = "Option::is_none")] pub recommended : Option < bool > , # [doc = "Disallow ambiguous anchor descriptions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_ambiguous_anchor_text : Option < RuleConfiguration < biome_rule_options :: no_ambiguous_anchor_text :: NoAmbiguousAnchorTextOptions >> , # [doc = "Disallow continue statements.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_continue : Option < RuleConfiguration < biome_rule_options :: no_continue :: NoContinueOptions >> , # [doc = "Restrict imports of deprecated exports.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_deprecated_imports : Option < RuleConfiguration < biome_rule_options :: no_deprecated_imports :: NoDeprecatedImportsOptions >> , # [doc = "Prevent the listing of duplicate dependencies. The rule supports the following dependency groups: \"bundledDependencies\", \"bundleDependencies\", \"dependencies\", \"devDependencies\", \"overrides\", \"optionalDependencies\", and \"peerDependencies\".\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_duplicate_dependencies : Option < RuleConfiguration < biome_rule_options :: no_duplicate_dependencies :: NoDuplicateDependenciesOptions >> , # [doc = "Disallow JSX prop spreading the same identifier multiple times.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_duplicated_spread_props : Option < RuleConfiguration < biome_rule_options :: no_duplicated_spread_props :: NoDuplicatedSpreadPropsOptions >> , # [doc = "Disallow empty sources.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_empty_source : Option < RuleConfiguration < biome_rule_options :: no_empty_source :: NoEmptySourceOptions >> , # [doc = "Require the use of === or !== for comparison with null.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_equals_to_null : Option < RuleFixConfiguration < biome_rule_options :: no_equals_to_null :: NoEqualsToNullOptions >> , # [doc = "Require Promise-like statements to be handled appropriately.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_floating_promises : Option < RuleFixConfiguration < biome_rule_options :: no_floating_promises :: NoFloatingPromisesOptions >> , # [doc = "Disallow iterating using a for-in loop.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_for_in : Option < RuleConfiguration < biome_rule_options :: no_for_in :: NoForInOptions >> , # [doc = "Prevent import cycles.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_import_cycles : Option < RuleConfiguration < biome_rule_options :: no_import_cycles :: NoImportCyclesOptions >> , # [doc = "Disallows the usage of the unary operators ++ and --.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_increment_decrement : Option < RuleConfiguration < biome_rule_options :: no_increment_decrement :: NoIncrementDecrementOptions >> , # [doc = "Disallow string literals inside JSX elements.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_jsx_literals : Option < RuleConfiguration < biome_rule_options :: no_jsx_literals :: NoJsxLiteralsOptions >> , # [doc = "Prevent problematic leaked values from being rendered.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_leaked_render : Option < RuleConfiguration < biome_rule_options :: no_leaked_render :: NoLeakedRenderOptions >> , # [doc = "Disallow Promises to be used in places where they are almost certainly a mistake.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_misused_promises : Option < RuleFixConfiguration < biome_rule_options :: no_misused_promises :: NoMisusedPromisesOptions >> , # [doc = "Disallow use of chained assignment expressions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_multi_assign : Option < RuleConfiguration < biome_rule_options :: no_multi_assign :: NoMultiAssignOptions >> , # [doc = "Disallow creating multiline strings by escaping newlines.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_multi_str : Option < RuleConfiguration < biome_rule_options :: no_multi_str :: NoMultiStrOptions >> , # [doc = "Prevent client components from being async functions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_next_async_client_component : Option < RuleConfiguration < biome_rule_options :: no_next_async_client_component :: NoNextAsyncClientComponentOptions >> , # [doc = "Disallow function parameters that are only used in recursive calls.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_parameters_only_used_in_recursion : Option < RuleFixConfiguration < biome_rule_options :: no_parameters_only_used_in_recursion :: NoParametersOnlyUsedInRecursionOptions >> , # [doc = "Disallow the use of the deprecated __proto__ object property.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_proto : Option < RuleConfiguration < biome_rule_options :: no_proto :: NoProtoOptions >> , # [doc = "Replaces usages of forwardRef with passing ref as a prop.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_react_forward_ref : Option < RuleFixConfiguration < biome_rule_options :: no_react_forward_ref :: NoReactForwardRefOptions >> , # [doc = "Disallow assignments in return statements.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_return_assign : Option < RuleConfiguration < biome_rule_options :: no_return_assign :: NoReturnAssignOptions >> , # [doc = "Disallow javascript: URLs in HTML.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_script_url : Option < RuleConfiguration < biome_rule_options :: no_script_url :: NoScriptUrlOptions >> , # [doc = "Disallow variable declarations from shadowing variables declared in the outer scope.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_shadow : Option < RuleConfiguration < biome_rule_options :: no_shadow :: NoShadowOptions >> , # [doc = "Prevent the usage of synchronous scripts.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_sync_scripts : Option < RuleConfiguration < biome_rule_options :: no_sync_scripts :: NoSyncScriptsOptions >> , # [doc = "Disallow ternary operators.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_ternary : Option < RuleConfiguration < biome_rule_options :: no_ternary :: NoTernaryOptions >> , # [doc = "Disallow the use of undeclared environment variables.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_undeclared_env_vars : Option < RuleConfiguration < biome_rule_options :: no_undeclared_env_vars :: NoUndeclaredEnvVarsOptions >> , # [doc = "Disallow unknown DOM properties.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unknown_attribute : Option < RuleConfiguration < biome_rule_options :: no_unknown_attribute :: NoUnknownAttributeOptions >> , # [doc = "Disallow unnecessary type-based conditions that can be statically determined as redundant.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unnecessary_conditions : Option < RuleConfiguration < biome_rule_options :: no_unnecessary_conditions :: NoUnnecessaryConditionsOptions >> , # [doc = "Warn when importing non-existing exports.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unresolved_imports : Option < RuleConfiguration < biome_rule_options :: no_unresolved_imports :: NoUnresolvedImportsOptions >> , # [doc = "Disallow expression statements that are neither a function call nor an assignment.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unused_expressions : Option < RuleConfiguration < biome_rule_options :: no_unused_expressions :: NoUnusedExpressionsOptions >> , # [doc = "Disallow unused catch bindings.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_useless_catch_binding : Option < RuleFixConfiguration < biome_rule_options :: no_useless_catch_binding :: NoUselessCatchBindingOptions >> , # [doc = "Disallow the use of useless undefined.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_useless_undefined : Option < RuleFixConfiguration < biome_rule_options :: no_useless_undefined :: NoUselessUndefinedOptions >> , # [doc = "Enforce that Vue component data options are declared as functions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_data_object_declaration : Option < RuleFixConfiguration < biome_rule_options :: no_vue_data_object_declaration :: NoVueDataObjectDeclarationOptions >> , # [doc = "Disallow duplicate keys in Vue component data, methods, computed properties, and other options.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_duplicate_keys : Option < RuleConfiguration < biome_rule_options :: no_vue_duplicate_keys :: NoVueDuplicateKeysOptions >> , # [doc = "Disallow reserved keys in Vue component data and computed properties.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_reserved_keys : Option < RuleConfiguration < biome_rule_options :: no_vue_reserved_keys :: NoVueReservedKeysOptions >> , # [doc = "Disallow reserved names to be used as props.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_reserved_props : Option < RuleConfiguration < biome_rule_options :: no_vue_reserved_props :: NoVueReservedPropsOptions >> , # [doc = "Disallow destructuring of props passed to setup in Vue projects.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_setup_props_reactivity_loss : Option < RuleConfiguration < biome_rule_options :: no_vue_setup_props_reactivity_loss :: NoVueSetupPropsReactivityLossOptions >> , # [doc = "Disallow using v-if and v-for directives on the same element.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_v_if_with_v_for : Option < RuleConfiguration < biome_rule_options :: no_vue_v_if_with_v_for :: NoVueVIfWithVForOptions >> , # [doc = "Require Array#sort and Array#toSorted calls to always provide a compareFunction.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_array_sort_compare : Option < RuleConfiguration < biome_rule_options :: use_array_sort_compare :: UseArraySortCompareOptions >> , # [doc = "Enforce that await is only used on Promise values.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_await_thenable : Option < RuleConfiguration < biome_rule_options :: use_await_thenable :: UseAwaitThenableOptions >> , # [doc = "Enforce consistent arrow function bodies.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_consistent_arrow_return : Option < RuleFixConfiguration < biome_rule_options :: use_consistent_arrow_return :: UseConsistentArrowReturnOptions >> , # [doc = "Require all descriptions to follow the same style (either block or inline) to maintain consistency and improve readability across the schema.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_consistent_graphql_descriptions : Option < RuleConfiguration < biome_rule_options :: use_consistent_graphql_descriptions :: UseConsistentGraphqlDescriptionsOptions >> , # [doc = "Require the @deprecated directive to specify a deletion date.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_deprecated_date : Option < RuleConfiguration < biome_rule_options :: use_deprecated_date :: UseDeprecatedDateOptions >> , # [doc = "Require destructuring from arrays and/or objects.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_destructuring : Option < RuleConfiguration < biome_rule_options :: use_destructuring :: UseDestructuringOptions >> , # [doc = "Require switch-case statements to be exhaustive.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_exhaustive_switch_cases : Option < RuleFixConfiguration < biome_rule_options :: use_exhaustive_switch_cases :: UseExhaustiveSwitchCasesOptions >> , # [doc = "Enforce types in functions, methods, variables, and parameters.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_explicit_type : Option < RuleConfiguration < biome_rule_options :: use_explicit_type :: UseExplicitTypeOptions >> , # [doc = "Enforce the use of Array.prototype.find() over Array.prototype.filter() followed by [0] when looking for a single result.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_find : Option < RuleConfiguration < biome_rule_options :: use_find :: UseFindOptions >> , # [doc = "Enforce a maximum number of parameters in function definitions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_max_params : Option < RuleConfiguration < biome_rule_options :: use_max_params :: UseMaxParamsOptions >> , # [doc = "Disallow use* hooks outside of component$ or other use* hooks in Qwik applications.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_qwik_method_usage : Option < RuleConfiguration < biome_rule_options :: use_qwik_method_usage :: UseQwikMethodUsageOptions >> , # [doc = "Disallow unserializable expressions in Qwik dollar ($) scopes.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_qwik_valid_lexical_scope : Option < RuleConfiguration < biome_rule_options :: use_qwik_valid_lexical_scope :: UseQwikValidLexicalScopeOptions >> , # [doc = "Enforce RegExp#exec over String#match if no global flag is provided.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_regexp_exec : Option < RuleConfiguration < biome_rule_options :: use_regexp_exec :: UseRegexpExecOptions >> , # [doc = "Enforce the presence of required scripts in package.json.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_required_scripts : Option < RuleConfiguration < biome_rule_options :: use_required_scripts :: UseRequiredScriptsOptions >> , # [doc = "Enforce the sorting of CSS utility classes.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_sorted_classes : Option < RuleFixConfiguration < biome_rule_options :: use_sorted_classes :: UseSortedClassesOptions >> , # [doc = "Enforce the use of the spread operator over .apply().\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_spread : Option < RuleFixConfiguration < biome_rule_options :: use_spread :: UseSpreadOptions >> , # [doc = "Enforce unique operation names across a GraphQL document.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_unique_graphql_operation_name : Option < RuleConfiguration < biome_rule_options :: use_unique_graphql_operation_name :: UseUniqueGraphqlOperationNameOptions >> , # [doc = "Enforce consistent defineProps declaration style.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_consistent_define_props_declaration : Option < RuleConfiguration < biome_rule_options :: use_vue_consistent_define_props_declaration :: UseVueConsistentDefinePropsDeclarationOptions >> , # [doc = "Enforce specific order of Vue compiler macros.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_define_macros_order : Option < RuleFixConfiguration < biome_rule_options :: use_vue_define_macros_order :: UseVueDefineMacrosOrderOptions >> , # [doc = "Enforce hyphenated (kebab-case) attribute names in Vue templates.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_hyphenated_attributes : Option < RuleFixConfiguration < biome_rule_options :: use_vue_hyphenated_attributes :: UseVueHyphenatedAttributesOptions >> , # [doc = "Enforce multi-word component names in Vue components.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_multi_word_component_names : Option < RuleConfiguration < biome_rule_options :: use_vue_multi_word_component_names :: UseVueMultiWordComponentNamesOptions >> , # [doc = "Forbids v-bind directives with missing arguments or invalid modifiers.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_bind : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_bind :: UseVueValidVBindOptions >> , # [doc = "Enforce valid usage of v-else.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_else : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_else :: UseVueValidVElseOptions >> , # [doc = "Enforce valid v-else-if directives.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_else_if : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_else_if :: UseVueValidVElseIfOptions >> , # [doc = "Enforce valid v-html directives.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_html : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_html :: UseVueValidVHtmlOptions >> , # [doc = "Enforces valid v-if usage for Vue templates.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_if : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_if :: UseVueValidVIfOptions >> , # [doc = "Enforce valid v-on directives with proper arguments, modifiers, and handlers.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_on : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_on :: UseVueValidVOnOptions >> , # [doc = "Enforce valid v-text Vue directives.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_text : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_text :: UseVueValidVTextOptions >> } +pub struct Nursery { # [doc = r" Enables the recommended rules for this group"] # [serde (skip_serializing_if = "Option::is_none")] pub recommended : Option < bool > , # [doc = "Disallow ambiguous anchor descriptions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_ambiguous_anchor_text : Option < RuleConfiguration < biome_rule_options :: no_ambiguous_anchor_text :: NoAmbiguousAnchorTextOptions >> , # [doc = "Disallow continue statements.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_continue : Option < RuleConfiguration < biome_rule_options :: no_continue :: NoContinueOptions >> , # [doc = "Restrict imports of deprecated exports.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_deprecated_imports : Option < RuleConfiguration < biome_rule_options :: no_deprecated_imports :: NoDeprecatedImportsOptions >> , # [doc = "Prevent the listing of duplicate dependencies. The rule supports the following dependency groups: \"bundledDependencies\", \"bundleDependencies\", \"dependencies\", \"devDependencies\", \"overrides\", \"optionalDependencies\", and \"peerDependencies\".\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_duplicate_dependencies : Option < RuleConfiguration < biome_rule_options :: no_duplicate_dependencies :: NoDuplicateDependenciesOptions >> , # [doc = "Disallow JSX prop spreading the same identifier multiple times.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_duplicated_spread_props : Option < RuleConfiguration < biome_rule_options :: no_duplicated_spread_props :: NoDuplicatedSpreadPropsOptions >> , # [doc = "Disallow empty sources.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_empty_source : Option < RuleConfiguration < biome_rule_options :: no_empty_source :: NoEmptySourceOptions >> , # [doc = "Require the use of === or !== for comparison with null.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_equals_to_null : Option < RuleFixConfiguration < biome_rule_options :: no_equals_to_null :: NoEqualsToNullOptions >> , # [doc = "Require Promise-like statements to be handled appropriately.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_floating_promises : Option < RuleFixConfiguration < biome_rule_options :: no_floating_promises :: NoFloatingPromisesOptions >> , # [doc = "Disallow iterating using a for-in loop.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_for_in : Option < RuleConfiguration < biome_rule_options :: no_for_in :: NoForInOptions >> , # [doc = "Prevent import cycles.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_import_cycles : Option < RuleConfiguration < biome_rule_options :: no_import_cycles :: NoImportCyclesOptions >> , # [doc = "Disallows the usage of the unary operators ++ and --.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_increment_decrement : Option < RuleConfiguration < biome_rule_options :: no_increment_decrement :: NoIncrementDecrementOptions >> , # [doc = "Disallow string literals inside JSX elements.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_jsx_literals : Option < RuleConfiguration < biome_rule_options :: no_jsx_literals :: NoJsxLiteralsOptions >> , # [doc = "Prevent problematic leaked values from being rendered.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_leaked_render : Option < RuleConfiguration < biome_rule_options :: no_leaked_render :: NoLeakedRenderOptions >> , # [doc = "Disallow Promises to be used in places where they are almost certainly a mistake.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_misused_promises : Option < RuleFixConfiguration < biome_rule_options :: no_misused_promises :: NoMisusedPromisesOptions >> , # [doc = "Disallow use of chained assignment expressions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_multi_assign : Option < RuleConfiguration < biome_rule_options :: no_multi_assign :: NoMultiAssignOptions >> , # [doc = "Disallow creating multiline strings by escaping newlines.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_multi_str : Option < RuleConfiguration < biome_rule_options :: no_multi_str :: NoMultiStrOptions >> , # [doc = "Prevent client components from being async functions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_next_async_client_component : Option < RuleConfiguration < biome_rule_options :: no_next_async_client_component :: NoNextAsyncClientComponentOptions >> , # [doc = "Disallow function parameters that are only used in recursive calls.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_parameters_only_used_in_recursion : Option < RuleFixConfiguration < biome_rule_options :: no_parameters_only_used_in_recursion :: NoParametersOnlyUsedInRecursionOptions >> , # [doc = "Disallow the use of the deprecated __proto__ object property.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_proto : Option < RuleConfiguration < biome_rule_options :: no_proto :: NoProtoOptions >> , # [doc = "Replaces usages of forwardRef with passing ref as a prop.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_react_forward_ref : Option < RuleFixConfiguration < biome_rule_options :: no_react_forward_ref :: NoReactForwardRefOptions >> , # [doc = "Disallow assignments in return statements.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_return_assign : Option < RuleConfiguration < biome_rule_options :: no_return_assign :: NoReturnAssignOptions >> , # [doc = "Disallow javascript: URLs in HTML.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_script_url : Option < RuleConfiguration < biome_rule_options :: no_script_url :: NoScriptUrlOptions >> , # [doc = "Disallow variable declarations from shadowing variables declared in the outer scope.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_shadow : Option < RuleConfiguration < biome_rule_options :: no_shadow :: NoShadowOptions >> , # [doc = "Prevent the usage of synchronous scripts.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_sync_scripts : Option < RuleConfiguration < biome_rule_options :: no_sync_scripts :: NoSyncScriptsOptions >> , # [doc = "Disallow ternary operators.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_ternary : Option < RuleConfiguration < biome_rule_options :: no_ternary :: NoTernaryOptions >> , # [doc = "Disallow the use of undeclared environment variables.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_undeclared_env_vars : Option < RuleConfiguration < biome_rule_options :: no_undeclared_env_vars :: NoUndeclaredEnvVarsOptions >> , # [doc = "Disallow unknown DOM properties.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unknown_attribute : Option < RuleConfiguration < biome_rule_options :: no_unknown_attribute :: NoUnknownAttributeOptions >> , # [doc = "Disallow unnecessary type-based conditions that can be statically determined as redundant.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unnecessary_conditions : Option < RuleConfiguration < biome_rule_options :: no_unnecessary_conditions :: NoUnnecessaryConditionsOptions >> , # [doc = "Warn when importing non-existing exports.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unresolved_imports : Option < RuleConfiguration < biome_rule_options :: no_unresolved_imports :: NoUnresolvedImportsOptions >> , # [doc = "Disallow expression statements that are neither a function call nor an assignment.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_unused_expressions : Option < RuleConfiguration < biome_rule_options :: no_unused_expressions :: NoUnusedExpressionsOptions >> , # [doc = "Disallow unused catch bindings.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_useless_catch_binding : Option < RuleFixConfiguration < biome_rule_options :: no_useless_catch_binding :: NoUselessCatchBindingOptions >> , # [doc = "Disallow the use of useless undefined.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_useless_undefined : Option < RuleFixConfiguration < biome_rule_options :: no_useless_undefined :: NoUselessUndefinedOptions >> , # [doc = "Enforce that Vue component data options are declared as functions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_data_object_declaration : Option < RuleFixConfiguration < biome_rule_options :: no_vue_data_object_declaration :: NoVueDataObjectDeclarationOptions >> , # [doc = "Disallow duplicate keys in Vue component data, methods, computed properties, and other options.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_duplicate_keys : Option < RuleConfiguration < biome_rule_options :: no_vue_duplicate_keys :: NoVueDuplicateKeysOptions >> , # [doc = "Disallow reserved keys in Vue component data and computed properties.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_reserved_keys : Option < RuleConfiguration < biome_rule_options :: no_vue_reserved_keys :: NoVueReservedKeysOptions >> , # [doc = "Disallow reserved names to be used as props.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_reserved_props : Option < RuleConfiguration < biome_rule_options :: no_vue_reserved_props :: NoVueReservedPropsOptions >> , # [doc = "Disallow destructuring of props passed to setup in Vue projects.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_setup_props_reactivity_loss : Option < RuleConfiguration < biome_rule_options :: no_vue_setup_props_reactivity_loss :: NoVueSetupPropsReactivityLossOptions >> , # [doc = "Disallow using v-if and v-for directives on the same element.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub no_vue_v_if_with_v_for : Option < RuleConfiguration < biome_rule_options :: no_vue_v_if_with_v_for :: NoVueVIfWithVForOptions >> , # [doc = "Require Array#sort and Array#toSorted calls to always provide a compareFunction.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_array_sort_compare : Option < RuleConfiguration < biome_rule_options :: use_array_sort_compare :: UseArraySortCompareOptions >> , # [doc = "Enforce that await is only used on Promise values.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_await_thenable : Option < RuleConfiguration < biome_rule_options :: use_await_thenable :: UseAwaitThenableOptions >> , # [doc = "Enforce consistent arrow function bodies.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_consistent_arrow_return : Option < RuleFixConfiguration < biome_rule_options :: use_consistent_arrow_return :: UseConsistentArrowReturnOptions >> , # [doc = "Require all descriptions to follow the same style (either block or inline) to maintain consistency and improve readability across the schema.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_consistent_graphql_descriptions : Option < RuleConfiguration < biome_rule_options :: use_consistent_graphql_descriptions :: UseConsistentGraphqlDescriptionsOptions >> , # [doc = "Require the @deprecated directive to specify a deletion date.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_deprecated_date : Option < RuleConfiguration < biome_rule_options :: use_deprecated_date :: UseDeprecatedDateOptions >> , # [doc = "Require destructuring from arrays and/or objects.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_destructuring : Option < RuleConfiguration < biome_rule_options :: use_destructuring :: UseDestructuringOptions >> , # [doc = "Require switch-case statements to be exhaustive.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_exhaustive_switch_cases : Option < RuleFixConfiguration < biome_rule_options :: use_exhaustive_switch_cases :: UseExhaustiveSwitchCasesOptions >> , # [doc = "Enforce types in functions, methods, variables, and parameters.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_explicit_type : Option < RuleConfiguration < biome_rule_options :: use_explicit_type :: UseExplicitTypeOptions >> , # [doc = "Enforce the use of Array.prototype.find() over Array.prototype.filter() followed by [0] when looking for a single result.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_find : Option < RuleConfiguration < biome_rule_options :: use_find :: UseFindOptions >> , # [doc = "Enforce a maximum number of parameters in function definitions.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_max_params : Option < RuleConfiguration < biome_rule_options :: use_max_params :: UseMaxParamsOptions >> , # [doc = "Disallow use* hooks outside of component$ or other use* hooks in Qwik applications.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_qwik_method_usage : Option < RuleConfiguration < biome_rule_options :: use_qwik_method_usage :: UseQwikMethodUsageOptions >> , # [doc = "Disallow unserializable expressions in Qwik dollar ($) scopes.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_qwik_valid_lexical_scope : Option < RuleConfiguration < biome_rule_options :: use_qwik_valid_lexical_scope :: UseQwikValidLexicalScopeOptions >> , # [doc = "Enforce RegExp#exec over String#match if no global flag is provided.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_regexp_exec : Option < RuleConfiguration < biome_rule_options :: use_regexp_exec :: UseRegexpExecOptions >> , # [doc = "Enforce the presence of required scripts in package.json.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_required_scripts : Option < RuleConfiguration < biome_rule_options :: use_required_scripts :: UseRequiredScriptsOptions >> , # [doc = "Enforce the sorting of CSS utility classes.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_sorted_classes : Option < RuleFixConfiguration < biome_rule_options :: use_sorted_classes :: UseSortedClassesOptions >> , # [doc = "Enforce the use of the spread operator over .apply().\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_spread : Option < RuleFixConfiguration < biome_rule_options :: use_spread :: UseSpreadOptions >> , # [doc = "Enforce unique operation names across a GraphQL document.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_unique_graphql_operation_name : Option < RuleConfiguration < biome_rule_options :: use_unique_graphql_operation_name :: UseUniqueGraphqlOperationNameOptions >> , # [doc = "Require all variable definitions to be unique.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_unique_variable_names : Option < RuleConfiguration < biome_rule_options :: use_unique_variable_names :: UseUniqueVariableNamesOptions >> , # [doc = "Enforce consistent defineProps declaration style.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_consistent_define_props_declaration : Option < RuleConfiguration < biome_rule_options :: use_vue_consistent_define_props_declaration :: UseVueConsistentDefinePropsDeclarationOptions >> , # [doc = "Enforce specific order of Vue compiler macros.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_define_macros_order : Option < RuleFixConfiguration < biome_rule_options :: use_vue_define_macros_order :: UseVueDefineMacrosOrderOptions >> , # [doc = "Enforce hyphenated (kebab-case) attribute names in Vue templates.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_hyphenated_attributes : Option < RuleFixConfiguration < biome_rule_options :: use_vue_hyphenated_attributes :: UseVueHyphenatedAttributesOptions >> , # [doc = "Enforce multi-word component names in Vue components.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_multi_word_component_names : Option < RuleConfiguration < biome_rule_options :: use_vue_multi_word_component_names :: UseVueMultiWordComponentNamesOptions >> , # [doc = "Forbids v-bind directives with missing arguments or invalid modifiers.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_bind : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_bind :: UseVueValidVBindOptions >> , # [doc = "Enforce valid usage of v-else.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_else : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_else :: UseVueValidVElseOptions >> , # [doc = "Enforce valid v-else-if directives.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_else_if : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_else_if :: UseVueValidVElseIfOptions >> , # [doc = "Enforce valid v-html directives.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_html : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_html :: UseVueValidVHtmlOptions >> , # [doc = "Enforces valid v-if usage for Vue templates.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_if : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_if :: UseVueValidVIfOptions >> , # [doc = "Enforce valid v-on directives with proper arguments, modifiers, and handlers.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_on : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_on :: UseVueValidVOnOptions >> , # [doc = "Enforce valid v-text Vue directives.\nSee "] # [serde (skip_serializing_if = "Option::is_none")] pub use_vue_valid_v_text : Option < RuleConfiguration < biome_rule_options :: use_vue_valid_v_text :: UseVueValidVTextOptions >> } impl Nursery { const GROUP_NAME: &'static str = "nursery"; pub(crate) const GROUP_RULES: &'static [&'static str] = &[ @@ -4907,6 +4911,7 @@ impl Nursery { "useSortedClasses", "useSpread", "useUniqueGraphqlOperationName", + "useUniqueVariableNames", "useVueConsistentDefinePropsDeclaration", "useVueDefineMacrosOrder", "useVueHyphenatedAttributes", @@ -4991,6 +4996,7 @@ impl Nursery { RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[63]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[64]), RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[65]), + RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[66]), ]; } impl RuleGroupExt for Nursery { @@ -5277,61 +5283,66 @@ impl RuleGroupExt for Nursery { { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[54])); } - if let Some(rule) = self.use_vue_consistent_define_props_declaration.as_ref() + if let Some(rule) = self.use_unique_variable_names.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[55])); } - if let Some(rule) = self.use_vue_define_macros_order.as_ref() + if let Some(rule) = self.use_vue_consistent_define_props_declaration.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[56])); } - if let Some(rule) = self.use_vue_hyphenated_attributes.as_ref() + if let Some(rule) = self.use_vue_define_macros_order.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[57])); } - if let Some(rule) = self.use_vue_multi_word_component_names.as_ref() + if let Some(rule) = self.use_vue_hyphenated_attributes.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[58])); } - if let Some(rule) = self.use_vue_valid_v_bind.as_ref() + if let Some(rule) = self.use_vue_multi_word_component_names.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[59])); } - if let Some(rule) = self.use_vue_valid_v_else.as_ref() + if let Some(rule) = self.use_vue_valid_v_bind.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[60])); } - if let Some(rule) = self.use_vue_valid_v_else_if.as_ref() + if let Some(rule) = self.use_vue_valid_v_else.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[61])); } - if let Some(rule) = self.use_vue_valid_v_html.as_ref() + if let Some(rule) = self.use_vue_valid_v_else_if.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[62])); } - if let Some(rule) = self.use_vue_valid_v_if.as_ref() + if let Some(rule) = self.use_vue_valid_v_html.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[63])); } - if let Some(rule) = self.use_vue_valid_v_on.as_ref() + if let Some(rule) = self.use_vue_valid_v_if.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[64])); } - if let Some(rule) = self.use_vue_valid_v_text.as_ref() + if let Some(rule) = self.use_vue_valid_v_on.as_ref() && rule.is_enabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[65])); } + if let Some(rule) = self.use_vue_valid_v_text.as_ref() + && rule.is_enabled() + { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[66])); + } index_set } fn get_disabled_rules(&self) -> FxHashSet> { @@ -5611,61 +5622,66 @@ impl RuleGroupExt for Nursery { { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[54])); } - if let Some(rule) = self.use_vue_consistent_define_props_declaration.as_ref() + if let Some(rule) = self.use_unique_variable_names.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[55])); } - if let Some(rule) = self.use_vue_define_macros_order.as_ref() + if let Some(rule) = self.use_vue_consistent_define_props_declaration.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[56])); } - if let Some(rule) = self.use_vue_hyphenated_attributes.as_ref() + if let Some(rule) = self.use_vue_define_macros_order.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[57])); } - if let Some(rule) = self.use_vue_multi_word_component_names.as_ref() + if let Some(rule) = self.use_vue_hyphenated_attributes.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[58])); } - if let Some(rule) = self.use_vue_valid_v_bind.as_ref() + if let Some(rule) = self.use_vue_multi_word_component_names.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[59])); } - if let Some(rule) = self.use_vue_valid_v_else.as_ref() + if let Some(rule) = self.use_vue_valid_v_bind.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[60])); } - if let Some(rule) = self.use_vue_valid_v_else_if.as_ref() + if let Some(rule) = self.use_vue_valid_v_else.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[61])); } - if let Some(rule) = self.use_vue_valid_v_html.as_ref() + if let Some(rule) = self.use_vue_valid_v_else_if.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[62])); } - if let Some(rule) = self.use_vue_valid_v_if.as_ref() + if let Some(rule) = self.use_vue_valid_v_html.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[63])); } - if let Some(rule) = self.use_vue_valid_v_on.as_ref() + if let Some(rule) = self.use_vue_valid_v_if.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[64])); } - if let Some(rule) = self.use_vue_valid_v_text.as_ref() + if let Some(rule) = self.use_vue_valid_v_on.as_ref() && rule.is_disabled() { index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[65])); } + if let Some(rule) = self.use_vue_valid_v_text.as_ref() + && rule.is_disabled() + { + index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[66])); + } index_set } #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"] @@ -5916,6 +5932,10 @@ impl RuleGroupExt for Nursery { .use_unique_graphql_operation_name .as_ref() .map(|conf| (conf.level(), conf.get_options())), + "useUniqueVariableNames" => self + .use_unique_variable_names + .as_ref() + .map(|conf| (conf.level(), conf.get_options())), "useVueConsistentDefinePropsDeclaration" => self .use_vue_consistent_define_props_declaration .as_ref() @@ -6023,6 +6043,7 @@ impl From for Nursery { use_sorted_classes: Some(value.into()), use_spread: Some(value.into()), use_unique_graphql_operation_name: Some(value.into()), + use_unique_variable_names: Some(value.into()), use_vue_consistent_define_props_declaration: Some(value.into()), use_vue_define_macros_order: Some(value.into()), use_vue_hyphenated_attributes: Some(value.into()), diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs index 3f54e392bd88..5885df765942 100644 --- a/crates/biome_diagnostics_categories/src/categories.rs +++ b/crates/biome_diagnostics_categories/src/categories.rs @@ -187,8 +187,8 @@ define_categories! { "lint/nursery/noParametersOnlyUsedInRecursion": "https://biomejs.dev/linter/rules/no-parameters-only-used-in-recursion", "lint/nursery/noProto": "https://biomejs.dev/linter/rules/no-proto", "lint/nursery/noReactForwardRef": "https://biomejs.dev/linter/rules/no-react-forward-ref", - "lint/nursery/noScriptUrl": "https://biomejs.dev/linter/rules/no-script-url", "lint/nursery/noReturnAssign": "https://biomejs.dev/linter/rules/no-return-assign", + "lint/nursery/noScriptUrl": "https://biomejs.dev/linter/rules/no-script-url", "lint/nursery/noShadow": "https://biomejs.dev/linter/rules/no-shadow", "lint/nursery/noSyncScripts": "https://biomejs.dev/linter/rules/no-sync-scripts", "lint/nursery/noTernary": "https://biomejs.dev/linter/rules/no-ternary", @@ -230,6 +230,7 @@ define_categories! { "lint/nursery/useSortedClasses": "https://biomejs.dev/linter/rules/use-sorted-classes", "lint/nursery/useSpread": "https://biomejs.dev/linter/rules/no-spread", "lint/nursery/useUniqueGraphqlOperationName": "https://biomejs.dev/linter/rules/use-unique-graphql-operation-name", + "lint/nursery/useUniqueVariableNames": "https://biomejs.dev/linter/rules/use-unique-variable-names", "lint/nursery/useVueConsistentDefinePropsDeclaration": "https://biomejs.dev/linter/rules/use-vue-consistent-define-props-declaration", "lint/nursery/useVueDefineMacrosOrder": "https://biomejs.dev/linter/rules/use-vue-define-macros-order", "lint/nursery/useVueHyphenatedAttributes": "https://biomejs.dev/linter/rules/use-vue-hyphenated-attributes", diff --git a/crates/biome_graphql_analyze/src/lint/nursery.rs b/crates/biome_graphql_analyze/src/lint/nursery.rs index bb65a1f116e4..76faa01402b3 100644 --- a/crates/biome_graphql_analyze/src/lint/nursery.rs +++ b/crates/biome_graphql_analyze/src/lint/nursery.rs @@ -7,4 +7,5 @@ pub mod no_empty_source; pub mod use_consistent_graphql_descriptions; pub mod use_deprecated_date; pub mod use_unique_graphql_operation_name; -declare_lint_group! { pub Nursery { name : "nursery" , rules : [self :: no_empty_source :: NoEmptySource , self :: use_consistent_graphql_descriptions :: UseConsistentGraphqlDescriptions , self :: use_deprecated_date :: UseDeprecatedDate , self :: use_unique_graphql_operation_name :: UseUniqueGraphqlOperationName ,] } } +pub mod use_unique_variable_names; +declare_lint_group! { pub Nursery { name : "nursery" , rules : [self :: no_empty_source :: NoEmptySource , self :: use_consistent_graphql_descriptions :: UseConsistentGraphqlDescriptions , self :: use_deprecated_date :: UseDeprecatedDate , self :: use_unique_graphql_operation_name :: UseUniqueGraphqlOperationName , self :: use_unique_variable_names :: UseUniqueVariableNames ,] } } diff --git a/crates/biome_graphql_analyze/src/lint/nursery/use_unique_variable_names.rs b/crates/biome_graphql_analyze/src/lint/nursery/use_unique_variable_names.rs new file mode 100644 index 000000000000..d1841763ae37 --- /dev/null +++ b/crates/biome_graphql_analyze/src/lint/nursery/use_unique_variable_names.rs @@ -0,0 +1,85 @@ +use std::collections::HashSet; + +use biome_analyze::{ + Ast, Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule, +}; +use biome_console::markup; +use biome_graphql_syntax::GraphqlVariableDefinitions; +use biome_rowan::{AstNode, TokenText}; +use biome_rule_options::use_unique_variable_names::UseUniqueVariableNamesOptions; + +declare_lint_rule! { + /// Require all variable definitions to be unique. + /// + /// A GraphQL operation is only valid if all its variables are uniquely named. + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```graphql,expect_diagnostic + /// query C($x: Int, $x: Int) { + /// __typename + /// } + /// ``` + /// + /// ### Valid + /// + /// ```graphql + /// query C($x: Int, $y: Int) { + /// __typename + /// } + /// ``` + /// + pub UseUniqueVariableNames { + version: "next", + name: "useUniqueVariableNames", + language: "graphql", + recommended: false, + sources: &[RuleSource::EslintGraphql("unique-variable-names").same()], + } +} + +impl Rule for UseUniqueVariableNames { + type Query = Ast; + type State = (); + type Signals = Option; + type Options = UseUniqueVariableNamesOptions; + + fn run(ctx: &RuleContext) -> Option { + let node = ctx.query(); + let mut found: HashSet = HashSet::new(); + + for element in node.elements() { + if let Some(variable) = element.variable().ok() + && let Some(name) = variable.name().ok() + && let Some(value_token) = name.value_token().ok() + { + let string = value_token.token_text(); + if found.contains(&string) { + return Some(()); + } else { + found.insert(string); + } + } + } + + None + } + + fn diagnostic(ctx: &RuleContext, _state: &Self::State) -> Option { + let span = ctx.query().range(); + Some( + RuleDiagnostic::new( + rule_category!(), + span, + markup! { + "Duplicate variable name." + }, + ) + .note(markup! { + "A GraphQL operation is only valid if all its variables are uniquely named. Make sure to name every variable differently." + }), + ) + } +} diff --git a/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/invalid.graphql b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/invalid.graphql new file mode 100644 index 000000000000..d7453dea2b0a --- /dev/null +++ b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/invalid.graphql @@ -0,0 +1,4 @@ +# should generate diagnostics +query A($x: Int, $x: Int, $x: String) { __typename } +query B($x: String, $x: Int) { __typename } +query C($x: Int, $x: Int) { __typename } diff --git a/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/invalid.graphql.snap b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/invalid.graphql.snap new file mode 100644 index 000000000000..39110c4f3851 --- /dev/null +++ b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/invalid.graphql.snap @@ -0,0 +1,68 @@ +--- +source: crates/biome_graphql_analyze/tests/spec_tests.rs +expression: invalid.graphql +--- +# Input +```graphql +# should generate diagnostics +query A($x: Int, $x: Int, $x: String) { __typename } +query B($x: String, $x: Int) { __typename } +query C($x: Int, $x: Int) { __typename } + +``` + +# Diagnostics +``` +invalid.graphql:2:8 lint/nursery/useUniqueVariableNames ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Duplicate variable name. + + 1 │ # should generate diagnostics + > 2 │ query A($x: Int, $x: Int, $x: String) { __typename } + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 3 │ query B($x: String, $x: Int) { __typename } + 4 │ query C($x: Int, $x: Int) { __typename } + + i A GraphQL operation is only valid if all its variables are uniquely named. Make sure to name every variable differently. + + i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. + + +``` + +``` +invalid.graphql:3:8 lint/nursery/useUniqueVariableNames ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Duplicate variable name. + + 1 │ # should generate diagnostics + 2 │ query A($x: Int, $x: Int, $x: String) { __typename } + > 3 │ query B($x: String, $x: Int) { __typename } + │ ^^^^^^^^^^^^^^^^^^^^^ + 4 │ query C($x: Int, $x: Int) { __typename } + 5 │ + + i A GraphQL operation is only valid if all its variables are uniquely named. Make sure to name every variable differently. + + i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. + + +``` + +``` +invalid.graphql:4:8 lint/nursery/useUniqueVariableNames ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Duplicate variable name. + + 2 │ query A($x: Int, $x: Int, $x: String) { __typename } + 3 │ query B($x: String, $x: Int) { __typename } + > 4 │ query C($x: Int, $x: Int) { __typename } + │ ^^^^^^^^^^^^^^^^^^ + 5 │ + + i A GraphQL operation is only valid if all its variables are uniquely named. Make sure to name every variable differently. + + i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. + + +``` diff --git a/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/valid.graphql b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/valid.graphql new file mode 100644 index 000000000000..8877c1e9117f --- /dev/null +++ b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/valid.graphql @@ -0,0 +1,3 @@ +# should not generate diagnostics +query A($x: Int, $y: String) { __typename } +query B($x: String, $y: Int) { __typename } diff --git a/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/valid.graphql.snap b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/valid.graphql.snap new file mode 100644 index 000000000000..3ccd304db073 --- /dev/null +++ b/crates/biome_graphql_analyze/tests/specs/nursery/useUniqueVariableNames/valid.graphql.snap @@ -0,0 +1,11 @@ +--- +source: crates/biome_graphql_analyze/tests/spec_tests.rs +expression: valid.graphql +--- +# Input +```graphql +# should not generate diagnostics +query A($x: Int, $y: String) { __typename } +query B($x: String, $y: Int) { __typename } + +``` diff --git a/crates/biome_rule_options/src/lib.rs b/crates/biome_rule_options/src/lib.rs index 8e6a2a58b396..2219e66dd592 100644 --- a/crates/biome_rule_options/src/lib.rs +++ b/crates/biome_rule_options/src/lib.rs @@ -384,6 +384,7 @@ pub mod use_trim_start_end; pub mod use_unified_type_signatures; pub mod use_unique_element_ids; pub mod use_unique_graphql_operation_name; +pub mod use_unique_variable_names; pub mod use_valid_anchor; pub mod use_valid_aria_props; pub mod use_valid_aria_role; diff --git a/crates/biome_rule_options/src/use_unique_variable_names.rs b/crates/biome_rule_options/src/use_unique_variable_names.rs new file mode 100644 index 000000000000..994f0ac22bfe --- /dev/null +++ b/crates/biome_rule_options/src/use_unique_variable_names.rs @@ -0,0 +1,6 @@ +use biome_deserialize_macros::{Deserializable, Merge}; +use serde::{Deserialize, Serialize}; +#[derive(Default, Clone, Debug, Deserialize, Deserializable, Merge, Eq, PartialEq, Serialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] +pub struct UseUniqueVariableNamesOptions {} diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 6709069aa256..7e8b8d29eecc 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -2137,6 +2137,11 @@ See */ useUniqueGraphqlOperationName?: UseUniqueGraphqlOperationNameConfiguration; /** + * Require all variable definitions to be unique. +See + */ + useUniqueVariableNames?: UseUniqueVariableNamesConfiguration; + /** * Enforce consistent defineProps declaration style. See */ @@ -3780,6 +3785,9 @@ export type UseSpreadConfiguration = export type UseUniqueGraphqlOperationNameConfiguration = | RulePlainConfiguration | RuleWithUseUniqueGraphqlOperationNameOptions; +export type UseUniqueVariableNamesConfiguration = + | RulePlainConfiguration + | RuleWithUseUniqueVariableNamesOptions; export type UseVueConsistentDefinePropsDeclarationConfiguration = | RulePlainConfiguration | RuleWithUseVueConsistentDefinePropsDeclarationOptions; @@ -5272,6 +5280,10 @@ export interface RuleWithUseUniqueGraphqlOperationNameOptions { level: RulePlainConfiguration; options?: UseUniqueGraphqlOperationNameOptions; } +export interface RuleWithUseUniqueVariableNamesOptions { + level: RulePlainConfiguration; + options?: UseUniqueVariableNamesOptions; +} export interface RuleWithUseVueConsistentDefinePropsDeclarationOptions { level: RulePlainConfiguration; options?: UseVueConsistentDefinePropsDeclarationOptions; @@ -6558,6 +6570,7 @@ export interface UseSortedClassesOptions { } export type UseSpreadOptions = {}; export type UseUniqueGraphqlOperationNameOptions = {}; +export type UseUniqueVariableNamesOptions = {}; export interface UseVueConsistentDefinePropsDeclarationOptions { style?: DeclarationStyle; } @@ -7332,8 +7345,8 @@ export type Category = | "lint/nursery/noParametersOnlyUsedInRecursion" | "lint/nursery/noProto" | "lint/nursery/noReactForwardRef" - | "lint/nursery/noScriptUrl" | "lint/nursery/noReturnAssign" + | "lint/nursery/noScriptUrl" | "lint/nursery/noShadow" | "lint/nursery/noSyncScripts" | "lint/nursery/noTernary" @@ -7375,6 +7388,7 @@ export type Category = | "lint/nursery/useSortedClasses" | "lint/nursery/useSpread" | "lint/nursery/useUniqueGraphqlOperationName" + | "lint/nursery/useUniqueVariableNames" | "lint/nursery/useVueConsistentDefinePropsDeclaration" | "lint/nursery/useVueDefineMacrosOrder" | "lint/nursery/useVueHyphenatedAttributes" diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 0f9758885962..e1d5b0f87fea 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -5561,6 +5561,13 @@ { "type": "null" } ] }, + "useUniqueVariableNames": { + "description": "Require all variable definitions to be unique.\nSee ", + "anyOf": [ + { "$ref": "#/$defs/UseUniqueVariableNamesConfiguration" }, + { "type": "null" } + ] + }, "useVueConsistentDefinePropsDeclaration": { "description": "Enforce consistent defineProps declaration style.\nSee ", "anyOf": [ @@ -9732,6 +9739,15 @@ "additionalProperties": false, "required": ["level"] }, + "RuleWithUseUniqueVariableNamesOptions": { + "type": "object", + "properties": { + "level": { "$ref": "#/$defs/RulePlainConfiguration" }, + "options": { "$ref": "#/$defs/UseUniqueVariableNamesOptions" } + }, + "additionalProperties": false, + "required": ["level"] + }, "RuleWithUseValidAnchorOptions": { "type": "object", "properties": { @@ -12757,6 +12773,16 @@ "type": "object", "additionalProperties": false }, + "UseUniqueVariableNamesConfiguration": { + "oneOf": [ + { "$ref": "#/$defs/RulePlainConfiguration" }, + { "$ref": "#/$defs/RuleWithUseUniqueVariableNamesOptions" } + ] + }, + "UseUniqueVariableNamesOptions": { + "type": "object", + "additionalProperties": false + }, "UseValidAnchorConfiguration": { "oneOf": [ { "$ref": "#/$defs/RulePlainConfiguration" },