跳轉至內文 跳轉至搜尋

實作 Rails::Command::NotesCommand 背後的邏輯。關於用法資訊,請參閱 rails notes --help

Annotation 物件是三聯集 :line:tag:text,顯示註解出現的行號、標籤和文字。請注意不儲存檔案名稱。

在註解和模組空白中尋找註解,它們必須以標籤為開頭,接著可以加上冒號。那一行結尾的所有內容 (或結束 ERB 註解標籤) 都視為其文字。

命名空間
方法
D
E
F
N

屬性

[R] tag

類別公用方法

enumerate(tag = nil, options = {})

列印所有標籤為 tag 的註解,其位於根目錄 appconfigdblibtest 下 (遞迴)。

如果 tagnil,列印具有預設或已註冊標籤的註解。

可使用 options 中的 :dirs 鍵明確設定特定目錄。

Rails::SourceAnnotationExtractor.enumerate 'TODO|FIXME', dirs: %w(app lib), tag: true

如果 options:tag 旗標,它會傳遞給所有註解的 to_s

查看 SourceAnnotationExtractor#find_in 以取得會列入考慮的檔案副檔名清單。

此類別方法是 rails notes 指令的單一進入點。

# File railties/lib/rails/source_annotation_extractor.rb, line 145
def self.enumerate(tag = nil, options = {})
  tag ||= Annotation.tags.join("|")
  extractor = new(tag)
  dirs = options.delete(:dirs) || Annotation.directories
  extractor.display(extractor.find(dirs), options)
end

new(tag)

# File railties/lib/rails/source_annotation_extractor.rb, line 154
def initialize(tag)
  @tag = tag
end

執行個體公用方法

display(results, options = {})

依檔案名稱列印 results 中從檔案名稱對應到註解的對應,並依檔案名稱排序。options hash 傳遞給所有註解的 to_s

# File railties/lib/rails/source_annotation_extractor.rb, line 203
def display(results, options = {})
  options[:indent] = results.flat_map { |f, a| a.map(&:line) }.max.to_s.size
  results.keys.sort.each do |file|
    puts "#{file}:"
    results[file].each do |note|
      puts "  * #{note.to_s(options)}"
    end
    puts
  end
end

find(dirs)

傳回一個雜湊,用於將檔案名稱對映到 dirs (遞迴) 下包含其註解的陣列。

# File railties/lib/rails/source_annotation_extractor.rb, line 160
def find(dirs)
  dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
end

find_in(dir)

傳回一個雜湊,用於將檔案名稱對映到 dir (遞迴) 下包含其註解的陣列。將符合在 Rails::SourceAnnotationExtractor::Annotation.extensions 註冊之副檔名的檔案納入考量範圍。僅包含具有註解的檔案。

# File railties/lib/rails/source_annotation_extractor.rb, line 168
def find_in(dir)
  results = {}

  Dir.glob("#{dir}/*") do |item|
    next if File.basename(item).start_with?(".")

    if File.directory?(item)
      results.update(find_in(item))
    else
      extension = Annotation.extensions.detect do |regexp, _block|
        regexp.match(item)
      end

      if extension
        pattern = extension.last.call(tag)

        # In case a user-defined pattern returns nothing for the given set
        # of tags, we exit early.
        next unless pattern

        # If a user-defined pattern returns a regular expression, we will
        # wrap it in a PatternExtractor to keep the same API.
        pattern = PatternExtractor.new(pattern) if pattern.is_a?(Regexp)

        annotations = pattern.annotations(item)
        results.update(item => annotations) if annotations.any?
      end
    end
  end

  results
end