Skip to main content
Pro+

Analyze Widgets

Reports the quality and usage of your widgets.

Shows the number widgets / blocs / context.read / context.watch being used, the number of widgets using a particular widget, similar widgets and a widget quality score (based on code metrics).

To execute the command, run:

$ dcm analyze-widgets lib # or dcm aw lib
info

This command uses metrics configuration from the analysis_options.yaml file and uses the following configuration as a fallback configuration:

cyclomatic-complexity: 20
halstead-volume: 300
maintainability-index: 50
maximum-nesting-level: 5
number-of-parameters: 6
source-lines-of-code: 50

Full command description:

Usage: dcm analyze-widgets [arguments] <directories>
-h, --help Print this usage information.


--show-similarity Include similar widgets into the report.
--threshold Set a minimum threshold after which widgets are considered similar.
(defaults to "0.2")


-r, --reporter=<console> Analysis output format.
[console (default) (Free+), html(Pro+), json(Team+), codeclimate(Team+), gitlab(Team+), checkstyle(Team+)]
-a, --absolute-path Use absolute path for console reporter output.
-o, --output-directory=<OUTPUT> Write HTML output to OUTPUT.
(defaults to "widgets_report")
--open Automatically open generated HTML report
--json-path=<path/to/file.json> Path to the JSON file with the analysis output.
--report-all Report all widgets (default is to report only medium or low quality widgets).


-c, --print-config Print resolved config.


--root-folder=<./> Root folder.
(defaults to the current directory)
--sdk-path=<directory-path> Dart SDK directory path.
If the project has a `.fvm/flutter_sdk` symlink, it will be used if the SDK is not found.
--exclude=<{**/*.g.dart,**/*.freezed.dart}> File paths in Glob syntax to be exclude.
(defaults to "{**/*.g.dart,**/*.freezed.dart}")


--no-congratulate Don't show output even when there are no issues.


--verbose Show verbose logs.


--ci-key The license key to run on CI server. Can be provided via DCM_CI_KEY env variable.
--email The email used to purchase the license. Can be provided via DCM_EMAIL env variable.


--no-analytics Disable sending anonymous usage statistics.


--fatal-level=<low> Treat given or lower quality level as fatal.
[low, medium]

Detecting similar widgets (disabled by default)

To include similar widgets into the report, pass --show-similarity CLI flag.

Similarity report includes:

  • name of the similar widget
  • source code of the similar widget with highlighted subtree matches
  • similarity percentage of the build method widget tree
  • list of the matching widgets subtree

By default, a pair of widgets is considered similar if their subtrees match more than 20%.

You can customize this threshold via the --threshold CLI option.

Report example

Similarity report example

Highlighted subtree example

Highlighted subtree example

Showing statically resolved widget trees

When similarity reporting is enabled, the report will also include the resolved widget tree.

Resolved tree example

This widget tree includes all found widgets and shows which widgets are rendered conditionally (e.g. via if (condition) MyWidget) and which are inside multi-child layout widgets (e.g. Column, Row, etc.).

Reporting all widgets

By default only the HTML reporter shows all widgets.

To enable output of all widgets (regardless of their quality level) for other reporters, pass the CLI flag --report-all.

Output example

Console

Use --reporter=console to enable this format.

Console

HTML

Use --reporter=html to enable this format.

HTML report overview

HTML

HTML single file report

HTML

JSON

The reporter prints a single JSON object containing meta information and the violations grouped by a file. Use --reporter=json to enable this format.

The root object fields are

  • formatVersion - an integer representing the format version (will be incremented each time the serialization format changes)
  • timestamp - a creation time of the report in YYYY-MM-DD HH:MM:SS format
  • records - an array of objects
  • summary - an array of objects
{
"formatVersion": 2,
"timestamp": "2021-04-11 14:44:42",
"records": [
{
...
},
{
...
},
{
...
}
],
"summary": [
{
...
},
{
...
}
]
}

The record object fields are

  • path - a relative path to the target file
  • widgets - an array with target file widgets
{
"path": "lib/src/widgets/some_widget_file.dart",
"widgets": {
...
},
}

The summary-record object fields are

  • title - a message with information about the record
  • value - an actual value of this record (is a single value)
{
"title": "Scanned folders",
"value": 50,
}

The widget object fields are

  • blocs - an array of used blocs (strings)
  • codeSpan - a source code span of the target entity
  • fromRead - an array of classes from context.read (strings)
  • fromWatch - an array of classes from context.watch (strings)
  • interfaces - an array of used interfaces (strings)
  • level - widget quality level
  • methodMetrics an array of method metrics
  • mixins - an array of used mixins (strings)
  • name - widget name
  • score - quality score
  • similarWidgets - an array of similar widgets
  • topLevelMetrics - an array of top level metrics
  • type - widget type
  • usedBy - an array of used widgets (strings)
  • usedWidgets - an array of used widgets
{
"blocs": [],
"codeSpan": {
...
},
"fromRead": ["SomeClass"],
"fromWatch": ["AnotherClass"],
"interfaces": [],
"level": "High",
"methodMetrics": [
...
],
"mixins": [],
"name": "MyWidget",
"score": 0.83,
"topLevelMetrics": [
...
],
"usedBy": ["SomeWidget", "AnotherWidget"],
"usedWidgets": [
...
]
}

The code span object fields are

  • start - a start location of an entity
  • end - an end location of an entity
  • text - a source code text of an entity
{
"start": {
...
},
"end": {
...
},
"text": "entity source code"
}

The location object fields are

  • offset - a zero-based offset of the location in the source
  • line - a zero-based line of the location in the source
  • column - a zero-based column of the location in the source
{
"offset": 156,
"line": 7,
"column": 1
}

The method metrics object fields are

  • codeSpan - a source code span associated with the method
  • level - method quality level
  • metrics - an array of top level metrics
  • name - method name
  • score - method quality score
{
"codeSpan": {
...
},
"level": "Medium",
"metrics": [
...
],
"name": "build",
"score": 0.80
}

The top level metrics object fields are

  • isInverted - whether the level value should be inverted (High means bad)
  • level - metric quality level
  • name - method name
  • value - method quality score
{
"isInverted": false,
"level": "Medium",
"name": "cyclomatic-complexity",
"value": 20
}

The similar widgets object fields are

  • widget - the name of the similar widget
  • similarity - similarity score
{
"widget": "AnotherWidget",
"similarity": 0.6
}

The used widget object fields are

  • path - absolute path to widget
  • references - number of references
  • type - widget type (local, external, flutter)
{
"path": "/path/to/used/widget.dart",
"references": 5,
"type": "local"
}

GitLab and Code Climate

GitLab and Code Climate formats are also supported. Refer to the analyze commands docs to set up them.

Checkstyle

Use --reporter=checkstyle to enable this format.

<?xml version="1.0"?>
<checkstyle version="10.0">
<file name="../abstract_class.dart">
<error line="0" severity="warning" message="someWidget quality score is 20% (low quality)" source="widget-quality-report"/>
</file>
<file name="../class_with_factory_constructors.dart">
<error line="0" severity="warning" message="anotherWidget quality score is 20% (low quality)" source="widget-quality-report"/>
</file>
</checkstyle>