ifdef 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []