Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

simple extract variable

  • Loading branch information...
commit 24fc0a2ba5b9ac4605c009e01d0c539bd3cce721 1 parent fee699a
authored December 21, 2009 fabiokung committed March 14, 2010
68  features/extract_variable.feature
... ...
@@ -0,0 +1,68 @@
  1
+Feature: Extract Variable
  2
+  In order to improve my code's quality
  3
+  As a developer
  4
+  I want to extract variables
  5
+
  6
+  Scenario: Extracting a variable
  7
+    Given I have the following code:
  8
+      """
  9
+        def method
  10
+          puts "string" + "other"
  11
+        end
  12
+      """
  13
+    And text '"string"' from line 2 is selected
  14
+    And I want it to be in the variable called 'var'
  15
+    When I call 'extract variable'
  16
+    Then the code should be:
  17
+      """
  18
+        def method
  19
+          var = "string"
  20
+          puts var + "other"
  21
+        end
  22
+      """
  23
+
  24
+  Scenario: Extracting a variable on multiple occurrences
  25
+    Given I have the following code:
  26
+      """
  27
+        def method
  28
+          puts "string" + "other"
  29
+          puts "string" + "another"
  30
+        end
  31
+      """
  32
+    And text '"string"' from line 2 is selected
  33
+    And I want it to be in the variable called 'var'
  34
+    When I call 'extract variable'
  35
+    Then the code should be:
  36
+      """
  37
+        def method
  38
+          var = "string"
  39
+          puts var + "other"
  40
+          puts var + "another"
  41
+        end
  42
+      """
  43
+      
  44
+  Scenario: Extracting a variable just in the current method
  45
+    Given I have the following code:
  46
+      """
  47
+        def method
  48
+          puts "string" + "other"
  49
+        end
  50
+        
  51
+        def other_method
  52
+          puts "string" + "other"
  53
+        end
  54
+      """
  55
+    And text '"string"' from line 2 is selected
  56
+    And I want it to be in the variable called 'var'
  57
+    When I call 'extract variable'
  58
+    Then the code should be:
  59
+      """
  60
+        def method
  61
+          var = "string"
  62
+          puts var + "other"
  63
+        end
  64
+        
  65
+        def other_method
  66
+          puts "string" + "other"
  67
+        end
  68
+      """
16  features/steps/code_steps.rb
@@ -6,10 +6,19 @@
6 6
   @selected_lines = [start_line.to_i, end_line.to_i]
7 7
 end
8 8
 
  9
+Given /^text '(.+)' from line (\d+) is selected$/ do |text, line|
  10
+  @text = text
  11
+  @line = line.to_i
  12
+end
  13
+
9 14
 Given /^I want them to be in the method called '(.+)'$/ do |name|
10 15
   @method_name = name
11 16
 end
12 17
 
  18
+Given /^I want it to be in the variable called '(.+)'$/ do |name|
  19
+  @variable_name = name
  20
+end
  21
+
13 22
 When /^I call 'extract method'$/ do
14 23
   @code = Rfactor::Code.new(@code)
15 24
   @new_code = @code.extract_method :name => @method_name,
@@ -17,6 +26,13 @@
17 26
       :end => @selected_lines[1]
18 27
 end
19 28
 
  29
+When /^I call 'extract variable'$/ do
  30
+  @code = Rfactor::Code.new(@code)
  31
+  @new_code = @code.extract_variable :name => @variable_name,
  32
+      :text => @text,
  33
+      :line => @line
  34
+end
  35
+
20 36
 Then /^the code should be:$/ do |expected|
21 37
   @new_code.should == expected
22 38
 end
44  lib/rfactor/code.rb
@@ -58,13 +58,55 @@ def extract_method(args)
58 58
       new_code
59 59
     end
60 60
 
  61
+    # == Required arguments
  62
+    #
  63
+    # You must pass them inside a Hash:
  64
+    #
  65
+    # * :name => 'the new variable name'
  66
+    # * :text => what to be extracted to the variable
  67
+    # * :line => line number where the variable to be extracted is
  68
+    #
  69
+    # == Example
  70
+    #
  71
+    #   code.extract_variable :name => 'common_code', :text => "'string'", :line => 3
  72
+    def extract_variable(args)
  73
+      raise ":name is required" unless args.has_key?(:name)
  74
+      
  75
+      ast = RubyParser.new.parse(@code)
  76
+      line_finder = LineFinder.new(ast)
  77
+      
  78
+      method_lines = line_finder.method_lines(args[:line])
  79
+      
  80
+      new_code = ""
  81
+      added = false
  82
+      identation = 0
  83
+      
  84
+      @code.each_with_index do |line, n|
  85
+        line_number = n + 1 # not 0-based
  86
+        if line_number == method_lines.first
  87
+          identation = extract_identation_level_from line
  88
+        end
  89
+        if line_number == method_lines.first + 1
  90
+          new_code << "#{identation}  #{args[:name]} = #{args[:text]}\n"
  91
+        end
  92
+        if method_lines.include? line_number
  93
+          new_line = line.gsub(args[:text], args[:name])
  94
+          new_code << new_line
  95
+        else
  96
+          new_code << line
  97
+        end
  98
+      end
  99
+      new_code
  100
+    end
  101
+    
  102
+    private
  103
+    
61 104
     def assignment_value(method_contents)
62 105
       last_instruction = method_contents.split("\n")[-1]
63 106
       is_assignment = remove_constants(last_instruction).match(/\s*(#{VALID_NAME})\s*=/)
64 107
       $1
65 108
     end
66 109
         
67  
-    private
68 110
     def raise_error_if_absent(arguments, keys)
69 111
       keys.each do |key|
70 112
         raise ":#{key} is required" unless arguments.has_key?(key.to_sym)

0 notes on commit 24fc0a2

Please sign in to comment.
Something went wrong with that request. Please try again.