Skip to content

Commit 7f64553

Browse files
committed
Add basic code breaking for variable assignments
1 parent 24f065b commit 7f64553

5 files changed

Lines changed: 88 additions & 4 deletions

File tree

code_breaker.gemspec

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ Gem::Specification.new do |spec|
2727
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
2828
spec.require_paths = ["lib"]
2929

30+
spec.add_dependency "parser", "~> 2.2"
31+
spec.add_dependency "activesupport", "~> 4"
32+
3033
spec.add_development_dependency "bundler", "~> 1.10"
3134
spec.add_development_dependency "rake", "~> 10.0"
32-
spec.add_development_dependency "rspec"
35+
spec.add_development_dependency "rspec", " ~> 3.2"
3336
end

lib/code_breaker.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
require "code_breaker/version"
2+
require "code_breaker/parser"
23

34
module CodeBreaker
4-
# Your code goes here...
5+
6+
def self.parse(code)
7+
CodeBreaker::Parser.new(code).run
8+
end
59
end

lib/code_breaker/parser.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
require 'parser/current'
2+
require 'active_support/inflector'
3+
4+
module CodeBreaker
5+
class Parser
6+
7+
attr_reader :input, :output
8+
9+
def initialize(code)
10+
@input = code.to_s.strip
11+
end
12+
13+
def run
14+
parsed = ::Parser::CurrentRuby.parse(@input)
15+
nodes = parsed.loc.node.children
16+
children = nodes[1].children
17+
18+
result = parse(children)
19+
@output = cleanup(result)
20+
end
21+
22+
private
23+
24+
def parse(nodes)
25+
nodes.map do |node|
26+
node.respond_to?(:children) ? parse(node.children).to_a : node
27+
end
28+
end
29+
30+
def cleanup(nodes)
31+
result = nodes.map do |node|
32+
if node.kind_of?(Symbol)
33+
node
34+
elsif node.kind_of?(Array) && node.length == 1
35+
node[0].class
36+
elsif node.kind_of?(Array)
37+
node[0].nil? ? node[1].to_s.constantize : cleanup(node)
38+
end
39+
end
40+
41+
result.flatten
42+
end
43+
end
44+
end

spec/code_breaker_spec.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@
55
expect(CodeBreaker::VERSION).not_to be nil
66
end
77

8-
it 'does something useful' do
9-
expect(false).to eq(true)
8+
describe '::parse' do
9+
it 'instanciates a new Parser and runs it' do
10+
allow_any_instance_of(CodeBreaker::Parser).to receive(:run) { 'parsed' }
11+
expect_any_instance_of(CodeBreaker::Parser).to receive(:run)
12+
13+
result = CodeBreaker.parse('gem_name = "code_breaker"')
14+
expect(result).to eq 'parsed'
15+
end
1016
end
1117
end

spec/parser_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
require 'spec_helper'
2+
3+
describe CodeBreaker::Parser do
4+
5+
let(:code_snippet) { 'gem_name = "code_breaker"' }
6+
subject { CodeBreaker::Parser.new(code_snippet) }
7+
8+
it { is_expected.to respond_to :run }
9+
it { is_expected.to respond_to :input }
10+
it { is_expected.to respond_to :output }
11+
12+
describe '#run' do
13+
it 'returns an Array' do
14+
expect(subject.run).to be_an Array
15+
end
16+
17+
context 'for code snippets defining a variable' do
18+
it 'returns the called classes and methods of the right hand side' do
19+
code_snippet = 'number = 1 + 2.3 - Rational(2,3) * Complex(0.4, 0.2)'
20+
expected_result = [Fixnum, :+, Float, :-, Rational, :*, Complex]
21+
actual_result = CodeBreaker::Parser.new(code_snippet).run
22+
23+
expect(actual_result).to eq expected_result
24+
end
25+
end
26+
end
27+
end

0 commit comments

Comments
 (0)