Skip to content

Commit

Permalink
refactor: Convert renderer typecheck methods to typeguards. (#8656)
Browse files Browse the repository at this point in the history
* refactor: Convert renderer typecheck methods to typeguards.

* chore: Revert unintended change.

* chore: Format types.ts.
  • Loading branch information
gonfunko authored Jan 7, 2025
1 parent 956f272 commit 151d21e
Show file tree
Hide file tree
Showing 18 changed files with 189 additions and 128 deletions.
20 changes: 7 additions & 13 deletions core/renderers/common/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import type {ExternalValueInput} from '../measurables/external_value_input.js';
import type {Field} from '../measurables/field.js';
import type {Icon} from '../measurables/icon.js';
import type {InlineInput} from '../measurables/inline_input.js';
import type {PreviousConnection} from '../measurables/previous_connection.js';
import type {Row} from '../measurables/row.js';
import {Types} from '../measurables/types.js';
import type {ConstantProvider, Notch, PuzzleTab} from './constants.js';
Expand Down Expand Up @@ -116,13 +115,8 @@ export class Drawer {
this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topLeft;
} else if (Types.isRightRoundedCorner(elem)) {
this.outlinePath_ += this.constants_.OUTSIDE_CORNERS.topRight;
} else if (
Types.isPreviousConnection(elem) &&
elem instanceof Connection
) {
this.outlinePath_ += (
(elem as PreviousConnection).shape as Notch
).pathLeft;
} else if (Types.isPreviousConnection(elem)) {
this.outlinePath_ += (elem.shape as Notch).pathLeft;
} else if (Types.isHat(elem)) {
this.outlinePath_ += this.constants_.START_HAT.path;
} else if (Types.isSpacer(elem)) {
Expand Down Expand Up @@ -217,7 +211,7 @@ export class Drawer {
let rightCornerYOffset = 0;
let outlinePath = '';
for (let i = elems.length - 1, elem; (elem = elems[i]); i--) {
if (Types.isNextConnection(elem) && elem instanceof Connection) {
if (Types.isNextConnection(elem)) {
outlinePath += (elem.shape as Notch).pathRight;
} else if (Types.isLeftSquareCorner(elem)) {
outlinePath += svgPaths.lineOnAxis('H', bottomRow.xPos);
Expand Down Expand Up @@ -269,9 +263,9 @@ export class Drawer {
for (let i = 0, row; (row = this.info_.rows[i]); i++) {
for (let j = 0, elem; (elem = row.elements[j]); j++) {
if (Types.isInlineInput(elem)) {
this.drawInlineInput_(elem as InlineInput);
this.drawInlineInput_(elem);
} else if (Types.isIcon(elem) || Types.isField(elem)) {
this.layoutField_(elem as Field | Icon);
this.layoutField_(elem);
}
}
}
Expand All @@ -295,13 +289,13 @@ export class Drawer {
}

if (Types.isIcon(fieldInfo)) {
const icon = (fieldInfo as Icon).icon;
const icon = fieldInfo.icon;
icon.setOffsetInBlock(new Coordinate(xPos, yPos));
if (this.info_.isInsertionMarker) {
icon.hideForInsertionMarker();
}
} else {
const svgGroup = (fieldInfo as Field).field.getSvgRoot()!;
const svgGroup = fieldInfo.field.getSvgRoot()!;
svgGroup.setAttribute(
'transform',
'translate(' + xPos + ',' + yPos + ')' + scale,
Expand Down
9 changes: 3 additions & 6 deletions core/renderers/common/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -671,20 +671,17 @@ export class RenderInfo {
return row.yPos + elem.height / 2;
}
if (Types.isBottomRow(row)) {
const bottomRow = row as BottomRow;
const baseline =
bottomRow.yPos + bottomRow.height - bottomRow.descenderHeight;
const baseline = row.yPos + row.height - row.descenderHeight;
if (Types.isNextConnection(elem)) {
return baseline + elem.height / 2;
}
return baseline - elem.height / 2;
}
if (Types.isTopRow(row)) {
const topRow = row as TopRow;
if (Types.isHat(elem)) {
return topRow.capline - elem.height / 2;
return row.capline - elem.height / 2;
}
return topRow.capline + elem.height / 2;
return row.capline + elem.height / 2;
}
return row.yPos + row.height / 2;
}
Expand Down
2 changes: 1 addition & 1 deletion core/renderers/geras/drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class Drawer extends BaseDrawer {
}

override drawInlineInput_(input: InlineInput) {
this.highlighter_.drawInlineInput(input as InlineInput);
this.highlighter_.drawInlineInput(input);

super.drawInlineInput_(input);
}
Expand Down
25 changes: 9 additions & 16 deletions core/renderers/geras/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@ import {StatementInput} from '../../inputs/statement_input.js';
import {ValueInput} from '../../inputs/value_input.js';
import {RenderInfo as BaseRenderInfo} from '../common/info.js';
import type {Measurable} from '../measurables/base.js';
import type {BottomRow} from '../measurables/bottom_row.js';
import {ExternalValueInput} from '../measurables/external_value_input.js';
import type {Field} from '../measurables/field.js';
import {InRowSpacer} from '../measurables/in_row_spacer.js';
import type {InputRow} from '../measurables/input_row.js';
import type {Row} from '../measurables/row.js';
import type {TopRow} from '../measurables/top_row.js';
import {Types} from '../measurables/types.js';
import type {ConstantProvider} from './constants.js';
import {InlineInput} from './measurables/inline_input.js';
Expand Down Expand Up @@ -150,7 +146,7 @@ export class RenderInfo extends BaseRenderInfo {
override getInRowSpacing_(prev: Measurable | null, next: Measurable | null) {
if (!prev) {
// Between an editable field and the beginning of the row.
if (next && Types.isField(next) && (next as Field).isEditable) {
if (next && Types.isField(next) && next.isEditable) {
return this.constants_.MEDIUM_PADDING;
}
// Inline input at the beginning of the row.
Expand All @@ -167,7 +163,7 @@ export class RenderInfo extends BaseRenderInfo {
// Spacing between a non-input and the end of the row or a statement input.
if (!Types.isInput(prev) && (!next || Types.isStatementInput(next))) {
// Between an editable field and the end of the row.
if (Types.isField(prev) && (prev as Field).isEditable) {
if (Types.isField(prev) && prev.isEditable) {
return this.constants_.MEDIUM_PADDING;
}
// Padding at the end of an icon-only row to make the block shape clearer.
Expand Down Expand Up @@ -208,7 +204,7 @@ export class RenderInfo extends BaseRenderInfo {
// Spacing between a non-input and an input.
if (!Types.isInput(prev) && next && Types.isInput(next)) {
// Between an editable field and an input.
if (Types.isField(prev) && (prev as Field).isEditable) {
if (Types.isField(prev) && prev.isEditable) {
if (Types.isInlineInput(next)) {
return this.constants_.SMALL_PADDING;
} else if (Types.isExternalInput(next)) {
Expand All @@ -233,7 +229,7 @@ export class RenderInfo extends BaseRenderInfo {
// Spacing between an inline input and a field.
if (Types.isInlineInput(prev) && next && Types.isField(next)) {
// Editable field after inline input.
if ((next as Field).isEditable) {
if (next.isEditable) {
return this.constants_.MEDIUM_PADDING;
} else {
// Noneditable field after inline input.
Expand Down Expand Up @@ -278,7 +274,7 @@ export class RenderInfo extends BaseRenderInfo {
Types.isField(prev) &&
next &&
Types.isField(next) &&
(prev as Field).isEditable === (next as Field).isEditable
prev.isEditable === next.isEditable
) {
return this.constants_.LARGE_PADDING;
}
Expand Down Expand Up @@ -323,20 +319,17 @@ export class RenderInfo extends BaseRenderInfo {
return row.yPos + elem.height / 2;
}
if (Types.isBottomRow(row)) {
const bottomRow = row as BottomRow;
const baseline =
bottomRow.yPos + bottomRow.height - bottomRow.descenderHeight;
const baseline = row.yPos + row.height - row.descenderHeight;
if (Types.isNextConnection(elem)) {
return baseline + elem.height / 2;
}
return baseline - elem.height / 2;
}
if (Types.isTopRow(row)) {
const topRow = row as TopRow;
if (Types.isHat(elem)) {
return topRow.capline - elem.height / 2;
return row.capline - elem.height / 2;
}
return topRow.capline + elem.height / 2;
return row.capline + elem.height / 2;
}

let result = row.yPos;
Expand Down Expand Up @@ -370,7 +363,7 @@ export class RenderInfo extends BaseRenderInfo {
rowNextRightEdges.set(row, nextRightEdge);
if (Types.isInputRow(row)) {
if (row.hasStatement) {
this.alignStatementRow_(row as InputRow);
this.alignStatementRow_(row);
}
if (
prevInput &&
Expand Down
8 changes: 8 additions & 0 deletions core/renderers/measurables/in_row_spacer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import {Types} from './types.js';
* row.
*/
export class InRowSpacer extends Measurable {
// This field exists solely to structurally distinguish this type from other
// Measurable subclasses. Because this class otherwise has the same fields as
// Measurable, and Typescript doesn't support nominal typing, Typescript will
// consider it and other subclasses in the same situation as being of the same
// type, even if typeguards are used, which could result in Typescript typing
// objects of this class as `never`.
private inRowSpacer: undefined;

/**
* @param constants The rendering constants provider.
* @param width The width of the spacer.
Expand Down
8 changes: 2 additions & 6 deletions core/renderers/measurables/input_row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
// Former goog.module ID: Blockly.blockRendering.InputRow

import type {ConstantProvider} from '../common/constants.js';
import {ExternalValueInput} from './external_value_input.js';
import {InputConnection} from './input_connection.js';
import {Row} from './row.js';
import {StatementInput} from './statement_input.js';
import {Types} from './types.js';

/**
Expand Down Expand Up @@ -40,12 +37,11 @@ export class InputRow extends Row {
for (let i = 0; i < this.elements.length; i++) {
const elem = this.elements[i];
this.width += elem.width;
if (Types.isInput(elem) && elem instanceof InputConnection) {
if (Types.isStatementInput(elem) && elem instanceof StatementInput) {
if (Types.isInput(elem)) {
if (Types.isStatementInput(elem)) {
connectedBlockWidths += elem.connectedBlockWidth;
} else if (
Types.isExternalInput(elem) &&
elem instanceof ExternalValueInput &&
elem.connectedBlockWidth !== 0
) {
connectedBlockWidths +=
Expand Down
8 changes: 8 additions & 0 deletions core/renderers/measurables/jagged_edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import {Types} from './types.js';
* collapsed block takes up during rendering.
*/
export class JaggedEdge extends Measurable {
// This field exists solely to structurally distinguish this type from other
// Measurable subclasses. Because this class otherwise has the same fields as
// Measurable, and Typescript doesn't support nominal typing, Typescript will
// consider it and other subclasses in the same situation as being of the same
// type, even if typeguards are used, which could result in Typescript typing
// objects of this class as `never`.
private jaggedEdge: undefined;

/**
* @param constants The rendering constants provider.
*/
Expand Down
8 changes: 8 additions & 0 deletions core/renderers/measurables/next_connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ import {Types} from './types.js';
* up during rendering.
*/
export class NextConnection extends Connection {
// This field exists solely to structurally distinguish this type from other
// Measurable subclasses. Because this class otherwise has the same fields as
// Measurable, and Typescript doesn't support nominal typing, Typescript will
// consider it and other subclasses in the same situation as being of the same
// type, even if typeguards are used, which could result in Typescript typing
// objects of this class as `never`.
private nextConnection: undefined;

/**
* @param constants The rendering constants provider.
* @param connectionModel The connection object on the block that this
Expand Down
8 changes: 8 additions & 0 deletions core/renderers/measurables/previous_connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ import {Types} from './types.js';
* up during rendering.
*/
export class PreviousConnection extends Connection {
// This field exists solely to structurally distinguish this type from other
// Measurable subclasses. Because this class otherwise has the same fields as
// Measurable, and Typescript doesn't support nominal typing, Typescript will
// consider it and other subclasses in the same situation as being of the same
// type, even if typeguards are used, which could result in Typescript typing
// objects of this class as `never`.
private previousConnection: undefined;

/**
* @param constants The rendering constants provider.
* @param connectionModel The connection object on the block that this
Expand Down
8 changes: 8 additions & 0 deletions core/renderers/measurables/round_corner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import {Types} from './types.js';
* during rendering.
*/
export class RoundCorner extends Measurable {
// This field exists solely to structurally distinguish this type from other
// Measurable subclasses. Because this class otherwise has the same fields as
// Measurable, and Typescript doesn't support nominal typing, Typescript will
// consider it and other subclasses in the same situation as being of the same
// type, even if typeguards are used, which could result in Typescript typing
// objects of this class as `never`.
private roundCorner: undefined;

/**
* @param constants The rendering constants provider.
* @param opt_position The position of this corner.
Expand Down
10 changes: 5 additions & 5 deletions core/renderers/measurables/row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export class Row {
for (let i = this.elements.length - 1; i >= 0; i--) {
const elem = this.elements[i];
if (Types.isInput(elem)) {
return elem as InputConnection;
return elem;
}
}
return null;
Expand Down Expand Up @@ -166,8 +166,8 @@ export class Row {
getFirstSpacer(): InRowSpacer | null {
for (let i = 0; i < this.elements.length; i++) {
const elem = this.elements[i];
if (Types.isSpacer(elem)) {
return elem as InRowSpacer;
if (Types.isInRowSpacer(elem)) {
return elem;
}
}
return null;
Expand All @@ -181,8 +181,8 @@ export class Row {
getLastSpacer(): InRowSpacer | null {
for (let i = this.elements.length - 1; i >= 0; i--) {
const elem = this.elements[i];
if (Types.isSpacer(elem)) {
return elem as InRowSpacer;
if (Types.isInRowSpacer(elem)) {
return elem;
}
}
return null;
Expand Down
8 changes: 8 additions & 0 deletions core/renderers/measurables/square_corner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import {Types} from './types.js';
* during rendering.
*/
export class SquareCorner extends Measurable {
// This field exists solely to structurally distinguish this type from other
// Measurable subclasses. Because this class otherwise has the same fields as
// Measurable, and Typescript doesn't support nominal typing, Typescript will
// consider it and other subclasses in the same situation as being of the same
// type, even if typeguards are used, which could result in Typescript typing
// objects of this class as `never`.
private squareCorner: undefined;

/**
* @param constants The rendering constants provider.
* @param opt_position The position of this corner.
Expand Down
8 changes: 8 additions & 0 deletions core/renderers/measurables/statement_input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ import {Types} from './types.js';
* during rendering
*/
export class StatementInput extends InputConnection {
// This field exists solely to structurally distinguish this type from other
// Measurable subclasses. Because this class otherwise has the same fields as
// Measurable, and Typescript doesn't support nominal typing, Typescript will
// consider it and other subclasses in the same situation as being of the same
// type, even if typeguards are used, which could result in Typescript typing
// objects of this class as `never`.
private statementInput: undefined;

/**
* @param constants The rendering constants provider.
* @param input The statement input to measure and store information for.
Expand Down
3 changes: 1 addition & 2 deletions core/renderers/measurables/top_row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import type {BlockSvg} from '../../block_svg.js';
import type {ConstantProvider} from '../common/constants.js';
import {Hat} from './hat.js';
import type {PreviousConnection} from './previous_connection.js';
import {Row} from './row.js';
import {Types} from './types.js';
Expand Down Expand Up @@ -85,7 +84,7 @@ export class TopRow extends Row {
const elem = this.elements[i];
width += elem.width;
if (!Types.isSpacer(elem)) {
if (Types.isHat(elem) && elem instanceof Hat) {
if (Types.isHat(elem)) {
ascenderHeight = Math.max(ascenderHeight, elem.ascenderHeight);
} else {
height = Math.max(height, elem.height);
Expand Down
Loading

0 comments on commit 151d21e

Please sign in to comment.