Skip to content

Commit b278318

Browse files
committed
Remove unnecessary defensive checks and redundant as-unknown casts
- Remove defensive ?. and ?? on padding properties in visitRightPadded and visitLeftPadded (padding is always present) - Remove unnecessary as-unknown-as casts where intersection types already make padded values assignable to the target type - Clean up tabs-and-indents-visitor: remove dead DEBUG logging, unused findMarker import, and inline trivial wrapper methods - Remove stale "For tree types" comments
1 parent f41ffcb commit b278318

13 files changed

Lines changed: 47 additions & 148 deletions

File tree

rewrite-javascript/rewrite/src/java/visitor.ts

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,30 +1231,25 @@ export class JavaVisitor<P> extends TreeVisitor<J, P> {
12311231
public async visitRightPadded<T extends J | boolean>(right: J.RightPadded<T>, p: P): Promise<J.RightPadded<T> | undefined> {
12321232
this.cursor = new Cursor(right, this.cursor);
12331233

1234-
// Check if this is a primitive wrapper (has 'element' property) or intersection type (tree node)
12351234
const hasElement = 'element' in right;
12361235
const visitedElement: T | undefined = hasElement
12371236
? (right as { element: boolean }).element as T
12381237
: await this.visitDefined(right as J, p) as T | undefined;
12391238

1240-
// Handle missing padding (can happen with template-generated trees)
1241-
const after = await this.visitSpace(right.padding?.after ?? emptySpace, p);
1242-
const paddingMarkers = await this.visitMarkers(right.padding?.markers ?? emptyMarkers, p);
1239+
const after = await this.visitSpace(right.padding.after, p);
1240+
const paddingMarkers = await this.visitMarkers(right.padding.markers, p);
12431241
this.cursor = this.cursor.parent!;
12441242

12451243
if (visitedElement === undefined) {
12461244
return undefined;
12471245
}
12481246

1249-
// Build padding, preserving identity if unchanged
1250-
const beforePadding = right.padding;
1251-
const paddingUnchanged = after === beforePadding?.after && paddingMarkers === beforePadding?.markers;
1252-
const padding: J.Suffix = paddingUnchanged ? beforePadding! : { after, markers: paddingMarkers };
1247+
const paddingUnchanged = after === right.padding.after && paddingMarkers === right.padding.markers;
1248+
const padding: J.Suffix = paddingUnchanged ? right.padding : { after, markers: paddingMarkers };
12531249

12541250
if (hasElement) {
12551251
return updateIfChanged(right, { element: visitedElement, padding } as any);
12561252
}
1257-
// Tree node - merge visited element with padding using updateIfChanged
12581253
return updateIfChanged(visitedElement as J & { padding: J.Suffix }, { padding }) as J.RightPadded<T>;
12591254
}
12601255

@@ -1279,10 +1274,8 @@ export class JavaVisitor<P> extends TreeVisitor<J, P> {
12791274
public async visitLeftPadded<T extends J | J.Space | number | string | boolean>(left: J.LeftPadded<T>, p: P): Promise<J.LeftPadded<T> | undefined>;
12801275
public async visitLeftPadded<T extends J | J.Space | number | string | boolean>(left: J.LeftPadded<T>, p: P): Promise<J.LeftPadded<T> | undefined> {
12811276
this.cursor = new Cursor(left, this.cursor);
1282-
// Handle missing padding (can happen with template-generated trees)
1283-
const before = await this.visitSpace(left.padding?.before ?? emptySpace, p);
1277+
const before = await this.visitSpace(left.padding.before, p);
12841278

1285-
// Check if this is a primitive wrapper (has 'element' property) or intersection type (tree node/Space)
12861279
const hasElement = 'element' in left;
12871280
let visitedElement: T | undefined;
12881281

@@ -1294,22 +1287,19 @@ export class JavaVisitor<P> extends TreeVisitor<J, P> {
12941287
visitedElement = await this.visitDefined(left as J, p) as T | undefined;
12951288
}
12961289

1297-
const paddingMarkers = await this.visitMarkers(left.padding?.markers ?? emptyMarkers, p);
1290+
const paddingMarkers = await this.visitMarkers(left.padding.markers, p);
12981291
this.cursor = this.cursor.parent!;
12991292

13001293
if (visitedElement === undefined) {
13011294
return undefined;
13021295
}
13031296

1304-
// Build padding, preserving identity if unchanged
1305-
const beforePadding = left.padding;
1306-
const paddingUnchanged = before === beforePadding?.before && paddingMarkers === beforePadding?.markers;
1307-
const padding: J.Prefix = paddingUnchanged ? beforePadding! : { before, markers: paddingMarkers };
1297+
const paddingUnchanged = before === left.padding.before && paddingMarkers === left.padding.markers;
1298+
const padding: J.Prefix = paddingUnchanged ? left.padding : { before, markers: paddingMarkers };
13081299

13091300
if (hasElement) {
13101301
return updateIfChanged(left, { element: visitedElement, padding } as any);
13111302
}
1312-
// Tree node or Space - merge visited element with padding using updateIfChanged
13131303
return updateIfChanged(visitedElement as (J | J.Space) & { padding: J.Prefix }, { padding }) as J.LeftPadded<T>;
13141304
}
13151305

rewrite-javascript/rewrite/src/javascript/cleanup/prefer-optional-chain.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export class PreferOptionalChain extends Recipe {
5454
// Check if the false part is undefined
5555
// Note: We only convert when the false part is undefined, not null,
5656
// because optional chaining returns undefined (not null) when the target is nullish.
57-
// For tree types, the padded value IS the element (intersection type)
5857
const falsePart = visited.falsePart as unknown as Expression;
5958
const isUndefinedFalse = falsePart.kind === J.Kind.Identifier &&
6059
(falsePart as J.Identifier).simpleName === 'undefined';
@@ -64,7 +63,6 @@ export class PreferOptionalChain extends Recipe {
6463
}
6564

6665
// Check if the true part accesses a property/method on the condition
67-
// For tree types, the padded value IS the element (intersection type)
6866
const truePart = visited.truePart as unknown as Expression;
6967
const result = this.extractOptionalChainTarget(truePart, conditionName);
7068

@@ -120,7 +118,6 @@ export class PreferOptionalChain extends Recipe {
120118
// Handle MethodInvocation: foo.bar()
121119
if (expr.kind === J.Kind.MethodInvocation) {
122120
const methodInvocation = expr as J.MethodInvocation;
123-
// For tree types, the padded value IS the element (intersection type)
124121
const selectExpr = methodInvocation.select as unknown as Expression | undefined;
125122
if (selectExpr?.kind === J.Kind.Identifier) {
126123
const select = selectExpr as J.Identifier;

rewrite-javascript/rewrite/src/javascript/cleanup/use-object-property-shorthand.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,8 @@ export class UseObjectPropertyShorthand extends Recipe {
5353

5454
// For tree types, the padded value IS the element (intersection type)
5555
const simplifiedBindings = visited.bindings.elements.map(right => {
56-
// right IS the element with padding mixed in
5756
if (right.kind === JS.Kind.BindingElement) {
5857
const binding = right as unknown as JS.BindingElement;
59-
60-
// For tree types, propertyName IS the identifier with padding mixed in
6158
const propNameExpr = binding.propertyName as unknown as Expression | undefined;
6259
if (propNameExpr?.kind === J.Kind.Identifier) {
6360
const propName = (propNameExpr as J.Identifier).simpleName;
@@ -112,13 +109,9 @@ export class UseObjectPropertyShorthand extends Recipe {
112109

113110
let hasChanges = false;
114111

115-
// For tree types, the padded value IS the element (intersection type)
116112
const simplifiedStatements = statements.map(stmt => {
117-
// stmt IS the statement with padding mixed in
118113
if (stmt.kind === JS.Kind.PropertyAssignment) {
119114
const prop = stmt as unknown as JS.PropertyAssignment;
120-
121-
// For tree types, name IS the identifier with padding mixed in
122115
const nameExpr = prop.name as unknown as Expression;
123116
if (nameExpr.kind === J.Kind.Identifier) {
124117
const propName = (nameExpr as J.Identifier).simpleName;

rewrite-javascript/rewrite/src/javascript/comparator.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2260,8 +2260,7 @@ export class JavaScriptSemanticComparatorVisitor extends JavaScriptComparatorVis
22602260
* Returns the simple name if the property is an identifier, undefined otherwise.
22612261
*/
22622262
private getPropertyName(prop: JS.PropertyAssignment): string | undefined {
2263-
// For tree types, the padded value IS the element (no .element property)
2264-
const nameExpr = prop.name as unknown as Expression;
2263+
const nameExpr = prop.name;
22652264
return isIdentifier(nameExpr) ? nameExpr.simpleName : undefined;
22662265
}
22672266

@@ -2291,8 +2290,7 @@ export class JavaScriptSemanticComparatorVisitor extends JavaScriptComparatorVis
22912290
return undefined;
22922291
}
22932292

2294-
// With intersection types, the statement IS the padded value (no .element property)
2295-
const stmt = block.statements[0] as unknown as Statement;
2293+
const stmt = block.statements[0];
22962294

22972295
if ((stmt as any).kind !== J.Kind.Return) {
22982296
return undefined;

rewrite-javascript/rewrite/src/javascript/format/tabs-and-indents-visitor.ts

Lines changed: 8 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import {Cursor, isScope, isTree, Tree} from "../../tree";
3535
import {mapAsync} from "../../util";
3636
import {produceAsync} from "../../visitor";
3737
import {TabsAndIndentsStyle} from "../style";
38-
import {findMarker} from "../../markers";
3938

4039
type IndentKind = 'block' | 'continuation' | 'align';
4140
type IndentContext = [number, IndentKind]; // [indent, kind]
@@ -215,10 +214,7 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
215214

216215
private prefixContainsNewline(tree: J): boolean {
217216
// Check if the element starts on a new line (only the last whitespace matters)
218-
if (tree.prefix && lastWhitespace(tree.prefix).includes("\n")) {
219-
return true;
220-
}
221-
return false;
217+
return !!(tree.prefix && lastWhitespace(tree.prefix).includes("\n"));
222218
}
223219

224220
private isJsxChildElement(tree: J): boolean {
@@ -556,10 +552,6 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
556552
// Restore cursor
557553
this.cursor = this.cursor.parent!;
558554

559-
// For tree types, ret IS the element (intersection type); check if undefined directly
560-
if (ret === undefined) {
561-
return undefined;
562-
}
563555
return ret;
564556
}
565557

@@ -627,8 +619,7 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
627619
// PropertyAssignment wrapping a spread (for object spread like `...obj`)
628620
if (element.kind === JS.Kind.PropertyAssignment) {
629621
const propAssign = element as JS.PropertyAssignment;
630-
// For tree types, name IS the expression with padding mixed in
631-
const nameElement = propAssign.name as unknown as J | undefined;
622+
const nameElement = propAssign.name;
632623
if (nameElement?.kind === JS.Kind.Spread) {
633624
return true;
634625
}
@@ -654,8 +645,6 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
654645
let anchorCursor: Cursor | undefined;
655646
let anchorIndent = 0;
656647

657-
const DEBUG = false; // Set to true to enable debug logging
658-
659648
for (let c = this.cursor.parent; c; c = c.parent) {
660649
path.push(c);
661650
const v = c.value;
@@ -665,7 +654,6 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
665654
if (isJavaWithPrefix && !anchorCursor) {
666655
const ws = lastWhitespace(v.prefix);
667656
const idx = ws.lastIndexOf('\n');
668-
if (DEBUG) console.log(` CHECK ${v.kind}: prefix=${JSON.stringify(ws.substring(0, 50))} hasNewline=${idx !== -1}`);
669657
if (idx !== -1) {
670658
anchorCursor = c;
671659
anchorIndent = ws.length - idx - 1;
@@ -684,18 +672,6 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
684672
if (path.length === 0) return;
685673
path.reverse();
686674

687-
if (DEBUG) {
688-
console.log(`PATH (raw): ${path.map(p => {
689-
const v = p.value as any;
690-
const isRP = this.isRightPaddedWrapper(v);
691-
const isLP = this.isLeftPaddedWrapper(v);
692-
const isCont = v?.kind === J.Kind.Container;
693-
const wrapper = isRP ? '[RP]' : isLP ? '[LP]' : isCont ? '[C]' : '';
694-
return `${v?.kind || 'unknown'}${wrapper}`;
695-
}).join(' -> ')}`);
696-
console.log(`ANCHOR: ${anchorCursor ? (anchorCursor.value as any)?.kind : 'none'} at indent ${anchorIndent}`);
697-
}
698-
699675
// Process ancestors from root to leaf
700676
for (let i = 0; i < path.length; i++) {
701677
const c = path[i];
@@ -708,22 +684,21 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
708684
if (c === anchorCursor && !c.messages.has("indentContext")) {
709685
const ctx: IndentContext = [anchorIndent, 'align'];
710686
c.messages.set("indentContext", ctx);
711-
if (DEBUG) console.log(`SET (anchor): ${v.kind} -> [${ctx[0]}, ${ctx[1]}]`);
712687
continue;
713688
}
714689

715690
// Handle wrapper types (RightPadded, LeftPadded, Container)
716691
// These need their context set up for proper indent propagation
717692
// Note: RightPadded<J> intersection types have the element's kind, not J.Kind.RightPadded
718693
// So we detect them by checking for padding.after property
719-
if (this.isRightPaddedWrapper(v)) {
694+
if (isRightPadded(v)) {
720695
const savedCursor = this.cursor;
721696
this.cursor = c;
722697
this.preVisitRightPadded(v);
723698
this.cursor = savedCursor;
724699
continue;
725700
}
726-
if (this.isLeftPaddedWrapper(v)) {
701+
if (isLeftPadded(v)) {
727702
const savedCursor = this.cursor;
728703
this.cursor = c;
729704
this.preVisitLeftPadded(v);
@@ -745,11 +720,6 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
745720
// Only set up context if not already set (e.g., by If->Block handling above)
746721
if (!c.messages.has("indentContext")) {
747722
this.setupCursorMessagesForTree(c, v);
748-
const ctx = c.messages.get("indentContext") as IndentContext;
749-
if (DEBUG) console.log(`SET (computed): ${v.kind} -> [${ctx?.[0]}, ${ctx?.[1]}]`);
750-
} else {
751-
const ctx = c.messages.get("indentContext") as IndentContext;
752-
if (DEBUG) console.log(`SKIP (already set): ${v.kind} -> [${ctx?.[0]}, ${ctx?.[1]}]`);
753723
}
754724
this.cursor = savedCursor;
755725

@@ -763,7 +733,7 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
763733
if (nextCursor !== anchorCursor) {
764734
const nextValue = nextCursor.value;
765735
// Check if next is a statement (J node, not a wrapper type)
766-
if (this.isActualJNode(nextValue) && !this.isRightPaddedWrapper(nextValue)) {
736+
if (this.isActualJNode(nextValue) && !isRightPadded(nextValue)) {
767737
// This is a Block child without explicit RightPadded wrapper in cursor chain
768738
// Apply RightPadded-like context: add indent if statement has newline
769739
const blockContext = c.messages.get("indentContext") as IndentContext | undefined;
@@ -776,10 +746,7 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
776746
// Create a synthetic cursor for the implied RightPadded context
777747
// and set the context for the statement directly
778748
nextCursor.messages.set("indentContext", [stmtIndent, 'align'] as IndentContext);
779-
if (DEBUG) console.log(`BLOCK->STMT: ${(nextValue as any).kind} hasNewline=${hasNewline} -> [${stmtIndent}, align]`);
780749
}
781-
} else {
782-
if (DEBUG) console.log(`BLOCK->ANCHOR: skipping (next is anchor)`);
783750
}
784751
}
785752

@@ -790,16 +757,13 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
790757
if (nextCursor !== anchorCursor) {
791758
const nextValue = nextCursor.value;
792759
// If thenPart is a Block and not wrapped in RightPadded in cursor chain
793-
if (this.isActualJNode(nextValue) && nextValue.kind === J.Kind.Block && !this.isRightPaddedWrapper(nextValue)) {
760+
if (this.isActualJNode(nextValue) && nextValue.kind === J.Kind.Block && !isRightPadded(nextValue)) {
794761
const ifContext = c.messages.get("indentContext") as IndentContext | undefined;
795762
const [ifIndent] = ifContext ?? [0, 'continuation'];
796763
// thenPart Block doesn't have newline in prefix (it's { after condition)
797764
// Keep same indent, use 'block' so children get proper indentation
798765
nextCursor.messages.set("indentContext", [ifIndent, 'block'] as IndentContext);
799-
if (DEBUG) console.log(`IF->BLOCK: ifIndent=${ifIndent} -> [${ifIndent}, block]`);
800766
}
801-
} else {
802-
if (DEBUG) console.log(`IF->ANCHOR: skipping (next is anchor)`);
803767
}
804768
}
805769
}
@@ -808,15 +772,8 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
808772
private isActualJNode(v: any): v is J {
809773
return isJava(v) &&
810774
v.kind !== J.Kind.Container &&
811-
!this.isRightPaddedWrapper(v) &&
812-
!this.isLeftPaddedWrapper(v);
775+
!isRightPadded(v) &&
776+
!isLeftPadded(v);
813777
}
814778

815-
private isRightPaddedWrapper(v: any): v is J.RightPadded<J> {
816-
return isRightPadded(v);
817-
}
818-
819-
private isLeftPaddedWrapper(v: any): v is J.LeftPadded<J> {
820-
return isLeftPadded(v);
821-
}
822779
}

rewrite-javascript/rewrite/src/javascript/migrate/es6/remove-duplicate-object-keys.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ export class RemoveDuplicateObjectKeys extends Recipe {
4848
const propertyNameToLastIndex = new Map<string, number>();
4949
const propertyNames: (string | null)[] = [];
5050

51-
// For tree types, the padded value IS the element (intersection type)
5251
for (let i = 0; i < statements.length; i++) {
53-
const stmt = statements[i] as unknown as Statement;
52+
const stmt = statements[i];
5453
if (stmt.kind === JS.Kind.PropertyAssignment) {
5554
const prop = stmt as unknown as JS.PropertyAssignment;
5655
const propName = this.getPropertyName(prop);
@@ -76,15 +75,13 @@ export class RemoveDuplicateObjectKeys extends Recipe {
7675
if (propName !== null) {
7776
const lastIndex = propertyNameToLastIndex.get(propName)!;
7877
if (i < lastIndex) {
79-
// For tree types, statements[i] IS the element with padding
80-
formatter.markRemoved(statements[i] as unknown as J);
78+
formatter.markRemoved(statements[i]);
8179
continue;
8280
}
8381
}
8482

8583
const stmt = statements[i];
86-
// For tree types, stmt IS the element with padding mixed in
87-
const adjustedElement = formatter.processKept(stmt as unknown as J);
84+
const adjustedElement = formatter.processKept(stmt);
8885
// Merge adjusted element with padding
8986
filteredStatements.push({
9087
...adjustedElement,
@@ -101,7 +98,6 @@ export class RemoveDuplicateObjectKeys extends Recipe {
10198
}
10299

103100
private getPropertyName(prop: JS.PropertyAssignment): string | null {
104-
// For tree types, name IS the expression with padding mixed in
105101
const name = prop.name as unknown as Expression;
106102

107103
// Handle identifier: { foo: 1 }

0 commit comments

Comments
 (0)