ifdef 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +3 -0
  4. data/bin/ifdef +52 -0
  5. data/ifdef.gemspec +23 -0
  6. data/lib/ifdef.rb +13 -0
  7. data/lib/ifdef/logic_processor.rb +138 -0
  8. data/lib/ifdef/rewriter.rb +24 -0
  9. data/lib/ifdef/truth.rb +37 -0
  10. data/lib/ifdef/version.rb +3 -0
  11. data/spec/data/ambiguous_if_statement/output.rb +7 -0
  12. data/spec/data/ambiguous_if_statement/source.rb +7 -0
  13. data/spec/data/ambiguous_if_statement/truth.json +3 -0
  14. data/spec/data/deeply_nested/output.rb +13 -0
  15. data/spec/data/deeply_nested/source.rb +13 -0
  16. data/spec/data/deeply_nested/truth.json +3 -0
  17. data/spec/data/elsif_statement/output.rb +9 -0
  18. data/spec/data/elsif_statement/source.rb +9 -0
  19. data/spec/data/elsif_statement/truth.json +4 -0
  20. data/spec/data/if_statement/output.rb +5 -0
  21. data/spec/data/if_statement/source.rb +5 -0
  22. data/spec/data/if_statement/truth.json +3 -0
  23. data/spec/data/inline_if_statement/output.rb +2 -0
  24. data/spec/data/inline_if_statement/source.rb +2 -0
  25. data/spec/data/inline_if_statement/truth.json +4 -0
  26. data/spec/data/inline_unless_statement/output.rb +2 -0
  27. data/spec/data/inline_unless_statement/source.rb +2 -0
  28. data/spec/data/inline_unless_statement/truth.json +4 -0
  29. data/spec/data/multiple_truth_statements/output.rb +11 -0
  30. data/spec/data/multiple_truth_statements/source.rb +11 -0
  31. data/spec/data/multiple_truth_statements/truth.json +3 -0
  32. data/spec/data/overlapping/output.rb +5 -0
  33. data/spec/data/overlapping/source.rb +9 -0
  34. data/spec/data/overlapping/truth.json +4 -0
  35. data/spec/data/ternary_statement/output.rb +2 -0
  36. data/spec/data/ternary_statement/source.rb +2 -0
  37. data/spec/data/ternary_statement/truth.json +4 -0
  38. data/spec/data/truth.json +4 -0
  39. data/spec/data/unless_statement/output.rb +5 -0
  40. data/spec/data/unless_statement/source.rb +5 -0
  41. data/spec/data/unless_statement/truth.json +3 -0
  42. data/spec/ifdef/logic_processor_spec.rb +118 -0
  43. data/spec/ifdef/rewriter_spec.rb +65 -0
  44. data/spec/ifdef/truth_spec.rb +38 -0
  45. data/spec/ifdef_spec.rb +9 -0
  46. metadata +133 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8f540bacd021264f26409fec0ce3e0aa9c924272
