solargraph 0.38.6 → 0.39.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/SPONSORS.md +9 -0
  3. data/lib/solargraph.rb +1 -0
  4. data/lib/solargraph/api_map.rb +24 -13
  5. data/lib/solargraph/api_map/bundler_methods.rb +3 -0
  6. data/lib/solargraph/api_map/source_to_yard.rb +1 -6
  7. data/lib/solargraph/api_map/store.rb +19 -3
  8. data/lib/solargraph/complex_type/type_methods.rb +4 -4
  9. data/lib/solargraph/convention/base.rb +0 -5
  10. data/lib/solargraph/core_fills.rb +28 -2
  11. data/lib/solargraph/diagnostics/base.rb +1 -0
  12. data/lib/solargraph/diagnostics/type_check.rb +13 -13
  13. data/lib/solargraph/language_server/host.rb +11 -2
  14. data/lib/solargraph/language_server/host/sources.rb +20 -11
  15. data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -11
  16. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  17. data/lib/solargraph/library.rb +3 -3
  18. data/lib/solargraph/parser.rb +26 -0
  19. data/lib/solargraph/parser/comment_ripper.rb +52 -0
  20. data/lib/solargraph/parser/legacy.rb +12 -0
  21. data/lib/solargraph/parser/legacy/class_methods.rb +105 -0
  22. data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
  23. data/lib/solargraph/parser/legacy/node_chainer.rb +115 -0
  24. data/lib/solargraph/parser/legacy/node_methods.rb +289 -0
  25. data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
  26. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
  27. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
  28. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
  29. data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
  30. data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
  31. data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
  32. data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
  33. data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
  34. data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
  35. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
  36. data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
  37. data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
  38. data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
  39. data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
  40. data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
  41. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +232 -0
  42. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
  43. data/lib/solargraph/parser/node_methods.rb +43 -0
  44. data/lib/solargraph/parser/node_processor.rb +43 -0
  45. data/lib/solargraph/parser/node_processor/base.rb +77 -0
  46. data/lib/solargraph/{source_map → parser}/region.rb +11 -6
  47. data/lib/solargraph/parser/rubyvm.rb +40 -0
  48. data/lib/solargraph/parser/rubyvm/class_methods.rb +146 -0
  49. data/lib/solargraph/parser/rubyvm/node_chainer.rb +133 -0
  50. data/lib/solargraph/parser/rubyvm/node_methods.rb +279 -0
  51. data/lib/solargraph/parser/rubyvm/node_processors.rb +60 -0
  52. data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
  53. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +62 -0
  54. data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
  55. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
  56. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
  57. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
  58. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
  59. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
  60. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
  61. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
  62. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +34 -0
  63. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
  64. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
  65. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
  66. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +26 -0
  67. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
  68. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
  69. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
  70. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
  71. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +292 -0
  72. data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
  73. data/lib/solargraph/parser/snippet.rb +13 -0
  74. data/lib/solargraph/pin/attribute.rb +8 -0
  75. data/lib/solargraph/pin/base.rb +1 -1
  76. data/lib/solargraph/pin/base_method.rb +26 -4
  77. data/lib/solargraph/pin/base_variable.rb +7 -8
  78. data/lib/solargraph/pin/block.rb +1 -1
  79. data/lib/solargraph/pin/constant.rb +16 -0
  80. data/lib/solargraph/pin/conversions.rb +2 -2
  81. data/lib/solargraph/pin/method.rb +26 -14
  82. data/lib/solargraph/pin/parameter.rb +56 -2
  83. data/lib/solargraph/pin/reference.rb +1 -0
  84. data/lib/solargraph/pin/reference/override.rb +2 -0
  85. data/lib/solargraph/pin/reference/prepend.rb +10 -0
  86. data/lib/solargraph/pin/yard_pin/constant.rb +2 -4
  87. data/lib/solargraph/pin/yard_pin/method.rb +34 -18
  88. data/lib/solargraph/pin/yard_pin/namespace.rb +3 -11
  89. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +3 -12
  90. data/lib/solargraph/range.rb +8 -2
  91. data/lib/solargraph/shell.rb +17 -11
  92. data/lib/solargraph/source.rb +114 -135
  93. data/lib/solargraph/source/chain.rb +11 -3
  94. data/lib/solargraph/source/chain/call.rb +1 -2
  95. data/lib/solargraph/source/chain/constant.rb +44 -8
  96. data/lib/solargraph/source/chain/link.rb +1 -0
  97. data/lib/solargraph/source/cursor.rb +2 -28
  98. data/lib/solargraph/source/source_chainer.rb +12 -6
  99. data/lib/solargraph/source/updater.rb +2 -0
  100. data/lib/solargraph/source_map.rb +0 -2
  101. data/lib/solargraph/source_map/clip.rb +24 -17
  102. data/lib/solargraph/source_map/mapper.rb +34 -29
  103. data/lib/solargraph/type_checker.rb +367 -275
  104. data/lib/solargraph/type_checker/checks.rb +95 -0
  105. data/lib/solargraph/type_checker/param_def.rb +2 -17
  106. data/lib/solargraph/type_checker/rules.rb +53 -0
  107. data/lib/solargraph/version.rb +1 -1
  108. data/lib/solargraph/views/environment.erb +5 -3
  109. data/lib/solargraph/workspace.rb +17 -2
  110. data/lib/solargraph/workspace/config.rb +15 -7
  111. data/lib/solargraph/yard_map.rb +89 -49
  112. data/lib/solargraph/yard_map/core_docs.rb +1 -1
  113. data/solargraph.gemspec +2 -1
  114. metadata +88 -32
  115. data/OVERVIEW.md +0 -37
  116. data/lib/solargraph/source/flawed_builder.rb +0 -15
  117. data/lib/solargraph/source/node_chainer.rb +0 -111
  118. data/lib/solargraph/source/node_methods.rb +0 -240
  119. data/lib/solargraph/source_map/node_processor.rb +0 -85
  120. data/lib/solargraph/source_map/node_processor/alias_node.rb +0 -21
  121. data/lib/solargraph/source_map/node_processor/args_node.rb +0 -24
  122. data/lib/solargraph/source_map/node_processor/base.rb +0 -103
  123. data/lib/solargraph/source_map/node_processor/begin_node.rb +0 -13
  124. data/lib/solargraph/source_map/node_processor/block_node.rb +0 -21
  125. data/lib/solargraph/source_map/node_processor/casgn_node.rb +0 -21
  126. data/lib/solargraph/source_map/node_processor/cvasgn_node.rb +0 -21
  127. data/lib/solargraph/source_map/node_processor/def_node.rb +0 -62
  128. data/lib/solargraph/source_map/node_processor/defs_node.rb +0 -33
  129. data/lib/solargraph/source_map/node_processor/gvasgn_node.rb +0 -21
  130. data/lib/solargraph/source_map/node_processor/ivasgn_node.rb +0 -34
  131. data/lib/solargraph/source_map/node_processor/lvasgn_node.rb +0 -24
  132. data/lib/solargraph/source_map/node_processor/namespace_node.rb +0 -35
  133. data/lib/solargraph/source_map/node_processor/orasgn_node.rb +0 -14
  134. data/lib/solargraph/source_map/node_processor/resbody_node.rb +0 -32
  135. data/lib/solargraph/source_map/node_processor/sclass_node.rb +0 -19
  136. data/lib/solargraph/source_map/node_processor/send_node.rb +0 -217
  137. data/lib/solargraph/source_map/node_processor/sym_node.rb +0 -16
