rails-annotate-solargraph 0.4.0 → 0.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80d2fcb8fc2090d6a1eabc8f510b3b9fec1608da1870c7d88b301ce64907920a
4
- data.tar.gz: 9553090d359f8f829e955349cac6c527c43335433e38d91152862780cce3ab63
3
+ metadata.gz: ac8d7c78804560db17c10943c462e838059d5f74d6d5d2664083c6da0f26c43a
4
+ data.tar.gz: b9a0d329cb657bdb74220b75ec14a53785d75f2e6847c7bc41e884103edb21df
5
5
  SHA512:
6
- metadata.gz: 8b2415d929d939454a4f65277d85baa03935219226c6ad5b35c35264cd2de94bb1b1d55a55a55ee8cc737523210e3653c648bea50798dd53b580767fbb6a2eec
7
- data.tar.gz: 9436e870a6cbc28e636151b76717cde5bf4186f44bc8af4293ada785f1c50e039895fcf5cb38dd27868c5e88027df9f52be8ee070591e0635de30fdba7437aef
6
+ metadata.gz: 39567ae796da52823201081813575f0859aefad622a5c43522b0b82f0864f4f87a8e3cccc65a83d9631c9a6f4c9febae0968b2e51980d679d7f0736e6c55c552
7
+ data.tar.gz: a8d6a79aa396d9110bc157703678d91f8b0e0f664f4175f296a47e07429727dbc3eb7d3e6025facaaff3b3abea94f151abeaece7e07f2160ba4eb1d48cf23c88
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "cSpell.words": [
3
3
  "activerecord",
4
+ "citext",
5
+ "datetime",
6
+ "gsub",
7
+ "inet",
4
8
  "klass",
5
9
  "rakefile",
6
10
  "solargraph",
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.5.2] - 2022-04-20
4
+
5
+ - proxy method overrides get loaded during app initialization
6
+
7
+ ## [0.5.1] - 2022-04-20
8
+
9
+ - `ActiveRecord` scopes are now documented
10
+
11
+ ## [0.5.0] - 2022-04-19
12
+
13
+ - Add some static comments to the schema file to improve general Rails intellisense
14
+ - Rename schema file from `app/models/annotate_solargraph_schema.rb` to `.annotate-solargraph-schema`
15
+ - Generate schema file as a regular ruby file
16
+ - Add `yard` and `solargraph` as dependencies
17
+ - Add `.solargraph.yml` to the installation generator
18
+
3
19
  ## [0.4.0] - 2022-04-17
4
20
 
5
21
  - Annotations get saved to a schema file by default `app/models/annotate_solargraph_schema.rb`
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in rails-annotate-solargraph.gemspec
6
6
  gemspec
7
7
 
8
+ gem 'byebug'
8
9
  gem 'debug'
9
10
  gem 'git'
10
11
  gem "minitest", "~> 5.0"
data/Gemfile.lock CHANGED
@@ -1,8 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rails-annotate-solargraph (0.4.0)
4
+ rails-annotate-solargraph (0.5.2)
5
5
  rails (>= 5.0, < 8.0)
6
+ solargraph
7
+ yard
6
8
 
7
9
  GEM
8
10
  remote: https://rubygems.org/
@@ -76,6 +78,7 @@ GEM
76
78
  backport (1.2.0)
77
79
  benchmark (0.2.0)
78
80
  builder (3.2.4)
81
+ byebug (11.1.3)
79
82
  concurrent-ruby (1.1.10)
80
83
  crass (1.0.6)
81
84
  debug (1.5.0)
@@ -219,6 +222,7 @@ PLATFORMS
219
222
  ruby
220
223
 
221
224
  DEPENDENCIES
225
+ byebug
222
226
  debug
223
227
  git
224
228
  minitest (~> 5.0)
@@ -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
@@ -5,11 +5,13 @@ if ::Rails.env.development?
5
5
  namespace :solargraph do
6
6
  desc "Add YARD comments documenting the models' schemas"
7
7
  task generate: :environment do
