lib/ember/appkit/rails/walker.rb in ember-appkit-rails-0.3.2 vs lib/ember/appkit/rails/walker.rb in ember-appkit-rails-0.4.0
- old
+ new
@@ -1,44 +1,44 @@
-require 'ripper'
+require 'parser/current'
-class Walker
+class Walker < AST::Processor
+ attr_accessor :found_nodes, :namespace_type
+
def initialize(resource, path, api_version)
@resource = resource
@file = File.open(path, 'r+')
- content = @file.read
- @ast = Ripper.sexp(content)
- @lines = content.split("\n")
+ @content = @file.read
+ @ast = Parser::CurrentRuby.parse(@content)
@api_version = api_version
+ @found_nodes = []
end
- def run
- find_api_namespace(@ast)
+ def handler_missing(node)
+ walk(node)
+ end
- output = nil
- line_number = @lines.index { |line| line =~ /routes\.draw do/ }
-
- if @write_to
- if @write_to.first == :version
- output = write_resource
- else
- output = write_version_namespace do
- write_resource
- end
+ def on_block(node)
+ if is_namespace?(node)
+ if is_namespace_type?(node, :api)
+ found_nodes << node
+ self.namespace_type = :api
+ walk_namespace(node)
+ elsif is_namespace_type?(node, "v#{@api_version}".to_sym)
+ found_nodes << node
+ self.namespace_type = :version
+ walk_namespace(node)
end
- line_number = @write_to.last - 1
else
- output = write_api_namespace do
- write_version_namespace do
- write_resource
- end
- end
+ walk(node)
end
+ end
- @lines.insert(line_number + 1, output)
- @file.rewind
- @file.write(@lines.join("\n"))
- @file.close
+ def on_send(node)
+ if is_resource?(node, @resource.to_sym)
+ @found_resource = true
+ found_nodes << node
+ end
end
def write_api_namespace
" namespace :api do\n#{yield}\n end"
end
@@ -49,51 +49,80 @@
def write_resource
" resources :#{@resource}, except: [:new, :edit]"
end
- def find_api_namespace(ast)
- find_namespace(ast, 'api') do |ast|
- find_version_namespace(ast, @api_version)
+ def invoke!
+ process(@ast)
+ if found_nodes.empty?
+ found_nodes << @ast
+ end
+ node = found_nodes.last
+ begin_pos = node.loc.begin.end_pos
- if @write_to.nil?
- @write_to = [:api, ast[1][1][2][0]]
+ output = ''
+
+ if namespace_type
+ if namespace_type == :version
+ output = write_resource
+ else
+ output = write_version_namespace do
+ write_resource
+ end
end
+ else
+ output = write_api_namespace do
+ write_version_namespace do
+ write_resource
+ end
+ end
+ end
- # found the first instance of the namespace
- # immediately short-circuit
- return
+ @file.rewind
+ @file.write(@content.insert(begin_pos + 1, output + "\n"))
+ @file.close
+ end
+
+ def revoke!
+ @revoke = true
+ process(@ast)
+ return if found_nodes.empty? || @found_resource.nil?
+ if found_nodes.last.loc.expression
+ begin_pos = found_nodes.last.loc.expression.begin_pos
+ end_pos = found_nodes.last.loc.expression.end_pos
+ else
+ begin_pos = found_nodes.last.loc.begin.begin_pos
+ end_pos = found_nodes.last.loc.end.end_pos
end
+ begin_pos = begin_pos - @content[0..begin_pos].reverse.index("\n")
+ @file.rewind
+ @file.write @content.sub(@content[begin_pos...end_pos], '')
+ @file.close
end
- def find_version_namespace(ast, version)
- find_namespace(ast, "v#{version}") do |ast|
- @write_to = [:version, ast[1][1][2][0]]
+ private
- # found the first instance of the namespace
- # immediately short-circuit
- return
- end
+ def is_resource?(node, type)
+ node.children[1] == :resource && node.children[2].children.first == type.to_sym
+ end
- @write_to
+ def is_namespace?(node)
+ node.children.first.children[1] == :namespace
end
- def find_namespace(ast, name)
- walk(ast) do |ast, node|
- if node == :method_add_block
- flat_ast = ast[1].flatten
- if flat_ast.include?('namespace') && flat_ast.include?(name)
- yield(ast)
- end
- end
+ def is_namespace_type?(node, type)
+ node.children.first.children[2].children.first == type.to_sym
+ end
+
+ def walk_namespace(node)
+ process(node.children[2])
+ if @revoke && node.children[2] && node.children[2].children == found_nodes.last.to_a
+ found_nodes << node
end
end
- def walk(ast, &block)
- if ast.is_a?(Array)
- ast.each do |node|
- yield(ast, node)
- walk(node, &block)
- end
+ def walk(node)
+ node.children.each do |child|
+ process(child) if child.respond_to?(:to_ast)
end
end
end