Skip to content
Snippets Groups Projects
Commit cab57d1f authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Replace FunctionAst#returns with #chainable?

As we're only detecting 'return this;' using a predicate is better
than a function returning 'this' or nil.

FunctionAst is now also a singleton, but that fact is hidden away behind
static #chainable? method.
parent 31bf26a2
Branches
Tags
No related merge requests found
......@@ -407,7 +407,7 @@ module JsDuck
end
def chainable?(ast)
FunctionAst.new.returns(ast) == "this"
FunctionAst.chainable?(ast)
end
def make_property(name=nil, ast=nil, tagname=:property)
......
require "singleton"
require "jsduck/serializer"
require "jsduck/evaluator"
......@@ -5,12 +6,21 @@ module JsDuck
# Analyzes the AST of a FunctionDeclaration or FunctionExpression.
class FunctionAst
# Detects from function body what the function returns.
def returns(ast)
include Singleton
# True when function always finishes by returning this. False
# doesn't neccessarily mean that the function doesn't return this
# - rather it means our static analyzes wasn't able to determine
# what the function returns.
def self.chainable?(ast)
FunctionAst.instance.chainable?(ast)
end
def chainable?(ast)
if ast && function?(ast)
body_returns(ast["body"]["body"])
else
nil
false
end
end
......@@ -23,11 +33,7 @@ module JsDuck
def body_returns(body)
body = skip_non_control_flow_statements(body)
if body.length > 0 && return_this?(body[0])
"this"
else
nil
end
return body.length > 0 && return_this?(body[0])
end
def return_this?(ast)
......
......@@ -2,29 +2,29 @@ require "jsduck/js_parser"
require "jsduck/function_ast"
describe "JsDuck::FunctionAst#returns" do
def returns(string)
def chainable?(string)
node = JsDuck::JsParser.new(string).parse[0]
return JsDuck::FunctionAst.new.returns(node[:code])
return JsDuck::FunctionAst.chainable?(node[:code])
end
it "fails when no AST given at all" do
returns("/** */").should == nil
chainable?("/** */").should == false
end
it "fails when no function AST given" do
returns("/** */ Ext.emptyFn;").should == nil
chainable?("/** */ Ext.emptyFn;").should == false
end
it "fails when body has no return statement." do
returns("/** */ function foo() {}").should == nil
chainable?("/** */ function foo() {}").should == false
end
it "returns this when single return this statement in body" do
returns("/** */ function foo() {return this;}").should == "this"
chainable?("/** */ function foo() {return this;}").should == true
end
it "returns this when return this after a few expression statements" do
returns(<<-EOJS).should == "this"
chainable?(<<-EOJS).should == true
/** */
function foo() {
doSomething();
......@@ -36,7 +36,7 @@ describe "JsDuck::FunctionAst#returns" do
end
it "returns this when return this after a few declarations" do
returns(<<-EOJS).should == "this"
chainable?(<<-EOJS).should == true
/** */
function foo() {
var x = 10;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment