Loading lib/jsduck/serializer.rb +86 −10 Original line number Diff line number Diff line Loading @@ -97,31 +97,31 @@ module JsDuck # Expressions when "AssignmentExpression" to_s(ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) parens(ast, ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) when "ArrayExpression" "[" + list(ast["elements"]) + "]" when "BinaryExpression" to_s(ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) binary(ast) when "CallExpression" call(ast) when "ConditionalExpression" to_s(ast["test"]) + " ? " + to_s(ast["consequent"]) + " : " + to_s(ast["alternate"]) parens(ast, ast["test"]) + " ? " + to_s(ast["consequent"]) + " : " + to_s(ast["alternate"]) when "FunctionExpression" function(ast) when "LogicalExpression" to_s(ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) binary(ast) when "MemberExpression" if ast["computed"] to_s(ast["object"]) + "[" + to_s(ast["property"]) + "]" parens(ast, ast["object"]) + "[" + to_s(ast["property"]) + "]" else to_s(ast["object"]) + "." + to_s(ast["property"]) parens(ast, ast["object"]) + "." + to_s(ast["property"]) end when "NewExpression" Loading @@ -140,13 +140,13 @@ module JsDuck "this" when "UnaryExpression" ast["operator"] + to_s(ast["argument"]) ast["operator"] + parens(ast, ast["argument"]) when "UpdateExpression" if ast["prefix"] ast["operator"] + to_s(ast["argument"]) ast["operator"] + parens(ast, ast["argument"]) else to_s(ast["argument"]) + ast["operator"] parens(ast, ast["argument"]) + ast["operator"] end # Basics Loading @@ -162,6 +162,8 @@ module JsDuck end end private # serializes function declaration or expression def function(ast) params = list(ast["params"]) Loading @@ -176,8 +178,82 @@ module JsDuck # serializes call- and new-expression def call(ast) to_s(ast["callee"]) + "(" + list(ast["arguments"]) + ")" parens(ast, ast["callee"]) + "(" + list(ast["arguments"]) + ")" end # Handles both binary- and logical-expression def binary(ast) parens(ast, ast["left"]) + " " + ast["operator"] + " " + parens(ast, ast["right"]) end # serializes child node and wraps it inside parenthesis if the # precedence rules compared to parent node would require so. def parens(parent, child) if precedence(parent) >= precedence(child) to_s(child) else "(" + to_s(child) + ")" end end # Returns the precedence of operator represented by given AST node def precedence(ast) p = PRECEDENCE[ast["type"]] if p.is_a? Fixnum p elsif p.is_a? Hash p[ast["operator"]] else 0 end end # Precedence rules of JavaScript operators. # # Taken from: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence # PRECEDENCE = { "SequenceExpression" => 17, "AssignmentExpression" => 16, "ConditionalExpression" => 15, "LogicalExpression" => { "||" => 14, "&&" => 13, }, "BinaryExpression" => { "|" => 12, "^" => 11, "&" => 10, "==" => 9, "!=" => 9, "===" => 9, "!==" => 9, "<" => 8, "<=" => 8, ">" => 8, ">=" => 8, "in" => 8, "instanceof" => 8, "<<" => 7, ">>" => 7, ">>>" => 7, "+" => 6, "-" => 6, "*" => 5, "/" => 5, "%" => 5, }, "UnaryExpression" => 4, "UpdateExpression" => 3, "CallExpression" => 2, "MemberExpression" => 1, "NewExpression" => 1, } end Loading spec/serializer_spec.rb +37 −0 Original line number Diff line number Diff line Loading @@ -131,7 +131,44 @@ describe JsDuck::Serializer do it "with statement" do test("with (obj) {}") end end describe "adds parenthesis correctly on" do it "assignment expression" do test("(foo, bar) = [1, 2];") end it "conditional expression" do test("(foo = true) ? 1 : 2;") end it "binary expression" do test("3 * (5 + 1);") end it "logical expression" do test("foo && (bar || baz);") end it "unary expression" do test("!(bar || baz);") end it "update expression" do test("++(5 + 5);") end it "call expression" do test("(foo || bar)();") end it "member expression" do test("(foo || bar).baz;") end it "new expression" do test("new (Foo || Bar)();") end end end Loading
lib/jsduck/serializer.rb +86 −10 Original line number Diff line number Diff line Loading @@ -97,31 +97,31 @@ module JsDuck # Expressions when "AssignmentExpression" to_s(ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) parens(ast, ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) when "ArrayExpression" "[" + list(ast["elements"]) + "]" when "BinaryExpression" to_s(ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) binary(ast) when "CallExpression" call(ast) when "ConditionalExpression" to_s(ast["test"]) + " ? " + to_s(ast["consequent"]) + " : " + to_s(ast["alternate"]) parens(ast, ast["test"]) + " ? " + to_s(ast["consequent"]) + " : " + to_s(ast["alternate"]) when "FunctionExpression" function(ast) when "LogicalExpression" to_s(ast["left"]) + " " + ast["operator"] + " " + to_s(ast["right"]) binary(ast) when "MemberExpression" if ast["computed"] to_s(ast["object"]) + "[" + to_s(ast["property"]) + "]" parens(ast, ast["object"]) + "[" + to_s(ast["property"]) + "]" else to_s(ast["object"]) + "." + to_s(ast["property"]) parens(ast, ast["object"]) + "." + to_s(ast["property"]) end when "NewExpression" Loading @@ -140,13 +140,13 @@ module JsDuck "this" when "UnaryExpression" ast["operator"] + to_s(ast["argument"]) ast["operator"] + parens(ast, ast["argument"]) when "UpdateExpression" if ast["prefix"] ast["operator"] + to_s(ast["argument"]) ast["operator"] + parens(ast, ast["argument"]) else to_s(ast["argument"]) + ast["operator"] parens(ast, ast["argument"]) + ast["operator"] end # Basics Loading @@ -162,6 +162,8 @@ module JsDuck end end private # serializes function declaration or expression def function(ast) params = list(ast["params"]) Loading @@ -176,8 +178,82 @@ module JsDuck # serializes call- and new-expression def call(ast) to_s(ast["callee"]) + "(" + list(ast["arguments"]) + ")" parens(ast, ast["callee"]) + "(" + list(ast["arguments"]) + ")" end # Handles both binary- and logical-expression def binary(ast) parens(ast, ast["left"]) + " " + ast["operator"] + " " + parens(ast, ast["right"]) end # serializes child node and wraps it inside parenthesis if the # precedence rules compared to parent node would require so. def parens(parent, child) if precedence(parent) >= precedence(child) to_s(child) else "(" + to_s(child) + ")" end end # Returns the precedence of operator represented by given AST node def precedence(ast) p = PRECEDENCE[ast["type"]] if p.is_a? Fixnum p elsif p.is_a? Hash p[ast["operator"]] else 0 end end # Precedence rules of JavaScript operators. # # Taken from: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence # PRECEDENCE = { "SequenceExpression" => 17, "AssignmentExpression" => 16, "ConditionalExpression" => 15, "LogicalExpression" => { "||" => 14, "&&" => 13, }, "BinaryExpression" => { "|" => 12, "^" => 11, "&" => 10, "==" => 9, "!=" => 9, "===" => 9, "!==" => 9, "<" => 8, "<=" => 8, ">" => 8, ">=" => 8, "in" => 8, "instanceof" => 8, "<<" => 7, ">>" => 7, ">>>" => 7, "+" => 6, "-" => 6, "*" => 5, "/" => 5, "%" => 5, }, "UnaryExpression" => 4, "UpdateExpression" => 3, "CallExpression" => 2, "MemberExpression" => 1, "NewExpression" => 1, } end Loading
spec/serializer_spec.rb +37 −0 Original line number Diff line number Diff line Loading @@ -131,7 +131,44 @@ describe JsDuck::Serializer do it "with statement" do test("with (obj) {}") end end describe "adds parenthesis correctly on" do it "assignment expression" do test("(foo, bar) = [1, 2];") end it "conditional expression" do test("(foo = true) ? 1 : 2;") end it "binary expression" do test("3 * (5 + 1);") end it "logical expression" do test("foo && (bar || baz);") end it "unary expression" do test("!(bar || baz);") end it "update expression" do test("++(5 + 5);") end it "call expression" do test("(foo || bar)();") end it "member expression" do test("(foo || bar).baz;") end it "new expression" do test("new (Foo || Bar)();") end end end