Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

line number extractor and basic code extractor

  • Loading branch information...
commit 5d47cdb590df12eaddd654a6665ae8b3b2629e33 1 parent 46b61f7
@fabiokung authored
View
30 features/extract_method.feature
@@ -0,0 +1,30 @@
+Feature: Extract Method
+ In order to improve my code's quality
+ As a developer
+ I want to extract methods
+
+ Scenario: Simple code, no variables
+ Given I have the following code:
+ """
+ def the_method(firstArg, secondArg)
+ puts "some"
+ puts :code
+ puts /to be/
+ puts 'refactored'
+ end
+ """
+ And lines from 3 to 5 are selected
+ And I want them to be in the method called 'other_method'
+ When I call 'extract method'
+ Then the code should be:
+ """
+ def the_method(firstArg, secondArg)
+ puts "some"
+ end
+
+ def other_method
+ puts :code
+ puts /to be/
+ puts 'refactored'
+ end
+ """
View
22 features/steps/code.rb
@@ -0,0 +1,22 @@
+Given /^I have the following code:$/ do |code|
+ @code = code
+end
+
+Given /^lines from (\d+) to (\d+) are selected$/ do |start_line, end_line|
+ @selected_lines = [start_line.to_i, end_line.to_i]
+end
+
+Given /^I want them to be in the method called '(.+)'$/ do |name|
+ @method_name = name
+end
+
+When /^I call 'extract method'$/ do
+ @code = Rfactor::Code.new(@code)
+ @new_code = @code.extract_method :name => @method_name,
+ :start => @selected_lines[0],
+ :end => @selected_lines[1]
+end
+
+Then /^the code should be:$/ do |expected|
+ @new_code.should == expected
+end
View
14 lib/rfactor.rb
@@ -5,5 +5,19 @@ module Rfactor
VERSION = '0.0.1'
end
+class String
+ def last_line
+ number = 0
+ self.each_with_index do |line, i|
+ number = i
+ end
+ number + 1
+ end
+end
+
require 'rubygems'
require 'ruby_parser'
+require 'sexp_processor'
+
+require 'rfactor/line_finder'
+require 'rfactor/code'
View
27 lib/rfactor/code.rb
@@ -0,0 +1,27 @@
+module Rfactor
+
+ class Code
+
+ def initialize(code)
+ @code = code
+ @ast = RubyParser.new.parse(code)
+ @line_finder = LineFinder.new(@ast, code.last_line)
+ end
+
+ def extract_method(args)
+ raise ":name is required" unless args.has_key?(:name)
+ method_lines = @line_finder.method_lines(args[:start])
+ selected_lines = Range.new(args[:start], args[:end])
+ new_code = ""
+ @code.each_with_index do |line, number|
+ if selected_lines.include?(number+1)
+ new_code << "#{args[:name]}()\n" if number == method_lines.first
+ else
+ new_code << line
+ end
+ end
+ new_code
+ end
+
+ end
+end
View
44 lib/rfactor/line_finder.rb
@@ -0,0 +1,44 @@
+module Rfactor
+
+ class LineFinder
+
+ def initialize(ast, last_line)
+ @ast = ast
+ @last_line = last_line
+ end
+
+ def method_lines(line_in_code)
+ processor = MethodLineFinderProcessor.new(line_in_code)
+ processor.process(@ast)
+ Range.new(processor.method_line, processor.last_method_line || @last_line, true)
+ end
+ end
+
+ class MethodLineFinderProcessor < ::SexpProcessor
+ attr_reader :method_line
+ attr_reader :last_method_line
+
+ def initialize(line)
+ super()
+ self.strict = false
+ self.require_empty = false
+ @line = line
+ @method_line = 0
+ @last_method_line = 0
+ end
+
+ def process_defn(exp, next_exp)
+ current = exp.line
+ if current > @method_line && current < @line
+ @method_line = current
+ @last_method_line = next_exp.line if next_exp
+ end
+ exp
+ end
+
+ def last_method_line
+ @last_method_line if @last_method_line > @method_line
+ end
+ end
+
+end
View
37 spec/line_finder_spec.rb
@@ -0,0 +1,37 @@
+require File.dirname(__FILE__) + '/spec_helper.rb'
+
+CODE = <<-END
+class Bla
+ def my_method
+ puts "something"
+ puts "more"
+ 3+2
+ end
+
+ def my_other_method
+ puts "anything"
+ end
+end
+
+END
+
+describe Rfactor::LineFinder do
+
+ before(:each) do
+ @ast = RubyParser.new.parse(CODE)
+ @finder = Rfactor::LineFinder.new(@ast, CODE.last_line)
+ end
+
+ it "should find method start line" do
+ @finder.method_lines(3).first.should == 2
+ end
+
+ it "should use next method line as last line" do
+ @finder.method_lines(3).last.should == 8
+ end
+
+ it "should use file last line if position is last method method" do
+ @finder.method_lines(9).last.should == 11
+ end
+
+end
View
10 spec/rfactor_spec.rb
@@ -1,11 +1,7 @@
require File.dirname(__FILE__) + '/spec_helper.rb'
-# Time to add your specs!
-# http://rspec.info/
-describe "Place your specs here" do
-
- it "find this spec in spec directory" do
- violated "Be sure to write your specs"
+describe Rfactor do
+ it "should have VERSION" do
+ Rfactor::VERSION.should_not be_empty
end
-
end
View
2  tasks/rspec.rake
@@ -14,7 +14,7 @@ EOS
exit(0)
end
-desc "Run the specs under spec/models"
+desc "Run the specs under spec/"
Spec::Rake::SpecTask.new do |t|
t.spec_opts = ['--options', "spec/spec.opts"]
t.spec_files = FileList['spec/**/*_spec.rb']
Please sign in to comment.
Something went wrong with that request. Please try again.