Skip to content

Commit

Permalink
Upgrade rules for variable pin param (#5712)
Browse files Browse the repository at this point in the history
* Beautify comments

* Add patch for variable pin param

* Fix block in test to shadow
  • Loading branch information
sae220 authored Aug 26, 2024
1 parent bf7ff7c commit b4962a3
Show file tree
Hide file tree
Showing 3 changed files with 243 additions and 152 deletions.
279 changes: 185 additions & 94 deletions editor/patch.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,96 @@
/**
* <block type="device_show_leds">
<field name="LED00">FALSE</field>
<field name="LED10">FALSE</field>
<field name="LED20">FALSE</field>
<field name="LED30">FALSE</field>
<field name="LED40">FALSE</field>
<field name="LED01">FALSE</field>
<field name="LED11">FALSE</field>
<field name="LED21">FALSE</field>
<field name="LED31">TRUE</field>
<field name="LED41">FALSE</field>
<field name="LED02">FALSE</field>
<field name="LED12">FALSE</field>
<field name="LED22">FALSE</field>
<field name="LED32">FALSE</field>
<field name="LED42">FALSE</field>
<field name="LED03">FALSE</field>
<field name="LED13">TRUE</field>
<field name="LED23">FALSE</field>
<field name="LED33">FALSE</field>
<field name="LED43">FALSE</field>
<field name="LED04">FALSE</field>
<field name="LED14">FALSE</field>
<field name="LED24">FALSE</field>
<field name="LED34">FALSE</field>
<field name="LED44">FALSE</field>
</block>
to
<block type="device_show_leds">
<field name="LEDS">`
# # # # #
. . . . #
. . . . .
. . . . #
. . . . #
`
</field>
</block>
*/

export function patchBlocks(pkgTargetVersion: string, dom: Element) {

if (pxt.semver.majorCmp(pkgTargetVersion || "0.0.0", "7.0.13") <= 0) {
// Variable pin param
/*
<block type="device_get_digital_pin">
<field name="name">DigitalPin.P0</field>
</block>
converts to
<block type="device_get_digital_pin">
<value name="name">
<shadow type="digital_pin">
<field name="pin">DigitalPin.P0</field>
</shadow>
</value>
</block>
*/
pxt.U.toArray(dom.querySelectorAll("block[type=device_get_digital_pin]"))
.concat(pxt.U.toArray(dom.querySelectorAll("shadow[type=device_get_digital_pin]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_set_digital_pin]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_get_analog_pin]")))
.concat(pxt.U.toArray(dom.querySelectorAll("shadow[type=device_get_analog_pin]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_set_analog_pin]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_set_analog_period]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=pins_on_pulsed]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=pins_pulse_in]")))
.concat(pxt.U.toArray(dom.querySelectorAll("shadow[type=pins_pulse_in]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_set_servo_pin]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_set_servo_pulse]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_analog_set_pitch_pin]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_set_pull]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_set_pin_events]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=pin_neopixel_matrix_width]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=spi_pins]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=pin_set_audio_pin]")))
.forEach(node => {
const blockType = node.getAttribute("type");
pxt.U.toArray(node.children)
.filter(oldPinNode => {
if (oldPinNode.tagName != "field") return false;
switch (blockType) {
case "device_get_digital_pin":
case "device_set_digital_pin":
case "device_get_analog_pin":
case "device_set_analog_pin":
case "pins_pulse_in":
case "device_set_servo_pin":
case "device_analog_set_pitch_pin":
case "pin_set_audio_pin":
return oldPinNode.getAttribute("name") === "name";
case "device_set_analog_period":
case "pins_on_pulsed":
case "device_set_pull":
case "device_set_pin_events":
case "pin_neopixel_matrix_width":
return oldPinNode.getAttribute("name") === "pin";
case "device_set_servo_pulse":
return oldPinNode.getAttribute("name") === "value";
case "spi_pins":
return ["mosi", "miso", "sck"].includes(oldPinNode.getAttribute("name"));
}
return false;
})
.forEach(oldPinNode => {
const valueNode = node.ownerDocument.createElement("value");
valueNode.setAttribute("name", oldPinNode.getAttribute("name"));

const pinShadowNode = node.ownerDocument.createElement("shadow");
let pinBlockType;
switch (oldPinNode.textContent.split(".")[0]) {
case "DigitalPin":
pinBlockType = "digital_pin";
break;
case "AnalogPin":
pinBlockType = "analog_pin";
break;
}
if (!pinBlockType) return;
pinShadowNode.setAttribute("type", pinBlockType);

const fieldNode = node.ownerDocument.createElement("field");
fieldNode.setAttribute("name", "pin");
fieldNode.textContent = oldPinNode.textContent;

pinShadowNode.appendChild(fieldNode);
valueNode.appendChild(pinShadowNode);
node.replaceChild(valueNode, oldPinNode);
});
});
}

if (pxt.semver.majorCmp(pkgTargetVersion || "0.0.0", "5.0.12") <= 0) {
// Eighth note misspelling
/*
Expand Down Expand Up @@ -79,64 +128,106 @@ export function patchBlocks(pkgTargetVersion: string, dom: Element) {
if (pxt.semver.majorCmp(pkgTargetVersion || "0.0.0", "1.0.0") >= 0) return;

// showleds
const nodes = pxt.U.toArray(dom.querySelectorAll("block[type=device_show_leds]"))
/**
<block type="device_show_leds">
<field name="LED00">FALSE</field>
<field name="LED10">FALSE</field>
<field name="LED20">FALSE</field>
<field name="LED30">FALSE</field>
<field name="LED40">FALSE</field>
<field name="LED01">FALSE</field>
<field name="LED11">FALSE</field>
<field name="LED21">FALSE</field>
<field name="LED31">TRUE</field>
<field name="LED41">FALSE</field>
<field name="LED02">FALSE</field>
<field name="LED12">FALSE</field>
<field name="LED22">FALSE</field>
<field name="LED32">FALSE</field>
<field name="LED42">FALSE</field>
<field name="LED03">FALSE</field>
<field name="LED13">TRUE</field>
<field name="LED23">FALSE</field>
<field name="LED33">FALSE</field>
<field name="LED43">FALSE</field>
<field name="LED04">FALSE</field>
<field name="LED14">FALSE</field>
<field name="LED24">FALSE</field>
<field name="LED34">FALSE</field>
<field name="LED44">FALSE</field>
</block>
converts to
<block type="device_show_leds">
<field name="LEDS">`
. . . . .
. . . # .
. . . . .
. # . . .
. . . . .
`
</field>
</block>
*/
pxt.U.toArray(dom.querySelectorAll("block[type=device_show_leds]"))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_build_image]")))
.concat(pxt.U.toArray(dom.querySelectorAll("shadow[type=device_build_image]")))
.concat(pxt.U.toArray(dom.querySelectorAll("block[type=device_build_big_image]")))
.concat(pxt.U.toArray(dom.querySelectorAll("shadow[type=device_build_big_image]")));
nodes.forEach(node => {
// don't rewrite if already upgraded, eg. field LEDS already present
if (pxt.U.toArray(node.children).filter(child => child.tagName == "field" && "LEDS" == child.getAttribute("name"))[0])
return;
// read LEDxx value and assmebly into a new field
const leds: string[][] = [[], [], [], [], []];
pxt.U.toArray(node.children)
.filter(child => child.tagName == "field" && /^LED\d+$/.test(child.getAttribute("name")))
.forEach(lednode => {
let n = lednode.getAttribute("name");
let col = parseInt(n[3]);
let row = parseInt(n[4]);
leds[row][col] = lednode.innerHTML == "TRUE" ? "#" : ".";
// remove node
node.removeChild(lednode);
});
// add new field
const f = node.ownerDocument.createElement("field");
f.setAttribute("name", "LEDS");
const s = '`\n' + leds.map(row => row.join('')).join('\n') + '\n`';
f.appendChild(node.ownerDocument.createTextNode(s));
node.insertBefore(f, null);
});
.concat(pxt.U.toArray(dom.querySelectorAll("shadow[type=device_build_big_image]")))
.forEach(node => {
// don't rewrite if already upgraded, eg. field LEDS already present
if (pxt.U.toArray(node.children).filter(child => child.tagName == "field" && "LEDS" == child.getAttribute("name"))[0])
return;
// read LEDxx value and assmebly into a new field
const leds: string[][] = [[], [], [], [], []];
pxt.U.toArray(node.children)
.filter(child => child.tagName == "field" && /^LED\d+$/.test(child.getAttribute("name")))
.forEach(lednode => {
let n = lednode.getAttribute("name");
let col = parseInt(n[3]);
let row = parseInt(n[4]);
leds[row][col] = lednode.innerHTML == "TRUE" ? "#" : ".";
// remove node
node.removeChild(lednode);
});
// add new field
const f = node.ownerDocument.createElement("field");
f.setAttribute("name", "LEDS");
const s = '`\n' + leds.map(row => row.join('')).join('\n') + '\n`';
f.appendChild(node.ownerDocument.createTextNode(s));
node.insertBefore(f, null);
});

// radio
/*
<block type="radio_on_packet" x="174" y="120">
<mutation callbackproperties="receivedNumber" renamemap="{}"></mutation>
<field name="receivedNumber">receivedNumber</field>
</block>
<block type="radio_on_packet" disabled="true" x="127" y="263">
<mutation callbackproperties="receivedString,receivedNumber" renamemap="{&quot;receivedString&quot;:&quot;name&quot;,&quot;receivedNumber&quot;:&quot;value&quot;}"></mutation>
<field name="receivedString">name</field>
<field name="receivedNumber">value</field>
</block>
<block type="radio_on_packet" disabled="true" x="162" y="420">
<mutation callbackproperties="receivedString" renamemap="{}"></mutation>
<field name="receivedString">receivedString</field>
</block>
converts to
<block type="radio_on_number" x="196" y="208">
<field name="HANDLER_receivedNumber" id="DCy(W;1)*jLWQUpoy4Mm" variabletype="">receivedNumber</field>
</block>
<block type="radio_on_value" x="134" y="408">
<field name="HANDLER_name" id="*d-Jm^MJXO]Djs(dTR*?" variabletype="">name</field>
<field name="HANDLER_value" id="A6HQjH[k^X43o3h775+G" variabletype="">value</field>
</block>
<block type="radio_on_string" x="165" y="583">
<field name="HANDLER_receivedString" id="V9KsE!h$(iO?%W:[32CV" variabletype="">receivedString</field>
</block>
*/
<block type="radio_on_packet" x="174" y="120">
<mutation callbackproperties="receivedNumber" renamemap="{}"></mutation>
<field name="receivedNumber">receivedNumber</field>
</block>
<block type="radio_on_packet" disabled="true" x="127" y="263">
<mutation callbackproperties="receivedString,receivedNumber" renamemap="{&quot;receivedString&quot;:&quot;name&quot;,&quot;receivedNumber&quot;:&quot;value&quot;}"></mutation>
<field name="receivedString">name</field>
<field name="receivedNumber">value</field>
</block>
<block type="radio_on_packet" disabled="true" x="162" y="420">
<mutation callbackproperties="receivedString" renamemap="{}"></mutation>
<field name="receivedString">receivedString</field>
</block>
converts to
<block type="radio_on_number" x="196" y="208">
<field name="HANDLER_receivedNumber" id="DCy(W;1)*jLWQUpoy4Mm" variabletype="">receivedNumber</field>
</block>
<block type="radio_on_value" x="134" y="408">
<field name="HANDLER_name" id="*d-Jm^MJXO]Djs(dTR*?" variabletype="">name</field>
<field name="HANDLER_value" id="A6HQjH[k^X43o3h775+G" variabletype="">value</field>
</block>
<block type="radio_on_string" x="165" y="583">
<field name="HANDLER_receivedString" id="V9KsE!h$(iO?%W:[32CV" variabletype="">receivedString</field>
</block>
*/
const varids: pxt.Map<string> = {};

function addField(node: Element, renameMap: pxt.Map<string>, name: string) {
Expand Down
Loading

0 comments on commit b4962a3

Please sign in to comment.