Skip to content

JS-1394 Fix S6767 false positive for decorator-consumed props#6947

Open
sonar-nigel[bot] wants to merge 44 commits into
masterfrom
fix/JS-1394-fix-fp-on-s6767-props-reported-unused-when-consumed-through-a-typescriptes-decorator-gpt-5.5
Open

JS-1394 Fix S6767 false positive for decorator-consumed props#6947
sonar-nigel[bot] wants to merge 44 commits into
masterfrom
fix/JS-1394-fix-fp-on-s6767-props-reported-unused-when-consumed-through-a-typescriptes-decorator-gpt-5.5

Conversation

@sonar-nigel
Copy link
Copy Markdown
Contributor

@sonar-nigel sonar-nigel Bot commented Apr 30, 2026

Relates to JS-1394

This updates S6767 false-positive handling in two narrowly-scoped cases: typed decorator callbacks that the upstream react/no-unused-prop-types rule does not fully credit, and React class non-props generics such as State or Snapshot that the upstream rule can misclassify as props in React.Component<Props, State, Snapshot> declarations. The remediation suppresses reports only when the callback's first parameter is proven to be the component props type and the callback reads the reported prop or forwards the whole props object, or when the reported declaration is proven to be a non-props generic rather than a props contract.

  • Covers both track(callback)(Component) and @track(callback) shapes, including whole-props forwarding from typed callbacks.
  • Suppresses React class non-props generic declarations that upstream reports as unused props when a third generic parameter is present.
  • Keeps unrelated decorator callbacks reportable by requiring a TypeScript props-type match, and avoids hiding legitimate reports when the same declaration is also used as real props elsewhere.

Vibe Bot added 3 commits April 30, 2026 09:46
Tests cover props consumed through decorator-factory callbacks,
including direct member reads and whole typed props forwarding to
helper logic. They also verify unrelated decorator callbacks still
allow unused props to be reported.

Relates to JS-1394
Suppress unused prop reports when a React component is wrapped by a
decorator factory whose callback consumes the reported prop directly or
forwards the callback's whole props object to helper logic. The
implementation follows the approved JS-1394 direction by keeping the
suppression component-local, using composable pattern checks, and moving
component variable lookup into shared React helpers.

Relates to JS-1394
Remove the export from getComponentIdentifier because it is only used
internally by the React rule helper. This keeps the helper available for
getComponentVariable while resolving the unused export reported by knip.
@sonar-nigel
Copy link
Copy Markdown
Contributor Author

sonar-nigel Bot commented Apr 30, 2026

Rule Profile

Field Value
Rule S6767 — Unused React typed props should be removed
Severity / type Minor CODE_SMELL
Sonar Way Yes
Scope Main
interface CardProps {
  title: string;
  subtitle: string;
}

function Card(props: CardProps) {
  return <div>{props.title}</div>;
}

False Positive Pattern

The false positives now covered by this branch fall into two narrow families. The first is decorator-based indirect prop usage: a React prop is not read inside the component body, but is consumed by typed decorator machinery through a callback whose first parameter is the component props object. The second is an upstream typing mismatch: in React.Component<Props, State, Snapshot> declarations, react/no-unused-prop-types can treat the State or Snapshot declaration as if it were a props contract and report its members as unused props.

function DecoratorFactoryComponent(props: DecoratorFactoryProps) {
  return <div />;
}

track((props: DecoratorFactoryProps) => ({
  context_module: props.contextModule,
  user_id: props.userId,
}))(DecoratorFactoryComponent);
interface AnchorState {
  activeLink: null | string;
}
interface AnchorProps {
  href?: string;
}
interface AnchorSnapshot {
  scrollTop: number;
}

class Anchor extends React.Component<AnchorProps, AnchorState, AnchorSnapshot> {
  render() {
    const { activeLink } = this.state;
    return <a href={this.props.href}>{activeLink}</a>;
  }
}

False Negative Risk

The risk is bounded by reporting by default unless TypeScript proves that the decorator callback's first parameter has the same declared props type as the component, and by suppressing non-props generic reports only when the reported declaration is proven to belong to a React class state/snapshot slot rather than a real props contract. This avoids suppressing unrelated metadata callbacks and avoids hiding legitimate reports when the same declaration is also used as props elsewhere.

interface SharedType {
  unused: string;
}
interface Snapshot {
  scrollTop: number;
}

