Skip to content

[js_interop_gen] Deduplicate UnionType and IntersectionType via UnionOrIntersectionType - #578

Merged
kevmoo merged 2 commits into
mainfrom
dedupe-union-intersection-ast
Sep 30, 2026
Merged

kevmoo merged 2 commits into
mainfrom
dedupe-union-intersection-ast

Conversation

@kevmoo

@kevmoo kevmoo commented Sep 19, 2026 •

Copy link
Copy Markdown
Member

Deduplicates UnionType and IntersectionType in js_interop_gen (lib/src/ast/types.dart):

  • Extracts sealed class UnionOrIntersectionType extends DeclarationType to hold the shared types, declarationName, id, emit, hashCode, and == implementations (~45 duplicated lines removed).
  • Bug Fix: Fixes a copy-paste bug in both UnionType.operator == and IntersectionType.operator ==, which previously checked other is TupleType (causing equality comparisons between two UnionTypes or two IntersectionTypes to always evaluate to false), and fixes IntersectionType.== to check other.homogenous instead of homogenous.
  • Simplifies UnionType | IntersectionType pattern matching in lib/src/ast/helpers.dart (UnnamedUnionOrIntersectionLength) and lib/src/interop_gen/transform/dependency_walker.dart to match directly on UnionOrIntersectionType.
  • Updates compileDartMain() in lib/src/cli.dart to compile to a temporary .tmp path and atomically renameSync into lib/src/js/dart_main.js (RandomAccessFile.lock() uses POSIX fcntl locks, which are per-process/PID rather than per-isolate and fail to prevent concurrent dart test isolates in the same VM from truncating dart_main.js mid-read).

🤖 Tool Provenance & Reproduction

Structural duplication analysis (cluster-47) performed with dedupe (v0.1.0).

To reproduce or re-run this duplication scan locally:

dart run dedupe@^0.1.0

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request refactors UnionType and IntersectionType to inherit from a new sealed base class UnionOrIntersectionType to share common logic, and updates compileDartMain to compile to a temporary file before renaming it to the final destination. The review feedback highlights two critical issues: first, the operator == implementation in UnionOrIntersectionType is not symmetric and violates the equivalence contract when comparing types of different lengths; second, File.renameSync in cli.dart will fail on Windows if the destination file already exists, so the target file should be deleted beforehand.

Comment thread js_interop_gen/lib/src/ast/types.dart Resolved
Comment thread js_interop_gen/lib/src/cli.dart Resolved
@kevmoo
kevmoo requested a review from srujzs September 20, 2026 05:31
kevmoo added a commit to kevmoo/web.dart that referenced this pull request Sep 20, 2026
…te type caching

Stacked on dart-lang#578.

- Extract `_transformConditionalType`, `_transformTypeLiteral`,
  `_transformClosureType`, `_transformUnionType`,
  `_transformIntersectionType`, and `_transformIndexedAccessType` from
  `Transformer._transformType` in
  `lib/src/interop_gen/transform/transformer.dart`, reducing
  `Transformer._transformType` cognitive complexity from `190` to `59` (-68.9%).
- Extract `_filterNonNullableTypeNodes` and `_getOrCreateCachedType` helpers on
  `Transformer`, eliminating duplicate union/intersection filtering and
  `typeMap` caching blocks (`pkg:dedupe` `cluster-45`, `cluster-51`, and
  `cluster-52`).
@kevmoo
kevmoo added this pull request to stack #581 September 20, 2026 16:40
@kevmoo
kevmoo removed this pull request from stack #581 September 20, 2026 17:34
@kevmoo
kevmoo added this pull request to stack #583 September 20, 2026 17:35
kevmoo added a commit that referenced this pull request Sep 28, 2026
…te type caching

Stacked on #578.

- Extract `_transformConditionalType`, `_transformTypeLiteral`,
  `_transformClosureType`, `_transformUnionType`,
  `_transformIntersectionType`, and `_transformIndexedAccessType` from
  `Transformer._transformType` in
  `lib/src/interop_gen/transform/transformer.dart`, reducing
  `Transformer._transformType` cognitive complexity from `190` to `59` (-68.9%).
- Extract `_filterNonNullableTypeNodes` and `_getOrCreateCachedType` helpers on
  `Transformer`, eliminating duplicate union/intersection filtering and
  `typeMap` caching blocks (`pkg:dedupe` `cluster-45`, `cluster-51`, and
  `cluster-52`).
