lib/review/preprocessor.rb in review-2.3.0 vs lib/review/preprocessor.rb in review-2.4.0

- old
+ new

@@ -1,11 +1,8 @@ +# Copyright (c) 2010-2017 Minero Aoki, Kenshi Muto +# 2002-2009 Minero Aoki # -# $Id: preprocessor.rb 4250 2009-05-24 14:03:01Z aamine $ -# -# Copyright (c) 2002-2009 Minero Aoki -# Copyright (c) 2010 Minero Aoki, Kenshi Muto -# # This program is free software. # You can distribute or modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # For details of the GNU LGPL, see the file "COPYING". # @@ -13,51 +10,44 @@ require 'review/textutils' require 'review/exception' require 'nkf' module ReVIEW - module ErrorUtils - - def init_ErrorUtils(f) + def init_errorutils(f) @errutils_file = f @errutils_err = false end def warn(msg) - $stderr.puts "#{location()}: warning: #{msg}" + @logger.warn "#{location}: #{msg}" end def error(msg) @errutils_err = true - raise ApplicationError, "#{location()}: #{msg}" + raise ApplicationError, "#{location}: #{msg}" end def location - "#{filename()}:#{lineno()}" + "#{filename}:#{lineno}" end def filename @errutils_file.path end def lineno @errutils_file.lineno end - end - class Preprocessor - include ErrorUtils - def Preprocessor.strip(f) + def self.strip(f) buf = '' - Strip.new(f).each do |line| - buf << line.rstrip << "\n" - end + Strip.new(f).each { |line| buf << line.rstrip << "\n" } buf end class Strip def initialize(f) @@ -71,16 +61,13 @@ def lineno @f.lineno end def gets - while line = @f.gets - if /\A\#@/ =~ line - return "\#@\#\n" - else - return line - end + @f.each_line do |line| + return "\#@\#\n" if /\A\#@/ =~ line + return line end nil end def each @@ -91,29 +78,30 @@ end def initialize(repo, param) @repository = repo @config = param + @logger = ReVIEW.logger end def process(inf, outf) - init_ErrorUtils inf + init_errorutils inf @f = outf begin preproc inf rescue Errno::ENOENT => err error err.message end end private - TYPES = %w(file range) + TYPES = %w[file range].freeze def preproc(f) init_vars - while line = f.gets + f.each_line do |line| case line when /\A\#@\#/, /\A\#\#\#\#/ @f.print line when /\A\#@defvar/ @@ -122,13 +110,11 @@ defvar(*direc.args) when /\A\#@mapoutput/ direc = parse_directive(line, 1, 'stderr') @f.print line - get_output(expand(direc.arg), direc['stderr']).each do |out| - @f.print out.string - end + get_output(expand(direc.arg), direc['stderr']).each { |out| @f.print out.string } skip_list f when /\A\#@mapfile/ direc = parse_directive(line, 1, 'eval') path = expand(direc.arg) @@ -138,32 +124,31 @@ when /\A\#@map(?:range)?/ direc = parse_directive(line, 2, 'unindent') path = expand(direc.args[0]) ent = @repository.fetch_range(path, direc.args[1]) or - error "unknown range: #{path}: #{direc.args[1]}" + error "unknown range: #{path}: #{direc.args[1]}" ent = (direc['unindent'] ? unindent(ent, direc['unindent']) : ent) replace_block(f, line, ent, false) # FIXME: turn off lineno: tmp when /\A\#@end/ error 'unbaranced #@end' when /\A\#@/ op = line.slice(/@(\w+)/, 1) - #error "unkown directive: #{line.strip}" unless known_directive?(op) - warn "unkown directive: #{line.strip}" unless known_directive?(op) + warn "unknown directive: #{line.strip}" unless known_directive?(op) @f.print line when /\A\s*\z/ # empty line @f.puts else @f.print line end end end - KNOWN_DIRECTIVES = %w(require provide warn ok) + KNOWN_DIRECTIVES = %w[require provide warn ok].freeze def known_directive?(op) KNOWN_DIRECTIVES.index(op) end @@ -180,23 +165,23 @@ @f.printf '%4s ', (num ? num.to_s : '') end def skip_list(f) begline = f.lineno - while line = f.gets + f.each_line do |line| case line - when %r[\A\#@end] + when /\A\#@end/ @f.print line - return - when %r[\A//\}] + return nil + when %r{\A//\}} warn '//} seen in list' @f.print line - return - when %r[\A\#@\w] + return nil + when /\A\#@\w/ warn "#{line.slice(/\A\#@\w+/)} seen in list" @f.print line - when %r[\A\#@] + when /\A\#@/ @f.print line end end error "list reached end of file (beginning line = #{begline})" end @@ -225,19 +210,19 @@ end end def parse_directive(line, argc, *optdecl) m = /\A\#@(\w+)\((.*?)\)(?:\[(.*?)\])?\z/.match(line.strip) or - error "wrong directive: #{line.strip}" + error "wrong directive: #{line.strip}" op = m[1] args = m[2].split(/,\s*/) opts = parse_optargs(m[3]) return if argc == 0 and args.empty? if argc == -1 # Any number of arguments are allowed. elsif args.size != argc - error "wrong arg size" + error 'wrong arg size' end if opts wrong_opts = opts.keys - optdecl unless wrong_opts.empty? error "wrong option: #{wrong_opts.keys.join(' ')}" @@ -248,11 +233,11 @@ def parse_optargs(str) return nil unless str table = {} str.split(/,\s*/).each do |a| - name, spec = a.split(/=/, 2) + name, spec = a.split('=', 2) table[name] = optarg_value(spec) end table end @@ -275,69 +260,63 @@ def defvar(name, value) @vartable[name] = value end def expand(str) - str.gsub(/\$\w+/) {|name| + str.gsub(/\$\w+/) do |name| s = @vartable[name.sub('$', '')] s ? expand(s) : name - } + end end def unindent(chunk, n) - n = minimum_indent(chunk) unless n.kind_of?(Integer) + n = minimum_indent(chunk) unless n.is_a?(Integer) re = /\A#{' ' * n}/ - chunk.map {|line| line.edit {|s| s.sub(re,'') } } + chunk.map { |line| line.edit { |s| s.sub(re, '') } } end INF_INDENT = 9999 def minimum_indent(chunk) - n = chunk.map {|line| line.empty? ? INF_INDENT : line.num_indent }.min + n = chunk.map { |line| line.empty? ? INF_INDENT : line.num_indent }.min n == INF_INDENT ? 0 : n end def evaluate(path, chunk) - outputs = get_output("ruby #{path}", false).split(/\n/).map {|s| s.strip } - chunk.map {|line| + outputs = get_output("ruby #{path}", false).split(/\n/).map(&:strip) + chunk.map do |line| if /\# \$\d+/ =~ line.string # map result into source. - line.edit {|s| - s.sub(/\$(\d+)/) { outputs[$1.to_i - 1] } - } + line.edit { |s| s.sub(/\$(\d+)/) { outputs[$1.to_i - 1] } } else line end - } + end end require 'open3' def get_output(cmd, use_stderr) out = err = nil - Open3.popen3(cmd) {|stdin, stdout, stderr| + Open3.popen3(cmd) do |_stdin, stdout, stderr| out = stdout.readlines if use_stderr out.concat stderr.readlines else err = stderr.readlines end - } + end if err and !err.empty? - $stderr.puts "[unexpected stderr message]" - err.each do |line| - $stderr.print line - end - error "get_output: got unexpected output" + $stderr.puts '[unexpected stderr message]' + err.each { |line| $stderr.print line } + error 'get_output: got unexpected output' end num = 0 - out.map {|line| Line.new(num += 1, line) } + out.map { |line| Line.new(num += 1, line) } end - end - class Line def initialize(number, string) @number = number @string = string end @@ -357,19 +336,18 @@ def num_indent @string.slice(/\A\s*/).size end end - class Repository - include TextUtils include ErrorUtils def initialize(param) @repository = {} @config = param + @logger = ReVIEW.logger end def fetch_file(file) file_descripter(file)['file'] end @@ -395,26 +373,26 @@ fname.start_with?('git|') end def parse_git_blob(g_obj) IO.popen('git show ' + g_obj.sub(/\Agit\|/, ''), 'r') do |f| - init_ErrorUtils f + init_errorutils f return _parse_file(f) end end def parse_file(fname) - File.open(fname, 'r:BOM|utf-8') {|f| - init_ErrorUtils f + File.open(fname, 'r:BOM|utf-8') do |f| + init_errorutils f return _parse_file(f) - } + end end def _parse_file(f) whole = [] - repo = {'file' => whole} - curr = {'WHOLE' => whole} + repo = { 'file' => whole } + curr = { 'WHOLE' => whole } lineno = 1 yacchack = false # remove ';'-only lines. opened = [['(not opened)', '(not opened)']] * 3 f.each do |line| @@ -428,89 +406,74 @@ key = "#{type}/#{spec}" error "begin x2: #{key}" if curr[key] (repo[type] ||= {})[spec] = curr[key] = [] when 'end' curr.delete("#{type}/#{spec}") or - error "end before begin: #{type}/#{spec}" + error "end before begin: #{type}/#{spec}" else raise 'must not happen' end - when %r<(?:\A\#@|\#@@)([a-z]+)/(\w+)\{> + when %r{(?:\A\#@|\#@@)([a-z]+)/(\w+)\{} type = check_type($1) spec = check_spec($2) key = "#{type}/#{spec}" error "begin x2: #{key}" if curr[key] (repo[type] ||= {})[spec] = curr[key] = [] opened.push [type, spec] - when %r<(?:\A\#@|\#@@)([a-z]+)/(\w+)\}> + when %r{(?:\A\#@|\#@@)([a-z]+)/(\w+)\}} type = check_type($1) spec = check_spec($2) curr.delete("#{type}/#{spec}") or - error "end before begin: #{type}/#{spec}" + error "end before begin: #{type}/#{spec}" opened.delete "#{type}/#{spec}" - when %r<(?:\A\#@|\#@@)\}> + when /(?:\A\#@|\#@@)\}/ type, spec = opened.last curr.delete("#{type}/#{spec}") or - error "closed before open: #{type}/#{spec}" + error "closed before open: #{type}/#{spec}" opened.pop when /(?:\A\#@|\#@@)yacchack/ yacchack = true when /\A\#@-/ # does not increment line number. line = canonical($') - curr.each_value do |list| - list.push Line.new(nil, line) - end + curr.each_value { |list| list.push Line.new(nil, line) } else next if yacchack and line.strip == ';' line = canonical(line) - curr.each_value do |list| - list.push Line.new(lineno, line) - end + curr.each_value { |list| list.push Line.new(lineno, line) } lineno += 1 end end if curr.size > 1 curr.delete 'WHOLE' - curr.each do |range, lines| - $stderr.puts "#{filename()}: unclosed range: #{range} (begin @#{lines.first.number})" - end - raise ApplicationError, "ERROR" + curr.each { |range, lines| @logger.warn "#{filename}: unclosed range: #{range} (begin @#{lines.first.number})" } + raise ApplicationError, 'ERROR' end repo end def canonical(line) - tabwidth = 8 - if @config['tabwidth'] - tabwidth = @config['tabwidth'] - end + tabwidth = @config['tabwidth'] || 8 if tabwidth > 0 detab(line, tabwidth).rstrip + "\n" else line end end def check_type(type) - unless Preprocessor::TYPES.index(type) - error "wrong type: #{type.inspect}" - end + error "wrong type: #{type.inspect}" unless Preprocessor::TYPES.index(type) type end def check_spec(spec) - unless /\A\w+\z/ =~ spec - error "wrong spec: #{spec.inspect}" - end + error "wrong spec: #{spec.inspect}" unless /\A\w+\z/ =~ spec spec end - end - end