diff --git a/CHANGELOG.md b/CHANGELOG.md index 74c97e2fd1af..e674aa3cf205 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,28 @@ New entries must be placed in a section entitled `Unreleased`. Read our [guidelines for writing a good changelog entry](https://github.com/biomejs/biome/blob/main/CONTRIBUTING.md#changelog). +## Unreleased + +### Analyzer + +### CLI + +### Configuration + +#### Bug fixes + +- Fix an issue where the JSON schema marked lint rules options as mandatory. Contributed by @ematipico + +### Editors + +### Formatter + +### JavaScript APIs + +### Linter + +### Parser + ## v1.9.3 (2024-10-01) ### CLI 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 a68d5ed96e4b..73f339c8107d 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 @@ -221,7 +221,7 @@ impl Rule for NoBlankTarget { #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct AllowDomainOptions { #[serde(skip_serializing_if = "Vec::is_empty")] /// List of domains to allow `target="_blank"` without `rel="noreferrer"` diff --git a/crates/biome_js_analyze/src/lint/a11y/use_valid_aria_role.rs b/crates/biome_js_analyze/src/lint/a11y/use_valid_aria_role.rs index 1e036c9e7337..fdd0cf52ff7b 100644 --- a/crates/biome_js_analyze/src/lint/a11y/use_valid_aria_role.rs +++ b/crates/biome_js_analyze/src/lint/a11y/use_valid_aria_role.rs @@ -76,7 +76,7 @@ declare_lint_rule! { #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct ValidAriaRoleOptions { pub allow_invalid_roles: Vec, pub ignore_non_dom: bool, diff --git a/crates/biome_js_analyze/src/lint/complexity/no_excessive_cognitive_complexity.rs b/crates/biome_js_analyze/src/lint/complexity/no_excessive_cognitive_complexity.rs index 0d8041ab152e..53598c34aaf7 100644 --- a/crates/biome_js_analyze/src/lint/complexity/no_excessive_cognitive_complexity.rs +++ b/crates/biome_js_analyze/src/lint/complexity/no_excessive_cognitive_complexity.rs @@ -370,7 +370,7 @@ pub struct ComplexityScore { /// Options for the rule `noExcessiveCognitiveComplexity`. #[derive(Clone, Debug, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct ComplexityOptions { /// The maximum complexity score that we allow. Anything higher is considered excessive. pub max_allowed_complexity: NonZeroU8, diff --git a/crates/biome_js_analyze/src/lint/correctness/use_exhaustive_dependencies.rs b/crates/biome_js_analyze/src/lint/correctness/use_exhaustive_dependencies.rs index 38519499846a..a20ba9922e61 100644 --- a/crates/biome_js_analyze/src/lint/correctness/use_exhaustive_dependencies.rs +++ b/crates/biome_js_analyze/src/lint/correctness/use_exhaustive_dependencies.rs @@ -291,7 +291,7 @@ impl Default for HookConfigMaps { /// Options for the rule `useExhaustiveDependencies` #[derive(Clone, Debug, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schemars", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct UseExhaustiveDependenciesOptions { /// Whether to report an error when a dependency is listed in the dependencies array but isn't used. Defaults to true. #[serde(default = "report_unnecessary_dependencies_default")] @@ -318,7 +318,7 @@ fn report_unnecessary_dependencies_default() -> bool { #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schemars", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] #[deserializable(with_validator)] pub struct Hook { /// The name of the hook. diff --git a/crates/biome_js_analyze/src/lint/correctness/use_hook_at_top_level.rs b/crates/biome_js_analyze/src/lint/correctness/use_hook_at_top_level.rs index 7d2c335dee7a..1ab6b8d3c662 100644 --- a/crates/biome_js_analyze/src/lint/correctness/use_hook_at_top_level.rs +++ b/crates/biome_js_analyze/src/lint/correctness/use_hook_at_top_level.rs @@ -553,7 +553,7 @@ impl Rule for UseHookAtTopLevel { /// hook. #[derive(Default, Deserialize, Serialize, Eq, PartialEq, Debug, Clone)] #[cfg_attr(feature = "schemars", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct DeprecatedHooksOptions {} impl Deserializable for DeprecatedHooksOptions { diff --git a/crates/biome_js_analyze/src/lint/correctness/use_import_extensions.rs b/crates/biome_js_analyze/src/lint/correctness/use_import_extensions.rs index 1d5670bbf3aa..53c09213b93d 100644 --- a/crates/biome_js_analyze/src/lint/correctness/use_import_extensions.rs +++ b/crates/biome_js_analyze/src/lint/correctness/use_import_extensions.rs @@ -126,7 +126,7 @@ declare_lint_rule! { #[derive(Clone, Debug, Default, Deserializable, Deserialize, Serialize, Eq, PartialEq)] #[cfg_attr(feature = "schemars", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct UseImportExtensionsOptions { /// A map of custom import extension mappings, where the key is the inspected file extension, /// and the value is a pair of `module` extension and `component` import extension @@ -135,7 +135,7 @@ pub struct UseImportExtensionsOptions { #[derive(Debug, Clone, Default, Deserializable, Deserialize, Serialize, Eq, PartialEq)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct SuggestedExtensionMapping { /// Extension that should be used for module imports pub module: String, diff --git a/crates/biome_js_analyze/src/lint/nursery/no_restricted_imports.rs b/crates/biome_js_analyze/src/lint/nursery/no_restricted_imports.rs index bb0c46c3a034..76002050d0bd 100644 --- a/crates/biome_js_analyze/src/lint/nursery/no_restricted_imports.rs +++ b/crates/biome_js_analyze/src/lint/nursery/no_restricted_imports.rs @@ -39,7 +39,7 @@ declare_lint_rule! { /// Options for the rule `noRestrictedImports`. #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct RestrictedImportsOptions { /// A list of names that should trigger the rule #[serde(skip_serializing_if = "FxHashMap::is_empty")] diff --git a/crates/biome_js_analyze/src/lint/nursery/no_restricted_types.rs b/crates/biome_js_analyze/src/lint/nursery/no_restricted_types.rs index 52de4cc3c732..e1d39dc949bb 100644 --- a/crates/biome_js_analyze/src/lint/nursery/no_restricted_types.rs +++ b/crates/biome_js_analyze/src/lint/nursery/no_restricted_types.rs @@ -124,7 +124,7 @@ impl Rule for NoRestrictedTypes { PartialEq, )] #[cfg_attr(feature = "schemars", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct NoRestrictedTypesOptions { types: FxHashMap, } @@ -140,7 +140,7 @@ pub struct NoRestrictedTypesOptions { PartialEq, )] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct CustomRestrictedTypeOptions { message: String, #[serde(rename = "use")] diff --git a/crates/biome_js_analyze/src/lint/nursery/use_component_export_only_modules.rs b/crates/biome_js_analyze/src/lint/nursery/use_component_export_only_modules.rs index 03b7914e01cd..e11484ba5100 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_component_export_only_modules.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_component_export_only_modules.rs @@ -113,7 +113,7 @@ declare_lint_rule! { #[derive(Debug, Clone, Deserialize, Deserializable, Eq, PartialEq, Serialize, Default)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct UseComponentExportOnlyModulesOptions { /// Allows the export of constants. This option is for environments that support it, such as [Vite](https://vitejs.dev/) #[serde(default)] diff --git a/crates/biome_js_analyze/src/lint/nursery/use_consistent_member_accessibility.rs b/crates/biome_js_analyze/src/lint/nursery/use_consistent_member_accessibility.rs index df8122604d05..5df90b9537a2 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_consistent_member_accessibility.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_consistent_member_accessibility.rs @@ -223,7 +223,7 @@ declare_lint_rule! { #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct ConsistentMemberAccessibilityOptions { pub accessibility: Accessibility, } @@ -247,7 +247,8 @@ impl Rule for UseConsistentMemberAccessibility { fn run(ctx: &RuleContext) -> Self::Signals { let node = ctx.query(); let accessibility = node.accessibility_modifier(); - match ctx.options().accessibility { + let options = ctx.options(); + match &options.accessibility { Accessibility::NoPublic => accessibility .filter(|accessibility| accessibility.is_public()) .map(|accessibility| accessibility.range()), @@ -257,7 +258,12 @@ impl Rule for UseConsistentMemberAccessibility { } fn diagnostic(ctx: &RuleContext, range: &Self::State) -> Option { - let (diag_msg, note_msg) = match ctx.options().accessibility { + let options = ctx.options(); + // let accessibility_option = match &options.accessibility { + // None => &Accessibility::default(), + // Some(option) => option, + // }; + let (diag_msg, note_msg) = match &options.accessibility { Accessibility::NoPublic => ( markup! { "The ""public"" modifier is disallowed." diff --git a/crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/options.rs b/crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/options.rs index 34339021a3f7..42637d925fcd 100644 --- a/crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/options.rs +++ b/crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/options.rs @@ -12,7 +12,7 @@ const CLASS_ATTRIBUTES: [&str; 2] = ["class", "className"]; #[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)] #[cfg_attr(feature = "schemars", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct UtilityClassSortingOptions { /// Additional attributes that will be sorted. #[serde(skip_serializing_if = "Option::is_none")] 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 2e9161d93482..d8b27ab87dac 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 @@ -137,7 +137,7 @@ const BILLING_AND_SHIPPING_ADDRESS: &[&str; 11] = &[ #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct UseValidAutocompleteOptions { /// `input` like custom components that should be checked. pub input_components: Vec, diff --git a/crates/biome_js_analyze/src/lint/style/no_restricted_globals.rs b/crates/biome_js_analyze/src/lint/style/no_restricted_globals.rs index 250dc66ad7d6..88d4e026842a 100644 --- a/crates/biome_js_analyze/src/lint/style/no_restricted_globals.rs +++ b/crates/biome_js_analyze/src/lint/style/no_restricted_globals.rs @@ -59,7 +59,7 @@ const RESTRICTED_GLOBALS: [&str; 2] = ["event", "error"]; /// Options for the rule `noRestrictedGlobals`. #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct RestrictedGlobalsOptions { /// A list of names that should trigger the rule #[serde(skip_serializing_if = "Vec::is_empty")] diff --git a/crates/biome_js_analyze/src/lint/style/use_consistent_array_type.rs b/crates/biome_js_analyze/src/lint/style/use_consistent_array_type.rs index c91d72519cef..7ef4312420ca 100644 --- a/crates/biome_js_analyze/src/lint/style/use_consistent_array_type.rs +++ b/crates/biome_js_analyze/src/lint/style/use_consistent_array_type.rs @@ -480,7 +480,7 @@ where #[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)] #[cfg_attr(feature = "schemars", derive(JsonSchema))] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] pub struct ConsistentArrayTypeOptions { pub syntax: ConsistentArrayType, } diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 1adc459d76b6..169db8b54401 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -2306,8 +2306,8 @@ export interface NoLabelWithoutControlOptions { labelComponents?: string[]; } export interface ValidAriaRoleOptions { - allowInvalidRoles: string[]; - ignoreNonDom: boolean; + allowInvalidRoles?: string[]; + ignoreNonDom?: boolean; } /** * Options for the rule `noExcessiveCognitiveComplexity`. @@ -2316,7 +2316,7 @@ export interface ComplexityOptions { /** * The maximum complexity score that we allow. Anything higher is considered excessive. */ - maxAllowedComplexity: number; + maxAllowedComplexity?: number; } /** * Options for the rule `useExhaustiveDependencies` @@ -2339,7 +2339,7 @@ export interface UseImportExtensionsOptions { /** * A map of custom import extension mappings, where the key is the inspected file extension, and the value is a pair of `module` extension and `component` import extension */ - suggestedExtensions: {}; + suggestedExtensions?: {}; } /** * Options for the rule `noRestrictedImports`. @@ -2351,7 +2351,7 @@ export interface RestrictedImportsOptions { paths: {}; } export interface NoRestrictedTypesOptions { - types: {}; + types?: {}; } export interface UseComponentExportOnlyModulesOptions { /** @@ -2364,7 +2364,7 @@ export interface UseComponentExportOnlyModulesOptions { allowExportNames: string[]; } export interface ConsistentMemberAccessibilityOptions { - accessibility: Accessibility; + accessibility?: Accessibility; } export interface UtilityClassSortingOptions { /** @@ -2380,7 +2380,7 @@ export interface UseValidAutocompleteOptions { /** * `input` like custom components that should be checked. */ - inputComponents: string[]; + inputComponents?: string[]; } /** * Options for the rule `noRestrictedGlobals`. @@ -2392,7 +2392,7 @@ export interface RestrictedGlobalsOptions { deniedGlobals: string[]; } export interface ConsistentArrayTypeOptions { - syntax: ConsistentArrayType; + syntax?: ConsistentArrayType; } /** * Rule's options. @@ -2465,7 +2465,7 @@ For example, for React's `useEffect()` hook, the dependencies index is 1. /** * The name of the hook. */ - name: string; + name?: string; /** * Whether the result of the hook is stable. diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 522ac842bf49..4b5dbd85ea20 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -360,7 +360,6 @@ }, "AllowDomainOptions": { "type": "object", - "required": ["allowDomains"], "properties": { "allowDomains": { "description": "List of domains to allow `target=\"_blank\"` without `rel=\"noreferrer\"`", @@ -643,10 +642,10 @@ "ComplexityOptions": { "description": "Options for the rule `noExcessiveCognitiveComplexity`.", "type": "object", - "required": ["maxAllowedComplexity"], "properties": { "maxAllowedComplexity": { "description": "The maximum complexity score that we allow. Anything higher is considered excessive.", + "default": 15, "type": "integer", "format": "uint8", "minimum": 1.0 @@ -676,9 +675,11 @@ }, "ConsistentArrayTypeOptions": { "type": "object", - "required": ["syntax"], "properties": { - "syntax": { "$ref": "#/definitions/ConsistentArrayType" } + "syntax": { + "default": "shorthand", + "allOf": [{ "$ref": "#/definitions/ConsistentArrayType" }] + } }, "additionalProperties": false }, @@ -690,9 +691,11 @@ }, "ConsistentMemberAccessibilityOptions": { "type": "object", - "required": ["accessibility"], "properties": { - "accessibility": { "$ref": "#/definitions/Accessibility" } + "accessibility": { + "default": "noPublic", + "allOf": [{ "$ref": "#/definitions/Accessibility" }] + } }, "additionalProperties": false }, @@ -1202,10 +1205,9 @@ }, "CustomRestrictedTypeOptions": { "type": "object", - "required": ["message"], "properties": { - "message": { "type": "string" }, - "use": { "type": ["string", "null"] } + "message": { "default": "", "type": "string" }, + "use": { "default": null, "type": ["string", "null"] } }, "additionalProperties": false }, @@ -1460,23 +1462,29 @@ }, "Hook": { "type": "object", - "required": ["name"], "properties": { "closureIndex": { "description": "The \"position\" of the closure function, starting from zero.\n\nFor example, for React's `useEffect()` hook, the closure index is 0.", + "default": null, "type": ["integer", "null"], "format": "uint8", "minimum": 0.0 }, "dependenciesIndex": { "description": "The \"position\" of the array of dependencies, starting from zero.\n\nFor example, for React's `useEffect()` hook, the dependencies index is 1.", + "default": null, "type": ["integer", "null"], "format": "uint8", "minimum": 0.0 }, - "name": { "description": "The name of the hook.", "type": "string" }, + "name": { + "description": "The name of the hook.", + "default": "", + "type": "string" + }, "stableResult": { "description": "Whether the result of the hook is stable.\n\nSet to `true` to mark the identity of the hook's return value as stable, or use a number/an array of numbers to mark the \"positions\" in the return array as stable.\n\nFor example, for React's `useRef()` hook the value would be `true`, while for `useState()` it would be `[1]`.", + "default": null, "anyOf": [ { "$ref": "#/definitions/StableHookResult" }, { "type": "null" } @@ -2040,9 +2048,9 @@ }, "NoRestrictedTypesOptions": { "type": "object", - "required": ["types"], "properties": { "types": { + "default": {}, "type": "object", "additionalProperties": { "$ref": "#/definitions/CustomRestrictedType" @@ -2531,7 +2539,6 @@ "RestrictedGlobalsOptions": { "description": "Options for the rule `noRestrictedGlobals`.", "type": "object", - "required": ["deniedGlobals"], "properties": { "deniedGlobals": { "description": "A list of names that should trigger the rule", @@ -2550,7 +2557,6 @@ "RestrictedImportsOptions": { "description": "Options for the rule `noRestrictedImports`.", "type": "object", - "required": ["paths"], "properties": { "paths": { "description": "A list of names that should trigger the rule", @@ -3440,14 +3446,15 @@ }, "SuggestedExtensionMapping": { "type": "object", - "required": ["component", "module"], "properties": { "component": { "description": "Extension that should be used for component file imports", + "default": "", "type": "string" }, "module": { "description": "Extension that should be used for module imports", + "default": "", "type": "string" } }, @@ -4025,10 +4032,10 @@ }, "UseImportExtensionsOptions": { "type": "object", - "required": ["suggestedExtensions"], "properties": { "suggestedExtensions": { "description": "A map of custom import extension mappings, where the key is the inspected file extension, and the value is a pair of `module` extension and `component` import extension", + "default": {}, "type": "object", "additionalProperties": { "$ref": "#/definitions/SuggestedExtensionMapping" @@ -4045,10 +4052,10 @@ }, "UseValidAutocompleteOptions": { "type": "object", - "required": ["inputComponents"], "properties": { "inputComponents": { "description": "`input` like custom components that should be checked.", + "default": [], "type": "array", "items": { "type": "string" } } @@ -4066,6 +4073,7 @@ "properties": { "attributes": { "description": "Additional attributes that will be sorted.", + "default": ["class", "className"], "type": ["array", "null"], "items": { "type": "string" } }, @@ -4085,10 +4093,13 @@ }, "ValidAriaRoleOptions": { "type": "object", - "required": ["allowInvalidRoles", "ignoreNonDom"], "properties": { - "allowInvalidRoles": { "type": "array", "items": { "type": "string" } }, - "ignoreNonDom": { "type": "boolean" } + "allowInvalidRoles": { + "default": [], + "type": "array", + "items": { "type": "string" } + }, + "ignoreNonDom": { "default": false, "type": "boolean" } }, "additionalProperties": false },