8
+ ::ENV['ANNOTATE_SOLARGRAPH_RAKE_TASK'] = 'true'
8
9
  ::Rails::Annotate::Solargraph.generate
9
10
  end
10
11
 
11
12
  desc "Remove YARD comments documenting the models' schemas"
12
13
  task remove: :environment do
14
+ ::ENV['ANNOTATE_SOLARGRAPH_RAKE_TASK'] = 'true'
13
15
  ::Rails::Annotate::Solargraph.remove
14
16
  end
15
17
  end
@@ -19,6 +21,7 @@ if ::Rails.env.development?
19
21
  next unless ::Rake::Task.task_defined?(task)
20
22
 
21
23
  ::Rake::Task[task].enhance do
24
+ system 'yard gems' unless ENV['TEST']
22
25
  ::Rake::Task['annotate:solargraph:generate'].invoke
23
26
  end
24
27
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActiveRecord::Base
4
+ class << self
5
+ alias orig_scope scope
6
+
7
+ def scope(*args, **kwargs, &block)
8
+ return orig_scope(*args, **kwargs, &block) unless ::ENV['ANNOTATE_SOLARGRAPH_RAKE_TASK']
9
+
10
+ file_path, scope_line_number = caller.first.split(':')
11
+ scope_line_number = scope_line_number.to_i
12
+ scope_name = args.first
13
+ scope_proc = args[1]
14
+ proc_parameters = scope_proc.respond_to?(:parameters) ? scope_proc.parameters.map(&:last) : []
15
+ scope_line = nil
16
+ scope_model_class = self
17
+
18
+ ::File.open(file_path) do |file|
19
+ file.each_line.with_index(1) do |line, current_line_number|
20
+ next unless current_line_number == scope_line_number
21
+
22
+ scope_line = line.strip
23
+ break
24
+ end
25
+ end
26
+
27
+ ::Rails::Annotate::Solargraph::Model.add_scope(scope_name.to_sym, scope_model_class, proc_parameters, scope_line)
28
+
29
+ orig_scope(*args, **kwargs, &block)
30
+ end
31
+ end
32
+ end
@@ -8,33 +8,48 @@ module Rails
8
8
  class Model
9
9
  using TerminalColors::Refinement
10
10
 
11
+ Scope = ::Struct.new(:name, :model_class, :proc_parameters, :definition, keyword_init: true)
12
+
11
13
  # @return [Regexp]
12
14
  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
13
15
 
16
+ # @return [Hash{Symbol => String}]
17
+ TYPE_MAP = {
18
+ float: 'BigDecimal',
19
+ decimal: 'BigDecimal',
20
+ integer: 'Integer',
21
+ datetime: 'ActiveSupport::TimeWithZone',
22
+ date: 'Date',
23
+ string: 'String',
24
+ boolean: 'Boolean',
25
+ text: 'String',
26
+ jsonb: 'Hash',
27
+ citext: 'String',
28
+ json: 'Hash',
29
+ bigint: 'Integer',
30
+ uuid: 'String',
31
+ inet: 'IPAddr'
32
+ }
33
+ TYPE_MAP.default = 'Object'
34
+ TYPE_MAP.freeze
35
+
14
36
  class << self
15
- # @param type [Symbol, String, nil]
16
- # @return [String]
17
- def active_record_type_to_yard(type)
18
- case type&.to_sym
19
- when :float
20
- ::Float.to_s
21
- when :integer
22
- ::Integer.to_s
23
- when :decimal
24
- ::BigDecimal.to_s
25
- when :datetime, :timestamp, :time
26
- ::Time.to_s
27
- when :json, :jsonb
28
- ::Hash.to_s
29
- when :date
30
- ::Date.to_s
31
- when :text, :string, :binary, :inet, :uuid
32
- ::String.to_s
33
- when :boolean
34
- 'Boolean'
35
- else
36
- ::Object.to_s
37
- end
37
+ # @return [Hash{Class => Array<Rails::Annotate::Solargraph::Model::Scope>}]
38
+ def scopes
39
+ @scopes ||= {}
40
+ @scopes
41
+ end
42
+
43
+ # @param name [Symbol]
44
+ # @param model_class [Class]
45
+ # @param proc_parameters [Array<Symbol>]
46
+ # @param definition [String]
47
+ def add_scope(name, model_class, proc_parameters, definition)
48
+ scope = Scope.new(name: name, model_class: model_class, proc_parameters: proc_parameters, definition: definition)
49
+ @scopes ||= {}
50
+ @scopes[model_class] ||= []
51
+ @scopes[model_class] << scope
52
+ @scopes[model_class].sort_by! { |scope| scope.name }
38
53
  end
