linters(dart): parse the JSON analyze output and batch from the project root - #1164
Open
AndrewDongminYoo wants to merge 2 commits into
Open
linters(dart): parse the JSON analyze output and batch from the project root#1164AndrewDongminYoo wants to merge 2 commits into
AndrewDongminYoo wants to merge 2 commits into
Conversation
…ct root The default analyze format is documented as user-consumable and unspecified between releases, and its relative paths force one invocation per parent directory. The JSON format reports absolute paths, lowercase rule codes, and uppercase severities, so a batch can be analyzed in one pass from the project root while existing trunk-ignore directives and issue URLs keep working.
The JSON output keeps the correction sentence in a separate correctionMessage field, so each recorded message is now the problem message alone. Codes, levels, lines, columns, and issue URLs are unchanged.
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
dart analyze --format=jsoninstead of the default human-readable output.analyzecommand once from the project root instead of once per parent directory.trunk-ignoredirectives are unchanged. Messages lose the trailing correction sentence, so the snapshot is regenerated here.Motivation
Two problems share one cause.
The default output format is not a contract.
dart analyze --help --verbosesays of it: "The default output format. This format is intended to be user consumable. The format is not specified and can change between releases." The linter currently parses that format with a regex.The default format also reports paths relative to a root that Dart itself chooses, so results are only addressable when the analyzer runs from the target's own directory. That is what
run_from: ${parent}is for, and it splits every batch along directory boundaries:batch: truenever batches across directories.formatdoes not share the problem because #1114 already runs it from the package root.--format=jsonis the documented machine-readable output. It reports absolute paths, so the batch can run once from the project root.Measurements
Four real repositories, each with
dart@SYSTEMenabled and its packages already resolved, on Dart 3.13.1 and Trunk CLI 1.25.0.analysis_optionscounts theanalysis_options.yamlfiles in the repository, since that is whatroot_or_parent_withgroups by. Invocation counts come from a shim placed ahead ofdartonPATHthat records each argument list.The gain tracks how many
analysis_options.yamlfiles a repository has, because that is what still bounds a batch after the change. A single-package repository collapses to one analyze invocation; a repository with four of them keeps four groups and gains less.A synthetic fixture of 161 files across 40 directories, alternating the two definitions and rewriting every file between rounds so the lint cache cannot serve a previous result, gives a median of 7.46s against 2.98s with 43 invocations against 6. Wall-clock figures were taken on a loaded machine and are directional; invocation counts are exact.
Correctness
Checked on a fixture with two packages, so that
root_or_parent_with(analysis_options.yaml)resolves to a subdirectory for some targets and to the repository root for others.example/lib/bad.dart:3:12andlib/feature_1/file.dart:3:12.dart/prefer_single_quotes,dart/undefined_identifier.issue_url_formatis unaffected.INFOto low,ERRORto high.// trunk-ignore(dart/prefer_single_quotes)still suppresses its issue, with notrunk/ignore-does-nothingnotice.On the Flutter app above, which reports 167 issues from its own
very_good_analysisrule set, the before and after runs produce the same 167 issues with identical files, lines, columns, levels, and rule codes.--format=machinewas tried first and rejected. It reports absolute paths too, but uppercases every rule code toPREFER_SINGLE_QUOTES, which breaksissue_url_formatand silently disarms everytrunk-ignore(dart/…)comment already written in a consumer repository.What changes for users
Issue messages become the analyzer's
problemMessagealone. Previously the regex captured the default format's line, which concatenates the problem and the correction:The JSON output carries
correctionMessageas a separate field, so the hint is available but cannot be joined into a single capture group by a regex parser.Tests
npx jest linters/dartpasses with the snapshot regenerated. The regenerated snapshot changes four lines, all of themmessage:code,level,line,column,file, andissueUrlare byte-identical, and the second snapshot file is untouched.Worth noting for review:
linters/dart/test_data/carries its ownanalysis_options.yaml, soroot_or_parent_with(analysis_options.yaml)resolves to the same directory${parent}does. The existing snapshot therefore cannot distinguish the tworun_fromsettings on its own, and the multi-package case above is what exercises that part of the change. I am happy to add such a fixture if you would like it covered.