annotaterb 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +68 -0
  3. data/VERSION +1 -1
  4. data/exe/annotaterb +7 -7
  5. data/lib/annotate_rb/active_record_patch.rb +2 -0
  6. data/lib/annotate_rb/commands/annotate_models.rb +0 -1
  7. data/lib/annotate_rb/commands/annotate_routes.rb +0 -1
  8. data/lib/annotate_rb/commands/print_help.rb +0 -1
  9. data/lib/annotate_rb/commands/print_version.rb +0 -1
  10. data/lib/annotate_rb/commands.rb +4 -4
  11. data/lib/annotate_rb/config_finder.rb +1 -1
  12. data/lib/annotate_rb/config_loader.rb +2 -2
  13. data/lib/annotate_rb/core.rb +3 -3
  14. data/lib/annotate_rb/helper.rb +16 -0
  15. data/lib/annotate_rb/model_annotator/{annotation_generator.rb → annotation_builder.rb} +18 -14
  16. data/lib/annotate_rb/model_annotator/annotation_decider.rb +10 -12
  17. data/lib/annotate_rb/model_annotator/annotation_diff.rb +1 -1
  18. data/lib/annotate_rb/model_annotator/annotation_diff_generator.rb +9 -9
  19. data/lib/annotate_rb/model_annotator/annotation_pattern_generator.rb +3 -3
  20. data/lib/annotate_rb/model_annotator/annotator.rb +12 -53
  21. data/lib/annotate_rb/model_annotator/column_annotation/annotation_builder.rb +135 -0
  22. data/lib/annotate_rb/model_annotator/column_annotation/attributes_builder.rb +104 -0
  23. data/lib/annotate_rb/model_annotator/column_annotation/column_wrapper.rb +103 -0
  24. data/lib/annotate_rb/model_annotator/column_annotation/type_builder.rb +54 -0
  25. data/lib/annotate_rb/model_annotator/column_annotation.rb +12 -0
  26. data/lib/annotate_rb/model_annotator/file_builder.rb +58 -0
  27. data/lib/annotate_rb/model_annotator/file_components.rb +78 -0
  28. data/lib/annotate_rb/model_annotator/file_name_resolver.rb +3 -3
  29. data/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder.rb +57 -0
  30. data/lib/annotate_rb/model_annotator/foreign_key_annotation.rb +9 -0
  31. data/lib/annotate_rb/model_annotator/index_annotation/annotation_builder.rb +113 -0
  32. data/lib/annotate_rb/model_annotator/index_annotation.rb +9 -0
  33. data/lib/annotate_rb/model_annotator/magic_comment_parser.rb +32 -0
  34. data/lib/annotate_rb/model_annotator/model_class_getter.rb +6 -6
  35. data/lib/annotate_rb/model_annotator/model_files_getter.rb +12 -10
  36. data/lib/annotate_rb/model_annotator/model_wrapper.rb +44 -37
  37. data/lib/annotate_rb/model_annotator/pattern_getter.rb +142 -10
  38. data/lib/annotate_rb/model_annotator/project_annotation_remover.rb +65 -0
  39. data/lib/annotate_rb/model_annotator/project_annotator.rb +63 -0
  40. data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +16 -18
  41. data/lib/annotate_rb/model_annotator/single_file_annotation_remover.rb +37 -0
  42. data/lib/annotate_rb/model_annotator/single_file_annotator.rb +49 -0
  43. data/lib/annotate_rb/model_annotator/{file_annotator_instruction.rb → single_file_annotator_instruction.rb} +2 -2
  44. data/lib/annotate_rb/model_annotator/single_file_remove_annotation_instruction.rb +15 -0
  45. data/lib/annotate_rb/model_annotator.rb +25 -26
  46. data/lib/annotate_rb/options.rb +20 -25
  47. data/lib/annotate_rb/parser.rb +150 -142
  48. data/lib/annotate_rb/rake_bootstrapper.rb +8 -8
  49. data/lib/annotate_rb/route_annotator/annotation_processor.rb +7 -8
  50. data/lib/annotate_rb/route_annotator/annotator.rb +2 -2
  51. data/lib/annotate_rb/route_annotator/base_processor.rb +3 -3
  52. data/lib/annotate_rb/route_annotator/header_generator.rb +15 -15
  53. data/lib/annotate_rb/route_annotator/helper.rb +9 -9
  54. data/lib/annotate_rb/route_annotator/removal_processor.rb +4 -4
  55. data/lib/annotate_rb/route_annotator.rb +6 -6
  56. data/lib/annotate_rb/runner.rb +0 -4
  57. data/lib/annotate_rb/tasks/annotate_models_migrate.rake +5 -5
  58. data/lib/annotate_rb.rb +19 -19
  59. data/lib/generators/annotate_rb/install/install_generator.rb +3 -2
  60. data/lib/generators/annotate_rb/install/templates/annotate_rb.rake +1 -1
  61. metadata +22 -16
  62. data/lib/annotate_rb/model_annotator/column_annotation_builder.rb +0 -92
  63. data/lib/annotate_rb/model_annotator/column_attributes_builder.rb +0 -102
  64. data/lib/annotate_rb/model_annotator/column_type_builder.rb +0 -51
  65. data/lib/annotate_rb/model_annotator/column_wrapper.rb +0 -84
  66. data/lib/annotate_rb/model_annotator/constants.rb +0 -22
  67. data/lib/annotate_rb/model_annotator/file_annotation_remover.rb +0 -25
  68. data/lib/annotate_rb/model_annotator/file_annotator.rb +0 -77
  69. data/lib/annotate_rb/model_annotator/file_patterns.rb +0 -129
  70. data/lib/annotate_rb/model_annotator/foreign_key_annotation_builder.rb +0 -55
  71. data/lib/annotate_rb/model_annotator/helper.rb +0 -107
  72. data/lib/annotate_rb/model_annotator/index_annotation_builder.rb +0 -74
  73. data/lib/annotate_rb/model_annotator/model_file_annotator.rb +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8888511eb71e6d0c45eadf9f562767868adf7cb9f2c5c58d6eb3458a65dfdc31
