Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

📝 stripping parenthesis breaks jsdoc types #4799

Closed
1 task done
JakobJingleheimer opened this issue Dec 27, 2024 · 11 comments
Closed
1 task done

📝 stripping parenthesis breaks jsdoc types #4799

JakobJingleheimer opened this issue Dec 27, 2024 · 11 comments
Labels
S-Needs triage Status: this issue needs to be triaged

Comments

@JakobJingleheimer
Copy link

JakobJingleheimer commented Dec 27, 2024

Environment information

CLI:
  Version:                      1.9.4
  Color support:                true

Platform:
  CPU Architecture:             aarch64
  OS:                           macos

Environment:
  BIOME_LOG_PATH:               unset
  BIOME_LOG_PREFIX_NAME:        unset
  BIOME_CONFIG_PATH:            unset
  NO_COLOR:                     unset
  TERM:                         "xterm-256color"
  JS_RUNTIME_VERSION:           "v23.5.0"
  JS_RUNTIME_NAME:              "node"
  NODE_PACKAGE_MANAGER:         "npm/10.9.2"

Biome Configuration:
  Status:                       Loaded successfully
  Formatter disabled:           false
  Linter disabled:              false
  Organize imports disabled:    true
  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:             AsNeeded
  Trailing commas:              All
  Semicolons:                   Always
  Arrow parentheses:            Always
  Bracket spacing:              unset
  Bracket same line:            false
  Quote style:                  Single
  Indent style:                 unset
  Indent width:                 unset
  Line ending:                  unset
  Line width:                   unset
  Attribute position:           unset

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",
	"files": {
		"ignore": ["**/fixture/**", "**/fixture.*"],
		"include": ["**/*.js", "**/*.mjs", "**/*.cjs", "**/*.css", "**/*.json"]
	},
	"formatter": {
		"enabled": true,
		"useEditorconfig": true
	},
	"linter": {
		"rules": {
			"style": {
				"useImportType": "error",
				"useNodeAssertStrict": "error",
				"useNodejsImportProtocol": "error",
				"useTemplate": "off"
			},
			"suspicious": {
				"noExplicitAny": "error",
				"noEmptyBlock": "error",
				"noDuplicateAtImportRules": "error",
				"noDuplicateObjectKeys": "error"
			},
			"correctness": {
				"noUnusedVariables": "off",
				"useArrayLiterals": "off",
				"noUnknownFunction": "error"
			}
		}
	},
	"javascript": {
		"formatter": {
			"arrowParentheses": "always",
			"semicolons": "always",
			"quoteStyle": "single",
			"trailingCommas": "all"
		},
		"linter": {
			"enabled": true
		}
	},
	"organizeImports": {
		"enabled": false
	},
	"json": {
		"formatter": {
			"enabled": true
		}
	},
	"vcs": {
		"enabled": true,
		"clientKind": "git"
	}
}

Playground link