class PropsOwner extends React.Component<SharedType> {
  render() {
    return <div />;
  }
}

class StateOwner extends React.Component<{}, SharedType, Snapshot> {
  render() {
    return <div>{this.state.unused}</div>;
  }
}

Fix Summary

The fix adds two focused S6767 suppressions: one for indirect prop usage through typed decorator callbacks, and one for upstream reports on React class non-props generics. It resolves the component binding used at the decorator site, matches callback parameter types against the component props type, and separately classifies reported type declarations as props vs state/snapshot before suppressing.

  • Reuses shared React helper logic for component binding lookup, including named function expressions, plus TypeScript declaration matching for non-props generic detection.
  • Recognizes direct member reads and whole typed-props forwarding in decorator callbacks, while keeping unrelated metadata callbacks reportable by default.
  • Adds valid and invalid regression tests around decorator shapes, third-generic state/snapshot misreports, and mixed props/non-props reuse boundaries.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 30, 2026

Ruling Report

Code no longer flagged (21 issues)

S6767

ant-design/components/input/ClearableLabeledInput.tsx:32

    30 |   disabled?: boolean;
    31 |   direction?: DirectionType;
>   32 |   focused?: boolean;
    33 |   readOnly?: boolean;
    34 |   bordered: boolean;

ant-design/components/input/ClearableLabeledInput.tsx:40

    38 | /** This props only for input. */
    39 | export interface ClearableInputProps extends BasicProps {
>   40 |   size?: SizeType;
    41 |   suffix?: React.ReactNode;
    42 |   prefix?: React.ReactNode;

ant-design/components/input/ClearableLabeledInput.tsx:42

    40 |   size?: SizeType;
    41 |   suffix?: React.ReactNode;
>   42 |   prefix?: React.ReactNode;
    43 |   addonBefore?: React.ReactNode;
    44 |   addonAfter?: React.ReactNode;

ant-design/components/input/ClearableLabeledInput.tsx:43

    41 |   suffix?: React.ReactNode;
    42 |   prefix?: React.ReactNode;
>   43 |   addonBefore?: React.ReactNode;
    44 |   addonAfter?: React.ReactNode;
    45 |   triggerFocus?: () => void;

ant-design/components/input/ClearableLabeledInput.tsx:44

    42 |   prefix?: React.ReactNode;
    43 |   addonBefore?: React.ReactNode;
>   44 |   addonAfter?: React.ReactNode;
    45 |   triggerFocus?: () => void;
    46 |   status?: InputStatus;

ant-design/components/input/ClearableLabeledInput.tsx:45

    43 |   addonBefore?: React.ReactNode;
    44 |   addonAfter?: React.ReactNode;
>   45 |   triggerFocus?: () => void;
    46 |   status?: InputStatus;
    47 | }

desktop/app/src/ui/app-menu/app-menu.tsx:41

    39 |    * menu will receive focus.
    40 |    */
>   41 |   readonly openedWithAccessKey: boolean
    42 | 
    43 |   /**

desktop/app/src/ui/branches/branch-list.tsx:30

    28 |    * See IBranchesState.defaultBranch
    29 |    */
>   30 |   readonly defaultBranch: Branch | null
    31 | 
    32 |   /**

desktop/app/src/ui/branches/branch-list.tsx:35

    33 |    * The currently checked out branch or null if HEAD is detached
    34 |    */
>   35 |   readonly currentBranch: Branch | null
    36 | 
    37 |   /**

desktop/app/src/ui/branches/branch-list.tsx:45

    43 |    * See IBranchesState.recentBranches
    44 |    */