@@ -0,0 +1,95 @@
1
+ module Solargraph
2
+ class TypeChecker
3
+ module Checks
4
+ module_function
5
+
6
+ # Compare an expected type with an inferred type. Common usage is to
7
+ # check if the type declared in a method's @return tag matches the type
8
+ # inferred from static analysis of the code.
9
+ #
10
+ # @param api_map [ApiMap]
11
+ # @param expected [ComplexType]
12
+ # @param inferred [ComplexType]
13
+ # @return [Boolean]
14
+ def types_match? api_map, expected, inferred
15
+ return true if expected.to_s == inferred.to_s
16
+ matches = []
17
+ expected.each do |exp|
18
+ found = false
19
+ inferred.each do |inf|
20
+ # if api_map.super_and_sub?(fuzz(inf), fuzz(exp))
21
+ if either_way?(api_map, inf, exp)
22
+ found = true
23
+ matches.push inf
24
+ break
25
+ end
26
+ end
27
+ return false unless found
28
+ end
29
+ inferred.each do |inf|
30
+ next if matches.include?(inf)
31
+ found = false
32
+ expected.each do |exp|
33
+ # if api_map.super_and_sub?(fuzz(inf), fuzz(exp))
34
+ if either_way?(api_map, inf, exp)
35
+ found = true
36
+ break
37
+ end
38
+ end
39
+ return false unless found
40
+ end
41
+ true
42
+ end
43
+
44
+ # @param api_map [ApiMap]
45
+ # @param expected [ComplexType]
46
+ # @param inferred [ComplexType]
47
+ # @return [Boolean]
48
+ def any_types_match? api_map, expected, inferred
49
+ return duck_types_match?(api_map, expected, inferred) if expected.duck_type?
50
+ expected.each do |exp|
51
+ next if exp.duck_type?
52
+ inferred.each do |inf|
53
+ # return true if exp == inf || api_map.super_and_sub?(fuzz(inf), fuzz(exp))
54
+ return true if exp == inf || either_way?(api_map, inf, exp)
55
+ end
56
+ end
57
+ false
58
+ end
59
+
60
+ # @param api_map [ApiMap]
61
+ # @param expected [ComplexType]
62
+ # @param inferred [ComplexType]
63
+ # @return [Boolean]
64
+ def duck_types_match? api_map, expected, inferred
65
+ raise ArgumentError, "Expected type must be duck type" unless expected.duck_type?
66
+ expected.each do |exp|
67
+ next unless exp.duck_type?
68
+ quack = exp.to_s[1..-1]
69
+ return false if api_map.get_method_stack(inferred.namespace, quack, scope: inferred.scope).empty?
70
+ end
71
+ true
72
+ end
73
+
74
+ # @param type [ComplexType]
75
+ # @return [String]
76
+ def fuzz type
77
+ if type.parameters?
78
+ type.name
79
+ else
80
+ type.tag
81
+ end
82
+ end
83
+
84
+ # @param api_map [ApiMap]
85
+ # @param cls1 [ComplexType]
86
+ # @param cls2 [ComplexType]
87
+ # @return [Boolean]
88
+ def either_way?(api_map, cls1, cls2)
89
+ f1 = fuzz(cls1)
90
+ f2 = fuzz(cls2)
91
+ api_map.super_and_sub?(f1, f2) || api_map.super_and_sub?(f2, f1)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -24,27 +24,12 @@ module Solargraph
24
24
  # @return [Array<ParamDef>]