https://biomejs.dev/playground/?code=aQBtAHAAbwByAHQAIAB7ACAAcwBwAGEAdwBuACAAfQAgAGYAcgBvAG0AIAAnAG4AbwBkAGUAOgBjAGgAaQBsAGQAXwBwAHIAbwBjAGUAcwBzACcAOwAKAAoALwAqACoACgAgACoAIABAAHAAYQByAGEAbQAgAHsALgAuAC4AUABhAHIAYQBtAGUAdABlAHIAcwA8AHQAeQBwAGUAbwBmACAAcwBwAGEAdwBuAD4AfQAgAGEAcgBnAHMACgAgACoALwAKAGUAeABwAG8AcgB0ACAAZgB1AG4AYwB0AGkAbwBuACAAcwBwAGEAdwBuAFAAcgBvAG0AaQBzAGkAZgBpAGUAZAAoAC4ALgAuAGEAcgBnAHMAKQAgAHsACgAJAGwAZQB0ACAAcwB0AGQAZQByAHIAIAA9ACAAJwAnADsACgAJAGwAZQB0ACAAcwB0AGQAbwB1AHQAIAA9ACAAJwAnADsACgAKAAkAYwBvAG4AcwB0ACAAYwBoAGkAbABkACAAPQAgAHMAcABhAHcAbgAoAC4ALgAuAGEAcgBnAHMAKQA7AAoACQBjAGgAaQBsAGQALgBzAHQAZABlAHIAcgA%2FAC4AcwBlAHQARQBuAGMAbwBkAGkAbgBnACgAJwB1AHQAZgA4ACcAKQA7AAoACQBjAGgAaQBsAGQALgBzAHQAZABlAHIAcgA%2FAC4AbwBuACgAJwBkAGEAdABhACcALAAgACgAZABhAHQAYQApACAAPQA%2BACAAewAKAAkACQBzAHQAZABlAHIAcgAgACsAPQAgAGQAYQB0AGEAOwAKAAkAfQApADsACgAJAGMAaABpAGwAZAAuAHMAdABkAG8AdQB0AD8ALgBzAGUAdABFAG4AYwBvAGQAaQBuAGcAKAAnAHUAdABmADgAJwApADsACgAJAGMAaABpAGwAZAAuAHMAdABkAG8AdQB0AD8ALgBvAG4AKAAnAGQAYQB0AGEAJwAsACAAKABkAGEAdABhACkAIAA9AD4AIAB7AAoACQAJAHMAdABkAG8AdQB0ACAAKwA9ACAAZABhAHQAYQA7AAoACQB9ACkAOwAKAAoACQAvACoAKgAKAAkAIAAqACAAQAB0AHkAcABlACAAewBQAHIAbwBtAGkAcwBlADwAewAgAGMAbwBkAGUAOgAgAG4AdQBtAGIAZQByACAAfAAgAG4AdQBsAGwALAAgAHMAaQBnAG4AYQBsADoAIABOAG8AZABlAEoAUwAuAFMAaQBnAG4AYQBsAHMAIAB8ACAAbgB1AGwAbAAsACAAcwB0AGQAZQByAHIAOgAgAHMAdAByAGkAbgBnACwAIABzAHQAZABvAHUAdAA6ACAAcwB0AHIAaQBuAGcAIAB9AD4AfQAKAAkAIAAqAC8ACgAJAHIAZQB0AHUAcgBuACAAKABuAGUAdwAgAFAAcgBvAG0AaQBzAGUAKAAoAHIAZQBzAG8AbAB2AGUALAAgAHIAZQBqAGUAYwB0ACkAIAA9AD4AIAB7AAoACQAJAGMAaABpAGwAZAAuAG8AbgAoACcAYwBsAG8AcwBlACcALAAgACgAYwBvAGQAZQAsACAAcwBpAGcAbgBhAGwAKQAgAD0APgAgAHsACgAJAAkACQByAGUAcwBvAGwAdgBlACgAewAKAAkACQAJAAkAYwBvAGQAZQAsAAoACQAJAAkACQBzAGkAZwBuAGEAbAAsAAoACQAJAAkACQBzAHQAZABlAHIAcgAsAAoACQAJAAkACQBzAHQAZABvAHUAdAAsAAoACQAJAAkAfQApADsACgAJAAkAfQApADsACgAJAAkAYwBoAGkAbABkAC4AbwBuACgAJwBlAHIAcgBvAHIAJwAsACAAKABjAG8AZABlACwAIABzAGkAZwBuAGEAbAApACAAPQA%2BACAAewAKAAkACQAJAHIAZQBqAGUAYwB0ACgAewAKAAkACQAJAAkAYwBvAGQAZQAsAAoACQAJAAkACQBzAGkAZwBuAGEAbAAsAAoACQAJAAkACQBzAHQAZABlAHIAcgAsAAoACQAJAAkACQBzAHQAZABvAHUAdAAsAAoACQAJAAkAfQApADsACgAJAAkAfQApADsACgAJAH0AKQApADsACgB9AAoA

Code of Conduct

  • I agree to follow Biome's Code of Conduct
@JakobJingleheimer JakobJingleheimer added the S-Needs triage Status: this issue needs to be triaged label Dec 27, 2024
@JakobJingleheimer
Copy link
Author

JakobJingleheimer commented Dec 27, 2024

But also, this behaviour is obnoxious in general, and I want to globally disable it. Sometimes extra parentheses greatly improve legibility, and I do not want to fight tooling to get get out of the way.

@arendjr
Copy link
Contributor

arendjr commented Jan 1, 2025

I'm not sure how exactly this breaks JSDoc types, but we don't have special support for JSDoc in any case, and we don't intend to add new formatter options: https://biomejs.dev/formatter/option-philosophy/

