Skip to content

Add lint rule for identifying common patterns in the checker that lead to inconsistent diagnostic output#4708

Open
weswigham wants to merge 5 commits into
microsoft:mainfrom
weswigham:lint-checker-children-checks
Open

Add lint rule for identifying common patterns in the checker that lead to inconsistent diagnostic output#4708
weswigham wants to merge 5 commits into
microsoft:mainfrom
weswigham:lint-checker-children-checks

Conversation

@weswigham

Copy link
Copy Markdown
Member

And fix the issues it flags, fixing the TS-1 diagnostic consistency issues we inherited from strada, and also allowing some simplification of the fixes I'd already made for new ones to markLinkedReferences.

This removes the remaining TS-1 consistency issues we inherited from strada in:

constructorWithIncompleteTypeAnnotation
multiLinePropertyAccessAndArrowFunctionIndent1
parseErrorIncorrectReturnToken
parserStatementIsNotAMemberVariableDeclaration1

Generally, the approach taken to fix them is an anti-brittle one - we no longer skip actually checking the children in the affected cases (yield, return, export =) when a grammar error is present, allowing us to always report the same diagnostic regardless of if checking starts inside the node with a grammar error or outside it. In some cases (like export =), this meant pushing some logic for the error into the child (eg, resolveName now knows not to report errors on as const or export = typeName since those either... aren't errors, or, in cases where they are, something other-than-resolveName will report them).

All up, that removes the last errors in our tests, allowing me to add the test failure I described in #4527 and finally say:
Fixes #4527

Comment thread _tools/customlint/checkchildren.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds diagnostic-stability enforcement for checker traversal and resolves inherited TS-1 baseline inconsistencies.

Changes:

  • Adds the checkchildren custom lint analyzer and tests.
  • Checks child nodes before checker error-path returns.
  • Fails tests on TS-1 diagnostics and updates affected baselines.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
testdata/tests/cases/compiler/checkChildrenAlwaysChecked.ts Adds checker regression cases.
testdata/submoduleAccepted.txt Documents accepted diagnostic differences.
testdata/baselines/reference/submoduleAccepted/conformance/YieldExpression2_es6.errors.txt.diff Updates yield diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/YieldExpression17_es6.errors.txt.diff Updates yield diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/YieldExpression15_es6.errors.txt.diff Updates yield diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/YieldExpression14_es6.errors.txt.diff Updates yield diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/YieldExpression12_es6.errors.txt.diff Updates yield diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/parserStatementIsNotAMemberVariableDeclaration1(alwaysstrict=true).errors.txt.diff Removes TS-1 instability.
testdata/baselines/reference/submoduleAccepted/conformance/parserExportAssignment9.errors.txt.diff Updates export diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/parserExportAssignment5.errors.txt.diff Updates export diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/parserErrorRecovery_ModuleElement1.errors.txt.diff Updates recovery diagnostics.
testdata/baselines/reference/submoduleAccepted/conformance/jsdocDisallowedInTypescript.errors.txt.diff Updates malformed-code diagnostics.
testdata/baselines/reference/submoduleAccepted/compiler/reachabilityChecksNoCrash1.errors.txt.diff Updates recovery diagnostics.
testdata/baselines/reference/submoduleAccepted/compiler/parseErrorIncorrectReturnToken.errors.txt.diff Removes TS-1 instability.
testdata/baselines/reference/submoduleAccepted/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.errors.txt.diff Removes TS-1 instability.
testdata/baselines/reference/submoduleAccepted/compiler/constructorWithIncompleteTypeAnnotation.errors.txt.diff Removes TS-1 instability.
testdata/baselines/reference/submodule/conformance/YieldExpression2_es6.errors.txt Records yield operand errors.
testdata/baselines/reference/submodule/conformance/YieldExpression17_es6.errors.txt Records yield operand errors.
testdata/baselines/reference/submodule/conformance/YieldExpression15_es6.errors.txt Records yield operand errors.
testdata/baselines/reference/submodule/conformance/YieldExpression14_es6.errors.txt Records yield operand errors.
testdata/baselines/reference/submodule/conformance/YieldExpression12_es6.errors.txt Records yield operand errors.
testdata/baselines/reference/submodule/conformance/parserStatementIsNotAMemberVariableDeclaration1(alwaysstrict=true).errors.txt Stabilizes return diagnostics.
testdata/baselines/reference/submodule/conformance/parserExportAssignment9.errors.txt Records export operand errors.
testdata/baselines/reference/submodule/conformance/parserExportAssignment5.errors.txt Records export operand errors.
testdata/baselines/reference/submodule/conformance/parserErrorRecovery_ModuleElement1.errors.txt Records recovered return errors.
testdata/baselines/reference/submodule/conformance/jsdocDisallowedInTypescript.errors.txt Records additional semantic errors.
testdata/baselines/reference/submodule/compiler/reachabilityChecksNoCrash1.errors.txt Records additional name error.
testdata/baselines/reference/submodule/compiler/parseErrorIncorrectReturnToken.errors.txt Stabilizes recovered return diagnostics.
testdata/baselines/reference/submodule/compiler/multiLinePropertyAccessAndArrowFunctionIndent1.errors.txt Stabilizes return-expression diagnostics.
testdata/baselines/reference/submodule/compiler/constructorWithIncompleteTypeAnnotation.errors.txt Stabilizes malformed-constructor diagnostics.
testdata/baselines/reference/compiler/checkChildrenAlwaysChecked.types Adds type baseline.
testdata/baselines/reference/compiler/checkChildrenAlwaysChecked.symbols Adds symbol baseline.
testdata/baselines/reference/compiler/checkChildrenAlwaysChecked.errors.txt Adds diagnostic baseline.
internal/testutil/tsbaseline/error_baseline.go Fails tests containing TS-1 diagnostics.
internal/checker/utilities.go Identifies special resolution contexts.
internal/checker/checker.go Ensures child checking across error paths.
_tools/customlint/testdata/checkchildren/checkchildren.go.golden Defines analyzer expectations.
_tools/customlint/testdata/checkchildren/checkchildren.go Adds analyzer test cases.
_tools/customlint/plugin.go Registers the analyzer.
_tools/customlint/checkchildren.go Implements early-return analysis.

Comment thread _tools/customlint/checkchildren.go Outdated
Comment thread _tools/customlint/testdata/checkchildren/checkchildren.go Outdated
@weswigham
weswigham requested a review from jakebailey July 22, 2026 22:40
Comment on lines +222 to +223
for cur := ret; ; {
parent := cur.Parent()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just cur := ret then for {}?

// statements that genuinely follow `ret` in execution order are considered:
// mutually exclusive branches (the other arm of an if, sibling switch cases) are
// not, while loop bodies are revisited in full.
func reachableChecksAfter(ret inspector.Cursor, checks []inspector.Cursor) []inspector.Cursor {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at some level I wonder if you could just reuse some of the shadow code for this, but that's probably a pain

@jakebailey

Copy link
Copy Markdown
Member

@typescript-bot test it

@typescript-automation

typescript-automation Bot commented Jul 23, 2026

Copy link
Copy Markdown

Starting jobs; this comment will be updated as builds start and complete.

Command Status Results
test top400 ✅ Started ✅ Results
perf test this faster ✅ Started 👀 Results

@typescript-automation

Copy link
Copy Markdown

@jakebailey
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Compiler-Unions - native
Errors 4 4 ~ ~ ~ p=1.000 n=6
Symbols 81,807 (± 0.03%) 81,804 (± 0.02%) ~ 81,782 81,827 p=0.521 n=6
Types 98,819 98,819 ~ ~ ~ p=1.000 n=6
Memory Used 177,144k (± 0.23%) 178,067k (± 0.39%) +923k (+ 0.52%) 177,033k 178,852k p=0.031 n=6
Memory Allocs 2,695,736 (± 0.01%) 2,695,812 (± 0.01%) ~ 2,695,499 2,696,193 p=0.689 n=6
Config Time 0.000s (±244.70%) 0.000s (±244.70%) ~ 0.000s 0.001s p=1.000 n=6
Parse Time 0.062s (± 9.11%) 0.063s (± 9.35%) ~ 0.055s 0.070s p=0.688 n=6
Bind Time 0.020s (±22.56%) 0.018s (±11.64%) ~ 0.015s 0.020s p=0.520 n=6
Check Time 0s 0s ~ ~ ~ p=1.000 n=6
Emit Time 0.879s (± 1.06%) 0.868s (± 1.09%) ~ 0.855s 0.881s p=0.092 n=6
Total Time 0.962s (± 0.73%) 0.950s (± 1.25%) -0.012s (- 1.23%) 0.932s 0.967s p=0.037 n=6
angular-1 - native
Errors 3 3 ~ ~ ~ p=1.000 n=6
Symbols 872,161 (± 0.19%) 872,999 (± 0.10%) ~ 871,890 873,746 p=0.378 n=6
Types 263,953 (± 0.00%) 263,962 (± 0.00%) +9 (+ 0.00%) 263,961 263,962 p=0.003 n=6
Memory Used 828,707k (± 0.14%) 828,609k (± 0.10%) ~ 827,738k 830,059k p=0.936 n=6
Memory Allocs 13,170,403 (± 0.03%) 13,174,304 (± 0.05%) ~ 13,168,409 13,187,019 p=0.575 n=6
Config Time 0.017s (± 2.42%) 0.017s (± 2.38%) ~ 0.017s 0.018s p=0.218 n=6
Parse Time 0.253s (± 3.85%) 0.255s (± 4.06%) ~ 0.244s 0.273s p=1.000 n=6
Bind Time 0.049s (±24.69%) 0.058s (±28.87%) ~ 0.042s 0.075s p=0.170 n=6
Check Time 0s 0s ~ ~ ~ p=1.000 n=6
Emit Time 1.918s (± 2.76%) 1.888s (± 1.59%) ~ 1.856s 1.934s p=0.298 n=6
Total Time 2.251s (± 2.04%) 2.231s (± 1.00%) ~ 2.211s 2.264s p=0.378 n=6
mui-docs - native
Errors 11,279 (± 0.03%) 11,279 (± 0.02%) ~ 11,274 11,281 p=0.466 n=6
Symbols 4,450,247 4,450,426 +179 (+ 0.00%) ~ ~ p=0.001 n=6
Types 1,659,961 1,660,029 +68 (+ 0.00%) ~ ~ p=0.001 n=6
Memory Used 5,072,395k (± 0.04%) 5,072,275k (± 0.04%) ~ 5,070,395k 5,075,985k p=0.936 n=6
Memory Allocs 51,244,843 (± 0.04%) 51,265,435 (± 0.08%) ~ 51,213,356 51,332,773 p=0.689 n=6
Config Time 0.017s (± 9.51%) 0.017s (± 4.47%) ~ 0.016s 0.018s p=0.485 n=6
Parse Time 0.522s (± 2.50%) 0.520s (± 1.74%) ~ 0.507s 0.526s p=1.000 n=6
Bind Time 0.002s 0.002s ~ ~ ~ p=1.000 n=6
Check Time 16.692s (± 0.87%) 16.684s (± 0.29%) ~ 16.635s 16.766s p=0.936 n=6
Emit Time 0.520s (±17.09%) 0.541s (±21.20%) ~ 0.493s 0.776s p=1.000 n=6
Total Time 18.485s (± 1.52%) 18.527s (± 0.66%) ~ 18.447s 18.768s p=0.689 n=6
self-build-src - native
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,394,141 1,394,228 +87 (+ 0.01%) ~ ~ p=0.001 n=6
Types 442,163 442,210 +47 (+ 0.01%) ~ ~ p=0.001 n=6
Memory Used 1,662,572k (± 0.35%) 1,664,706k (± 0.45%) ~ 1,656,025k 1,676,148k p=0.689 n=6
Memory Allocs 97,274,506 (± 0.05%) 97,294,380 (± 0.07%) ~ 97,219,095 97,374,392 p=0.689 n=6
Config Time 0.023s (±10.30%) 0.021s (±12.85%) ~ 0.018s 0.024s p=0.261 n=6
Parse Time 0.253s (± 1.49%) 0.257s (± 3.41%) ~ 0.247s 0.269s p=0.748 n=6
Bind Time 0.000s 0.000s (±244.70%) ~ 0.000s 0.001s p=0.405 n=6
Check Time 2.511s (± 0.43%) 2.539s (± 0.51%) +0.027s (+ 1.09%) 2.523s 2.556s p=0.008 n=6
Emit Time 0.341s (± 3.42%) 0.349s (± 4.60%) ~ 0.328s 0.369s p=0.378 n=6
Total Time 32.398s (± 0.20%) 32.747s (± 0.48%) +0.348s (+ 1.08%) 32.527s 32.982s p=0.005 n=6
self-compiler - native
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 337,634 337,689 +55 (+ 0.02%) ~ ~ p=0.001 n=6
Types 199,520 199,559 +39 (+ 0.02%) ~ ~ p=0.001 n=6
Memory Used 326,506k (± 0.05%) 326,488k (± 0.06%) ~ 326,227k 326,816k p=0.630 n=6
Memory Allocs 4,685,419 (± 0.02%) 4,685,276 (± 0.02%) ~ 4,683,856 4,686,636 p=0.810 n=6
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=6
Parse Time 0.127s (± 4.81%) 0.125s (± 4.62%) ~ 0.120s 0.135s p=0.517 n=6
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=6
Check Time 1.283s (± 0.52%) 1.285s (± 1.09%) ~ 1.270s 1.309s p=0.936 n=6
Emit Time 0.112s (± 4.75%) 0.118s (± 7.12%) ~ 0.108s 0.126s p=0.229 n=6
Total Time 1.578s (± 0.96%) 1.582s (± 1.21%) ~ 1.560s 1.615s p=1.000 n=6
ts-pre-modules - native
Errors 3 3 ~ ~ ~ p=1.000 n=6
Symbols 97,488 97,488 ~ ~ ~ p=1.000 n=6
Types 356 356 ~ ~ ~ p=1.000 n=6
Memory Used 133,543k (± 0.03%) 133,544k (± 0.03%) ~ 133,492k 133,585k p=1.000 n=6
Memory Allocs 180,419 (± 0.23%) 180,306 (± 0.19%) ~ 179,888 180,816 p=0.689 n=6
Config Time 0.000s (±244.70%) 0.001s (±48.94%) 🔻+0.001s (+400.00%) 0.000s 0.001s p=0.034 n=6
Parse Time 0.110s (± 8.96%) 0.122s (± 2.61%) 🔻+0.012s (+10.93%) 0.116s 0.125s p=0.016 n=6
Bind Time 0.035s (± 7.05%) 0.035s (±14.44%) ~ 0.030s 0.041s p=0.626 n=6
Check Time 0s 0s ~ ~ ~ p=1.000 n=6
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=6
Total Time 0.148s (± 5.98%) 0.160s (± 4.12%) 🔻+0.012s (+ 8.36%) 0.149s 0.167s p=0.025 n=6
vscode - native
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 7,275,984 7,281,038 +5,054 (+ 0.07%) ~ ~ p=0.001 n=6
Types 2,544,277 2,544,911 +634 (+ 0.02%) ~ ~ p=0.001 n=6
Memory Used 4,983,930k (± 0.02%) 4,985,917k (± 0.03%) +1,987k (+ 0.04%) 4,984,256k 4,988,480k p=0.013 n=6
Memory Allocs 37,415,147 (± 0.09%) 37,407,787 (± 0.07%) ~ 37,383,612 37,453,454 p=0.689 n=6
Config Time 0.079s (± 7.86%) 0.072s (±12.17%) ~ 0.058s 0.084s p=0.197 n=6
Parse Time 0.965s (± 4.41%) 0.919s (± 3.85%) ~ 0.867s 0.972s p=0.066 n=6
Bind Time 0.183s (±28.44%) 0.220s (±36.35%) ~ 0.151s 0.348s p=1.000 n=6
Check Time 8.509s (± 0.63%) 8.518s (± 0.96%) ~ 8.422s 8.629s p=1.000 n=6
Emit Time 2.647s (± 6.92%) 2.349s (±10.79%) 🟩-0.297s (-11.24%) 2.115s 2.658s p=0.020 n=6
Total Time 12.403s (± 0.92%) 12.100s (± 1.24%) -0.302s (- 2.44%) 11.993s 12.297s p=0.013 n=6
webpack - native
Errors 2 2 ~ ~ ~ p=1.000 n=6
Symbols 192,430 192,430 ~ ~ ~ p=1.000 n=6
Types 340 340 ~ ~ ~ p=1.000 n=6
Memory Used 237,234k (± 0.13%) 237,110k (± 0.12%) ~ 236,589k 237,403k p=0.810 n=6
Memory Allocs 984,430 (± 0.43%) 983,540 (± 0.78%) ~ 972,754 992,237 p=0.575 n=6
Config Time 0.010s (±19.72%) 0.012s (±11.02%) 🔻+0.003s (+27.12%) 0.011s 0.014s p=0.035 n=6
Parse Time 0.151s (± 2.65%) 0.154s (± 4.25%) ~ 0.141s 0.159s p=0.063 n=6
Bind Time 0s 0s ~ ~ ~ p=1.000 n=6
Check Time 0s 0s ~ ~ ~ p=1.000 n=6
Emit Time 0.052s (± 8.76%) 0.042s (±23.38%) ~ 0.031s 0.059s p=0.090 n=6
Total Time 0.214s (± 3.26%) 0.210s (± 3.07%) ~ 0.201s 0.219s p=0.419 n=6
xstate-main - native
Errors 0 0 ~ ~ ~ p=1.000 n=6
Symbols 1,064,596 1,064,618 +22 (+ 0.00%) ~ ~ p=0.001 n=6
Types 392,760 392,776 +16 (+ 0.00%) ~ ~ p=0.001 n=6
Memory Used 649,051k (± 0.03%) 649,058k (± 0.02%) ~ 648,867k 649,215k p=0.689 n=6
Memory Allocs 5,005,396 (± 0.12%) 5,005,930 (± 0.12%) ~ 4,997,726 5,016,120 p=0.936 n=6
Config Time 0.005s 0.005s (±18.57%) ~ 0.003s 0.005s p=0.176 n=6
Parse Time 0.139s (± 4.39%) 0.135s (± 6.38%) ~ 0.124s 0.146s p=0.423 n=6
Bind Time 0.032s (±22.00%) 0.037s (±21.36%) ~ 0.030s 0.050s p=0.335 n=6
Check Time 1.236s (± 1.18%) 1.233s (± 1.19%) ~ 1.215s 1.257s p=0.748 n=6
Emit Time 0.001s 0.001s ~ ~ ~ p=1.000 n=6
Total Time 1.417s (± 0.94%) 1.414s (± 1.15%) ~ 1.395s 1.437s p=0.689 n=6
System info unknown
Hosts
  • native
Scenarios
  • Compiler-Unions - native
  • angular-1 - native
  • mui-docs - native
  • self-build-src - native
  • self-compiler - native
  • ts-pre-modules - native
  • vscode - native
  • webpack - native
  • xstate-main - native
Benchmark Name Iterations
Current pr 6
Baseline baseline 6

Developer Information:

Download Benchmarks

@typescript-automation

Copy link
Copy Markdown

@jakebailey Here are the results of running the top 400 repos with tsc comparing main and refs/pull/4708/merge:

Everything looks good!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate inconsistent diagnostic output in baselines & make builds with inconsistent diagnostic output fail tests

3 participants