solargraph 0.40.3 → 0.42.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -5
  3. data/CHANGELOG.md +34 -0
  4. data/README.md +15 -0
  5. data/SPONSORS.md +1 -0
  6. data/lib/.rubocop.yml +4 -3
  7. data/lib/solargraph.rb +8 -7
  8. data/lib/solargraph/api_map.rb +40 -111
  9. data/lib/solargraph/api_map/store.rb +5 -0
  10. data/lib/solargraph/bench.rb +13 -16
  11. data/lib/solargraph/compat.rb +15 -1
  12. data/lib/solargraph/diagnostics/rubocop.rb +10 -2
  13. data/lib/solargraph/diagnostics/rubocop_helpers.rb +18 -0
  14. data/lib/solargraph/diagnostics/type_check.rb +1 -1
  15. data/lib/solargraph/language_server/host.rb +108 -7
  16. data/lib/solargraph/language_server/host/diagnoser.rb +9 -1
  17. data/lib/solargraph/language_server/host/sources.rb +1 -1
  18. data/lib/solargraph/language_server/message/completion_item/resolve.rb +1 -0
  19. data/lib/solargraph/language_server/message/extended/environment.rb +3 -3
  20. data/lib/solargraph/language_server/message/initialize.rb +37 -35
  21. data/lib/solargraph/language_server/message/text_document/formatting.rb +28 -7
  22. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  23. data/lib/solargraph/library.rb +132 -22
  24. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -1
  25. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +11 -12
  26. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +1 -6
  27. data/lib/solargraph/shell.rb +5 -1
  28. data/lib/solargraph/source.rb +1 -1
  29. data/lib/solargraph/source/chain/head.rb +0 -16
  30. data/lib/solargraph/source/source_chainer.rb +1 -0
  31. data/lib/solargraph/source_map/mapper.rb +0 -5
  32. data/lib/solargraph/type_checker.rb +2 -2
  33. data/lib/solargraph/type_checker/checks.rb +4 -4
  34. data/lib/solargraph/version.rb +1 -1
  35. data/lib/solargraph/workspace.rb +1 -0
  36. data/lib/solargraph/workspace/config.rb +4 -3
  37. data/lib/solargraph/yard_map.rb +41 -39
  38. data/lib/solargraph/yard_map/core_fills.rb +1 -0
  39. data/solargraph.gemspec +1 -0
  40. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8eaae0cf888e025f51bdbeea3c414f98e7014d416f58e23d29770b4969f1eb5a
4
- data.tar.gz: 4d0b4b1d24e81953aa819b83f318767e79ce7d6ed3cfb5f6e4b1fcf6a3b5ffc0
3
+ metadata.gz: ee62ce435bde441d527641ea98d3f448d36ce67f575f35d16927c315a98f1401
4
+ data.tar.gz: 514c7a0540e0bce8b050e9da507ed6d778b0ba482c5c73bef6ebc54360d93367
5
5
  SHA512:
6
- metadata.gz: 668db64477f7249ad2d9381292e19f4007a28d607eedfb96848bbb9efd55645ec78c705976e31f765d706c47f08243a322594ccf177f54c950432f565f286789
7
- data.tar.gz: e0986273bb88005f0471c5837f979507fd8f2d13b9d45c1717e6bd77c3ebfd42c746e87aaf41fdf0271007c31849f8622fe9e5a4974e8a35bd0d9f6a4b8e9e3c
6
+ metadata.gz: fec2a060f92ba925c0911b41025033afb6821e0f5758de849c2722a03b9b102b97f437dad23097d442546e254f21ec407fdf3ca494ee311ce3d2f26396cc9e1d
7
+ data.tar.gz: 919ae0f90af0de75228cf2c42eb5ab22a9f9ef3af9c9f7003c4fdf746d0b2ee43375f006a08b926f4d5135facfd97f4cacd5df47e2a1862c3d17a96d4c11b004
data/.travis.yml CHANGED
@@ -8,15 +8,10 @@ rvm:
8
8
  - jruby-head
9
9
  matrix:
10
10
  include:
11
- - rvm: 2.4
12
- os: osx
13
- - rvm: 2.6
14
- os: osx
15
11
  - rvm: 2.7
16
12
  os: osx