I don't think this issue will be picked up any time soon, sorry.

@arendjr arendjr closed this as not planned Won't fix, can't repro, duplicate, stale Jan 1, 2025
@JakobJingleheimer
Copy link
Author

Seemingly unnecessary parentheses are required around whatever is be casted in TypeScript via jsdocs:

https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#casts

Your formatter removes them, breaking the types.

JSDocs and TypeScript are huge—way bigger than biome, and they're already used in millions of projects. If you force a choice between them and biome, you'll surely lose.

This is not about one preference versus another—biome's opinion breaks things, which makes it objectively wrong.

@ematipico
Copy link
Member

@JakobJingleheimer

Unfortunately, we aren't in a position where a formatter can be aware of types (and TSDoc types) inside the code. And, as you can see, Prettier does the same as Biome.

You're better off disabling the formatter for that line

@JakobJingleheimer
Copy link
Author

You don't need to be aware of types in the least. Stop the behaviour altogether.

Prettier is also wrong; more things being wrong doesn't make it more right.

It's not a one-off problem, like in this particular case, this line of code looks better with more parentheses, for which disabling the line is suitable. All instances of this behave the same way, and you break it.

@rivy
Copy link

rivy commented Jan 12, 2025

I strongly agree with @JakobJingleheimer.

biome should have an option to preserve parentheses.

Parentheses, even when not technically necessary, are many times a boon to code readability. And code readability is really the prime reason for (re-)formatters. This is especially true for coders who work with multiple languages, between which parentheses requirements and operator precedence can differ. Parentheses can just make certain code so much easier to quickly understand.

I realize there are other development priorities and that you may not agree, but that's my position.

But the current functionality does break things and is, again IMO, a poor choice. This should be re-opened, discussed, and fixed.

@JakobJingleheimer
Copy link
Author

There is also the accessibility issue: parentheses make things easier to read for the poorly sighted. So projects that consider accessibility cannot use biome.

@dyc3
Copy link
Contributor

dyc3 commented Jan 12, 2025

I agree that parentheses can help with code readability, but I don't understand how the current behavior breaks code. I tried playing around with the code in the playground, and the code you linked to in the typescript docs. Biome already handles the casting comment case just fine. Additionally, we don't remove parenthesis that occur inside expressions.

@JakobJingleheimer
Copy link
Author

I'm not sure what you mean. In both examples, the parentheses do get stripped. The first example is the sort of repo, so I don't know why biome would always break it for only me (as well as in the playground link of my OP).

For the second link, it does remove them (contrary to you saying it doesn't), and there's even a comment saying they will get removed:

image

@dyc3
Copy link
Contributor

dyc3 commented Jan 13, 2025

Ah my bad, got my clipboards mixed up posting that last comment. I've updated the playgrounds in my previous comment to be more clear.

For easier viewing:

Example 1:

/**
 * @type {number | string}
 */
const numberOrString = Math.random() < 0.5 ? "hello" : 100;
// these do not get removed, which preserves the jsdoc type casting
const typeAssertedNumber = /** @type {number} */ (numberOrString);

Example 2:

const a = 4;
const b = 7;
// these parentheses get removed because they encompass the entire expression
const c = (a + b + 4);
// these parentheses do not because they are inside an expression
const d = a + (b + 4);

In the playground originally posted, the parentheses surrounding the expression below are removed because they surround the entire expression:

// before
return (new Promise(...))
// after
return new Promise(...)

This does not "break" the code. It functions exactly as it did before, and type checking still works.

@JakobJingleheimer
Copy link
Author

In the playground originally posted, the parentheses surrounding the expression below are removed because they surround the entire expression:

// before
return (new Promise(...))
// after
return new Promise(...)

This does not "break" the code. It functions exactly as it did before, and type checking still works.

It breaks the tsdoc, which breaks type-checking.

There are also other, simpler occurrances where biome removes the parens, breaking tsdoc and type-checking. For instance, in @nodejs-loaders (I haven't removed biome yet)

https://github.com/nodejs-loaders/nodejs-loaders/blob/main/packages/alias/alias.mjs#L28-L30

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-Needs triage Status: this issue needs to be triaged
Projects
None yet
Development

No branches or pull requests

5 participants