Skip to content

Commit 1ba01f1

Browse files
chore: fix lint errors except non-null createXXXNode
1 parent 817e18d commit 1ba01f1

24 files changed

+232
-181
lines changed

eslint.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ module.exports = [
129129
},
130130
},
131131
{
132-
files: ['**/*.mocha.js'],
132+
files: ['**/*.mocha.js', 'test/webdriverio/test/*_test.mjs'],
133133
languageOptions: {
134134
globals: {
135135
...globals.mocha,

src/actions/action_menu.ts

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
ContextMenu,
1111
ContextMenuRegistry,
1212
ShortcutRegistry,
13-
comments,
1413
utils as BlocklyUtils,
1514
WidgetDiv,
1615
} from 'blockly';
@@ -23,10 +22,7 @@ const createSerializedKey = ShortcutRegistry.registry.createSerializedKey.bind(
2322
ShortcutRegistry.registry,
2423
);
2524

26-
export interface Scope {
27-
block?: BlockSvg;
28-
workspace?: WorkspaceSvg;
29-
comment?: comments.RenderedWorkspaceComment;
25+
export interface ScopeWithConnection extends ContextMenuRegistry.Scope {
3026
connection?: Connection;
3127
}
3228

@@ -100,6 +96,8 @@ export class ActionMenu {
10096
* Returns true if it is possible to open the action menu in the
10197
* current location, even if the menu was not opened due there being
10298
* no applicable menu items.
99+
*
100+
* @param workspace The workspace.
103101
*/
104102
private openActionMenu(workspace: WorkspaceSvg): boolean {
105103
let menuOptions: Array<
@@ -114,7 +112,7 @@ export class ActionMenu {
114112
if (!node) return false;
115113
const nodeType = node.getType();
116114
switch (nodeType) {
117-
case ASTNode.types.BLOCK:
115+
case ASTNode.types.BLOCK: {
118116
const block = node.getLocation() as BlockSvg;
119117
rtl = block.RTL;
120118
// Reimplement BlockSvg.prototype.generateContextMenu as that
@@ -130,11 +128,12 @@ export class ActionMenu {
130128
}
131129
// End reimplement.
132130
break;
131+
}
133132

134133
// case Blockly.ASTNode.types.INPUT:
135134
case ASTNode.types.NEXT:
136135
case ASTNode.types.PREVIOUS:
137-
case ASTNode.types.INPUT:
136+
case ASTNode.types.INPUT: {
138137
const connection = node.getLocation() as Connection;
139138
rtl = connection.getSourceBlock().RTL;
140139

@@ -143,6 +142,7 @@ export class ActionMenu {
143142
// a possible kind of scope.
144143
this.addConnectionItems(connection, menuOptions);
145144
break;
145+
}
146146

147147
default:
148148
console.info(`No action menu for ASTNode of type ${nodeType}`);
@@ -177,24 +177,21 @@ export class ActionMenu {
177177
*/
178178
private addConnectionItems(
179179
connection: Connection,
180-
menuOptions: (
180+
menuOptions: Array<
181181
| ContextMenuRegistry.ContextMenuOption
182182
| ContextMenuRegistry.LegacyContextMenuOption
183-
)[],
183+
>,
184184
) {
185-
const insertAction = ContextMenuRegistry.registry.getItem('insert');
186-
if (!insertAction) throw new Error("can't find insert action");
187-
188-
const pasteAction = ContextMenuRegistry.registry.getItem(
189-
'blockPasteFromContextMenu',
190-
);
191-
if (!pasteAction) throw new Error("can't find paste action");
192-
const possibleOptions = [insertAction, pasteAction /* etc.*/];
185+
const possibleOptions = [
186+
this.getContextMenuAction('insert'),
187+
this.getContextMenuAction('blockPasteFromContextMenu'),
188+
];
193189

194190
// Check preconditions and get menu texts.
195191
const scope = {
196192
connection,
197193
} as unknown as ContextMenuRegistry.Scope;
194+
198195
for (const option of possibleOptions) {
199196
const precondition = option.preconditionFn?.(scope);
200197
if (precondition === 'hidden') continue;
@@ -205,14 +202,33 @@ export class ActionMenu {
205202
menuOptions.push({
206203
text: displayText,
207204
enabled: precondition === 'enabled',
208-
callback: option.callback!,
205+
callback: option.callback,
209206
scope,
210207
weight: option.weight,
211208
});
212209
}
213210
return menuOptions;
214211
}
215212

213+
/**
214+
* Find a context menu action, throwing an `Error` if it is not present or
215+
* not an action. This usefully narrows the type to `ActionRegistryItem`
216+
* which is not exported from Blockly.
217+
*
218+
* @param id The id of the action.
219+
* @returns the action.
220+
*/
221+
private getContextMenuAction(id: string) {
222+
const item = ContextMenuRegistry.registry.getItem('insert');
223+
if (!item) {
224+
throw new Error(`can't find context menu item ${id}`);
225+
}
226+
if (!item?.callback) {
227+
throw new Error(`context menu item unexpectedly not action ${id}`);
228+
}
229+
return item;
230+
}
231+
216232
/**
217233
* Create a fake PointerEvent for opening the action menu for the
218234
* given ASTNode.

src/actions/arrow_navigation.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class ArrowNavigation {
5757
right: {
5858
name: Constants.SHORTCUT_NAMES.RIGHT,
5959
preconditionFn: (workspace) => this.canCurrentlyNavigate(workspace),
60-
callback: (workspace, _, shortcut) => {
60+
callback: (workspace, e, shortcut) => {
6161
const toolbox = workspace.getToolbox() as Toolbox;
6262
let isHandled = false;
6363
switch (this.navigation.getState(workspace)) {
@@ -94,7 +94,7 @@ export class ArrowNavigation {
9494
left: {
9595
name: Constants.SHORTCUT_NAMES.LEFT,
9696
preconditionFn: (workspace) => this.canCurrentlyNavigate(workspace),
97-
callback: (workspace, _, shortcut) => {
97+
callback: (workspace, e, shortcut) => {
9898
const toolbox = workspace.getToolbox() as Toolbox;
9999
let isHandled = false;
100100
switch (this.navigation.getState(workspace)) {
@@ -129,7 +129,7 @@ export class ArrowNavigation {
129129
down: {
130130
name: Constants.SHORTCUT_NAMES.DOWN,
131131
preconditionFn: (workspace) => this.canCurrentlyNavigate(workspace),
132-
callback: (workspace, _, shortcut) => {
132+
callback: (workspace, e, shortcut) => {
133133
const toolbox = workspace.getToolbox() as Toolbox;
134134
const flyout = workspace.getFlyout();
135135
let isHandled = false;
@@ -170,7 +170,7 @@ export class ArrowNavigation {
170170
up: {
171171
name: Constants.SHORTCUT_NAMES.UP,
172172
preconditionFn: (workspace) => this.canCurrentlyNavigate(workspace),
173-
callback: (workspace, _, shortcut) => {
173+
callback: (workspace, e, shortcut) => {
174174
const flyout = workspace.getFlyout();
175175
const toolbox = workspace.getToolbox() as Toolbox;
176176
let isHandled = false;

src/actions/clipboard.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import * as Constants from '../constants';
1818
import type {BlockSvg, WorkspaceSvg} from 'blockly';
1919
import {LineCursor} from '../line_cursor';
2020
import {Navigation} from '../navigation';
21+
import {ScopeWithConnection} from './action_menu';
2122

2223
const KeyCodes = blocklyUtils.KeyCodes;
2324
const createSerializedKey = ShortcutRegistry.registry.createSerializedKey.bind(
@@ -238,21 +239,23 @@ export class Clipboard {
238239
private copyPrecondition(workspace: WorkspaceSvg) {
239240
if (!this.canCurrentlyEdit(workspace)) return false;
240241
switch (this.navigation.getState(workspace)) {
241-
case Constants.STATE.WORKSPACE:
242+
case Constants.STATE.WORKSPACE: {
242243
const curNode = workspace?.getCursor()?.getCurNode();
243244
const source = curNode?.getSourceBlock();
244245
return !!(
245246
source?.isDeletable() &&
246247
source?.isMovable() &&
247248
!Gesture.inProgress()
248249
);
249-
case Constants.STATE.FLYOUT:
250+
}
251+
case Constants.STATE.FLYOUT: {
250252
const flyoutWorkspace = workspace.getFlyout()?.getWorkspace();
251253
const sourceBlock = flyoutWorkspace
252254
?.getCursor()
253255
?.getCurNode()
254256
?.getSourceBlock();
255257
return !!(sourceBlock && !Gesture.inProgress());
258+
}
256259
default:
257260
return false;
258261
}
@@ -314,18 +317,15 @@ export class Clipboard {
314317
private registerPasteContextMenuAction() {
315318
const pasteAction: ContextMenuRegistry.RegistryItem = {
316319
displayText: (scope) => `Paste (${this.getPlatformPrefix()}V)`,
317-
preconditionFn: (scope) => {
318-
const ws =
319-
scope.block?.workspace ??
320-
(scope as any).connection?.getSourceBlock().workspace;
320+
preconditionFn: (scope: ScopeWithConnection) => {
321+
const block = scope.block ?? scope.connection?.getSourceBlock();
322+
const ws = block?.workspace as WorkspaceSvg | null;
321323
if (!ws) return 'hidden';
322-
323324
return this.pastePrecondition(ws) ? 'enabled' : 'disabled';
324325
},
325-
callback: (scope) => {
326-
const ws =
327-
scope.block?.workspace ??
328-
(scope as any).connection?.getSourceBlock().workspace;
326+
callback: (scope: ScopeWithConnection) => {
327+
const block = scope.block ?? scope.connection?.getSourceBlock();
328+
const ws = block?.workspace as WorkspaceSvg | null;
329329
if (!ws) return;
330330
return this.pasteCallback(ws);
331331
},

src/actions/delete.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ export class DeleteAction {
113113
// Run the original precondition code, from the context menu option.
114114
// If the item would be hidden or disabled, respect it.
115115
const originalPreconditionResult =
116-
this.oldContextMenuItem!.preconditionFn?.(scope) ?? 'enabled';
116+
this.oldContextMenuItem?.preconditionFn?.(scope) ?? 'enabled';
117117
if (!ws || originalPreconditionResult !== 'enabled') {
118118
return originalPreconditionResult;
119119
}

src/actions/disconnect.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,17 @@ export class DisconnectAction {
117117
if (!curConnection.isConnected()) {
118118
return;
119119
}
120+
const targetConnection = curConnection.targetConnection;
121+
if (!targetConnection) {
122+
throw new Error('Must have target if connected');
123+
}
124+
120125
const superiorConnection = curConnection.isSuperior()
121126
? curConnection
122-
: curConnection.targetConnection!;
127+
: targetConnection;
123128

124129
const inferiorConnection = curConnection.isSuperior()
125-
? curConnection.targetConnection!
130+
? targetConnection
126131
: curConnection;
127132

128133
if (inferiorConnection.getSourceBlock().isShadow()) {
@@ -140,8 +145,8 @@ export class DisconnectAction {
140145
rootBlock.bringToFront();
141146

142147
if (wasVisitingConnection) {
143-
const connectionNode = ASTNode.createConnectionNode(superiorConnection);
144-
workspace.getCursor()!.setCurNode(connectionNode!);
148+
const connectionNode = ASTNode.createConnectionNode(superiorConnection)!;
149+
workspace.getCursor()?.setCurNode(connectionNode);
145150
}
146151
}
147152
}

src/actions/edit.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,9 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import {
8-
Connection,
9-
ContextMenuRegistry,
10-
ShortcutRegistry,
11-
comments,
12-
utils as BlocklyUtils,
13-
} from 'blockly';
14-
import * as Constants from '../constants';
15-
import type {BlockSvg, WorkspaceSvg} from 'blockly';
7+
import {ContextMenuRegistry} from 'blockly';
8+
import type {WorkspaceSvg} from 'blockly';
169
import {LineCursor} from '../line_cursor';
17-
import {NavigationController} from '../navigation_controller';
18-
19-
const KeyCodes = BlocklyUtils.KeyCodes;
2010

2111
/**
2212
* Action to edit a block. This just moves the cursor to the first

src/actions/enter.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ export class EnterAction {
144144
}
145145

146146
this.navigation.focusWorkspace(workspace);
147-
workspace.getCursor()!.setCurNode(ASTNode.createBlockNode(newBlock)!);
147+
workspace.getCursor()?.setCurNode(ASTNode.createBlockNode(newBlock)!);
148148
}
149149

150150
/**
@@ -155,17 +155,22 @@ export class EnterAction {
155155
*/
156156
private triggerButtonCallback(workspace: WorkspaceSvg) {
157157
const button = this.navigation
158-
.getFlyoutCursor(workspace)!
159-
.getCurNode()
158+
.getFlyoutCursor(workspace)
159+
?.getCurNode()
160160
?.getLocation() as FlyoutButton | undefined;
161161
if (!button) return;
162-
const buttonCallback = (workspace as any).flyoutButtonCallbacks.get(
163-
(button as any).callbackKey,
164-
);
165-
if (typeof buttonCallback === 'function') {
162+
163+
const flyoutButtonCallbacks: Map<string, (p1: FlyoutButton) => void> =
164+
// @ts-expect-error private field access
165+
workspace.flyoutButtonCallbacks;
166+
167+
const info = button.info;
168+
if ('callbackkey' in info) {
169+
const buttonCallback = flyoutButtonCallbacks.get(info.callbackkey);
170+
if (!buttonCallback) {
171+
throw new Error('No callback function found for flyout button.');
172+
}
166173
buttonCallback(button);
167-
} else if (!button.isLabel()) {
168-
throw new Error('No callback function found for flyout button.');
169174
}
170175
}
171176

@@ -208,8 +213,8 @@ export class EnterAction {
208213
}
209214

210215
const curBlock = this.navigation
211-
.getFlyoutCursor(workspace)!
212-
.getCurNode()
216+
.getFlyoutCursor(workspace)
217+
?.getCurNode()
213218
?.getLocation() as BlockSvg | undefined;
214219
if (!curBlock?.isEnabled()) {
215220
console.warn("Can't insert a disabled block.");

src/actions/insert.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@
55
*/
66

77
import {
8-
Connection,
98
ContextMenuRegistry,
109
ShortcutRegistry,
11-
comments,
1210
utils as BlocklyUtils,
1311
} from 'blockly';
1412
import * as Constants from '../constants';
15-
import type {BlockSvg, WorkspaceSvg} from 'blockly';
13+
import type {WorkspaceSvg} from 'blockly';
1614
import {Navigation} from '../navigation';
17-
import {Scope} from './action_menu';
15+
import {ScopeWithConnection} from './action_menu';
1816

1917
const KeyCodes = BlocklyUtils.KeyCodes;
2018

@@ -87,15 +85,15 @@ export class InsertAction {
8785
return 'Insert Block (I)';
8886
}
8987
},
90-
preconditionFn: (scope: Scope) => {
88+
preconditionFn: (scope: ScopeWithConnection) => {
9189
const block = scope.block ?? scope.connection?.getSourceBlock();
9290
const ws = block?.workspace as WorkspaceSvg | null;
9391
if (!ws) return 'hidden';
9492

9593
return this.insertPrecondition(ws) ? 'enabled' : 'hidden';
9694
},
97-
callback: (scope: Scope) => {
98-
let ws =
95+
callback: (scope: ScopeWithConnection) => {
96+
const ws =
9997
scope.block?.workspace ??
10098
(scope.connection?.getSourceBlock().workspace as WorkspaceSvg);
10199
if (!ws) return false;

0 commit comments

Comments
 (0)