# File lib/rcodetools/xmpfilter.rb, line 44 44: def self.detect_rbtest(code, opts) 45: opts[:use_rbtest] ||= (opts[:detect_rbtest] and code =~ /^=begin test./) ? true : false 46: end
# File lib/rcodetools/xmpfilter.rb, line 53 53: def initialize(opts = {}) 54: options = INITIALIZE_OPTS.merge opts 55: @interpreter_info = INTERPRETER_RUBY 56: @interpreter = options[:interpreter] 57: @options = options[:options] 58: @libs = options[:libs] 59: @evals = options[:evals] || [] 60: @include_paths = options[:include_paths] 61: @output_stdout = options[:output_stdout] 62: @dump = options[:dump] 63: @warnings = options[:warnings] 64: @parentheses = options[:use_parentheses] 65: @ignore_NoMethodError = options[:ignore_NoMethodError] 66: test_script = options[:test_script] 67: test_method = options[:test_method] 68: filename = options[:filename] 69: @execute_ruby_tmpfile = options[:execute_ruby_tmpfile] 70: @postfix = "" 71: @stdin_path = nil 72: @width = options[:width] 73: 74: initialize_rct_fork if options[:detect_rct_fork] 75: initialize_rbtest if options[:use_rbtest] 76: initialize_for_test_script test_script, test_method, filename if test_script and !options[:use_rbtest] 77: end
# File lib/rcodetools/xmpfilter.rb, line 117 117: def add_markers(code, min_codeline_size = 50) 118: maxlen = code.map{|x| x.size}.max 119: maxlen = [min_codeline_size, maxlen + 2].max 120: ret = "" 121: code.each do |l| 122: l = l.chomp.gsub(/ # (=>|!>).*/, "").gsub(/\s*$/, "") 123: ret << (l + " " * (maxlen - l.size) + " # =>\n") 124: end 125: ret 126: end
# File lib/rcodetools/xmpfilter.rb, line 130 130: def annotate(code) 131: idx = 0 132: code = code.gsub(/ # !>.*/, '') 133: newcode = code.gsub(SINGLE_LINE_RE){ prepare_line($1, idx += 1) } 134: newcode.gsub!(MULTI_LINE_RE){ prepare_line($1, idx += 1, true)} 135: File.open(@dump, "w"){|f| f.puts newcode} if @dump 136: stdout, stderr = execute(newcode) 137: output = stderr.readlines 138: runtime_data = extract_data(output) 139: idx = 0 140: annotated = code.gsub(SINGLE_LINE_RE) { |l| 141: expr = $1 142: if /^\s*#/ =~ l 143: l 144: else 145: annotated_line(l, expr, runtime_data, idx += 1) 146: end 147: } 148: annotated.gsub!(/ # !>.*/, '') 149: annotated.gsub!(/# (>>|~>)[^\n]*\n/, ""); 150: annotated.gsub!(MULTI_LINE_RE) { |l| 151: annotated_multi_line(l, $1, $3, runtime_data, idx += 1) 152: } 153: ret = final_decoration(annotated, output) 154: if @output_stdout and (s = stdout.read) != "" 155: ret << s.inject(""){|s,line| s + "# >> #{line}".chomp + "\n" } 156: end 157: ret 158: end
# File lib/rcodetools/xmpfilter.rb, line 160 160: def annotated_line(line, expression, runtime_data, idx) 161: "#{expression} # => " + (runtime_data.results[idx].map{|x| x[1]} || []).join(", ") 162: end
# File lib/rcodetools/xmpfilter.rb, line 164 164: def annotated_multi_line(line, expression, indent, runtime_data, idx) 165: pretty = (runtime_data.results[idx].map{|x| x[1]} || []).join(", ") 166: first, *rest = pretty.to_a 167: rest.inject("#{expression}\n#{indent}# => #{first || "\n"}") {|s, l| s << "#{indent}# " << l } 168: end
# File lib/rcodetools/xmpfilter.rb, line 113 113: def common_path(a, b) 114: (a.split(File::Separator) & b.split(File::Separator)).join(File::Separator) 115: end
# File lib/rcodetools/xmpfilter.rb, line 338 338: def debugprint(*args) 339: $stderr.puts(*args) if $DEBUG 340: end
# File lib/rcodetools/xmpfilter.rb, line 278 278: def execute(code) 279: __send__ @interpreter_info.execute_method, code 280: end
# File lib/rcodetools/xmpfilter.rb, line 247 247: def execute_popen(code) 248: require 'open3' 249: stdin, stdout, stderr = Open3::popen3(*interpreter_command) 250: stdin.puts code 251: @evals.each{|x| stdin.puts x } unless @evals.empty? 252: stdin.close 253: [stdout, stderr] 254: end
# File lib/rcodetools/xmpfilter.rb, line 210 210: def execute_ruby(code) 211: meth = (windows? or @execute_ruby_tmpfile) ? :execute_tmpfile : :execute_popen 212: __send__ meth, code 213: end
# File lib/rcodetools/xmpfilter.rb, line 256 256: def execute_script(code) 257: path = File.expand_path("xmpfilter.tmpfile_#{Process.pid}.rb", Dir.tmpdir) 258: File.open(path, "w"){|f| f.puts code} 259: at_exit { File.unlink path if File.exist? path} 260: stdout_path, stderr_path = (1..2).map do |i| 261: fname = "xmpfilter.tmpfile_#{Process.pid}-#{i}.rb" 262: File.expand_path(fname, Dir.tmpdir) 263: end 264: args = *(interpreter_command << %["#{path}"] << "2>" << 265: %["#{stderr_path}"] << ">" << %["#{stdout_path}"]) 266: system(args.join(" ")) 267: 268: [stdout_path, stderr_path].map do |fullname| 269: f = File.open(fullname, "r") 270: at_exit { 271: f.close unless f.closed? 272: File.unlink fullname if File.exist? fullname 273: } 274: f 275: end 276: end
# File lib/rcodetools/xmpfilter.rb, line 215 215: def execute_tmpfile(code) 216: ios = ]_ stdin stdout stderr] 217: stdin, stdout, stderr = (1..3).map do |i| 218: fname = if $DEBUG 219: "xmpfilter.tmpfile_#{ios[i]}.rb" 220: else 221: "xmpfilter.tmpfile_#{Process.pid}-#{i}.rb" 222: end 223: f = File.open(fname, "w+") 224: at_exit { f.close unless f.closed?; File.unlink fname unless $DEBUG} 225: f 226: end 227: stdin.puts code 228: stdin.close 229: @stdin_path = File.expand_path stdin.path 230: exe_line = $stdout.reopen('#{File.expand_path(stdout.path)}', 'w') $stderr.reopen('#{File.expand_path(stderr.path)}', 'w') $0 = '#{File.expand_path(stdin.path)}' ARGV.replace(#{@options.inspect}) load #{File.expand_path(stdin.path).inspect} #{@evals.join(";")}.map{|l| l.strip}.join(";") 231: debugprint "execute command = #{(interpreter_command << "-e" << exe_line).join ' '}" 232: 233: oldpwd = Dir.pwd 234: @interpreter_info.chdir_proc and @interpreter_info.chdir_proc.call 235: system(*(interpreter_command << "-e" << exe_line)) 236: Dir.chdir oldpwd 237: [stdout, stderr] 238: end
# File lib/rcodetools/xmpfilter.rb, line 291 291: def extract_data(output) 292: results = Hash.new{|h,k| h[k] = []} 293: exceptions = Hash.new{|h,k| h[k] = []} 294: bindings = Hash.new{|h,k| h[k] = []} 295: output.grep(XMP_RE).each do |line| 296: result_id, op, result = XMP_RE.match(line).captures 297: case op 298: when "=>" 299: klass, value = /(\S+)\s+(.*)/.match(result).captures 300: results[result_id.to_i] << [klass, value.gsub(/PPPROTECT/, "\n")] 301: when "~>" 302: exceptions[result_id.to_i] << result 303: when "==>" 304: bindings[result_id.to_i] << result unless result.index(VAR) 305: end 306: end 307: RuntimeData.new(results, exceptions, bindings) 308: end
# File lib/rcodetools/xmpfilter.rb, line 310 310: def final_decoration(code, output) 311: warnings = {} 312: output.join.grep(WARNING_RE).map do |x| 313: md = WARNING_RE.match(x) 314: warnings[md[1].to_i] = md[2] 315: end 316: idx = 0 317: ret = code.map do |line| 318: w = warnings[idx+=1] 319: if @warnings 320: w ? (line.chomp + " # !> #{w}") : line 321: else 322: line 323: end 324: end 325: output = output.reject{|x| /^-:[0-9]+: warning/.match(x)} 326: if exception = /^-e?:[0-9]+:.*|^(?!!XMP)[^\n]+:[0-9]+:in .*/.match(output.join) 327: err = exception[0] 328: err.gsub!(Regexp.union(@stdin_path), '-') if @stdin_path 329: ret << err.map{|line| "# ~> " + line } 330: end 331: ret 332: end
# File lib/rcodetools/xmpfilter.rb, line 103 103: def get_test_method_from_lineno(filename, lineno) 104: lines = File.readlines(filename) 105: (lineno-1).downto(0) do |i| 106: if lines[i] =~ /^ *def *(test_[A-Za-z0-9?!_]+)$/ 107: return $1 108: end 109: end 110: nil 111: end
# File lib/rcodetools/xmpfilter.rb, line 89 89: def initialize_for_test_script(test_script, test_method, filename) 90: test_script.replace File.expand_path(test_script) 91: filename.replace File.expand_path(filename) 92: unless test_script == filename 93: basedir = common_path(test_script, filename) 94: relative_filename = filename[basedir.length+1 .. 1].sub(%^lib/!, '') 95: @evals << %$LOADED_FEATURES << #{relative_filename.dump}! 96: @evals << safe_require_code('test/unit') 97: @evals << %load #{test_script.dump}! 98: end 99: test_method = get_test_method_from_lineno(test_script, test_method.to_i) if test_method =~ /^\d/ 100: @evals << %Test::Unit::AutoRunner.run(false, nil, ["-n", #{test_method.dump}])! if test_method 101: end
# File lib/rcodetools/xmpfilter.rb, line 85 85: def initialize_rbtest 86: @interpreter_info = INTERPRETER_RBTEST 87: end
# File lib/rcodetools/xmpfilter.rb, line 79 79: def initialize_rct_fork 80: if Fork::run? 81: @interpreter_info = INTERPRETER_FORK 82: end 83: end
# File lib/rcodetools/xmpfilter.rb, line 282 282: def interpreter_command 283: r = [ @interpreter ] + @interpreter_info.options 284: r << "-d" if $DEBUG and @interpreter_info.accept_debug 285: r << "-I#{@include_paths.join(":")}" if @interpreter_info.accept_include_paths and !@include_paths.empty? 286: @libs.each{|x| r << "-r#{x}" } unless @libs.empty? 287: (r << "-").concat @options unless @options.empty? 288: r 289: end
# File lib/rcodetools/xmpfilter.rb, line 334 334: def oneline_ize(code) 335: "((" + code.gsub(/\r?\n|\r/, ';') + "));#{@postfix}\n" 336: end
# File lib/rcodetools/xmpfilter.rb, line 170 170: def prepare_line_annotation(expr, idx, multi_line=false) 171: v = "#{VAR}" 172: blocal = "__#{VAR}" 173: blocal2 = "___#{VAR}" 174: lastmatch = "____#{VAR}" 175: if multi_line 176: pp = safe_require_code "pp" 177: result = "((begin; #{lastmatch} = $~; PP.pp(#{v}, '', #{@width-5}).gsub(/\\r?\\n/, 'PPPROTECT'); ensure; $~ = #{lastmatch} end))" 178: else 179: pp = '' 180: result = "#{v}.inspect" 181: end 182: oneline_ize(#{pp}#{v} = (#{expr})$stderr.puts("#{MARKER}[#{idx}] => " + #{v}.class.to_s + " " + #{result}) || begin $stderr.puts local_variables local_variables.each{|#{blocal}| #{blocal2} = eval(#{blocal}) if #{v} == #{blocal2} && #{blocal} != %#{expr}.strip $stderr.puts("#{MARKER}[#{idx}] ==> " + #{blocal}) elsif [#{blocal2}] == #{v} $stderr.puts("#{MARKER}[#{idx}] ==> [" + #{blocal} + "]") end } nilrescue Exception nilend || #{v}).chomp 183: 184: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.