You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
UpdateSourcePositions builds its position map with a JavaPrinter. A JavaPrinter cannot print
JS-only node types, so those nodes — and everything beneath them — never enter the position map
and receive no Range marker.
The JavaScript printer does implement these nodes (visitBindingElement, print.ts L57); UpdateSourcePositions simply does not use it. There is no JS-side SourcePositionService
override, which looks like the natural fix location.
Minimal reproduction
// d-binding-element.tsfunctionpick(): number{return1;}exportfunctiondestructure({ a =pick()}: {a?: number}={}): number{returna;}
Run UpdateSourcePositions over the compilation unit, then walk it. The J.MethodInvocation for pick() — reached through a JS.BindingElement — has no Range marker, while ordinary
invocations elsewhere in the same file do.
A consumer that treats a missing Range after UpdateSourcePositions as a broken precondition
throws here:
java.lang.IllegalStateException: no Range marker on MethodInvocation in d-binding-element.ts
... LstCallIndex.visitMethodInvocation
... JavaScriptVisitor.visitBindingElement
Expected
Every node in a positioned compilation unit carries a Range, or the gap is documented so consumers
know a missing Range is a legitimate outcome for JS rather than a bug in their own pipeline.
Why this matters downstream
The failure is silent and partial, which is worse than loud. In our emitter the exception aborted
the compilation unit mid-scan: methods and calls had already been recorded, types had not. One
unpositioned node cost a 1,053-line file every type row it should have produced, the artifact looked
complete, and the run reported success. It surfaced only because an unrelated threshold could not
reach zero.
Any consumer that indexes a file in more than one pass is exposed to the same shape.
The fix likely belongs in a JS SourcePositionService override rather than in UpdateSourcePositions itself, which may make it larger than a drive-by change.
UpdateSourcePositionsleaves JS-only nodes and their subtrees unpositionedComponent:
rewrite-javascript/rewrite-java(UpdateSourcePositions)Versions:
rewrite-javascript8.90.0, Moderne CLI 4.6.1, TypeScript 5.9.3, Node 26.7.0What happens
UpdateSourcePositionsbuilds its position map with aJavaPrinter. AJavaPrintercannot printJS-only node types, so those nodes — and everything beneath them — never enter the position map
and receive no
Rangemarker.The JavaScript printer does implement these nodes (
visitBindingElement,print.tsL57);UpdateSourcePositionssimply does not use it. There is no JS-sideSourcePositionServiceoverride, which looks like the natural fix location.
Minimal reproduction
Run
UpdateSourcePositionsover the compilation unit, then walk it. TheJ.MethodInvocationforpick()— reached through aJS.BindingElement— has noRangemarker, while ordinaryinvocations elsewhere in the same file do.
A consumer that treats a missing
RangeafterUpdateSourcePositionsas a broken preconditionthrows here:
Expected
Every node in a positioned compilation unit carries a
Range, or the gap is documented so consumersknow a missing
Rangeis a legitimate outcome for JS rather than a bug in their own pipeline.Why this matters downstream
The failure is silent and partial, which is worse than loud. In our emitter the exception aborted
the compilation unit mid-scan: methods and calls had already been recorded, types had not. One
unpositioned node cost a 1,053-line file every type row it should have produced, the artifact looked
complete, and the run reported success. It surfaced only because an unrelated threshold could not
reach zero.
Any consumer that indexes a file in more than one pass is exposed to the same shape.
Timing / related
TypeUsesandMethodCalls#8454 (line numbers inTypeUses/MethodCalls) isJavaPrinter-based viaSourcePositionServiceand will inherit this gap for JS sources. Filing now, while that work isin flight, so the two can be considered together.
SourcePositionServiceoverride rather than inUpdateSourcePositionsitself, which may make it larger than a drive-by change.