solargraph-rails 0.2.2.pre.4 → 1.0.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +33 -0
- data/.github/workflows/ruby.yml +36 -0
- data/.gitignore +8 -0
- data/.solargraph.yml +19 -0
- data/CHANGELOG.md +19 -0
- data/DEVELOPMENT.md +83 -0
- data/README.md +5 -3
- data/lib/solargraph/rails/annotate.rb +44 -0
- data/lib/solargraph/rails/annotations.rb +50 -0
- data/lib/solargraph/rails/autoload.rb +53 -0
- data/lib/solargraph/rails/debug.rb +30 -0
- data/lib/solargraph/rails/delegate.rb +42 -0
- data/lib/solargraph/rails/devise.rb +48 -0
- data/lib/solargraph/rails/model.rb +100 -0
- data/lib/solargraph/rails/rails_api.rb +98 -0
- data/lib/solargraph/rails/schema.rb +100 -0
- data/lib/solargraph/rails/storage.rb +48 -0
- data/lib/solargraph/rails/types.yml +24 -0
- data/lib/solargraph/rails/util.rb +68 -0
- data/lib/solargraph/rails/version.rb +1 -1
- data/lib/solargraph/rails/walker.rb +89 -0
- data/lib/solargraph-rails.rb +57 -22
- data/script/generate_definitions.rb +134 -0
- data/solargraph-rails.gemspec +24 -22
- metadata +26 -16
- data/Gemfile.lock +0 -109
- data/lib/solargraph/rails/files_loader.rb +0 -16
- data/lib/solargraph/rails/meta_source/association/belongs_to_matcher.rb +0 -24
- data/lib/solargraph/rails/meta_source/association/has_and_belongs_to_many_matcher.rb +0 -24
- data/lib/solargraph/rails/meta_source/association/has_many_matcher.rb +0 -24
- data/lib/solargraph/rails/meta_source/association/has_one_matcher.rb +0 -24
- data/lib/solargraph/rails/pin_creator.rb +0 -117
- data/lib/solargraph/rails/ruby_parser.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 134394397585a1df968b364e98d20b8e38a2fb6294833bfe8bbcfb81b13c545f
|
4
|
+
data.tar.gz: cb4e7fe2906a0769c95e8a3e7de08b6d0188b4dd8d509db2e001006e9367e6db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7acc8b51be9a665bcca385a67bcee5eed0ffd9e697c155bfab4e5e94dcd691cb4ccab4f04c09306166c99e9802e3276e9895374540d3df7b3c979c59be582d4
|
7
|
+
data.tar.gz: 4de5589904080422ed72fec8d76e4679a53df812f551c7e99d5d0e6fc7a6cabefe5256a6403dab04ae96e0fd79ec85c92f7a171502202afdb7403e30b266ee04
|
@@ -0,0 +1,33 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Create a report to help us improve
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Describe the bug**
|
11
|
+
A clear and concise description of what the bug is.
|
12
|
+
|
13
|
+
**To Reproduce**
|
14
|
+
Steps to reproduce the behavior:
|
15
|
+
1. Go to '...'
|
16
|
+
2. Click on '....'
|
17
|
+
3. Scroll down to '....'
|
18
|
+
4. See error
|
19
|
+
|
20
|
+
**Expected behavior**
|
21
|
+
A clear and concise description of what you expected to happen.
|
22
|
+
|
23
|
+
**Screenshots**
|
24
|
+
If applicable, add screenshots to help explain your problem.
|
25
|
+
|
26
|
+
**Debug log**
|
27
|
+
|
28
|
+
Run the following command in the project you are having problems:
|
29
|
+
```
|
30
|
+
ruby -r'solargraph-rails' -e 'Solargraph::Rails::Debug.run()'
|
31
|
+
```
|
32
|
+
|
33
|
+
and paste the output here
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
workflow_dispatch: {}
|
12
|
+
pull_request:
|
13
|
+
branches: [master]
|
14
|
+
|
15
|
+
jobs:
|
16
|
+
test:
|
17
|
+
runs-on: ubuntu-latest
|
18
|
+
strategy:
|
19
|
+
matrix:
|
20
|
+
ruby-version:
|
21
|
+
- "2.7"
|
22
|
+
- "3.0"
|
23
|
+
- "3.1"
|
24
|
+
|
25
|
+
steps:
|
26
|
+
- uses: actions/checkout@v2
|
27
|
+
- uses: ruby/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: ${{ matrix.ruby-version }}
|
30
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
31
|
+
- name: Install Rails 5 deps
|
32
|
+
run: (cd spec/rails5; bundle install; yard gems)
|
33
|
+
- name: Install Rails 6 deps
|
34
|
+
run: (cd spec/rails6; bundle install; yard gems)
|
35
|
+
- name: Run tests
|
36
|
+
run: bundle exec rspec
|
data/.gitignore
CHANGED
data/.solargraph.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
include:
|
3
|
+
- "**/*.rb"
|
4
|
+
exclude:
|
5
|
+
- test/**/*
|
6
|
+
- vendor/**/*
|
7
|
+
- ".bundle/**/*"
|
8
|
+
require: []
|
9
|
+
domains: []
|
10
|
+
reporters: []
|
11
|
+
formatter:
|
12
|
+
rubocop:
|
13
|
+
cops: safe
|
14
|
+
except: []
|
15
|
+
only: []
|
16
|
+
extra_args: []
|
17
|
+
require_paths: []
|
18
|
+
plugins: []
|
19
|
+
max_files: 5000
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
## Changes
|
4
4
|
|
5
|
+
### v1.0.0.pre.1
|
6
|
+
|
7
|
+
https://github.com/alisnic/solargraph-arc was merged, with the following features:
|
8
|
+
- fixes autocompletion for multi-level classes defined in 1 line `class Foo::Bar::Baz`. See https://github.com/castwide/solargraph/issues/506
|
9
|
+
- autocomplete database columns by parsing db/schema.rb
|
10
|
+
- autocomplete of model relations
|
11
|
+
- parsing of `delegate` calls
|
12
|
+
- completions for methods generated by Devise
|
13
|
+
- better support for running solargraph outside bundle
|
14
|
+
- better completion inside controllers. `request`, `response`, `params`, etc.
|
15
|
+
- autocomplete inside routes.rb
|
16
|
+
- autocomplete inside migrations
|
17
|
+
- completions for methods generated by ActiveStorage
|
18
|
+
- better ActiveRecord completions
|
19
|
+
|
20
|
+
### v0.3.0
|
21
|
+
* Require String inflection monkeypatches directly to avoid error from ActiveSupport v7
|
22
|
+
* Remove Gemfile.lock from version control
|
23
|
+
|
5
24
|
### v0.2.2.pre.4
|
6
25
|
* Loosen the dependency requirements
|
7
26
|
|
data/DEVELOPMENT.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Solargraph-Rails development guide
|
2
|
+
|
3
|
+
## Contributing
|
4
|
+
|
5
|
+
1. create fork and clone the repo
|
6
|
+
2. install gem deps `bundle install`
|
7
|
+
3. install dummy rails5 app deps and build its yard cache
|
8
|
+
|
9
|
+
```
|
10
|
+
$ cd spec/rails5
|
11
|
+
$ bundle install && yard gems
|
12
|
+
$ cd ../../
|
13
|
+
```
|
14
|
+
|
15
|
+
3. install dummy rails6 app deps and build its yard cache
|
16
|
+
|
17
|
+
```
|
18
|
+
$ cd spec/rails6
|
19
|
+
$ bundle install && yard gems
|
20
|
+
$ cd ../../
|
21
|
+
```
|
22
|
+
4. now tests should pass locally and you can try different changes
|
23
|
+
5. sumbit PR
|
24
|
+
|
25
|
+
## Completion coverage tracking
|
26
|
+
|
27
|
+
Solargraph-Rails uses a [set of yaml files](https://github.com/iftheshoefritz/solargraph-rails/tree/master/spec/definitions) to track coverage of found completions.
|
28
|
+
Those yaml files are generated at runtime from a dummy [rails5](https://github.com/iftheshoefritz/solargraph-rails/tree/master/spec/rails5) or [rails6](https://github.com/iftheshoefritz/solargraph-rails/tree/master/spec/rails6) app.
|
29
|
+
|
30
|
+
The main goal is to catch any regressions in case of any change. In case a method completion is marked completed and it is not found in solargraph completions, the tests will fail.
|
31
|
+
|
32
|
+
### Checking coverage
|
33
|
+
|
34
|
+
To see what is completion coverage for solargraph-rails, run the tests with the `PRINT_STATS=true` environment variable:
|
35
|
+
|
36
|
+
```
|
37
|
+
$ PRINT_STATS=true bundle exec rspec
|
38
|
+
```
|
39
|
+
|
40
|
+
What you will see in test output is reported coverage for classes that are tracked:
|
41
|
+
|
42
|
+
```
|
43
|
+
{:class_name=>"ActiveRecord::Base", :total=>800, :covered=>321, :typed=>10, :percent_covered=>40.1, :percent_typed=>1.3}
|
44
|
+
provides completions for ActiveRecord::Base
|
45
|
+
```
|
46
|
+
|
47
|
+
### Updating assertions
|
48
|
+
|
49
|
+
In case an improvement is made, and more completions are found then being asserted, tests will throw a warning:
|
50
|
+
|
51
|
+
```
|
52
|
+
ActionDispatch::Routing::Mapper.try! is marked as skipped in spec/definitions/rails5/routes.yml, but is actually present.
|
53
|
+
Consider setting skip=false
|
54
|
+
provides completions for ActionDispatch::Routing::Mapper
|
55
|
+
```
|
56
|
+
|
57
|
+
In this case there are 2 options:
|
58
|
+
1. Manually updating yml file and setting `skip: false` for that method
|
59
|
+
2. Updating yml file in place by passing `update: true` to assertion:
|
60
|
+
|
61
|
+
```diff
|
62
|
+
assert_matches_definition(
|
63
|
+
map,
|
64
|
+
'ActionDispatch::Routing::Mapper',
|
65
|
+
'rails5/routes',
|
66
|
+
+ update: true
|
67
|
+
)
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
In case of option 2, don't forget to remove the flag after yml file has been updated. Also review git diff, to make sure that no regressions have been set (skip=true was set for entries which previously had skip=false)
|
72
|
+
|
73
|
+
### Generating assertions
|
74
|
+
|
75
|
+
In case a new set of assertion files has to be created (for a new Rails version for example), a script can be used - https://github.com/iftheshoefritz/solargraph-rails/blob/master/script/generate_definitions.rb.
|
76
|
+
|
77
|
+
All you have to do is to go to the same Rails app root, and execute the script:
|
78
|
+
|
79
|
+
```
|
80
|
+
ruby path/to/generate_definitions.rb
|
81
|
+
```
|
82
|
+
|
83
|
+
Make sure to review the script and uncomment relevant parts
|
data/README.md
CHANGED
@@ -52,23 +52,25 @@ Solargraph won't know about attributes that you add during a session. Restart yo
|
|
52
52
|
For my setup with Emacs, that means running `M-x lsp-workspace-restart`, YMMV in other editors.
|
53
53
|
|
54
54
|
## Associations (experimental)
|
55
|
-
There is
|
55
|
+
There is simplistic support for `belongs_to` and `has_many` macros:
|
56
56
|
|
57
57
|
![Experimental autocomplete and go to definition of associations](assets/solar_rails_associations.gif)
|
58
58
|
|
59
59
|
## Known issues
|
60
60
|
This project is being used to write production code by the maintainer, but it is still WIP. Check out the issues tab and contribute if you are interested.
|
61
61
|
|
62
|
+
Association support is slightly less functional in Rails 7.
|
63
|
+
|
62
64
|
## Installation
|
63
65
|
|
64
|
-
### Install `solargraph`
|
66
|
+
### Install `solargraph` and `solargraph-rails` locally
|
65
67
|
|
66
68
|
Typically gems like these are not installed via the Gemfile, because most projects have more than one contributor and other contributors might have different setups for their editors in mind. Instead you need to use `gem install`.
|
67
69
|
|
68
70
|
`gem install solargraph-rails`
|
69
71
|
|
70
72
|
#### Alternative: using bundler
|
71
|
-
If you do want to use bundler, add `gem 'solargraph-rails'
|
73
|
+
If you do want to use bundler, add `gem 'solargraph-rails'`
|
72
74
|
|
73
75
|
### Add `solargraph-rails` to your `.solargraph.yml`
|
74
76
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Rails
|
3
|
+
class Annotate
|
4
|
+
def self.instance
|
5
|
+
@instance ||= self.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.reset
|
9
|
+
@instance = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@schema_present = File.exist?('db/schema.rb')
|
14
|
+
end
|
15
|
+
|
16
|
+
def process(source_map, ns)
|
17
|
+
return [] if @schema_present
|
18
|
+
return [] unless source_map.filename.include?('app/models')
|
19
|
+
|
20
|
+
pins = []
|
21
|
+
walker = Walker.from_source(source_map.source)
|
22
|
+
walker.comments.each do |_, snip|
|
23
|
+
name, type = snip.text.gsub(/[\(\),:\d]/, '').split[1..2]
|
24
|
+
|
25
|
+
next unless name && type
|
26
|
+
|
27
|
+
ruby_type = Schema::RUBY_TYPES[type.to_sym]
|
28
|
+
next unless ruby_type
|
29
|
+
|
30
|
+
pins <<
|
31
|
+
Util.build_public_method(
|
32
|
+
ns,
|
33
|
+
name,
|
34
|
+
types: [ruby_type],
|
35
|
+
location:
|
36
|
+
Solargraph::Location.new(source_map.filename, snip.range)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
pins
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# The following comments fill some of the gaps in Solargraph's understanding of
|
2
|
+
# Rails apps. Since they're all in YARD, they get mapped in Solargraph but
|
3
|
+
# ignored at runtime.
|
4
|
+
#
|
5
|
+
# You can put this file anywhere in the project, as long as it gets included in
|
6
|
+
# the workspace maps. It's recommended that you keep it in a standalone file
|
7
|
+
# instead of pasting it into an existing one.
|
8
|
+
#
|
9
|
+
# @!parse
|
10
|
+
# class ActionController::Base
|
11
|
+
# include ActionController::MimeResponds
|
12
|
+
# include ActionController::Redirecting
|
13
|
+
# include ActionController::Cookies
|
14
|
+
# include AbstractController::Rendering
|
15
|
+
# extend ActiveSupport::Callbacks::ClassMethods
|
16
|
+
# extend ActiveSupport::Rescuable::ClassMethods
|
17
|
+
# extend AbstractController::Callbacks::ClassMethods
|
18
|
+
# extend ActionController::RequestForgeryProtection::ClassMethods
|
19
|
+
# end
|
20
|
+
# class ActionDispatch::Routing::Mapper
|
21
|
+
# include ActionDispatch::Routing::Mapper::Base
|
22
|
+
# include ActionDispatch::Routing::Mapper::HttpHelpers
|
23
|
+
# include ActionDispatch::Routing::Mapper::Redirection
|
24
|
+
# include ActionDispatch::Routing::Mapper::Scoping
|
25
|
+
# include ActionDispatch::Routing::Mapper::Concerns
|
26
|
+
# include ActionDispatch::Routing::Mapper::Resources
|
27
|
+
# include ActionDispatch::Routing::Mapper::CustomUrls
|
28
|
+
# end
|
29
|
+
# class Rails
|
30
|
+
# # @return [Rails::Application]
|
31
|
+
# def self.application; end
|
32
|
+
# end
|
33
|
+
# class Rails::Application
|
34
|
+
# # @return [ActionDispatch::Routing::RouteSet]
|
35
|
+
# def routes; end
|
36
|
+
# end
|
37
|
+
# class ActionDispatch::Routing::RouteSet
|
38
|
+
# # @yieldself [ActionDispatch::Routing::Mapper]
|
39
|
+
# def draw; end
|
40
|
+
# end
|
41
|
+
# class ActiveRecord::Base
|
42
|
+
# extend ActiveRecord::QueryMethods
|
43
|
+
# extend ActiveRecord::FinderMethods
|
44
|
+
# extend ActiveRecord::Associations::ClassMethods
|
45
|
+
# extend ActiveRecord::Inheritance::ClassMethods
|
46
|
+
# extend ActiveRecord::ModelSchema::ClassMethods
|
47
|
+
# extend ActiveRecord::Transactions::ClassMethods
|
48
|
+
# extend ActiveRecord::Scoping::Named::ClassMethods
|
49
|
+
# include ActiveRecord::Persistence
|
50
|
+
# end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Rails
|
3
|
+
class Autoload
|
4
|
+
def self.instance
|
5
|
+
@instance ||= self.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def process(source_map, ns, ds)
|
9
|
+
return [] unless ds.size == 1 && ns.path.include?('::')
|
10
|
+
Solargraph.logger.debug(
|
11
|
+
"[Rails][Autoload] seeding class tree for #{ns.path}"
|
12
|
+
)
|
13
|
+
|
14
|
+
root_ns = source_map.pins.find { |p| p.path == '' }
|
15
|
+
namespace_stubs(root_ns, ns)
|
16
|
+
end
|
17
|
+
|
18
|
+
def namespace_stubs(root_ns, ns)
|
19
|
+
parts = ns.path.split('::')
|
20
|
+
|
21
|
+
candidates =
|
22
|
+
parts
|
23
|
+
.each_with_index
|
24
|
+
.reduce([]) { |acc, (_, i)| acc + [parts[0..i].join('::')] }
|
25
|
+
.reject { |el| el == ns.path }
|
26
|
+
|
27
|
+
previous_ns = root_ns
|
28
|
+
pins = []
|
29
|
+
|
30
|
+
parts[0..-2].each_with_index do |name, i|
|
31
|
+
gates = candidates[0..i].reverse + ['']
|
32
|
+
path = gates.first
|
33
|
+
next if path == ns.path
|
34
|
+
|
35
|
+
previous_ns =
|
36
|
+
Solargraph::Pin::Namespace.new(
|
37
|
+
type: :class,
|
38
|
+
location: ns.location,
|
39
|
+
closure: previous_ns,
|
40
|
+
name: name,
|
41
|
+
comments: ns.comments,
|
42
|
+
visibility: :public,
|
43
|
+
gates: gates[1..-1]
|
44
|
+
)
|
45
|
+
|
46
|
+
pins << previous_ns
|
47
|
+
end
|
48
|
+
|
49
|
+
pins
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Rails
|
3
|
+
class Debug
|
4
|
+
def self.run(query = nil)
|
5
|
+
self.new.run(query)
|
6
|
+
end
|
7
|
+
|
8
|
+
def run(query)
|
9
|
+
Solargraph.logger.level = Logger::DEBUG
|
10
|
+
|
11
|
+
api_map = Solargraph::ApiMap.load('./')
|
12
|
+
|
13
|
+
puts "Ruby version: #{RUBY_VERSION}"
|
14
|
+
puts "Solargraph version: #{Solargraph::VERSION}"
|
15
|
+
puts "Solargraph Rails version: #{Solargraph::Rails::VERSION}"
|
16
|
+
|
17
|
+
return unless query
|
18
|
+
|
19
|
+
puts "Known methods for #{query}"
|
20
|
+
|
21
|
+
pin = api_map.pins.find { |p| p.path == query }
|
22
|
+
return unless pin
|
23
|
+
|
24
|
+
api_map
|
25
|
+
.get_complex_type_methods(pin.return_type)
|
26
|
+
.each { |pin| puts "- #{pin.path}" }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Rails
|
3
|
+
class Delegate
|
4
|
+
def self.instance
|
5
|
+
@instance ||= self.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def process(source_map, ns)
|
9
|
+
return [] unless source_map.code.include?('delegate')
|
10
|
+
|
11
|
+
walker = Walker.from_source(source_map.source)
|
12
|
+
pins = []
|
13
|
+
|
14
|
+
walker.on :send, [nil, :delegate] do |ast|
|
15
|
+
methods =
|
16
|
+
ast.children[2..-1]
|
17
|
+
.map { |c| c.children.first }
|
18
|
+
.select { |s| s.is_a?(Symbol) }
|
19
|
+
|
20
|
+
methods.each do |meth|
|
21
|
+
pins <<
|
22
|
+
Util.build_public_method(
|
23
|
+
ns,
|
24
|
+
meth.to_s,
|
25
|
+
location: Util.build_location(ast, ns.filename)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
walker.walk
|
31
|
+
|
32
|
+
if pins.any?
|
33
|
+
Solargraph.logger.debug(
|
34
|
+
"[Rails][Delegate] added #{pins.map(&:name)} to #{ns.path}"
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
pins
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Rails
|
3
|
+
class Devise
|
4
|
+
def self.instance
|
5
|
+
@instance ||= self.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def process(source_map, ns)
|
9
|
+
if source_map.filename.include?('app/models')
|
10
|
+
process_model(source_map.source, ns)
|
11
|
+
else
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def process_model(source, ns)
|
19
|
+
walker = Walker.from_source(source)
|
20
|
+
pins = []
|
21
|
+
|
22
|
+
walker.on :send, [nil, :devise] do |ast|
|
23
|
+
modules =
|
24
|
+
ast.children[2..-1]
|
25
|
+
.map { |c| c.children.first }
|
26
|
+
.select { |s| s.is_a?(Symbol) }
|
27
|
+
|
28
|
+
modules.each do |mod|
|
29
|
+
pins <<
|
30
|
+
Util.build_module_include(
|
31
|
+
ns,
|
32
|
+
"Devise::Models::#{mod.to_s.capitalize}",
|
33
|
+
Util.build_location(ast, ns.filename)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
walker.walk
|
39
|
+
if pins.any?
|
40
|
+
Solargraph.logger.debug(
|
41
|
+
"[Rails][Devise] added #{pins.map(&:name)} to #{ns.path}"
|
42
|
+
)
|
43
|
+
end
|
44
|
+
pins
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Rails
|
3
|
+
class Model
|
4
|
+
def self.instance
|
5
|
+
@instance ||= self.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def process(source_map, ns)
|
9
|
+
return [] unless source_map.filename.include?('app/models')
|
10
|
+
|
11
|
+
walker = Walker.from_source(source_map.source)
|
12
|
+
pins = []
|
13
|
+
|
14
|
+
walker.on :send, [nil, :belongs_to] do |ast|
|
15
|
+
pins << singular_association(ns, ast)
|
16
|
+
end
|
17
|
+
|
18
|
+
walker.on :send, [nil, :has_one] do |ast|
|
19
|
+
pins << singular_association(ns, ast)
|
20
|
+
end
|
21
|
+
|
22
|
+
walker.on :send, [nil, :has_many] do |ast|
|
23
|
+
pins << plural_association(ns, ast)
|
24
|
+
end
|
25
|
+
|
26
|
+
walker.on :send, [nil, :has_and_belongs_to_many] do |ast|
|
27
|
+
pins << plural_association(ns, ast)
|
28
|
+
end
|
29
|
+
|
30
|
+
walker.on :send, [nil, :scope] do |ast|
|
31
|
+
name = ast.children[2].children.last
|
32
|
+
|
33
|
+
method_pin =
|
34
|
+
Util.build_public_method(
|
35
|
+
ns,
|
36
|
+
name.to_s,
|
37
|
+
types: ns.return_type.map(&:tag),
|
38
|
+
scope: :class,
|
39
|
+
location: Util.build_location(ast, ns.filename)
|
40
|
+
)
|
41
|
+
|
42
|
+
if ast.children.last.type == :block
|
43
|
+
location = ast.children.last.location
|
44
|
+
block_pin =
|
45
|
+
source_map.locate_block_pin(location.line, location.column)
|
46
|
+
method_pin.parameters.concat(block_pin.parameters.clone)
|
47
|
+
end
|
48
|
+
pins << method_pin
|
49
|
+
end
|
50
|
+
|
51
|
+
walker.walk
|
52
|
+
if pins.any?
|
53
|
+
Solargraph.logger.debug(
|
54
|
+
"[Rails][Model] added #{pins.map(&:name)} to #{ns.path}"
|
55
|
+
)
|
56
|
+
end
|
57
|
+
pins
|
58
|
+
end
|
59
|
+
|
60
|
+
def plural_association(ns, ast)
|
61
|
+
relation_name = ast.children[2].children.first
|
62
|
+
class_name =
|
63
|
+
extract_custom_class_name(ast) ||
|
64
|
+
relation_name.to_s.singularize.camelize
|
65
|
+
|
66
|
+
Util.build_public_method(
|
67
|
+
ns,
|
68
|
+
relation_name.to_s,
|
69
|
+
types: ["ActiveRecord::Associations::CollectionProxy<#{class_name}>"],
|
70
|
+
location: Util.build_location(ast, ns.filename)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
def singular_association(ns, ast)
|
75
|
+
relation_name = ast.children[2].children.first
|
76
|
+
class_name =
|
77
|
+
extract_custom_class_name(ast) || relation_name.to_s.camelize
|
78
|
+
|
79
|
+
Util.build_public_method(
|
80
|
+
ns,
|
81
|
+
relation_name.to_s,
|
82
|
+
types: [class_name],
|
83
|
+
location: Util.build_location(ast, ns.filename)
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def extract_custom_class_name(ast)
|
88
|
+
options = ast.children[3..-1].find { |n| n.type == :hash }
|
89
|
+
return unless options
|
90
|
+
|
91
|
+
class_name_pair =
|
92
|
+
options.children.find do |n|
|
93
|
+
n.children[0].deconstruct == %i[sym class_name] &&
|
94
|
+
n.children[1].type == :str
|
95
|
+
end
|
96
|
+
class_name_pair && class_name_pair.children.last.children.last
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|