solargraph 0.39.0 → 0.40.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.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -7
  3. data/CHANGELOG.md +984 -0
  4. data/Rakefile +12 -1
  5. data/SPONSORS.md +6 -0
  6. data/lib/.rubocop.yml +21 -0
  7. data/lib/solargraph/api_map/cache.rb +4 -0
  8. data/lib/solargraph/api_map/store.rb +35 -51
  9. data/lib/solargraph/api_map.rb +94 -87
  10. data/lib/solargraph/{bundle.rb → bench.rb} +6 -2
  11. data/lib/solargraph/compat.rb +23 -0
  12. data/lib/solargraph/complex_type.rb +2 -2
  13. data/lib/solargraph/convention/base.rb +16 -8
  14. data/lib/solargraph/convention/gemfile.rb +2 -5
  15. data/lib/solargraph/convention/gemspec.rb +3 -6
  16. data/lib/solargraph/convention/rspec.rb +3 -6
  17. data/lib/solargraph/convention.rb +14 -5
  18. data/lib/solargraph/diagnostics/rubocop.rb +2 -1
  19. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
  20. data/lib/solargraph/documentor.rb +4 -0
  21. data/lib/solargraph/environ.rb +11 -6
  22. data/lib/solargraph/language_server/host.rb +1 -1
  23. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +6 -1
  24. data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
  25. data/lib/solargraph/language_server/message/text_document/formatting.rb +7 -3
  26. data/lib/solargraph/language_server/uri_helpers.rb +23 -3
  27. data/lib/solargraph/library.rb +22 -8
  28. data/lib/solargraph/parser/legacy/class_methods.rb +4 -0
  29. data/lib/solargraph/parser/legacy/node_chainer.rb +10 -7
  30. data/lib/solargraph/parser/legacy/node_methods.rb +16 -3
  31. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +1 -1
  32. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +48 -23
  33. data/lib/solargraph/parser/node_processor/base.rb +3 -0
  34. data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -2
  35. data/lib/solargraph/parser/rubyvm/node_chainer.rb +11 -9
  36. data/lib/solargraph/parser/rubyvm/node_methods.rb +6 -1
  37. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +35 -11
  38. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +1 -1
  39. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +6 -1
  40. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +6 -1
  41. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +52 -67
  42. data/lib/solargraph/parser/rubyvm/node_processors.rb +2 -0
  43. data/lib/solargraph/pin/base.rb +2 -2
  44. data/lib/solargraph/pin/base_variable.rb +1 -1
  45. data/lib/solargraph/pin/block.rb +28 -14
  46. data/lib/solargraph/pin/closure.rb +1 -1
  47. data/lib/solargraph/pin/common.rb +1 -1
  48. data/lib/solargraph/pin/constant.rb +1 -1
  49. data/lib/solargraph/pin/conversions.rb +3 -4
  50. data/lib/solargraph/pin/documenting.rb +6 -11
  51. data/lib/solargraph/pin/local_variable.rb +1 -1
  52. data/lib/solargraph/pin/method.rb +143 -9
  53. data/lib/solargraph/pin/method_alias.rb +2 -2
  54. data/lib/solargraph/pin/namespace.rb +1 -1
  55. data/lib/solargraph/pin/parameter.rb +2 -2
  56. data/lib/solargraph/pin/proxy_type.rb +1 -1
  57. data/lib/solargraph/pin.rb +0 -3
  58. data/lib/solargraph/position.rb +2 -14
  59. data/lib/solargraph/shell.rb +2 -1
  60. data/lib/solargraph/source/chain/call.rb +9 -0
  61. data/lib/solargraph/source/chain/head.rb +14 -8
  62. data/lib/solargraph/source/chain/z_super.rb +30 -0
  63. data/lib/solargraph/source/chain.rb +19 -36
  64. data/lib/solargraph/source/source_chainer.rb +2 -1
  65. data/lib/solargraph/source.rb +24 -9
  66. data/lib/solargraph/source_map/clip.rb +78 -44
  67. data/lib/solargraph/source_map/mapper.rb +41 -21
  68. data/lib/solargraph/source_map.rb +20 -2
  69. data/lib/solargraph/type_checker/param_def.rb +1 -1
  70. data/lib/solargraph/type_checker.rb +61 -42
  71. data/lib/solargraph/version.rb +1 -1
  72. data/lib/solargraph/views/_name_type_tag.erb +1 -1
  73. data/lib/solargraph/workspace.rb +1 -1
  74. data/lib/solargraph/yard_map/core_fills.rb +185 -0
  75. data/lib/solargraph/yard_map/helpers.rb +16 -0
  76. data/lib/solargraph/{pin/yard_pin/constant.rb → yard_map/mapper/to_constant.rb} +6 -6
  77. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
  78. data/lib/solargraph/{pin/yard_pin/namespace.rb → yard_map/mapper/to_namespace.rb} +6 -6
  79. data/lib/solargraph/yard_map/mapper.rb +17 -8
  80. data/lib/solargraph/yard_map/rdoc_to_yard.rb +26 -15
  81. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
  82. data/lib/solargraph/yard_map/to_method.rb +79 -0
  83. data/lib/solargraph/yard_map.rb +140 -92
  84. data/lib/solargraph.rb +5 -4
  85. data/solargraph.gemspec +5 -5
  86. data/yardoc/2.2.2.tar.gz +0 -0
  87. metadata +29 -41
  88. data/.rubocop.yml +0 -6
  89. data/lib/solargraph/core_fills.rb +0 -159
  90. data/lib/solargraph/pin/attribute.rb +0 -49
  91. data/lib/solargraph/pin/base_method.rb +0 -141
  92. data/lib/solargraph/pin/yard_pin/method.rb +0 -65
  93. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +0 -26
  94. data/lib/solargraph/pin/yard_pin.rb +0 -12
  95. data/lib/solargraph/stdlib_fills.rb +0 -32
  96. data/travis-bundler.rb +0 -11
