diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 4fd1a2369f693c4715c317e4e99e44f6434c0895..4f18f4cdd29b92b3192d69eff4ac28d0e0cb78ae 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,5 +1,11 @@ ## Rails 4.0.0 (unreleased) ## +* Allow a `:dirs` key in the `SourceAnnotationExtractor.enumerate` options + to explicitly set the directories to be traversed so it's easier to define + custom rake tasks. + + *Brian D. Burns* + * Deprecate `Rails::Generators::ActiveModel#update_attributes` in favor of `#update`. ORMs that implement `Generators::ActiveModel#update_attributes` should change diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 971fbf627b120d8d4e16d2473e8fbe3452df02e4..2cbb0a435c3ed81b36171a29866c7b93fd92ac97 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -32,15 +32,24 @@ def to_s(options={}) end # Prints all annotations with tag +tag+ under the root directories +app+, - # +config+, +lib+, and +test+ (recursively). Filenames with extension - # +.builder+, +.rb+, +.erb+, +.haml+, +.slim+, +.css+, +.scss+, +.js+, - # +.coffee+, and +.rake+ are taken into account. The +options+ hash is - # passed to each annotation's +to_s+. + # +config+, +db+, +lib+, and +test+ (recursively). + # + # Additional directories may be added using a comma-delimited list set using + # ENV['SOURCE_ANNOTATION_DIRECTORIES']. + # + # Directories may also be explicitly set using the :dirs key in +options+. + # + # SourceAnnotationExtractor.enumerate 'TODO|FIXME', dirs: %w(app lib), tag: true + # + # If +options+ has a :tag flag, it will be passed to each annotation's +to_s+. + # + # See #find_in for a list of file extensions that will be taken into account. # # This class method is the single entry point for the rake tasks. def self.enumerate(tag, options={}) extractor = new(tag) - extractor.display(extractor.find, options) + dirs = options.delete(:dirs) || Annotation.directories + extractor.display(extractor.find(dirs), options) end attr_reader :tag @@ -51,7 +60,7 @@ def initialize(tag) # Returns a hash that maps filenames under +dirs+ (recursively) to arrays # with their annotations. - def find(dirs = Annotation.directories) + def find(dirs) dirs.inject({}) { |h, dir| h.update(find_in(dir)) } end @@ -68,16 +77,22 @@ def find_in(dir) if File.directory?(item) results.update(find_in(item)) - elsif item =~ /\.(builder|rb|coffee|rake)$/ - results.update(extract_annotations_from(item, /#\s*(#{tag}):?\s*(.*)$/)) - elsif item =~ /\.(css|scss|js)$/ - results.update(extract_annotations_from(item, /\/\/\s*(#{tag}):?\s*(.*)$/)) - elsif item =~ /\.erb$/ - results.update(extract_annotations_from(item, /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/)) - elsif item =~ /\.haml$/ - results.update(extract_annotations_from(item, /-\s*#\s*(#{tag}):?\s*(.*)$/)) - elsif item =~ /\.slim$/ - results.update(extract_annotations_from(item, /\/\s*\s*(#{tag}):?\s*(.*)$/)) + else + pattern = + case item + when /\.(builder|rb|coffee|rake)$/ + /#\s*(#{tag}):?\s*(.*)$/ + when /\.(css|scss|js)$/ + /\/\/\s*(#{tag}):?\s*(.*)$/ + when /\.erb$/ + /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/ + when /\.haml$/ + /-\s*#\s*(#{tag}):?\s*(.*)$/ + when /\.slim$/ + /\/\s*\s*(#{tag}):?\s*(.*)$/ + else nil + end + results.update(extract_annotations_from(item, pattern)) if pattern end end diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb index 5893d589259775eb9c605e49b31d125d3da3cd63..3508f4225a847f69d5c82a8cd2b5ae405e3e80d0 100644 --- a/railties/test/application/rake/notes_test.rb +++ b/railties/test/application/rake/notes_test.rb @@ -130,6 +130,45 @@ def teardown end end + test 'custom rake task finds specific notes in specific directories' do + app_file "app/controllers/some_controller.rb", "# TODO: note in app directory" + app_file "lib/some_file.rb", "# OPTIMIZE: note in lib directory\n" << "# FIXME: note in lib directory" + app_file "test/some_test.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in test directory" + + app_file "lib/tasks/notes_custom.rake", <<-EOS + require 'rails/source_annotation_extractor' + task :notes_custom do + tags = 'TODO|FIXME' + opts = { dirs: %w(lib test), tag: true } + SourceAnnotationExtractor.enumerate(tags, opts) + end + EOS + + boot_rails + + require 'rake' + require 'rdoc/task' + require 'rake/testtask' + + Rails.application.load_tasks + + Dir.chdir(app_path) do + output = `bundle exec rake notes_custom` + lines = output.scan(/\[([0-9\s]+)\]/).flatten + + assert_match(/\[FIXME\] note in lib directory/, output) + assert_match(/\[TODO\] note in test directory/, output) + assert_no_match(/OPTIMIZE/, output) + assert_no_match(/note in app directory/, output) + + assert_equal 2, lines.size + + lines.each do |line_number| + assert_equal 4, line_number.size + end + end + end + private def boot_rails super