Class: Wrong::Chunk
Instance Attribute Summary collapse
-
#block ⇒ Object
readonly
Returns the value of attribute block.
-
#file ⇒ Object
readonly
Returns the value of attribute file.
-
#line_number ⇒ Object
readonly
Returns the value of attribute line_number.
Class Method Summary collapse
Instance Method Summary collapse
- #build_sexp ⇒ Object
-
#claim ⇒ Object
The claim is the part of the assertion inside the curly braces.
- #code ⇒ Object
-
#glom(source) ⇒ Object
Algorithm: * try to parse the starting line * if it parses OK, then we’re done! * if not, then glom the next line and try again * repeat until it parses or we’re out of lines.
-
#initialize(file, line_number, &block) ⇒ Chunk
constructor
line parameter is 1-based.
- #line_index ⇒ Object
- #location ⇒ Object
- #parts(sexp = nil) ⇒ Object
- #read_source_file(file) ⇒ Object
- #sexp ⇒ Object
Methods included from Capturing
Constructor Details
#initialize(file, line_number, &block) ⇒ Chunk
line parameter is 1-based
32 33 34 35 36 |
# File 'lib/wrong/chunk.rb', line 32 def initialize(file, line_number, &block) @file = file @line_number = line_number.to_i @block = block end |
Instance Attribute Details
#block ⇒ Object (readonly)
Returns the value of attribute block.
29 30 31 |
# File 'lib/wrong/chunk.rb', line 29 def block @block end |
#file ⇒ Object (readonly)
Returns the value of attribute file.
29 30 31 |
# File 'lib/wrong/chunk.rb', line 29 def file @file end |
#line_number ⇒ Object (readonly)
Returns the value of attribute line_number.
29 30 31 |
# File 'lib/wrong/chunk.rb', line 29 def line_number @line_number end |
Class Method Details
.from_block(block, depth = 0) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/wrong/chunk.rb', line 11 def self.from_block(block, depth = 0) as_proc = block.to_proc file, line = if as_proc.respond_to? :source_location # in Ruby 1.9, or with Sourcify, it reads the source location from the block as_proc.source_location else # in Ruby 1.8, it reads the source location from the call stack relevant_caller = caller[depth] relevant_caller.split(":") end new(file, line, &block) end |
Instance Method Details
#build_sexp ⇒ Object
50 51 52 53 54 55 56 |
# File 'lib/wrong/chunk.rb', line 50 def build_sexp glom(if @file == "(irb)" IRB.CurrentContext.all_lines else read_source_file(@file) end) end |
#claim ⇒ Object
The claim is the part of the assertion inside the curly braces. E.g. for “assert { x == 5 }” the claim is “x == 5”
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/wrong/chunk.rb', line 89 def claim sexp() if @sexp.nil? raise "Could not parse #{location}" else assertion = @sexp.assertion statement = assertion && assertion[3] if statement.nil? @sexp # raise "Could not find assertion in #{location}\n\t#{@chunk.strip}\n\t#{@sexp}" else statement end end end |
#code ⇒ Object
106 107 108 109 110 111 112 |
# File 'lib/wrong/chunk.rb', line 106 def code self.claim.to_ruby rescue => e # note: this is untested; it's to recover from when we can't locate the code = "Failed at #{file}:#{line_number} [couldn't retrieve source code due to #{e.inspect}]" raise end |
#glom(source) ⇒ Object
Algorithm:
-
try to parse the starting line
-
if it parses OK, then we’re done!
-
if not, then glom the next line and try again
-
repeat until it parses or we’re out of lines
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/wrong/chunk.rb', line 67 def glom(source) lines = source.split("\n") @parser ||= RubyParser.new @chunk = nil c = 0 sexp = nil while sexp.nil? && line_index + c < lines.size begin @chunk = lines[line_index..line_index+c].join("\n") capturing(:stderr) do # new RubyParser is too loud sexp = @parser.parse(@chunk) end rescue Racc::ParseError => e # loop and try again c += 1 end end sexp end |
#line_index ⇒ Object
38 39 40 |
# File 'lib/wrong/chunk.rb', line 38 def line_index @line_number - 1 end |
#location ⇒ Object
42 43 44 |
# File 'lib/wrong/chunk.rb', line 42 def location "#{@file}:#{@line_number}" end |
#parts(sexp = nil) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/wrong/chunk.rb', line 114 def parts(sexp = nil) if sexp.nil? parts(self.claim).compact.uniq else # todo: extract some of this into Sexp parts_list = [] begin unless [:arglist, :lasgn, :iter].include? sexp.first code = sexp.to_ruby.strip parts_list << code unless code == "" || parts_list.include?(code) end rescue => e puts "#{e.class}: #{e.}" puts e.backtrace.join("\n") end if sexp.first == :iter sexp.delete_at(1) # remove the method-call-sans-block subnode end sexp.each do |sub| if sub.is_a?(Sexp) parts_list += parts(sub) end end parts_list end end |
#read_source_file(file) ⇒ Object
58 59 60 |
# File 'lib/wrong/chunk.rb', line 58 def read_source_file(file) Config.read_here_or_higher(file) end |
#sexp ⇒ Object
46 47 48 |
# File 'lib/wrong/chunk.rb', line 46 def sexp @sexp ||= build_sexp end |