# SonarQube sonar.inclusions and sonar.exclusions: combining scope patterns without silently scanning nothing

Fixes the pain of SonarQube inclusions and exclusions silently doing nothing: a bare folder path as an inclusion matches zero files, patterns without a **/ prefix only match at the repo root, capitalized property names are ignored, and test files need sonar.test.exclusions rather than sonar.exclusions. Shows how inclusions and exclusions compose so one folder pattern plus a few exclusions replaces enumerating folders one by one, including the exact scanner flags for an Azure DevOps pipeline.

Exact reference: {"kind":"skill_version","skill_id":"skl_7TQ3D_PBgnhRCf6GXFucFw","version_id":"skv_KCmDM7MzC4d-aGawiI-7BQ"}

Applicability: [{"constraint":">=9.9","technology":"SonarQube Server","version_scheme":"semver"},{"constraint":"rolling release (current)","technology":"SonarQube Cloud","version_scheme":"unknown"}]

# SonarQube sonar.inclusions and sonar.exclusions: combine scope patterns without silently scanning nothing

Use this skill when a SonarQube analysis keeps scanning files you tried to include or exclude: test projects still appear after setting exclusions, an inclusion of a folder changes nothing, or combining `sonar.inclusions` with `sonar.exclusions` in an Azure DevOps pipeline produces results that ignore both settings.

## The core model

Inclusions and exclusions compose. Inclusions define the initial file set, exclusions subtract from it. Both are comma-separated lists of Ant-style path patterns, matched relative to the project base directory. Every mistake in this skill comes from treating one of those two facts loosely.

## Write patterns, not paths

A bare folder path matches nothing. This is the single most common failure:

- Wrong: `sonar.inclusions=Repo/Folder 1` — matches zero files, analysis scope silently unchanged.
- Right: `sonar.inclusions=Repo/Folder 1/**/*` — matches everything under that folder.

The `**` wildcard crosses directory boundaries; `*` does not. Any inclusion that names a directory must end in `/**/*` or name files explicitly.

## Anchor patterns correctly

A pattern without a `**/` prefix only matches at the base directory root:

- `Test*.cs` matches test files sitting at the repo root and nothing else.
- `**/Test*.cs` matches test files in any subfolder, which is almost always what you want.
- `**/AssemblyInfo.cs` and `**/*.xml` are correct as written.
- Avoid a leading slash (`/*.bin`). Patterns are already relative to the base directory; a leading slash anchors oddly and usually matches nothing. Use `**/*.bin` instead.

Spaces inside path segments are fine, but remember the list is comma-separated: never put a comma inside a pattern, and quote the whole value in YAML or pipeline variables so the space survives.

## Property names are lowercase and scope-specific

The property names are case-sensitive: `sonar.inclusions` and `sonar.exclusions`, all lowercase. Capitalized variants are silently ignored.

Then the naming trap that causes most "exclusions don't work" reports: similarly named properties control different scopes.

- `sonar.exclusions` — main source files.
- `sonar.test.exclusions` — test files.
- `sonar.coverage.exclusions` — coverage calculation only; the files are still analyzed for issues.
- `sonar.cpd.exclusions` — duplication detection only.
- `sonar.test.inclusions` — which files count as tests (pairs with `sonar.tests`).

If test projects still show up in your overview after setting `sonar.exclusions`, you probably need `sonar.test.exclusions` instead — or as well. Excluding a file from coverage does not exclude it from analysis.

## Combining both in an Azure DevOps pipeline

Pass them as scanner properties on the analysis step, for example:

```
-Dsonar.inclusions="Repo/Folder 1/**/*" -Dsonar.exclusions="**/AssemblyInfo.cs,**/*.xml,**/Test*.cs,**/*.bin"
```

Or set them in `sonar-project.properties` checked into the repo so every pipeline run inherits them. You do not need to enumerate folders one by one: one inclusion pattern for the folder plus exclusion patterns for the noise inside it is the intended combination.

## Quick checklist

1. Every inclusion that names a directory ends in `/**/*`.
2. Every filename pattern that should match in subfolders starts with `**/`.
3. No leading slashes on any pattern.
4. Property names are lowercase `sonar.inclusions` / `sonar.exclusions`.
5. Test files are handled with `sonar.test.exclusions`, not `sonar.exclusions`.
6. Coverage-only noise uses `sonar.coverage.exclusions` so issues are still reported.
7. After changing scope, confirm the file count on the project's overview moved in the expected direction before trusting the numbers.


## Supporting basis and limitations

Grounding: the SonarQube Community thread 'Using Sonar Inclusions and Exclusion' (Sept 2026) for the concrete failure (bare folder inclusion, Test*.cs unanchored, /*.bin leading slash, capitalized property names in the report); SonarSource docs 'Analysis scope' (server 10.1 and Cloud) for the inclusions-then-exclusions composition model, Ant-style pattern syntax relative to the project base directory, and the scope-specific properties sonar.exclusions, sonar.test.exclusions, sonar.coverage.exclusions, sonar.cpd.exclusions, and sonar.test.inclusions.

## Change and rationale

New skill covering SonarQube analysis scope via sonar.inclusions and sonar.exclusions: the compose model (inclusions set the initial file set, exclusions subtract), why bare folder paths match nothing and need /**/*, **/ prefixing for subfolder matches, lowercase case-sensitive property names, the scope naming traps (sonar.exclusions vs sonar.test.exclusions vs sonar.coverage.exclusions vs sonar.cpd.exclusions), and combining both properties in an Azure DevOps pipeline.

A real SonarQube Community thread shows the exact failure mode: a user sets sonar.inclusions to a bare folder path and sonar.exclusions to unanchored filename patterns, and the analysis silently ignores both. The documented remedy is Ant-style patterns relative to the project base directory (directory inclusions must end in /**/*, subfolder matches need a **/ prefix), lowercase property names, and the scope-specific exclusion properties so test and coverage noise is carved out without hiding real issues.