4
- data.tar.gz: 51d25d56e5068979a09d4562e7018b0272f8f73e952941a4f66faece7408cc11
3
+ metadata.gz: 5864a6030a7b4cfbf7751761c07136690ebafe15393d67147789f70319036205
4
+ data.tar.gz: a1dc2b99206b342bbd0dbc66795db4156abddfee307acecf6c2c383e8dbe89b1
5
5
  SHA512:
6
- metadata.gz: 9b878bfc48836e52fe762c547870b67619427772e54efd28835e8699371dc60fdb5511649d9f2bf39431541a9b07f8e32188469526dd109553f71badedd6ec45
7
- data.tar.gz: df69b71c4c10cc046ebd6cf0a21391262b90e0bcffe19556b59214d7658623fa323a7adbf24e711726bb685377e47596d9b95fed9c2425f22f4877264eed97d8
6
+ metadata.gz: b7cbd03e31fdc24f27d23d700773c157eca461078cddcd87739605980d6f5f07887b59f345ef41d91994547d8efbc2b82595e454f9e4619a5fe4e0fb506d29cd
7
+ data.tar.gz: f162544608cce0746a92250287ca4a5c7d25d151fe5bfe8bf4d18075834e98ce68939dc8b176dbe97d16f1f039a1a001cbb71066b26280f9fb5e83df763ba158
data/CHANGELOG.md CHANGED
@@ -0,0 +1,68 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased](https://github.com/drwl/annotaterb/tree/HEAD)
4
+
5
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.1.1...HEAD)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Specify `standard` gem version [\#39](https://github.com/drwl/annotaterb/pull/39) ([drwl](https://github.com/drwl))
10
+ - Bump version to v4.2.0 [\#37](https://github.com/drwl/annotaterb/pull/37) ([drwl](https://github.com/drwl))
11
+ - Generate changelog for 4.2 [\#36](https://github.com/drwl/annotaterb/pull/36) ([drwl](https://github.com/drwl))
12
+ - Improve tests for `ColumnAnnotation::*` [\#35](https://github.com/drwl/annotaterb/pull/35) ([drwl](https://github.com/drwl))
13
+ - Change instances of `Options.from` =\> `Options.new` in tests [\#34](https://github.com/drwl/annotaterb/pull/34) ([drwl](https://github.com/drwl))
14
+ - Add `Standard` linter to project [\#33](https://github.com/drwl/annotaterb/pull/33) ([drwl](https://github.com/drwl))
15
+ - Support Sorbet `typed` magic comment [\#32](https://github.com/drwl/annotaterb/pull/32) ([drwl](https://github.com/drwl))
16
+ - Add `position_in_additional_file_patterns` to Options and Parser [\#31](https://github.com/drwl/annotaterb/pull/31) ([drwl](https://github.com/drwl))
17
+ - Remove `Files` gem as a dependency [\#30](https://github.com/drwl/annotaterb/pull/30) ([drwl](https://github.com/drwl))
18
+ - Refactor `ModelAnnotator` again [\#28](https://github.com/drwl/annotaterb/pull/28) ([drwl](https://github.com/drwl))
19
+ - Add initial change log [\#27](https://github.com/drwl/annotaterb/pull/27) ([drwl](https://github.com/drwl))
20
+
21
+ ## [v4.1.1](https://github.com/drwl/annotaterb/tree/v4.1.1) (2023-05-20)
22
+
23
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.1.0...v4.1.1)
24
+
25
+ **Merged pull requests:**
26
+
27
+ - Bump version to v4.1.1 [\#26](https://github.com/drwl/annotaterb/pull/26) ([drwl](https://github.com/drwl))
28
+ - Tidy the github repo [\#25](https://github.com/drwl/annotaterb/pull/25) ([drwl](https://github.com/drwl))
29
+ - Add guide for migrating from Annotate gem [\#24](https://github.com/drwl/annotaterb/pull/24) ([drwl](https://github.com/drwl))
30
+ - Update column pattern regex to incorporate special column comments [\#23](https://github.com/drwl/annotaterb/pull/23) ([drwl](https://github.com/drwl))
31
+
32
+ ## [v4.1.0](https://github.com/drwl/annotaterb/tree/v4.1.0) (2023-05-17)
33
+
34
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/v4.0.0...v4.1.0)
35
+
36
+ **Merged pull requests:**
37
+
38
+ - Bump version to 4.1.0 [\#22](https://github.com/drwl/annotaterb/pull/22) ([drwl](https://github.com/drwl))
39
+ - Refactor ModelAnnotator; Fix instances of incorrect `exclude_*` keys [\#21](https://github.com/drwl/annotaterb/pull/21) ([drwl](https://github.com/drwl))
40
+ - Fix the default behavior for model annotator [\#20](https://github.com/drwl/annotaterb/pull/20) ([drwl](https://github.com/drwl))
41
+ - Refactor model annotator [\#19](https://github.com/drwl/annotaterb/pull/19) ([drwl](https://github.com/drwl))
42
+ - Removed unused helper methods and `Env` class [\#18](https://github.com/drwl/annotaterb/pull/18) ([drwl](https://github.com/drwl))
43
+ - Update dummy app depdencies [\#17](https://github.com/drwl/annotaterb/pull/17) ([drwl](https://github.com/drwl))
44
+
45
+ ## [v4.0.0](https://github.com/drwl/annotaterb/tree/v4.0.0) (2023-05-03)
46
+
47
+ [Full Changelog](https://github.com/drwl/annotaterb/compare/1da0386bf9e1ca3fbd0d9d3ae69cdc7a8cdc26fa...v4.0.0)
48
+
49
+ **Merged pull requests:**
50
+
51
+ - Last project polish for 4.0.0 release [\#14](https://github.com/drwl/annotaterb/pull/14) ([drwl](https://github.com/drwl))
52
+ - Add configuration instructions to README [\#13](https://github.com/drwl/annotaterb/pull/13) ([drwl](https://github.com/drwl))
53
+ - Prepare gem for beta release [\#12](https://github.com/drwl/annotaterb/pull/12) ([drwl](https://github.com/drwl))
54
+ - Make annotaterb usable [\#11](https://github.com/drwl/annotaterb/pull/11) ([drwl](https://github.com/drwl))
55
+ - Move old annotate code into AnnotateRb namespace [\#10](https://github.com/drwl/annotaterb/pull/10) ([drwl](https://github.com/drwl))
56
+ - Fix CodeQL action [\#9](https://github.com/drwl/annotaterb/pull/9) ([drwl](https://github.com/drwl))
57
+ - Regularly run CI [\#8](https://github.com/drwl/annotaterb/pull/8) ([drwl](https://github.com/drwl))
58
+ - Get CI consistently green [\#7](https://github.com/drwl/annotaterb/pull/7) ([drwl](https://github.com/drwl))
59
+ - More work [\#6](https://github.com/drwl/annotaterb/pull/6) ([drwl](https://github.com/drwl))
60
+ - Make CI green [\#5](https://github.com/drwl/annotaterb/pull/5) ([drwl](https://github.com/drwl))
61
+ - Make it work for Rails 7 [\#4](https://github.com/drwl/annotaterb/pull/4) ([drwl](https://github.com/drwl))
62
+ - Tidy up project [\#3](https://github.com/drwl/annotaterb/pull/3) ([drwl](https://github.com/drwl))
63
+ - Set spec run order to random [\#2](https://github.com/drwl/annotaterb/pull/2) ([drwl](https://github.com/drwl))
64
+ - Tidy rspec configuration [\#1](https://github.com/drwl/annotaterb/pull/1) ([drwl](https://github.com/drwl))
65
+
66
+
67
+
68
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.1.1
1
+ 4.2.0
data/exe/annotaterb CHANGED
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- unless File.exist?('./Rakefile') || File.exist?('./Gemfile')
5
- abort 'Please run annotaterb from the root of the project.'
4
+ unless File.exist?("./Rakefile") || File.exist?("./Gemfile")
5
+ abort "Please run annotaterb from the root of the project."
6
6
  end
7
7
 
8
8
  begin
9
- require 'bundler'
9
+ require "bundler"
10
10
  Bundler.setup
11
- rescue StandardError
11
+ rescue
12
12
  end
13
13
 
14
14
  $LOAD_PATH.unshift("#{__dir__}/../lib")
15
15
 
16
- require 'annotate_rb'
16
+ require "annotate_rb"
17
17
 
18
- exit_status = ::AnnotateRb::Runner.run(ARGV)
18
+ _exit_status = ::AnnotateRb::Runner.run(ARGV)
19
19
 
20
20
  # TODO: Return exit status
21
- # exit exit_status
21
+ # exit exit_status
@@ -1,5 +1,6 @@
1
1
  # monkey patches
2
2
 
3
+ # standard:disable Style/MissingRespondToMissing
3
4
  module ::ActiveRecord
4
5
  class Base
5
6
  def self.method_missing(_name, *_args)
@@ -7,3 +8,4 @@ module ::ActiveRecord
7
8
  end
8
9
  end
9
10
  end
11
+ # standard:enable Style/MissingRespondToMissing
@@ -19,4 +19,3 @@ module AnnotateRb
19
19
  end
20
20
  end
21
21
  end
22
-
@@ -16,4 +16,3 @@ module AnnotateRb
16
16
  end
17
17
  end
18
18
  end
19
-
@@ -13,4 +13,3 @@ module AnnotateRb
13
13
  end
14
14
  end
15
15
  end
16
-
@@ -9,4 +9,3 @@ module AnnotateRb
9
9
  end
10
10
  end
11
11
  end
12
-
@@ -2,9 +2,9 @@
2
2
 
3
3
  module AnnotateRb
4
4
  module Commands
5
- autoload :PrintVersion, 'annotate_rb/commands/print_version'
6
- autoload :PrintHelp, 'annotate_rb/commands/print_help'
7
- autoload :AnnotateModels, 'annotate_rb/commands/annotate_models'
8
- autoload :AnnotateRoutes, 'annotate_rb/commands/annotate_routes'
5
+ autoload :PrintVersion, "annotate_rb/commands/print_version"
6
+ autoload :PrintHelp, "annotate_rb/commands/print_help"
7
+ autoload :AnnotateModels, "annotate_rb/commands/annotate_models"
8
+ autoload :AnnotateRoutes, "annotate_rb/commands/annotate_routes"
9
9
  end
10
10
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module AnnotateRb
4
4
  class ConfigFinder
5
- DOTFILE = '.annotaterb.yml'
5
+ DOTFILE = ".annotaterb.yml"
6
6
 
7
7
  class << self
8
8
  def find_project_root
@@ -44,9 +44,9 @@ module AnnotateRb
44
44
  # Method from Rubocop::ConfigLoader
45
45
  def yaml_safe_load(yaml_code, filename)
46
46
  yaml_safe_load!(yaml_code, filename)
47
- rescue ::StandardError
47
+ rescue
48
48
  if defined?(::SafeYAML)
49
- raise 'SafeYAML is unmaintained, no longer needed and should be removed'
49
+ raise "SafeYAML is unmaintained, no longer needed and should be removed"
50
50
  end
51
51
 
52
52
  raise
@@ -4,13 +4,13 @@ module AnnotateRb
4
4
  module Core
5
5
  class << self
6
6
  def version
7
- @version ||= File.read(File.expand_path('../../VERSION', __dir__)).strip
7
+ @version ||= File.read(File.expand_path("../../VERSION", __dir__)).strip
8
8
  end
9
9
 
10
10
  def load_rake_tasks
11
11
  return if @load_rake_tasks
12
12
 
13
- rake_tasks = Dir[File.join(File.dirname(__FILE__), 'tasks', '**/*.rake')]
13
+ rake_tasks = Dir[File.join(File.dirname(__FILE__), "tasks", "**/*.rake")]
14
14
 
15
15
  rake_tasks.each do |task|
16
16
  load task
@@ -20,4 +20,4 @@ module AnnotateRb
20
20
  end
21
21
  end
22
22
  end
23
- end
23
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module Helper
5
+ class << self
6
+ def width(string)
7
+ string.chars.inject(0) { |acc, elem| acc + ((elem.bytesize == 3) ? 2 : 1) }
8
+ end
9
+
10
+ # TODO: Find another implementation that doesn't depend on ActiveSupport
11
+ def fallback(*args)
12
+ args.compact.detect(&:present?)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,12 +2,12 @@
2
2
 
3
3
  module AnnotateRb
4
4
  module ModelAnnotator
5
- class AnnotationGenerator
5
+ class AnnotationBuilder
6
6
  # Annotate Models plugin use this header
7
- PREFIX = '== Schema Information'.freeze
8
- PREFIX_MD = '## Schema Information'.freeze
7
+ PREFIX = "== Schema Information"
8
+ PREFIX_MD = "## Schema Information"
9
9
 
10
- END_MARK = '== Schema Information End'.freeze
10
+ END_MARK = "== Schema Information End"
11
11
 
12
12
  MD_NAMES_OVERHEAD = 6
13
13
  MD_TYPE_ALLOWANCE = 18
@@ -18,7 +18,7 @@ module AnnotateRb
18
18
  @info = "" # TODO: Make array and build string that way
19
19
  end
20
20
 
21
- def generate
21
+ def build
22
22
  @info = "# #{header}\n"
23
23
  @info += schema_header_text
24
24
 
@@ -26,22 +26,22 @@ module AnnotateRb
26
26
 
27
27
  if @options[:format_markdown]
28
28
  @info += format("# %-#{max_size + MD_NAMES_OVERHEAD}.#{max_size + MD_NAMES_OVERHEAD}s | %-#{MD_TYPE_ALLOWANCE}.#{MD_TYPE_ALLOWANCE}s | %s\n",
29
- 'Name',
30
- 'Type',
31
- 'Attributes')
32
- @info += "# #{'-' * (max_size + MD_NAMES_OVERHEAD)} | #{'-' * MD_TYPE_ALLOWANCE} | #{'-' * 27}\n"
29
+ "Name",
30
+ "Type",
31
+ "Attributes")
32
+ @info += "# #{"-" * (max_size + MD_NAMES_OVERHEAD)} | #{"-" * MD_TYPE_ALLOWANCE} | #{"-" * 27}\n"
33
33
  end
34
34
 
35
35
  @info += @model.columns.map do |col|
36
- ColumnAnnotationBuilder.new(col, @model, max_size, @options).build
36
+ ColumnAnnotation::AnnotationBuilder.new(col, @model, max_size, @options).build
37
37
  end.join
38
38
 
39
39
  if @options[:show_indexes] && @model.table_exists?
40
- @info += IndexAnnotationBuilder.new(@model, @options).build
40
+ @info += IndexAnnotation::AnnotationBuilder.new(@model, @options).build
41
41
  end
42
42
 
43
43
  if @options[:show_foreign_keys] && @model.table_exists?
44
- @info += ForeignKeyAnnotationBuilder.new(@model, @options).build
44
+ @info += ForeignKeyAnnotation::AnnotationBuilder.new(@model, @options).build
45
45
  end
46
46
 
47
47
  @info += schema_footer_text
@@ -51,7 +51,11 @@ module AnnotateRb
51
51
 
52
52
  def header
53
53
  header = @options[:format_markdown] ? PREFIX_MD.dup : PREFIX.dup
54
- version = ActiveRecord::Migrator.current_version rescue 0
54
+ version = begin
55
+ ActiveRecord::Migrator.current_version
56
+ rescue
57
+ 0
58
+ end
55
59
 
56
60
  if @options[:include_version] && version > 0
57
61
  header += "\n# Schema version: #{version}"
@@ -91,4 +95,4 @@ module AnnotateRb
91
95
  end
92
96
  end
93
97
  end
94
- end
98
+ end
@@ -4,6 +4,8 @@ module AnnotateRb
4
4
  module ModelAnnotator
5
5
  # Class that encapsulates the logic to decide whether to annotate a model file and its related files or not.
6
6
  class AnnotationDecider
7
+ SKIP_ANNOTATION_PREFIX = '# -\*- SkipSchemaAnnotations'
8
+
7
9
  def initialize(file, options)
8
10
  @file = file
9
11
  @options = options
@@ -35,12 +37,12 @@ module AnnotateRb
35
37
  return to_annotate
36
38
  rescue BadModelFileError => e
37
39
  unless @options[:ignore_unknown_models]
38
- $stderr.puts "Unable to annotate #{@file}: #{e.message}"
39
- $stderr.puts "\t" + e.backtrace.join("\n\t") if @options[:trace]
40
+ warn "Unable to process #{@file}: #{e.message}"
41
+ warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
40
42
  end
41
- rescue StandardError => e
42
- $stderr.puts "Unable to annotate #{@file}: #{e.message}"
43
- $stderr.puts "\t" + e.backtrace.join("\n\t") if @options[:trace]
43
+ rescue => e
44
+ warn "Unable to process #{@file}: #{e.message}"
45
+ warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
44
46
  end
45
47
 
46
48
  false
@@ -49,14 +51,10 @@ module AnnotateRb
49
51
  private
50
52
 
51
53
  def file_contains_skip_annotation
52
- file_string = File.exist?(@file) ? File.read(@file) : ''
54
+ file_string = File.exist?(@file) ? File.read(@file) : ""
53
55
 
54
- if /#{Constants::SKIP_ANNOTATION_PREFIX}.*/ =~ file_string
55
- true
56
- else
57
- false
58
- end
56
+ /#{SKIP_ANNOTATION_PREFIX}.*/o.match?(file_string)
59
57
  end
60
58
  end
61
59
  end
62
- end
60
+ end
@@ -16,4 +16,4 @@ module AnnotateRb
16
16
  end
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -4,8 +4,8 @@ module AnnotateRb
4
4
  module ModelAnnotator
5
5
  # Compares the current file content and new annotation block and generates the column annotation differences
6
6
  class AnnotationDiffGenerator
7
- HEADER_PATTERN = /(^# Table name:.*?\n(#.*[\r]?\n)*[\r]?)/.freeze
8
- COLUMN_PATTERN = /^#[\t ]+[\w\*\.`\[\]():]+[\t ]+.+$/.freeze
7
+ HEADER_PATTERN = /(^# Table name:.*?\n(#.*\r?\n)*\r?)/
8
+ COLUMN_PATTERN = /^#[\t ]+[\w*.`\[\]():]+[\t ]+.+$/
9
9
 
10
10
  class << self
11
11
  def call(file_content, annotation_block)
@@ -25,20 +25,20 @@ module AnnotateRb
25
25
  current_annotations = @file_content.match(HEADER_PATTERN).to_s
26
26
  new_annotations = @annotation_block.match(HEADER_PATTERN).to_s
27
27
 
28
- if current_annotations.present?
29
- current_annotation_columns = current_annotations.scan(COLUMN_PATTERN).sort
28
+ current_annotation_columns = if current_annotations.present?
29
+ current_annotations.scan(COLUMN_PATTERN).sort
30
30
  else
31
- current_annotation_columns = []
31
+ []
32
32
  end
33
33
 
34
- if new_annotations.present?
35
- new_annotation_columns = new_annotations.scan(COLUMN_PATTERN).sort
34
+ new_annotation_columns = if new_annotations.present?
35
+ new_annotations.scan(COLUMN_PATTERN).sort
36
36
  else
37
- new_annotation_columns = []
37
+ []
38
38
  end
39
39
 
40
40
  _result = AnnotationDiff.new(current_annotation_columns, new_annotation_columns)
41
41
  end
42
42
  end
43
43
  end
44
- end
44
+ end
@@ -3,15 +3,15 @@
3
3
  module AnnotateRb
4
4
  module ModelAnnotator
5
5
  class AnnotationPatternGenerator
6
- COMPAT_PREFIX = '== Schema Info'.freeze
7
- COMPAT_PREFIX_MD = '## Schema Info'.freeze
6
+ COMPAT_PREFIX = "== Schema Info"
7
+ COMPAT_PREFIX_MD = "## Schema Info"
8
8
 
9
9
  class << self
10
10
  def call(options = Options.from({}))
11
11
  if options[:wrapper_open]
12
12
  return /(?:^(\n|\r\n)?# (?:#{options[:wrapper_open]}).*(\n|\r\n)?# (?:#{COMPAT_PREFIX}|#{COMPAT_PREFIX_MD}).*?(\n|\r\n)(#.*(\n|\r\n))*(\n|\r\n)*)|^(\n|\r\n)?# (?:#{COMPAT_PREFIX}|#{COMPAT_PREFIX_MD}).*?(\n|\r\n)(#.*(\n|\r\n))*(\n|\r\n)*/
13
13
  end
14
- /^(\n|\r\n)?# (?:#{COMPAT_PREFIX}|#{COMPAT_PREFIX_MD}).*?(\n|\r\n)(#.*(\n|\r\n))*(\n|\r\n)*/
14
+ /^(\n|\r\n)?# (?:#{COMPAT_PREFIX}|#{COMPAT_PREFIX_MD}).*?(\n|\r\n)(#.*(\n|\r\n))*(\n|\r\n)*/o
15
15
  end
16
16
  end
17
17
  end
@@ -5,66 +5,25 @@ module AnnotateRb
5
5
  class Annotator
6
6
  class << self
7
7
  def do_annotations(options = {})
8
- annotated = []
9
-
10
- model_files_to_consider = ModelFilesGetter.call(options)
11
-
12
- model_files_to_consider.each do |path, filename|
13
- file = File.join(path, filename)
14
-
15
- if AnnotationDecider.new(file, options).annotate?
16
- ModelFileAnnotator.call(annotated, file, options)
17
- end
18
- end
19
-
20
- if annotated.empty?
21
- puts 'Model files unchanged.'
22
- else
23
- puts "Annotated (#{annotated.length}): #{annotated.join(', ')}"
24
- end
8
+ new(options).do_annotations
25
9
  end
26
10
 
27
11
  def remove_annotations(options = {})
28
- deannotated = []
29
-
30
- model_files_to_consider = ModelFilesGetter.call(options)
31
-
32
- model_files_to_consider.each do |path, filename|
33
- deannotated_klass = false
34
- file = File.join(path, filename)
35
-
36
- begin
37
- klass = ModelClassGetter.call(file, options)
38
- if klass < ActiveRecord::Base && !klass.abstract_class?
39
- model_name = klass.name.underscore
40
- table_name = klass.table_name
41
-
42
- if FileAnnotationRemover.call(file, options)
43
- deannotated_klass = true
44
- end
45
-
46
- related_files = RelatedFilesListBuilder.new(file, model_name, table_name, options).build
12
+ new(options).remove_annotations
13
+ end
14
+ end
47
15
 
48
- related_files.each do |f, _position_key|
49
- if File.exist?(f)
50
- FileAnnotationRemover.call(f, options)
51
- end
52
- end
53
- end
16
+ def initialize(options)
17
+ @options = options
18
+ end
54
19
 
55
- if deannotated_klass
56
- deannotated << klass
57
- end
58
- rescue StandardError => e
59
- $stderr.puts "Unable to deannotate #{File.join(file)}: #{e.message}"
60
- $stderr.puts "\t" + e.backtrace.join("\n\t") if options[:trace]
61
- end
62
- end
20
+ def do_annotations
21
+ ProjectAnnotator.new(@options).annotate
22
+ end
63
23
 
64
- puts "Removed annotations from: #{deannotated.join(', ')}"
65
- end
24
+ def remove_annotations
25
+ ProjectAnnotationRemover.new(@options).remove_annotations
66
26
  end
67
27
  end
68
28
  end
69
29
  end
70
-
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnnotateRb
4
+ module ModelAnnotator
5
+ module ColumnAnnotation
6
+ class AnnotationBuilder
7
+ BARE_TYPE_ALLOWANCE = 16
8
+ MD_TYPE_ALLOWANCE = 18
9
+
10
+ def initialize(column, model, max_size, options)
11
+ @column = column
12
+ @model = model
13
+ @max_size = max_size
14
+ @options = options
15
+ end
16
+
17
+ def build
18
+ result = ""
19
+
20
+ is_primary_key = is_column_primary_key?(@model, @column.name)
21
+
22
+ table_indices = @model.retrieve_indexes_from_table
23
+ column_indices = table_indices.select { |ind| ind.columns.include?(@column.name) }
24
+
25
+ column_attributes = AttributesBuilder.new(@column, @options, is_primary_key, column_indices).build
26
+ formatted_column_type = TypeBuilder.new(@column, @options).build
27
+
28
+ col_name = if @model.with_comments? && @column.comment
29
+ "#{@column.name}(#{@column.comment.gsub(/\n/, '\\n')})"
30
+ else
31
+ @column.name
32
+ end
33
+
34
+ result += if @options[:format_rdoc]
35
+ format_rdoc(col_name, @max_size, formatted_column_type, column_attributes)
36
+ elsif @options[:format_yard]
37
+ format_yard(col_name, @max_size, formatted_column_type, column_attributes)
38
+ elsif @options[:format_markdown]
39
+ format_markdown(col_name, @max_size, formatted_column_type, column_attributes)
40
+ else
41
+ format_default(col_name, @max_size, formatted_column_type, column_attributes)
42
+ end
43
+
44
+ result
45
+ end
46
+
47
+ private
48
+
49
+ def non_ascii_length(string)
50
+ string.to_s.chars.count { |element| !element.ascii_only? }
51
+ end
52
+
53
+ def mb_chars_ljust(string, length)
54
+ string = string.to_s
55
+ padding = length - Helper.width(string)
56
+ if padding.positive?
57
+ string + (" " * padding)
58
+ else
59
+ string[0..(length - 1)]
60
+ end
61
+ end
62
+
63
+ def map_col_type_to_ruby_classes(col_type)
64
+ case col_type
65
+ when "integer" then Integer.to_s
66
+ when "float" then Float.to_s
67
+ when "decimal" then BigDecimal.to_s
68
+ when "datetime", "timestamp", "time" then Time.to_s
69
+ when "date" then Date.to_s
70
+ when "text", "string", "binary", "inet", "uuid" then String.to_s
71
+ when "json", "jsonb" then Hash.to_s
72
+ when "boolean" then "Boolean"
73
+ end
74
+ end
75
+
76
+ def format_rdoc(col_name, max_size, formatted_column_type, column_attributes)
77
+ format("# %-#{max_size}.#{max_size}s<tt>%s</tt>",
78
+ "*#{col_name}*::",
79
+ column_attributes.unshift(formatted_column_type).join(", ")).rstrip + "\n"
80
+ end
81
+
82
+ def format_yard(col_name, _max_size, formatted_column_type, _column_attributes)
83
+ res = ""
84
+ res += sprintf("# @!attribute #{col_name}") + "\n"
85
+
86
+ ruby_class = if @column.respond_to?(:array) && @column.array
87
+ "Array<#{map_col_type_to_ruby_classes(formatted_column_type)}>"
88
+ else
89
+ map_col_type_to_ruby_classes(formatted_column_type)
90
+ end
91
+
92
+ res += sprintf("# @return [#{ruby_class}]") + "\n"
93
+
94
+ res
95
+ end
96
+
97
+ def format_markdown(col_name, max_size, formatted_column_type, column_attributes)
98
+ name_remainder = max_size - col_name.length - non_ascii_length(col_name)
99
+ type_remainder = (MD_TYPE_ALLOWANCE - 2) - formatted_column_type.length
100
+
101
+ format("# **`%s`**%#{name_remainder}s | `%s`%#{type_remainder}s | `%s`",
102
+ col_name,
103
+ " ",
104
+ formatted_column_type,
105
+ " ",
106
+ column_attributes.join(", ").rstrip).gsub("``", " ").rstrip + "\n"
107
+ end
108
+
109
+ def format_default(col_name, max_size, formatted_column_type, column_attributes)
110
+ format("# %s:%s %s",
111
+ mb_chars_ljust(col_name, max_size),
112
+ mb_chars_ljust(formatted_column_type, BARE_TYPE_ALLOWANCE),
113
+ column_attributes.join(", ")).rstrip + "\n"
114
+ end
115
+
116
+ # TODO: Simplify this conditional
117
+ def is_column_primary_key?(model, column_name)
118
+ if model.primary_key
119
+ if model.primary_key.is_a?(Array)
120
+ # If the model has multiple primary keys, check if this column is one of them
121
+ if model.primary_key.collect(&:to_sym).include?(column_name.to_sym)
122
+ return true
123
+ end
124
+ elsif column_name.to_sym == model.primary_key.to_sym
125
+ # If model has 1 primary key, check if this column is it
126
+ return true
127
+ end
128
+ end
129
+
130
+ false
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end