biomejs / biome

A toolchain for web projects, aimed to provide functionalities to maintain them. Biome offers formatter and linter, usable via CLI and LSP.
https://biomejs.dev
Apache License 2.0
15.17k stars 473 forks source link

📝 "quoteProperties": "preserve" doesn't work as expected #4329

Closed deanrih closed 2 weeks ago

deanrih commented 2 weeks ago

Environment information

CLI:
Version:                      1.9.4
Color support:                true

Platform:
CPU Architecture:             x86_64
OS:                           linux

Environment:
BIOME_LOG_PATH:               unset
BIOME_LOG_PREFIX_NAME:        unset
BIOME_CONFIG_PATH:            unset
NO_COLOR:                     unset
TERM:                         "xterm-256color"
JS_RUNTIME_VERSION:           "v23.0.0"
JS_RUNTIME_NAME:              "node"
NODE_PACKAGE_MANAGER:         "bun/1.1.30"

Biome Configuration:
Status:                       Loaded successfully
Formatter disabled:           false
Linter disabled:              false
Organize imports disabled:    false
VCS disabled:                 false

Formatter:
Format with errors:           false
Indent style:                 Tab
Indent width:                 2
Line ending:                  Lf
Line width:                   80
Attribute position:           Auto
Bracket spacing:              BracketSpacing(true)
Ignore:                       []
Include:                      []

JavaScript Formatter:
Enabled:                      false
JSX quote style:              Double
Quote properties:             Preserve
Trailing commas:              All
Semicolons:                   Always
Arrow parentheses:            Always
Bracket spacing:              BracketSpacing(true)
Bracket same line:            false
Quote style:                  Double
Indent style:                 unset
Indent width:                 unset
Line ending:                  unset
Line width:                   unset
Attribute position:           Auto

JSON Formatter:
Enabled:                      true
Indent style:                 unset
Indent width:                 unset
Line ending:                  unset
Line width:                   unset
Trailing Commas:              unset

CSS Formatter:
Enabled:                      true
Indent style:                 unset
Indent width:                 unset
Line ending:                  unset
Line width:                   unset
Quote style:                  Double

GraphQL Formatter:
Enabled:                      false
Indent style:                 unset
Indent width:                 unset
Line ending:                  unset
Line width:                   unset
Bracket spacing:              unset
Quote style:                  unset

Workspace:
Open Documents:               0

Configuration

