mirror of
https://github.com/google/blockly.git
synced 2026-01-07 00:50:27 +01:00
Reduce unneeded parentheses in JS and Python.
This commit is contained in:
@@ -77,6 +77,12 @@ Blockly.Generator.prototype.INDENT = ' ';
|
||||
*/
|
||||
Blockly.Generator.prototype.COMMENT_WRAP = 60;
|
||||
|
||||
/**
|
||||
* List of outer-inner pairings that do NOT require parentheses.
|
||||
* @type {!Array.<!Array.<number>>}
|
||||
*/
|
||||
Blockly.Generator.prototype.ORDER_OVERRIDES = [];
|
||||
|
||||
/**
|
||||
* Generate code for all blocks in the workspace to the specified language.
|
||||
* @param {Blockly.Workspace} workspace Workspace to generate code from.
|
||||
@@ -198,13 +204,13 @@ Blockly.Generator.prototype.blockToCode = function(block) {
|
||||
* Generate code representing the specified value input.
|
||||
* @param {!Blockly.Block} block The block containing the input.
|
||||
* @param {string} name The name of the input.
|
||||
* @param {number} order The maximum binding strength (minimum order value)
|
||||
* @param {number} outerOrder The maximum binding strength (minimum order value)
|
||||
* of any operators adjacent to "block".
|
||||
* @return {string} Generated code or '' if no blocks are connected or the
|
||||
* specified input does not exist.
|
||||
*/
|
||||
Blockly.Generator.prototype.valueToCode = function(block, name, order) {
|
||||
if (isNaN(order)) {
|
||||
Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) {
|
||||
if (isNaN(outerOrder)) {
|
||||
goog.asserts.fail('Expecting valid order from block "%s".', block.type);
|
||||
}
|
||||
var targetBlock = block.getInputTargetBlock(name);
|
||||
@@ -226,8 +232,17 @@ Blockly.Generator.prototype.valueToCode = function(block, name, order) {
|
||||
goog.asserts.fail('Expecting valid order from value block "%s".',
|
||||
targetBlock.type);
|
||||
}
|
||||
if (code && order <= innerOrder) {
|
||||
if (order == innerOrder && (order == 0 || order == 99)) {
|
||||
if (!code) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Add parentheses if needed.
|
||||
var parensNeeded = false;
|
||||
var outerOrderClass = Math.floor(outerOrder);
|
||||
var innerOrderClass = Math.floor(innerOrder);
|
||||
if (outerOrderClass <= innerOrderClass) {
|
||||
if (outerOrderClass == innerOrderClass &&
|
||||
(outerOrderClass == 0 || outerOrderClass == 99)) {
|
||||
// Don't generate parens around NONE-NONE and ATOMIC-ATOMIC pairs.
|
||||
// 0 is the atomic order, 99 is the none order. No parentheses needed.
|
||||
// In all known languages multiple such code blocks are not order
|
||||
@@ -236,11 +251,22 @@ Blockly.Generator.prototype.valueToCode = function(block, name, order) {
|
||||
// The operators outside this code are stonger than the operators
|
||||
// inside this code. To prevent the code from being pulled apart,
|
||||
// wrap the code in parentheses.
|
||||
// Technically, this should be handled on a language-by-language basis.
|
||||
// However all known (sane) languages use parentheses for grouping.
|
||||
code = '(' + code + ')';
|
||||
parensNeeded = true;
|
||||
// Check for special exceptions.
|
||||
for (var i = 0; i < this.ORDER_OVERRIDES.length; i++) {
|
||||
if (this.ORDER_OVERRIDES[i][0] == outerOrder &&
|
||||
this.ORDER_OVERRIDES[i][1] == innerOrder) {
|
||||
parensNeeded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parensNeeded) {
|
||||
// Technically, this should be handled on a language-by-language basis.
|
||||
// However all known (sane) languages use parentheses for grouping.
|
||||
code = '(' + code + ')';
|
||||
}
|
||||
return code;
|
||||
};
|
||||
|
||||
|
||||
@@ -90,12 +90,8 @@ Blockly.Dart['lists_getIndex'] = function(block) {
|
||||
var where = block.getFieldValue('WHERE') || 'FROM_START';
|
||||
var at = Blockly.Dart.valueToCode(block, 'AT',
|
||||
Blockly.Dart.ORDER_UNARY_PREFIX) || '1';
|
||||
// Special case to avoid wrapping function calls in unneeded parenthesis.
|
||||
// func()[0] is prefered over (func())[0]
|
||||
var valueBlock = this.getInputTargetBlock('VALUE');
|
||||
var order = (valueBlock && valueBlock.type == 'procedures_callreturn') ?
|
||||
Blockly.Dart.ORDER_NONE : Blockly.Dart.ORDER_UNARY_POSTFIX;
|
||||
var list = Blockly.Dart.valueToCode(block, 'VALUE', order) || '[]';
|
||||
var list = Blockly.Dart.valueToCode(block, 'VALUE',
|
||||
Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';
|
||||
|
||||
if (where == 'FIRST') {
|
||||
if (mode == 'GET') {
|
||||
|
||||
@@ -70,38 +70,61 @@ Blockly.JavaScript.addReservedWords(
|
||||
* Order of operation ENUMs.
|
||||
* https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence
|
||||
*/
|
||||
Blockly.JavaScript.ORDER_ATOMIC = 0; // 0 "" ...
|
||||
Blockly.JavaScript.ORDER_MEMBER = 1; // . []
|
||||
Blockly.JavaScript.ORDER_NEW = 1; // new
|
||||
Blockly.JavaScript.ORDER_FUNCTION_CALL = 2; // ()
|
||||
Blockly.JavaScript.ORDER_INCREMENT = 3; // ++
|
||||
Blockly.JavaScript.ORDER_DECREMENT = 3; // --
|
||||
Blockly.JavaScript.ORDER_LOGICAL_NOT = 4; // !
|
||||
Blockly.JavaScript.ORDER_BITWISE_NOT = 4; // ~
|
||||
Blockly.JavaScript.ORDER_UNARY_PLUS = 4; // +
|
||||
Blockly.JavaScript.ORDER_UNARY_NEGATION = 4; // -
|
||||
Blockly.JavaScript.ORDER_TYPEOF = 4; // typeof
|
||||
Blockly.JavaScript.ORDER_VOID = 4; // void
|
||||
Blockly.JavaScript.ORDER_DELETE = 4; // delete
|
||||
Blockly.JavaScript.ORDER_MULTIPLICATION = 5; // *
|
||||
Blockly.JavaScript.ORDER_DIVISION = 5; // /
|
||||
Blockly.JavaScript.ORDER_MODULUS = 5; // %
|
||||
Blockly.JavaScript.ORDER_ADDITION = 6; // +
|
||||
Blockly.JavaScript.ORDER_SUBTRACTION = 6; // -
|
||||
Blockly.JavaScript.ORDER_BITWISE_SHIFT = 7; // << >> >>>
|
||||
Blockly.JavaScript.ORDER_RELATIONAL = 8; // < <= > >=
|
||||
Blockly.JavaScript.ORDER_IN = 8; // in
|
||||
Blockly.JavaScript.ORDER_INSTANCEOF = 8; // instanceof
|
||||
Blockly.JavaScript.ORDER_EQUALITY = 9; // == != === !==
|
||||
Blockly.JavaScript.ORDER_BITWISE_AND = 10; // &
|
||||
Blockly.JavaScript.ORDER_BITWISE_XOR = 11; // ^
|
||||
Blockly.JavaScript.ORDER_BITWISE_OR = 12; // |
|
||||
Blockly.JavaScript.ORDER_LOGICAL_AND = 13; // &&
|
||||
Blockly.JavaScript.ORDER_LOGICAL_OR = 14; // ||
|
||||
Blockly.JavaScript.ORDER_CONDITIONAL = 15; // ?:
|
||||
Blockly.JavaScript.ORDER_ASSIGNMENT = 16; // = += -= *= /= %= <<= >>= ...
|
||||
Blockly.JavaScript.ORDER_COMMA = 17; // ,
|
||||
Blockly.JavaScript.ORDER_NONE = 99; // (...)
|
||||
Blockly.JavaScript.ORDER_ATOMIC = 0; // 0 "" ...
|
||||
Blockly.JavaScript.ORDER_MEMBER = 1.1; // . []
|
||||
Blockly.JavaScript.ORDER_NEW = 1.2; // new
|
||||
Blockly.JavaScript.ORDER_FUNCTION_CALL = 2; // ()
|
||||
Blockly.JavaScript.ORDER_INCREMENT = 3; // ++
|
||||
Blockly.JavaScript.ORDER_DECREMENT = 3; // --
|
||||
Blockly.JavaScript.ORDER_LOGICAL_NOT = 4.1; // !
|
||||
Blockly.JavaScript.ORDER_BITWISE_NOT = 4.2; // ~
|
||||
Blockly.JavaScript.ORDER_UNARY_PLUS = 4.3; // +
|
||||
Blockly.JavaScript.ORDER_UNARY_NEGATION = 4.4; // -
|
||||
Blockly.JavaScript.ORDER_TYPEOF = 4.5; // typeof
|
||||
Blockly.JavaScript.ORDER_VOID = 4.6; // void
|
||||
Blockly.JavaScript.ORDER_DELETE = 4.7; // delete
|
||||
Blockly.JavaScript.ORDER_MULTIPLICATION = 5.1; // *
|
||||
Blockly.JavaScript.ORDER_DIVISION = 5.2; // /
|
||||
Blockly.JavaScript.ORDER_MODULUS = 5.3; // %
|
||||
Blockly.JavaScript.ORDER_ADDITION = 6.1; // +
|
||||
Blockly.JavaScript.ORDER_SUBTRACTION = 6.2; // -
|
||||
Blockly.JavaScript.ORDER_BITWISE_SHIFT = 7; // << >> >>>
|
||||
Blockly.JavaScript.ORDER_RELATIONAL = 8; // < <= > >=
|
||||
Blockly.JavaScript.ORDER_IN = 8; // in
|
||||
Blockly.JavaScript.ORDER_INSTANCEOF = 8; // instanceof
|
||||
Blockly.JavaScript.ORDER_EQUALITY = 9; // == != === !==
|
||||
Blockly.JavaScript.ORDER_BITWISE_AND = 10; // &
|
||||
Blockly.JavaScript.ORDER_BITWISE_XOR = 11; // ^
|
||||
Blockly.JavaScript.ORDER_BITWISE_OR = 12; // |
|
||||
Blockly.JavaScript.ORDER_LOGICAL_AND = 13; // &&
|
||||
Blockly.JavaScript.ORDER_LOGICAL_OR = 14; // ||
|
||||
Blockly.JavaScript.ORDER_CONDITIONAL = 15; // ?:
|
||||
Blockly.JavaScript.ORDER_ASSIGNMENT = 16; // = += -= *= /= %= <<= >>= ...
|
||||
Blockly.JavaScript.ORDER_COMMA = 17; // ,
|
||||
Blockly.JavaScript.ORDER_NONE = 99; // (...)
|
||||
|
||||
/**
|
||||
* List of outer-inner pairings that do NOT require parentheses.
|
||||
* @type {!Array.<!Array.<number>>}
|
||||
*/
|
||||
Blockly.JavaScript.ORDER_OVERRIDES = [
|
||||
// (foo()).bar() -> foo().bar()
|
||||
// (foo())[0] -> foo()[0]
|
||||
[Blockly.JavaScript.ORDER_FUNCTION_CALL, Blockly.JavaScript.ORDER_MEMBER],
|
||||
// (foo[0])[1] -> foo[0][1]
|
||||
// (foo.bar).baz -> foo.bar.baz
|
||||
[Blockly.JavaScript.ORDER_MEMBER, Blockly.JavaScript.ORDER_MEMBER],
|
||||
// !(!foo) -> !!foo
|
||||
[Blockly.JavaScript.ORDER_LOGICAL_NOT, Blockly.JavaScript.ORDER_LOGICAL_NOT],
|
||||
// a * (b * c) -> a * b * c
|
||||
[Blockly.JavaScript.ORDER_MULTIPLICATION, Blockly.JavaScript.ORDER_MULTIPLICATION],
|
||||
// a + (b + c) -> a + b + c
|
||||
[Blockly.JavaScript.ORDER_ADDITION, Blockly.JavaScript.ORDER_ADDITION],
|
||||
// a && (b && c) -> a && b && c
|
||||
[Blockly.JavaScript.ORDER_LOGICAL_AND, Blockly.JavaScript.ORDER_LOGICAL_AND],
|
||||
// a || (b || c) -> a || b || c
|
||||
[Blockly.JavaScript.ORDER_LOGICAL_OR, Blockly.JavaScript.ORDER_LOGICAL_OR]
|
||||
];
|
||||
|
||||
/**
|
||||
* Allow for switching between one and zero based indexing, one based by
|
||||
|
||||
@@ -98,12 +98,8 @@ Blockly.JavaScript['lists_getIndex'] = function(block) {
|
||||
var where = block.getFieldValue('WHERE') || 'FROM_START';
|
||||
var at = Blockly.JavaScript.valueToCode(block, 'AT',
|
||||
Blockly.JavaScript.ORDER_UNARY_NEGATION) || '1';
|
||||
// Special case to avoid wrapping function calls in unneeded parenthesis.
|
||||
// func()[0] is prefered over (func())[0]
|
||||
var valueBlock = this.getInputTargetBlock('VALUE');
|
||||
var order = (valueBlock && valueBlock.type == 'procedures_callreturn') ?
|
||||
Blockly.JavaScript.ORDER_NONE : Blockly.JavaScript.ORDER_MEMBER;
|
||||
var list = Blockly.JavaScript.valueToCode(block, 'VALUE', order) || '[]';
|
||||
var list = Blockly.JavaScript.valueToCode(block, 'VALUE',
|
||||
Blockly.JavaScript.ORDER_MEMBER) || '[]';
|
||||
|
||||
if (where == 'FIRST') {
|
||||
if (mode == 'GET') {
|
||||
|
||||
@@ -160,11 +160,7 @@ Blockly.Lua['lists_getIndex'] = function(block) {
|
||||
var at = Blockly.Lua.valueToCode(block, 'AT',
|
||||
Blockly.Lua.ORDER_ADDITIVE) || '1';
|
||||
if (mode == 'GET') {
|
||||
// Special case to avoid wrapping function calls in unneeded parenthesis.
|
||||
// func()[0] is prefered over (func())[0]
|
||||
var valueBlock = this.getInputTargetBlock('VALUE');
|
||||
var order = (valueBlock && valueBlock.type == 'procedures_callreturn') ?
|
||||
Blockly.Lua.ORDER_NONE : Blockly.Lua.ORDER_HIGH;
|
||||
var order = Blockly.Lua.ORDER_HIGH;
|
||||
} else {
|
||||
// List will be an argument in a function call.
|
||||
var order = Blockly.Lua.ORDER_NONE;
|
||||
|
||||
@@ -133,11 +133,7 @@ Blockly.PHP['lists_getIndex'] = function(block) {
|
||||
var at = Blockly.PHP.valueToCode(block, 'AT',
|
||||
Blockly.PHP.ORDER_UNARY_NEGATION) || '1';
|
||||
if (mode == 'GET') {
|
||||
// Special case to avoid wrapping function calls in unneeded parenthesis.
|
||||
// func()[0] is prefered over (func())[0]
|
||||
var valueBlock = this.getInputTargetBlock('VALUE');
|
||||
var order = (valueBlock && valueBlock.type == 'procedures_callreturn') ?
|
||||
Blockly.PHP.ORDER_NONE : Blockly.PHP.ORDER_FUNCTION_CALL;
|
||||
var order = Blockly.PHP.ORDER_FUNCTION_CALL;
|
||||
} else {
|
||||
// List will be an argument in a function call.
|
||||
var order = Blockly.PHP.ORDER_COMMA;
|
||||
|
||||
@@ -79,6 +79,16 @@ Blockly.Python.ORDER_CONDITIONAL = 15; // if else
|
||||
Blockly.Python.ORDER_LAMBDA = 16; // lambda
|
||||
Blockly.Python.ORDER_NONE = 99; // (...)
|
||||
|
||||
/**
|
||||
* List of outer-inner pairings that do NOT require parentheses.
|
||||
* @type {!Array.<!Array.<number>>}
|
||||
*/
|
||||
Blockly.Python.ORDER_OVERRIDES = [
|
||||
// (foo()).bar() -> foo().bar()
|
||||
// (foo())[0] -> foo()[0]
|
||||
[Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_MEMBER]
|
||||
];
|
||||
|
||||
/**
|
||||
* Initialise the database of variable names.
|
||||
* @param {!Blockly.Workspace} workspace Workspace to generate code from.
|
||||
|
||||
@@ -105,12 +105,8 @@ Blockly.Python['lists_getIndex'] = function(block) {
|
||||
var where = block.getFieldValue('WHERE') || 'FROM_START';
|
||||
var at = Blockly.Python.valueToCode(block, 'AT',
|
||||
Blockly.Python.ORDER_UNARY_SIGN) || '1';
|
||||
// Special case to avoid wrapping function calls in unneeded parenthesis.
|
||||
// func()[0] is prefered over (func())[0]
|
||||
var valueBlock = this.getInputTargetBlock('VALUE');
|
||||
var order = (valueBlock && valueBlock.type == 'procedures_callreturn') ?
|
||||
Blockly.Python.ORDER_NONE : Blockly.Python.ORDER_MEMBER;
|
||||
var list = Blockly.Python.valueToCode(block, 'VALUE', order) || '[]';
|
||||
var list = Blockly.Python.valueToCode(block, 'VALUE',
|
||||
Blockly.Python.ORDER_MEMBER) || '[]';
|
||||
|
||||
if (where == 'FIRST') {
|
||||
if (mode == 'GET') {
|
||||
|
||||
Reference in New Issue
Block a user