Repository: biomejs/biome (language: rust)

Issue:
💅 incorrect unused error
### Environment information

```bash
CLI:
  Version:                      1.9.3
  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:           "v22.9.0"
  JS_RUNTIME_NAME:              "node"
  NODE_PACKAGE_MANAGER:         "bun/1.1.29"

Biome Configuration:
  Status:                       Loaded successfully
  Formatter disabled:           false
  Linter disabled:              false
  Organize imports disabled:    false
  VCS disabled:                 true

Linter:
  JavaScript enabled:           true
  JSON enabled:                 true
  CSS enabled:                  true
  GraphQL enabled:              false
  Recommended:                  true
  All:                          false
  Enabled rules:
  suspicious/noClassAssign
  suspicious/noCatchAssign
  suspicious/noUnsafeNegation
  complexity/useLiteralKeys
  style/useImportType
  complexity/noMultipleSpacesInRegularExpressionLiterals
  a11y/useValidLang
  complexity/noUselessEmptyExport
  suspicious/useNamespaceKeyword
  suspicious/useValidTypeof
  suspicious/noAssignInExpressions
  a11y/useValidAriaRole
  correctness/noConstantCondition
  a11y/useAriaActivedescendantWithTabindex
  style/useDefaultParameterLast
  complexity/noEmptyTypeParameters
  correctness/noConstructorReturn
  style/useSelfClosingElements
  suspicious/noDuplicateParameters
  suspicious/noDuplicateSelectorsKeyframeBlock
  correctness/noUnknownProperty
  style/useTemplate
  correctness/noUnusedLabels
  complexity/noUselessTernary
  correctness/noUnreachableSuper
  suspicious/noCompareNegZero
  correctness/noSwitchDeclarations
  a11y/noAutofocus
  correctness/noUnsafeOptionalChaining
  correctness/noConstAssign
  suspicious/noControlCharactersInRegex
  complexity/noUselessTypeConstraint
  style/noVar
  suspicious/noDoubleEquals
  suspicious/noRedundantUseStrict
  style/useLiteralEnumMembers
  suspicious/noGlobalIsNan
  suspicious/noEmptyInterface
  suspicious/noConstEnum
  suspicious/noMisleadingCharacterClass
  correctness/noPrecisionLoss
  a11y/noLabelWithoutControl
  suspicious/noRedeclare
  correctness/noStringCaseMismatch
  correctness/noSetterReturn
  correctness/noInvalidConstructorSuper
  suspicious/noImplicitAnyLet
  suspicious/noFallthroughSwitchClause
  suspicious/noUnsafeDeclarationMerging
  complexity/noUselessThisAlias
  correctness/noUnreachable
  a11y/useKeyWithClickEvents
  suspicious/noDuplicateObjectKeys
  complexity/noThisInStatic
  complexity/useOptionalChain
  correctness/noInnerDeclarations
  style/noParameterAssign
  suspicious/noDuplicateCase
  a11y/useValidAnchor
  complexity/useRegexLiterals
  correctness/noSelfAssign
  correctness/noInvalidBuiltinInstantiation
  style/useShorthandFunctionType
  suspicious/noShadowRestrictedNames
  correctness/noInvalidDirectionInLinearGradient
  suspicious/noImportantInKeyframe
  a11y/useMediaCaption
  complexity/noUselessLabel
  complexity/noUselessCatch
  correctness/noUnsafeFinally
  a11y/useAriaPropsForRole
  correctness/noNonoctalDecimalEscape
  style/useEnumInitializers
  a11y/useHtmlLang
  suspicious/noDuplicateTestHooks
  complexity/noStaticOnlyClass
  style/useWhile
  complexity/useArrowFunction
  style/noInferrableTypes
  a11y/noNoninteractiveTabindex
  complexity/useSimpleNumberKeys
  correctness/useYield
  a11y/noInteractiveElementToNoninteractiveRole
  style/useNumericLiterals
  correctness/noUnnecessaryContinue
  suspicious/noApproximativeNumericConstant
  suspicious/noImportAssign
  suspicious/noLabelVar
  correctness/noGlobalObjectCalls
  suspicious/useDefaultSwitchClauseLast
  correctness/noUnknownUnit
  correctness/useImportExtensions
  a11y/useAltText
  suspicious/noSuspiciousSemicolonInJsx
  a11y/useIframeTitle
  complexity/noBannedTypes
  a11y/noSvgWithoutTitle
  correctness/noVoidElementsWithChildren
  style/useAsConstAssertion
  correctness/useJsxKeyInIterable
  style/useExportType
  complexity/noUselessLoneBlockStatements
  suspicious/noDebugger
  style/noArguments
  suspicious/noMisleadingInstantiator
  a11y/useValidAriaValues
  a11y/useFocusableInteractive
  suspicious/noCommentText
  correctness/noUnmatchableAnbSelector
  suspicious/noDuplicateJsxProps
  suspicious/noGlobalAssign
  a11y/noPositiveTabindex
  correctness/noEmptyPattern
  complexity/noExcessiveNestedTestSuites
  security/noDangerouslySetInnerHtmlWithChildren
  a11y/useKeyWithMouseEvents
  suspicious/noExtraNonNullAssertion
  suspicious/noShorthandPropertyOverrides
  correctness/noRenderReturnValue
  security/noGlobalEval
  style/useConst
  suspicious/useGetterReturn
  a11y/noRedundantRoles
  complexity/useFlatMap
  correctness/useIsNan
  correctness/noUnusedVariables
  suspicious/noGlobalIsFinite
  suspicious/noSelfCompare
  suspicious/noThenProperty
  suspicious/noAsyncPromiseExecutor
  suspicious/noDuplicateFontNames
  security/noDangerouslySetInnerHtml
  style/useNodejsImportProtocol
  a11y/noDistractingElements
  suspicious/noArrayIndexKey
  complexity/noWith
  suspicious/noDuplicateClassMembers
  complexity/noExtraBooleanCast
  performance/noAccumulatingSpread
  a11y/useValidAriaProps
  a11y/noRedundantAlt
  correctness/noChildrenProp
  correctness/noUnknownFunction
  correctness/noInvalidPositionAtImportRule
  suspicious/noConfusingLabels
  suspicious/noPrototypeBuiltins
  suspicious/noConfusingVoidType
  suspicious/noFocusedTests
  a11y/useButtonType
  a11y/useSemanticElements
  a11y/noAriaUnsupportedElements
  correctness/noInvalidGridAreas
  correctness/noFlatMapIdentity
  a11y/noBlankTarget
  a11y/useHeadingContent
  suspicious/noSparseArray
  correctness/useValidForDirection
  correctness/noVoidTypeReturn
  correctness/noInvalidUseBeforeDeclaration
  a11y/noAriaHiddenOnFocusable
  a11y/useGenericFontNames
  correctness/noUnknownMediaFeatureName
  a11y/useAnchorContent
  complexity/noUselessRename
  style/useBlockStatements
  style/useNumberNamespace
  complexity/noUselessConstructor
  a11y/noAccessKey
  correctness/noUnusedFunctionParameters
  style/noUnusedTemplateLiteral
  complexity/noUselessSwitchCase
  style/useExponentiationOperator
  style/useSingleVarDeclarator
  suspicious/noExportsInTest
  a11y/noNoninteractiveElementToInteractiveRole
  style/noCommaOperator
  suspicious/noDuplicateAtImportRules
  suspicious/useIsArray
  a11y/noHeaderScope
  complexity/noUselessFragments
  suspicious/noMisrefactoredShorthandAssign
  suspicious/noEmptyBlock
  complexity/noForEach
  correctness/noUnusedImports
  suspicious/noFunctionAssign

Workspace:
  Open Documents:               0
```


