Skip to content

Commit 151d21e

Browse files
authored
refactor: Convert renderer typecheck methods to typeguards. (#8656)
* refactor: Convert renderer typecheck methods to typeguards. * chore: Revert unintended change. * chore: Format types.ts.
1 parent 956f272 commit 151d21e

18 files changed

Lines changed: 189 additions & 128 deletions

core/renderers/common/drawer.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import type {ExternalValueInput} from '../measurables/external_value_input.js';
1515
import type {Field} from '../measurables/field.js';
1616
import type {Icon} from '../measurables/icon.js';
1717
import type {InlineInput} from '../measurables/inline_input.js';
18-
import type {PreviousConnection} from '../measurables/previous_connection.js';
1918
import type {Row} from '../measurables/row.js';
2019
import {Types} from '../measurables/types.js';
2120
import type {ConstantProvider, Notch, PuzzleTab} from './constants.js';
@@ -116,13 +115,8 @@ export class Drawer {
116115
this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topLeft;
117116
} else if (Types.isRightRoundedCorner(elem)) {
118117
this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topRight;
119-
} else if (
120-
Types.isPreviousConnection(elem) &&
121-
elem instanceof Connection
122-
) {
123-
this.outlinePath_ += (
124-
(elem as PreviousConnection).shape as Notch
125-
).pathLeft;
118+
} else if (Types.isPreviousConnection(elem)) {
119+
this.outlinePath_ += (elem.shape as Notch).pathLeft;
126120
} else if (Types.isHat(elem)) {
127121
this.outlinePath_ += this.constants_.START_HAT.path;
128122
} else if (Types.isSpacer(elem)) {
@@ -217,7 +211,7 @@ export class Drawer {
217211
let rightCornerYOffset = 0;
218212
let outlinePath = '';
219213
for (let i = elems.length - 1, elem; (elem = elems[i]); i--) {
220-
if (Types.isNextConnection(elem) && elem instanceof Connection) {
214+
if (Types.isNextConnection(elem)) {
221215
outlinePath += (elem.shape as Notch).pathRight;
222216
} else if (Types.isLeftSquareCorner(elem)) {
223217
outlinePath += svgPaths.lineOnAxis('H', bottomRow.xPos);
@@ -269,9 +263,9 @@ export class Drawer {
269263
for (let i = 0, row; (row = this.info_.rows[i]); i++) {
270264
for (let j = 0, elem; (elem = row.elements[j]); j++) {
271265
if (Types.isInlineInput(elem)) {
272-
this.drawInlineInput_(elem as InlineInput);
266+
this.drawInlineInput_(elem);
273267
} else if (Types.isIcon(elem) || Types.isField(elem)) {
274-
this.layoutField_(elem as Field | Icon);
268+
this.layoutField_(elem);
275269
}
276270
}
277271
}
@@ -295,13 +289,13 @@ export class Drawer {
295289
}
296290

297291
if (Types.isIcon(fieldInfo)) {
298-
const icon = (fieldInfo as Icon).icon;
292+
const icon = fieldInfo.icon;
299293
icon.setOffsetInBlock(new Coordinate(xPos, yPos));
300294
if (this.info_.isInsertionMarker) {
301295
icon.hideForInsertionMarker();
302296
}
303297
} else {
304-
const svgGroup = (fieldInfo as Field).field.getSvgRoot()!;
298+
const svgGroup = fieldInfo.field.getSvgRoot()!;
305299
svgGroup.setAttribute(
306300
'transform',
307301
'translate(' + xPos + ',' + yPos + ')' + scale,

core/renderers/common/info.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -671,20 +671,17 @@ export class RenderInfo {
671671
return row.yPos + elem.height / 2;
672672
}
673673
if (Types.isBottomRow(row)) {
674-
const bottomRow = row as BottomRow;
675-
const baseline =
676-
bottomRow.yPos + bottomRow.height - bottomRow.descenderHeight;
674+
const baseline = row.yPos + row.height - row.descenderHeight;
677675
if (Types.isNextConnection(elem)) {
678676
return baseline + elem.height / 2;
679677
}
680678
return baseline - elem.height / 2;
681679
}
682680
if (Types.isTopRow(row)) {
683-
const topRow = row as TopRow;
684681
if (Types.isHat(elem)) {
685-
return topRow.capline - elem.height / 2;
682+
return row.capline - elem.height / 2;
686683
}
687-
return topRow.capline + elem.height / 2;
684+
return row.capline + elem.height / 2;
688685
}
689686
return row.yPos + row.height / 2;
690687
}

core/renderers/geras/drawer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class Drawer extends BaseDrawer {
100100
}
101101

102102
override drawInlineInput_(input: InlineInput) {
103-
this.highlighter_.drawInlineInput(input as InlineInput);
103+
this.highlighter_.drawInlineInput(input);
104104

105105
super.drawInlineInput_(input);
106106
}

core/renderers/geras/info.ts

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,9 @@ import {StatementInput} from '../../inputs/statement_input.js';
1414
import {ValueInput} from '../../inputs/value_input.js';
1515
import {RenderInfo as BaseRenderInfo} from '../common/info.js';
1616
import type {Measurable} from '../measurables/base.js';
17-
import type {BottomRow} from '../measurables/bottom_row.js';
1817
import {ExternalValueInput} from '../measurables/external_value_input.js';
19-
import type {Field} from '../measurables/field.js';
2018
import {InRowSpacer} from '../measurables/in_row_spacer.js';
21-
import type {InputRow} from '../measurables/input_row.js';
2219
import type {Row} from '../measurables/row.js';
23-
import type {TopRow} from '../measurables/top_row.js';
2420
import {Types} from '../measurables/types.js';
2521
import type {ConstantProvider} from './constants.js';
2622
import {InlineInput} from './measurables/inline_input.js';
@@ -150,7 +146,7 @@ export class RenderInfo extends BaseRenderInfo {
150146
override getInRowSpacing_(prev: Measurable | null, next: Measurable | null) {
151147
if (!prev) {
152148
// Between an editable field and the beginning of the row.
153-
if (next && Types.isField(next) && (next as Field).isEditable) {
149+
if (next && Types.isField(next) && next.isEditable) {
154150
return this.constants_.MEDIUM_PADDING;
155151
}
156152
// Inline input at the beginning of the row.
@@ -167,7 +163,7 @@ export class RenderInfo extends BaseRenderInfo {
167163
// Spacing between a non-input and the end of the row or a statement input.
168164
if (!Types.isInput(prev) && (!next || Types.isStatementInput(next))) {
169165
// Between an editable field and the end of the row.
170-
if (Types.isField(prev) && (prev as Field).isEditable) {
166+
if (Types.isField(prev) && prev.isEditable) {
171167
return this.constants_.MEDIUM_PADDING;
172168
}
173169
// Padding at the end of an icon-only row to make the block shape clearer.
@@ -208,7 +204,7 @@ export class RenderInfo extends BaseRenderInfo {
208204
// Spacing between a non-input and an input.
209205
if (!Types.isInput(prev) && next && Types.isInput(next)) {
210206
// Between an editable field and an input.
211-
if (Types.isField(prev) && (prev as Field).isEditable) {
207+
if (Types.isField(prev) && prev.isEditable) {
212208
if (Types.isInlineInput(next)) {
213209
return this.constants_.SMALL_PADDING;
214210
} else if (Types.isExternalInput(next)) {
@@ -233,7 +229,7 @@ export class RenderInfo extends BaseRenderInfo {
233229
// Spacing between an inline input and a field.
234230
if (Types.isInlineInput(prev) && next && Types.isField(next)) {
235231
// Editable field after inline input.
236-
if ((next as Field).isEditable) {
232+
if (next.isEditable) {
237233
return this.constants_.MEDIUM_PADDING;
238234
} else {
239235
// Noneditable field after inline input.
@@ -278,7 +274,7 @@ export class RenderInfo extends BaseRenderInfo {
278274
Types.isField(prev) &&
279275
next &&
280276
Types.isField(next) &&
281-
(prev as Field).isEditable === (next as Field).isEditable
277+
prev.isEditable === next.isEditable
282278
) {
283279
return this.constants_.LARGE_PADDING;
284280
}
@@ -323,20 +319,17 @@ export class RenderInfo extends BaseRenderInfo {
323319
return row.yPos + elem.height / 2;
324320
}
325321
if (Types.isBottomRow(row)) {
326-
const bottomRow = row as BottomRow;
327-
const baseline =
328-
bottomRow.yPos + bottomRow.height - bottomRow.descenderHeight;
322+
const baseline = row.yPos + row.height - row.descenderHeight;
329323
if (Types.isNextConnection(elem)) {
330324
return baseline + elem.height / 2;
331325
}
332326
return baseline - elem.height / 2;
333327
}
334328
if (Types.isTopRow(row)) {
335-
const topRow = row as TopRow;
336329
if (Types.isHat(elem)) {
337-
return topRow.capline - elem.height / 2;
330+
return row.capline - elem.height / 2;
338331
}
339-
return topRow.capline + elem.height / 2;
332+
return row.capline + elem.height / 2;
340333
}
341334

342335
let result = row.yPos;
@@ -370,7 +363,7 @@ export class RenderInfo extends BaseRenderInfo {
370363
rowNextRightEdges.set(row, nextRightEdge);
371364
if (Types.isInputRow(row)) {
372365
if (row.hasStatement) {
373-
this.alignStatementRow_(row as InputRow);
366+
this.alignStatementRow_(row);
374367
}
375368
if (
376369
prevInput &&

core/renderers/measurables/in_row_spacer.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import {Types} from './types.js';
1515
* row.
1616
*/
1717
export class InRowSpacer extends Measurable {
18+
// This field exists solely to structurally distinguish this type from other
19+
// Measurable subclasses. Because this class otherwise has the same fields as
20+
// Measurable, and Typescript doesn't support nominal typing, Typescript will
21+
// consider it and other subclasses in the same situation as being of the same
22+
// type, even if typeguards are used, which could result in Typescript typing
23+
// objects of this class as `never`.
24+
private inRowSpacer: undefined;
25+
1826
/**
1927
* @param constants The rendering constants provider.
2028
* @param width The width of the spacer.

core/renderers/measurables/input_row.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77
// Former goog.module ID: Blockly.blockRendering.InputRow
88

99
import type {ConstantProvider} from '../common/constants.js';
10-
import {ExternalValueInput} from './external_value_input.js';
11-
import {InputConnection} from './input_connection.js';
1210
import {Row} from './row.js';
13-
import {StatementInput} from './statement_input.js';
1411
import {Types} from './types.js';
1512

1613
/**
@@ -40,12 +37,11 @@ export class InputRow extends Row {
4037
for (let i = 0; i < this.elements.length; i++) {
4138
const elem = this.elements[i];
4239
this.width += elem.width;
43-
if (Types.isInput(elem) && elem instanceof InputConnection) {
44-
if (Types.isStatementInput(elem) && elem instanceof StatementInput) {
40+
if (Types.isInput(elem)) {
41+
if (Types.isStatementInput(elem)) {
4542
connectedBlockWidths += elem.connectedBlockWidth;
4643
} else if (
4744
Types.isExternalInput(elem) &&
48-
elem instanceof ExternalValueInput &&
4945
elem.connectedBlockWidth !== 0
5046
) {
5147
connectedBlockWidths +=

core/renderers/measurables/jagged_edge.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import {Types} from './types.js';
1515
* collapsed block takes up during rendering.
1616
*/
1717
export class JaggedEdge extends Measurable {
18+
// This field exists solely to structurally distinguish this type from other
19+
// Measurable subclasses. Because this class otherwise has the same fields as
20+
// Measurable, and Typescript doesn't support nominal typing, Typescript will
21+
// consider it and other subclasses in the same situation as being of the same
22+
// type, even if typeguards are used, which could result in Typescript typing
23+
// objects of this class as `never`.
24+
private jaggedEdge: undefined;
25+
1826
/**
1927
* @param constants The rendering constants provider.
2028
*/

core/renderers/measurables/next_connection.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ import {Types} from './types.js';
1616
* up during rendering.
1717
*/
1818
export class NextConnection extends Connection {
19+
// This field exists solely to structurally distinguish this type from other
20+
// Measurable subclasses. Because this class otherwise has the same fields as
21+
// Measurable, and Typescript doesn't support nominal typing, Typescript will
22+
// consider it and other subclasses in the same situation as being of the same
23+
// type, even if typeguards are used, which could result in Typescript typing
24+
// objects of this class as `never`.
25+
private nextConnection: undefined;
26+
1927
/**
2028
* @param constants The rendering constants provider.
2129
* @param connectionModel The connection object on the block that this

core/renderers/measurables/previous_connection.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ import {Types} from './types.js';
1616
* up during rendering.
1717
*/
1818
export class PreviousConnection extends Connection {
19+
// This field exists solely to structurally distinguish this type from other
20+
// Measurable subclasses. Because this class otherwise has the same fields as
21+
// Measurable, and Typescript doesn't support nominal typing, Typescript will
22+
// consider it and other subclasses in the same situation as being of the same
23+
// type, even if typeguards are used, which could result in Typescript typing
24+
// objects of this class as `never`.
25+
private previousConnection: undefined;
26+
1927
/**
2028
* @param constants The rendering constants provider.
2129
* @param connectionModel The connection object on the block that this

core/renderers/measurables/round_corner.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import {Types} from './types.js';
1515
* during rendering.
1616
*/
1717
export class RoundCorner extends Measurable {
18+
// This field exists solely to structurally distinguish this type from other
19+
// Measurable subclasses. Because this class otherwise has the same fields as
20+
// Measurable, and Typescript doesn't support nominal typing, Typescript will
21+
// consider it and other subclasses in the same situation as being of the same
22+
// type, even if typeguards are used, which could result in Typescript typing
23+
// objects of this class as `never`.
24+
private roundCorner: undefined;
25+
1826
/**
1927
* @param constants The rendering constants provider.
2028
* @param opt_position The position of this corner.

0 commit comments

Comments
 (0)