25
25
  def from pin
26
26
  result = []
27
- pin.parameters.each_with_index do |full, index|
28
- result.push ParamDef.new(pin.parameter_names[index], arg_type(full))
27
+ pin.parameters.each do |par|
28
+ result.push ParamDef.new(par.name, par.decl)
29
29
  end
30
30
  result
31
31
  end
32
-
33
- private
34
-
35
- # @param string [String]
36
- # @return [Symbol]
37
- def arg_type string
38
- return :kwrestarg if string.start_with?('**')
39
- return :restarg if string.start_with?('*')
40
- return :optarg if string.include?('=')
41
- return :kwoptarg if string.end_with?(':')
42
- return :kwarg if string =~ /^[a-z0-9_]*?:/
43
- return :blockarg if string.start_with?('&')
44
- :arg
45
- end
46
32
  end
47
-
48
33
  end
49
34
  end
50
35
  end
@@ -0,0 +1,53 @@
1
+ module Solargraph
2
+ class TypeChecker
3
+ class Rules
4
+ LEVELS = {
5
+ normal: 0,
6
+ typed: 1,
7
+ strict: 2,
8
+ strong: 3
9
+ }
10
+
11
+ # @return [Symbol]
12
+ attr_reader :level
13
+
14
+ # @return [Integer]
15
+ attr_reader :rank
16
+
17
+ # @param level [Symbol]
18
+ def initialize level
19
+ @rank = if LEVELS.key?(level)
20
+ LEVELS[level]
21
+ else
22
+ Solargraph.logger.warn "Unrecognized TypeChecker level #{level}, assuming normal"
23
+ 0
24
+ end
25
+ @level = LEVELS[LEVELS.values.index(@rank)]
26
+ end
27
+
28
+ def ignore_all_undefined?
29
+ rank < LEVELS[:strict]
30
+ end
31
+
32
+ def validate_consts?
33
+ rank >= LEVELS[:strict]
34
+ end
35
+
36
+ def validate_calls?
37
+ rank >= LEVELS[:strict]
38
+ end
39
+
40
+ def require_type_tags?
41
+ rank >= LEVELS[:strong]
42
+ end
43
+
44
+ def must_tag_or_infer?
45
+ rank > LEVELS[:typed]
46
+ end
47
+
48
+ def validate_tags?
49
+ rank > LEVELS[:normal]
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.38.6'
4
+ VERSION = '0.39.0'
5
5
  end
