File: reader/reader.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: TmDoc#11
  module: Reader#13
has properties
module method: read / 4 #64
module method: read_source / 3 #125
module method: check_file / 3 #154
module method: valid_file_path? / 4 #178
  class: FileItem#15
includes
  Comparable ( Builtin-Module )
inherits from
  Abstract ( TmStd::Lsm::Product )
has properties
attribute: expand_path [R] #18
attribute: name [R] #18
attribute: index [R] #18
attribute: hash [R] #19
method: initialize / 3 #22
method: eql? / 1 #36
method: freeze_equality! #44
method: <=> / 1 #49
  class: SetOfFileItem#59
inherits from
  Abstract ( TmStd::Lsm::Collection::Set )
has properties
constant: LSM_ELEMENT_CLASS #60

Code

   1  # $Id: reader.rb,v 1.12 2011/12/15 02:20:43 machan Exp $
   2 
   3  require 'tmdoc/tmstd'
   4  require 'tmdoc/constant'
   5  require 'tmdoc/environment'
   6  require 'tmdoc/model/core'
   7  require 'tmdoc/reader/ruby1.8/scanner'
   8  require 'tmdoc/reader/ruby1.8/parser'
   9 
  10 
  11  module TmDoc
  12 
  13  module Reader
  14 
  15  class FileItem < TmStd::Lsm::Product::Abstract
  16      include Comparable
  17 
  18      attr_reader :expand_path, :name, :index
  19      attr_reader :hash
  20 
  21 
  22      def initialize(expand_path, name, index)
  23          ASSERT.kind_of expand_path, String
  24          ASSERT.kind_of name,        String
  25          ASSERT.kind_of index,       Integer
  26 
  27          @expand_path    = expand_path
  28          @name           = name
  29          @index          = index
  30 
  31          @expand_path.freeze
  32          @hash = self.expand_path.hash
  33      end
  34 
  35 
  36      def eql?(other)
  37          result =    self.class          >= other.class &&
  38                      self.expand_path    == other.expand_path
  39 
  40          ASSERT.boolean result
  41      end
  42 
  43 
  44      def freeze_equality!
  45          nil     # Nop, already frozen.
  46      end
  47 
  48 
  49      def <=>(other)
  50          ASSERT.kind_of other, FileItem
  51 
  52          result = self.index <=> other.index
  53 
  54          ASSERT.kind_of result, Integer
  55      end
  56  end
  57 
  58 
  59  class SetOfFileItem < TmStd::Lsm::Collection::Set::Abstract
  60      LSM_ELEMENT_CLASS = FileItem
  61  end
  62 
  63 
  64      def self.read(dir_name, file_names, env, &logger)
  65          ASSERT.kind_of      dir_name,   String
  66          ASSERT.kind_of      file_names, LSM::SeqOfString
  67          ASSERT.kind_of      env,            ENV::Environment
  68          ASSERT.opt_kind_of  logger,         Proc
  69 
  70          LOG::Debug.msgout "CALLED" if env.debug?
  71 
  72          set_of_file_item = file_names.map_with_index { |file_name, index|
  73              [file_name, index]
  74          }.inject(SetOfFileItem.new) { |set, pair|
  75              ASSERT.tuple_of pair, [String, Integer]
  76              file_name, index = pair
  77 
  78              expand_file_path = self.check_file dir_name, file_name, env
  79              if expand_file_path
  80                  file_item = FileItem.new(
  81                      expand_file_path, file_name, index
  82                  )
  83 
  84                  unless set.include?(file_item)
  85                      set << file_item
  86                  else
  87                      LOG::Error.log(
  88                          "Source file duplication: '%s'", expand_file_path
  89                      )
  90                      CMD.test_sensitive_level env, LOG::Error
  91 
  92                      set
  93                  end
  94              else
  95                  set
  96              end
  97          }
  98 
  99          mc_array_of_file = set_of_file_item.sort.map { |file_item|
 100              file_name = file_item.name
 101              logger.call(file_name) if logger
 102 
 103              mc_toplevel_module = self.read_source(
 104                  file_item.expand_path, file_name, env
 105              )
 106 
 107              if mc_toplevel_module
 108                  MCP::File.new(
 109                      file_name, file_item.index, mc_toplevel_module
 110                  )
 111              else
 112                  nil
 113              end
 114          }.compact
 115 
 116          if mc_array_of_file.empty?
 117              LOG::Error.log "None applicatable source file."
 118              CMD.test_sensitive_level env, LOG::Error
 119          end
 120 
 121          MC::Store.new MCP::SetOfFile.new(mc_array_of_file)
 122      end
 123 
 124 
 125      def self.read_source(expand_file_path, input_file_name, env)
 126          ASSERT.kind_of expand_file_path,    String
 127          ASSERT.kind_of input_file_name,     String
 128          ASSERT.kind_of env,                 ENV::Environment
 129 
 130          mc_toplevel_module = nil
 131          begin
 132              File.open(expand_file_path) do |input|
 133                  mc_toplevel_module = Ruby18::Parser.parse(
 134                      Ruby18::Scanner.new(input, env, input_file_name), env
 135                  )
 136              end
 137          rescue SystemCallError => exception
 138              LOG::Error.log(
 139                  "System call error in reading file\n" + "\t%s (%s)",
 140                  exception.to_s, exception.class.to_s
 141              )
 142              CMD.test_sensitive_level env, LOG::Error
 143          rescue IOError => exception
 144              LOG::Error.log "I/O error: '%s'", expand_file_path
 145              CMD.test_sensitive_level env, LOG::Error
 146          end
 147 
 148          mc_toplevel_module
 149 
 150          ASSERT.opt_kind_of mc_toplevel_module, MCLN::ToplevelModule
 151      end
 152 
 153 
 154      def self.check_file(dir_name, file_name, env)
 155          ASSERT.opt_kind_of  dir_name,   String
 156          ASSERT.opt_kind_of  file_name,  String
 157          ASSERT.kind_of      env,        ENV::Environment
 158 
 159          current_file_path   = File.expand_path './' + file_name
 160          expand_file_path    = File.expand_path dir_name + '/' + file_name
 161 
 162          if current_file_path != expand_file_path
 163              if self.valid_file_path?(
 164                  current_file_path, file_name, env, false
 165              )
 166                  return ASSERT.kind_of current_file_path, String
 167              end
 168          end
 169 
 170          if self.valid_file_path?(expand_file_path, file_name, env)
 171              return ASSERT.kind_of expand_file_path, String
 172          end
 173 
 174          nil
 175      end
 176 
 177 
 178      def self.valid_file_path?(file_path, file_name, env, does_log = true)
 179          ASSERT.opt_kind_of  file_path,  String
 180          ASSERT.opt_kind_of  file_name,  String
 181          ASSERT.kind_of      env,        ENV::Environment
 182          ASSERT.boolean      does_log
 183 
 184          unless File.exist?(file_path)
 185              if does_log
 186                  LOG::Error.log "No such file: '%s'", file_path
 187                  CMD.test_sensitive_level env, LOG::Error
 188              end
 189 
 190              return false
 191          end
 192 
 193          file_stat = File.stat(file_path)
 194          ASSERT.kind_of file_stat, File::Stat
 195 
 196          unless file_stat.file?
 197              if does_log
 198                  LOG::Error.log "Not a regular file: '%s'", file_path
 199                  CMD.test_sensitive_level env, LOG::Error
 200              end
 201 
 202              return false
 203          end
 204 
 205          unless file_stat.readable?
 206              if does_log
 207                  LOG::Error.log "Not a readable file: '%s'", file_path
 208                  CMD.test_sensitive_level env, LOG::Error
 209              end
 210 
 211              return false
 212          end
 213 
 214          true
 215      end
 216  end
 217 
 218  end # TmDoc