@@ -11,22 +11,27 @@ module Solargraph
11
11
  extend ApiMap::SourceToYard
12
12
 
13
13
  # @param spec [Gem::Specification]
14
- def self.run spec
14
+ # @param cache_dir [String]
15
+ # @return [void]
16
+ def self.run spec, cache_dir: nil
15
17
  Dir.mktmpdir do |tmpdir|
16
- rdir = File.join(tmpdir, 'rdoc')
17
- Dir.chdir spec.full_gem_path do
18
+ rdir = File.join(tmpdir, 'sg_tmp_rdoc')
19
+ FileUtils.cp_r Dir.glob(File.join(spec.full_gem_path, '*')), tmpdir
20
+ Dir.chdir tmpdir do
18
21
  pins = []
19
22
  pins.push Solargraph::Pin::ROOT_PIN
20
23
  name_hash = {}
21
- cmd = "rdoc -q -N -r -o #{rdir}"
24
+
25
+ argv = ['-q', '-r', '-N', '-o', rdir]
22
26
  spec.load_paths.each do |path|
23
- cmd += " -i #{path}"
27
+ argv.concat ['-i', path]
24
28
  end
25
- `#{cmd}`
26
- store = RDoc::Store.new(rdir)
27
- store.load_all
29
+ rdoc = RDoc::RDoc.new
30
+ rdoc.document argv
31
+ # @type [RDoc::Store]
32
+ store = rdoc.store
33
+ store.path = rdir
28
34
  store.cache[:modules].each do |mod|
29
- # store.load_class(mod)
30
35
  # @type [RDoc::NormalClass]
31
36
  mod = store.find_class_or_module(mod)
32
37
  closure = pins.select { |pin| pin.path == mod.full_name.split('::')[0..-2].join('::') }.first || pins.first
@@ -46,7 +51,7 @@ module Solargraph
46
51
  closure: namepin
47
52
  )
48
53
  end
49
- # @param inc [RDoc::Extend]
54
+ # @param ext [RDoc::Extend]
50
55
  mod.extends.each do |ext|