{
    "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
    "formatter": {
        "attributePosition": "auto",
        "bracketSpacing": true,
        "enabled": true,
        "formatWithErrors": false,
        "indentStyle": "tab",
        "indentWidth": 2,
        "lineEnding": "lf",
        "lineWidth": 80,
        "useEditorconfig": true
    },
    "javascript": {
        "formatter": {
            "arrowParentheses": "always",
            "attributePosition": "auto",
            "bracketSameLine": false,
            "bracketSpacing": true,
            "jsxQuoteStyle": "double",
            "quoteProperties": "preserve",
            "quoteStyle": "double",
            "semicolons": "always",
            "trailingCommas": "all"
        }
    },
    "linter": {
        "enabled": true,
        "rules": {
            "a11y": {
                "noAccessKey": "off",
                "noAriaHiddenOnFocusable": "off",
                "noAriaUnsupportedElements": "off",
                "noAutofocus": "off",
                "noBlankTarget": "off",
                "noDistractingElements": "off",
                "noHeaderScope": "off",
                "noPositiveTabindex": "off",
                "noRedundantAlt": "off",
                "noRedundantRoles": "off",
                "useAltText": "off",
                "useAnchorContent": "off",
                "useAriaActivedescendantWithTabindex": "off",
                "useAriaPropsForRole": "off",
                "useButtonType": "off",
                "useHeadingContent": "off",
                "useHtmlLang": "off",
                "useIframeTitle": "off",
                "useKeyWithClickEvents": "off",
                "useKeyWithMouseEvents": "off",
                "useMediaCaption": "off",
                "useSemanticElements": "off",
                "useValidAnchor": "off",
                "useValidAriaProps": "off",
                "useValidAriaRole": "off",
                "useValidLang": "off"
            },
            "complexity": {
                "noBannedTypes": "error",
                "noExtraBooleanCast": "error",
                "noForEach": "off",
                "noMultipleSpacesInRegularExpressionLiterals": "error",
                "noStaticOnlyClass": "off",
                "noUselessCatch": "error",
                "noUselessFragments": "off",
                "noUselessRename": "off",
                "noUselessSwitchCase": "off",
                "noUselessTypeConstraint": "error",
                "noVoid": "off",
                "noWith": "error",
                "useDateNow": "off",
                "useFlatMap": "off"
            },
            "correctness": {
                "noChildrenProp": "off",
                "noConstAssign": "error",
                "noConstantCondition": "error",
                "noEmptyCharacterClassInRegex": "error",
                "noEmptyPattern": "error",
                "noGlobalObjectCalls": "error",
                "noInnerDeclarations": "off",
                "noInvalidBuiltinInstantiation": "off",
                "noInvalidConstructorSuper": "error",
                "noNewSymbol": "off",
                "noNonoctalDecimalEscape": "error",
                "noPrecisionLoss": "error",
                "noSelfAssign": "error",
                "noSetterReturn": "error",
                "noSwitchDeclarations": "error",
                "noUndeclaredVariables": "error",
                "noUnreachable": "error",
                "noUnreachableSuper": "error",
                "noUnsafeFinally": "error",
                "noUnsafeOptionalChaining": "error",
                "noUnusedLabels": "error",
                "noUnusedPrivateClassMembers": "error",
                "noUnusedVariables": "error",
                "noVoidElementsWithChildren": "off",
                "useArrayLiterals": "off",
                "useIsNan": "error",
                "useJsxKeyInIterable": "off",
                "useValidForDirection": "error",
                "useYield": "error"
            },
            "recommended": false,
            "security": {
                "noDangerouslySetInnerHtml": "off",
                "noGlobalEval": "off"
            },
            "style": {
                "noDefaultExport": "off",
                "noDoneCallback": "off",
                "noInferrableTypes": "off",
                "noNamespace": "error",
                "noParameterAssign": "off",
                "noVar": "off",
                "useAsConstAssertion": "error",
                "useConsistentArrayType": "off",
                "useConsistentBuiltinInstantiation": "off",
                "useDefaultParameterLast": "off",
                "useExplicitLengthCheck": "off",
                "useForOf": "off",
                "useNodejsImportProtocol": "off",
                "useNumberNamespace": "off",
                "useShorthandFunctionType": "off",
                "useThrowNewError": "off"
            },
            "suspicious": {
                "noAsyncPromiseExecutor": "error",
                "noCatchAssign": "error",
                "noClassAssign": "error",
                "noCommentText": "off",
                "noCompareNegZero": "error",
                "noConsole": "off",
                "noControlCharactersInRegex": "error",
                "noDebugger": "error",
                "noDoubleEquals": "off",
                "noDuplicateCase": "error",
                "noDuplicateClassMembers": "error",
                "noDuplicateJsxProps": "off",
                "noDuplicateObjectKeys": "error",
                "noDuplicateParameters": "error",
                "noEmptyBlockStatements": "error",
                "noExplicitAny": "error",
                "noExtraNonNullAssertion": "error",
                "noFallthroughSwitchClause": "error",
                "noFunctionAssign": "error",
                "noGlobalAssign": "error",
                "noImportAssign": "error",
                "noMisleadingCharacterClass": "error",
                "noMisleadingInstantiator": "error",
                "noPrototypeBuiltins": "error",
                "noRedeclare": "error",
                "noSelfCompare": "off",
                "noShadowRestrictedNames": "error",
                "noSparseArray": "error",
                "noThenProperty": "off",
                "noUnsafeDeclarationMerging": "error",
                "noUnsafeNegation": "error",
                "useDefaultSwitchClauseLast": "off",
                "useErrorMessage": "off",
                "useGetterReturn": "error",
                "useIsArray": "off",
                "useNumberToFixedDigitsArgument": "off",
                "useValidTypeof": "error"
            }
        }
    },
    "organizeImports": {
        "enabled": true
    },
    "overrides": [
        {
            "include": [
                "*.ts",
                "*.tsx",
                "*.mts",
                "*.cts"
            ],
            "linter": {
                "rules": {
                    "correctness": {
                        "noConstAssign": "off",
                        "noGlobalObjectCalls": "off",
                        "noInvalidConstructorSuper": "off",
                        "noNewSymbol": "off",
                        "noSetterReturn": "off",
                        "noUndeclaredVariables": "off",
                        "noUnreachable": "off",
                        "noUnreachableSuper": "off"
                    },
                    "style": {
                        "noArguments": "error",
                        "noVar": "error",
                        "useConst": "error"
                    },
                    "suspicious": {
                        "noDuplicateClassMembers": "off",
                        "noDuplicateObjectKeys": "off",
                        "noDuplicateParameters": "off",
                        "noFunctionAssign": "off",
                        "noImportAssign": "off",
                        "noRedeclare": "off",
                        "noUnsafeNegation": "off",
                        "useGetterReturn": "off"
                    }
                }
            }
        }
    ],
    "vcs": {
        "clientKind": "git",
        "enabled": true,
        "useIgnoreFile": true
    }
}

Playground link

