跳至内容 跳至搜索

实现了 Rails::Command::NotesCommand 背后的逻辑。有关用法信息,请参阅 rails notes --help

Annotation 对象是三元组 :line:tag:text,它们代表注解所在的行、其标签和其文本。请注意,文件名不会被存储。

注解在注释中被查找,并忽略空格,它们必须以标签开头,后面可以选择性地跟着一个冒号。行尾(或闭合的 ERB 注释标签)之前的所有内容都被认为是它们的文本。

命名空间
方法
D
E
F
N

Attributes

[R] tag

类公共方法

enumerate(tag = nil, options = {})

打印在根目录 appconfigdblibtest(递归)下的所有带有 tag 标签的注解。

如果 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 哈希会被传递给每个注解的 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