acls 1.1.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b1e9054c2aa8a265732a826ab96128fe5101388
4
- data.tar.gz: 51daeadc17700f03440fcdc417f56d90ab365897
3
+ metadata.gz: dbea83036ba56155987eaa3cdfa0955c95fd0410
4
+ data.tar.gz: cbe8a2759eebbbbd26be047e5c9bc5639f4539a3
5
5
  SHA512:
6
- metadata.gz: bb760e38f2fab04f17a321c45439afefa8acf641c0f25888d8019e153e7ae277cd4bcc39d196c89a9ad12092127da22079b477debc41b1aa5f7a41e7f84bbcf1
7
- data.tar.gz: 3f1d7c3c865a8161817e55855e76c50b03dd2f9933b7b9fa3f7c5c41106073582613565c69d848201dcead4ccfa3e2d0f7b11ebe2f68e8e2017a74a5c314754c
6
+ metadata.gz: 950a74f0011826e6447cc715dbead105c5817e19759eb00586a8f1a7f292d2b55bfe4ddfdab6c318ae9579813b7e8967b1756bc36481613a02788235c956cb69
7
+ data.tar.gz: 51905b9dbfcf6c444310a4d393f03da42842f6d0a48bbdd21a853228730f3f9a0d77d818217dd3403ebf00701d659751b3d138a20ef90d1f659beceda2324852
@@ -1,4 +1,5 @@
1
1
  require 'active_support/inflector'
2
+ require 'parser/current'
2
3
 
3
4
  module ACLS
4
5
  require_relative './acls/loader'
@@ -14,49 +14,43 @@ module ACLS
14
14
  private
15
15
 
16
16
  def build_trees(paths, opts)
17
- if paths.respond_to?(:each)
18
- paths.map { |path| build_tree(path, opts) }
19
- else
20
- [build_tree(paths, opts)]
21
- end
22
- end
23
-
24
- def build_tree(path, opts)
25
- Parser.parse(path)
17
+ paths = [paths] unless paths.respond_to?(:map)
18
+ paths.map { |path| Parser.parse(path) }
26
19
  end
27
20
 
28
21
  def autoload_statement(tree)
29
22
  "autoload :#{tree.name}, \"#{tree.source}\""
30
23
  end
31
24
 
32
- def autoload_root(tree, opts)
33
- root = Object
34
- if opts[:root_ns].is_a?(TrueClass)
35
- root = submodule(root, File.basename(tree.directory).camelize)
36
- elsif opts[:root_ns].is_a?(String)
37
- opts[:root_ns].split('::').each { |ns| root = submodule(root, ns) }
25
+ def autoload_tree(mod, tree, opts)
26
+ unless exclude?(tree, opts)
27
+ if tree.children.empty?
28
+ mod.module_eval(autoload_statement(tree))
29
+ else
30
+ mod = submodule(mod, tree.name)
31
+ end
32
+ tree.children.map { |child| autoload_tree(mod, child, opts) }
38
33
  end
39
- root
40
34
  end
41
35
 
42
36
  def autoload_trees(trees, opts)
43
37
  trees.map do |tree|
44
- root = autoload_root(tree, opts)
38
+ root = Object
45
39
  tree.children.map do |node|
46
40
  autoload_tree(root, node, opts)
47
41
  end
48
42
  end
49
43
  end
50
44
 
51
- def autoload_tree(mod, tree, opts)
52
- unless exclude?(mod, tree, opts)
53
- if tree.source
54
- mod.module_eval(autoload_statement(tree))
45
+ def exclude?(tree, opts)
46
+ opts[:exclude].each do |pattern|
47
+ if pattern.is_a?(String)
48
+ return true if pattern == File.basename(tree.path, ".rb")
55
49
  else
56
- sub = submodule(mod, tree.name)
57
- tree.children.map { |child| autoload_tree(sub, child, opts) }
50
+ return true if pattern.match(tree.path)
58
51
  end
59
52
  end
53
+ false
60
54
  end
61
55
 
62
56
  def submodule(parent, child)
@@ -65,17 +59,6 @@ module ACLS
65
59
  parent.const_set(child, Module.new)
66
60
  end
67
61
 
68
- def exclude?(mod, tree, opts)
69
- opts[:exclude].each do |pattern|
70
- if pattern.is_a?(String)
71
- return true if pattern == File.basename(tree.path, ".rb")
72
- else
73
- return true if pattern.match(tree.path)
74
- end
75
- end
76
- false
77
- end
78
-
79
62
  end
80
63
  end
81
64
  end
@@ -2,58 +2,77 @@ module ACLS
2
2
  class Parser
3
3
  class << self
4
4
 
5
- def parse(base_dir, namespace=nil)
6
- parse_tree(Tree.new(nil, namespace, base_dir))
5
+ # Given a base directory, parse all Ruby source files into a custom Tree
6
+ # representation.
7
+ def parse(base_dir)
8
+ parse_tree(Tree.new(nil, nil, base_dir), base_dir)
7
9
  end
8
10
 
9
11
  private
10
12
 
