Merge pull request #2133 from alschmiedt/single_code_block

Generate Code For Single Block
This commit is contained in:
alschmiedt
2018-11-27 13:38:20 -08:00
committed by GitHub
8 changed files with 185 additions and 15 deletions

View File

@@ -158,17 +158,18 @@ Blockly.Generator.prototype.allNestedComments = function(block) {
/**
* Generate code for the specified block (and attached blocks).
* @param {Blockly.Block} block The block to generate code for.
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
* @return {string|!Array} For statement blocks, the generated code.
* For value blocks, an array containing the generated code and an
* operator order value. Returns '' if block is null.
*/
Blockly.Generator.prototype.blockToCode = function(block) {
Blockly.Generator.prototype.blockToCode = function(block, opt_thisOnly) {
if (!block) {
return '';
}
if (block.disabled) {
// Skip past this block if it is disabled.
return this.blockToCode(block.getNextBlock());
return opt_thisOnly ? '' : this.blockToCode(block.getNextBlock());
}
var func = this[block.type];
@@ -186,13 +187,13 @@ Blockly.Generator.prototype.blockToCode = function(block) {
if (!block.outputConnection) {
throw TypeError('Expecting string from statement block: ' + block.type);
}
return [this.scrub_(block, code[0]), code[1]];
return [this.scrub_(block, code[0], opt_thisOnly), code[1]];
} else if (typeof code == 'string') {
var id = block.id.replace(/\$/g, '$$$$'); // Issue 251.
if (this.STATEMENT_PREFIX) {
code = this.STATEMENT_PREFIX.replace(/%1/g, '\'' + id + '\'') + code;
}
return this.scrub_(block, code);
return this.scrub_(block, code, opt_thisOnly);
} else if (code === null) {
// Block has handled code generation itself.
return '';

View File

@@ -188,10 +188,11 @@ Blockly.Dart.quote_ = function(string) {
* Calls any statements following this block.
* @param {!Blockly.Block} block The current block.
* @param {string} code The Dart code created for this block.
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
* @return {string} Dart code with comments and subsequent blocks added.
* @private
*/
Blockly.Dart.scrub_ = function(block, code) {
Blockly.Dart.scrub_ = function(block, code, opt_thisOnly) {
var commentCode = '';
// Only collect comments for blocks that aren't inline.
if (!block.outputConnection || !block.outputConnection.targetConnection) {
@@ -221,7 +222,7 @@ Blockly.Dart.scrub_ = function(block, code) {
}
}
var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
var nextCode = Blockly.Dart.blockToCode(nextBlock);
var nextCode = opt_thisOnly ? '' : Blockly.Dart.blockToCode(nextBlock);
return commentCode + code + nextCode;
};

View File

@@ -229,10 +229,11 @@ Blockly.JavaScript.quote_ = function(string) {
* Calls any statements following this block.
* @param {!Blockly.Block} block The current block.
* @param {string} code The JavaScript code created for this block.
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
* @return {string} JavaScript code with comments and subsequent blocks added.
* @private
*/
Blockly.JavaScript.scrub_ = function(block, code) {
Blockly.JavaScript.scrub_ = function(block, code, opt_thisOnly) {
var commentCode = '';
// Only collect comments for blocks that aren't inline.
if (!block.outputConnection || !block.outputConnection.targetConnection) {
@@ -264,7 +265,7 @@ Blockly.JavaScript.scrub_ = function(block, code) {
}
}
var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
var nextCode = Blockly.JavaScript.blockToCode(nextBlock);
var nextCode = opt_thisOnly ? '' : Blockly.JavaScript.blockToCode(nextBlock);
return commentCode + code + nextCode;
};

View File

@@ -162,10 +162,11 @@ Blockly.Lua.quote_ = function(string) {
* Calls any statements following this block.
* @param {!Blockly.Block} block The current block.
* @param {string} code The Lua code created for this block.
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
* @return {string} Lua code with comments and subsequent blocks added.
* @private
*/
Blockly.Lua.scrub_ = function(block, code) {
Blockly.Lua.scrub_ = function(block, code, opt_thisOnly) {
var commentCode = '';
// Only collect comments for blocks that aren't inline.
if (!block.outputConnection || !block.outputConnection.targetConnection) {
@@ -190,6 +191,6 @@ Blockly.Lua.scrub_ = function(block, code) {
}
}
var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
var nextCode = Blockly.Lua.blockToCode(nextBlock);
var nextCode = opt_thisOnly ? '' : Blockly.Lua.blockToCode(nextBlock);
return commentCode + code + nextCode;
};

View File

@@ -218,10 +218,11 @@ Blockly.PHP.quote_ = function(string) {
* Calls any statements following this block.
* @param {!Blockly.Block} block The current block.
* @param {string} code The PHP code created for this block.
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
* @return {string} PHP code with comments and subsequent blocks added.
* @private
*/
Blockly.PHP.scrub_ = function(block, code) {
Blockly.PHP.scrub_ = function(block, code, opt_thisOnly) {
var commentCode = '';
// Only collect comments for blocks that aren't inline.
if (!block.outputConnection || !block.outputConnection.targetConnection) {
@@ -246,7 +247,7 @@ Blockly.PHP.scrub_ = function(block, code) {
}
}
var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
var nextCode = Blockly.PHP.blockToCode(nextBlock);
var nextCode = opt_thisOnly ? '' : Blockly.PHP.blockToCode(nextBlock);
return commentCode + code + nextCode;
};

View File

@@ -244,10 +244,11 @@ Blockly.Python.quote_ = function(string) {
* Calls any statements following this block.
* @param {!Blockly.Block} block The current block.
* @param {string} code The Python code created for this block.
* @param {boolean=} opt_thisOnly True to generate code for only this statement.
* @return {string} Python code with comments and subsequent blocks added.
* @private
*/
Blockly.Python.scrub_ = function(block, code) {
Blockly.Python.scrub_ = function(block, code, opt_thisOnly) {
var commentCode = '';
// Only collect comments for blocks that aren't inline.
if (!block.outputConnection || !block.outputConnection.targetConnection) {
@@ -277,7 +278,7 @@ Blockly.Python.scrub_ = function(block, code) {
}
}
var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
var nextCode = Blockly.Python.blockToCode(nextBlock);
var nextCode = opt_thisOnly ? '' : Blockly.Python.blockToCode(nextBlock);
return commentCode + code + nextCode;
};

View File

@@ -19,10 +19,169 @@
*/
'use strict';
goog.require('Blockly.Dart');
goog.require('Blockly.JavaScript');
goog.require('Blockly.Lua');
goog.require('Blockly.PHP');
goog.require('Blockly.Python');
var workspace;
function defineGeneratorTestBlocks() {
Blockly.defineBlocksWithJsonArray([{
"type": "stack_block",
"message0": "",
"previousStatement": null,
"nextStatement": null
},
{
"type": "row_block",
"message0": "%1",
"args0": [
{
"type": "input_value",
"name": "INPUT"
}
],
"output": null,
"nextStatement": null
},
{
"type": "controls_repeat_ext",
"message0": "Repeat Loop",
"message1": "%1",
"args1": [{
"type": "input_statement",
"name": "DO"
}],
"previousStatement": null,
"nextStatement": null
}]);
}
function undefineGeneratorTestBlocks() {
delete Blockly.Blocks['stack_block'];
delete Blockly.Blocks['row_block'];
}
function generatorTest_setUp() {
defineGeneratorTestBlocks();
workspace = new Blockly.Workspace();
}
function generatorTest_tearDown() {
undefineGeneratorTestBlocks();
workspace.dispose();
}
function blockToCodeTestSetup(generator) {
var row_block = workspace.newBlock('row_block');
var stack_block = workspace.newBlock('stack_block');
generator.row_block = function(block){return 'row_block'};
generator.stack_block = function(block){return 'stack_block'};
row_block.nextConnection.connect(stack_block.previousConnection);
return row_block;
}
function blockToCodeTest(generator, opt_thisOnly) {
var row_block = blockToCodeTestSetup(generator);
return generator.blockToCode(row_block, opt_thisOnly);
}
function disabledBlockTest(generator, opt_thisOnly) {
var row_block = blockToCodeTestSetup(generator);
row_block.disabled=true;
return generator.blockToCode(row_block, opt_thisOnly);
}
function nestedLoopTest(generator, opt_thisOnly) {
Blockly.Msg['CONTROLS_REPEAT_TITLE'] = 'repeat %1 times';
var blockA = workspace.newBlock('controls_repeat_ext');
var blockB = workspace.newBlock('controls_repeat_ext');
var blockC = workspace.newBlock('controls_repeat_ext');
generator.controls_repeat_ext = getControlRepeatFunc(generator);
blockA.getInput('DO').connection.connect(blockB.previousConnection);
blockA.nextConnection.connect(blockC.previousConnection);
return generator.blockToCode(blockA, opt_thisOnly);
}
function getControlRepeatFunc(generator) {
return function(block){
return '{' + generator.statementToCode(block, 'DO') + '}';
};
}
function test_blockToCodeOnAllGeneartors() {
generatorTest_setUp();
assertEquals(blockToCodeTest(Blockly.Dart, true), 'row_block');
assertEquals(blockToCodeTest(Blockly.Dart, false), 'row_blockstack_block');
assertEquals(blockToCodeTest(Blockly.JavaScript, true), 'row_block');
assertEquals(blockToCodeTest(Blockly.JavaScript, false), 'row_blockstack_block');
assertEquals(blockToCodeTest(Blockly.Lua, true), 'row_block');
assertEquals(blockToCodeTest(Blockly.Lua, false), 'row_blockstack_block');
assertEquals(blockToCodeTest(Blockly.PHP, true), 'row_block');
assertEquals(blockToCodeTest(Blockly.PHP, false), 'row_blockstack_block');
assertEquals(blockToCodeTest(Blockly.Python, true), 'row_block');
assertEquals(blockToCodeTest(Blockly.Python, false), 'row_blockstack_block');
generatorTest_tearDown();
}
function test_disabledBlockToCode() {
generatorTest_setUp();
assertEquals(disabledBlockTest(Blockly.Dart, true), '');
assertEquals(disabledBlockTest(Blockly.Dart, false), 'stack_block');
assertEquals(disabledBlockTest(Blockly.JavaScript, true), '');
assertEquals(disabledBlockTest(Blockly.JavaScript, false), 'stack_block');
assertEquals(disabledBlockTest(Blockly.Lua, true), '');
assertEquals(disabledBlockTest(Blockly.Lua, false), 'stack_block');
assertEquals(disabledBlockTest(Blockly.PHP, true), '');
assertEquals(disabledBlockTest(Blockly.PHP, false), 'stack_block');
assertEquals(disabledBlockTest(Blockly.Python, true), '');
assertEquals(disabledBlockTest(Blockly.Python, false), 'stack_block');
generatorTest_tearDown();
}
// { {}} represents a nested block
//{ {}}{} represents a nested block with a block after it
function test_nestedLoopBlockToCode() {
generatorTest_setUp();
assertEquals(nestedLoopTest(Blockly.Dart, true), '{ {}}');
assertEquals(nestedLoopTest(Blockly.Dart, false), '{ {}}{}');
assertEquals(nestedLoopTest(Blockly.JavaScript, true), '{ {}}');
assertEquals(nestedLoopTest(Blockly.JavaScript, false), '{ {}}{}');
assertEquals(nestedLoopTest(Blockly.Lua, true), '{ {}}');
assertEquals(nestedLoopTest(Blockly.Lua, false), '{ {}}{}');
assertEquals(nestedLoopTest(Blockly.PHP, true), '{ {}}');
assertEquals(nestedLoopTest(Blockly.PHP, false), '{ {}}{}');
assertEquals(nestedLoopTest(Blockly.Python, true), '{ {}}');
assertEquals(nestedLoopTest(Blockly.Python, false), '{ {}}{}');
generatorTest_tearDown();
}
function test_prefix() {
var generator = new Blockly.Generator('INTERCAL');
assertEquals('Prefix nothing.', '', generator.prefixLines('', ''));
assertEquals('Prefix a word.', '@Hello', generator.prefixLines('Hello', '@'));
assertEquals('Prefix one line.', '12Hello\n', generator.prefixLines('Hello\n', '12'));
assertEquals('Prefix two lines.', '***Hello\n***World\n', generator.prefixLines('Hello\nWorld\n', '***'));
}
}

View File

@@ -4,6 +4,11 @@
<meta charset="utf-8">
<title>Unit Tests for Blockly</title>
<script src="../../blockly_uncompressed.js"></script>
<script src="../../generators/dart.js"></script>
<script src="../../generators/javascript.js"></script>
<script src="../../generators/lua.js"></script>
<script src="../../generators/php.js"></script>
<script src="../../generators/python.js"></script>
<script>goog.require('goog.testing.jsunit');</script>
</head>
<body>