51
56
  pins.push Solargraph::Pin::Reference::Extend.new(
52
57
  location: locate(ext),
@@ -58,13 +63,13 @@ module Solargraph
58
63
  name_hash[mod.full_name] = namepin
59
64
  # @param met [RDoc::AnyMethod]
60
65
  mod.each_method do |met|
61
- pin = Solargraph::SourceMap.load_string("def Object.tmp#{met.param_seq};end").first_pin('Object.tmp') || Solargraph::Pin::BaseMethod.new
66
+ pin = Solargraph::SourceMap.load_string("def Object.tmp#{met.param_seq};end").first_pin('Object.tmp') || Solargraph::Pin::Method.new
62
67
  pins.push Solargraph::Pin::Method.new(
63
68
  name: met.name,
64
69
  closure: namepin,
65
70
  comments: commentary(met.comment),
66
71
  scope: met.type.to_sym,
67
- args: pin.parameters,
72
+ parameters: pin.parameters,
68
73
  visibility: met.visibility,
69
74
  location: locate(met)
70
75
  )
@@ -85,11 +90,13 @@ module Solargraph
85
90
  code_object_map.values.each do |co|
86
91
  YARD::Registry.register(co)
87
92
  end
88
- cache_dir = File.join(Solargraph::YardMap::CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}", "yardoc")
93
+ cache_dir ||= File.join(Solargraph::YardMap::CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}", "yardoc")
89
94
  FileUtils.remove_entry_secure cache_dir if File.exist?(cache_dir)
90
95
  FileUtils.mkdir_p cache_dir
91
96
  # @todo Should merge be true?
92
97
  YARD::Registry.save true, cache_dir
98
+ # Clear the serialized cache if it exists
99
+ FileUtils.safe_unlink File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
93
100
  end
94
101
  end
95
102
  end
@@ -98,7 +105,11 @@ module Solargraph
98
105
  mod.full_name.split('::')[0..-2].join('::')
99
106
  end
100
107
 
108
+ # @param cmnt [RDoc::Comment]
109
+ # @return [String]
101
110
  def self.commentary cmnt
111
+ return cmnt if cmnt.is_a?(String)
112
+ return cmnt.text if cmnt.is_a?(RDoc::Comment)
102
113
  result = []
103
114
  cmnt.parts.each do |part|
104
115
  result.push RDoc::Markup::ToHtml.new({}).to_html(part.text) if part.respond_to?(:text)
@@ -119,9 +130,9 @@ module Solargraph
119
130
 
120
131
  def self.find_file obj
121
132
  if obj.respond_to?(:in_files) && !obj.in_files.empty?
122
- [obj.in_files.first.to_s.sub(/^file /, ''), obj.in_files.first.line]
133
+ [obj.in_files.first.to_s.sub(/^file /, ''), obj.line]
123
134
  else
124
- [obj.file_name, obj.line]
135
+ [obj.file, obj.line]
125
136
  end
126
137
  end
127
138
  end
@@ -0,0 +1,43 @@
1
+ module Solargraph
2
+ class YardMap
3
+ module StdlibFills
4
+ Override = Pin::Reference::Override
5
+
6
+ LIBS = {
7
+ 'benchmark' => [
8
+ Override.method_return('Benchmark.measure', 'Benchmark::Tms')
9
+ ],
10
+
11
+ 'pathname' => [
12
+ Override.method_return('Pathname#join', 'Pathname'),
13
+ Override.method_return('Pathname#basename', 'Pathname'),
14
+ Override.method_return('Pathname#dirname', 'Pathname'),
15
+ Override.method_return('Pathname#cleanpath', 'Pathname'),
16
+ Override.method_return('Pathname#children', 'Array<Pathname>'),
17
+ Override.method_return('Pathname#entries', 'Array<Pathname>')
18
+ ],
19
+
20
+ 'set' => [
21
+ Override.method_return('Enumerable#to_set', 'Set'),
22
+ Override.method_return('Set#add', 'self'),
23
+ Override.method_return('Set#add?', 'self, nil'),
24
+ Override.method_return('Set#classify', 'Hash'),
25
+ Override.from_comment('Set#each', '@yieldparam_single_parameter'),
26
+ ],
27
+
28
+ 'tempfile' => [
29
+ Override.from_comment('Tempfile.open', %(
30
+ @yieldparam [Tempfile]
31
+ @return [Tempfile]
32
+ ))
33
+ ]
34
+ }.freeze
35
+
36
+ # @param path [String]
37
+ # @return [Array<Pin::Reference::Override>]
38
+ def self.get path
39
+ LIBS[path] || []
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class YardMap
5
+ class ToMethod
6
+ module InnerMethods
7
+ module_function
8
+
9
+ # @param code_object [YARD::CodeObjects::Base]
10
+ # @return [Array<Solargraph::Pin::Parameter>]
11
+ def get_parameters code_object, location, comments
12
+ return [] unless code_object.is_a?(YARD::CodeObjects::MethodObject)
13
+ # HACK: Skip `nil` and `self` parameters that are sometimes emitted
14
+ # for methods defined in C
15
+ # See https://github.com/castwide/solargraph/issues/345
16
+ code_object.parameters.select { |a| a[0] && a[0] != 'self' }.map do |a|
17
+ Solargraph::Pin::Parameter.new(
18
+ location: location,
19
+ closure: self,
20
+ comments: comments,
21
+ name: arg_name(a),
22
+ presence: nil,
23
+ decl: arg_type(a),
24
+ asgn_code: a[1]
25
+ )
26
+ end
27
+ end
28
+
29
+ # @param a [Array]
30
+ # @return [String]
31
+ def arg_name a
32
+ a[0].gsub(/[^a-z0-9_]/i, '')
33
+ end
34
+
35
+ # @param a [Array]
36
+ # @return [::Symbol]
37
+ def arg_type a
38
+ if a[0].start_with?('**')
39
+ :kwrestarg
40
+ elsif a[0].start_with?('*')
41
+ :restarg
42
+ elsif a[0].start_with?('&')
43
+ :blockarg
44
+ elsif a[0].end_with?(':')
45
+ a[1] ? :kwoptarg : :kwarg
46
+ elsif a[1]
47
+ :optarg
48
+ else
49
+ :arg
50
+ end
51
+ end
52
+ end
53
+ private_constant :InnerMethods
54
+
55
+ # include YardMixin
56
+ # extend YardMixin
57
+ extend Helpers
58
+
59
+ def make code_object, name = nil, scope = nil, visibility = nil, closure = nil, spec = nil
60
+ closure ||= Solargraph::Pin::Namespace.new(
61
+ name: code_object.namespace.to_s,
62
+ gates: [code_object.namespace.to_s]
63
+ )
64
+ location = object_location(code_object, spec)
65
+ comments = code_object.docstring ? code_object.docstring.all.to_s : ''
66
+ Pin::Method.new(
67
+ location: location,
68
+ closure: closure,
69
+ name: name || code_object.name.to_s,
70
+ comments: comments,
71
+ scope: scope || code_object.scope,
72
+ visibility: visibility || code_object.visibility,
73
+ parameters: InnerMethods.get_parameters(code_object, location, comments),
74
+ explicit: code_object.is_explicit?
75
+ )
76
+ end
77
+ end
78
+ end
79
+ end
@@ -3,17 +3,22 @@
3
3
  require 'yard'
4
4
  require 'yard-solargraph'
5
5
  require 'rubygems/package'
6
+ require 'set'
6
7
 
7
8
  module Solargraph
8
9
  # The YardMap provides access to YARD documentation for the Ruby core, the
9
10
  # stdlib, and gems.
10
11
  #
11
12
  class YardMap
12
- autoload :Cache, 'solargraph/yard_map/cache'
13
- autoload :CoreDocs, 'solargraph/yard_map/core_docs'
14
- autoload :CoreGen, 'solargraph/yard_map/core_gen'
15
- autoload :Mapper, 'solargraph/yard_map/mapper'
16
- autoload :RdocToYard, 'solargraph/yard_map/rdoc_to_yard'
13
+ autoload :Cache, 'solargraph/yard_map/cache'
14
+ autoload :CoreDocs, 'solargraph/yard_map/core_docs'
15
+ autoload :CoreGen, 'solargraph/yard_map/core_gen'
16
+ autoload :Mapper, 'solargraph/yard_map/mapper'
17
+ autoload :RdocToYard, 'solargraph/yard_map/rdoc_to_yard'
18
+ autoload :CoreFills, 'solargraph/yard_map/core_fills'
19
+ autoload :StdlibFills, 'solargraph/yard_map/stdlib_fills'
20
+ autoload :Helpers, 'solargraph/yard_map/helpers'
21
+ autoload :ToMethod, 'solargraph/yard_map/to_method'
17
22
 
18
23
  CoreDocs.require_minimum
19
24
 
@@ -49,6 +54,8 @@ module Solargraph
49
54
  def initialize(required: [], gemset: {}, with_dependencies: true)
50
55
  # HACK: YardMap needs its own copy of this array
51
56
  @required = required.clone
57
+ # HACK: Hardcoded YAML handling
58
+ @required.push 'psych' if @required.include?('yaml')
52
59
  @with_dependencies = with_dependencies
53
60
  @gem_paths = {}
54
61
  @stdlib_namespaces = []
@@ -56,6 +63,7 @@ module Solargraph
56
63
  @source_gems = []
57
64
  process_requires
58
65
  yardocs.uniq!
66
+ @pin_select_cache = {}
59
67
  end
60
68
 
61
69
  # @return [Array<Solargraph::Pin::Base>]
@@ -72,6 +80,8 @@ module Solargraph
72
80
  # @param new_gemset [Hash{String => String}]
73
81
  # @return [Boolean]
74
82
  def change new_requires, new_gemset, source_gems = []
83
+ # HACK: Hardcoded YAML handling
84
+ new_requires.push 'psych' if new_requires.include?('yaml')
75
85
  if new_requires.uniq.sort == required.uniq.sort && new_gemset == gemset && @source_gems.uniq.sort == source_gems.uniq.sort
76
86
  false
77
87
  else
@@ -80,10 +90,22 @@ module Solargraph
80
90
  @gemset = new_gemset
81
91
  @source_gems = source_gems
82
92
  process_requires
93
+ @rebindable_method_names = nil
94
+ @pin_class_hash = nil
95
+ @pin_select_cache = {}
83
96
  true
84
97
  end
85
98
  end
86
99
 
100
+ # @return [Set<String>]
101
+ def rebindable_method_names
102
+ @rebindable_method_names ||= pins_by_class(Pin::Method)
103
+ .select { |pin| pin.comments && pin.comments.include?('@yieldself') }
104
+ .map(&:name)
105
+ .concat(['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec'])
106
+ .to_set
107
+ end
108
+
87
109
  # @return [Array<String>]
88
110
  def yardocs
89
111
  @yardocs ||= []
@@ -102,7 +124,7 @@ module Solargraph
102
124
  else
103
125
  YARD::Registry.load! y
104
126
  end
105
- rescue Exception => e
127
+ rescue StandardError => e
106
128
  Solargraph::Logging.logger.warn "Error loading yardoc '#{y}' #{e.class} #{e.message}"
107
129
  yardocs.delete y
108
130
  nil
@@ -110,58 +132,14 @@ module Solargraph
110
132
 
111
133
  # @return [Array<Solargraph::Pin::Base>]
112
134
  def core_pins
113
- @@core_pins ||= begin
114
- yd = CoreDocs.yardoc_file
115
- ser = File.join(File.dirname(yd), 'core.ser')
116
- result = []
117
- if File.file?(ser)
118
- file = File.open(ser, 'rb')
119
- dump = file.read
120
- file.close
121
- result.concat Marshal.load(dump)
122
- else
123
- load_yardoc CoreDocs.yardoc_file
124
- result.concat Mapper.new(YARD::Registry.all).map
125
- # HACK: Assume core methods with a single `args` parameter accept restarg
126
- result.select { |pin| pin.is_a?(Solargraph::Pin::BaseMethod )}.each do |pin|
127
- if pin.parameters.length == 1 && pin.parameters.first.name == 'args' && pin.parameters.first.decl == :arg
128
- # @todo Smelly instance variable access
129
- pin.parameters.first.instance_variable_set(:@decl, :restarg)
130
- end
131
- end
132
- # HACK: Set missing parameters on `==` methods, e.g., `Symbol#==`
133
- result.select { |pin| pin.name == '==' && pin.parameters.empty? }.each do |pin|
134
- pin.parameters.push Pin::Parameter.new(decl: :arg, name: 'obj2')
135
- end
136
- dump = Marshal.dump(result)
137
- file = File.open(ser, 'wb')
138
- file.write dump
139
- file.close
140
- end
141
- # HACK: Add Errno exception classes
142
- errno = result.select{ |pin| pin.path == 'Errno' }.first
143
- Errno.constants.each do |const|
144
- result.push Solargraph::Pin::Namespace.new(type: :class, name: const.to_s, closure: errno)
145
- result.push Solargraph::Pin::Reference::Superclass.new(closure: result.last, name: 'SystemCallError')
146
- end
147
- CoreFills::OVERRIDES.each do |ovr|
148
- pin = result.select { |p| p.path == ovr.name }.first
149
- next if pin.nil?
150
- (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
151
- pin.docstring.delete_tags tag.to_sym
152
- end
153
- ovr.tags.each do |tag|
154
- pin.docstring.add_tag(tag)
155
- end
156
- end
157
- result
158
- end
135
+ # Using a class variable to reduce loads
136
+ @@core_pins ||= load_core_pins
159
137
  end
160
138
 
161
139
  # @param path [String]
162
140
  # @return [Pin::Base]
163
141
  def path_pin path
164
- pins.select{ |p| p.path == path }.first
142
+ pins.select { |p| p.path == path }.first
165
143
  end
166
144
 
167
145
  # Get the location of a file referenced by a require path.
@@ -181,6 +159,10 @@ module Solargraph
181
159
  nil
182
160
  end
183
161
 
162
+ def stdlib_pins
163
+ @stdlib_pins ||= []
164
+ end
165
+
184
166
  private
185
167
 
186
168
  # @return [YardMap::Cache]
@@ -188,6 +170,16 @@ module Solargraph
188
170
  @cache ||= YardMap::Cache.new
189
171
  end
190
172
 
173
+ # @return [Hash]
174
+ def pin_class_hash
175
+ @pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
176
+ end
177
+
178
+ # @return [Array<Pin::Base>]
179
+ def pins_by_class klass
180
+ @pin_select_cache[klass] ||= pin_class_hash.select { |key, _| key <= klass }.values.flatten
181
+ end
182
+
191
183
  # @param ns [YARD::CodeObjects::NamespaceObject]
192
184
  # @return [Array<YARD::CodeObjects::Base>]
193
185
  def recurse_namespace_object ns
@@ -201,12 +193,13 @@ module Solargraph
201
193
 
202
194
  # @return [void]
203
195
  def process_requires
204
- pins.clear
196
+ pins.replace core_pins
205
197
  unresolved_requires.clear
206
- # stdnames = {}
198
+ stdlib_pins.clear
199
+ environ = Convention.for_global(self)
207
200
  done = []
208
201
  from_std = []
209
- required.each do |r|
202
+ (required + environ.requires).each do |r|
210
203
  next if r.nil? || r.empty? || done.include?(r)
211
204
  done.push r
212
205
  cached = cache.get_path_pins(r)
@@ -231,37 +224,17 @@ module Solargraph
231
224
  yardocs.unshift yd
232
225
  result.concat process_yardoc yd, spec
233
226
  result.concat add_gem_dependencies(spec) if with_dependencies?
234
- stdlib_fill r, result
235
227
  end
236
228
  rescue Gem::LoadError => e
237
229
  base = r.split('/').first
238
230
  next if from_std.include?(base)
239
231
  from_std.push base
240
- stdtmp = []
241
- ser = File.join(File.dirname(CoreDocs.yardoc_stdlib_file), "#{base}.ser")
242
- if File.file?(ser)
243
- Solargraph.logger.info "Loading #{base} stdlib from cache"
244
- file = File.open(ser, 'rb')
245
- dump = file.read
246
- file.close
247
- stdtmp.concat Marshal.load(dump)
248
- else
249
- if stdlib_paths[base]
250
- Solargraph.logger.info "Loading #{base} stdlib from yardoc"
251
- stdtmp.concat Mapper.new(stdlib_paths[base]).map
252
- next if stdtmp.empty?
253
- dump = Marshal.dump(stdtmp)
254
- file = File.open(ser, 'wb')
255
- file.write dump
256
- file.close
257
- end
258
- end
232
+ stdtmp = load_stdlib_pins(base)
259
233
  if stdtmp.empty?
260
234
  unresolved_requires.push r
261
235
  else
262
- stdlib_fill base, stdtmp
236
+ stdlib_pins.concat stdtmp
263
237
  result.concat stdtmp
264
- # stdnames[r] = stdtmp
265
238
  end
266
239
  end
267
240
  result.delete_if(&:nil?)
@@ -270,8 +243,13 @@ module Solargraph
270
243
  pins.concat result
271
244
  end
272
245
  end
273
- # pins.concat process_stdlib(stdnames)
274
- pins.concat core_pins
246
+ if required.include?('yaml') && required.include?('psych')
247
+ # HACK: Hardcoded YAML handling
248
+ # @todo Why can't this be handled with an override or a virtual pin?
249
+ pin = path_pin('YAML')
250
+ pin.instance_variable_set(:@return_type, ComplexType.parse('Module<Psych>')) unless pin.nil?
251
+ end
252
+ pins.concat environ.pins
275
253
  end
276
254
 
277
255
  # @param spec [Gem::Specification]
@@ -316,7 +294,12 @@ module Solargraph
316
294
  file = File.open(ser, 'rb')
317
295
  dump = file.read
318
296
  file.close
319
- return Marshal.load(dump)
297
+ begin
298
+ return Marshal.load(dump)
299
+ rescue StandardError => e
300
+ Solargraph.logger.warn "Error loading pin cache: [#{e.class}] #{e.message}"
301
+ File.unlink ser
302
+ end
320
303
  end
321
304
  end
322
305
  if !size.nil? && size > 20_000_000
@@ -364,20 +347,85 @@ module Solargraph
364
347
  spec
365
348
  end
366
349
 
367
- # @param path [String]
368
- # @param pins [Array<Pin::Base>]
369
- # @return [void]
370
- def stdlib_fill path, pins
371
- StdlibFills.get(path).each do |ovr|
372
- pin = pins.select { |p| p.path == ovr.name }.first
373
- next if pin.nil?
374
- (ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
375
- pin.docstring.delete_tags tag.to_sym
350
+ def load_core_pins
351
+ yd = CoreDocs.yardoc_file
352
+ ser = File.join(File.dirname(yd), 'core.ser')
353
+ result = if File.file?(ser)
354
+ file = File.open(ser, 'rb')
355
+ dump = file.read
356
+ file.close
357
+ begin
358
+ Marshal.load(dump)
359
+ rescue StandardError => e
360
+ Solargraph.logger.warn "Error loading core pin cache: [#{e.class}] #{e.message}"
361
+ File.unlink ser
362
+ read_core_and_save_cache(yd, ser)
376
363
  end
377
- ovr.tags.each do |tag|
378
- pin.docstring.add_tag(tag)
364
+ else
365
+ read_core_and_save_cache(yd, ser)
366
+ end
367
+ ApiMap::Store.new(result + CoreFills::ALL).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
368
+ end
369
+
370
+ def read_core_and_save_cache yd, ser
371
+ result = []
372
+ load_yardoc yd
373
+ result.concat Mapper.new(YARD::Registry.all).map
374
+ # HACK: Assume core methods with a single `args` parameter accept restarg
375
+ result.select { |pin| pin.is_a?(Solargraph::Pin::Method )}.each do |pin|
376
+ if pin.parameters.length == 1 && pin.parameters.first.name == 'args' && pin.parameters.first.decl == :arg
377
+ # @todo Smelly instance variable access
378
+ pin.parameters.first.instance_variable_set(:@decl, :restarg)
379
379
  end
380
380
  end
381
+ # HACK: Set missing parameters on `==` methods, e.g., `Symbol#==`
382
+ result.select { |pin| pin.name == '==' && pin.parameters.empty? }.each do |pin|
383
+ pin.parameters.push Pin::Parameter.new(decl: :arg, name: 'obj2')
384
+ end
385
+ dump = Marshal.dump(result)
386
+ file = File.open(ser, 'wb')
387
+ file.write dump
388
+ file.close
389
+ result
390
+ end
391
+
392
+ def load_stdlib_pins base
393
+ ser = File.join(File.dirname(CoreDocs.yardoc_stdlib_file), "#{base}.ser")
394
+ result = if File.file?(ser)
395
+ Solargraph.logger.info "Loading #{base} stdlib from cache"
396
+ file = File.open(ser, 'rb')
397
+ dump = file.read
398
+ file.close
399
+ begin
400
+ Marshal.load(dump)
401
+ rescue StandardError => e
402
+ Solargraph.logger.warn "Error loading #{base} stdlib pin cache: [#{e.class}] #{e.message}"
403
+ File.unlink ser
404
+ read_stdlib_and_save_cache(base, ser)
405
+ end
406
+ else
407
+ read_stdlib_and_save_cache(base, ser)
408
+ end
409
+ fills = StdlibFills.get(base)
410
+ unless fills.empty?
411
+ result = ApiMap::Store.new(result + fills).pins.reject { |pin| pin.is_a?(Pin::Reference::Override) }
412
+ end
413
+ result
414
+ end
415
+
416
+ def read_stdlib_and_save_cache base, ser
417
+ result = []
418
+ if stdlib_paths[base]
419
+ Solargraph.logger.info "Loading #{base} stdlib from yardoc"
420
+ result.concat Mapper.new(stdlib_paths[base]).map
421
+ unless result.empty?
422
+ dump = Marshal.dump(result)
423
+ file = File.open(ser, 'wb')
424
+ file.write dump
425
+ file.close
426
+ end
427
+ end
428
+ result
381
429
  end
382
430
  end
383
431
  end
data/lib/solargraph.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ Encoding.default_external = 'UTF-8'
4
+
5
+ require 'solargraph/compat'
3
6
  require 'solargraph/version'
4
7
 
5
8
  # The top-level namespace for the Solargraph code mapping, documentation,
@@ -24,15 +27,13 @@ module Solargraph
24
27
  autoload :YardMap, 'solargraph/yard_map'
25
28
  autoload :Pin, 'solargraph/pin'
26
29
  autoload :ServerMethods, 'solargraph/server_methods'
27
- autoload :CoreFills, 'solargraph/core_fills'
28
- autoload :StdlibFills, 'solargraph/stdlib_fills'
29
30
  autoload :LanguageServer, 'solargraph/language_server'
30
31
  autoload :Workspace, 'solargraph/workspace'
31
32
  autoload :Page, 'solargraph/page'
32
33
  autoload :Library, 'solargraph/library'
33
34
  autoload :Diagnostics, 'solargraph/diagnostics'
34
35
  autoload :ComplexType, 'solargraph/complex_type'
35
- autoload :Bundle, 'solargraph/bundle'
36
+ autoload :Bench, 'solargraph/bench'
36
37
  autoload :Logging, 'solargraph/logging'
37
38
  autoload :TypeChecker, 'solargraph/type_checker'
38
39
  autoload :Environ, 'solargraph/environ'
@@ -53,7 +54,7 @@ module Solargraph
53
54
  end
54
55
 
55
56
  # A helper method that runs Bundler.with_unbundled_env or falls back to
56
- # Bundler.with_clean env for earlier versions of Bundler.
57
+ # Bundler.with_clean_env for earlier versions of Bundler.
57
58
  #
58
59
  def self.with_clean_env &block
59
60
  meth = if Bundler.respond_to?(:with_unbundled_env)
data/solargraph.gemspec CHANGED
@@ -17,18 +17,18 @@ Gem::Specification.new do |s|
17
17
  s.license = 'MIT'
18
18
  s.executables = ['solargraph']
19
19
 
20
- s.required_ruby_version = '>= 2.1'
20
+ s.required_ruby_version = '>= 2.4'
21
21
 
22
22
  s.add_runtime_dependency 'backport', '~> 1.1'
23
23
  s.add_runtime_dependency 'benchmark'
24
24
  s.add_runtime_dependency 'bundler', '>= 1.17.2'
25
25
  s.add_runtime_dependency 'e2mmap'
26
26
  s.add_runtime_dependency 'jaro_winkler', '~> 1.5'
27
- s.add_runtime_dependency 'maruku', '~> 0.7', '>= 0.7.3'
28
- s.add_runtime_dependency 'nokogiri', '~> 1.9', '>= 1.9.1'
27
+ s.add_runtime_dependency 'kramdown', '~> 2.3'
28
+ s.add_runtime_dependency 'kramdown-parser-gfm', '~> 1.1'
29
29
  s.add_runtime_dependency 'parser', '~> 2.3'
30
- s.add_runtime_dependency 'reverse_markdown', '~> 1.0', '>= 1.0.5'
31
- s.add_runtime_dependency 'rubocop', '~> 0.52'
30
+ s.add_runtime_dependency 'reverse_markdown', '>= 1.0.5', '< 3'
31
+ s.add_runtime_dependency 'rubocop', '>= 0.52'
32
32
  s.add_runtime_dependency 'thor', '~> 1.0'
33
33
  s.add_runtime_dependency 'tilt', '~> 2.0'
34
34
  s.add_runtime_dependency 'yard', '~> 0.9', '>= 0.9.24'
data/yardoc/2.2.2.tar.gz CHANGED
Binary file