annotaterb 4.7.0 → 4.8.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 +32 -4
- data/VERSION +1 -1
- data/lib/annotate_rb/model_annotator/annotated_file/generator.rb +4 -3
- data/lib/annotate_rb/model_annotator/annotated_file/updater.rb +2 -2
- data/lib/annotate_rb/model_annotator/annotation_builder.rb +15 -4
- data/lib/annotate_rb/model_annotator/annotation_decider.rb +4 -0
- data/lib/annotate_rb/model_annotator/check_constraint_annotation/annotation_builder.rb +57 -0
- data/lib/annotate_rb/model_annotator/check_constraint_annotation.rb +9 -0
- data/lib/annotate_rb/model_annotator/file_parser/annotation_finder.rb +2 -4
- data/lib/annotate_rb/model_annotator/file_parser/parsed_file.rb +7 -4
- data/lib/annotate_rb/model_annotator/file_parser/parsed_file_result.rb +6 -2
- data/lib/annotate_rb/model_annotator/file_parser/yml_parser.rb +67 -0
- data/lib/annotate_rb/model_annotator/file_parser.rb +1 -0
- data/lib/annotate_rb/model_annotator/file_to_parser_mapper.rb +25 -0
- data/lib/annotate_rb/model_annotator/pattern_getter.rb +56 -15
- data/lib/annotate_rb/model_annotator/related_files_list_builder.rb +86 -5
- data/lib/annotate_rb/model_annotator/single_file_annotation_remover.rb +3 -1
- data/lib/annotate_rb/model_annotator/single_file_annotator.rb +6 -4
- data/lib/annotate_rb/model_annotator.rb +2 -0
- data/lib/annotate_rb/options.rb +20 -0
- data/lib/annotate_rb/parser.rb +6 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 255fdc09fbc3848ba6d9306ec84d07c2471491ffbfde2440dc502bc35432a702
|
4
|
+
data.tar.gz: 004c6df59a13ec89bca83190fcb4de77c88435b0a091cd0385e1bc2a1c3f9ae8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff01eaa95eda26cd5a14d30fb93bd2da5cabde3dc2da12cac718c40349a4228963e162162db017461942aa01cffba5ef59ca7c43344c01549a11ee2d6ba189b1
|
7
|
+
data.tar.gz: 4ee46c7c044938e98a883f72daa023ed89f3c2d13548d1986d2353b0f5f034a8eccab3cd8ea4032c80c3d7e3b3f8f093deccc92ef494c81f1c5631be5261d720
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,41 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v4.7.1](https://github.com/drwl/annotaterb/tree/v4.7.1) (2024-05-09)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/drwl/annotaterb/compare/v4.7.0...v4.7.1)
|
6
|
+
|
7
|
+
**Closed issues:**
|
8
|
+
|
9
|
+
- Check constraint support [\#104](https://github.com/drwl/annotaterb/issues/104)
|
10
|
+
|
11
|
+
**Merged pull requests:**
|
12
|
+
|
13
|
+
- Bump version to v4.7.1 [\#113](https://github.com/drwl/annotaterb/pull/113) ([drwl](https://github.com/drwl))
|
14
|
+
- Change AnnotationDecider to return false early [\#112](https://github.com/drwl/annotaterb/pull/112) ([drwl](https://github.com/drwl))
|
15
|
+
- Memoize ActiveRecord migrator version calls [\#111](https://github.com/drwl/annotaterb/pull/111) ([drwl](https://github.com/drwl))
|
16
|
+
- Fix misspelling in migration guide [\#109](https://github.com/drwl/annotaterb/pull/109) ([RobinDaugherty](https://github.com/RobinDaugherty))
|
17
|
+
- Annotate model check constraints [\#105](https://github.com/drwl/annotaterb/pull/105) ([drwl](https://github.com/drwl))
|
18
|
+
- Fix CHANGELOG.md [\#102](https://github.com/drwl/annotaterb/pull/102) ([drwl](https://github.com/drwl))
|
19
|
+
- Generate changelog for v4.7.0 [\#101](https://github.com/drwl/annotaterb/pull/101) ([drwl](https://github.com/drwl))
|
20
|
+
|
21
|
+
## [v4.7.0](https://github.com/drwl/annotaterb/tree/v4.7.0) (2024-03-27)
|
22
|
+
|
23
|
+
[Full Changelog](https://github.com/drwl/annotaterb/compare/v4.6.0...v4.7.0)
|
24
|
+
|
25
|
+
**Closed issues:**
|
26
|
+
|
27
|
+
- Feature request: better custom type representation [\#97](https://github.com/drwl/annotaterb/issues/97)
|
28
|
+
|
29
|
+
**Merged pull requests:**
|
30
|
+
|
31
|
+
- Bump version to v4.7.0 [\#100](https://github.com/drwl/annotaterb/pull/100) ([drwl](https://github.com/drwl))
|
32
|
+
- Add configurable classes list with `to_s` representation [\#98](https://github.com/drwl/annotaterb/pull/98) ([viralpraxis](https://github.com/viralpraxis))
|
33
|
+
- Generate changelog for v4.6.0 [\#96](https://github.com/drwl/annotaterb/pull/96) ([drwl](https://github.com/drwl))
|
34
|
+
|
3
35
|
## [v4.6.0](https://github.com/drwl/annotaterb/tree/v4.6.0) (2024-02-27)
|
4
36
|
|
5
37
|
[Full Changelog](https://github.com/drwl/annotaterb/compare/v4.5.0...v4.6.0)
|
6
38
|
|
7
|
-
Adds two big changes: Fix annotations swallowing comments [\#72](https://github.com/drwl/annotaterb/pull/72) and
|
8
|
-
Add Zeitwerk support [\#85](https://github.com/drwl/annotaterb/pull/85).
|
9
|
-
Please report any issues you encounter.
|
10
|
-
|
11
39
|
**Closed issues:**
|
12
40
|
|
13
41
|
- Add support for `data_migrate` gem [\#89](https://github.com/drwl/annotaterb/issues/89)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.
|
1
|
+
4.8.0
|
@@ -5,7 +5,7 @@ module AnnotateRb
|
|
5
5
|
module AnnotatedFile
|
6
6
|
# Generates the file with fresh annotations
|
7
7
|
class Generator
|
8
|
-
def initialize(file_content, new_annotations, annotation_position, options)
|
8
|
+
def initialize(file_content, new_annotations, annotation_position, parser_klass, parsed_file, options)
|
9
9
|
@annotation_position = annotation_position
|
10
10
|
@options = options
|
11
11
|
|
@@ -14,7 +14,8 @@ module AnnotateRb
|
|
14
14
|
@new_annotations = new_annotations
|
15
15
|
@file_content = file_content
|
16
16
|
|
17
|
-
@
|
17
|
+
@parser = parser_klass
|
18
|
+
@parsed_file = parsed_file
|
18
19
|
end
|
19
20
|
|
20
21
|
# @return [String] Returns the annotated file content to be written back to a file
|
@@ -32,7 +33,7 @@ module AnnotateRb
|
|
32
33
|
end
|
33
34
|
|
34
35
|
# We need to get class start and class end depending on the position
|
35
|
-
parsed =
|
36
|
+
parsed = @parser.parse(content_without_annotations)
|
36
37
|
|
37
38
|
_content = if %w[after bottom].include?(annotation_write_position)
|
38
39
|
content_annotated_after(parsed, content_without_annotations)
|
@@ -5,13 +5,13 @@ module AnnotateRb
|
|
5
5
|
module AnnotatedFile
|
6
6
|
# Updates existing annotations
|
7
7
|
class Updater
|
8
|
-
def initialize(file_content, new_annotations, _annotation_position, options)
|
8
|
+
def initialize(file_content, new_annotations, _annotation_position, parsed_file, options)
|
9
9
|
@options = options
|
10
10
|
|
11
11
|
@new_annotations = new_annotations
|
12
12
|
@file_content = file_content
|
13
13
|
|
14
|
-
@parsed_file =
|
14
|
+
@parsed_file = parsed_file
|
15
15
|
end
|
16
16
|
|
17
17
|
# @return [String] Returns the annotated file content to be written back to a file
|
@@ -44,6 +44,10 @@ module AnnotateRb
|
|
44
44
|
@info += ForeignKeyAnnotation::AnnotationBuilder.new(@model, @options).build
|
45
45
|
end
|
46
46
|
|
47
|
+
if @options[:show_check_constraints] && @model.table_exists?
|
48
|
+
@info += CheckConstraintAnnotation::AnnotationBuilder.new(@model, @options).build
|
49
|
+
end
|
50
|
+
|
47
51
|
@info += schema_footer_text
|
48
52
|
|
49
53
|
@info
|
@@ -52,12 +56,19 @@ module AnnotateRb
|
|
52
56
|
def header
|
53
57
|
header = @options[:format_markdown] ? PREFIX_MD.dup : PREFIX.dup
|
54
58
|
header = "# #{header}"
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
|
60
|
+
if @options.get_state(:current_version).nil?
|
61
|
+
migration_version = begin
|
62
|
+
ActiveRecord::Migrator.current_version
|
63
|
+
rescue
|
64
|
+
0
|
65
|
+
end
|
66
|
+
|
67
|
+
@options.set_state(:current_version, migration_version)
|
59
68
|
end
|
60
69
|
|
70
|
+
version = @options.get_state(:current_version)
|
71
|
+
|
61
72
|
if @options[:include_version] && version > 0
|
62
73
|
header += "\n# Schema version: #{version}"
|
63
74
|
end
|
@@ -18,6 +18,10 @@ module AnnotateRb
|
|
18
18
|
klass = ModelClassGetter.call(@file, @options)
|
19
19
|
|
20
20
|
klass_is_a_class = klass.is_a?(Class)
|
21
|
+
# Methods such as #superclass only exist on a class. Because of how the code is structured, `klass` could be a
|
22
|
+
# module that does not support the #superclass method, so we want to return early.
|
23
|
+
return false if !klass_is_a_class
|
24
|
+
|
21
25
|
klass_inherits_active_record_base = klass < ActiveRecord::Base
|
22
26
|
klass_is_not_abstract = klass.respond_to?(:abstract_class) && !klass.abstract_class?
|
23
27
|
klass_table_exists = klass.respond_to?(:abstract_class) && klass.table_exists?
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
module CheckConstraintAnnotation
|
6
|
+
class AnnotationBuilder
|
7
|
+
def initialize(model, options)
|
8
|
+
@model = model
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def build
|
13
|
+
constraint_info = if @options[:format_markdown]
|
14
|
+
"#\n# ### Check Constraints\n#\n"
|
15
|
+
else
|
16
|
+
"#\n# Check Constraints\n#\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
return "" unless @model.connection.respond_to?(:supports_check_constraints?) &&
|
20
|
+
@model.connection.supports_check_constraints? && @model.connection.respond_to?(:check_constraints)
|
21
|
+
|
22
|
+
check_constraints = @model.connection.check_constraints(@model.table_name)
|
23
|
+
return "" if check_constraints.empty?
|
24
|
+
|
25
|
+
max_size = check_constraints.map { |check_constraint| check_constraint.name.size }.max + 1
|
26
|
+
check_constraints.sort_by(&:name).each do |check_constraint|
|
27
|
+
expression = check_constraint.expression ? "(#{check_constraint.expression.squish})" : nil
|
28
|
+
|
29
|
+
constraint_info += if @options[:format_markdown]
|
30
|
+
cc_info_in_markdown(check_constraint.name, expression)
|
31
|
+
else
|
32
|
+
cc_info_string(check_constraint.name, expression, max_size)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
constraint_info
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def cc_info_in_markdown(name, expression)
|
42
|
+
cc_info_markdown = sprintf("# * `%s`", name)
|
43
|
+
cc_info_markdown += sprintf(": `%s`", expression) if expression
|
44
|
+
cc_info_markdown += "\n"
|
45
|
+
|
46
|
+
cc_info_markdown
|
47
|
+
end
|
48
|
+
|
49
|
+
def cc_info_string(name, expression, max_size)
|
50
|
+
# standard:disable Lint/FormatParameterMismatch
|
51
|
+
sprintf("# %-#{max_size}.#{max_size}s %s", name, expression).rstrip + "\n"
|
52
|
+
# standard:enable Lint/FormatParameterMismatch
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -19,19 +19,17 @@ module AnnotateRb
|
|
19
19
|
|
20
20
|
attr_reader :parser
|
21
21
|
|
22
|
-
def initialize(content, wrapper_open, wrapper_close)
|
22
|
+
def initialize(content, wrapper_open, wrapper_close, parser)
|
23
23
|
@content = content
|
24
24
|
@wrapper_open = wrapper_open
|
25
25
|
@wrapper_close = wrapper_close
|
26
26
|
@annotation_start = nil
|
27
27
|
@annotation_end = nil
|
28
|
-
@parser =
|
28
|
+
@parser = parser
|
29
29
|
end
|
30
30
|
|
31
31
|
# Find the annotation's line start and line end
|
32
32
|
def run
|
33
|
-
# CustomParser returns line numbers as 0-indexed
|
34
|
-
@parser = FileParser::CustomParser.new(@content, "", 0).tap(&:parse)
|
35
33
|
comments = @parser.comments
|
36
34
|
|
37
35
|
start = comments.find_index { |comment, _| comment.include?(COMPAT_PREFIX) || comment.include?(COMPAT_PREFIX_MD) }
|
@@ -6,15 +6,17 @@ module AnnotateRb
|
|
6
6
|
class ParsedFile
|
7
7
|
SKIP_ANNOTATION_STRING = "# -*- SkipSchemaAnnotations"
|
8
8
|
|
9
|
-
def initialize(file_content, new_annotations, options)
|
9
|
+
def initialize(file_content, new_annotations, parser_klass, options)
|
10
10
|
@file_content = file_content
|
11
11
|
@file_lines = @file_content.lines
|
12
12
|
@new_annotations = new_annotations
|
13
|
+
@parser_klass = parser_klass
|
13
14
|
@options = options
|
14
15
|
end
|
15
16
|
|
16
17
|
def parse
|
17
|
-
@
|
18
|
+
@file_parser = @parser_klass.parse(@file_content)
|
19
|
+
@finder = AnnotationFinder.new(@file_content, @options[:wrapper_open], @options[:wrapper_close], @file_parser)
|
18
20
|
has_annotations = false
|
19
21
|
|
20
22
|
begin
|
@@ -30,7 +32,6 @@ module AnnotateRb
|
|
30
32
|
end
|
31
33
|
|
32
34
|
@diff = AnnotationDiffGenerator.new(annotations, @new_annotations).generate
|
33
|
-
@file_parser = @finder.parser
|
34
35
|
|
35
36
|
has_skip_string = @file_parser.comments.any? { |comment, _lineno| comment.include?(SKIP_ANNOTATION_STRING) }
|
36
37
|
annotations_changed = @diff.changed?
|
@@ -85,7 +86,9 @@ module AnnotateRb
|
|
85
86
|
annotations_with_whitespace: annotations_with_whitespace,
|
86
87
|
has_leading_whitespace: has_leading_whitespace,
|
87
88
|
has_trailing_whitespace: has_trailing_whitespace,
|
88
|
-
annotation_position: annotation_position
|
89
|
+
annotation_position: annotation_position,
|
90
|
+
starts: @file_parser.starts,
|
91
|
+
ends: @file_parser.ends
|
89
92
|
)
|
90
93
|
end
|
91
94
|
end
|
@@ -12,7 +12,9 @@ module AnnotateRb
|
|
12
12
|
annotations_with_whitespace:,
|
13
13
|
has_leading_whitespace:,
|
14
14
|
has_trailing_whitespace:,
|
15
|
-
annotation_position
|
15
|
+
annotation_position:,
|
16
|
+
starts:,
|
17
|
+
ends:
|
16
18
|
)
|
17
19
|
@has_annotations = has_annotations
|
18
20
|
@has_skip_string = has_skip_string
|
@@ -22,9 +24,11 @@ module AnnotateRb
|
|
22
24
|
@has_leading_whitespace = has_leading_whitespace
|
23
25
|
@has_trailing_whitespace = has_trailing_whitespace
|
24
26
|
@annotation_position = annotation_position
|
27
|
+
@starts = starts
|
28
|
+
@ends = ends
|
25
29
|
end
|
26
30
|
|
27
|
-
attr_reader :annotations, :annotation_position
|
31
|
+
attr_reader :annotations, :annotation_position, :starts, :ends
|
28
32
|
|
29
33
|
# Returns annotations with new line before and after if they exist
|
30
34
|
attr_reader :annotations_with_whitespace
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "psych"
|
4
|
+
|
5
|
+
module AnnotateRb
|
6
|
+
module ModelAnnotator
|
7
|
+
module FileParser
|
8
|
+
class YmlParser
|
9
|
+
class << self
|
10
|
+
def parse(string)
|
11
|
+
_parser = new(string).tap(&:parse)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :comments, :starts, :ends
|
16
|
+
|
17
|
+
def initialize(input)
|
18
|
+
@input = input
|
19
|
+
@comments = []
|
20
|
+
@starts = []
|
21
|
+
@ends = []
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse
|
25
|
+
parse_comments
|
26
|
+
parse_yml
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def parse_comments
|
32
|
+
# Adds 0-indexed line numbers
|
33
|
+
@input.split($/).each_with_index do |line, line_no|
|
34
|
+
if line.strip.starts_with?("#")
|
35
|
+
@comments << [line, line_no]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_yml
|
41
|
+
# https://docs.ruby-lang.org/en/master/Psych.html#module-Psych-label-Reading+to+Psych-3A-3ANodes-3A-3AStream+structure
|
42
|
+
parser = Psych.parser
|
43
|
+
parser.parse(@input)
|
44
|
+
|
45
|
+
stream = parser.handler.root
|
46
|
+
|
47
|
+
if stream.children.any?
|
48
|
+
doc = stream.children.first
|
49
|
+
@starts << [nil, doc.start_line]
|
50
|
+
@ends << [nil, doc.end_line]
|
51
|
+
else
|
52
|
+
# When parsing a yml file, streamer returns an instance of `Psych::Nodes::Stream` which is a subclass of
|
53
|
+
# `Psych::Nodes::Node`. It along with children nodes, implement #start_line and #end_line.
|
54
|
+
#
|
55
|
+
# When parsing input that is only comments, the parser counts #start_line as the start of the file being
|
56
|
+
# line 0.
|
57
|
+
#
|
58
|
+
# What we really want is where the "start" of the yml file would happen, which would be after comments.
|
59
|
+
# This is stream#end_line.
|
60
|
+
@starts << [nil, stream.end_line]
|
61
|
+
@ends << [nil, stream.end_line]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -7,6 +7,7 @@ module AnnotateRb
|
|
7
7
|
autoload :CustomParser, "annotate_rb/model_annotator/file_parser/custom_parser"
|
8
8
|
autoload :ParsedFile, "annotate_rb/model_annotator/file_parser/parsed_file"
|
9
9
|
autoload :ParsedFileResult, "annotate_rb/model_annotator/file_parser/parsed_file_result"
|
10
|
+
autoload :YmlParser, "annotate_rb/model_annotator/file_parser/yml_parser"
|
10
11
|
end
|
11
12
|
end
|
12
13
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnnotateRb
|
4
|
+
module ModelAnnotator
|
5
|
+
class FileToParserMapper
|
6
|
+
class UnsupportedFileTypeError < StandardError; end
|
7
|
+
|
8
|
+
MAP = {
|
9
|
+
".rb" => FileParser::CustomParser,
|
10
|
+
".yml" => FileParser::YmlParser
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def map(file_name)
|
15
|
+
extension = File.extname(file_name).downcase
|
16
|
+
parser = MAP[extension]
|
17
|
+
|
18
|
+
raise UnsupportedFileTypeError, "File '#{file_name}' does not have a supported file type." if parser.nil?
|
19
|
+
|
20
|
+
parser
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -88,22 +88,51 @@ module AnnotateRb
|
|
88
88
|
when "scaffold" then scaffold_files(root_directory)
|
89
89
|
when "factory" then factory_files(root_directory)
|
90
90
|
when "serializer" then serialize_files(root_directory)
|
91
|
-
when "
|
92
|
-
|
93
|
-
when "controller"
|
94
|
-
|
95
|
-
when "admin"
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
]
|
100
|
-
when "helper"
|
101
|
-
[File.join(root_directory, FilePatterns::HELPER_DIR, "%PLURALIZED_MODEL_NAME%_helper.rb")]
|
91
|
+
when "serializer_test" then serializer_test_files(root_directory)
|
92
|
+
when "additional_file_patterns" then additional_file_patterns
|
93
|
+
when "controller" then controller_files(root_directory)
|
94
|
+
when "controller_test" then controller_test_files(root_directory)
|
95
|
+
when "admin" then active_admin_files(root_directory)
|
96
|
+
when "helper" then helper_files(root_directory)
|
97
|
+
when "request_spec" then request_spec_files(root_directory)
|
98
|
+
when "routing_spec" then routing_spec_files(root_directory)
|
102
99
|
else
|
103
100
|
[]
|
104
101
|
end
|
105
102
|
end
|
106
103
|
|
104
|
+
def controller_files(root_directory)
|
105
|
+
[
|
106
|
+
File.join(root_directory, FilePatterns::CONTROLLER_DIR, "%PLURALIZED_MODEL_NAME%_controller.rb")
|
107
|
+
]
|
108
|
+
end
|
109
|
+
|
110
|
+
def controller_test_files(root_directory)
|
111
|
+
[
|
112
|
+
File.join(root_directory, FilePatterns::CONTROLLER_TEST_DIR, "%PLURALIZED_MODEL_NAME%_controller_test.rb"),
|
113
|
+
File.join(root_directory, FilePatterns::CONTROLLER_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_controller_spec.rb")
|
114
|
+
]
|
115
|
+
end
|
116
|
+
|
117
|
+
def additional_file_patterns
|
118
|
+
[
|
119
|
+
@options[:additional_file_patterns] || []
|
120
|
+
].flatten
|
121
|
+
end
|
122
|
+
|
123
|
+
def active_admin_files(root_directory)
|
124
|
+
[
|
125
|
+
File.join(root_directory, FilePatterns::ACTIVEADMIN_DIR, "%MODEL_NAME%.rb"),
|
126
|
+
File.join(root_directory, FilePatterns::ACTIVEADMIN_DIR, "%PLURALIZED_MODEL_NAME%.rb")
|
127
|
+
]
|
128
|
+
end
|
129
|
+
|
130
|
+
def helper_files(root_directory)
|
131
|
+
[
|
132
|
+
File.join(root_directory, FilePatterns::HELPER_DIR, "%PLURALIZED_MODEL_NAME%_helper.rb")
|
133
|
+
]
|
134
|
+
end
|
135
|
+
|
107
136
|
def test_files(root_directory)
|
108
137
|
[
|
109
138
|
File.join(root_directory, FilePatterns::UNIT_TEST_DIR, "%MODEL_NAME%_test.rb"),
|
@@ -122,10 +151,17 @@ module AnnotateRb
|
|
122
151
|
end
|
123
152
|
|
124
153
|
def scaffold_files(root_directory)
|
154
|
+
controller_test_files(root_directory) + request_spec_files(root_directory) + routing_spec_files(root_directory)
|
155
|
+
end
|
156
|
+
|
157
|
+
def request_spec_files(root_directory)
|
158
|
+
[
|
159
|
+
File.join(root_directory, FilePatterns::REQUEST_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_spec.rb")
|
160
|
+
]
|
161
|
+
end
|
162
|
+
|
163
|
+
def routing_spec_files(root_directory)
|
125
164
|
[
|
126
|
-
File.join(root_directory, FilePatterns::CONTROLLER_TEST_DIR, "%PLURALIZED_MODEL_NAME%_controller_test.rb"),
|
127
|
-
File.join(root_directory, FilePatterns::CONTROLLER_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_controller_spec.rb"),
|
128
|
-
File.join(root_directory, FilePatterns::REQUEST_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_spec.rb"),
|
129
165
|
File.join(root_directory, FilePatterns::ROUTING_SPEC_DIR, "%PLURALIZED_MODEL_NAME%_routing_spec.rb")
|
130
166
|
]
|
131
167
|
end
|
@@ -151,7 +187,12 @@ module AnnotateRb
|
|
151
187
|
|
152
188
|
def serialize_files(root_directory)
|
153
189
|
[
|
154
|
-
File.join(root_directory, FilePatterns::SERIALIZERS_DIR, "%MODEL_NAME%_serializer.rb")
|
190
|
+
File.join(root_directory, FilePatterns::SERIALIZERS_DIR, "%MODEL_NAME%_serializer.rb")
|
191
|
+
]
|
192
|
+
end
|
193
|
+
|
194
|
+
def serializer_test_files(root_directory)
|
195
|
+
[
|
155
196
|
File.join(root_directory, FilePatterns::SERIALIZERS_TEST_DIR, "%MODEL_NAME%_serializer_test.rb"),
|
156
197
|
File.join(root_directory, FilePatterns::SERIALIZERS_SPEC_DIR, "%MODEL_NAME%_serializer_spec.rb")
|
157
198
|
]
|
@@ -7,6 +7,9 @@ module AnnotateRb
|
|
7
7
|
class RelatedFilesListBuilder
|
8
8
|
RELATED_TYPES = %w[test fixture factory serializer scaffold controller helper].freeze
|
9
9
|
|
10
|
+
# Valid options when `:exclude_tests` is an Array, note that symbols are expected
|
11
|
+
EXCLUDE_TEST_OPTIONS = %i[model controller serializer request routing].freeze
|
12
|
+
|
10
13
|
def initialize(file, model_name, table_name, options)
|
11
14
|
@file = file
|
12
15
|
@model_name = model_name
|
@@ -17,11 +20,14 @@ module AnnotateRb
|
|
17
20
|
def build
|
18
21
|
@list = []
|
19
22
|
|
20
|
-
add_related_test_files if
|
23
|
+
add_related_test_files if !exclude_model_test_files?
|
21
24
|
add_related_fixture_files if !@options[:exclude_fixtures]
|
22
25
|
add_related_factory_files if !@options[:exclude_factories]
|
23
26
|
add_related_serializer_files if !@options[:exclude_serializers]
|
24
|
-
|
27
|
+
add_related_serializer_test_files if !exclude_serializer_tests?
|
28
|
+
add_related_controller_test_files if !exclude_controller_tests?
|
29
|
+
add_related_request_spec_files if !exclude_request_specs?
|
30
|
+
add_related_routing_spec_files if !exclude_routing_specs?
|
25
31
|
add_related_controller_files if !@options[:exclude_controllers]
|
26
32
|
add_related_helper_files if !@options[:exclude_helpers]
|
27
33
|
add_related_admin_files if @options[:active_admin]
|
@@ -32,6 +38,51 @@ module AnnotateRb
|
|
32
38
|
|
33
39
|
private
|
34
40
|
|
41
|
+
def exclude_model_test_files?
|
42
|
+
option = @options[:exclude_tests]
|
43
|
+
|
44
|
+
# If exclude_tests: [:model] then
|
45
|
+
# 1) we want to exclude model test files, and
|
46
|
+
# 2) we don't want to include model test files
|
47
|
+
if option.is_a?(Array)
|
48
|
+
option.include?(:model)
|
49
|
+
else
|
50
|
+
option
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def exclude_serializer_tests?
|
55
|
+
if @options[:exclude_tests].is_a?(Array)
|
56
|
+
@options[:exclude_tests].include?(:serializer)
|
57
|
+
else
|
58
|
+
@options[:exclude_serializers]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def exclude_controller_tests?
|
63
|
+
if @options[:exclude_tests].is_a?(Array)
|
64
|
+
@options[:exclude_tests].include?(:controller)
|
65
|
+
else
|
66
|
+
@options[:exclude_scaffolds]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def exclude_routing_specs?
|
71
|
+
if @options[:exclude_tests].is_a?(Array)
|
72
|
+
@options[:exclude_tests].include?(:routing)
|
73
|
+
else
|
74
|
+
@options[:exclude_scaffolds]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def exclude_request_specs?
|
79
|
+
if @options[:exclude_tests].is_a?(Array)
|
80
|
+
@options[:exclude_tests].include?(:request)
|
81
|
+
else
|
82
|
+
@options[:exclude_scaffolds]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
35
86
|
def related_files_for_pattern(pattern_type)
|
36
87
|
patterns = PatternGetter.call(@options, pattern_type)
|
37
88
|
|
@@ -81,9 +132,9 @@ module AnnotateRb
|
|
81
132
|
@list.concat(files_with_position_key)
|
82
133
|
end
|
83
134
|
|
84
|
-
def
|
85
|
-
position_key = :
|
86
|
-
pattern_type = "
|
135
|
+
def add_related_serializer_test_files
|
136
|
+
position_key = :position_in_serializer
|
137
|
+
pattern_type = "serializer_test"
|
87
138
|
|
88
139
|
related_files = related_files_for_pattern(pattern_type)
|
89
140
|
files_with_position_key = related_files.map { |f| [f, position_key] }
|
@@ -101,6 +152,36 @@ module AnnotateRb
|
|
101
152
|
@list.concat(files_with_position_key)
|
102
153
|
end
|
103
154
|
|
155
|
+
def add_related_controller_test_files
|
156
|
+
position_key = :position_in_scaffold # Key does not exist
|
157
|
+
pattern_type = "controller_test"
|
158
|
+
|
159
|
+
related_files = related_files_for_pattern(pattern_type)
|
160
|
+
files_with_position_key = related_files.map { |f| [f, position_key] }
|
161
|
+
|
162
|
+
@list.concat(files_with_position_key)
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_related_request_spec_files
|
166
|
+
position_key = :position_in_scaffold # Key does not exist
|
167
|
+
pattern_type = "request_spec"
|
168
|
+
|
169
|
+
related_files = related_files_for_pattern(pattern_type)
|
170
|
+
files_with_position_key = related_files.map { |f| [f, position_key] }
|
171
|
+
|
172
|
+
@list.concat(files_with_position_key)
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_related_routing_spec_files
|
176
|
+
position_key = :position_in_scaffold # Key does not exist
|
177
|
+
pattern_type = "routing_spec"
|
178
|
+
|
179
|
+
related_files = related_files_for_pattern(pattern_type)
|
180
|
+
files_with_position_key = related_files.map { |f| [f, position_key] }
|
181
|
+
|
182
|
+
@list.concat(files_with_position_key)
|
183
|
+
end
|
184
|
+
|
104
185
|
def add_related_helper_files
|
105
186
|
position_key = :position_in_helper # Key does not exist
|
106
187
|
pattern_type = "helper"
|
@@ -12,8 +12,10 @@ module AnnotateRb
|
|
12
12
|
return false unless File.exist?(file_name)
|
13
13
|
old_content = File.read(file_name)
|
14
14
|
|
15
|
+
parser_klass = FileToParserMapper.map(file_name)
|
16
|
+
|
15
17
|
begin
|
16
|
-
parsed_file = FileParser::ParsedFile.new(old_content, "", options).parse
|
18
|
+
parsed_file = FileParser::ParsedFile.new(old_content, "", parser_klass, options).parse
|
17
19
|
rescue FileParser::AnnotationFinder::MalformedAnnotation => e
|
18
20
|
warn "Unable to process #{file_name}: #{e.message}"
|
19
21
|
warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
|
@@ -25,8 +25,10 @@ module AnnotateRb
|
|
25
25
|
return false unless File.exist?(file_name)
|
26
26
|
old_content = File.read(file_name)
|
27
27
|
|
28
|
+
parser_klass = FileToParserMapper.map(file_name)
|
29
|
+
|
28
30
|
begin
|
29
|
-
parsed_file = FileParser::ParsedFile.new(old_content, annotation, options).parse
|
31
|
+
parsed_file = FileParser::ParsedFile.new(old_content, annotation, parser_klass, options).parse
|
30
32
|
rescue FileParser::AnnotationFinder::MalformedAnnotation => e
|
31
33
|
warn "Unable to process #{file_name}: #{e.message}"
|
32
34
|
warn "\t" + e.backtrace.join("\n\t") if @options[:trace]
|
@@ -39,11 +41,11 @@ module AnnotateRb
|
|
39
41
|
abort "AnnotateRb error. #{file_name} needs to be updated, but annotaterb was run with `--frozen`." if options[:frozen]
|
40
42
|
|
41
43
|
updated_file_content = if !parsed_file.has_annotations?
|
42
|
-
AnnotatedFile::Generator.new(old_content, annotation, annotation_position, options).generate
|
44
|
+
AnnotatedFile::Generator.new(old_content, annotation, annotation_position, parser_klass, parsed_file, options).generate
|
43
45
|
elsif options[:force]
|
44
|
-
AnnotatedFile::Generator.new(old_content, annotation, annotation_position, options).generate
|
46
|
+
AnnotatedFile::Generator.new(old_content, annotation, annotation_position, parser_klass, parsed_file, options).generate
|
45
47
|
else
|
46
|
-
AnnotatedFile::Updater.new(old_content, annotation, annotation_position, options).update
|
48
|
+
AnnotatedFile::Updater.new(old_content, annotation, annotation_position, parsed_file, options).update
|
47
49
|
end
|
48
50
|
|
49
51
|
File.open(file_name, "wb") { |f| f.puts updated_file_content }
|
@@ -26,5 +26,7 @@ module AnnotateRb
|
|
26
26
|
autoload :AnnotatedFile, "annotate_rb/model_annotator/annotated_file"
|
27
27
|
autoload :FileParser, "annotate_rb/model_annotator/file_parser"
|
28
28
|
autoload :ZeitwerkClassGetter, "annotate_rb/model_annotator/zeitwerk_class_getter"
|
29
|
+
autoload :CheckConstraintAnnotation, "annotate_rb/model_annotator/check_constraint_annotation"
|
30
|
+
autoload :FileToParserMapper, "annotate_rb/model_annotator/file_to_parser_mapper"
|
29
31
|
end
|
30
32
|
end
|
data/lib/annotate_rb/options.rb
CHANGED
@@ -45,6 +45,7 @@ module AnnotateRb
|
|
45
45
|
ignore_unknown_models: false, # ModelAnnotator
|
46
46
|
include_version: false, # ModelAnnotator
|
47
47
|
show_complete_foreign_keys: false, # ModelAnnotator
|
48
|
+
show_check_constraints: false, # ModelAnnotator
|
48
49
|
show_foreign_keys: true, # ModelAnnotator
|
49
50
|
show_indexes: true, # ModelAnnotator
|
50
51
|
simple_indexes: false, # ModelAnnotator
|
@@ -109,6 +110,7 @@ module AnnotateRb
|
|
109
110
|
:ignore_model_sub_dir,
|
110
111
|
:ignore_unknown_models,
|
111
112
|
:include_version,
|
113
|
+
:show_check_constraints,
|
112
114
|
:show_complete_foreign_keys,
|
113
115
|
:show_foreign_keys,
|
114
116
|
:show_indexes,
|
@@ -161,6 +163,8 @@ module AnnotateRb
|
|
161
163
|
|
162
164
|
# For now, state is a hash to store state that we need but is not a configuration option
|
163
165
|
@state = state
|
166
|
+
|
167
|
+
symbolize_exclude_tests
|
164
168
|
end
|
165
169
|
|
166
170
|
def to_h
|
@@ -216,5 +220,21 @@ module AnnotateRb
|
|
216
220
|
def print
|
217
221
|
# TODO: prints options and state
|
218
222
|
end
|
223
|
+
|
224
|
+
private
|
225
|
+
|
226
|
+
# Guard against user inputting strings instead of symbols
|
227
|
+
def symbolize_exclude_tests
|
228
|
+
# `:exclude_tests` option is being expanded to function as a boolean OR an array of symbols
|
229
|
+
# https://github.com/drwl/annotaterb/issues/103
|
230
|
+
|
231
|
+
if @options[:exclude_tests].is_a?(Array)
|
232
|
+
@options[:exclude_tests].map! do |item|
|
233
|
+
item = item.strip if item.respond_to?(:strip)
|
234
|
+
|
235
|
+
item.to_sym
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
219
239
|
end
|
220
240
|
end
|
data/lib/annotate_rb/parser.rb
CHANGED
@@ -198,6 +198,12 @@ module AnnotateRb
|
|
198
198
|
@options[:simple_indexes] = true
|
199
199
|
end
|
200
200
|
|
201
|
+
option_parser.on("-c",
|
202
|
+
"--show-check-constraints",
|
203
|
+
"List the table's check constraints in the annotation") do
|
204
|
+
@options[:show_check_constraints] = true
|
205
|
+
end
|
206
|
+
|
201
207
|
option_parser.on("--hide-limit-column-types VALUES",
|
202
208
|
"don't show limit for given column types, separated by commas (i.e., `integer,boolean,text`)") do |values|
|
203
209
|
@options[:hide_limit_column_types] = values.to_s
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: annotaterb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew W. Lee
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Annotates Rails/ActiveRecord Models, routes, fixtures, and others based
|
14
14
|
on the database schema.
|
@@ -46,6 +46,8 @@ files:
|
|
46
46
|
- lib/annotate_rb/model_annotator/annotation_diff_generator.rb
|
47
47
|
- lib/annotate_rb/model_annotator/annotator.rb
|
48
48
|
- lib/annotate_rb/model_annotator/bad_model_file_error.rb
|
49
|
+
- lib/annotate_rb/model_annotator/check_constraint_annotation.rb
|
50
|
+
- lib/annotate_rb/model_annotator/check_constraint_annotation/annotation_builder.rb
|
49
51
|
- lib/annotate_rb/model_annotator/column_annotation.rb
|
50
52
|
- lib/annotate_rb/model_annotator/column_annotation/annotation_builder.rb
|
51
53
|
- lib/annotate_rb/model_annotator/column_annotation/attributes_builder.rb
|
@@ -58,6 +60,8 @@ files:
|
|
58
60
|
- lib/annotate_rb/model_annotator/file_parser/custom_parser.rb
|
59
61
|
- lib/annotate_rb/model_annotator/file_parser/parsed_file.rb
|
60
62
|
- lib/annotate_rb/model_annotator/file_parser/parsed_file_result.rb
|
63
|
+
- lib/annotate_rb/model_annotator/file_parser/yml_parser.rb
|
64
|
+
- lib/annotate_rb/model_annotator/file_to_parser_mapper.rb
|
61
65
|
- lib/annotate_rb/model_annotator/foreign_key_annotation.rb
|
62
66
|
- lib/annotate_rb/model_annotator/foreign_key_annotation/annotation_builder.rb
|
63
67
|
- lib/annotate_rb/model_annotator/index_annotation.rb
|