rails-annotate-solargraph 0.2.3 → 0.5.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/.vscode/settings.json +5 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +3 -1
- data/README.md +22 -2
- data/lib/generators/annotate/solargraph/install_generator.rb +16 -0
- data/lib/generators/annotate/solargraph/templates/.annotate_solargraph_schema +69 -0
- data/lib/generators/annotate/solargraph/templates/rails_annotate_solargraph.rake +1 -0
- data/lib/rails/annotate/solargraph/configuration.rb +6 -2
- data/lib/rails/annotate/solargraph/model.rb +197 -52
- data/lib/rails/annotate/solargraph/version.rb +1 -1
- data/lib/rails/annotate/solargraph.rb +17 -0
- data/rails-annotate-solargraph.gemspec +3 -1
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 641aad34ff5a1a7f98a1eca52baf74c311308b2e9e062cf8c5ac3c0186d1f1ec
|
4
|
+
data.tar.gz: 70657a49775862f8b50dc2e04f7b489b04f124cbfb4893f777f5a11f69b0ba51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a2c58e2d0dbb0dd0df66d1f2f04242095081c4159059c8830021cc16f9ece5222dc9fee73392757b88cf1798f5e53256a09fc2291585b8474c36db8777d64f2
|
7
|
+
data.tar.gz: 6335dab053b82ff232fdcc69c3453eea68ae44432bd6f4032f29ab812072e9053795955556f14578479bd47ebd37a3bfc6ac592254de63801d38369834dcc358
|
data/.vscode/settings.json
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.0] - 2022-04-19
|
4
|
+
|
5
|
+
- Add some static comments to the schema file to improve general Rails intellisense
|
6
|
+
- Rename schema file from `app/models/annotate_solargraph_schema.rb` to `.annotate-solargraph-schema`
|
7
|
+
- Generate schema file as a regular ruby file
|
8
|
+
- Add `yard` and `solargraph` as dependencies
|
9
|
+
- Add `.solargraph.yml` to the installation generator
|
10
|
+
|
11
|
+
## [0.4.0] - 2022-04-17
|
12
|
+
|
13
|
+
- Annotations get saved to a schema file by default `app/models/annotate_solargraph_schema.rb`
|
14
|
+
|
15
|
+
## [0.3.0] - 2022-04-17
|
16
|
+
|
17
|
+
- `has_many :through` and `has_one :through` relations get documented
|
18
|
+
|
3
19
|
## [0.2.3] - 2022-04-16
|
4
20
|
|
5
21
|
- A nicer fix for the previous problem
|
@@ -15,6 +31,7 @@
|
|
15
31
|
## [0.2.0] - 2022-04-16
|
16
32
|
|
17
33
|
- Associations get fully documented
|
34
|
+
- `has_many`, `has_one` and `belongs_to` relations get documented
|
18
35
|
|
19
36
|
## [0.1.1] - 2022-04-15
|
20
37
|
|
@@ -24,4 +41,5 @@
|
|
24
41
|
|
25
42
|
- Initial release
|
26
43
|
- Automatic generation of annotations after migrations
|
44
|
+
- Database fields get documented
|
27
45
|
- Manual rake tasks `annotate:solargraph:generate`, `annotate:solargraph:remove`
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -63,11 +63,31 @@ You can change the gem's default configuration like so:
|
|
63
63
|
```ruby
|
64
64
|
# config/initializers/rails_annotate_solargraph.rb
|
65
65
|
|
66
|
-
Rails
|
67
|
-
|
66
|
+
if ::Rails.env.development?
|
67
|
+
::Rails::Annotate::Solargraph.configure do |conf|
|
68
|
+
conf.annotation_position = :top # `:schema_file` by default
|
69
|
+
end
|
68
70
|
end
|
69
71
|
```
|
70
72
|
|
73
|
+
#### annotation_position
|
74
|
+
|
75
|
+
There are a few values for this option:
|
76
|
+
|
77
|
+
- `:schema_file` -- default value, annotations get saved to a special file `app/models/annotate_solargraph_schema.rb`
|
78
|
+
- `:bottom` -- annotations are appended to the model files
|
79
|
+
- `:top` -- annotations are prepended to the model files
|
80
|
+
|
81
|
+
### Update
|
82
|
+
|
83
|
+
To update this gem you should generate the rakefiles once again. Overwrite them.
|
84
|
+
|
85
|
+
```sh
|
86
|
+
$ rails g annotate:solargraph:install
|
87
|
+
$ rake annotate:solargraph:remove
|
88
|
+
$ rake annotate:solargraph:generate
|
89
|
+
```
|
90
|
+
|
71
91
|
## Development
|
72
92
|
|
73
93
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -1,3 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'set'
|
5
|
+
|
1
6
|
module Annotate
|
2
7
|
module Solargraph
|
3
8
|
module Generators
|
@@ -8,6 +13,17 @@ module Annotate
|
|
8
13
|
# copy rake tasks
|
9
14
|
def copy_tasks
|
10
15
|
template ::Rails::Annotate::Solargraph::RAKEFILE_NAME, ::File.join('lib', 'tasks', ::Rails::Annotate::Solargraph::RAKEFILE_NAME)
|
16
|
+
template ::Rails::Annotate::Solargraph::SCHEMA_FILE_NAME, ::Rails::Annotate::Solargraph::SCHEMA_RAILS_PATH
|
17
|
+
|
18
|
+
solargraph_config_file = ::File.join(::Rails.root, ::Rails::Annotate::Solargraph::SOLARGRAPH_FILE_NAME)
|
19
|
+
system 'solargraph config' unless ::File.exist? solargraph_config_file
|
20
|
+
solargraph_config = ::YAML.load_file solargraph_config_file
|
21
|
+
solargraph_config['include'] = solargraph_config['include'] || []
|
22
|
+
solargraph_config['include'].unshift ::Rails::Annotate::Solargraph::SCHEMA_RAILS_PATH
|
23
|
+
# make sure there are no duplicated entries
|
24
|
+
solargraph_config['include'] = solargraph_config['include'].to_set.to_a
|
25
|
+
|
26
|
+
::File.write(solargraph_config_file, solargraph_config.to_yaml)
|
11
27
|
end
|
12
28
|
end
|
13
29
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# This is a dummy file generated by `rails-annotate-solargraph`
|
2
|
+
# to extend solargraph's understanding of your Rails app.
|
3
|
+
# You should probably add it to `.gitignore`
|
4
|
+
|
5
|
+
# Some static comments to fill a few gaps
|
6
|
+
# in Rails comprehension.
|
7
|
+
|
8
|
+
class ActionController::Base
|
9
|
+
include ActionController::MimeResponds
|
10
|
+
include ActionController::Redirecting
|
11
|
+
include ActionController::Cookies
|
12
|
+
include AbstractController::Rendering
|
13
|
+
extend ActiveSupport::Callbacks::ClassMethods
|
14
|
+
extend ActiveSupport::Rescuable::ClassMethods
|
15
|
+
extend AbstractController::Callbacks::ClassMethods
|
16
|
+
extend ActionController::RequestForgeryProtection::ClassMethods
|
17
|
+
end
|
18
|
+
class ActiveRecord::Base
|
19
|
+
extend ActiveRecord::Reflection::ClassMethods
|
20
|
+
extend ActiveModel::SecurePassword::ClassMethods
|
21
|
+
extend ActiveModel::Attributes::ClassMethods
|
22
|
+
include ActiveModel::Attributes
|
23
|
+
include ActiveModel::Dirty
|
24
|
+
extend ActiveRecord::Validations::ClassMethods
|
25
|
+
include ActiveRecord::Validations
|
26
|
+
extend ActiveModel::Validations::ClassMethods
|
27
|
+
include ActiveModel::Validations
|
28
|
+
extend ActiveRecord::Calculations
|
29
|
+
extend ActiveRecord::Batches
|
30
|
+
extend ActiveRecord::QueryMethods
|
31
|
+
extend ActiveRecord::FinderMethods
|
32
|
+
extend ActiveRecord::Associations::ClassMethods
|
33
|
+
extend ActiveRecord::Inheritance::ClassMethods
|
34
|
+
extend ActiveRecord::ModelSchema::ClassMethods
|
35
|
+
extend ActiveRecord::Transactions::ClassMethods
|
36
|
+
extend ActiveRecord::Scoping::Named::ClassMethods
|
37
|
+
include ActiveRecord::Persistence
|
38
|
+
|
39
|
+
<% (ActiveRecord::Callbacks::CALLBACKS rescue []).each do |callback| -%>
|
40
|
+
# Registers a callback to be called <%= callback.to_s.gsub('_', ' ') %>.
|
41
|
+
# See `ActiveRecord::Callbacks` for more information.
|
42
|
+
# @return [void]
|
43
|
+
def self.<%= callback %>(*args, &block); end
|
44
|
+
<% end -%>
|
45
|
+
|
46
|
+
end
|
47
|
+
class Rails
|
48
|
+
# @return [Rails::Application]
|
49
|
+
def self.application; end
|
50
|
+
end
|
51
|
+
class Rails::Application
|
52
|
+
# @return [ActionDispatch::Routing::RouteSet]
|
53
|
+
def routes; end
|
54
|
+
end
|
55
|
+
class ActionDispatch::Routing::Mapper
|
56
|
+
include ActionDispatch::Routing::Mapper::Base
|
57
|
+
include ActionDispatch::Routing::Mapper::HttpHelpers
|
58
|
+
include ActionDispatch::Routing::Mapper::Redirection
|
59
|
+
include ActionDispatch::Routing::Mapper::Scoping
|
60
|
+
include ActionDispatch::Routing::Mapper::Concerns
|
61
|
+
include ActionDispatch::Routing::Mapper::Resources
|
62
|
+
include ActionDispatch::Routing::Mapper::CustomUrls
|
63
|
+
end
|
64
|
+
class ActionDispatch::Routing::RouteSet
|
65
|
+
# @yieldself [ActionDispatch::Routing::Mapper]
|
66
|
+
def draw; end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Dynamically generated documentation
|
@@ -9,10 +9,10 @@ module Rails
|
|
9
9
|
# @return [Symbol]
|
10
10
|
attr_reader :annotation_position
|
11
11
|
|
12
|
-
ANNOTATION_POSITIONS = ::Set[:bottom, :top].freeze
|
12
|
+
ANNOTATION_POSITIONS = ::Set[:bottom, :top, :schema_file].freeze
|
13
13
|
|
14
14
|
def initialize
|
15
|
-
@annotation_position = :
|
15
|
+
@annotation_position = :schema_file
|
16
16
|
end
|
17
17
|
|
18
18
|
# @param val [Symbol]
|
@@ -22,6 +22,10 @@ module Rails
|
|
22
22
|
|
23
23
|
@annotation_position = val
|
24
24
|
end
|
25
|
+
|
26
|
+
def schema_file?
|
27
|
+
@annotation_position == :schema_file
|
28
|
+
end
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
@@ -1,44 +1,55 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'fileutils'
|
4
|
+
|
3
5
|
module Rails
|
4
6
|
module Annotate
|
5
7
|
module Solargraph
|
6
8
|
class Model
|
7
9
|
using TerminalColors::Refinement
|
8
10
|
|
9
|
-
# @return [String]
|
10
|
-
ANNOTATION_START = "\n# %%<RailsAnnotateSolargraph:Start>%%"
|
11
|
-
# @return [String]
|
12
|
-
ANNOTATION_END = "%%<RailsAnnotateSolargraph:End>%%\n\n"
|
13
|
-
# @return [Regexp]
|
14
|
-
ANNOTATION_REGEXP = /#{ANNOTATION_START}.*#{ANNOTATION_END}/m.freeze
|
15
11
|
# @return [Regexp]
|
16
12
|
MAGIC_COMMENT_REGEXP = /(^#\s*encoding:.*(?:\n|r\n))|(^# coding:.*(?:\n|\r\n))|(^# -\*- coding:.*(?:\n|\r\n))|(^# -\*- encoding\s?:.*(?:\n|\r\n))|(^#\s*frozen_string_literal:.+(?:\n|\r\n))|(^# -\*- frozen_string_literal\s*:.+-\*-(?:\n|\r\n))/.freeze
|
17
13
|
|
14
|
+
# @return [Hash{Symbol => String}]
|
15
|
+
TYPE_MAP = {
|
16
|
+
float: 'BigDecimal',
|
17
|
+
decimal: 'BigDecimal',
|
18
|
+
integer: 'Integer',
|
19
|
+
datetime: 'ActiveSupport::TimeWithZone',
|
20
|
+
date: 'Date',
|
21
|
+
string: 'String',
|
22
|
+
boolean: 'Boolean',
|
23
|
+
text: 'String',
|
24
|
+
jsonb: 'Hash',
|
25
|
+
citext: 'String',
|
26
|
+
json: 'Hash',
|
27
|
+
bigint: 'Integer',
|
28
|
+
uuid: 'String',
|
29
|
+
inet: 'IPAddr'
|
30
|
+
}
|
31
|
+
TYPE_MAP.default = 'Object'
|
32
|
+
TYPE_MAP.freeze
|
33
|
+
|
18
34
|
class << self
|
19
|
-
# @param
|
35
|
+
# @param klass [Class]
|
20
36
|
# @return [String]
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
when :boolean
|
38
|
-
'Boolean'
|
39
|
-
else
|
40
|
-
::Object.to_s
|
41
|
-
end
|
37
|
+
def annotation_start(klass = nil)
|
38
|
+
table_name = klass && CONFIG.schema_file? ? ":#{klass.table_name}" : ''
|
39
|
+
"\n# %%<RailsAnnotateSolargraph:Start#{table_name}>%%"
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param klass [Class]
|
43
|
+
# @return [String]
|
44
|
+
def annotation_end(klass = nil)
|
45
|
+
table_name = klass && CONFIG.schema_file? ? ":#{klass.table_name}" : ''
|
46
|
+
"%%<RailsAnnotateSolargraph:End#{table_name}>%%\n\n"
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param klass [Class]
|
50
|
+
# @return [Regexp]
|
51
|
+
def annotation_regexp(klass = nil)
|
52
|
+
/#{annotation_start(klass)}.*#{annotation_end(klass)}/m
|
42
53
|
end
|
43
54
|
end
|
44
55
|
|
@@ -51,7 +62,22 @@ module Rails
|
|
51
62
|
# @param klass [Class]
|
52
63
|
def initialize(klass)
|
53
64
|
@klass = klass
|
54
|
-
@file_name = ::File.join(::Rails.root, MODEL_DIR, "#{klass.to_s.underscore}.rb")
|
65
|
+
@file_name = CONFIG.schema_file? ? SCHEMA_RAILS_PATH : ::File.join(::Rails.root, MODEL_DIR, "#{klass.to_s.underscore}.rb")
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [String]
|
69
|
+
def annotation_start
|
70
|
+
self.class.annotation_start(@klass)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [String]
|
74
|
+
def annotation_end
|
75
|
+
self.class.annotation_end(@klass)
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [Regexp]
|
79
|
+
def annotation_regexp
|
80
|
+
self.class.annotation_regexp(@klass)
|
55
81
|
end
|
56
82
|
|
57
83
|
# @param :write [Boolean]
|
@@ -79,8 +105,10 @@ module Rails
|
|
79
105
|
# @param :write [Boolean]
|
80
106
|
# @return [Array<String>] Old file content followed by new content.
|
81
107
|
def remove_annotation(write: true)
|
108
|
+
return ['', ''] unless ::File.exist?(@file_name)
|
109
|
+
|
82
110
|
file_content = ::File.read(@file_name)
|
83
|
-
new_file_content = file_content.sub(
|
111
|
+
new_file_content = file_content.sub(annotation_regexp, '')
|
84
112
|
result = [file_content, new_file_content]
|
85
113
|
return result unless write
|
86
114
|
return result if file_content == new_file_content
|
@@ -93,8 +121,8 @@ module Rails
|
|
93
121
|
def annotation
|
94
122
|
doc_string = ::String.new
|
95
123
|
doc_string << <<~DOC
|
96
|
-
#{
|
97
|
-
|
124
|
+
#{annotation_start}
|
125
|
+
##{parse_clause}
|
98
126
|
# class #{@klass} < #{@klass.superclass}
|
99
127
|
DOC
|
100
128
|
|
@@ -117,12 +145,23 @@ module Rails
|
|
117
145
|
|
118
146
|
doc_string << <<~DOC.chomp
|
119
147
|
# end
|
120
|
-
# #{
|
148
|
+
# #{annotation_end}
|
121
149
|
DOC
|
150
|
+
|
151
|
+
# uncomment the generated annotations if they're saved in the schema file
|
152
|
+
return doc_string.gsub(/^#\ {3}/, '').gsub(/^#\n/, "\n") if CONFIG.schema_file?
|
153
|
+
|
154
|
+
doc_string
|
122
155
|
end
|
123
156
|
|
124
157
|
private
|
125
158
|
|
159
|
+
def parse_clause
|
160
|
+
return if CONFIG.schema_file?
|
161
|
+
|
162
|
+
" @!parse\n#"
|
163
|
+
end
|
164
|
+
|
126
165
|
# @param file_name [String]
|
127
166
|
# @return [String]
|
128
167
|
def relative_file_name(file_name)
|
@@ -133,6 +172,7 @@ module Rails
|
|
133
172
|
# @param content [String]
|
134
173
|
# @return [void]
|
135
174
|
def write_file(file_name, content)
|
175
|
+
::FileUtils.touch(file_name) unless ::File.exists?(file_name)
|
136
176
|
::File.write(file_name, content)
|
137
177
|
puts "modify".rjust(12).with_styles(:bold, :green) + " #{relative_file_name(file_name)}"
|
138
178
|
end
|
@@ -142,37 +182,57 @@ module Rails
|
|
142
182
|
@klass.table_name[..-2]
|
143
183
|
end
|
144
184
|
|
185
|
+
# @param reflection [ActiveRecord::Reflection::AbstractReflection]
|
186
|
+
# @return [Class]
|
187
|
+
def reflection_class(reflection)
|
188
|
+
reflection.klass
|
189
|
+
rescue ::NameError
|
190
|
+
Object
|
191
|
+
end
|
192
|
+
|
193
|
+
# @param reflection [ActiveRecord::Reflection::AbstractReflection]
|
194
|
+
# @return [String]
|
195
|
+
def reflection_foreign_key(reflection)
|
196
|
+
reflection.try(:foreign_key) || '<unknown>'
|
197
|
+
end
|
198
|
+
|
199
|
+
# @param klass [Class]
|
200
|
+
# @return [String]
|
201
|
+
def class_table_name(klass)
|
202
|
+
klass.try(:table_name) || '<unknown>'
|
203
|
+
end
|
204
|
+
|
145
205
|
# @param doc_string [String]
|
146
206
|
# @param attr_name [String]
|
147
207
|
# @param reflection [ActiveRecord::Reflection::AbstractReflection]
|
148
208
|
# @return [void]
|
149
209
|
def document_relation(doc_string, attr_name, reflection)
|
150
|
-
|
151
|
-
|
152
|
-
rescue ::NameError
|
153
|
-
Object
|
154
|
-
end
|
155
|
-
|
156
|
-
associated_table_name = reflection_class.try(:table_name) || '<unknown>'
|
157
|
-
foreign_key = reflection.try(:foreign_key) || '<unknown>'
|
158
|
-
db_description = \
|
210
|
+
reflection_klass = reflection_class(reflection)
|
211
|
+
type_docstring, db_description = \
|
159
212
|
case reflection
|
160
213
|
when ::ActiveRecord::Reflection::BelongsToReflection
|
161
|
-
|
162
|
-
|
214
|
+
belongs_to_description(reflection_klass,
|
215
|
+
class_table_name(@klass),
|
216
|
+
reflection_foreign_key(reflection))
|
163
217
|
when ::ActiveRecord::Reflection::HasOneReflection
|
164
|
-
|
165
|
-
|
218
|
+
has_one_description(reflection_klass,
|
219
|
+
class_table_name(reflection_klass),
|
220
|
+
reflection_foreign_key(reflection))
|
166
221
|
when ::ActiveRecord::Reflection::HasManyReflection
|
167
|
-
|
168
|
-
|
222
|
+
has_many_description(reflection_klass,
|
223
|
+
class_table_name(reflection_klass),
|
224
|
+
reflection_foreign_key(reflection))
|
225
|
+
when ::ActiveRecord::Reflection::ThroughReflection
|
226
|
+
through_description(reflection)
|
227
|
+
else
|
228
|
+
[::Object.to_s, '']
|
169
229
|
end
|
170
230
|
|
171
231
|
doc_string << <<~DOC
|
172
|
-
#
|
232
|
+
# ##{db_description}
|
173
233
|
# # @param val [#{type_docstring}, nil]
|
174
234
|
# def #{attr_name}=(val); end
|
175
|
-
#
|
235
|
+
# ##{db_description}
|
176
236
|
# # @return [#{type_docstring}, nil]
|
177
237
|
# def #{attr_name}; end
|
178
238
|
DOC
|
@@ -187,7 +247,7 @@ module Rails
|
|
187
247
|
model_class.reflections[klass_relation_name]&.options&.[](:as)&.to_sym == attr_name.to_sym
|
188
248
|
end
|
189
249
|
|
190
|
-
classes_string = classes.join(', ')
|
250
|
+
classes_string = classes.empty? ? ::Object.to_s : classes.join(', ')
|
191
251
|
doc_string << <<~DOC
|
192
252
|
# # Polymorphic relation. Database columns `#{@klass.table_name}.#{attr_name}_id` and `#{@klass.table_name}.#{attr_name}_type`.
|
193
253
|
# # @param val [#{classes_string}, nil]
|
@@ -198,13 +258,98 @@ module Rails
|
|
198
258
|
DOC
|
199
259
|
end
|
200
260
|
|
261
|
+
# @param reflection [ActiveRecord::Reflection::AbstractReflection]
|
262
|
+
# @return [Array<String>]
|
263
|
+
def through_description(reflection)
|
264
|
+
through_klass = reflection_class(reflection.through_reflection)
|
265
|
+
|
266
|
+
case (reflection.__send__(:delegate_reflection) rescue nil)
|
267
|
+
when ::ActiveRecord::Reflection::HasOneReflection
|
268
|
+
has_one_description(reflection_class(reflection.source_reflection),
|
269
|
+
class_table_name(through_klass),
|
270
|
+
reflection_foreign_key(reflection.source_reflection),
|
271
|
+
through: through_klass)
|
272
|
+
when ::ActiveRecord::Reflection::HasManyReflection
|
273
|
+
has_many_description(reflection_class(reflection.source_reflection),
|
274
|
+
class_table_name(through_klass),
|
275
|
+
reflection_foreign_key(reflection.source_reflection),
|
276
|
+
through: through_klass)
|
277
|
+
else
|
278
|
+
[::Object.to_s, '']
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
# @param through [Class, nil]
|
283
|
+
# @return [String]
|
284
|
+
def through_sentence(through = nil)
|
285
|
+
return '' unless through
|
286
|
+
|
287
|
+
" through `#{through}`"
|
288
|
+
end
|
289
|
+
|
290
|
+
# @param table_name [String]
|
291
|
+
# @param foreign_key [String]
|
292
|
+
# @param through [Class, nil]
|
293
|
+
# @return [String]
|
294
|
+
def column_description(table_name, foreign_key, through = nil)
|
295
|
+
return '' if through
|
296
|
+
|
297
|
+
" Database column `#{table_name}.#{foreign_key}`."
|
298
|
+
end
|
299
|
+
|
300
|
+
# @param relation [Symbol, String]
|
301
|
+
# @param klass [Class]
|
302
|
+
# @param table_name [String]
|
303
|
+
# @param foreign_key [String]
|
304
|
+
# @param through [Class, nil]
|
305
|
+
# @return [String]
|
306
|
+
def relation_description(relation, klass, table_name, foreign_key, through = nil)
|
307
|
+
" `#{relation}` relation with `#{klass}`#{through_sentence(through)}.#{column_description(table_name, foreign_key, through)}"
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
# @param klass [Class]
|
312
|
+
# @param table_name [String]
|
313
|
+
# @param foreign_key [String]
|
314
|
+
# @param :through [Class, nil]
|
315
|
+
# @return [Array<String>] Type docstring followed by the description of the method.
|
316
|
+
def has_many_description(klass, table_name, foreign_key, through: nil)
|
317
|
+
type_docstring = "Array<#{klass}>"
|
318
|
+
desc = relation_description(:has_many, klass, table_name, foreign_key, through)
|
319
|
+
|
320
|
+
[type_docstring, desc]
|
321
|
+
end
|
322
|
+
|
323
|
+
# @param klass [Class]
|
324
|
+
# @param table_name [String]
|
325
|
+
# @param foreign_key [String]
|
326
|
+
# @param :through [Class, nil]
|
327
|
+
# @return [Array<String>] Type docstring followed by the description of the method.
|
328
|
+
def has_one_description(klass, table_name, foreign_key, through: nil)
|
329
|
+
type_docstring = klass
|
330
|
+
desc = relation_description(:has_one, klass, table_name, foreign_key, through)
|
331
|
+
|
332
|
+
[type_docstring, desc]
|
333
|
+
end
|
334
|
+
|
335
|
+
# @param klass [Class]
|
336
|
+
# @param table_name [String]
|
337
|
+
# @param foreign_key [String]
|
338
|
+
# @return [Array<String>] Type docstring followed by the description of the method.
|
339
|
+
def belongs_to_description(klass, table_name, foreign_key)
|
340
|
+
type_docstring = klass
|
341
|
+
desc = relation_description(:belongs_to, klass, table_name, foreign_key)
|
342
|
+
|
343
|
+
[type_docstring, desc]
|
344
|
+
end
|
345
|
+
|
201
346
|
# @param attr_type [ActiveModel::Type::Value]
|
202
347
|
# @return [String]
|
203
348
|
def yard_type(attr_type)
|
204
349
|
return attr_type.coder.object_class.to_s if attr_type.respond_to?(:coder) && attr_type.coder.respond_to?(:object_class)
|
205
350
|
return 'Object' if attr_type.respond_to?(:coder) && attr_type.coder.is_a?(::ActiveRecord::Coders::JSON)
|
206
351
|
|
207
|
-
|
352
|
+
TYPE_MAP[attr_type.type]
|
208
353
|
end
|
209
354
|
end
|
210
355
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'set'
|
4
|
+
require 'fileutils'
|
4
5
|
|
5
6
|
require_relative "solargraph/version"
|
6
7
|
require_relative "solargraph/configuration"
|
@@ -19,11 +20,20 @@ module Rails
|
|
19
20
|
CONFIG = Configuration.new
|
20
21
|
# @return [Set<Symbol>]
|
21
22
|
VALID_MODIFICATION_METHODS = ::Set[:annotate, :remove_annotation].freeze
|
23
|
+
# @return [String]
|
24
|
+
SCHEMA_CLASS_NAME = 'AnnotateSolargraphSchema'
|
25
|
+
# @return [String]
|
26
|
+
SOLARGRAPH_FILE_NAME = '.solargraph.yml'
|
27
|
+
# @return [String]
|
28
|
+
SCHEMA_FILE_NAME = '.annotate_solargraph_schema'
|
29
|
+
# @return [String]
|
30
|
+
SCHEMA_RAILS_PATH = SCHEMA_FILE_NAME
|
22
31
|
|
23
32
|
class << self
|
24
33
|
# @return [Array<String>] Array of changed files.
|
25
34
|
def generate
|
26
35
|
title 'Generating model schema annotations'
|
36
|
+
create_schema_file
|
27
37
|
modify_models :annotate
|
28
38
|
end
|
29
39
|
|
@@ -49,6 +59,13 @@ module Rails
|
|
49
59
|
|
50
60
|
include TerminalColors
|
51
61
|
|
62
|
+
def create_schema_file
|
63
|
+
schema_file = ::File.join ::Rails.root, SCHEMA_RAILS_PATH
|
64
|
+
return if ::File.exist?(schema_file)
|
65
|
+
|
66
|
+
system 'rails g annotate:solargraph:install'
|
67
|
+
end
|
68
|
+
|
52
69
|
# @param method [Symbol] Name of the method that will be called on every loaded Model
|
53
70
|
# @return [Array<String>] Array of changed files.
|
54
71
|
def modify_models(method)
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = "https://gitlab.com/mateuszdrewniak/rails-annotate-solargraph"
|
19
|
-
|
19
|
+
spec.metadata["changelog_uri"] = "https://gitlab.com/mateuszdrewniak/rails-annotate-solargraph/-/raw/main/CHANGELOG.md"
|
20
20
|
|
21
21
|
# Specify which files should be added to the gem when it is released.
|
22
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -31,6 +31,8 @@ Gem::Specification.new do |spec|
|
|
31
31
|
|
32
32
|
# Uncomment to register a new dependency of your gem
|
33
33
|
spec.add_dependency 'rails', ">= 5.0", '< 8.0'
|
34
|
+
spec.add_dependency 'solargraph'
|
35
|
+
spec.add_dependency 'yard'
|
34
36
|
|
35
37
|
# For more information and examples about making a new gem, check out our
|
36
38
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-annotate-solargraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mateusz Drewniak
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -30,6 +30,34 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '8.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: solargraph
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: yard
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
33
61
|
description: Annotate ActiveRecord models with schema comments formatted in YARD that
|
34
62
|
are compatible with Solargraph.
|
35
63
|
email:
|
@@ -53,6 +81,7 @@ files:
|
|
53
81
|
- bin/console
|
54
82
|
- bin/setup
|
55
83
|
- lib/generators/annotate/solargraph/install_generator.rb
|
84
|
+
- lib/generators/annotate/solargraph/templates/.annotate_solargraph_schema
|
56
85
|
- lib/generators/annotate/solargraph/templates/rails_annotate_solargraph.rake
|
57
86
|
- lib/rails/annotate/solargraph.rb
|
58
87
|
- lib/rails/annotate/solargraph/configuration.rb
|
@@ -67,6 +96,7 @@ licenses:
|
|
67
96
|
metadata:
|
68
97
|
homepage_uri: https://gitlab.com/mateuszdrewniak/rails-annotate-solargraph
|
69
98
|
source_code_uri: https://gitlab.com/mateuszdrewniak/rails-annotate-solargraph
|
99
|
+
changelog_uri: https://gitlab.com/mateuszdrewniak/rails-annotate-solargraph/-/raw/main/CHANGELOG.md
|
70
100
|
post_install_message:
|
71
101
|
rdoc_options: []
|
72
102
|
require_paths:
|