solargraph 0.40.4 → 0.42.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -5
  3. data/CHANGELOG.md +32 -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/bench.rb +13 -16
  10. data/lib/solargraph/compat.rb +15 -1
  11. data/lib/solargraph/diagnostics/rubocop.rb +10 -2
  12. data/lib/solargraph/diagnostics/rubocop_helpers.rb +18 -0
  13. data/lib/solargraph/diagnostics/type_check.rb +1 -1
  14. data/lib/solargraph/language_server/host.rb +108 -7
  15. data/lib/solargraph/language_server/host/diagnoser.rb +9 -1
  16. data/lib/solargraph/language_server/host/sources.rb +1 -1
  17. data/lib/solargraph/language_server/message/completion_item/resolve.rb +1 -0
  18. data/lib/solargraph/language_server/message/extended/environment.rb +3 -3
  19. data/lib/solargraph/language_server/message/initialize.rb +37 -35
  20. data/lib/solargraph/language_server/message/text_document/formatting.rb +28 -7
  21. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  22. data/lib/solargraph/library.rb +132 -22
  23. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -1
  24. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -1
  25. data/lib/solargraph/shell.rb +5 -1
  26. data/lib/solargraph/source/chain/head.rb +0 -16
  27. data/lib/solargraph/source/source_chainer.rb +2 -1
  28. data/lib/solargraph/source_map/mapper.rb +0 -5
  29. data/lib/solargraph/type_checker/checks.rb +4 -4
  30. data/lib/solargraph/version.rb +1 -1
  31. data/lib/solargraph/workspace.rb +1 -0
  32. data/lib/solargraph/workspace/config.rb +4 -3
  33. data/lib/solargraph/yard_map.rb +41 -39
  34. data/lib/solargraph/yard_map/core_fills.rb +1 -0
  35. data/solargraph.gemspec +1 -0
  36. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eff7d664014ae6d25990957afb4328baafe88ff76ef892db8b3d50791860845e
4
- data.tar.gz: 8038c884a63ce269f1a0faaf635e4c295fadd61c456ba2665c84a17b4f03a031
3
+ metadata.gz: 1099281670bd5cacd480624f66b36d7ce8fb6b69b4486f080d0c0d6436c0f36c
4
+ data.tar.gz: 4b1e028bc357204b953c31916845a7f12caefc07d733dc90cfb5bc142401f2d4
5
5
  SHA512:
6
- metadata.gz: a7b95e2ba342b191642a1d5ea228243a60b9211f6c05cab2acf09ddcaab3efb25cef488ca910964e0ac1c32edacc2f0ced4eef09fa819b03d2919af4ac734ca7
7
- data.tar.gz: 6990c07591d43fdb583484c00fc5221d228850fa75e12b5cd2632413a21c1984f634ce2655371d9be7016a035e23fe622469418779bf3285f03a087a38c394ae
6
+ metadata.gz: 771c40ddff0a11757d1e9c4487802afc9f5b992840383f525643957d92516e735dc7328a8d23ed1ff4f0e55ceb09e3792eb24818758e4b217927bf4ba9708b5a
7
+ data.tar.gz: 948101863fc7f3f167dee00139f07ccdf5711afd12125aa2a18b708ed4ba6edaffbc7ba0c1a7a7dd09ad51460a0827546841cf2dbcd223198247fd86d8b0841b
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,35 @@
1
+ ## 0.42.1 - June 11, 2021
2
+ - YardMap#change sets new directory (#445)
3
+
4
+ ## 0.42.0 - June 11, 2021
5
+ - Improve YardMap efficiency
6
+ - Bench includes Workspace for cataloging
7
+ - Initialize confirms static features from options (#436)
8
+ - Enable simple repairs without incremental sync (#416)
9
+ - Discard unrecognized client responses
10
+ - Notify on use of closest match for core (#390)
11
+
12
+ ## 0.41.2 - June 9, 2021
13
+ - Rescue InvalidOffset in async diagnosis
14
+ - Remove erroneous escaping from Hover
15
+
16
+ ## 0.41.1 - May 31, 2021
17
+ - ApiMap handles required bundles (#443)
18
+
19
+ ## 0.41.0 - May 30, 2021
20
+ - Chain constant at last double colon with more than two nested namespaces
21
+ - Fill Integer#times return type (#440)
22
+ - Validate included modules in type checks (#424)
23
+ - Faster language server initialization
24
+ - Server response to initialize is near immediate
25
+ - Workspace is mapped in a background thread
26
+ - Supported clients report mapping progress
27
+ - Log RuboCop corrections at info level (#426)
28
+ - Allow configuring the version of RuboCop to require (#430)
29
+ - Fix source of diagnostic (#434)
30
+ - Fix file argument in RuboCop (#435)
31
+ - Config ignores directories with .rb extension (#423)
32
+
1
33
  ## 0.40.4 - March 3, 2021
2
34
  - Fix optarg and blockarg ordering
3
35
  - Override specialization for #initialize
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
@@ -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
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rubocop'
4
3
  require 'stringio'
5
4
 
6
5
  module Solargraph
@@ -23,6 +22,7 @@ module Solargraph
23
22
  # @param _api_map [Solargraph::ApiMap]
24
23
  # @return [Array<Hash>]
25
24
  def diagnose source, _api_map
25
+ require_rubocop(rubocop_version)
26
26
  options, paths = generate_options(source.filename, source.code)
27
27
  store = RuboCop::ConfigStore.new
28
28
  runner = RuboCop::Runner.new(options, store)
@@ -36,6 +36,13 @@ module Solargraph
36
36
 
37
37
  private
38
38
 
39
+ # Extracts the rubocop version from _args_
40
+ #
41
+ # @return [String]
42
+ def rubocop_version
43
+ args.find { |a| a =~ /version=/ }.to_s.split('=').last
44
+ end
45
+
39
46
  # @param resp [Hash]
40
47
  # @return [Array<Hash>]
41
48
  def make_array resp
@@ -57,7 +64,8 @@ module Solargraph
57
64
  range: offense_range(off).to_hash,
58
65
  # 1 = Error, 2 = Warning, 3 = Information, 4 = Hint
59
66
  severity: SEVERITIES[off['severity']],
60
- source: off['cop_name'],
67
+ source: 'rubocop',
68
+ code: off['cop_name'],
61
69
  message: off['message'].gsub(/^#{off['cop_name']}\:/, '')
62
70
  }
63
71
  end