False positives for rules when using yarn PnP configuration in monorepo

We have recently tried to switch to yarn Plug’n’Play nodeLinker configuration, however once this setting is enabled in yarn, we start to get a lot of false positives for 2 specific rules (typescript:S6671 and typescript:S4325). If we change the yarn configuration back to node-modules , the false positives will not appear.

  • ALM used : GitHub
  • CI system used : GitHub Actions
  • Scanner command used when applicable (private details masked):
    using the github action sonarsource/sonarcloud-github-action@v2.0.2
    with configuration
    - name: Sonar PR scan
      uses: sonarsource/sonarcloud-github-action@v2.0.2
      if: github.event_name == 'pull_request'
      env:
        GITHUB_TOKEN: ${{ inputs.github_token }}
        SONAR_TOKEN: ${{ inputs.project_login }}
      with:
        args: >
          -Dsonar.exclusions=${{ inputs.exclusions }}
          -Dsonar.host.url=https://sonarcloud.io
          -Dsonar.javascript.lcov.reportPaths=${{ inputs.report_path }}
          -Dsonar.go.coverage.reportPaths=${{ inputs.report_path }}
          -Dsonar.javascript.node.maxspace=8192
          -Dsonar.organization=${{ inputs.organization }}
          -Dsonar.projectKey=${{ inputs.project_key }}
          -Dsonar.pullrequest.github.summary_comment=true
          -Dsonar.pullrequest.key=${{ github.event.number }}
          -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }}
          -Dsonar.pullrequest.base=${{ github.event.pull_request.base.ref }}
          -Dsonar.scm.disabled=true
          -Dsonar.sources=${{ inputs.source }}
        projectBaseDir: ${{ steps.app-path.outputs.path }}
  • Languages of the repository: Typescript
  • Error observed (wrap logs/code around with triple quotes ``` for proper formatting)
    2 Rules trigger false positives when yarn Plu’n’Play nodeLinker is enabled
  1.  This assertion is unnecessary since the receiver accepts the original type of the expression.
     Redundant casts and non-null assertions should be avoided typescript:S4325
    
    In the observed cases, the assertion is necessary, and compilation will fail without it.
  2.  Expected the Promise rejection reason to be an Error.
     Literals should not be used for promise rejection typescript:S6671
    
    In this case, the returned type does extend from Error. Changing the nodeLinker configuration of yarn to be node-modules will correctly identify this.
  • Steps to reproduce
    1. Use yarn as package manager, with nodeLinker : pnp
    2. Set up a monorepo structure, with a reference to another workspace project
      eg. in mainApp → package.json, add a dependency “some-library”: “workspace:*”
    3. Add a custom error type in “some-library”
      eg. export class MyError extends Error {}
    4. reject a promise using MyError
    5. Scan the project, will fail the sonar rule typescript:S6671
  • Potential workaround
    We need to add // NOSONAR to all the affected lines

Hello @mon0051,

thanks for reporting this. It seems Typescript is not properly resolving the dependencies. Can you confirm you are using ts-loader/webpack?

Typescript does not seem to support yarn package resolution by itself.

Hi Team,

Sorry I don’t really understand your comment.
My understanding is that sonar is run after / during unit test runs, which are compiled and executed with jest 29.7.0, ts-jest 29.1.1 + typescript 5.4.5.
Why would webpack be involved?

Hi @mon0051,

Sonar will look into the code as a whole. Unit tests will be used for coverage, but Sonar does not depend on those to raise issues.

The JS/TS analyzer uses a Typescript type-checker in many of the rules to determine the interface to certain objects, including the dependencies. Typescript supports out-of-the-box node_modules resolution, so it can provide information for project dependencies, making the whole analysis much more robust. When using PnP, Typescript cannot resolve the types of your dependencies, which affects the results.

I hope this makes things clearer.

Cheers,
Victor

Where does the typescript package that sonar uses come from?
How does the JS/TS analyzer invoke typescript?
The version of typescript inside our codebase is compatible with PnP as long as it is invoked with yarn

Hello @mon0051,

The current version of JS/TS analyzer is bundled with TypeScript 5.4.3. The analyzer does not invoke TS, but uses the compiler API to analyze the source code (first we search for tsconfigs.json to be used for the program). The program creation step is when TypeScript searches for dependencies in the fs. At this stage, our analyzer does not support PnP because the magic yarn is doing in your case does not enter the scene when JS/TS analyzer reads the code.

Cheers,
Victor

Hi @mon0051,

Coming back to the initial report, I agree this is a false positive. So, long story short, we don’t support PnP at this moment, and the only workaround is not to use it.

I created a ticket to support yarn PnP.

Thanks for reporting this.