Skip to content

Commit

Permalink
refactor(generators): Migrate JavaScript generators to TypeScript (#7602
Browse files Browse the repository at this point in the history
)

* refactor(generators): Migrate javascript_generator.js to TypeScript

* refactor(generators): Simplify getAdjusted

  Slightly simplify the implementation of getAdjusted, in part to
  make it more readable.  Also improve its JSDoc comment.

* refactor(generators): Migrate generators/javascript/* to TypeScript

  First pass doing very mechanistic migration, not attempting to fix
  all the resulting type errors.

* fix(generators): Fix type errors in generator functions

  This consists almost entirely of adding casts, so the code output
  by tsc should be as similar as possible to the pre-migration .js
  source files.

* refactor(generators): Migrate generators/javascript.js to TypeScript

  The way the generator functions are added to
  javascriptGenerator.forBlock has been modified so that incorrect
  generator function signatures will cause tsc to generate a type
  error.

* chore(generator): Format

  One block protected with // prettier-ignore to preserve careful
  comment formatting.

  Where there are repeated concatenations prettier has made a pretty
  mess of things, but the correct fix is probably to use template
  literals instead (rather than just locally disabling prettier).
  This has been added to the to-do list in #7600.

* fix(generators): Fixes for PR #7602

* fix(generators): Fix syntax error
  • Loading branch information
cpcallen authored Oct 30, 2023
1 parent 7d2c307 commit 4ab8d00
Show file tree
Hide file tree
Showing 17 changed files with 1,095 additions and 766 deletions.
5 changes: 2 additions & 3 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

# Demos, scripts, misc
/node_modules/*
/generators/*
/demos/*
/appengine/*
/externs/*
Expand All @@ -27,5 +26,5 @@
CHANGELOG.md
PULL_REQUEST_TEMPLATE.md

# Don't bother formatting js blocks since we're getting rid of them
/blocks/*.js
# Don't bother formatting JavaScript files we're about to migrate:
/generators/**/*.js
8 changes: 6 additions & 2 deletions blocks/lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,12 @@ export const blocks = createBlockDefinitionsFromJsonArray([
},
]);

/** Type of a 'lists_create_with' block. */
type CreateWithBlock = Block & ListCreateWithMixin;
/**
* Type of a 'lists_create_with' block.
*
* @internal
*/
export type CreateWithBlock = Block & ListCreateWithMixin;
interface ListCreateWithMixin extends ListCreateWithMixinType {
itemCount_: number;
}
Expand Down
8 changes: 6 additions & 2 deletions blocks/loops.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,12 @@ export const loopTypes: Set<string> = new Set([
'controls_whileUntil',
]);

/** Type of a block that has CONTROL_FLOW_IN_LOOP_CHECK_MIXIN */
type ControlFlowInLoopBlock = Block & ControlFlowInLoopMixin;
/**
* Type of a block that has CONTROL_FLOW_IN_LOOP_CHECK_MIXIN
*
* @internal
*/
export type ControlFlowInLoopBlock = Block & ControlFlowInLoopMixin;
interface ControlFlowInLoopMixin extends ControlFlowInLoopMixinType {}
type ControlFlowInLoopMixinType = typeof CONTROL_FLOW_IN_LOOP_CHECK_MIXIN;

Expand Down
8 changes: 6 additions & 2 deletions blocks/procedures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1209,8 +1209,12 @@ blocks['procedures_callreturn'] = {
defType_: 'procedures_defreturn',
};

/** Type of a procedures_ifreturn block. */
type IfReturnBlock = Block & IfReturnMixin;
/**
* Type of a procedures_ifreturn block.
*
* @internal
*/
export type IfReturnBlock = Block & IfReturnMixin;
interface IfReturnMixin extends IfReturnMixinType {
hasReturnValue_: boolean;
}
Expand Down
8 changes: 6 additions & 2 deletions blocks/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -725,8 +725,12 @@ const QUOTES_EXTENSION = function (this: QuoteImageBlock) {
this.quoteField_('TEXT');
};

/** Type of a block that has TEXT_JOIN_MUTATOR_MIXIN */
type JoinMutatorBlock = BlockSvg & JoinMutatorMixin & QuoteImageMixin;
/**
* Type of a block that has TEXT_JOIN_MUTATOR_MIXIN
*
* @internal
*/
export type JoinMutatorBlock = BlockSvg & JoinMutatorMixin & QuoteImageMixin;
interface JoinMutatorMixin extends JoinMutatorMixinType {}
type JoinMutatorMixinType = typeof JOIN_MUTATOR_MIXIN;