@kevmoo
kevmoo force-pushed the dedupe-union-intersection-ast branch from 3730de7 to 6144b43 Compare September 28, 2026 17:07
kevmoo added a commit that referenced this pull request Sep 29, 2026
…te type caching

Stacked on #578.

- Extract `_transformConditionalType`, `_transformTypeLiteral`,
  `_transformClosureType`, `_transformUnionType`,
  `_transformIntersectionType`, and `_transformIndexedAccessType` from
  `Transformer._transformType` in
  `lib/src/interop_gen/transform/transformer.dart`, reducing
  `Transformer._transformType` cognitive complexity from `190` to `59` (-68.9%).
- Extract `_filterNonNullableTypeNodes` and `_getOrCreateCachedType` helpers on
  `Transformer`, eliminating duplicate union/intersection filtering and
  `typeMap` caching blocks (`pkg:dedupe` `cluster-45`, `cluster-51`, and
  `cluster-52`).
@kevmoo
kevmoo force-pushed the dedupe-union-intersection-ast branch from 6144b43 to c0bb468 Compare September 29, 2026 16:51
Base automatically changed from undead-cleanup to main September 29, 2026 19:17
…UnionOrIntersectionType`

Stacked on #577.

- Extract `sealed class UnionOrIntersectionType extends DeclarationType` in
  `lib/src/ast/types.dart` (mirroring `_UnionOrIntersectionDeclaration`) to
  share `types`, `isNullable`, `declarationName`, `id`, `emit()`, `hashCode`,
  and `operator ==` across `UnionType` and `IntersectionType` (`pkg:dedupe`
  `cluster-47`).
- Fix `UnionType.==` and `IntersectionType.==`, which previously checked
  `other is TupleType` due to copy-paste.
- Consolidate `UnionType` / `IntersectionType` pattern cases in
  `lib/src/ast/helpers.dart` and
  `lib/src/interop_gen/transform/dependency_walker.dart`.
- Write `dart_main.js` via an atomic temporary file rename in
  `compileDartMain()` (`lib/src/cli.dart`) so parallel `dart test` isolates in
  the same VM process cannot truncate `dart_main.js` while `node main.mjs` is
  loading it.
kevmoo added a commit that referenced this pull request Sep 29, 2026
…te type caching

Stacked on #578.

- Extract `_transformConditionalType`, `_transformTypeLiteral`,
  `_transformClosureType`, `_transformUnionType`,
  `_transformIntersectionType`, and `_transformIndexedAccessType` from
  `Transformer._transformType` in
  `lib/src/interop_gen/transform/transformer.dart`, reducing
  `Transformer._transformType` cognitive complexity from `190` to `59` (-68.9%).
- Extract `_filterNonNullableTypeNodes` and `_getOrCreateCachedType` helpers on
  `Transformer`, eliminating duplicate union/intersection filtering and
  `typeMap` caching blocks (`pkg:dedupe` `cluster-45`, `cluster-51`, and
  `cluster-52`).
@kevmoo
kevmoo force-pushed the dedupe-union-intersection-ast branch from c0bb468 to 9223b54 Compare September 29, 2026 19:17

@srujzs srujzs 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.

Thanks!

@kevmoo
kevmoo merged commit 6f3dd4e into main Sep 30, 2026
21 checks passed
@kevmoo
kevmoo deleted the dedupe-union-intersection-ast branch September 30, 2026 15:12
kevmoo added a commit that referenced this pull request Sep 30, 2026
…te type caching (#579)

* [js_interop_gen] Decompose `Transformer._transformType` and deduplicate type caching

Stacked on #578.

- Extract `_transformConditionalType`, `_transformTypeLiteral`,
  `_transformClosureType`, `_transformUnionType`,
  `_transformIntersectionType`, and `_transformIndexedAccessType` from
  `Transformer._transformType` in
  `lib/src/interop_gen/transform/transformer.dart`, reducing
  `Transformer._transformType` cognitive complexity from `190` to `59` (-68.9%).
- Extract `_filterNonNullableTypeNodes` and `_getOrCreateCachedType` helpers on
  `Transformer`, eliminating duplicate union/intersection filtering and
  `typeMap` caching blocks (`pkg:dedupe` `cluster-45`, `cluster-51`, and
  `cluster-52`).

* chore(js_interop_gen): restore original inline comments in extracted type helpers
kevmoo added a commit that referenced this pull request Sep 30, 2026
…ransformer (#580)

* [js_interop_gen] Require `code_builder: ^4.12.0` and update golden headers

`package:code_builder` `4.12.0` fixed dart-lang/tools#2404
by emitting scoped lint ignores (`no_leading_underscores_for_library_prefixes`)
directly in the sorted top-of-file `// ignore_for_file:` block before library
annotations and directives.

