Integrating DCM Into an Existing Project
One of the most challenging parts of adopting a linter is integrating it into an existing codebase. That's especially true for old projects or projects developed by large teams as the number of warnings may be overwhelming.
This guide describes several techniques and DCM features that can significantly simplify the integration process for your team.
Getting Preview of Current Rule Issues​
To quickly asses the number of issues before integrating the tool, use the preview command.
By default, dcm init preview
runs all available rules.
To change this behavior, pass --severity
, --rule-types
and --only-fixable
options.
For example, to get only for Flutter
and Bloc
rule violations with warning
and style
severities, pass --severity=warning,style --rule-types=flutter,bloc
.
dcm init preview --severity=warning,style --rule-types=flutter,bloc
For more information on "dcm init preview", refer to the Preview documentation.
Enabling a Preset​
Given that DCM currently provides more than 350 rules for various mistakes, style issues and packages, it can be challenging to choose the right set of rules without spending hours going through the whole list.
That's where presets can help. Presets are lists of rules curated by us and updated with each release.
To quickly start with a recommended set of rules, add the following configuration to your analysis_option.yaml
file:
dart_code_metrics:
extends:
- recommended
The recommended
preset focuses more on the potential bugs, rather than style issues and once you are ready to add more rules, simply update your configuration:
dart_code_metrics:
extends:
- recommended
rules:
- members-ordering
- avoid-watch-outside-build
- avoid-passing-bloc-to-bloc
For more information on other presets (or how to create custom presets), refer to the Presets documentation.
Fixing Existing Problems​
Once you've chosen a list of rules, it is time to address the existing issues.
While some of the rules cannot be fixed automatically, some rules 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 fixed. 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.
Using Quick-Fixes​
To address rule issues one by one, use IDE quick fixes.
Using "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 your project at once, DCM provides a command called dcm fix
.
dcm fix lib
Calling this command will address all issues for the enabled rules in a 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 helps removing unused code highlighted by dcm check-unused-code
. To do so, pass the --type=unused-code
option to the command invocation.
dcm fix --type=unused-code lib
For more information on "dcm fix", refer to the Fix documentation.
Using "Fix On Save" in the IDE​
- VS Code
- IntelliJ / Android Studio
To quickly fix all fixable issues within a particular file, use the "DCM: Fix All Auto-fixable Problems" IDE command or a shortcut ⌘ + Shift + S
.
To apply fixes on save, modify the settings.json
to the following:
{
"editor.codeActionsOnSave": {
"source.fixAll": "explicit", // This line enables "fix on save" for the Dart analyzer
"source.dcm.fixAll": "explicit"
}
}
To quickly fix all fixable issues within a particular file, use the "DCM: Fix All Auto-fixable Problems" IDE command or a shortcut ⌘ + Shift + S
.
Ignoring Existing Problems​
If you have too many issues and/or don't have time to address them all at once, several techniques can help you with the integration:
Using the Configuration​
Aside from the rule-specific configuration, each rule accepts a common configuration option (exclude
and include
among them). Those options can be used to scope a rule to a set of specific folders or files.
For any rule to skip a folder(s) (or a set of files), set the exclude
configuration option for that rule:
dart_code_metrics:
rules:
- newline-before-return:
exclude:
- test/**
To exclude a folder for all the rules, use the global configuration option called exclude:rules:
.
If instead you need the rule to apply to a specific folder only (e.g. the test
) folder, set the include
configuration option:
dart_code_metrics:
rules:
- newline-before-return:
include:
- test/**
For more information on the rules configuration, refer to the Configuring Rules documentation.
Enabling Baseline​
While excluding folders and files can work in some cases, the main problem with this approach is that it also affects new issues.
To ignore only existing issues, DCM provides a feature called "Baseline". In short, it generates a file with all existing violations and those violations will not be reported by the tool (unless the related code is changed).
dcm init baseline lib
Here is an example of a baseline file:
{
"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.
For more information on "dcm init baseline", refer to the Baseline documentation.
Disabling a Rule​
If scoping the rules or adding them to the baseline does not work for you, consider temporarily disabling a rule:
dart_code_metrics:
rules:
- newline-before-return: false
# Or
# - newline-before-return
Synchronizing Your Team​
Integrating a linter is not only about the issues but also about how to ensure everyone works with the same version and in the same environment.
Synchronizing DCM Version​
- VS Code
- IntelliJ / Android Studio
To ensure that all team members using VS Code have the necessary extensions installed, configure the "Workspace recommended extensions":
-
Create or update the
.vscode/extensions.json
file in your project directory. -
Add the following configuration:
{
"recommendations": ["publisher.dcm"]
}
Refer to the Workspace recommended extensions documentation for more details.
To ensure team-wide plugins installation, configure the list of required plugins:
- Go to File > Settings (or IntelliJ IDEA > Preferences on macOS).
- Navigate to Plugins and select the Required Plugins tab.
- Add "DCM" to the list of required plugins.
Refer to the Required plugins documentation for detailed instructions.
Ensuring Consistent Executable Versions Across the Team​
To ensure that all team members use the same version of the DCM executable, configure the version constraints in your project's dcm_global.yaml
file:
-
Open or create the
dcm_global.yaml
file in your project root. -
Set the version constraint:
version: '>=1.15.0 <2.0.0'
For more information on global configuration options, refer to the global configuration documentation.