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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -0
- data/VERSION +1 -1
- data/exe/annotaterb +7 -7
- data/lib/annotate_rb/active_record_patch.rb +2 -0
- data/lib/annotate_rb/commands/annotate_models.rb +0 -1
- data/lib/annotate_rb/commands/annotate_routes.rb +0 -1
- data/lib/annotate_rb/commands/print_help.rb +0 -1
- data/lib/annotate_rb/commands/print_version.rb +0 -1
- data/lib/annotate_rb/commands.rb +4 -4
- data/lib/annotate_rb/config_finder.rb +1 -1
- data/lib/annotate_rb/config_loader.rb +2 -2
- data/lib/annotate_rb/core.rb +3 -3
- data/lib/annotate_rb/helper.rb +16 -0
- data/lib/annotate_rb/model_annotator/{annotation_generator.rb → annotation_builder.rb} +18 -14
- data/lib/annotate_rb/model_annotator/annotation_decider.rb +10 -12
- data/lib/annotate_rb/model_annotator/annotation_diff.rb +1 -1
- data/lib/annotate_rb/model_annotator/annotation_diff_generator.rb +9 -9
- data/lib/annotate_rb/model_annotator/annotation_pattern_generator.rb +3 -3
- data/lib/annotate_rb/model_annotator/annotator.rb +12 -53
- data/lib/annotate_rb/model_annotator/column_annotation/annotation_builder.rb +135 -0
- data/lib/annotate_rb/model_annotator/column_annotation/attributes_builder.rb +104 -0
- data/lib/annotate_rb/model_annotator/column_annotation/column_wrapper.rb +103 -0
- data/lib/annotate_rb/model_annotator/column_annotation/type_builder.rb +54 -0
- data/lib/annotate_rb/model_annotator/column_annotation.rb +12 -0
- data/lib/annotate_rb/model_annotator/file_builder.rb +58 -0
- data/lib/annotate_rb/model_annotator/file_components.rb +78 -0
- data/lib/annotate_rb/model_annotator/file_name_resolver.rb +3 -3
- data/lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder.rb +57 -0
- data/lib/annotate_rb/model_annotator/foreign_key_annotation.rb +9 -0
- data/lib/annotate_rb/model_annotator/index_annotation/annotation_builder.rb +113 -0
- data/lib/annotate_rb/model_annotator/index_annotation.rb +9 -0
- data/lib/annotate_rb/model_annotator/magic_comment_parser.rb +32 -0
- data/lib/annotate_rb/model_annotator/model_class_getter.rb +6 -6
- data/lib/annotate_rb/model_annotator/model_files_getter.rb +12 -10
- data/lib/annotate_rb/model_annotator/model_wrapper.rb +44 -37
- data/lib/annotate_rb/model_annotator/pattern_getter.rb +142 -10
- data/lib/annotate_rb/model_annotator/project_annotation_remover.rb +65 -0
- data/lib/annotate_rb/model_annotator/project_annotator.rb +63 -0
- data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +16 -18
- data/lib/annotate_rb/model_annotator/single_file_annotation_remover.rb +37 -0
- data/lib/annotate_rb/model_annotator/single_file_annotator.rb +49 -0
- data/lib/annotate_rb/model_annotator/{file_annotator_instruction.rb → single_file_annotator_instruction.rb} +2 -2
- data/lib/annotate_rb/model_annotator/single_file_remove_annotation_instruction.rb +15 -0
- data/lib/annotate_rb/model_annotator.rb +25 -26
- data/lib/annotate_rb/options.rb +20 -25
- data/lib/annotate_rb/parser.rb +150 -142
- data/lib/annotate_rb/rake_bootstrapper.rb +8 -8
- data/lib/annotate_rb/route_annotator/annotation_processor.rb +7 -8
- data/lib/annotate_rb/route_annotator/annotator.rb +2 -2
- data/lib/annotate_rb/route_annotator/base_processor.rb +3 -3
- data/lib/annotate_rb/route_annotator/header_generator.rb +15 -15
- data/lib/annotate_rb/route_annotator/helper.rb +9 -9
- data/lib/annotate_rb/route_annotator/removal_processor.rb +4 -4
- data/lib/annotate_rb/route_annotator.rb +6 -6
- data/lib/annotate_rb/runner.rb +0 -4
- data/lib/annotate_rb/tasks/annotate_models_migrate.rake +5 -5
- data/lib/annotate_rb.rb +19 -19
- data/lib/generators/annotate_rb/install/install_generator.rb +3 -2
- data/lib/generators/annotate_rb/install/templates/annotate_rb.rake +1 -1
- metadata +22 -16
- data/lib/annotate_rb/model_annotator/column_annotation_builder.rb +0 -92
- data/lib/annotate_rb/model_annotator/column_attributes_builder.rb +0 -102
- data/lib/annotate_rb/model_annotator/column_type_builder.rb +0 -51
- data/lib/annotate_rb/model_annotator/column_wrapper.rb +0 -84
- data/lib/annotate_rb/model_annotator/constants.rb +0 -22
- data/lib/annotate_rb/model_annotator/file_annotation_remover.rb +0 -25
- data/lib/annotate_rb/model_annotator/file_annotator.rb +0 -77
- data/lib/annotate_rb/model_annotator/file_patterns.rb +0 -129
- data/lib/annotate_rb/model_annotator/foreign_key_annotation_builder.rb +0 -55
- data/lib/annotate_rb/model_annotator/helper.rb +0 -107
- data/lib/annotate_rb/model_annotator/index_annotation_builder.rb +0 -74
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5864a6030a7b4cfbf7751761c07136690ebafe15393d67147789f70319036205
|
4
|
+
data.tar.gz: a1dc2b99206b342bbd0dbc66795db4156abddfee307acecf6c2c383e8dbe89b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
+
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?(
|
5
|
-
abort
|
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
|
9
|
+
require "bundler"
|
10
10
|
Bundler.setup
|
11
|
-
rescue
|
11
|
+
rescue
|
12
12
|
end
|
13
13
|
|
14
14
|
$LOAD_PATH.unshift("#{__dir__}/../lib")
|
15
15
|
|
16
|
-
require
|
16
|
+
require "annotate_rb"
|
17
17
|
|
18
|
-
|
18
|
+
_exit_status = ::AnnotateRb::Runner.run(ARGV)
|
19
19
|
|
20
20
|
# TODO: Return exit status
|
21
|
-
# exit exit_status
|
21
|
+
# exit exit_status
|
data/lib/annotate_rb/commands.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module AnnotateRb
|
4
4
|
module Commands
|
5
|
-
autoload :PrintVersion,
|
6
|
-
autoload :PrintHelp,
|
7
|
-
autoload :AnnotateModels,
|
8
|
-
autoload :AnnotateRoutes,
|
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
|
@@ -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
|
47
|
+
rescue
|
48
48
|
if defined?(::SafeYAML)
|
49
|
-
raise
|
49
|
+
raise "SafeYAML is unmaintained, no longer needed and should be removed"
|
50
50
|
end
|
51
51
|
|
52
52
|
raise
|
data/lib/annotate_rb/core.rb
CHANGED
@@ -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(
|
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__),
|
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
|
5
|
+
class AnnotationBuilder
|
6
6
|
# Annotate Models plugin use this header
|
7
|
-
PREFIX =
|
8
|
-
PREFIX_MD =
|
7
|
+
PREFIX = "== Schema Information"
|
8
|
+
PREFIX_MD = "## Schema Information"
|
9
9
|
|
10
|
-
END_MARK =
|
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
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
@info += "# #{
|
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
|
-
|
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 +=
|
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 +=
|
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 =
|
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
|
-
|
39
|
-
|
40
|
+
warn "Unable to process #{@file}: #{e.message}"
|
41
|
+
warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
|
40
42
|
end
|
41
|
-
rescue
|
42
|
-
|
43
|
-
|
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
|
-
|
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
|
@@ -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(
|
8
|
-
COLUMN_PATTERN = /^#[\t ]+[\w
|
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
|
-
|
28
|
+
current_annotation_columns = if current_annotations.present?
|
29
|
+
current_annotations.scan(COLUMN_PATTERN).sort
|
30
30
|
else
|
31
|
-
|
31
|
+
[]
|
32
32
|
end
|
33
33
|
|
34
|
-
if new_annotations.present?
|
35
|
-
|
34
|
+
new_annotation_columns = if new_annotations.present?
|
35
|
+
new_annotations.scan(COLUMN_PATTERN).sort
|
36
36
|
else
|
37
|
-
|
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 =
|
7
|
-
COMPAT_PREFIX_MD =
|
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
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
16
|
+
def initialize(options)
|
17
|
+
@options = options
|
18
|
+
end
|
54
19
|
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
-
|
65
|
-
|
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
|