@@ -35,9 +35,11 @@
35
35
  <li>
36
36
  Core Cache Directory: <%= Solargraph::YardMap::CoreDocs.cache_dir %>
37
37
  </li>
38
- <li>
39
- Parser Target Version: <%= Solargraph::Source.parser.version %>
40
- </li>
38
+ <% unless Solargraph::Parser.rubyvm? %>
39
+ <li>
40
+ Parser Target Version: <%= Solargraph::Parser.version %>
41
+ </li>
42
+ <% end %>
41
43
  <li>
42
44
  Using Bundler: <%= ENV.key?('BUNDLE_BIN_PATH') %>
43
45
  </li>
@@ -27,6 +27,7 @@ module Solargraph
27
27
  load_sources
28
28
  @gemnames = []
29
29
  @require_paths = generate_require_paths
30
+ require_plugins
30
31
  end
31
32
 
32
33
  # @return [Solargraph::Workspace::Config]
@@ -145,7 +146,11 @@ module Solargraph
145
146
  size = config.calculated.length
146
147
  raise WorkspaceTooLargeError, "The workspace is too large to index (#{size} files, #{config.max_files} max)" if config.max_files > 0 and size > config.max_files
147
148
  config.calculated.each do |filename|
148
- source_hash[filename] = Solargraph::Source.load(filename)
149
+ begin
150
+ source_hash[filename] = Solargraph::Source.load(filename)
151
+ rescue Errno::ENOENT => e
152
+ Solargraph.logger.warn("Error loading #{filename}: [#{e.class}] #{e.message}")
153
+ end
149
154
  end
150
155
  end
151
156
  end
@@ -169,7 +174,7 @@ module Solargraph
169
174
  next unless Gem::Specification === spec
170
175
  @gemnames.push spec.name
171
176
  result.concat(spec.require_paths.map { |path| File.join(base, path) })
172
- rescue Exception => e
177
+ rescue RuntimeError, ScriptError, Errno::ENOENT => e
173
178
  # Don't die if we have an error during eval-ing a gem spec.
174
179
  # Concat the default lib directory instead.
175
180
  Solargraph.logger.warn "Error reading #{file}: [#{e.class}] #{e.message}"
@@ -190,5 +195,15 @@ module Solargraph
190
195
  return [File.join(directory, 'lib')] if config.require_paths.empty?
191
196
  config.require_paths.map{|p| File.join(directory, p)}
192
197
  end
198
+
199
+ def require_plugins
200
+ config.plugins.each do |plugin|
201
+ begin
202
+ require plugin
203
+ rescue LoadError
204
+ Solargraph.logger.warn "Failed to load plugin '#{plugin}'"
205
+ end
206
+ end
207
+ end
193
208
  end
194
209
  end
@@ -10,7 +10,7 @@ module Solargraph
10
10
  # The maximum number of files that can be added to a workspace.