11
- def parse_tree(parent)
12
- Dir.entries(parent.directory).each do |entry|
13
- next if entry[0] == '.'
14
- full_path = "#{parent.directory}/#{entry}"
15
- name = entry.sub(".rb", "").strip.camelize
16
- if File.directory?(full_path)
17
- child = parent.make_child(name, full_path)
18
- parse_tree(child)
19
- else
20
- class_name = guess_classname(name, full_path)
21
- parent.make_child(class_name, parent.directory, full_path)
22
- end
23
- end
24
- parent
13
+ # Attempt to parse a collection of module/class names to determine a
14
+ # fully-qualified namespace for a source module/class.
15
+ def parse_names(node, parent, source)
16
+ return parent if node.nil?
17
+
18
+ parent = parse_names(node.children.first, parent, source)
19
+ parent.make_child(node.children.last, '', source)
20
+ end
21
+
22
+ # Parse an AST to get the top-most parent name and build a module/class
23
+ # chain from there.
24
+ def parse_parent(ast, parent, source)
25
+ name = ast.children.first
26
+ parse_names(name, parent, source)
25
27
  end
26
28
 
27
- def guess_classname(name, file)
28
- process_classname_matches( scan_classnames(file), name )
29
+ # Parse a module. Similar to parsing a class, except you continue to parse
30
+ # child nodes.
31
+ def parse_module(ast, parent, source)
32
+ parent = parse_parent(ast, parent, source)
33
+ ast.children[1..-1].map { |node| parse_ast(node, parent, source) }
29
34
  end
30
35
 
31
- def scan_classnames(file)
32
- contents = File.read(file)
33
- contents.scrub! if (contents.respond_to?(:scrub!))
34
- contents.scan(/(class|module)\s+([^\n\r<]+)/)
36
+ # Parse a class. Similar to parsing a module, except you do not parse any
37
+ # child nodes.
38
+ def parse_class(ast, parent, source)
39
+ parse_parent(ast, parent, source)
35
40
  end
36
41
 
37
- def process_classname_matches(matches, name)
38
- if match = best_classname_match(matches, name)
39
- base_classname(match[1])
42
+ # Parse an AST Node.
43
+ def parse_ast(ast, parent, source)
44
+ return if ast.nil? || !ast.is_a?(::AST::Node)
45
+
46
+ if ast.type == :module
47
+ parse_module(ast, parent, source)
48
+ elsif ast.type == :class
49
+ parse_class(ast, parent, source)
40
50
  else
41
- name
51
+ ast.children.each { |node| parse_ast(node, parent, source) }
42
52
  end
43
- end
44
53
 
45
- def best_classname_match(matches, name)
46
- return nil unless matches
47
- matches.drop_while { |match| !match_classname(match[1], name) }.first
54
+ parent
48
55
  end
49
56
 
50
- def match_classname(match, name)
51
- base_classname(match).downcase == name.downcase
57
+ # Convert a source file into an AST and parse it.
58
+ def parse_file(tree, file)
59
+ ast = ::Parser::CurrentRuby.parse(File.read(file))
60
+ parse_ast(ast, tree, file)
52
61
  end
53
62
 
54
- def base_classname(name)
55
- name.split("::").last.strip
63
+ def parse_tree(tree, directory)
64
+ Dir.entries(directory).each do |entry|
65
+ next if entry[0] == '.'
66
+ full_path = "#{directory}/#{entry}"
67
+ if File.directory?(full_path)
68
+ parse_tree(tree, full_path)
69
+ elsif entry.end_with?('.rb')
70
+ parse_file(tree, full_path)
71
+ end
72
+ end
73
+ tree
56
74
  end
75
+
57
76
  end
58
77
  end
59
78
  end
@@ -16,12 +16,29 @@ module ACLS
16
16
  child
17
17
  end
18
18
 
19
+ # If a source file is specified, returns the path to the source file.
19
20
  def path
20
21
  @source || @directory
21
22
  end
22
23
 
23
- def to_s
24
- "name: #{@name}, source: #{@source}, directory: #{@directory}, parent: #{@parent}, children: #{@children.length}"
24
+ # Find the first child with a given name, including the calling node in the
25
+ # search.
26
+ def find(name)
27
+ return self if @name == name
28
+ @children.find { |child| child.find(name) }
29
+ end
30
+
31
+ def to_s(level=0)
32
+ tab = '**' * 2 * level
33
+ <<EOS
34
+ #{tab} level: #{level}
35
+ #{tab} name: #{@name}
36
+ #{tab} source: #{@source}
37
+ #{tab} directory: #{@directory}
38
+ #{tab} children => [
39
+ #{@children.map { |child| child.to_s(level+1) }.join}
40
+ #{tab} ]
41
+ EOS
25
42
  end
26
43
 
27
44
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acls
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kolo Rahl
@@ -30,6 +30,26 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 4.2.5
33
+ - !ruby/object:Gem::Dependency
34
+ name: parser
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.3'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 2.3.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '2.3'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.3.0
33
53
  - !ruby/object:Gem::Dependency
34
54
  name: rspec
35
55
  requirement: !ruby/object:Gem::Requirement