diff --git a/guides/source/command_line.md b/guides/source/command_line.md index 8949ef4c78..57283f7c40 100644 --- a/guides/source/command_line.md +++ b/guides/source/command_line.md @@ -411,7 +411,7 @@ The `doc:` namespace has the tools to generate documentation for your app, API d ### `notes` -`rake notes` will search through your code for comments beginning with FIXME, OPTIMIZE or TODO. The search is done in files with extension `.builder`, `.rb`, `.erb`, `.haml`, `.slim`, `.css`, `.scss`, `.js`, `.coffee`, `.rake`, `.sass` and `.less` for both default and custom annotations. +`rake notes` will search through your code for comments beginning with FIXME, OPTIMIZE or TODO. The search is done in files with extension `.builder`, `.rb`, `.rake`, `.yml`, `.yaml`, `.ruby`, `.css`, `.js` and `.erb` for both default and custom annotations. ```bash $ rake notes @@ -425,6 +425,12 @@ app/models/school.rb: * [ 17] [FIXME] ``` +You can add support for new file extensions using `config.annotations.register_extensions` option, which receives a list of the extensions with its corresponding regex to match it up. + +```ruby +config.annotations.register_extensions("scss", "sass", "less") { |annotation| /\/\/\s*(#{annotation}):?\s*(.*)$/ } +``` + If you are looking for a specific annotation, say FIXME, you can use `rake notes:fixme`. Note that you have to lower case the annotation's name. ```bash diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 35b3a379ae..b52b80e802 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,11 @@ +* Add public API to register new extensions for `rake notes`. + + Example: + + config.annotations.register_extensions("scss", "sass") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ } + + *Roberto Miranda* + * Removed unnecessary `rails application` command. *Arun Agrawal* diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 20e3de32aa..9aec2f9734 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/kernel/reporting' require 'active_support/file_update_checker' require 'rails/engine/configuration' +require 'rails/source_annotation_extractor' module Rails class Application @@ -149,6 +150,9 @@ def session_store(*args) end end + def annotations + SourceAnnotationExtractor::Annotation + end end end end diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index 83e28090f8..201532d299 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -18,6 +18,20 @@ def self.directories @@directories ||= %w(app config db lib test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',') end + def self.extensions + @@extensions ||= {} + end + + # Registers new Annotations File Extensions + # SourceAnnotationExtractor::Annotation.register_extensions("css", "scss", "sass", "less", "js") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ } + def self.register_extensions(*exts, &block) + extensions[/\.(#{exts.join("|")})$/] = block + end + + register_extensions("builder", "rb", "rake", "yml", "yaml", "ruby") { |tag| /#\s*(#{tag}):?\s*(.*)$/ } + register_extensions("css", "js") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ } + register_extensions("erb") { |tag| /<%\s*#\s*(#{tag}):?\s*(.*?)\s*%>/ } + # Returns a representation of the annotation that looks like this: # # [126] [TODO] This algorithm is simple and clearly correct, make it faster. @@ -78,21 +92,14 @@ def find_in(dir) if File.directory?(item) results.update(find_in(item)) else - pattern = - case item - when /\.(builder|rb|coffee|rake)$/ - /#\s*(#{tag}):?\s*(.*)$/ - when /\.(css|scss|sass|less|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 + extension = Annotation.extensions.detect do |regexp, _block| + regexp.match(item) + end + + if extension + pattern = extension.last.call(tag) + results.update(extract_annotations_from(item, pattern)) if pattern + end end end diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index b39cd3747b..b11fd55170 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -793,5 +793,15 @@ def index assert ActiveRecord::Base.dump_schema_after_migration end + + test "config.annotations wrapping SourceAnnotationExtractor::Annotation class" do + make_basic_app do |app| + app.config.annotations.register_extensions("coffee") do |tag| + /#\s*(#{tag}):?\s*(.*)$/ + end + end + + assert_not_nil SourceAnnotationExtractor::Annotation.extensions[/\.(coffee)$/] + end end end diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb index 05f6338b68..df5615be1c 100644 --- a/railties/test/application/rake/notes_test.rb +++ b/railties/test/application/rake/notes_test.rb @@ -1,4 +1,5 @@ require "isolation/abstract_unit" +require 'rails/source_annotation_extractor' module ApplicationTests module RakeTests @@ -18,17 +19,14 @@ def teardown test 'notes finds notes for certain file_types' do app_file "app/views/home/index.html.erb", "<% # TODO: note in erb %>" - app_file "app/views/home/index.html.haml", "-# TODO: note in haml" - app_file "app/views/home/index.html.slim", "/ TODO: note in slim" - app_file "app/assets/javascripts/application.js.coffee", "# TODO: note in coffee" app_file "app/assets/javascripts/application.js", "// TODO: note in js" app_file "app/assets/stylesheets/application.css", "// TODO: note in css" - app_file "app/assets/stylesheets/application.css.scss", "// TODO: note in scss" - app_file "app/assets/stylesheets/application.css.sass", "// TODO: note in sass" - app_file "app/assets/stylesheets/application.css.less", "// TODO: note in less" app_file "app/controllers/application_controller.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in ruby" app_file "lib/tasks/task.rake", "# TODO: note in rake" app_file 'app/views/home/index.html.builder', '# TODO: note in builder' + app_file 'config/locales/en.yml', '# TODO: note in yml' + app_file 'config/locales/en.yaml', '# TODO: note in yaml' + app_file "app/views/home/index.ruby", "# TODO: note in ruby" boot_rails require 'rake' @@ -42,19 +40,15 @@ def teardown lines = output.scan(/\[([0-9\s]+)\](\s)/) assert_match(/note in erb/, output) - assert_match(/note in haml/, output) - assert_match(/note in slim/, output) - assert_match(/note in ruby/, output) - assert_match(/note in coffee/, output) assert_match(/note in js/, output) assert_match(/note in css/, output) - assert_match(/note in scss/, output) - assert_match(/note in sass/, output) - assert_match(/note in less/, output) assert_match(/note in rake/, output) assert_match(/note in builder/, output) + assert_match(/note in yml/, output) + assert_match(/note in yaml/, output) + assert_match(/note in ruby/, output) - assert_equal 12, lines.size + assert_equal 9, lines.size lines.each do |line| assert_equal 4, line[0].size @@ -175,6 +169,28 @@ def teardown end end + test 'register a new extension' do + add_to_config %q{ config.annotations.register_extensions("scss", "sass") { |annotation| /\/\/\s*(#{annotation}):?\s*(.*)$/ } } + app_file "app/assets/stylesheets/application.css.scss", "// TODO: note in scss" + app_file "app/assets/stylesheets/application.css.sass", "// TODO: note in sass" + + boot_rails + + require 'rake' + require 'rdoc/task' + require 'rake/testtask' + + Rails.application.load_tasks + + Dir.chdir(app_path) do + output = `bundle exec rake notes` + lines = output.scan(/\[([0-9\s]+)\]/).flatten + assert_match(/note in scss/, output) + assert_match(/note in sass/, output) + assert_equal 2, lines.size + end + end + private def boot_rails super