- Bump `code_builder` dependency constraint to `^4.12.0` (compatible with
  `sdk: ^3.10.0`, preserving `js_interop_gen`'s `sdk: ^3.12.0` constraint).
- Remove the now-obsolete `replaceFirstMapped` regex workaround for
  `dart-lang/tools#2404` in `lib/src/interop_gen/transform.dart`.
- Regenerate the expected test golden headers across `test/`.

* [js_interop_gen] Remove unused JS interop extension types and bindings

Stacked on #576.

Remove 13 unreferenced declarations identified by `pkg:undead`
(`--extra-roots=lib/src/dart_main.dart`):
- `createSourceFile` in `lib/src/js/typescript.dart`
- `InterfacelikeExtension` in `lib/src/js/webidl_api.dart`
- 11 unused TypeScript AST extension types in
  `lib/src/js/typescript.types.dart` (`TSTypePredicateNode`,
  `TSNamedTupleMember`, `TSFunctionTypeNode`, `TSConstructorTypeNode`,
  `TSPropertyAccessExpression`, `TSNamespaceExport`, `TSExportAssignment`,
  `TSClassDeclaration`, `TSInterfaceDeclaration`, `TSPropertyDeclaration`,
  `TSMethodDeclaration`)

* [js_interop_gen] Deduplicate `UnionType` and `IntersectionType` via `UnionOrIntersectionType`

Stacked on #577.

- Extract `sealed class UnionOrIntersectionType extends DeclarationType` in
  `lib/src/ast/types.dart` (mirroring `_UnionOrIntersectionDeclaration`) to
  share `types`, `isNullable`, `declarationName`, `id`, `emit()`, `hashCode`,
  and `operator ==` across `UnionType` and `IntersectionType` (`pkg:dedupe`
  `cluster-47`).
- Fix `UnionType.==` and `IntersectionType.==`, which previously checked
  `other is TupleType` due to copy-paste.
- Consolidate `UnionType` / `IntersectionType` pattern cases in
  `lib/src/ast/helpers.dart` and
  `lib/src/interop_gen/transform/dependency_walker.dart`.
- Write `dart_main.js` via an atomic temporary file rename in
  `compileDartMain()` (`lib/src/cli.dart`) so parallel `dart test` isolates in
  the same VM process cannot truncate `dart_main.js` while `node main.mjs` is
  loading it.

* [js_interop_gen] Decompose `Transformer._transformType` and deduplicate type caching

Stacked on #578.

- Extract `_transformConditionalType`, `_transformTypeLiteral`,
  `_transformClosureType`, `_transformUnionType`,
  `_transformIntersectionType`, and `_transformIndexedAccessType` from
  `Transformer._transformType` in
  `lib/src/interop_gen/transform/transformer.dart`, reducing
  `Transformer._transformType` cognitive complexity from `190` to `59` (-68.9%).
- Extract `_filterNonNullableTypeNodes` and `_getOrCreateCachedType` helpers on
  `Transformer`, eliminating duplicate union/intersection filtering and
  `typeMap` caching blocks (`pkg:dedupe` `cluster-45`, `cluster-51`, and
  `cluster-52`).

* Enforce symmetric equality and length check in UnionOrIntersectionType.==

* [js_interop_gen] Split union/intersection AST types and extract TypeTransformer

* chore(js_interop_gen): restore original inline comments in extracted type helpers

* chore(js_interop_gen): revert unrelated formatting change in translator.dart

* fix(js_interop_gen): update js_type_supertypes for Dart 3.12 and prefer JSObject over JSIterable

* fix(js_interop_gen): write compileDartMain output atomically

* refactor(js_interop_gen): use firstWhere in computeJsTypeSupertypes
copybara-service Bot pushed a commit to dart-lang/sdk that referenced this pull request Oct 7, 2026
Revisions updated by `dart tools/rev_sdk_deps.dart`.

core (https://github.com/dart-lang/core/compare/08e4022..4d80610):
  4d80610a  Thu Oct 1 22:03:38 2026 +0000  dependabot[bot]  Bump the github-actions group with 5 updates (dart-lang/core#1005)

dartdoc (https://github.com/dart-lang/dartdoc/compare/2a040a8..5eb0f2c):
  5eb0f2c7  Thu Oct 1 19:03:48 2026 +0000  dependabot[bot]  Bump github/codeql-action/upload-sarif from 4.37.9 to 4.38.2 in the github-actions group (dart-lang/dartdoc#4291)

http (https://github.com/dart-lang/http/compare/d8e8e9c..585d433):
  585d433  Mon Oct 5 16:12:54 2026 -0700  Brian Quinlan  fix(cupertino_http): fix a websocket memory leak (dart-lang/http#1991)
  337adf3  Mon Oct 5 16:03:25 2026 -0700  Brian Quinlan  fix(cupertino_http): add `autoReleasePool` use to `CupertinoClient` (dart-lang/http#1990)
  47c57df  Tue Sep 29 14:07:01 2026 -0700  Brian Quinlan  fix(ok_http): fix `NetworkOnMainThreadException` (dart-lang/http#1995)
  d8cde5d  Tue Sep 29 14:06:44 2026 -0700  Brian Quinlan  fix test (dart-lang/http#1996)
  31056fe  Tue Sep 29 13:57:20 2026 -0700  Brian Quinlan  chore(cronet_http): prepare to release 1.10.0 (dart-lang/http#1993)
  9bc3a91  Tue Sep 29 13:53:25 2026 -0700  Brian Quinlan  fix(cronet_http): one global reference per `onReadCompleted` (dart-lang/http#1992)
  49ecd36  Mon Sep 28 14:20:26 2026 -0700  Brian Quinlan  fix(conformance): `supportsAbort` not considered in response (dart-lang/http#1994)

native (https://github.com/dart-lang/native/compare/27f7678..a2a6179):
  a2a617910  Tue Oct 6 13:53:17 2026 +0200  Daco Harkes  [jni_flutter] Bump version for publishing (dart-lang/native#3730)
  d3a99d66b  Tue Oct 6 19:46:34 2026 +1100  Liam Appelbe  [infra] Fix ffigen and jni_flutter (dart-lang/native#3724)
  b66d0815a  Tue Oct 6 04:28:35 2026 +0300  Manar Elhabbal  [ffigen] add Support passing C++ classes by value  (dart-lang/native#3677)
  f7ffe9667  Fri Oct 2 11:33:49 2026 +0200  Moritz  [native_toolchain_c] Don't pass /INCLUDE per symbol with a generated .def on Windows (dart-lang/native#3718)
  77a5e4169  Thu Oct 1 10:56:45 2026 +0300  Hassnaa Mohamed  [ffigen] Fix cpp method filtering (dart-lang/native#3696)
  cca065ca6  Thu Oct 1 10:17:12 2026 +1000  Liam Appelbe  [infra] Prepare to publish everything (dart-lang/native#3716)
  f13623ee3  Thu Oct 1 10:16:39 2026 +1000  Liam Appelbe  [jnigen] API docs (dart-lang/native#3715)
  be618790c  Thu Oct 1 10:05:26 2026 +1000  Liam Appelbe  [objective_c] API docs (dart-lang/native#3708)
  a18dd1148  Thu Oct 1 10:04:38 2026 +1000  Liam Appelbe  [ffigen] API docs (dart-lang/native#3707)
  6fd87c3b2  Tue Sep 29 19:01:11 2026 -0700  Brian Quinlan  [jni] Clarify `JBuffer.asUint8List` behavior (dart-lang/native#3704)
  6d5bbcfad  Wed Sep 30 09:35:47 2026 +1000  Liam Appelbe  [jni] API documentation (dart-lang/native#3706)
  fbcbc894b  Wed Sep 30 09:35:34 2026 +1000  Liam Appelbe  [ffigen] Document autorelease issues (dart-lang/native#3705)
  f99449ec9  Tue Sep 29 09:39:27 2026 +1000  Liam Appelbe  [infra] Add swift2objc to the workspace (dart-lang/native#3700)
  31494fa08  Tue Sep 29 09:38:59 2026 +1000  Liam Appelbe  [infra] Add jni_util to the workspace (dart-lang/native#3698)

shelf (https://github.com/dart-lang/shelf/compare/e5c8dc6..b2cb503):
  b2cb503  Wed Sep 30 22:53:07 2026 -0700  Kevin Moore  Resolve shelf.io.connection_info lazily (dart-lang/shelf#542)
  b70fafa  Tue Sep 29 13:37:08 2026 -0700  Kevin Moore  Match parameterless shelf_router routes without running a regex (dart-lang/shelf#544)

test (https://github.com/dart-lang/test/compare/4f92d53..d749b10):
  d749b104  Mon Oct 5 15:42:46 2026 -0700  Nate Bosch  Fail isolate suites when the test isolate exits (dart-lang/test#2775)
  da2157e9  Mon Oct 5 11:12:43 2026 -0700  Nate Bosch  Wait longer for the Chrome test tab to appear (dart-lang/test#2771)
  00bd0c99  Mon Oct 5 18:50:03 2026 +0300  Yusuf İhsan Görgel  Fix broken links in architecture.md (dart-lang/test#2774)
  3be2f547  Thu Oct 1 03:46:29 2026 +0000  dependabot[bot]  Bump the github-actions group with 4 updates (dart-lang/test#2773)
  40a5ad90  Tue Sep 29 12:07:31 2026 -0700  Nate Bosch  Delete compilation artifacts once they are no longer needed (dart-lang/test#2764)
  171ad0e5  Mon Sep 28 17:29:48 2026 -0700  Jacob MacDonald  export additional types from package:test_api/backend.dart (dart-lang/test#2745)
  52b45064  Mon Sep 28 15:04:08 2026 -0700  Nate Bosch  Tag browser and node tests, relax flaky timeouts (dart-lang/test#2770)

tools (https://github.com/dart-lang/tools/compare/d87eaf7..a66d517):
  a66d517d  Tue Oct 6 09:41:32 2026 -0700  Phil Quitslund  [analytics] `DASH__SUPPRESS_ANALYTICS` env handling (dart-lang/tools#2641)
  00c6e4ad  Fri Oct 2 17:17:49 2026 +0530  shivytyahoo  Fix VersionConstraint.intersection throwing on disjoint ranges (dart-lang/tools#2622)
  d523e1f8  Thu Oct 1 11:09:16 2026 +0200  Morgan :)  [unified_analytics] Append to the log file instead of rewriting it (dart-lang/tools#2613)
  6993cbad  Wed Sep 30 14:09:32 2026 +0300  Yusuf İhsan Görgel  [yaml] Improve error messages when mixing list and key-value syntax (dart-lang/tools#2610)
  068119b4  Tue Sep 29 23:21:03 2026 +0200  Lukas Klingsbo  [pubspec_parse] Support tag_pattern for git dependencies (dart-lang/tools#2565)
  7d859ed5  Mon Sep 28 20:28:23 2026 -0700  Kevin Moore  [api_summary] Add expectApiSummaryClean and --write/--check CLI flags (dart-lang/tools#2603)

web (https://github.com/dart-lang/web/compare/ec71a4c..63e6662):
  63e6662  Sat Oct 3 00:23:21 2026 +0000  Natalie Weizenbaum  Add a JSPair type (dart-lang/web#586)
  2d68d90  Fri Oct 2 20:26:48 2026 +0000  Natalie Weizenbaum  Use `js_interop` APIs in `js_interop_gen` (dart-lang/web#585)
  037823c  Thu Oct 1 21:59:21 2026 +0000  Natalie Weizenbaum  Add JSMap, JSSet, and JSSetLike types (dart-lang/web#571)
  b2d1d6b  Thu Oct 1 06:57:03 2026 +0000  dependabot[bot]  Bump the github-actions group with 3 updates (dart-lang/web#584)
  8dc8f75  Wed Sep 30 08:12:18 2026 -0700  Kevin Moore  [js_interop_gen] Split union/intersection AST types and extract TypeTransformer (dart-lang/web#580)
  751ccdf  Wed Sep 30 08:12:18 2026 -0700  Kevin Moore  [js_interop_gen] Decompose `Transformer._transformType` and deduplicate type caching (dart-lang/web#579)
  6f3dd4e  Wed Sep 30 08:12:17 2026 -0700  Kevin Moore  [js_interop_gen] Deduplicate `UnionType` and `IntersectionType` via `UnionOrIntersectionType` (dart-lang/web#578)
  d9f095e  Tue Sep 29 12:17:29 2026 -0700  Kevin Moore  [js_interop_gen] Remove unused JS interop extension types and bindings (dart-lang/web#577)
  07111ee  Tue Sep 29 09:51:36 2026 -0700  Kevin Moore  fix(js_interop_gen): update js_type_supertypes for Dart 3.12 (dart-lang/web#582)

Change-Id: I4532049c45561fe8f8c57713ac8ec2153096fd9a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/560660
Commit-Queue: Nate Bosch <[email protected]>
Reviewed-by: Brian Quinlan <[email protected]>
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.

2 participants