Skip to main content

Integrating DCM into an existing project

· 5 min read

While the benefits of using static analysis tools such as DCM are quite obvious, integrating them into an existing project can be challenging due to the many possible warnings that need attention. That's why developers prefer to add such tools in the early stages of a project and quickly give up when it comes to old existing codebases.

But when it comes to DCM there are several tricks you can use to significantly reduce the time spend on its integration.

Power of presets

DCM currently provides around 180 lint rules for various mistakes, style issues and packages. And this number continues to grow with each release making it hard to keep up with all the new rules become available.

In order to always be up to date with the available rules, you can use a feature called presets. Presets are basically lists of rules curated by us and updated with each release.

Let's take a look on how one can install and use them.

Installing a preset

In order to install a preset, add dart_code_metrics_presets as a dev dependency and configure the extends entry in the analysis_options.yaml. For example,

analysis_options.yaml
dart_code_metrics:
extends:
- package:dart_code_metrics_presets/all.yaml

This config enables all rules listed in dart_code_metrics_presets/all.yaml.

But what's more important, you can not only have multiple presets at once, but also create your own presets. For example,

analysis_options.yaml
dart_code_metrics:
extends:
- package:dart_code_metrics_presets/all.yaml
- package:dart_code_metrics_presets/teams_all.yaml
- package:my_presets/all.yaml

This configuration will load rules from all the presets.

What structure a custom preset should have?

The only requirement for a preset is that it should match the regular DCM config structure. For example,

analysis_options.yaml
dart_code_metrics:
rules:
- avoid-cubits
- avoid-bloc-public-methods
- avoid-passing-bloc-to-bloc
- prefer-multi-bloc-provider
- prefer-correct-bloc-provider

this preset contains all rules for the Bloc library. If any of the rules in a preset have configuration, it will be loaded and used as well.

What happens if a rule is included into multiple loaded presets?

When configuration is loaded, the last each subsequent entry overrides the previous one, meaning that if in dart_code_metrics_presets/all.yaml we have a rule called some-rule and in my_presets/all.yaml the same rule is disabled via some-rule: false, in the resulting config the rule will be disabled.

This behavior gives you the flexibility to create a base preset that is reused in all packages, but you can disable some parts of it via other presets.

Note, that

analysis_options.yaml
dart_code_metrics:
extends:
- package:dart_code_metrics_presets/all.yaml
- package:my_presets/all.yaml
rules:
- some-rule: false

also works as expected.

Fixing existing problems

Some rules DCM provide come with quick-fixes, that can help you address the issues faster. For example, if you enable the avoid-redundant-async rule and apply a quick-fix, it will remove an async keyword marked as redundant.

For rules that does not provide a quick-fix the main reason behind is that it is impossible to say unequivocally how the problem should be solved. For example, for avoid-passing-async-when-sync-expected you might want to mark the function sync or pass another function or change the type of the parameter. Another common reason why a rule does not provide a quick-fix is when a fix is too complex and can break your code.

DCM fix

While quick-fixes can help you address issues faster, they are limited to a particular file. To help you fix all issues in you project at once, DCM provides a command called dcm fix.

Calling this command will address all issues for the enabled rules in non-conflicting way, meaning that each subsequent fix is not blocked by a previous one even if the code was changed significantly.

dcm fix also allows you to remove unused code highlighted by dcm check-unused-code. To do so, pass the --type=unused-code option to the command invocation.

Fix on save in the IDE

VS Code

You can quickly fix all fixable DCM rule issues with "DCM: Fix All Auto-fixable Problems" IDE command or via a shortcut ⌘ + Shift + S.

To apply fixes on save, modify the settings.json to the following:

.vscode/settings.json
{
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.dcm.fixAll": true
}
}

IntelliJ / AS

You can quickly fix all fixable DCM rule issues with "DCM: Fix All Auto-fixable Problems" IDE command or via a shortcut ⌘ + Shift + S.

Ignore all existing problems

Last, but not least is an ability to ignore all existing violations unless the related code is changed. This feature is called a baseline.

To calculate the baseline for your project, simply call dcm init and it will generate a json file that will be used both by CLI and the IDE integrations.

Here is an example:

dcm_baseline.json
{
"date": "2023-04-06 11:21:12.433111Z",
"paths": {
"lib/src/fixes/models/fix_producer.dart": {
"prefer-match-file-name": [
"2dca28e191c53faa330a518d0af4ffc5"
]
},
"lib/src/fixes/correct_source_visitor.dart": {
"no-empty-block": [
"99914b932bd37a50b983c5e7c90ae93b",
"99914b932bd37a50b983c5e7c90ae93b"
],
"prefer-correct-identifier-length": [
"865c0c0b4ab0e063e5caa3387c1a8741",
"865c0c0b4ab0e063e5caa3387c1a8741"
]
}
}
}

The file contains all issues groped by the rule and file, where the issues occurred. This structure allows you to manually remove a particular file or rule violations to address them separately, reducing the number of ignored issues.

Conclusion

That's a wrap! Now you know all the approaches one can take to speed up the DCM integration into an existing project.

If you have other suggestions how we can help you with the integration, just let us know!