diff --git a/lib/rake/task_manager.rb b/lib/rake/task_manager.rb index c1e60b95e..7f9d76411 100644 --- a/lib/rake/task_manager.rb +++ b/lib/rake/task_manager.rb @@ -275,6 +275,8 @@ def attempt_rule(task_name, task_pattern, args, extensions, block, level) return nil end } + match_data = task_pattern.match(task_name) + block.binding.eval("proc { |match_data| $~ = match_data }").call(match_data) task = FileTask.define_task(task_name, { args => prereqs }, &block) task.sources = prereqs task @@ -288,13 +290,23 @@ def make_sources(task_name, task_pattern, extensions) when /%/ task_name.pathmap(ext) when %r{/} - ext + task_pattern.match(task_name) + pre_match = Regexp.new("^" + Regexp.quote(Regexp.last_match.pre_match)) + post_match = Regexp.new(Regexp.quote(Regexp.last_match.post_match) + "$") + task_name.sub(task_pattern, ext).sub(pre_match, "").sub(post_match, "") when /^\./ source = task_name.sub(task_pattern, ext) source == ext ? task_name.ext(ext) : source when String - ext + task_pattern.match(task_name) + pre_match = Regexp.new("^" + Regexp.quote(Regexp.last_match.pre_match)) + post_match = Regexp.new(Regexp.quote(Regexp.last_match.post_match) + "$") + task_name.sub(task_pattern, ext).sub(pre_match, "").sub(post_match, "") when Proc, Method + if ext.is_a?(Proc) + match_data = task_pattern.match(task_name) + ext.binding.eval("proc { |match_data| $~ = match_data }").call(match_data) + end if ext.arity == 1 ext.call(task_name) else diff --git a/test/test_rake_rules.rb b/test/test_rake_rules.rb index 52934c258..e310c3c76 100644 --- a/test/test_rake_rules.rb +++ b/test/test_rake_rules.rb @@ -409,4 +409,93 @@ def test_works_with_chained_extensions_in_rules assert_equal [MINFILE], @runs end + def test_regex_rule_with_proc_dependent_with_capture + mkdir_p("src/jw") + create_file("src/jw/X.java") + rule %r(classes/(.*)\.class) => [ + proc { "src/#{$1}.java" } + ] do |task| + assert_equal task.name, "classes/jw/X.class" + assert_equal task.source, "src/jw/X.java" + assert_equal $1, "jw/X" + @runs << :RULE + end + Task["classes/jw/X.class"].invoke + assert_equal [:RULE], @runs + end + + def test_regex_rule_with_capture_in_action + create_file("icon.svg") + rule %r(-(\d+)x(\d+)\.png$) => [ + ".svg" + ] do |task| + assert_equal task.name, "icon-160x120.png" + assert_equal task.source, "icon.svg" + assert_equal $`, "icon" + assert_equal $1, "160" + assert_equal $2, "120" + @runs << :RULE + end + Task["icon-160x120.png"].invoke + assert_equal [:RULE], @runs + end + + def test_regex_rule_with_named_capture + create_file("icon.png") + rule %r(-(?\d+)x(?\d+)\.(?\w+)$) => [ + '.\k' + ] do |task| + assert_equal task.name, "icon-160x120.png" + assert_equal task.source, "icon.png" + assert_equal $`, "icon" + assert_equal $~[:width], "160" + assert_equal $~[:height], "120" + assert_equal $~[:ext], "png" + @runs << :RULE + end + Task["icon-160x120.png"].invoke + assert_equal [:RULE], @runs + end + + def test_regex_rule_with_proc_dependent_with_named_capture + mkdir_p("src/jw") + create_file("src/jw/X.java") + rule %r(classes/(?.*)\.class$) => [ + proc { "src/#{$~[:basename]}.java" } + ] do |task| + assert_equal task.name, "classes/jw/X.class" + assert_equal task.source, "src/jw/X.java" + assert_equal $1, "jw/X" + assert_equal $~[:basename], "jw/X" + @runs << :RULE + end + Task["classes/jw/X.class"].invoke + assert_equal [:RULE], @runs + end + + def test_regex_rule_with_string_dependent_with_named_capture + mkdir_p("src/jw") + create_file("src/jw/X.java") + rule %r(classes/(?.*)\.class) => [ + 'src/\k.java' + ] do |task| + assert_equal task.name, "classes/jw/X.class" + assert_equal task.source, "src/jw/X.java" + assert_equal $1, "jw/X" + assert_equal $~[:basename], "jw/X" + @runs << :RULE + end + Task["classes/jw/X.class"].invoke + assert_equal [:RULE], @runs + end + + def test_regex_rule_with_backreference_prematch + create_file(SRCFILE) + rule ".o" => '\`.c' do |t| + @runs << t.name + end + Task[OBJFILE].invoke + assert_equal [OBJFILE], @runs + end + end