### Rule name

lint/correctness/noUnusedVariables

### Playground link

https://biomejs.dev/playground/?lintRules=all&code=ZQB4AHAAbwByAHQAIABjAGwAYQBzAHMAIABGAG8AbwAgAHsACgAgACAAYgBhAHIAKABuAGEAbQBlADoAIABzAHQAcgBpAG4AZwAsACAAXwBjAGwAYQBzAHMAOgAgAG4AZQB3ACAAKABuAGEAbQBlADoAIABzAHQAcgBpAG4AZwApACAAPQA%2BACAAYQBuAHkAKQAgAHsACgAgACAAIAAgAHIAZQB0AHUAcgBuACAAbgBhAG0AZQAKACAAIAB9AAoAfQA%3D

### Expected result

The first parameter to `bar` is incorrectly reported as unused. This is caused by the type of the second parameter, which is a class with the same named parameter in its constructor.

### Code of Conduct

- [X] I agree to follow Biome's Code of Conduct


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02ae34164731..8e1af31d6cd5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -103,18 +103,33 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
 
   Contributed by @Conaclos
 
-- Fixes [#4059](https://github.com/biomejs/biome/issues/4059), the rule [noUselessFragments](https://biomejs.dev/linter/rules/no-useless-fragments/) now correctly handles fragments containing HTML escapes (e.g. `&nbsp;`) inside expression escapes `{ ... }`.
-The following code is no longer reported:
+- [noUselessFragments](https://biomejs.dev/linter/rules/no-useless-fragments/) now correctly handles fragments containing HTML escapes (e.g. `&nbsp;`) inside expression escapes `{ ... }` ([#4059](https://github.com/biomejs/biome/issues/4059)).
 
-```jsx
-function Component() {
-  return (
-    <div key={index}>{line || <>&nbsp;</>}</div>
-  )
-}
-```
+  The following code is no longer reported:
+
+  ```jsx
+  function Component() {
+    return (
+      <div key={index}>{line || <>&nbsp;</>}</div>
+    )
+  }
+  ```
 
-Contributed by @fireairforce
+  Contributed by @fireairforce
+
+- [noUnusedFunctionParameters](https://biomejs.dev/linter/rules/no-unused-function-parameters/) and [noUnusedVariables](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports a parameter as unused when another parameter has a constructor type with the same parameter name ([#4227](https://github.com/biomejs/biome/issues/4227)).
+
+  In the following code, the `name` parameter is no longer reported as unused.
+
+  ```ts
+  export class Foo {
+    bar(name: string, _class: new (name: string) => any) {
+      return name
+    }
+  }
+  ```
+
+  Contributed by @Conaclos
 
 ### Parser
 
diff --git a/crates/biome_js_semantic/src/events.rs b/crates/biome_js_semantic/src/events.rs
index bed7ce3f0efb..f2eef59b50e9 100644
--- a/crates/biome_js_semantic/src/events.rs
+++ b/crates/biome_js_semantic/src/events.rs
@@ -439,7 +439,9 @@ impl SemanticEventExtractor {
         let node = node.syntax();
         if matches!(
             node.kind(),
-            JsSyntaxKind::TS_FUNCTION_TYPE | JsSyntaxKind::TS_MAPPED_TYPE
+            JsSyntaxKind::TS_CONSTRUCTOR_TYPE
+                | JsSyntaxKind::TS_FUNCTION_TYPE
+                | JsSyntaxKind::TS_MAPPED_TYPE
         ) {
             self.push_scope(
                 node.text_trimmed_range(),
@@ -811,7 +813,9 @@ impl SemanticEventExtractor {
         let node = node.syntax();
         if matches!(
             node.kind(),
-            JsSyntaxKind::TS_FUNCTION_TYPE | JsSyntaxKind::TS_MAPPED_TYPE
+            JsSyntaxKind::TS_CONSTRUCTOR_TYPE
+                | JsSyntaxKind::TS_FUNCTION_TYPE
+                | JsSyntaxKind::TS_MAPPED_TYPE
         ) {
             self.pop_scope(node.text_trimmed_range());
         }
diff --git a/crates/biome_js_semantic/src/semantic_model/builder.rs b/crates/biome_js_semantic/src/semantic_model/builder.rs
index ac8c76dba880..753232abab9f 100644
--- a/crates/biome_js_semantic/src/semantic_model/builder.rs
+++ b/crates/biome_js_semantic/src/semantic_model/builder.rs
@@ -100,6 +100,7 @@ impl SemanticModelBuilder {
             | JS_FOR_IN_STATEMENT
             | JS_SWITCH_STATEMENT
             | JS_CATCH_CLAUSE
+            | TS_CONSTRUCTOR_TYPE
             | TS_FUNCTION_TYPE
             | TS_MAPPED_TYPE => {
                 self.scope_node_by_range


Test patch:
diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedFunctionParameters/issue4227.ts b/crates/biome_js_analyze/tests/specs/correctness/noUnusedFunctionParameters/issue4227.ts
new file mode 100644
index 000000000000..8be4d8d9baa5
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedFunctionParameters/issue4227.ts
@@ -0,0 +1,5 @@
+class Foo {
+    bar(name: string, _class: new (name: string) => any) {
+        return name
+    }
+}
\ No newline at end of file
diff --git a/crates/biome_js_analyze/tests/specs/correctness/noUnusedFunctionParameters/issue4227.ts.snap b/crates/biome_js_analyze/tests/specs/correctness/noUnusedFunctionParameters/issue4227.ts.snap
new file mode 100644
index 000000000000..f92663464864
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/correctness/noUnusedFunctionParameters/issue4227.ts.snap
@@ -0,0 +1,12 @@
+---
+source: crates/biome_js_analyze/tests/spec_tests.rs
+expression: issue4227.ts
+---
+# Input
+```ts
+class Foo {
+    bar(name: string, _class: new (name: string) => any) {
+        return name
+    }
+}
+```