Expand Down
19 changes: 14 additions & 5 deletions generators/javascript.js → generators/javascript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,17 @@ export * from './javascript/javascript_generator.js';
export const javascriptGenerator = new JavascriptGenerator();

// Install per-block-type generator functions:
Object.assign(
javascriptGenerator.forBlock,
colour, lists, logic, loops, math, procedures,
text, variables, variablesDynamic
);
const generators: typeof javascriptGenerator.forBlock = {
...colour,
...lists,
...logic,
...loops,
...math,
...procedures,
...text,
...variables,
...variablesDynamic,
};
for (const name in generators) {
javascriptGenerator.forBlock[name] = generators[name];
}
67 changes: 42 additions & 25 deletions generators/javascript/colour.js → generators/javascript/colour.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,48 @@

// Former goog.module ID: Blockly.JavaScript.colour

import type {Block} from '../../core/block.js';
import type {JavascriptGenerator} from './javascript_generator.js';
import {Order} from './javascript_generator.js';


export function colour_picker(block, generator) {
export function colour_picker(
block: Block,
generator: JavascriptGenerator,
): [string, Order] {
// Colour picker.
const code = generator.quote_(block.getFieldValue('COLOUR'));
return [code, Order.ATOMIC];
};
}

export function colour_random(block, generator) {
export function colour_random(
block: Block,
generator: JavascriptGenerator,
): [string, Order] {
// Generate a random colour.
const functionName = generator.provideFunction_('colourRandom', `
const functionName = generator.provideFunction_(
'colourRandom',
`
function ${generator.FUNCTION_NAME_PLACEHOLDER_}() {
var num = Math.floor(Math.random() * Math.pow(2, 24));
return '#' + ('00000' + num.toString(16)).substr(-6);
}
`);
`,
);
const code = functionName + '()';
return [code, Order.FUNCTION_CALL];
};
}

export function colour_rgb(block, generator) {
export function colour_rgb(
block: Block,
generator: JavascriptGenerator,
): [string, Order] {
// Compose a colour from RGB components expressed as percentages.
const red = generator.valueToCode(block, 'RED', Order.NONE) || 0;
const green =
generator.valueToCode(block, 'GREEN', Order.NONE) || 0;
const blue =
generator.valueToCode(block, 'BLUE', Order.NONE) || 0;
const functionName = generator.provideFunction_('colourRgb', `
const green = generator.valueToCode(block, 'GREEN', Order.NONE) || 0;
const blue = generator.valueToCode(block, 'BLUE', Order.NONE) || 0;
const functionName = generator.provideFunction_(
'colourRgb',
`
function ${generator.FUNCTION_NAME_PLACEHOLDER_}(r, g, b) {
r = Math.max(Math.min(Number(r), 100), 0) * 2.55;
g = Math.max(Math.min(Number(g), 100), 0) * 2.55;
Expand All @@ -48,20 +61,23 @@ function ${generator.FUNCTION_NAME_PLACEHOLDER_}(r, g, b) {
b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);
return '#' + r + g + b;
}
`);
`,
);
const code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';
return [code, Order.FUNCTION_CALL];
};
}

export function colour_blend(block, generator) {
export function colour_blend(
block: Block,
generator: JavascriptGenerator,
): [string, Order] {
// Blend two colours together.
const c1 = generator.valueToCode(block, 'COLOUR1', Order.NONE) ||
"'#000000'";
const c2 = generator.valueToCode(block, 'COLOUR2', Order.NONE) ||
"'#000000'";
const ratio =
generator.valueToCode(block, 'RATIO', Order.NONE) || 0.5;
const functionName = generator.provideFunction_('colourBlend', `
const c1 = generator.valueToCode(block, 'COLOUR1', Order.NONE) || "'#000000'";
const c2 = generator.valueToCode(block, 'COLOUR2', Order.NONE) || "'#000000'";
const ratio = generator.valueToCode(block, 'RATIO', Order.NONE) || 0.5;
const functionName = generator.provideFunction_(
'colourBlend',
`
function ${generator.FUNCTION_NAME_PLACEHOLDER_}(c1, c2, ratio) {
ratio = Math.max(Math.min(Number(ratio), 1), 0);
var r1 = parseInt(c1.substring(1, 3), 16);
Expand All @@ -78,7 +94,8 @@ function ${generator.FUNCTION_NAME_PLACEHOLDER_}(c1, c2, ratio) {
b = ('0' + (b || 0).toString(16)).slice(-2);
return '#' + r + g + b;
}
`);
`,
);
const code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';
return [code, Order.FUNCTION_CALL];
};
}
Loading

0 comments on commit 4ab8d00

Please sign in to comment.