Ruby Codeを調べて、defやclassのロケーション情報をYAML形式で保存

http://jp.rubyist.net/magazine/?0009-YAML
を参考に.

YAMLの練習.YAMLは、後で、名前からメソッドやクラスへ移動する際に利用する.
どんなYAMLフォーマットで保存しようか考えるのは、面白かった.

  • 配列は、indexを自動にふってくれる
  • 配列は、indexを使った検索が得意
  • ハッシュは 、keyとvalueの集まりを作れば、データ構造が表現できる
  • ハッシュは、keyを使った探索が得意

まぁ普通の話なんだけど、YAML形式で保存って、上記の特性をうまく組み合わせるということなのかなと.

require File.dirname(__FILE__) + "/config"
require "yaml"

module QuickMate
  module Tag
    class Generator
      def initialize(conf = $config)
        @conf = conf
        @conf[:project_dir] ||= File.dirname(__FILE__)
      end
      
      def run
        converter = YamlConverter.new
        Dir.glob("#{@conf[:project_dir]}/**/*.rb").each do |file_name|
          converter.visit(file_name)
        end
        File.open("#{@conf[:tag_yaml]}", "w") do |file|
          file.puts converter.to_yaml
        end
        puts "created #{@conf[:tag_yaml]}"
      end
    end
    
    class YamlConverter
      def initialize
        @locations = []
        @paths = []
        @name_locationids = {}
        #TODO molude Hoge::Fugaに対応すること
        @regular = /^\s*(class|def|module)\s*(\w*).*$/
      end
      
      def visit(file_name)
        File.open(file_name) do |file|
          each_file(file)
        end
      end

      def each_file(file)
        file.each_with_index do |line, index|
          if m = @regular.match(line)
            name = m[2].to_s
            path = File.expand_path(file.path)
            @paths << path unless @paths.include?(path)
            @name_locationids[name] ||= []
            @name_locationids[name] << @locations.size 
            @locations << {  
              :path_id => @paths.index(path),
              :line => index + 1, }
          end
        end
      end
      
      def to_yaml
        YAML.dump({
                    :name_locationids => @name_locationids, 
                    :paths => @paths, 
                    :locations => @locations})
      end
    end
  end
end

クラス名とかは、散々考えたけどいいのが出てこなかった