Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
mayarajan3 committed Jul 21, 2024
2 parents 788c937 + 2c513a2 commit 0a64933
Show file tree
Hide file tree
Showing 11 changed files with 855 additions and 98 deletions.
71 changes: 44 additions & 27 deletions extensions/src/common/extension/decorators/blocks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type BlockUtility from "$scratch-vm/engine/block-utility";

Check failure on line 1 in extensions/src/common/extension/decorators/blocks.ts

View workflow job for this annotation

GitHub Actions / build (18)

Cannot find name 'Config'.
import { TypedClassDecorator, TypedGetterDecorator, TypedMethodDecorator, TypedSetterDecorator } from ".";
import { BlockType } from "$common/types/enums";
import { BlockMetadata, ScratchArgument, Argument, NoArgsBlock, Config } from "$common/types";
import { BlockMetadata, ScratchArgument, Argument, NoArgsBlock, VersionedOptions } from "$common/types";
import { getImplementationName } from "../mixins/base/scratchInfo/index";
import { ExtensionInstance } from "..";
import { isFunction, isString, tryCreateBundleTimeEvent } from "$common/utils";
Expand Down Expand Up @@ -64,34 +64,51 @@ export function block<
>
(
blockInfoOrGetter: (BlockMetadata<(...args: TRemoveUtil) => Return> | ((this: This, self: This) => BlockMetadata<(...args: TRemoveUtil) => Return>))
, versions?: Config): TypedMethodDecorator<This, Args, Return, (...args: Args) => Return> {
, versions?: Config): TypedMethodDecorator<This, Args, Return, (...args: Args) => Return> {

return function (this: This, target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, Fn>) {
var opcode = target.name;
const internalFuncName = getImplementationName(opcode);
// could add check for if this block is meant for scratch
if (versions) {
context.addInitializer(function () { this.pushBlock(opcode, blockInfoOrGetter, target, versions) });
} else {
context.addInitializer(function () { this.pushBlock(opcode, blockInfoOrGetter, target) });
}


const isProbableAtBundleTime = !isFunction(blockInfoOrGetter);
if (isProbableAtBundleTime) {
const { type } = blockInfoOrGetter;
blockBundleEvent?.fire({
methodName: opcode,
args: extractArgs(blockInfoOrGetter).map(a => isString(a) ? a : a.type),
// is 'any' an issue? Likely!
returns: type === "command" ? "void" : type === "Boolean" ? "bool" : "any",
scratchType: blockInfoOrGetter.type
});
}
return (function () { return this[internalFuncName].call(this, ...arguments) });



var opcode = target.name;
const internalFuncName = getImplementationName(opcode);
// could add check for if this block is meant for scratch
if (versions) {
context.addInitializer(function () { this.pushBlock(opcode, blockInfoOrGetter, target, versions) });
} else {
context.addInitializer(function () { this.pushBlock(opcode, blockInfoOrGetter, target) });
}


const isProbableAtBundleTime = !isFunction(blockInfoOrGetter);
if (isProbableAtBundleTime) {
const { type } = blockInfoOrGetter;
blockBundleEvent?.fire({
methodName: opcode,
args: extractArgs(blockInfoOrGetter).map(a => isString(a) ? a : a.type),
// is 'any' an issue? Likely!
returns: type === "command" ? "void" : type === "Boolean" ? "bool" : "any",
scratchType: blockInfoOrGetter.type
});
}
return (function () { return this[internalFuncName].call(this, ...arguments) });



};
}

export function versions<
const This extends ExtensionInstance,
const Args extends any[],
const Return,
const Fn extends (...args: Args) => Return,
>
(
...config: VersionedOptions[]
): TypedMethodDecorator<This, Args, Return, (...args: Args) => Return> {

return function (this: This, target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext<This, Fn>) {
context.addInitializer(function () { this.pushVersions(target.name, config); });
//
return target;
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@ interface TemplateEngine<TBlockType extends ScratchBlockType> {
export const scratch = {
reporter: makeDecorator("reporter"),
command: makeDecorator("command"),
hat: makeDecorator("hat"),
button: makeDecorator("button"),
}
3 changes: 2 additions & 1 deletion extensions/src/common/extension/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ExtensionWithFunctionality, MixinName, optionalMixins } from "./mixins/index";
import { ExtensionBase } from "./ExtensionBase";
import scratchInfo from "./mixins/base/scratchInfo";
import scratchVersions from "./mixins/base/scratchVersioning";
import supported from "./mixins/base/supported";
import { ExtensionMenuDisplayDetails, Writeable } from "$common/types";
import { tryCaptureDependencies } from "./mixins/dependencies";
Expand Down Expand Up @@ -56,7 +57,7 @@ export const extension = <const TSupported extends readonly MixinName[]>(
extensionBundleEvent?.fire({ details, addOns });
}

const Base = scratchInfo(supported(ExtensionBase, addOns)) as ExtensionWithFunctionality<[...TSupported]>;
const Base = scratchVersions(scratchInfo(supported(ExtensionBase, addOns))) as ExtensionWithFunctionality<[...TSupported]>;

if (!addOns) return Base;

Expand Down
8 changes: 6 additions & 2 deletions extensions/src/common/extension/mixins/base/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import scratchInfo from "./scratchInfo/index";
import scratchVersioning from "./scratchVersioning/index";
import supported from "./supported";

export type CustomizableExtensionConstructor = ReturnType<typeof supported>;
export type CustomizableExtensionInstance = InstanceType<CustomizableExtensionConstructor>

export type MinimalExtensionConstructor = ReturnType<typeof scratchInfo>;
export type MinimalExtensionInstance = InstanceType<ReturnType<typeof scratchInfo>>;
export type BaseScratchExtensionConstuctor = ReturnType<typeof scratchInfo>;
export type BaseScratchExtensionInstance = InstanceType<BaseScratchExtensionConstuctor>;

export type MinimalExtensionConstructor = ReturnType<typeof scratchVersioning>;
export type MinimalExtensionInstance = InstanceType<ReturnType<typeof scratchVersioning>>;
28 changes: 21 additions & 7 deletions extensions/src/common/extension/mixins/base/scratchInfo/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { castToType } from "$common/cast";
import CustomArgumentManager from "$common/extension/mixins/configurable/customArguments/CustomArgumentManager";
import { ArgumentType, BlockType } from "$common/types/enums";
import { Config } from "$common/types"
import { BlockOperation, ValueOf, Menu, ExtensionMetadata, ExtensionBlockMetadata, ExtensionMenuMetadata, DynamicMenu, BlockMetadata, BlockUtilityWithID, } from "$common/types";
import { BlockOperation, ValueOf, Menu, ExtensionMetadata, ExtensionBlockMetadata, ExtensionMenuMetadata, DynamicMenu, BlockMetadata, BlockUtilityWithID, VersionedOptions } from "$common/types";
import { registerButtonCallback } from "$common/ui";
import { isString, typesafeCall, } from "$common/utils";
import { menuProbe, asStaticMenu, getMenuName, convertMenuItemsToString } from "./menus";
import { Handler } from "./handlers";
import { BlockDefinition, getButtonID, isBlockGetter } from "./util";
import { convertToArgumentInfo, extractArgs, zipArgs } from "./args";
import { convertToDisplayText } from "./text";
import { CustomizableExtensionConstructor, MinimalExtensionInstance, } from "..";
import { CustomizableExtensionConstructor, BaseScratchExtensionInstance, } from "..";
import { ExtensionInstanceWithFunctionality } from "../..";
import { blockIDKey } from "$common/globals";

Expand All @@ -31,7 +30,7 @@ const checkForBlockContext = (blockUtility: BlockUtilityWithID) => isBlockUtilit
* @param args The args that must be parsed before being passed to the underlying operation
* @returns
*/
export const wrapOperation = <T extends MinimalExtensionInstance>(
export const wrapOperation = <T extends BaseScratchExtensionInstance>(
_this: T,
operation: BlockOperation,
args: { name: string, type: ValueOf<typeof ArgumentType>, handler: Handler }[]
Expand Down Expand Up @@ -73,8 +72,10 @@ export const wrapOperation = <T extends MinimalExtensionInstance>(
export default function (Ctor: CustomizableExtensionConstructor) {
type BlockEntry = { definition: BlockDefinition<ScratchExtension, BlockOperation>, operation: BlockOperation, versions: Config };
type BlockMap = Map<string, BlockEntry>;
type VersionMap = Map<string, VersionedOptions[]>;
abstract class ScratchExtension extends Ctor {
private readonly blockMap: BlockMap = new Map();
private readonly versionMap: VersionMap = new Map();

private readonly menus: Menu<any>[] = [];
private info: ExtensionMetadata;
Expand All @@ -89,11 +90,24 @@ export default function (Ctor: CustomizableExtensionConstructor) {
pushBlock<Fn extends BlockOperation>(opcode: string, definition: BlockDefinition<any, Fn>, operation: BlockOperation, versions?: Config) {
if (this.blockMap.has(opcode)) throw new Error(`Attempt to push block with opcode ${opcode}, but it was already set. This is assumed to be a mistake.`)
if (versions) {
this.blockMap.set(opcode, { definition, operation, versions} as BlockEntry);
this.blockMap.set(opcode, { definition, operation, versions } as BlockEntry);
} else {
this.blockMap.set(opcode, { definition, operation, versions: [] } as BlockEntry);
}


}

pushVersions(opcode: string, versions: any) {
if (this.versionMap.has(opcode)) throw new Error(`Attempt to push block with opcode ${opcode}, but it was already set. This is assumed to be a mistake.`)
this.versionMap.set(opcode, versions);
}

getVersion(opcode: string) {
return this.versionMap.get(opcode);
}

getVersionMap() {
return this.versionMap;
}

protected getInfo(): ExtensionMetadata {
Expand Down Expand Up @@ -134,7 +148,7 @@ export default function (Ctor: CustomizableExtensionConstructor) {
info.func = buttonID;
} else {
const implementationName = getImplementationName(opcode);
this[implementationName] = wrapOperation(this as MinimalExtensionInstance, operation, zipArgs(args));
this[implementationName] = wrapOperation(this as BaseScratchExtensionInstance, operation, zipArgs(args));
}

return info;
Expand Down
Loading

0 comments on commit 0a64933

Please sign in to comment.