17
13
  allow_failures:
18
14
  - rvm: jruby-head
19
- - rvm: 3.0
20
15
  before_install:
21
16
  - gem update --system
22
17
  - gem install bundler
data/CHANGELOG.md CHANGED
@@ -1,3 +1,37 @@
1
+ ## 0.42.0 - June 11, 2021
2
+ - Improve YardMap efficiency
3
+ - Bench includes Workspace for cataloging
4
+ - Initialize confirms static features from options (#436)
5
+ - Enable simple repairs without incremental sync (#416)
6
+ - Discard unrecognized client responses
7
+ - Notify on use of closest match for core (#390)
8
+
9
+ ## 0.41.2 - June 9, 2021
10
+ - Rescue InvalidOffset in async diagnosis
11
+ - Remove erroneous escaping from Hover
12
+
13
+ ## 0.41.1 - May 31, 2021
14
+ - ApiMap handles required bundles (#443)
15
+
16
+ ## 0.41.0 - May 30, 2021
17
+ - Chain constant at last double colon with more than two nested namespaces
18
+ - Fill Integer#times return type (#440)
19
+ - Validate included modules in type checks (#424)
20
+ - Faster language server initialization
21
+ - Server response to initialize is near immediate
22
+ - Workspace is mapped in a background thread
23
+ - Supported clients report mapping progress
24
+ - Log RuboCop corrections at info level (#426)
25
+ - Allow configuring the version of RuboCop to require (#430)
26
+ - Fix source of diagnostic (#434)
27
+ - Fix file argument in RuboCop (#435)
28
+ - Config ignores directories with .rb extension (#423)
29
+
30
+ ## 0.40.4 - March 3, 2021
31
+ - Fix optarg and blockarg ordering
32
+ - Override specialization for #initialize
33
+ - Find definitions with cursor after double colon
34
+
1
35
  ## 0.40.3 - February 7, 2021
2
36
  - Simplify and allow to configure rubocop formatter (#403)
3
37
  - Type checker shows tag in param type errors (#398)
data/README.md CHANGED
@@ -79,6 +79,21 @@ Run `bundle install` and use `bundle exec yard gems` to generate the documentati
79
79
 
80
80
  In order to make sure you're using the correct dependencies, you can start the language server with Bundler. In VS Code, there's a `solargraph.useBundler` option. Other clients will vary, but the command you probably want to run is `bundle exec solargraph socket` or `bundle exec solargraph stdio`.
81
81
 
82
+ ### Rubocop Version
83
+
84
+ If you have multiple versions of [`rubocop`](https://rubygems.org/gems/rubocop) installed and you would like to choose a version other than the latest to use, this specific version can be configured.
85
+
86
+ In `.solargraph.yml`:
87
+
88
+ ```yaml
89
+ ---
90
+ reporters:
91
+ - rubocop:version=0.61.0 # diagnostics
92
+ formatter:
93
+ rubocop:
94
+ version: 0.61.0 # formatting
95
+ ```
96
+
82
97
  ### Integrating Other Editors
83
98
 
84
99
  The [language server protocol](https://microsoft.github.io/language-server-protocol/specification) is the recommended way for integrating Solargraph into editors and IDEs. Clients can connect using either stdio or TCP. Language client developers should refer to [https://solargraph.org/guides/language-server](https://solargraph.org/guides/language-server).
data/SPONSORS.md CHANGED
@@ -13,3 +13,4 @@ The following people and organizations provide funding or other resources. [Beco
13
13
  - Emily Strickland
14
14
  - Tom de Grunt
15
15
  - Akira Yamada
16
+ - Jared White
data/lib/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
- Layout/EndOfLine:
2
- EnforcedStyle: lf
1
+ AllCops:
2
+ NewCops: enable
3
3
  Style/MethodDefParentheses:
4
4
  Enabled: false
5
5
  Layout/EmptyLineAfterGuardClause:
@@ -10,6 +10,8 @@ Lint/RaiseException:
10
10
  Enabled: true
11
11
  Lint/StructNewOverride:
12
12
  Enabled: true
13
+ Metrics/MethodLength:
14
+ Max: 25
13
15
  Style/ExponentialNotation:
14
16
  Enabled: true
15
17
  Style/HashEachMethods:
@@ -18,4 +20,3 @@ Style/HashTransformKeys:
18
20
  Enabled: true
19
21
  Style/HashTransformValues:
20
22
  Enabled: true
21
-
data/lib/solargraph.rb CHANGED
@@ -9,13 +9,14 @@ require 'solargraph/version'
9
9
  # static analysis, and language server libraries.
10
10
  #
11
11
  module Solargraph
12
- class InvalidOffsetError < RangeError; end
13
- class DiagnosticsError < RuntimeError; end
14
- class FileNotFoundError < RuntimeError; end
15
- class SourceNotAvailableError < StandardError; end
16
- class ComplexTypeError < StandardError; end
17
- class WorkspaceTooLargeError < RuntimeError; end
18
- class BundleNotFoundError < StandardError; end
12
+ class InvalidOffsetError < RangeError; end
13
+ class DiagnosticsError < RuntimeError; end
14
+ class FileNotFoundError < RuntimeError; end
15
+ class SourceNotAvailableError < StandardError; end
16
+ class ComplexTypeError < StandardError; end
17
+ class WorkspaceTooLargeError < RuntimeError; end
18
+ class BundleNotFoundError < StandardError; end
19
+ class InvalidRubocopVersionError < RuntimeError; end
19
20
 
20
21
  autoload :Position, 'solargraph/position'
21
22
  autoload :Range, 'solargraph/range'
@@ -17,7 +17,6 @@ module Solargraph
17
17
  autoload :BundlerMethods, 'solargraph/api_map/bundler_methods'
18
18
 
19
19
  include SourceToYard
20
- include BundlerMethods
21
20
 
22
21
  # @return [Array<String>]
23
22
  attr_reader :unresolved_requires
@@ -33,7 +32,12 @@ module Solargraph
33
32
  # @param pins [Array<Pin::Base>]
34
33
  # @return [self]
35
34
  def index pins
36
- catalog Bench.new(pins: pins)
35
+ # @todo This implementation is incomplete. It should probably create a
36
+ # Bench.
37
+ @source_map_hash = {}
38
+ implicit.clear
39
+ cache.clear
40
+ @store = Store.new(yard_map.pins + pins)
37
41
  self
38
42
  end
39
43
 
@@ -42,97 +46,39 @@ module Solargraph
42
46
  # @param source [Source]
43
47
  # @return [self]
44
48
  def map source
45
- catalog Bench.new(opened: [source])
49
+ map = Solargraph::SourceMap.map(source)
50
+ catalog Bench.new(source_maps: [map])
46
51
  self
47
52
  end
48
53
 
49
- # @param name [String]
50
- # @return [YARD::Tags::MacroDirective, nil]
51
- def named_macro name
52
- store.named_macros[name]
53
- end
54
-
55
54
  # Catalog a bench.
56
55
  #
57
56
  # @param bench [Bench]
58
- # @return [self]
59
57
  def catalog bench
60
- new_map_hash = {}
61
- # Bench always needs to be merged if it adds or removes sources
62
- merged = (bench.sources.length == source_map_hash.values.length)
63
- bench.sources.each do |source|
64
- if source_map_hash.key?(source.filename)
65
- if source_map_hash[source.filename].code == source.code &&
66
- source_map_hash[source.filename].source.synchronized? &&
67
- source.synchronized?
68
- new_map_hash[source.filename] = source_map_hash[source.filename]
69
- elsif !source.synchronized?
70
- new_map_hash[source.filename] = source_map_hash[source.filename]
71
- # @todo Smelly instance variable access
72
- new_map_hash[source.filename].instance_variable_set(:@source, source)
73
- else
74
- map = Solargraph::SourceMap.map(source)
75
- if source_map_hash[source.filename].try_merge!(map)
76
- new_map_hash[source.filename] = source_map_hash[source.filename]
77
- else
78
- new_map_hash[source.filename] = map
79
- merged = false
80
- end
81
- end
82
- else
83
- map = Solargraph::SourceMap.map(source)
84
- new_map_hash[source.filename] = map
85
- merged = false
86
- end
87
- end
88
- return self if bench.pins.empty? && @store && merged
89
58
  implicit.clear
90
- pins = []
91
- reqs = Set.new
92
- # @param map [SourceMap]
93
- new_map_hash.each_value do |map|
94
- pins.concat map.pins
95
- reqs.merge map.requires.map(&:name)
96
- end
97
- pins.concat bench.pins
98
- reqs.merge bench.workspace.config.required
99
- @required = reqs
100
- bench.sources.each do |src|
101
- implicit.merge new_map_hash[src.filename].environ
102
- end
103
- # implicit.merge Convention.for_global(self)
104
- local_path_hash.clear
105
- unless bench.workspace.require_paths.empty?
106
- file_keys = new_map_hash.keys
107
- workspace_path = Pathname.new(bench.workspace.directory)
108
- reqs.delete_if do |r|
109
- bench.workspace.require_paths.any? do |base|
110
- pn = workspace_path.join(base, "#{r}.rb").to_s
111
- if file_keys.include? pn
112
- local_path_hash[r] = pn
113
- true
114
- else
115
- false
116
- end
117
- end
118
- end
119
- end
120
- reqs.merge implicit.requires
121
- br = reqs.include?('bundler/require') ? require_from_bundle(bench.workspace.directory) : {}
122
- reqs.merge br.keys
123
- yard_map.change(reqs.to_a, br, bench.workspace.gemnames)
124
- new_store = Store.new(yard_map.pins + implicit.pins + pins)
125
59
  @cache.clear
126
- @source_map_hash = new_map_hash
127
- @store = new_store
60
+ @source_map_hash = bench.source_maps.map { |s| [s.filename, s] }.to_h
61
+ pins = bench.source_maps.map(&:pins).flatten
62
+ external_requires = bench.external_requires
63
+ source_map_hash.each_value do |map|
64
+ implicit.merge map.environ
65
+ end
66
+ external_requires.merge implicit.requires
67
+ external_requires.merge bench.workspace.config.required
68
+ yard_map.change(external_requires, bench.workspace.directory, bench.workspace.source_gems)
69
+ @store = Store.new(yard_map.pins + implicit.pins + pins)
128
70
  @unresolved_requires = yard_map.unresolved_requires
129
- workspace_filenames.clear
130
- workspace_filenames.concat bench.workspace.filenames
131
71
  @rebindable_method_names = nil
132
72
  store.block_pins.each { |blk| blk.rebind(self) }
133
73
  self
134
74
  end
135
75
 
76
+ # @param name [String]
77
+ # @return [YARD::Tags::MacroDirective, nil]
78
+ def named_macro name
79
+ store.named_macros[name]
80
+ end
81
+
136
82
  def required
137
83
  @required ||= Set.new
138
84
  end
@@ -142,11 +88,6 @@ module Solargraph
142
88
  @implicit ||= Environ.new
143
89
  end
144
90
 
145
- # @return [Hash{String => String}]
146
- def local_path_hash
147
- @local_paths ||= {}
148
- end
149
-
150
91
  # @param filename [String]
151
92
  # @param position [Position, Array(Integer, Integer)]
152
93
  # @return [Source::Cursor]
@@ -173,7 +114,10 @@ module Solargraph
173
114
  def self.load directory
174
115
  api_map = new
175
116
  workspace = Solargraph::Workspace.new(directory)
176
- api_map.catalog Bench.new(workspace: workspace)
117
+ # api_map.catalog Bench.new(workspace: workspace)
118
+ library = Library.new(workspace)
119
+ library.map!
120
+ api_map.catalog library.bench
177
121
  api_map
178
122
  end
179
123
 
@@ -490,27 +434,6 @@ module Solargraph
490
434
  source_map_hash.keys.include?(filename)
491
435
  end
492
436
 
493
- # True if the specified file is included in the workspace.
494
- #
495
- # @param filename [String]
496
- def workspaced? filename
497
- workspace_filenames.include?(filename)
498
- end
499
-
500
- # @param location [Location]
501
- # @return [Location]
502
- def require_reference_at location
503
- map = source_map(location.filename)
504
- pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
505
- return nil if pin.nil?
506
- if local_path_hash.key?(pin.name)
507
- return Location.new(local_path_hash[pin.name], Solargraph::Range.from_to(0, 0, 0, 0))
508
- end
509
- yard_map.require_reference(pin.name)
510
- rescue FileNotFoundError
511
- nil
512
- end
513
-
514
437
  # Check if a class is a superclass of another class.
515
438
  #
516
439
  # @param sup [String] The superclass
@@ -531,20 +454,26 @@ module Solargraph
531
454
  @yard_map ||= YardMap.new
532
455
  end
533
456
 
534
- private
535
-
536
- # @return [Array<String>]
537
- def workspace_filenames
538
- @workspace_filenames ||= []
457
+ # Check if the host class includes the specified module.
458
+ #
459
+ # @param host [String] The class
460
+ # @param mod [String] The module
461
+ # @return [Boolean]
462
+ def type_include?(host, mod)
463
+ store.get_includes(host).include?(mod)
539
464
  end
540
465
 
466
+ private
467
+
541
468
  # A hash of source maps with filename keys.
542
469
  #
543
470
  # @return [Hash{String => SourceMap}]
544
471
  attr_reader :source_map_hash
545
472
 
546
473
  # @return [ApiMap::Store]
547
- attr_reader :store
474
+ def store
475
+ @store ||= Store.new
476
+ end
548
477
 
549
478
  # @return [Solargraph::ApiMap::Cache]
550
479
  attr_reader :cache
@@ -238,11 +238,16 @@ module Solargraph
238
238
  pins_by_class(Pin::Reference::Override).each do |ovr|
239
239
  pin = get_path_pins(ovr.name).first
240
240
  next if pin.nil?
241
+ new_pin = if pin.path.end_with?('#initialize')
242
+ get_path_pins(pin.path.sub(/#initialize/, '.new')).first
243
+ end
241
244
  (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
242
245
  pin.docstring.delete_tags tag.to_sym
246
+ new_pin.docstring.delete_tags tag.to_sym if new_pin
243
247
  end
244
248
  ovr.tags.each do |tag|
245
249
  pin.docstring.add_tag(tag)
250
+ new_pin.docstring.add_tag(tag) if new_pin
246
251
  end
247
252
  end
248
253
  end
@@ -1,30 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
4
+
3
5
  module Solargraph
4
- # An aggregation of a workspace and additional sources to be cataloged in an
5
- # ApiMap.
6
+ # A container of source maps and gem specs to be cataloged in an ApiMap.
6
7
  #
7
8
  class Bench
9
+ # @return [Set<SourceMap>]
10
+ attr_reader :source_maps
11
+
8
12
  # @return [Workspace]
9
13
  attr_reader :workspace
10
14
 
11
- # @return [Array<Source>]
12
- attr_reader :opened
13
-
14
- # @return [Array<Pin::Base>]
15
- attr_reader :pins
15
+ # @return [Set<String>]
16
+ attr_reader :external_requires
16
17
 
18
+ # @param source_maps [Array<SourceMap>, Set<SourceMap>]
17
19
  # @param workspace [Workspace]
18
- # @param opened [Array<Source>]
19
- def initialize workspace: Workspace.new, opened: [], pins: []
20
+ # @param external_requires [Array<String>, Set<String>]
21
+ def initialize source_maps: [], workspace: Workspace.new, external_requires: []
22
+ @source_maps = source_maps.to_set
20
23
  @workspace = workspace
21
- @opened = opened
22
- @pins = pins
23
- end
24
-
25
- # @return [Array<Source>]
26
- def sources
27
- @sources ||= (opened + workspace.sources).uniq(&:filename)
24
+ @external_requires = external_requires.to_set
28
25
  end
29
26
  end
30
27
  end
@@ -1,9 +1,23 @@
1
+ unless Hash.method_defined?(:transform_keys)
2
+ class Hash
3
+ def transform_keys &block
4
+ result = {}
5
+ each_pair do |k, v|
6
+ result[block.call(k)] = v
7
+ end
8
+ result
9
+ end
10
+ end
11
+ end
12
+
1
13
  unless Hash.method_defined?(:transform_values)
2
14
  class Hash
3
15
  def transform_values &block
16
+ result = {}
4
17
  each_pair do |k, v|
5
- self[k] = block.call(v)
18
+ result[k] = block.call(v)
6
19
  end
20
+ result
7
21
  end
8
22
  end
9
23
  end