11
11
  # The workspace's .solargraph.yml can override this value.
12
12
  MAX_FILES = 5000
13
-
13
+
14
14
  # @return [String]
15
15
  attr_reader :directory
16
16
 
@@ -85,6 +85,13 @@ module Solargraph
85
85
  raw_data['reporters']
86
86
  end
87
87
 
88
+ # An array of plugins to require.
89
+ #
90
+ # @return [Array<String>]
91
+ def plugins
92
+ raw_data['plugins']
93
+ end
94
+
88
95
  # The maximum number of files to parse from the workspace.
89
96
  #
90
97
  # @return [Integer]
@@ -93,7 +100,7 @@ module Solargraph
93
100
  end
94
101
 
95
102
  private
96
-
103
+
97
104
  # @return [String]
98
105
  def global_config_path
99
106
  ENV['SOLARGRAPH_GLOBAL_CONFIG'] ||
@@ -110,7 +117,7 @@ module Solargraph
110
117
  def config_data
111
118
  workspace_config = read_config(workspace_config_path)
112
119
  global_config = read_config(global_config_path)
113
-
120
+
114
121
  defaults = default_config
115
122
  defaults.merge({'exclude' => []}) unless workspace_config.nil?
116
123
 
@@ -118,17 +125,17 @@ module Solargraph
118
125
  .merge(global_config || {})
119
126
  .merge(workspace_config || {})
120
127
  end
121
-
128
+
122
129
  # Read a .solargraph yaml config
123
130
  #
124
131
  # @param directory [String]
125
- # @return [Hash]
132
+ # @return [Hash, nil]
126
133
  def read_config config_path = ''
127
134
  return nil if config_path.empty?
128
135
  return nil unless File.file?(config_path)
129
136
  YAML.safe_load(File.read(config_path))
130
137
  end
131
-
138
+
132
139
  # @return [Hash]
133
140
  def default_config
134
141
  {
@@ -138,7 +145,8 @@ module Solargraph
138
145
  'domains' => [],
139
146
  'reporters' => %w[rubocop require_not_found],
140
147
  'require_paths' => [],
141
- 'max_files' => MAX_FILES,
148
+ 'plugins' => [],
149
+ 'max_files' => MAX_FILES
142
150
  }
143
151
  end
144
152
 
@@ -16,17 +16,20 @@ module Solargraph
16
16
  autoload :RdocToYard, 'solargraph/yard_map/rdoc_to_yard'
17
17
 
18
18
  CoreDocs.require_minimum