>   45 |   readonly recentBranches: ReadonlyArray<Branch>
    46 | 
    47 |   /**

...and 11 more

New issues flagged (2 issues)

S6767

eigen/src/app/Scenes/Artwork/Components/CommercialInformation.tsx:34

    32 |   me: CommercialInformation_me$data
    33 |   hasStarted?: boolean
>   34 |   tracking?: TrackingProp
    35 |   biddingEndAt?: string
    36 |   hasBeenExtended?: boolean

eigen/src/app/Scenes/Artwork/Components/CommercialInformation.tsx:37

    35 |   biddingEndAt?: string
    36 |   hasBeenExtended?: boolean
>   37 |   refetchArtwork: () => void
    38 |   setAuctionTimerState?: (auctionTimerState: string) => void
    39 | }
📋 View full report

Code no longer flagged (21)

S6767

New issues flagged (2)

S6767

github-actions Bot and others added 4 commits April 30, 2026 14:35
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
s6767-props-reported-unused-when-consumed-through-a-typescriptes-decorator-gpt-5.5
Add unit tests to cover S6767 decorator and React helper fallback paths.
This improves code coverage to meet the quality gate threshold.
Make unused exported type aliases module-local in the analysis and gRPC
packages. The affected types are still available internally where they shape
exported APIs, but they are no longer reported by knip as unused exports.
@sonar-nigel sonar-nigel Bot marked this pull request as ready for review May 1, 2026 05:06
@sonar-review-alpha
Copy link
Copy Markdown
Contributor

sonar-review-alpha Bot commented May 1, 2026

Summary

This PR adds five targeted false-positive suppressions to rule S6767 (unused prop types) to handle indirect prop consumption patterns that the upstream react/no-unused-prop-types rule doesn't fully recognize.

The new escape hatches:

  1. React class non-props generic declarations (State, Snapshot) that upstream misclassifies as unused props
  2. Typed decorator callbacks that consume props indirectly (both factory and annotation forms)
  3. Whole-props handoff through helper functions or spread operators
  4. Props forwarding to custom (non-React) superclasses in component constructors
  5. Props consumed in forwardRef callbacks (already existed, now clarified)

Scope: The fixes are narrowly scoped — decorator callbacks must have TypeScript-verified props types matching the component, and React class non-props reports are only suppressed when a third generic parameter is present. This keeps legitimate unused-prop reports visible while eliminating false positives observed in real projects (ant-design, desktop, eigen, etc.).

Impact: Test expectations across multiple projects show dozens of false-positive suppressions, confirming these patterns are widely used in production TypeScript React code.

What reviewers should know

Start here: Read decorator.ts to see the five escape hatches and their decision tree in shouldSuppressUnusedPropType() (lines 113–154).

Key implementation details:

  • decorator-indirect-prop-usage.ts is the largest addition — handles both @decorator(callback) and decoratorFactory(...)(Component) patterns, with type verification via isSameDeclaredPropsType() (line 175)
  • react-non-props-usage.ts leverages TypeScript's type checker to distinguish State/Snapshot from Props in class declarations — only suppresses when the reported type is truly non-props (line 107)
  • whole-props-usage.ts is shared logic now reused by decorator callbacks (line 26 import) to detect buildPayload(props) and spread patterns
  • New helpers are isolated per escape hatch with minimal cross-file dependencies

Non-obvious decisions:

  • Decorator callbacks use caching (WeakMap by component node) to avoid repeated type checks — see react-non-props-usage.ts lines 43–48
  • The decorator callback must introduce its own props parameter (not close over the original) to need special handling — see comment at lines 167–171 in decorator-indirect-prop-usage.ts
  • Generic type equality (with any, unknown, nested generics) is handled by areSameTypeDeclarations() in the type helper

Testing: Unit tests show edge cases like generic aliases, named function expressions, method signatures, and literal-keyed properties — all now correctly handled.


  • Generate Walkthrough
  • Generate Diagram

🗣️ Give feedback

sonar-review-alpha[bot]

This comment was marked as resolved.

Vibe Bot added 2 commits May 1, 2026 05:13
…rc/jsts/rules/helpers/react.ts

Comment: **Logic duplication:** The two `if` blocks in `getComponentIdentifier` are structurally identical — both check `componentNode.id` and return it. The only difference is the set of node types in the condition. They can be merged into one:

```typescript
if (
  (componentNode.type === 'ClassDeclaration' ||
   componentNode.type === 'FunctionDeclaration' ||
   componentNode.type === 'ClassExpression' ||
   componentNode.type === 'FunctionExpression') &&
  componentNode.id
) {
  return componentNode.id;
}
```

As written, adding a new node type that has an `id` would require updating two separate blocks.

```suggestion
  if (
    (componentNode.type === 'ClassExpression' ||
      componentNode.type === 'FunctionExpression' ||
      componentNode.type === 'ClassDeclaration' ||
      componentNode.type === 'FunctionDeclaration') &&
    componentNode.id
  ) {
    return componentNode.id;
  }
```

- [ ] Mark as noise
…rc/jsts/rules/S6767/decorator.ts

Comment: **Logic duplication:** `isWholePropsUsage` encodes the same four "whole props usage" patterns as `hasPropsCall` (lines 276–316): a non-`Super` call with props as argument, `SpreadElement`, `JSXSpreadAttribute`, and computed `MemberExpression`. The difference is that `hasPropsCall` uses name-based pattern matching and recurses over the whole subtree, while this function uses reference-identity and checks a single parent node.

If the taxonomy of "whole props usage" ever grows (e.g. object rest/spread assignment), both functions would need to be updated independently. Consider extracting the shared set of patterns into a shared predicate or a documented constant so the two sites stay in sync.

- [ ] Mark as noise
sonar-review-alpha[bot]

This comment was marked as outdated.

@francois-mora-sonarsource
Copy link
Copy Markdown
Contributor

There is still a gap in the decorator-factory suppression for named function expressions.

getComponentIdentifier() currently prefers the inner self-name of a FunctionExpression / ClassExpression over the outer variable binding:

const WrappedComponent = function InnerWrappedComponent(props: Props) {
  return <div>{props.label}</div>;
};

But hasDecoratorFactoryCallPropUsage() needs to follow the binding that is actually used at the decorator application site:

track((props: Props) => ({
  context_module: props.contextModule,
}))(WrappedComponent);

In this shape, the relevant reference is WrappedComponent, not InnerWrappedComponent, so the current implementation misses the decorator application and still reports contextModule as unused.

I reproduced this locally after npm ci + npm run bbf with a small RuleTester case, and it still fails with one unusedPropType error.

Please adjust the component-variable lookup to follow the outer binding for named expressions here, and add a regression test for that case. A good fit would be a new valid case in packages/analysis/src/jsts/rules/S6767/unit.typescript.test.ts like:

declare const React: any;
declare function track<P>(
  mapper: (props: P) => Record<string, unknown>,
): <TComponent>(target: TComponent) => TComponent;
interface NamedExpressionProps {
  label: string;
  contextModule: string;
}
const WrappedComponent = function InnerWrappedComponent(props: NamedExpressionProps) {
  return <div>{props.label}</div>;
};
track((props: NamedExpressionProps) => ({
  context_module: props.contextModule,
}))(WrappedComponent);

Comment: There is still a gap in the decorator-factory suppression for **named function expressions**.

`getComponentIdentifier()` currently prefers the inner self-name of a `FunctionExpression` / `ClassExpression` over the outer variable binding:

```ts
const WrappedComponent = function InnerWrappedComponent(props: Props) {
  return <div>{props.label}</div>;
};
```

But `hasDecoratorFactoryCallPropUsage()` needs to follow the binding that is actually used at the decorator application site:

```ts
track((props: Props) => ({
  context_module: props.contextModule,
}))(WrappedComponent);
```

In this shape, the relevant reference is `WrappedComponent`, not `InnerWrappedComponent`, so the current implementation misses the decorator application and still reports `contextModule` as unused.

I reproduced this locally after `npm ci` + `npm run bbf` with a small RuleTester case, and it still fails with one `unusedPropType` error.

Please adjust the component-variable lookup to follow the outer binding for named expressions here, and add a regression test for that case. A good fit would be a new **valid** case in `packages/analysis/src/jsts/rules/S6767/unit.typescript.test.ts` like:

```ts
declare const React: any;
declare function track<P>(
  mapper: (props: P) => Record<string, unknown>,
): <TComponent>(target: TComponent) => TComponent;
interface NamedExpressionProps {
  label: string;
  contextModule: string;
}
const WrappedComponent = function InnerWrappedComponent(props: NamedExpressionProps) {
  return <div>{props.label}</div>;
};
track((props: NamedExpressionProps) => ({
  context_module: props.contextModule,
}))(WrappedComponent);
```
sonar-review-alpha[bot]

This comment was marked as outdated.

@francois-mora-sonarsource
Copy link
Copy Markdown
Contributor

I think there is still a scope gap against JS-1394.

The original ticket is explicitly about props consumed through decorator annotations (@track(...) / @screenTrack(...) on the component), and the Jira discussion later treated decorator and decorator-factory forms as the same FP family. The current branch only implements the curried wrapper shape in hasDecoratorFactoryCallPropUsage(); I don't see corresponding support for class decorator annotations via node.decorators.

Could you extend the remediation to also cover the annotation form, for example:

@track((props: Props) => ({
  context_module: props.contextModule,
  user_id: props.userId,
}))
class MyTrackedComponent extends React.Component<Props> {
  render() {
    return <div />;
  }
}

As it stands, the branch fixes only one syntactic manifestation of the ticket's FP pattern.

Vibe Bot added 2 commits May 1, 2026 17:15
Comment: I think there is still a scope gap against JS-1394.

The original ticket is explicitly about props consumed through decorator annotations (`@track(...)` / `@screenTrack(...)` on the component), and the Jira discussion later treated decorator and decorator-factory forms as the same FP family. The current branch only implements the curried wrapper shape in `hasDecoratorFactoryCallPropUsage()`; I don't see corresponding support for class decorator annotations via `node.decorators`.

Could you extend the remediation to also cover the annotation form, for example:

```ts
@track((props: Props) => ({
  context_module: props.contextModule,
  user_id: props.userId,
}))
class MyTrackedComponent extends React.Component<Props> {
  render() {
    return <div />;
  }
}
```

As it stands, the branch fixes only one syntactic manifestation of the ticket's FP pattern.
The upstream react/no-unused-prop-types rule now accepts typed class-decorator callback member reads, so the sentinel should treat that sample as valid. Keep the factory-call member-read and whole-props forwarding samples invalid because upstream still reports them.
sonar-review-alpha[bot]

This comment was marked as resolved.

…rc/jsts/rules/S6767/unit.typescript.test.ts

Comment: The upstream sentinel test (`unit.upstream.test.ts`, the new `valid` entry) confirms that the upstream `no-unused-prop-types` rule already suppresses this exact `@track(callback)` class decorator pattern when TypeScript type information is available — it never calls `context.report()` for it.

Because `interceptReportForReact` only fires when the upstream rule calls `report()`, `hasDecoratorAnnotationPropUsage()` is never invoked for this test case. The test would pass even if that function were deleted.

Two questions:
1. Is there a scenario where the upstream rule *does* report a class decorator case (e.g. without TypeScript type info, or a whole-props-forwarding variant like `@track(props => buildPayload(props))`), where our new function provides the actual suppression?
2. If yes, can a test be added for that scenario so `hasDecoratorAnnotationPropUsage()` is verified to change the outcome?

If `hasDecoratorAnnotationPropUsage()` is intentional defense-in-depth against future upstream changes, a comment explaining that intent would prevent confusion.

- [ ] Mark as noise
sonar-review-alpha[bot]

This comment was marked as outdated.

@francois-mora-sonarsource
Copy link
Copy Markdown
Contributor

The new decorator callback suppression still looks too broad.

hasDecoratorFactoryCallPropUsage() / isPropsCallbackUsingProp() currently treat any first-parameter callback passed through decorate(...)(Component) as if that parameter were the component props. That means a shape like this is now suppressed even though the prop is still genuinely unused:

function decorate(metadataMapper) {
  return function applyDecorator(target) {
    return target;
  };
}
function DecoratedComponent(props) {
  return <div />;
}
DecoratedComponent.propTypes = {
  contextModule: PropTypes.string,
};
decorate(function (metadata) {
  return {
    context_module: metadata.contextModule,
  };
})(DecoratedComponent);

I reproduced that locally with NoTypeCheckingRuleTester: expected 1 unusedPropType error, got 0.

So the current remediation is still suppression-first: unknown decorator callback APIs are assumed to be props mappers based only on a property-name coincidence. Because isPropsCallbackUsingProp() is shared, the same risk also applies to the annotation path when upstream still reports.

Can we tighten this back to a report-first shape and add an invalid regression test for this boundary? If we cannot prove that the callback parameter is actually the component props, we should report by default rather than suppress.

Comment: The new decorator callback suppression still looks too broad.

`hasDecoratorFactoryCallPropUsage()` / `isPropsCallbackUsingProp()` currently treat any first-parameter callback passed through `decorate(...)(Component)` as if that parameter were the component props. That means a shape like this is now suppressed even though the prop is still genuinely unused:

```ts
function decorate(metadataMapper) {
  return function applyDecorator(target) {
    return target;
  };
}
function DecoratedComponent(props) {
  return <div />;
}
DecoratedComponent.propTypes = {
  contextModule: PropTypes.string,
};
decorate(function (metadata) {
  return {
    context_module: metadata.contextModule,
  };
})(DecoratedComponent);
```

I reproduced that locally with `NoTypeCheckingRuleTester`: expected `1` `unusedPropType` error, got `0`.

So the current remediation is still suppression-first: unknown decorator callback APIs are assumed to be props mappers based only on a property-name coincidence. Because `isPropsCallbackUsingProp()` is shared, the same risk also applies to the annotation path when upstream still reports.

Can we tighten this back to a report-first shape and add an invalid regression test for this boundary? If we cannot prove that the callback parameter is actually the component props, we should report by default rather than suppress.
sonar-review-alpha[bot]

This comment was marked as outdated.

s6767-props-reported-unused-when-consumed-through-a-typescriptes-decorator-gpt-5.5
sonar-review-alpha[bot]

This comment was marked as outdated.

sonar-review-alpha[bot]

This comment was marked as outdated.

sonar-review-alpha[bot]

This comment was marked as outdated.

sonar-review-alpha[bot]

This comment was marked as resolved.

sonar-review-alpha[bot]

This comment was marked as outdated.

sonar-review-alpha[bot]

This comment was marked as outdated.

s6767-props-reported-unused-when-consumed-through-a-typescriptes-decorator-gpt-5.5
sonar-review-alpha[bot]

This comment was marked as outdated.

@francois-mora-sonarsource francois-mora-sonarsource requested a review from a team May 11, 2026 15:57
sonar-review-alpha[bot]

This comment was marked as resolved.

sonar-review-alpha[bot]

This comment was marked as resolved.

sonar-review-alpha[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@francois-mora-sonarsource francois-mora-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed the review feedback already reflected in the branch. Re-verified the S6767 TypeScript coverage on current HEAD.

Comment thread packages/analysis/src/jsts/rules/helpers/type.ts
Comment thread packages/analysis/src/jsts/rules/helpers/react.ts
@francois-mora-sonarsource
Copy link
Copy Markdown
Contributor

While validating the non-props escape, I found a false negative on wrapped props contracts.

A class such as React.Component<Readonly<SharedType>, SharedType, Snapshot> could be misclassified as non-props because the props slot wraps the same declaration instead of exposing it as the exact same enclosing type. That incorrectly suppressed a real unused-prop report.

Fixed in 18c4a287d3ebcb98746a33a93e5df7da7887f689 by making the non-props escape check whether the relevant React type slot exposes the reported member, rather than relying only on exact enclosing-type declaration equality when a reported member is available.

sonar-review-alpha[bot]

This comment was marked as outdated.

@sonarqube-next
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@sonar-review-alpha sonar-review-alpha Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a large, well-structured PR that tackles a real problem (false positives in S6767 for decorator-consumed props) with careful type-system reasoning. The test coverage is extensive and the five escape hatches are narrowly scoped. However there are two real bugs that need fixing before merge.

Bug 1 — areSameTypeArguments / Box<any> comparison: The recursive path in areSameTypeArguments calls areSameTypeDeclarations when both sides share a declared type symbol, but areSameTypeDeclarations immediately returns false for any/unknown at the top. This means Box<any> vs Box<any> fails the recursive check and the test cases in unit.typescript.test.ts that expect identical any/unknown generic instantiations to be recognised as the same type will fail at runtime (even if they pass in the current test suite due to a different code path). See the inline comment on type.ts.

Bug 2 — getComponentIdentifier returns the variable declarator id for ordinary VariableDeclarator nodes: The final return in getComponentIdentifier fires for any VariableDeclarator with an identifier id, regardless of whether its init is a function/class expression. This means a variable like const label = "hello" that happens to appear as a parent of a component node could produce a wrong identifier. See the inline comment on react.ts.

🗣️ Give feedback

@francois-mora-sonarsource
Copy link
Copy Markdown
Contributor

Clarification on the latest Sonar Review summary:

  • The areSameTypeArguments / Box<any> point is already fixed on current HEAD. areSameTypeArguments() now handles any / unknown before the symbol-based branch, so identical instantiations like Box<any> no longer fall into the old recursive false path.
  • The getComponentIdentifier() point is not a current correctness issue. That helper is only called for actual component nodes, and the VariableDeclarator fallback is the intended path for variable-assigned components such as const Foo = () => ..., const Foo = function () {}, and const Foo = class extends React.Component {}. It is not used to derive identifiers from arbitrary declarators like const label = "hello".

So there is no remaining blocker from that review body on the current branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant