Skip to content

Commit

Permalink
[EXPERIMENTAL] Declare Ruby files dependencies through magic comments
Browse files Browse the repository at this point in the history
  • Loading branch information
palkan committed Jul 19, 2017
1 parent 39779b3 commit 01ce44b
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 1 deletion.
4 changes: 3 additions & 1 deletion tasks/mrbgem_spec.rake
Expand Up @@ -2,6 +2,7 @@ require 'pathname'
require 'forwardable'
require 'tsort'
require 'shellwords'
require_relative 'utils/rbfiles_sorter'

module MRuby
module Gem
Expand Down Expand Up @@ -58,7 +59,8 @@ module MRuby
end
@linker = LinkerConfig.new([], [], [], [], [])

@rbfiles = Dir.glob("#{@dir}/#{@mrblib_dir}/**/*.rb").sort
@rbfiles = RbfilesSorter.new("#{@dir}/#{@mrblib_dir}").sort

@objs = Dir.glob("#{@dir}/#{@objs_dir}/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
end
Expand Down
28 changes: 28 additions & 0 deletions tasks/test/rbfiles_sorter_test.rb
@@ -0,0 +1,28 @@
require "minitest/autorun"

require_relative "../utils/rbfiles_sorter"

class TestRbfilesSorter < Minitest::Test
def test_sort
@sorter = RbfilesSorter.new("./support/rbfiles_sorter")
sorted = @sorter.sort

root = File.expand_path("./support/rbfiles_sorter")

assert_equal "#{root}/stuff/y.rb", sorted[0]
assert_equal "#{root}/utils/x.rb", sorted[1]
assert_equal "#{root}/b.rb", sorted[2]
assert_equal "#{root}/a.rb", sorted[3]
end

def test_sort_without_requires
@sorter = RbfilesSorter.new("./support/rbfiles_sorter_2")
sorted = @sorter.sort

root = File.expand_path("./support/rbfiles_sorter_2")

assert_equal "#{root}/0_x.rb", sorted[0]
assert_equal "#{root}/a.rb", sorted[1]
assert_equal "#{root}/c.rb", sorted[2]
end
end
6 changes: 6 additions & 0 deletions tasks/test/support/rbfiles_sorter/a.rb
@@ -0,0 +1,6 @@

# require: "b"

# require: "utils/x.rb"

class A; end
5 changes: 5 additions & 0 deletions tasks/test/support/rbfiles_sorter/b.rb
@@ -0,0 +1,5 @@
#require:'utils/x.rb'

module B; end

#require:'utils/y.rb'
1 change: 1 addition & 0 deletions tasks/test/support/rbfiles_sorter/stuff/y.rb
@@ -0,0 +1 @@
module Y; end
3 changes: 3 additions & 0 deletions tasks/test/support/rbfiles_sorter/utils/x.rb
@@ -0,0 +1,3 @@
# require: "../stuff/y.rb"

module X; end
Empty file.
Empty file.
Empty file.
45 changes: 45 additions & 0 deletions tasks/utils/rbfiles_sorter.rb
@@ -0,0 +1,45 @@
require "tsort"

class RbfilesSorter
include TSort

TAG_RXP = /^#\s*require:\s*['"]([\w\.\/]+)["']\s*$/

def initialize(root)
@root = root
@files = Dir.glob("#{root}/**/*.rb").sort
@deps = {}
end

def sort
@files.each { |f| parse_deps(f) }
tsort
end

def tsort_each_child(node, &block)
@deps[node].each(&block)
end

def tsort_each_node(&block)
@deps.each_key(&block)
end

def parse_deps(file)
f = File.new(file)

deps_list = @deps[File.expand_path(file)] = []

f.each_line do |line|
# Skip blank lines
next if line =~ /^\s*$/
# All requires should be in the beginning of the file
break if line !~ TAG_RXP

dep = line.match(TAG_RXP)[1]

dep += ".rb" unless dep.end_with?(".rb")

deps_list << File.expand_path(dep, File.dirname(file))
end
end
end

0 comments on commit 01ce44b

Please sign in to comment.