19
- @@stdlib_yardoc = CoreDocs.yardoc_stdlib_file
20
- @@stdlib_paths = {}
21
- YARD::Registry.load! @@stdlib_yardoc
22
- YARD::Registry.all(:class, :module).each do |ns|
23
- next if ns.nil? || ns.file.nil?
24
- path = ns.file.sub(/^(ext|lib)\//, '').sub(/\.(rb|c)$/, '')
25
- next if path.start_with?('-')
26
- base = path.split('/').first
27
- @@stdlib_paths[base] ||= {}
28
- @@stdlib_paths[base][path] ||= []
29
- @@stdlib_paths[base][path].push ns
19
+
20
+ def stdlib_paths
21
+ @@stdlib_paths ||= begin
22
+ result = {}
23
+ YARD::Registry.load! CoreDocs.yardoc_stdlib_file
24
+ YARD::Registry.all.each do |co|
25
+ next if co.file.nil?
26
+ path = co.file.sub(/^(ext|lib)\//, '').sub(/\.(rb|c)$/, '')
27
+ base = path.split('/').first
28
+ result[base] ||= []
29
+ result[base].push co
30
+ end
31
+ result
32
+ end
30
33
  end
31
34
 
32
35
  # @return [Array<String>]
@@ -108,8 +111,39 @@ module Solargraph
108
111
  # @return [Array<Solargraph::Pin::Base>]
109
112
  def core_pins
110
113
  @@core_pins ||= begin
111
- load_yardoc CoreDocs.yardoc_file
112
- result = Mapper.new(YARD::Registry.all).map
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
113
147
  CoreFills::OVERRIDES.each do |ovr|
114
148
  pin = result.select { |p| p.path == ovr.name }.first
115
149
  next if pin.nil?
@@ -169,7 +203,7 @@ module Solargraph
169
203
  def process_requires
170
204
  pins.clear
171
205
  unresolved_requires.clear
172
- stdnames = {}
206
+ # stdnames = {}
173
207
  done = []
174
208
  from_std = []
175
209
  required.each do |r|
@@ -201,20 +235,33 @@ module Solargraph
201
235
  end
202
236
  rescue Gem::LoadError => e
203
237
  base = r.split('/').first
238
+ next if from_std.include?(base)
239
+ from_std.push base
204
240
  stdtmp = []
205
- if @@stdlib_paths[base]
206
- @@stdlib_paths[base].each_pair do |path, objects|
207
- next if from_std.include?(path)
208
- if path == r || path.start_with?("#{r}/")
209
- from_std.push path
210
- stdtmp.concat objects
211
- end
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
212
257
  end
213
258
  end
214
259
  if stdtmp.empty?
215
260
  unresolved_requires.push r
216
261
  else
217
- stdnames[r] = stdtmp
262
+ stdlib_fill base, stdtmp
263
+ result.concat stdtmp
264
+ # stdnames[r] = stdtmp
218
265
  end
219
266
  end
220
267
  result.delete_if(&:nil?)
@@ -223,35 +270,10 @@ module Solargraph
223
270
  pins.concat result
224
271
  end
225
272
  end
226
- pins.concat process_stdlib(stdnames)
273
+ # pins.concat process_stdlib(stdnames)
227
274
  pins.concat core_pins
228
275
  end
229
276
 
230
- # @param required_namespaces [Array<YARD::CodeObjects::Namespace>]
231
- # @return [Array<Solargraph::Pin::Base>]
232
- def process_stdlib required_namespaces
233
- pins = []
234
- unless required_namespaces.empty?
235
- yard = load_yardoc @@stdlib_yardoc
236
- done = []
237
- required_namespaces.each_pair do |r, objects|
238
- result = []
239
- objects.each do |ns|
240
- next if done.include?(ns.path)
241
- done.push ns.path
242
- all = [ns]
243
- all.concat recurse_namespace_object(ns)
244
- result.concat Mapper.new(all).map
245
- end
246
- result.delete_if(&:nil?)
247
- stdlib_fill r, result
248
- cache.set_path_pins(r, result) unless result.empty?
249
- pins.concat result
250
- end
251
- end
252
- pins
253
- end
254
-
255
277
  # @param spec [Gem::Specification]
256
278
  # @return [void]
257
279
  def add_gem_dependencies spec
@@ -287,12 +309,30 @@ module Solargraph
287
309
  size = Dir.glob(File.join(y, '**', '*'))
288
310
  .map{ |f| File.size(f) }
289
311
  .inject(:+)
312
+ if spec
313
+ ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
314
+ if File.file?(ser)
315
+ Solargraph.logger.info "Loading #{spec.name} #{spec.version} from cache"
316
+ file = File.open(ser, 'rb')
317
+ dump = file.read
318
+ file.close
319
+ return Marshal.load(dump)
320
+ end
321
+ end
290
322
  if !size.nil? && size > 20_000_000
291
323
  Solargraph::Logging.logger.warn "Yardoc at #{y} is too large to process (#{size} bytes)"
292
324
  return []
293
325
  end
294
326
  load_yardoc y
295
- Mapper.new(YARD::Registry.all, spec).map
327
+ Solargraph.logger.info "Loading #{spec.name} #{spec.version} from yardoc"
328
+ result = Mapper.new(YARD::Registry.all, spec).map
329
+ if spec
330
+ ser = File.join(CoreDocs.cache_dir, 'gems', "#{spec.name}-#{spec.version}.ser")
331
+ file = File.open(ser, 'wb')
332
+ file.write Marshal.dump(result)
333
+ file.close
334
+ end
335
+ result
296
336
  end
297
337
 
298
338
  # @param spec [Gem::Specification]