https://biomejs.dev/playground/?code=LwAvACAAYgBpAG8AbQBlAC0AaQBnAG4AbwByAGUAIABmAG8AcgBtAGEAdAA6ACAALQAKAGkAbgB0AGUAcgBmAGEAYwBlACAASgBXAFQASABlAGEAZABlAHIAUwBwAGUAYwAgAHsACgAJAC8AKgAqAAoACQAgACoAIABBAGwAZwBvAHIAaQB0AGgAbQAKAAkAIAAqAC8ACgAJACIAYQBsAGcAIgA6ACAAIgBIAFMAMgA1ADYAIgAgAHwAIAAiAEgAUwAzADgANAAiACAAfAAgACIASABTADUAMQAyACIAOwAKAAkALwAqACoACgAJACAAKgAgAEoAVwBLACAAUwBlAHQAIABVAFIATAAKAAkAIAAqAC8ACgAJACIAagBrAHUAIgA6ACAAcwB0AHIAaQBuAGcAOwAKAAkAIgBqAHcAawAiADoAIABzAHQAcgBpAG4AZwA7ACAAIAAgACAAIAAgAC8ALwAgACgASgBTAE8ATgAgAFcAZQBiACAASwBlAHkAKQAgAEgAZQBhAGQAZQByACAAUABhAHIAYQBtAGUAdABlAHIACgAJACIAawBpAGQAIgA6ACAAcwB0AHIAaQBuAGcAOwAgACAAIAAgACAAIAAvAC8AIAAoAEsAZQB5ACAASQBEACkAIABIAGUAYQBkAGUAcgAgAFAAYQByAGEAbQBlAHQAZQByAAoACQAiAHgANQB1ACIAOgAgAHMAdAByAGkAbgBnADsAIAAgACAAIAAgACAALwAvACAAKABYAC4ANQAwADkAIABVAFIATAApACAASABlAGEAZABlAHIAIABQAGEAcgBhAG0AZQB0AGUAcgAKAAkAIgB4ADUAYwAiADoAIABzAHQAcgBpAG4AZwA7ACAAIAAgACAAIAAgAC8ALwAgACgAWAAuADUAMAA5ACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAQwBoAGEAaQBuACkAIABIAGUAYQBkAGUAcgAgAFAAYQByAGEAbQBlAHQAZQByAAoACQAiAHgANQB0ACIAOgAgAHMAdAByAGkAbgBnADsAIAAgACAAIAAgACAALwAvACAAKABYAC4ANQAwADkAIABDAGUAcgB0AGkAZgBpAGMAYQB0AGUAIABTAEgAQQAtADEAIABUAGgAdQBtAGIAcAByAGkAbgB0ACkACgAJACIAeAA1AHQAIwBTADIANQA2ACIAOgAgAHMAdAByAGkAbgBnADsAIAAvAC8AIAAoAFgALgA1ADAAOQAgAEMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAFMASABBAC0AMgA1ADYAIABUAGgAdQBtAGIAcAByAGkAbgB0ACkACgAJAC8AKgAqAAoACQAgACoAIABUAHkAcABlAAoACQAgACoALwAKAAkAIgB0AHkAcAAiAD8AOgAgACIASgBXAFQAIgA7AAoACQAvACoAKgAKAAkAIAAqACAAQwBvAG4AdABlAG4AdAAgAFQAeQBwAGUACgAJACAAKgAvAAoACQAiAGMAdAB5ACIAOgAgAHMAdAByAGkAbgBnADsACgAJACIAYwByAGkAdAAiADoAIABzAHQAcgBpAG4AZwA7ACAAIAAgACAAIAAvAC8AIAAoAEMAcgBpAHQAaQBjAGEAbAApACAASABlAGEAZABlAHIAIABQAGEAcgBhAG0AZQB0AGUAcgAKAH0ACgAKAGUAeABwAG8AcgB0ACAAZgB1AG4AYwB0AGkAbwBuACAAZwBlAG4AZQByAGEAdABlAFQAbwBrAGUAbgA8AFQAIABlAHgAdABlAG4AZABzACAAUgBlAGMAbwByAGQAPABzAHQAcgBpAG4AZwAsACAAdQBuAGsAbgBvAHcAbgA%2BAD4AKAAKAAkAcABhAHkAbABvAGEAZAA6ACAAVAAsAAoACQBrAGUAeQA6ACAAcwB0AHIAaQBuAGcALAAKACkAOgAgAHMAdAByAGkAbgBnACAAewAKACAAIAAgACAALwAvACAAZQB4AHAAZQBjAHQAZQBkACwAIABuAGUAZQBkACAAdABvACAAdQBzAGUAIABiAGkAbwBtAGUALQBpAGcAbgBvAHIAZQAKACAAIAAgACAALwAvACAAYgBpAG8AbQBlAC0AaQBnAG4AbwByAGUAIABmAG8AcgBtAGEAdAA6ACAALQAKACAAIAAgACAAYwBvAG4AcwB0ACAAaABlAGEAZABlAHIARQB4AHAAZQBjAHQAZQBkADoAIABKAFcAVABIAGUAYQBkAGUAcgBTAHAAZQBjACAAPQAgAHsACgAgACAAIAAgACAAIAAgACAAIgBhAGwAZwAiADoAIAAiAEgAUwAyADUANgAiACwACgAgACAAIAAgAH0AOwAKACAAIAAgACAALwAvACAAYQBjAHQAdQBhAGwACgAJAGMAbwBuAHMAdAAgAGgAZQBhAGQAZQByADoAIABKAFcAVABIAGUAYQBkAGUAcgBTAHAAZQBjACAAPQAgAHsACgAJAAkAIgBhAGwAZwAiADoAIAAiAEgAUwAyADUANgAiACwACgAJAH0AOwAKAAoAIAAgACAAIABjAG8AbgBzAHQAIABoAGUAYQBkAGUAcgBBAGwAZwAgAD0AIABoAGUAYQBkAGUAcgBbACIAYQBsAGcAIgBdADsACgB9AA%3D%3D

