Skip to content

Commit f41ffcb

Browse files
committed
Centralize padding type guards into src/java/tree.ts
Add isRightPadded, isLeftPadded, isPrimitiveRightPadded, and isPrimitiveLeftPadded type guards and migrate six files that had their own ad-hoc checks.
1 parent 3f51882 commit f41ffcb

7 files changed

Lines changed: 53 additions & 83 deletions

File tree

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,28 @@ export function isIntersectionPadded(padded: any): boolean {
974974
*/
975975
export const isTreePadded = isIntersectionPadded;
976976

977+
/** Is this value a RightPadded of any form (intersection or primitive wrapper)? */
978+
export function isRightPadded(value: any): boolean {
979+
if (value === null || typeof value !== 'object' || !('padding' in value)) return false;
980+
return typeof value.padding === 'object' && value.padding !== null && 'after' in value.padding;
981+
}
982+
983+
/** Is this value a LeftPadded of any form (intersection or primitive wrapper)? */
984+
export function isLeftPadded(value: any): boolean {
985+
if (value === null || typeof value !== 'object' || !('padding' in value)) return false;
986+
return typeof value.padding === 'object' && value.padding !== null && 'before' in value.padding;
987+
}
988+
989+
/** Is this a primitive-wrapper RightPadded value (has `element` property)? */
990+
export function isPrimitiveRightPadded(value: any): boolean {
991+
return isRightPadded(value) && 'element' in value;
992+
}
993+
994+
/** Is this a primitive-wrapper LeftPadded value (has `element` property)? */
995+
export function isPrimitiveLeftPadded(value: any): boolean {
996+
return isLeftPadded(value) && 'element' in value;
997+
}
998+
977999
/**
9781000
* Extracts the element from a padded value.
9791001
* For tree nodes and Space: returns the padded value itself (it IS the element with padding mixed in).

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

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616
import {JavaScriptVisitor} from './visitor';
17-
import {J, Type, Expression, Statement, isIdentifier, getPaddedElement, isIntersectionPadded} from '../java';
17+
import {J, Type, Expression, Statement, isIdentifier, getPaddedElement, isRightPadded, isLeftPadded} from '../java';
1818
import {JS, JSX} from './tree';
1919
import {Cursor, Tree} from "../tree";
2020

@@ -237,31 +237,14 @@ export class JavaScriptComparatorVisitor extends JavaScriptVisitor<J> {
237237
await this.visitLeftPadded(j, other);
238238
}
239239

240-
// Check for intersection-padded tree elements (has `padding` property but no `element`)
241-
// These are tree types (J) with RightPaddingMixin or LeftPaddingMixin mixed in
242-
if (isIntersectionPadded(j)) {
243-
// Determine if it's left or right padded by checking for 'before' vs 'after' in padding
244-
const padding = (j as any).padding;
245-
if ('after' in padding) {
246-
return propertyName ? await this.visitRightPaddedProperty(propertyName, j, other) :
247-
await this.visitRightPadded(j, other);
248-
} else if ('before' in padding) {
249-
return propertyName ? await this.visitLeftPaddedProperty(propertyName, j, other) :
250-
await this.visitLeftPadded(j, other);
251-
}
240+
// Check for padded values (both intersection-padded tree elements and primitive wrappers)
241+
if (isRightPadded(j)) {
242+
return propertyName ? await this.visitRightPaddedProperty(propertyName, j, other) :
243+
await this.visitRightPadded(j, other);
252244
}
253-
254-
// Check for primitive-padded wrappers (has `padding` AND `element`)
255-
// These are primitives (boolean, number, string) wrapped with padding
256-
if (typeof j === 'object' && j !== null && 'padding' in j && 'element' in j) {
257-
const padding = (j as any).padding;
258-
if ('after' in padding) {
259-
return propertyName ? await this.visitRightPaddedProperty(propertyName, j, other) :
260-
await this.visitRightPadded(j, other);
261-
} else if ('before' in padding) {
262-
return propertyName ? await this.visitLeftPaddedProperty(propertyName, j, other) :
263-
await this.visitLeftPadded(j, other);
264-
}
245+
if (isLeftPadded(j)) {
246+
return propertyName ? await this.visitLeftPaddedProperty(propertyName, j, other) :
247+
await this.visitLeftPadded(j, other);
265248
}
266249

267250
if (kind === J.Kind.Container) {
@@ -375,7 +358,7 @@ export class JavaScriptComparatorVisitor extends JavaScriptVisitor<J> {
375358

376359
// Extract the other element if it's also a RightPadded
377360
// With intersection types, check for `padding` property (not `kind === J.Kind.RightPadded`)
378-
const isRightPaddedOther = isIntersectionPadded(p) || ('element' in p && 'padding' in p);
361+
const isRightPaddedOther = isRightPadded(p);
379362
const otherWrapper = isRightPaddedOther ? (p as unknown) as J.RightPadded<T> : undefined;
380363
// For tree types, the padded value IS the element; for primitives use getPaddedElement
381364
const otherElement = isRightPaddedOther ? getPaddedElement(otherWrapper!) : p;
@@ -415,7 +398,7 @@ export class JavaScriptComparatorVisitor extends JavaScriptVisitor<J> {
415398

416399
// Extract the other element if it's also a LeftPadded
417400
// With intersection types, check for `padding.before` property (not `kind === J.Kind.LeftPadded`)
418-
const isLeftPaddedOther = (p as any)?.padding && 'before' in (p as any).padding;
401+
const isLeftPaddedOther = isLeftPadded(p);
419402
const otherWrapper = isLeftPaddedOther ? (p as unknown) as J.LeftPadded<T> : undefined;
420403
// For tree types, the padded value IS the element; for primitives use getPaddedElement
421404
const otherElement = isLeftPaddedOther ? getPaddedElement(otherWrapper!) : p;

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

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {JavaScriptVisitor} from "../visitor";
1818
import {
1919
getPaddedElement,
2020
isJava,
21+
isLeftPadded,
22+
isRightPadded,
2123
isSpace,
2224
J,
2325
lastWhitespace,
@@ -810,19 +812,11 @@ export class TabsAndIndentsVisitor<P> extends JavaScriptVisitor<P> {
810812
!this.isLeftPaddedWrapper(v);
811813
}
812814

813-
/**
814-
* Detects if a value is a RightPadded wrapper.
815-
* RightPadded<J> intersection types have padding.after but not padding.before.
816-
*/
817815
private isRightPaddedWrapper(v: any): v is J.RightPadded<J> {
818-
return v?.padding?.after !== undefined && v?.padding?.before === undefined;
816+
return isRightPadded(v);
819817
}
820818

821-
/**
822-
* Detects if a value is a LeftPadded wrapper.
823-
* LeftPadded<J> intersection types have padding.before but not padding.after.
824-
*/
825819
private isLeftPaddedWrapper(v: any): v is J.LeftPadded<J> {
826-
return v?.padding?.before !== undefined && v?.padding?.after === undefined;
820+
return isLeftPadded(v);
827821
}
828822
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616
import {Cursor, Tree} from '../..';
17-
import {getPaddedElement, isIntersectionPadded, J} from '../../java';
17+
import {getPaddedElement, isRightPadded, J} from '../../java';
1818
import {JS} from '../index';
1919
import {JavaScriptSemanticComparatorVisitor} from '../comparator';
2020
import {CaptureMarker, CaptureStorageValue, PlaceholderUtils} from './utils';
@@ -191,7 +191,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
191191
if (captureMarker) {
192192
// Extract the target wrapper if it's also a RightPadded
193193
// With intersection types, RightPadded elements have `padding` property but no `element`
194-
const isRightPaddedOther = isIntersectionPadded(p);
194+
const isRightPaddedOther = isRightPadded(p);
195195
const targetWrapper = isRightPaddedOther ? (p as unknown) as J.RightPadded<T> : undefined;
196196
// For tree types, the padded value IS the element (use getPaddedElement helper)
197197
const targetElement = isRightPaddedOther ? getPaddedElement(targetWrapper!) : p;
@@ -1000,7 +1000,7 @@ export class DebugPatternMatchingComparator extends PatternMatchingComparator {
10001000
const captureMarker = PlaceholderUtils.getCaptureMarkerFromPadded(right);
10011001
if (captureMarker) {
10021002
// With intersection types, RightPadded elements have `padding` property but no `element`
1003-
const isRightPaddedOther = isIntersectionPadded(p);
1003+
const isRightPaddedOther = isRightPadded(p);
10041004
const targetWrapper = isRightPaddedOther ? (p as unknown) as J.RightPadded<T> : undefined;
10051005
// For tree types, the padded value IS the element (use getPaddedElement helper)
10061006
const targetElement = isRightPaddedOther ? getPaddedElement(targetWrapper!) : p;

rewrite-javascript/rewrite/src/javascript/templating/pattern.ts

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616
import {Cursor} from '../..';
17-
import {getPaddedElement, J} from '../../java';
17+
import {getPaddedElement, isRightPadded, J} from '../../java';
1818
import {
1919
Any,
2020
Capture,
@@ -638,29 +638,22 @@ export class MatchResult implements IMatchResult {
638638
if (Array.isArray(value)) {
639639
// Check if it's an array of wrappers
640640
// For tree types, check for RightPaddingMixin's padding property
641-
if (value.length > 0 && this.isRightPadded(value[0])) {
641+
if (value.length > 0 && isRightPadded(value[0])) {
642642
// Array of J.RightPadded - extract elements using getPaddedElement
643643
return (value as J.RightPadded<J>[]).map(w => getPaddedElement(w)) as any;
644644
}
645645
// Already an array of elements
646646
return value as any;
647647
}
648648
// Check if it's a scalar wrapper (has RightPaddingMixin properties)
649-
if (this.isRightPadded(value)) {
649+
if (isRightPadded(value)) {
650650
return getPaddedElement(value as J.RightPadded<J>);
651651
}
652652
// Scalar element
653653
return value as J;
654654
}
655655

656-
/**
657-
* Checks if a value is a RightPadded wrapper.
658-
* For tree types, checks for RightPaddingMixin's padding property.
659-
*/
660-
private isRightPadded(value: unknown): boolean {
661-
return typeof value === 'object' && value !== null &&
662-
'padding' in value && !('element' in value);
663-
}
656+
664657

665658
/**
666659
* Internal method to get wrappers (used by template expansion).
@@ -670,10 +663,10 @@ export class MatchResult implements IMatchResult {
670663
[WRAPPERS_MAP_SYMBOL](): Map<string, J.RightPadded<J> | J.RightPadded<J>[]> {
671664
const result = new Map<string, J.RightPadded<J> | J.RightPadded<J>[]>();
672665
for (const [name, value] of this.storage) {
673-
if (Array.isArray(value) && value.length > 0 && this.isRightPadded(value[0])) {
666+
if (Array.isArray(value) && value.length > 0 && isRightPadded(value[0])) {
674667
// This is an array of wrappers (variadic)
675668
result.set(name, value as J.RightPadded<J>[]);
676-
} else if (!Array.isArray(value) && this.isRightPadded(value)) {
669+
} else if (!Array.isArray(value) && isRightPadded(value)) {
677670
// This is a scalar wrapper
678671
result.set(name, value as J.RightPadded<J>);
679672
}
@@ -753,29 +746,22 @@ class Matcher {
753746
if (Array.isArray(value)) {
754747
// Check if it's an array of wrappers
755748
// For tree types, check for RightPaddingMixin's padding property
756-
if (value.length > 0 && this.isRightPadded(value[0])) {
749+
if (value.length > 0 && isRightPadded(value[0])) {
757750
// Array of J.RightPadded - extract elements using getPaddedElement
758751
return (value as J.RightPadded<J>[]).map(w => getPaddedElement(w)) as any;
759752
}
760753
// Already an array of elements
761754
return value as any;
762755
}
763756
// Check if it's a scalar wrapper (has RightPaddingMixin properties)
764-
if (this.isRightPadded(value)) {
757+
if (isRightPadded(value)) {
765758
return getPaddedElement(value as J.RightPadded<J>);
766759
}
767760
// Scalar element
768761
return value as J;
769762
}
770763

771-
/**
772-
* Checks if a value is a RightPadded wrapper.
773-
* For tree types, checks for RightPaddingMixin's padding property.
774-
*/
775-
private isRightPadded(value: unknown): boolean {
776-
return typeof value === 'object' && value !== null &&
777-
'padding' in value && !('element' in value);
778-
}
764+
779765

780766
/**
781767
* Logs a debug message if debugging is enabled.

rewrite-javascript/rewrite/src/javascript/templating/placeholder-replacement.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616
import {Cursor, isTree} from '../..';
17-
import {getPaddedElement, J, Statement} from '../../java';
17+
import {getPaddedElement, isRightPadded, J, Statement} from '../../java';
1818
import {JS} from '..';
1919
import {JavaScriptVisitor} from '../visitor';
2020
import {create as produce} from 'mutative';
@@ -426,12 +426,7 @@ export class PlaceholderReplacementVisitor extends JavaScriptVisitor<any> {
426426
return placeholder;
427427
}
428428

429-
// Check if the parameter value is a J.RightPadded wrapper (intersection type)
430-
// With intersection types, RightPadded tree elements have `padding` property but no `element`
431-
const isRightPadded = param.value && typeof param.value === 'object' &&
432-
'padding' in param.value && !('element' in param.value);
433-
434-
if (isRightPadded) {
429+
if (isRightPadded(param.value)) {
435430
// For intersection types, the padded value IS the element (with padding mixed in)
436431
const element = param.value as J;
437432
return produce(element, draft => {

rewrite-javascript/rewrite/src/javascript/tree-debug.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import {Cursor, Tree} from "../tree";
18-
import {Comment, isIdentifier, isJava, isLiteral, J, TextComment, getPaddedElement} from "../java";
18+
import {Comment, isIdentifier, isJava, isLiteral, J, TextComment, getPaddedElement, isPrimitiveLeftPadded, isPrimitiveRightPadded} from "../java";
1919
import {JS} from "./tree";
2020
import {JavaScriptVisitor} from "./visitor";
2121
import * as fs from "fs";
@@ -999,21 +999,11 @@ export class LstDebugPrinter {
999999
}
10001000

10011001
private isLeftPadded(value: any): boolean {
1002-
if (value === null || typeof value !== 'object') return false;
1003-
// Only match primitive wrappers (have .element), not intersection-padded J nodes
1004-
if ('padding' in value && 'element' in value && value.padding && typeof value.padding === 'object' && 'before' in value.padding) {
1005-
return true;
1006-
}
1007-
return false;
1002+
return isPrimitiveLeftPadded(value);
10081003
}
10091004

10101005
private isRightPadded(value: any): boolean {
1011-
if (value === null || typeof value !== 'object') return false;
1012-
// Only match primitive wrappers (have .element), not intersection-padded J nodes
1013-
if ('padding' in value && 'element' in value && value.padding && typeof value.padding === 'object' && 'after' in value.padding) {
1014-
return true;
1015-
}
1016-
return false;
1006+
return isPrimitiveRightPadded(value);
10171007
}
10181008

10191009
/**

0 commit comments

Comments
 (0)