39
54
 
40
55
  # @param klass [Class]
@@ -67,8 +82,7 @@ module Rails
67
82
  # @param klass [Class]
68
83
  def initialize(klass)
69
84
  @klass = klass
70
- base_file_name = CONFIG.schema_file? ? SCHEMA_FILE_NAME : "#{klass.to_s.underscore}.rb"
71
- @file_name = ::File.join(::Rails.root, MODEL_DIR, base_file_name)
85
+ @file_name = CONFIG.schema_file? ? SCHEMA_RAILS_PATH : ::File.join(::Rails.root, MODEL_DIR, "#{klass.to_s.underscore}.rb")
72
86
  end
73
87
 
74
88
  # @return [String]
@@ -101,7 +115,6 @@ module Rails
101
115
  end
102
116
 
103
117
  return new_file_content unless write
104
- # debugger
105
118
  return new_file_content if old_content == new_file_content
106
119
 
107
120
  write_file @file_name, new_file_content
@@ -128,16 +141,55 @@ module Rails
128
141
  doc_string = ::String.new
129
142
  doc_string << <<~DOC
130
143
  #{annotation_start}
131
- # @!parse
144
+ ##{parse_clause}
132
145
  # class #{@klass} < #{@klass.superclass}
133
146
  DOC
134
147
 