Code of Conduct

deanrih commented 2 weeks ago

I was expecting "preserve" means preserve any quote around the properties if it has any, but instead biome removes it anyway, or is it intended behaviour? if so, is there a way to "preserve" the quote around object properties?

Conaclos commented 2 weeks ago

I think you are mistaken: the formatter doesn't remove them if you enabled set preserve on quoteProperties. It is certainly the useLIteralKeys linter rule that removes them. Try to disable complexity/useLIteralKeys.

deanrih commented 2 weeks ago

I think you are mistaken: the formatter doesn't remove them if you enabled set preserve on quoteProperties. It is certainly the useLIteralKeys linter rule that removes them. Try to disable complexity/useLIteralKeys.

if by disabling you mean setting it to "off" then I did and it still remove the quote, also I don't think useLiteralKeys should affect formatting, when useLiteralKeys is on, it only shows an error on something like

const someObject = {
    name: "My Name",
};

console.log(someObject["name"]);
                      ^^^^^^^^

it will show an error under ["name"] and suggest to use .name instead, doing format doesn't delete quote, and also when the useLiteralKeys having

interface Test {
    "propOne": string;
}

doesn't show any error like useLiteralKeys supposed to, and furthermore, it's linter, it shouldn't remove or affect the decision to remove anything, so I'm not sure if it's really caused by complexity/useLiteralKeys

Conaclos commented 2 weeks ago

when useLiteralKeys is on, it only shows an error on something like

Oh yeah, we changed the rule some versions ago to avoid conflicts with qyoteProperties. Ignore my previous comment.

Thus, we need a reproduction. The Playground link that you posted has a biome-ignore comment and is not properly set (quotePropeties is not set to preserve). If I remove the biome-ignore-comment and set quotePropeties to preserve, then Biome outputs the expected behavior: it preserves the quotes.

github-actions[bot] commented 2 weeks ago

Hello @deanrih, please provide a minimal reproduction. You can use one of the following options:

Issues marked with S-Needs repro will be closed if they have no activity within 3 days.

deanrih commented 2 weeks ago

Thus, we need a reproduction.

The playground does actually work, and I forgot to set the quoteProperties setting there, but I set it in my local machine but the behaviour is differen, it has a good chance that this is a version issue, is there a way to change version in the playground? I'm having a hard time finding it and the only thing that suggest currently used version on the playground is just beneath the Formatter section tab Biome <commit hash>

Conaclos commented 2 weeks ago

The Playground uses the main branch of the Biome repository. We released Biome 1.9.4 yesterday, thus you should get the same behavior with Biome 1.9.4.

deanrih commented 2 weeks ago

well, I'm on 1.9.4

[deanrih@aqua project]$ bunx biome --version
Version: 1.9.4
ematipico commented 2 weeks ago

Thus, we need a reproduction.

The playground does actually work, and I forgot to set the quoteProperties setting there, but I set it in my local machine but the behaviour is differen, it has a good chance that this is a version issue, is there a way to change version in the playground? I'm having a hard time finding it and the only thing that suggest currently used version on the playground is just beneath the Formatter section tab Biome <commit hash>

Maybe it's best if you create a minimal reproduction in a repository, so we can have a look. Maybe there's some misconfiguration, or a bug in the CLI that doesn't affect the playground. This message tells you how to create a minimal repository using our CLI

deanrih commented 2 weeks ago

Okay, while I was creating minimal reproduction repository, I found some inconsistencies with my main repo (which is why it took me some time), after fighting through I nailed down the problem, it's most likely the CLI couldn't find the configuration file or I put the configuration file wrong between git rebase or something, probably the reason why I didn't suspect this at start because some of rule worked just fine (probably before the file moved after some git rebase) and then I hit a condition where I require the quoteProperties feature, so it's safe to say, it's all working as intended. Sorry for the inconvenience.