Skip to content

Commit

Permalink
lazy task definition: take codeclimate into account
Browse files Browse the repository at this point in the history
  • Loading branch information
lionelperrin committed Feb 18, 2020
1 parent b550157 commit 2458477
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 99 deletions.
1 change: 1 addition & 0 deletions lib/rake.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ module Rake; end
require "rake/late_time"
require "rake/name_space"
require "rake/task_manager"
require "rake/lazy_task_definition"
require "rake/application"
require "rake/backtrace"

Expand Down
23 changes: 14 additions & 9 deletions lib/rake/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require "optparse"

require "rake/task_manager"
require "rake/lazy_task_definition"
require "rake/file_list"
require "rake/thread_pool"
require "rake/thread_history_display"
Expand All @@ -18,6 +19,7 @@ module Rake

class Application
include TaskManager
include LazyTaskDefinition
include TraceOutput

# The name of the application (typically 'rake')
Expand Down Expand Up @@ -107,17 +109,20 @@ def load_rakefile

# Run the top level tasks of a Rake application.
def top_level
run_with_threads do
execute_all_lazy_definitions if options.loadlazydefinitions
if options.show_tasks
display_tasks_and_comments
elsif options.show_prereqs
display_prerequisites
else
top_level_tasks.each { |task_name| invoke_task(task_name) }
end
run_with_threads { top_level_intern }
end

def top_level_intern
execute_all_lazy_definitions if options.loadlazydefinitions
if options.show_tasks
display_tasks_and_comments
elsif options.show_prereqs
display_prerequisites
else
top_level_tasks.each { |task_name| invoke_task(task_name) }
end
end
private :top_level_intern

# Run the given block with the thread startup and shutdown.
def run_with_threads
Expand Down
53 changes: 53 additions & 0 deletions lib/rake/lazy_task_definition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true
module Rake

# The LazyTaskDefinition module is a mixin for managing lazy defined tasks.
module LazyTaskDefinition

# Execute all definitions: usefull for rake -T for instance
def execute_all_lazy_definitions
lazy_definitions.each do |scope_path, _definitions|
execute_lazy_definitions(scope_path)
end
end

# Execute all definitions linked to specified +scope_path+
# and its parent scopes.
def execute_lazy_definitions(scope_path)
scope_path_elements = scope_path.split(':')
sub_scope_elements = []
scope_path_elements.each do |e|
sub_scope_elements << e
sub_scope_path = sub_scope_elements.join(':')
definitions = lazy_definitions[sub_scope_path]
next unless definitions
definitions.each do |definition|
definition.call
end
definitions.clear
end
end

# Evaluate the block in specified +scope+.
def in_scope(scope)
cur_scope = @scope
@scope = scope
yield
ensure
@scope = cur_scope
end

# Register a block which will be called only when necessary during the lookup
# of tasks
def register_lazy_definition(&block)
cur_scope = @scope
lazy_definitions[cur_scope.path] ||= []
lazy_definitions[cur_scope.path] << ->() { in_scope(cur_scope, &block) }
end

def lazy_definitions
@lazy_definitions ||= {}
end
private :lazy_definitions
end
end
45 changes: 2 additions & 43 deletions lib/rake/task_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def initialize # :nodoc:
@rules = Array.new
@scope = Scope.make
@last_description = nil
@lazy_definitions = {}
end

def create_rule(*args, &block) # :nodoc:
Expand Down Expand Up @@ -209,7 +208,8 @@ def lookup(task_name, initial_scope=nil)
def lookup_in_scope(name, scope)
loop do
tn = scope.path_with_task_name(name)
execute_lazy_definitions(tn.rpartition(':')[0])
# use lazy definitions if mixin LazyTaskDefinition is enabled
execute_lazy_definitions(tn) if respond_to?(:execute_lazy_definitions)
task = @tasks[tn]
return task if task
break if scope.empty?
Expand Down Expand Up @@ -237,47 +237,6 @@ def in_namespace(name)
@scope = @scope.tail
end

# Execute all definitions: usefull for rake -T for instance
def execute_all_lazy_definitions
@lazy_definitions.each do |scope_path, _definitions|
execute_lazy_definitions(scope_path)
end
end

# Execute all definitions linked to specified +scope_path+
# and its parent scopes.
def execute_lazy_definitions(scope_path)
scope_path_elements = scope_path.split(':')
sub_scope_elements = []
scope_path_elements.each do |e|
sub_scope_elements << e
sub_scope_path = sub_scope_elements.join(':')
definitions = @lazy_definitions[sub_scope_path]
next unless definitions
definitions.each do |definition|
definition.call
end
definitions.clear
end
end

# Evaluate the block in specified +scope+.
def in_scope(scope)
cur_scope = @scope
@scope = scope
yield
ensure
@scope = cur_scope
end

# Register a block which will be called only when necessary during the lookup
# of tasks
def register_lazy_definition(&block)
cur_scope = @scope
@lazy_definitions[cur_scope.path] ||= []
@lazy_definitions[cur_scope.path] << ->() { in_scope(cur_scope, &block) }
end

private

# Add a location to the locations field of the given task.
Expand Down
60 changes: 60 additions & 0 deletions test/test_rake_lazy_task_definition.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true
require File.expand_path("../helper", __FILE__)

class TestRakeLazyTaskDefinition < Rake::TestCase # :nodoc:

def setup
super

@tm = Rake::TestCase::TaskManager.new
@tm.extend Rake::LazyTaskDefinition
end

def test_lazy_definition
t1, t2, t3 = nil, nil, nil
lazy_definition_call_count = 0
@tm.in_namespace("a1") do
@tm.register_lazy_definition do
t1 = @tm.define_task(Rake::Task, :t1)
lazy_definition_call_count += 1
@tm.in_namespace("a2") do
t2 = @tm.define_task(Rake::Task, :t2)
end
end
end
@tm.in_namespace("b") do
t3 = @tm.define_task(Rake::Task, :t3)
end
# task t3 is not lazy. It can be found
assert_equal t3, @tm[:t3, Rake::Scope.make("b")]
# lazy definition is not called until we look for task in namespace a
assert_equal lazy_definition_call_count, 0

# task t2 can be found
found_task_t2 = @tm[:t2, Rake::Scope.make("a1:a2")]
assert_equal t2, found_task_t2
# lazy definition is expected to be called
assert_equal lazy_definition_call_count, 1

# task t1 can also be found
found_task_t1 = @tm[:t1, Rake::Scope.make("a1")]
assert_equal t1, found_task_t1
# lazy definition is called at most once
assert_equal lazy_definition_call_count, 1
end

def test_execute_all_lazy_definitions
lazy_definition_call_count = 0
@tm.in_namespace("a") do
@tm.register_lazy_definition do
lazy_definition_call_count += 1
end
end
assert_equal lazy_definition_call_count, 0
@tm.execute_all_lazy_definitions
assert_equal lazy_definition_call_count, 1
@tm.execute_all_lazy_definitions
assert_equal lazy_definition_call_count, 1
end

end
47 changes: 0 additions & 47 deletions test/test_rake_task_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -186,51 +186,4 @@ def test_correctly_scoped_prerequisites_are_invoked
assert_equal ["next z"], values
end

def test_lazy_definition
t1, t2, t3 = nil, nil, nil
lazy_definition_call_count = 0
@tm.in_namespace("a1") do
@tm.register_lazy_definition do
t1 = @tm.define_task(Rake::Task, :t1)
lazy_definition_call_count += 1
@tm.in_namespace("a2") do
t2 = @tm.define_task(Rake::Task, :t2)
end
end
end
@tm.in_namespace("b") do
t3 = @tm.define_task(Rake::Task, :t3)
end
# task t3 is not lazy. It can be found
assert_equal t3, @tm[:t3, Rake::Scope.make("b")]
# lazy definition is not called until we look for task in namespace a
assert_equal lazy_definition_call_count, 0

# task t2 can be found
found_task_t2 = @tm[:t2, Rake::Scope.make("a1:a2")]
assert_equal t2, found_task_t2
# lazy definition is expected to be called
assert_equal lazy_definition_call_count, 1

# task t1 can also be found
found_task_t1 = @tm[:t1, Rake::Scope.make("a1")]
assert_equal t1, found_task_t1
# lazy definition is called at most once
assert_equal lazy_definition_call_count, 1
end

def test_execute_all_lazy_definitions
lazy_definition_call_count = 0
@tm.in_namespace("a") do
@tm.register_lazy_definition do
lazy_definition_call_count += 1
end
end
assert_equal lazy_definition_call_count, 0
@tm.execute_all_lazy_definitions
assert_equal lazy_definition_call_count, 1
@tm.execute_all_lazy_definitions
assert_equal lazy_definition_call_count, 1
end

end

0 comments on commit 2458477

Please sign in to comment.