slightning-coco-widget
Version:
SLIGHTNING 的 CoCo 控件框架。
305 lines (304 loc) • 10.7 kB
JavaScript
import { merge } from "../../utils";
import { FunctionType, MutatorType } from "../type";
import { BlockType, BUILD_IN_ICON_URL_MAP } from "../types";
export function traverseTypes(types, visitors) {
if (hasVisitor(visitors.PropertyGroup) ||
hasVisitor(visitors.PropertyTypes)) {
for (const index = { value: 0 }; index.value <= types.properties.length; index.value++) {
const property = types.properties[index.value];
if (property == undefined) {
continue;
}
if ("contents" in property) {
new PropertyGroupNode({
groupContents: types.properties,
index,
value: property
}).traverse(visitors);
continue;
}
new PropertyTypesNode({
groupContents: types.properties,
index,
value: property
}).traverse(visitors);
}
}
if (hasVisitor(visitors.MethodGroup) ||
hasVisitor(visitors.MethodTypes) ||
hasVisitor(visitors.EventTypes) ||
hasVisitor(visitors.BlockBoxOptions)) {
for (const index = { value: 0 }; index.value <= types.methods.length; index.value++) {
const method = types.methods[index.value];
if (method == undefined) {
continue;
}
if ("contents" in method) {
new MethodGroupNode({
groupContents: types.methods,
index,
value: method
}).traverse(visitors);
continue;
}
if ("type" in method) {
switch (method.type) {
case BlockType.METHOD:
new MethodTypesNode({
groupContents: types.methods,
index,
value: method
}).traverse(visitors);
break;
case BlockType.EVENT:
new EventTypesNode({
groupContents: types.methods,
index,
value: method
}).traverse(visitors);
break;
}
}
else {
new BlockBoxOptionsNode({
groupContents: types.methods,
index,
value: method
}).traverse(visitors);
}
}
}
}
export class TypesNode {
/**
* 节点的积木选项。与`this.value.blockOptions`不同的是,该项包含从组中继承的积木选项。
*/
get blockOptions() {
var _a, _b, _c;
if (this.__blockOptions !== undefined) {
return this.__blockOptions;
}
const { value } = this;
return this.__blockOptions = merge({}, (_b = ((_a = this.group) !== null && _a !== void 0 ? _a : {}).blockOptions) !== null && _b !== void 0 ? _b : {}, value != null && typeof value == "object" && "blockOptions" in value ? (_c = value.blockOptions) !== null && _c !== void 0 ? _c : {} : {});
}
constructor({ group, groupContents, index, value }) {
this.group = group;
this.groupContents = groupContents;
this.index = index;
this.value = value;
this.isRemoved = false;
}
remove() {
if (this.isRemoved) {
return;
}
this.groupContents.splice(this.index.value, 1);
this.index.value--;
this.isRemoved = true;
}
removeNext() {
this.groupContents.splice(this.index.value + 1, 1);
}
replaceWith(...values) {
this.remove();
this.insertAfter(...values);
}
insertAfter(...values) {
this.groupContents.splice(this.index.value + 1, 0, ...values);
}
}
export class PropertyGroupNode extends TypesNode {
traverse(visitors) {
if (!(hasVisitor(visitors.PropertyGroup) ||
hasVisitor(visitors.PropertyTypes))) {
return;
}
enterNode(this, visitors.PropertyGroup);
for (const index = { value: 0 }; index.value <= this.value.contents.length; index.value++) {
const property = this.value.contents[index.value];
if (property == undefined) {
continue;
}
if ("contents" in property) {
new PropertyGroupNode({
group: this,
groupContents: this.value.contents,
index,
value: property
}).traverse(visitors);
continue;
}
new PropertyTypesNode({
group: this,
groupContents: this.value.contents,
index,
value: property
}).traverse(visitors);
}
exitNode(this, visitors.PropertyGroup);
}
}
export class PropertyTypesNode extends TypesNode {
traverse(visitors) {
enterNode(this, visitors.PropertyTypes);
exitNode(this, visitors.PropertyTypes);
}
}
export class MethodGroupNode extends TypesNode {
traverse(visitors) {
if (!(hasVisitor(visitors.MethodGroup) ||
hasVisitor(visitors.MethodTypes) ||
hasVisitor(visitors.EventTypes) ||
hasVisitor(visitors.BlockBoxOptions))) {
return;
}
enterNode(this, visitors.MethodGroup);
for (const index = { value: 0 }; index.value <= this.value.contents.length; index.value++) {
const method = this.value.contents[index.value];
if (method == undefined) {
continue;
}
if ("contents" in method) {
new MethodGroupNode({
group: this,
groupContents: this.value.contents,
index,
value: method
}).traverse(visitors);
continue;
}
if ("type" in method) {
switch (method.type) {
case BlockType.METHOD:
new MethodTypesNode({
group: this,
groupContents: this.value.contents,
index,
value: method
}).traverse(visitors);
break;
case BlockType.EVENT:
new EventTypesNode({
group: this,
groupContents: this.value.contents,
index,
value: method
}).traverse(visitors);
break;
}
}
else {
new BlockBoxOptionsNode({
group: this,
groupContents: this.value.contents,
index,
value: method
}).traverse(visitors);
}
}
exitNode(this, visitors.MethodGroup);
}
}
export class MethodTypesNode extends TypesNode {
traverse(visitors) {
enterNode(this, visitors.MethodTypes);
exitNode(this, visitors.MethodTypes);
}
}
export class EventTypesNode extends TypesNode {
traverse(visitors) {
enterNode(this, visitors.EventTypes);
exitNode(this, visitors.EventTypes);
}
}
export class BlockBoxOptionsNode extends TypesNode {
traverse(visitors) {
enterNode(this, visitors.BlockBoxOptions);
exitNode(this, visitors.BlockBoxOptions);
}
}
function hasVisitor(visitor) {
return getVisitorCache(visitor, "has", () => (hasEnter(visitor) || hasExit(visitor)));
}
function hasEnter(visitor) {
return getVisitorCache(visitor, "hasEnter", () => (visitor != null && (typeof visitor == "function" ||
visitor.enter != null ||
visitor.entry != null)));
}
function hasExit(visitor) {
return getVisitorCache(visitor, "hasExit", () => (visitor != null && typeof visitor != "function" && visitor.exit != null));
}
function NULL_TYPES_NODE_VISITOR_FUNCTION() { }
function enterNode(node, visitor) {
getVisitorCache(visitor, "enter", () => {
if (visitor == null) {
return NULL_TYPES_NODE_VISITOR_FUNCTION;
}
if (typeof visitor == "function") {
return visitor;
}
else if (visitor.enter != null) {
return visitor.enter;
}
else if (visitor.entry != null) {
return visitor.entry;
}
return NULL_TYPES_NODE_VISITOR_FUNCTION;
})(node);
}
function exitNode(node, visitor) {
getVisitorCache(visitor, "exit", () => {
if (visitor != null && typeof visitor == "object" && visitor.exit != null) {
return visitor.exit;
}
return NULL_TYPES_NODE_VISITOR_FUNCTION;
})(node);
}
const NULL_TYPES_NODE_VISITOR_CACHE = {
has: false,
hasEnter: false,
hasExit: false
};
function getVisitorCache(visitor, property, loader) {
let visitorCache;
if (visitor == null) {
visitorCache = NULL_TYPES_NODE_VISITOR_CACHE;
}
else {
if (visitor.__slightning_coco_widget_visitor_cache__ == null) {
visitor.__slightning_coco_widget_visitor_cache__ = {};
}
visitorCache = visitor.__slightning_coco_widget_visitor_cache__;
}
const value = visitorCache[property];
if (value == null) {
return visitorCache[property] = loader();
}
return value;
}
export function methodParamNeedsTransformToEvent(part) {
if (typeof part != "object") {
return false;
}
return part.type instanceof FunctionType && !part.type.raw;
}
export function methodParamNeedsTransformToCodeBlocks(part) {
if (typeof part != "object") {
return false;
}
return part.type instanceof FunctionType &&
!part.type.raw && ((part.type.returns != null && !(part.type.returns.isVoid())) ||
(part.type.throws != null && !(part.type.throws.isVoid())));
}
export function methodParamTypeIsMutator(part) {
if (typeof part != "object") {
return false;
}
return part.type instanceof MutatorType;
}
export function transformIcon(object) {
var _a;
if (object != null && object.icon != null) {
object.icon = (_a = BUILD_IN_ICON_URL_MAP[object.icon]) !== null && _a !== void 0 ? _a : object.icon;
}
}