148
+ document_scopes(doc_string)
149
+ document_relations(doc_string)
150
+ document_fields(doc_string)
151
+
152
+ doc_string << <<~DOC.chomp
153
+ # end
154
+ # #{annotation_end}
155
+ DOC
156
+
157
+ # uncomment the generated annotations if they're saved in the schema file
158
+ return doc_string.gsub(/^#\ {3}/, '').gsub(/^#\n/, "\n") if CONFIG.schema_file?
159
+
160
+ doc_string
161
+ end
162
+
163
+ private
164
+
165
+ # @param doc_string [String]
166
+ # @return [void]
167
+ def document_scopes(doc_string)
168
+ self.class.scopes[@klass]&.each do |scope|
169
+ doc_string << <<~DOC
170
+ # # Scope `#{scope.name.inspect}`.
171
+ # #
172
+ # # #{scope.definition}
173
+ # #
174
+ # # @return [Array<#{@klass}>, nil]
175
+ # def self.#{scope.name}(#{scope.proc_parameters.join(', ')}); end
176
+ DOC
177
+ end
178
+ end
179
+
180
+ # @param doc_string [String]
181
+ # @return [void]
182
+ def document_relations(doc_string)
135
183
  @klass.reflections.sort.each do |attr_name, reflection|
136
184
  next document_polymorphic_relation(doc_string, attr_name, reflection) if reflection.polymorphic?
137
185
 
138
186
  document_relation(doc_string, attr_name, reflection)
139
187
  end
188
+ end
140
189
 
190
+ # @param doc_string [String]
191
+ # @return [void]
192
+ def document_fields(doc_string)
141
193
  @klass.attribute_types.each do |name, attr_type|
142
194
  doc_string << <<~DOC
143
195
  # # Database column `#{@klass.table_name}.#{name}`, type: `#{attr_type.type}`.
@@ -148,14 +200,14 @@ module Rails
148
200
  # def #{name}; end
149
201
  DOC
150
202
  end
151
-
152
- doc_string << <<~DOC.chomp
153
- # end
154
- # #{annotation_end}
155
- DOC
156
203
  end
157
204
 
158
- private
205
+ # @return [String, nil]
206
+ def parse_clause
207
+ return if CONFIG.schema_file?
208
+
209
+ " @!parse\n#"
210
+ end
159
211
 
160
212
  # @param file_name [String]
161
213
  # @return [String]
@@ -344,7 +396,7 @@ module Rails
344
396
  return attr_type.coder.object_class.to_s if attr_type.respond_to?(:coder) && attr_type.coder.respond_to?(:object_class)
345
397
  return 'Object' if attr_type.respond_to?(:coder) && attr_type.coder.is_a?(::ActiveRecord::Coders::JSON)
346
398
 
347
- self.class.active_record_type_to_yard(attr_type.type)
399
+ TYPE_MAP[attr_type.type]
348
400
  end
349
401
  end
350
402
  end
@@ -3,7 +3,7 @@
3
3
  module Rails
4
4
  module Annotate
5
5
  module Solargraph
6
- VERSION = '0.4.0'
6
+ VERSION = '0.5.2'
7
7
  end
8
8
  end
9
9
  end
@@ -8,6 +8,12 @@ require_relative "solargraph/configuration"
8
8
  require_relative "solargraph/terminal_colors"
9
9
  require_relative "solargraph/model"
10
10
 
11
+ begin
12
+ require_relative "overrides"
13
+ rescue
14
+ nil
15
+ end
16
+
11
17
  module Rails
12
18
  module Annotate
13
19
  module Solargraph
@@ -23,7 +29,11 @@ module Rails
23
29
  # @return [String]
24
30
  SCHEMA_CLASS_NAME = 'AnnotateSolargraphSchema'
25
31
  # @return [String]
26
- SCHEMA_FILE_NAME = "annotate_solargraph_schema.rb"
32
+ SOLARGRAPH_FILE_NAME = '.solargraph.yml'
33
+ # @return [String]
34
+ SCHEMA_FILE_NAME = '.annotate_solargraph_schema'
35
+ # @return [String]
36
+ SCHEMA_RAILS_PATH = SCHEMA_FILE_NAME
27
37
 
28
38
  class << self
29
39
  # @return [Array<String>] Array of changed files.
@@ -56,13 +66,10 @@ module Rails
56
66
  include TerminalColors
57
67
 
58
68
  def create_schema_file
59
- schema_file = ::File.join(::Rails.root, MODEL_DIR, SCHEMA_FILE_NAME)
60
- return unless CONFIG.schema_file? && !::File.exist?(schema_file)
69
+ schema_file = ::File.join ::Rails.root, SCHEMA_RAILS_PATH
70
+ return if ::File.exist?(schema_file)
61
71
 
62
- ::FileUtils.touch(schema_file)
63
- ::File.write schema_file, <<~SCHEMA
64
- module AnnotateSolargraphSchema; end
65
- SCHEMA
72
+ system 'rails g annotate:solargraph:install'
66
73
  end
67
74
 
68
75
  # @param method [Symbol] Name of the method that will be called on every loaded Model
@@ -74,6 +81,7 @@ module Rails
74
81
  changed_files = []
75
82
  model_files = ::Dir[::File.join(::Rails.root, MODEL_DIR, '**/*.rb')].map { |file| file.sub("#{::Rails.root}/", '') }.to_set
76
83
 
84
+ require_relative "overrides"
77
85
  ::Rails.application.eager_load!
78
86
  model_classes.each do |subclass|
79
87
  subclass_file = ::File.join MODEL_DIR, "#{subclass.to_s.underscore}.rb"
@@ -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.0
4
+ version: 0.5.2
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-17 00:00:00.000000000 Z
11
+ date: 2022-04-20 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,7 +81,9 @@ 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
86
+ - lib/rails/annotate/overrides.rb
57
87
  - lib/rails/annotate/solargraph.rb
58
88
  - lib/rails/annotate/solargraph/configuration.rb
59
89
  - lib/rails/annotate/solargraph/model.rb