4
+ data.tar.gz: 1ac88926ae1d7a303c5b9728d13cb5750700a06c
5
+ SHA512:
6
+ metadata.gz: 39bd24a2be9850beb8ae571f7d29f3369e950ddcca098485e0c3939db213b32769e7948b240d53aa93e7caf7784db6184a66b8230a886f6ecdcb3677154c3fea
7
+ data.tar.gz: 076ade530eff83823ae239f2ea39e36bba476f18acdf2c827a5c139969d2837e20b354d29d8c148804f8330b7327a35b831f3040ff701e8328147877a01ed8fe
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ begin
5
+ # Silence Parser version warnings
6
+ require "stringio"
7
+ stderr_bak, $stderr = $stderr, StringIO.new
8
+ require "parser/current"
9
+ ensure
10
+ $stderr = stderr_bak
11
+ end
12
+ require "optparse"
13
+ require "ifdef"
14
+
15
+ truth = {
16
+ "true" => [],
17
+ "false" => []
18
+ }
19
+
20
+ optparser = OptionParser.new do |opts|
21
+ opts.banner = "Usage: ifdef [options] file"
22
+
23
+ opts.on("-a", "--true", "=MANDATORY", Array, "A comma separated list of statements to treat as true") do |t|
24
+ truth["true"] += t
25
+ end
26
+
27
+ opts.on("-b", "--false", "=MANDATORY", Array, "A comma separated list of statements to treat as false") do |f|
28
+ truth["false"] += f
29
+ end
30
+
31
+ opts.on("-c", "--config", "=MANDATORY", String, "The path to a JSON truth config file") do |c|
32
+ truth.merge!(JSON.parse(File.read(c)))
33
+ end
34
+
35
+ opts.on_tail("-h", "--help", "Show this message") do
36
+ puts opts
37
+ exit
38
+ end
39
+ end
40
+
41
+ optparser.parse!
42
+
43
+ abort(optparser.help) unless file = ARGV.first
44
+ source = File.read(file)
45
+ ast = Ifdef.parse(source)
46
+ buffer = Parser::Source::Buffer.new(file)
47
+ buffer.source = source
48
+
49
+ truth = Ifdef::Truth.parse_hash(truth)
50
+ rewriter = Ifdef::Rewriter.new(truth)
51
+
52
+ puts rewriter.rewrite(buffer, ast)
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ $:.unshift File.expand_path('../lib', __FILE__)
3
+ require 'ifdef/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ifdef"
7
+ spec.version = Ifdef::VERSION
8
+ spec.authors = ["Ben Toews"]
9
+ spec.email = ["mastahyeti@gmail.com"]
10
+ spec.homepage = "https://github.com/mastahyeti/ifdef"
11
+ spec.summary = "Ruby rewriter to replace false logic branches"
12
+ spec.description = "Parse source code, looking for conditional statements and replace brances that are known to be false."
13
+ spec.licenses = ["MIT"]
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = ["ifdef"]
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency "parser", "~> 2.2"
20
+
21
+ spec.add_development_dependency "rspec", "~> 3.1"
22
+ spec.add_development_dependency "bundler", "~> 1.6"
23
+ end
@@ -0,0 +1,13 @@
1
+ require "parser/current"
2
+ require "json"
3
+ require "ifdef/rewriter"
4
+ require "ifdef/logic_processor"
5
+ require "ifdef/truth"
6
+
7
+ module Ifdef
8
+ def parse(src)
9
+ Parser::CurrentRuby.parse(src)
10
+ end
11
+
12
+ extend self
13
+ end
@@ -0,0 +1,138 @@
1
+ module Ifdef
2
+ class LogicProcessor < Parser::AST::Processor
3
+ class LogicError < StandardError; end
4
+
5
+ def initialize(truth)
6
+ @truth = truth
7
+ end
8
+
9
+ # Evaluate a logical statement and reduce it to true/false if we know
10
+ # enough to do so.
11
+ #
12
+ # ast - the AST to evaluate.
13
+ #
14
+ # Returns true if we know the statement to be :true, :false if we know the
15
+ # statement to be false, and nil otherwise.
16
+ def result(ast)
17
+ case @truth.fetch(ast, process(ast))
18
+ when :true
19
+ :true
20
+ when :false
21
+ :false
22
+ else
23
+ nil
24
+ end
25
+ end
26
+
27
+ # Handle the `||` statement.
28
+ #
29
+ # node - the node to evaluate.
30
+ #
31
+ # Returns :true if either side is known to be true, :false if both sides are
32
+ # known to be false, and nil otherwise.
33
+ def on_or(node)
34
+ a, b = node.children.map { |c| @truth.fetch(c, process(c)) }
35
+
36
+ if a == :true || b == :true
37
+ :true
38
+ elsif a == :false && b == :false
39
+ :false
40
+ else
41
+ nil
42
+ end
43
+ end
44
+
45
+ # Handle the `&&` statement.
46
+ #
47
+ # node - the node to evaluate.
48
+ #
49
+ # Returns :true if both sides are known to be true, :false if either sides
50
+ # is known to be false, and nil otherwise.
51
+ def on_and(node)
52
+ a, b = node.children.map { |c| @truth.fetch(c, process(c)) }
53
+
54
+ if a == :true && b == :true
55
+ :true
56
+ elsif a == :false || b == :false
57
+ :false
58
+ else
59
+ nil
60
+ end
61
+ end
62
+
63
+ # Handles the `!` statement.
64
+ #
65
+ #
66
+ # node - the node to evaluate.
67
+ #
68
+ # Returns the inverse of the child expression.
69
+ def on_send(node)
70
+ _target, _method, _args = node.children
71
+
72
+ if _method == :!
73
+ case @truth.fetch(_target, process(_target))
74
+ when :true
75
+ :false
76
+ when :false
77
+ :true
78
+ else
79
+ nil
80
+ end
81
+ else
82
+ nil
83
+ end
84
+ end
85
+
86
+ # Handle logic statements explicitly wrapped in parenthesis.
87
+ #
88
+ # node - the node to evaluate.
89
+ #
90
+ # Returns the result of the statement within the parenthesis.
91
+ def on_begin(node)
92
+ child, other_children = *node.children
93
+
94
+ # Not sure if this can happen in an `if` statement
95
+ raise LogicError if other_children
96
+
97
+ case @truth.fetch(child, process(child))
98
+ when :true
99
+ :true
100
+ when :false
101
+ :false
102
+ else
103
+ nil
104
+ end
105
+ end
106
+
107
+ # Handle the `true` statement.
108
+ #
109
+ # node - the node to evaluate.
110
+ #
111
+ # Returns :true
112
+ def on_true(node)
113
+ :true
114
+ end
115
+
116
+ # Handle the `false` statement.
117
+ #
118
+ # node - the node to evaluate.
119
+ #
120
+ # Returns :false
121
+ def on_false(node)
122
+ :false
123
+ end
124
+
125
+ # Handle the `nil` statement.
126
+ #
127
+ # node - the node to evaluate.
128
+ #
129
+ # Returns :false
130
+ def on_nil(node)
131
+ :false
132
+ end
133
+
134
+ def node?(object)
135
+ object.is_a?(Parser::AST::Node)
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,24 @@
1
+ module Ifdef
2
+ class Rewriter < ::Parser::Rewriter
3
+ def initialize(truth)
4
+ @logic_processor = LogicProcessor.new(truth)
5
+ super()
6
+ end
7
+
8
+ def on_if(node)
9
+ _if, _then, _else = *node.children
10
+
11
+ case @logic_processor.result(_if)
12
+ when :true
13
+ process(_then) if _then
14
+ replace(_else.loc.expression, "nil") if _else
15
+ when :false
16
+ process(_else) if _else
17
+ replace(_then.loc.expression, "nil") if _then
18
+ else
19
+ process(_then) if _then
20
+ process(_else) if _else
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,37 @@
1
+ module Ifdef
2
+ module Truth
3
+ # Loads and parseds a truth-hash from a JSON file.
4
+ #
5
+ # path - The path of the JSON file.
6
+ #
7
+ # Returns a Hash.
8
+ def load_json(path)
9
+ parse_hash(JSON.parse(File.read(path)))
10
+ end
11
+
12
+ # Convert a Hash like:
13
+ #
14
+ # { "true" => ["statement1", "statement2"], "false" => "statement3"}
15
+ #
16
+ # to a Hash like:
17
+ #
18
+ # {
19
+ # s(:send, nil, :statement1) => :true,
20
+ # s(:send, nil, :statement2) => :true,
21
+ # s(:send, nil, :statement3) => :false
22
+ # }
23
+ #
24
+ # hash - The Hash to convert.
25
+ #
26
+ # Returns a new Hash.
27
+ def parse_hash(hash)
28
+ hash.each_with_object({}) do |(key, values), new_hash|
29
+ Array(values).each do |value|
30
+ new_hash[Ifdef.parse(value)] = key.to_sym
31
+ end
32
+ end
33
+ end
34
+
35
+ extend self
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module Ifdef
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ if unknown_statement
2
+ if true_statement
3
+ puts 123
4
+ else
5
+ nil
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ if unknown_statement
2
+ if true_statement
3
+ puts 123
4
+ else
5
+ puts 234
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "true": ["true_statement"]
3
+ }
@@ -0,0 +1,13 @@
1
+ module Foo
2
+ class Bar
3
+ if true_statement
4
+ def baz
5
+ if true_statement
6
+ puts 123
7
+ else
8
+ nil
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Foo
2
+ class Bar
3
+ if true_statement
4
+ def baz
5
+ if true_statement
6
+ puts 123
7
+ else
8
+ puts 234
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "true": ["true_statement"]
3
+ }
@@ -0,0 +1,9 @@
1
+ if false_statement
2
+ nil
3
+ elsif false_statement
4
+ nil
5
+ elsif true_statement
6
+ puts 345
7
+ else
8
+ nil
9
+ end
@@ -0,0 +1,9 @@
1
+ if false_statement
2
+ puts 123
3
+ elsif false_statement
4
+ puts 234
5
+ elsif true_statement
6
+ puts 345
7
+ else
8
+ puts 456
9
+ end
@@ -0,0 +1,4 @@
1
+ {
2
+ "true": ["true_statement"],
3
+ "false": ["false_statement"]
4
+ }
@@ -0,0 +1,5 @@
1
+ if true_statement
2
+ puts 123
3
+ else
4
+ nil
5
+ end
@@ -0,0 +1,5 @@
1
+ if true_statement
2
+ puts 123
3
+ else
4
+ puts 234
5
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "true": ["true_statement"]
3
+ }
@@ -0,0 +1,2 @@
1
+ puts 123 if true_statement
2
+ nil if false_statement
@@ -0,0 +1,2 @@
1
+ puts 123 if true_statement
2
+ puts 234 if false_statement
@@ -0,0 +1,4 @@
1
+ {
2
+ "true": ["true_statement"],
3
+ "false": ["false_statement"]
4
+ }
@@ -0,0 +1,2 @@
1
+ nil unless true_statement
2
+ puts 234 unless false_statement
@@ -0,0 +1,2 @@
1
+ puts 123 unless true_statement
2
+ puts 234 unless false_statement
@@ -0,0 +1,4 @@
1
+ {
2
+ "true": ["true_statement"],
3
+ "false": ["false_statement"]
4
+ }
@@ -0,0 +1,11 @@
1
+ if false_statement
2
+ nil
3
+ else
4
+ puts 234
5
+ end
6
+
7
+ if other_false_statement
8
+ nil
9
+ else
10
+ puts 456
11
+ end
@@ -0,0 +1,11 @@
1
+ if false_statement
2
+ puts 123
3
+ else
4
+ puts 234
5
+ end
6
+
7
+ if other_false_statement
8
+ puts 345
9
+ else
10
+ puts 456
11
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "false": ["false_statement", "other_false_statement"]
3
+ }
@@ -0,0 +1,5 @@
1
+ if false_statement
2
+ nil
3
+ else
4
+ puts 345
5
+ end
@@ -0,0 +1,9 @@
1
+ if false_statement
2
+ if true_statement
3
+ puts 123
4
+ else
5
+ puts 234
6
+ end
7
+ else
8
+ puts 345
9
+ end
@@ -0,0 +1,4 @@
1
+ {
2
+ "true": ["true_statement"],
3
+ "false": ["false_statement"]
4
+ }
@@ -0,0 +1,2 @@
1
+ puts true_statement ? 123 : nil
2
+ puts false_statement ? nil : 456
@@ -0,0 +1,2 @@
1
+ puts true_statement ? 123 : 234
2
+ puts false_statement ? 345 : 456
@@ -0,0 +1,4 @@
1
+ {
2
+ "true": ["true_statement"],
3
+ "false": ["false_statement"]
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "true": ["true_statement", "other_true_statement"],
3
+ "false": ["false_statement"]
4
+ }
@@ -0,0 +1,5 @@
1
+ unless false_statement
2
+ puts 123
3
+ else
4
+ nil
5
+ end
@@ -0,0 +1,5 @@
1
+ unless false_statement
2
+ puts 123
3
+ else
4
+ puts 234
5
+ end
@@ -0,0 +1,3 @@
1
+ {
2
+ "false": ["false_statement"]
3
+ }
@@ -0,0 +1,118 @@
1
+ require "ifdef"
2
+
3
+ describe Ifdef::LogicProcessor, "#result" do
4
+ include AST::Sexp
5
+
6
+ subject do
7
+ Ifdef::LogicProcessor.new(
8
+ Ifdef.parse("true_statement") => :true,
9
+ Ifdef.parse("false_statement") => :false,
10
+ )
11
+ end
12
+
13
+ def result(statement)
14
+ subject.result(Ifdef.parse(statement))
15
+ end
16
+
17
+ it "handles basic statements" do
18
+ expect(result("true_statement")).to eq(:true)
19
+ expect(result("false_statement")).to eq(:false)
20
+ end
21
+
22
+ it "follows basic logic for &&" do
23
+ expect(result("true && true")).to eq(:true)
24
+ expect(result("true && false")).to eq(:false)
25
+ expect(result("false && true")).to eq(:false)
26
+ expect(result("false && false")).to eq(:false)
27
+
28
+ expect(result("true_statement && true")).to eq(:true)
29
+ expect(result("true_statement && false")).to eq(:false)
30
+ expect(result("false_statement && true")).to eq(:false)
31
+ expect(result("false_statement && false")).to eq(:false)
32
+
33
+ expect(result("true && true_statement")).to eq(:true)
34
+ expect(result("true && false_statement")).to eq(:false)
35
+ expect(result("false && true_statement")).to eq(:false)
36
+ expect(result("false && false_statement")).to eq(:false)
37
+
38
+ expect(result("true_statement && true_statement")).to eq(:true)
39
+ expect(result("true_statement && false_statement")).to eq(:false)
40
+ expect(result("false_statement && true_statement")).to eq(:false)
41
+ expect(result("false_statement && false_statement")).to eq(:false)
42
+ end
43
+
44
+ it "follows basic logic for ||" do
45
+ expect(result("true || true")).to eq(:true)
46
+ expect(result("true || false")).to eq(:true)
47
+ expect(result("false || true")).to eq(:true)
48
+ expect(result("false || false")).to eq(:false)
49
+
50
+ expect(result("true_statement || true")).to eq(:true)
51
+ expect(result("true_statement || false")).to eq(:true)
52
+ expect(result("false_statement || true")).to eq(:true)
53
+ expect(result("false_statement || false")).to eq(:false)
54
+
55
+ expect(result("true || true_statement")).to eq(:true)
56
+ expect(result("true || false_statement")).to eq(:true)
57
+ expect(result("false || true_statement")).to eq(:true)
58
+ expect(result("false || false_statement")).to eq(:false)
59
+
60
+ expect(result("true_statement || true_statement")).to eq(:true)
61
+ expect(result("true_statement || false_statement")).to eq(:true)
62
+ expect(result("false_statement || true_statement")).to eq(:true)
63
+ expect(result("false_statement || false_statement")).to eq(:false)
64
+ end
65
+
66
+ it "follows basic logic for !" do
67
+ expect(result("!true")).to eq(:false)
68
+ expect(result("!false")).to eq(:true)
69
+
70
+ expect(result("!true_statement")).to eq(:false)
71
+ expect(result("!false_statement")).to eq(:true)
72
+ end
73
+
74
+ it "chains logic for implicitly nested statements" do
75
+ expect(result("true && true && true")).to eq(:true)
76
+ expect(result("true && true && false")).to eq(:false)
77
+
78
+ expect(result("true || true || true")).to eq(:true)
79
+ expect(result("true || false || true")).to eq(:true)
80
+ end
81
+
82
+ it "chains logic for explicitly nested statements" do
83
+ expect(result("true || (true || true)")).to eq(:true)
84
+ expect(result("true && (true || true)")).to eq(:true)
85
+ expect(result("true || (true && true)")).to eq(:true)
86
+ expect(result("true && (true && true)")).to eq(:true)
87
+
88
+ expect(result("false || (true || true)")).to eq(:true)
89
+ expect(result("false && (true || true)")).to eq(:false)
90
+ expect(result("false || (true && true)")).to eq(:true)
91
+ expect(result("false && (true && true)")).to eq(:false)
92
+
93
+ expect(result("true || (false || true)")).to eq(:true)
94
+ expect(result("true && (false || true)")).to eq(:true)
95
+ expect(result("true || (false && true)")).to eq(:true)
96
+ expect(result("true && (false && true)")).to eq(:false)
97
+
98
+ expect(result("true || (true || false)")).to eq(:true)
99
+ expect(result("true && (true || false)")).to eq(:true)
100
+ expect(result("true || (true && false)")).to eq(:true)
101
+ expect(result("true && (true && false)")).to eq(:false)
102
+
103
+ expect(result("false || (false || true)")).to eq(:true)
104
+ expect(result("false && (false || true)")).to eq(:false)
105
+ expect(result("false || (false && true)")).to eq(:false)
106
+ expect(result("false && (false && true)")).to eq(:false)
107
+
108
+ expect(result("true || (false || false)")).to eq(:true)
109
+ expect(result("true && (false || false)")).to eq(:false)
110
+ expect(result("true || (false && false)")).to eq(:true)
111
+ expect(result("true && (false && false)")).to eq(:false)
112
+
113
+ expect(result("false || (false || false)")).to eq(:false)
114
+ expect(result("false && (false || false)")).to eq(:false)
115
+ expect(result("false || (false && false)")).to eq(:false)
116
+ expect(result("false && (false && false)")).to eq(:false)
117
+ end
118
+ end
@@ -0,0 +1,65 @@
1
+ require "ifdef"
2
+
3
+ describe Ifdef::Rewriter, "#process" do
4
+ def run_example(name)
5
+ example_dir = File.expand_path(File.join(__FILE__, "../../data/", name))
6
+
7
+ # What we're expecting the rewriter to output.
8
+ expected_output = File.read(File.join(example_dir, "output.rb"))
9
+
10
+ # The truth to assert on the example source.
11
+ truth = Ifdef::Truth.load_json(File.join(example_dir, "truth.json"))
12
+
13
+ # The source code to operate on.
14
+ source_path = File.join(example_dir, "source.rb")
15
+ source = File.read(source_path)
16
+ ast = Ifdef.parse(source)
17
+ buffer = Parser::Source::Buffer.new(source_path)
18
+ buffer.source = source
19
+
20
+ # Rewrite the source.
21
+ rewriter = Ifdef::Rewriter.new(truth)
22
+ actual_output = rewriter.rewrite(buffer, ast)
23
+ expect(actual_output).to eq(expected_output)
24
+ end
25
+
26
+ it "replaces else branch in if statement with nil" do
27
+ run_example("if_statement")
28
+ end
29
+
30
+ it "replaces then branch in unless statement with nil" do
31
+ run_example("unless_statement")
32
+ end
33
+
34
+ it "replaces else branch in inline if statement with nil" do
35
+ run_example("inline_if_statement")
36
+ end
37
+
38
+ it "replaces then branch in inline unless statement with nil" do
39
+ run_example("inline_unless_statement")
40
+ end
41
+
42
+ it "replaces else branch in ternary statement with nil" do
43
+ run_example("ternary_statement")
44
+ end
45
+
46
+ it "finds statements nested in other code" do
47
+ run_example("deeply_nested")
48
+ end
49
+
50
+ it "if replaces false branches in elsif sections" do
51
+ run_example("elsif_statement")
52
+ end
53
+
54
+ it "merges overlapping replacements" do
55
+ run_example("overlapping")
56
+ end
57
+
58
+ it "allows for multiple truth statements" do
59
+ run_example("multiple_truth_statements")
60
+ end
61
+
62
+ it "ignores if statements where truth is ambiguous" do
63
+ run_example("ambiguous_if_statement")
64
+ end
65
+ end
@@ -0,0 +1,38 @@
1
+ require "ifdef"
2
+
3
+ describe Ifdef::Truth, "#load_json" do
4
+ subject { Ifdef::Truth }
5
+
6
+ it "loads json files" do
7
+ path = File.expand_path("../../data/truth.json", __FILE__)
8
+ expect(subject.load_json(path)).to be_a(Hash)
9
+ end
10
+ end
11
+
12
+ describe Ifdef::Truth, "#parse_hash" do
13
+ subject { Ifdef::Truth }
14
+
15
+ it "returns a hash whose values are :true/:false" do
16
+ hash = {
17
+ "true" => ["true_statement"]
18
+ }
19
+ subject.parse_hash(hash).values.each do |value|
20
+ expect(value).to eq(:true).or(:false)
21
+ end
22
+ end
23
+
24
+ it "returns a hash whose keys are nodes" do
25
+ hash = {
26
+ "true" => ["true_statement"]
27
+ }
28
+ subject.parse_hash(hash).keys.each do |key|
29
+ expect(key).to be_a(Parser::AST::Node)
30
+ end
31
+ end
32
+
33
+ it "allows strings or arrays as input hash values" do
34
+ with_string = subject.parse_hash("true" => "true_statement")
35
+ with_array = subject.parse_hash("true" => ["true_statement"])
36
+ expect(with_array).to eq(with_string)
37
+ end
38
+ end
@@ -0,0 +1,9 @@
1
+ require "ifdef"
2
+
3
+ describe Ifdef, ".parse" do
4
+ subject { Ifdef }
5
+
6
+ it "parses ruby" do
7
+ expect(subject.parse("nil")).to be_a(AST::Node)
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ifdef
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben Toews
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ description: Parse source code, looking for conditional statements and replace brances
56
+ that are known to be false.
57
+ email:
58
+ - mastahyeti@gmail.com
59
+ executables:
60
+ - ifdef
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - bin/ifdef
68
+ - ifdef.gemspec
69
+ - lib/ifdef.rb
70
+ - lib/ifdef/logic_processor.rb
71
+ - lib/ifdef/rewriter.rb
72
+ - lib/ifdef/truth.rb
73
+ - lib/ifdef/version.rb
74
+ - spec/data/ambiguous_if_statement/output.rb
75
+ - spec/data/ambiguous_if_statement/source.rb
76
+ - spec/data/ambiguous_if_statement/truth.json
77
+ - spec/data/deeply_nested/output.rb
78
+ - spec/data/deeply_nested/source.rb
79
+ - spec/data/deeply_nested/truth.json
80
+ - spec/data/elsif_statement/output.rb
81
+ - spec/data/elsif_statement/source.rb
82
+ - spec/data/elsif_statement/truth.json
83
+ - spec/data/if_statement/output.rb
84
+ - spec/data/if_statement/source.rb
85
+ - spec/data/if_statement/truth.json
86
+ - spec/data/inline_if_statement/output.rb
87
+ - spec/data/inline_if_statement/source.rb
88
+ - spec/data/inline_if_statement/truth.json
89
+ - spec/data/inline_unless_statement/output.rb
90
+ - spec/data/inline_unless_statement/source.rb
91
+ - spec/data/inline_unless_statement/truth.json
92
+ - spec/data/multiple_truth_statements/output.rb
93
+ - spec/data/multiple_truth_statements/source.rb
94
+ - spec/data/multiple_truth_statements/truth.json
95
+ - spec/data/overlapping/output.rb
96
+ - spec/data/overlapping/source.rb
97
+ - spec/data/overlapping/truth.json
98
+ - spec/data/ternary_statement/output.rb
99
+ - spec/data/ternary_statement/source.rb
100
+ - spec/data/ternary_statement/truth.json
101
+ - spec/data/truth.json
102
+ - spec/data/unless_statement/output.rb
103
+ - spec/data/unless_statement/source.rb
104
+ - spec/data/unless_statement/truth.json
105
+ - spec/ifdef/logic_processor_spec.rb
106
+ - spec/ifdef/rewriter_spec.rb
107
+ - spec/ifdef/truth_spec.rb
108
+ - spec/ifdef_spec.rb
109
+ homepage: https://github.com/mastahyeti/ifdef
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.2.2
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Ruby rewriter to replace false logic branches
133
+ test_files: []