solargraph 0.56.0 → 0.58.2

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 (191) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +183 -7
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.gitignore +6 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +92 -1
  14. data/README.md +8 -4
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +110 -109
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +193 -175
  20. data/lib/solargraph/api_map/source_to_yard.rb +97 -88
  21. data/lib/solargraph/api_map/store.rb +384 -266
  22. data/lib/solargraph/api_map.rb +945 -973
  23. data/lib/solargraph/bench.rb +1 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +228 -222
  25. data/lib/solargraph/complex_type/unique_type.rb +482 -475
  26. data/lib/solargraph/complex_type.rb +444 -423
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +17 -0
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemspec.rb +3 -2
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -60
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -100
  35. data/lib/solargraph/convention/struct_definition.rb +164 -101
  36. data/lib/solargraph/convention.rb +32 -2
  37. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  38. data/lib/solargraph/diagnostics/rubocop.rb +118 -113
  39. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -66
  40. data/lib/solargraph/diagnostics/type_check.rb +55 -55
  41. data/lib/solargraph/doc_map.rb +439 -405
  42. data/lib/solargraph/environ.rb +9 -2
  43. data/lib/solargraph/equality.rb +34 -33
  44. data/lib/solargraph/gem_pins.rb +98 -88
  45. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  46. data/lib/solargraph/language_server/host/dispatch.rb +130 -128
  47. data/lib/solargraph/language_server/host/message_worker.rb +112 -109
  48. data/lib/solargraph/language_server/host/sources.rb +99 -99
  49. data/lib/solargraph/language_server/host.rb +878 -871
  50. data/lib/solargraph/language_server/message/base.rb +2 -1
  51. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -114
  52. data/lib/solargraph/language_server/message/extended/document.rb +23 -23
  53. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -56
  54. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  55. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -26
  56. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -131
  57. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  58. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  59. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -24
  60. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  61. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  62. data/lib/solargraph/language_server/progress.rb +8 -0
  63. data/lib/solargraph/language_server/request.rb +4 -1
  64. data/lib/solargraph/library.rb +683 -666
  65. data/lib/solargraph/location.rb +82 -79
  66. data/lib/solargraph/logging.rb +37 -28
  67. data/lib/solargraph/page.rb +3 -0
  68. data/lib/solargraph/parser/comment_ripper.rb +69 -62
  69. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -227
  70. data/lib/solargraph/parser/node_processor/base.rb +92 -87
  71. data/lib/solargraph/parser/node_processor.rb +62 -46
  72. data/lib/solargraph/parser/parser_gem/class_methods.rb +149 -159
  73. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  74. data/lib/solargraph/parser/parser_gem/node_chainer.rb +166 -164
  75. data/lib/solargraph/parser/parser_gem/node_methods.rb +486 -497
  76. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -21
  77. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -59
  78. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +15 -15
  79. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -45
  80. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
  81. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +53 -53
  82. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -21
  83. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +40 -40
  84. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +29 -29
  85. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -53
  86. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
  87. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -41
  88. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -16
  89. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +38 -37
  90. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +52 -43
  91. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +291 -271
  92. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
  93. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -29
  94. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -66
  95. data/lib/solargraph/parser/region.rb +69 -66
  96. data/lib/solargraph/parser/snippet.rb +17 -15
  97. data/lib/solargraph/pin/base.rb +729 -651
  98. data/lib/solargraph/pin/base_variable.rb +126 -125
  99. data/lib/solargraph/pin/block.rb +104 -103
  100. data/lib/solargraph/pin/breakable.rb +9 -9
  101. data/lib/solargraph/pin/callable.rb +231 -218
  102. data/lib/solargraph/pin/closure.rb +72 -74
  103. data/lib/solargraph/pin/common.rb +79 -75
  104. data/lib/solargraph/pin/constant.rb +2 -0
  105. data/lib/solargraph/pin/conversions.rb +123 -123
  106. data/lib/solargraph/pin/delegated_method.rb +120 -120
  107. data/lib/solargraph/pin/documenting.rb +114 -114
  108. data/lib/solargraph/pin/instance_variable.rb +34 -34
  109. data/lib/solargraph/pin/keyword.rb +20 -20
  110. data/lib/solargraph/pin/local_variable.rb +75 -76
  111. data/lib/solargraph/pin/method.rb +672 -651
  112. data/lib/solargraph/pin/method_alias.rb +34 -31
  113. data/lib/solargraph/pin/namespace.rb +115 -115
  114. data/lib/solargraph/pin/parameter.rb +275 -261
  115. data/lib/solargraph/pin/proxy_type.rb +39 -35
  116. data/lib/solargraph/pin/reference/override.rb +47 -33
  117. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  118. data/lib/solargraph/pin/reference.rb +39 -22
  119. data/lib/solargraph/pin/search.rb +61 -56
  120. data/lib/solargraph/pin/signature.rb +61 -59
  121. data/lib/solargraph/pin/symbol.rb +53 -48
  122. data/lib/solargraph/pin/until.rb +18 -18
  123. data/lib/solargraph/pin/while.rb +18 -18
  124. data/lib/solargraph/pin.rb +44 -44
  125. data/lib/solargraph/pin_cache.rb +245 -185
  126. data/lib/solargraph/position.rb +132 -116
  127. data/lib/solargraph/range.rb +112 -107
  128. data/lib/solargraph/rbs_map/conversions.rb +823 -773
  129. data/lib/solargraph/rbs_map/core_fills.rb +18 -0
  130. data/lib/solargraph/rbs_map/core_map.rb +58 -51
  131. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -43
  132. data/lib/solargraph/rbs_map.rb +163 -150
  133. data/lib/solargraph/shell.rb +352 -268
  134. data/lib/solargraph/source/chain/call.rb +337 -333
  135. data/lib/solargraph/source/chain/constant.rb +26 -89
  136. data/lib/solargraph/source/chain/hash.rb +34 -34
  137. data/lib/solargraph/source/chain/if.rb +28 -28
  138. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  139. data/lib/solargraph/source/chain/link.rb +11 -2
  140. data/lib/solargraph/source/chain/literal.rb +48 -48
  141. data/lib/solargraph/source/chain/or.rb +23 -23
  142. data/lib/solargraph/source/chain.rb +291 -282
  143. data/lib/solargraph/source/change.rb +82 -82
  144. data/lib/solargraph/source/cursor.rb +166 -167
  145. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  146. data/lib/solargraph/source/source_chainer.rb +194 -194
  147. data/lib/solargraph/source/updater.rb +55 -55
  148. data/lib/solargraph/source.rb +498 -495
  149. data/lib/solargraph/source_map/clip.rb +226 -234
  150. data/lib/solargraph/source_map/data.rb +34 -30
  151. data/lib/solargraph/source_map/mapper.rb +259 -259
  152. data/lib/solargraph/source_map.rb +212 -200
  153. data/lib/solargraph/type_checker/checks.rb +124 -124
  154. data/lib/solargraph/type_checker/param_def.rb +37 -35
  155. data/lib/solargraph/type_checker/problem.rb +32 -32
  156. data/lib/solargraph/type_checker/rules.rb +84 -62
  157. data/lib/solargraph/type_checker.rb +814 -699
  158. data/lib/solargraph/version.rb +5 -5
  159. data/lib/solargraph/workspace/config.rb +255 -239
  160. data/lib/solargraph/workspace/require_paths.rb +97 -0
  161. data/lib/solargraph/workspace.rb +220 -249
  162. data/lib/solargraph/yard_map/helpers.rb +44 -16
  163. data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
  164. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -134
  165. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -30
  166. data/lib/solargraph/yard_map/mapper.rb +79 -79
  167. data/lib/solargraph/yard_map/to_method.rb +89 -88
  168. data/lib/solargraph/yardoc.rb +87 -49
  169. data/lib/solargraph.rb +105 -90
  170. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  171. data/rbs/fills/open3/0/open3.rbs +172 -0
  172. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  173. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  174. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  175. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  176. data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
  177. data/rbs/shims/ast/0/node.rbs +5 -0
  178. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  179. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  180. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  181. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  182. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  183. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  184. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  185. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  186. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  187. data/rbs_collection.yaml +4 -4
  188. data/solargraph.gemspec +26 -5
  189. metadata +187 -15
  190. data/lib/.rubocop.yml +0 -22
  191. data/lib/solargraph/parser/node_methods.rb +0 -97
@@ -1,113 +1,118 @@
1
- # frozen_string_literal: true
2
-
3
- require 'stringio'
4
-
5
- module Solargraph
6
- module Diagnostics
7
- # This reporter provides linting through RuboCop.
8
- #
9
- class Rubocop < Base
10
- include RubocopHelpers
11
-
12
- # Conversion of RuboCop severity names to LSP constants
13
- SEVERITIES = {
14
- 'info' => Severities::HINT,
15
- 'refactor' => Severities::HINT,
16
- 'convention' => Severities::INFORMATION,
17
- 'warning' => Severities::WARNING,
18
- 'error' => Severities::ERROR,
19
- 'fatal' => Severities::ERROR
20
- }
21
-
22
- # @param source [Solargraph::Source]
23
- # @param _api_map [Solargraph::ApiMap]
24
- # @return [Array<Hash>]
25
- def diagnose source, _api_map
26
- @source = source
27
- require_rubocop(rubocop_version)
28
- options, paths = generate_options(source.filename, source.code)
29
- store = RuboCop::ConfigStore.new
30
- runner = RuboCop::Runner.new(options, store)
31
- result = redirect_stdout{ runner.run(paths) }
32
-
33
- return [] if result.empty?
34
-
35
- make_array JSON.parse(result)
36
- rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
37
- raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
38
- rescue JSON::ParserError => e
39
- raise DiagnosticsError, "RuboCop returned invalid data: #{e.message}"
40
- end
41
-
42
- private
43
-
44
- # Extracts the rubocop version from _args_
45
- #
46
- # @return [String]
47
- def rubocop_version
48
- args.find { |a| a =~ /version=/ }.to_s.split('=').last
49
- end
50
-
51
- # @param resp [Hash{String => Array<Hash{String => Array<Hash{String => undefined}>}>}]
52
- # @return [Array<Hash>]
53
- def make_array resp
54
- diagnostics = []
55
- resp['files'].each do |file|
56
- file['offenses'].each do |off|
57
- diagnostics.push offense_to_diagnostic(off)
58
- end
59
- end
60
- diagnostics
61
- end
62
-
63
- # Convert a RuboCop offense to an LSP diagnostic
64
- #
65
- # @param off [Hash{String => unknown}] Offense received from Rubocop
66
- # @return [Hash{Symbol => Hash, String, Integer}] LSP diagnostic
67
- def offense_to_diagnostic off
68
- {
69
- range: offense_range(off).to_hash,
70
- # 1 = Error, 2 = Warning, 3 = Information, 4 = Hint
71
- severity: SEVERITIES[off['severity']],
72
- source: 'rubocop',
73
- code: off['cop_name'],
74
- message: off['message'].gsub(/^#{off['cop_name']}\:/, '')
75
- }
76
- end
77
-
78
- # @param off [Hash]
79
- # @return [Range]
80
- def offense_range off
81
- Range.new(offense_start_position(off), offense_ending_position(off))
82
- end
83
-
84
- # @param off [Hash{String => Hash{String => Integer}}]
85
- # @return [Position]
86
- def offense_start_position off
87
- Position.new(off['location']['start_line'] - 1, off['location']['start_column'] - 1)
88
- end
89
-
90
- # @param off [Hash{String => Hash{String => Integer}}]
91
- # @return [Position]
92
- def offense_ending_position off
93
- if off['location']['start_line'] != off['location']['last_line']
94
- Position.new(off['location']['start_line'], 0)
95
- else
96
- start_line = off['location']['start_line'] - 1
97
- # @type [Integer]
98
- last_column = off['location']['last_column']
99
- line = @source.code.lines[start_line]
100
- col_off = if line.nil? || line.empty?
101
- 1
102
- else
103
- 0
104
- end
105
-
106
- Position.new(
107
- start_line, last_column - col_off
108
- )
109
- end
110
- end
111
- end
112
- end
113
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+
5
+ module Solargraph
6
+ module Diagnostics
7
+ # This reporter provides linting through RuboCop.
8
+ #
9
+ class Rubocop < Base
10
+ include RubocopHelpers
11
+
12
+ # Conversion of RuboCop severity names to LSP constants
13
+ SEVERITIES = {
14
+ 'info' => Severities::HINT,
15
+ 'refactor' => Severities::HINT,
16
+ 'convention' => Severities::INFORMATION,
17
+ 'warning' => Severities::WARNING,
18
+ 'error' => Severities::ERROR,
19
+ 'fatal' => Severities::ERROR
20
+ }
21
+
22
+ # @param source [Solargraph::Source]
23
+ # @param _api_map [Solargraph::ApiMap]
24
+ # @return [Array<Hash>]
25
+ def diagnose source, _api_map
26
+ @source = source
27
+ require_rubocop(rubocop_version)
28
+ options, paths = generate_options(source.filename, source.code)
29
+ store = RuboCop::ConfigStore.new
30
+ runner = RuboCop::Runner.new(options, store)
31
+ # Ensure only one instance of RuboCop::Runner is running at
32
+ # a time - it uses 'chdir' to read config files with ERB,
33
+ # which can conflict with other chdirs.
34
+ result = Solargraph::CHDIR_MUTEX.synchronize do
35
+ redirect_stdout{ runner.run(paths) }
36
+ end
37
+
38
+ return [] if result.empty?
39
+
40
+ make_array JSON.parse(result)
41
+ rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
42
+ raise DiagnosticsError, "Error in RuboCop configuration: #{e.message}"
43
+ rescue JSON::ParserError => e
44
+ raise DiagnosticsError, "RuboCop returned invalid data: #{e.message}"
45
+ end
46
+
47
+ private
48
+
49
+ # Extracts the rubocop version from _args_
50
+ #
51
+ # @return [String]
52
+ def rubocop_version
53
+ args.find { |a| a =~ /version=/ }.to_s.split('=').last
54
+ end
55
+
56
+ # @param resp [Hash{String => Array<Hash{String => Array<Hash{String => undefined}>}>}]
57
+ # @return [Array<Hash>]
58
+ def make_array resp
59
+ diagnostics = []
60
+ resp['files'].each do |file|
61
+ file['offenses'].each do |off|
62
+ diagnostics.push offense_to_diagnostic(off)
63
+ end
64
+ end
65
+ diagnostics
66
+ end
67
+
68
+ # Convert a RuboCop offense to an LSP diagnostic
69
+ #
70
+ # @param off [Hash{String => unknown}] Offense received from Rubocop
71
+ # @return [Hash{Symbol => Hash, String, Integer}] LSP diagnostic
72
+ def offense_to_diagnostic off
73
+ {
74
+ range: offense_range(off).to_hash,
75
+ # 1 = Error, 2 = Warning, 3 = Information, 4 = Hint
76
+ severity: SEVERITIES[off['severity']],
77
+ source: 'rubocop',
78
+ code: off['cop_name'],
79
+ message: off['message'].gsub(/^#{off['cop_name']}\:/, '')
80
+ }
81
+ end
82
+
83
+ # @param off [Hash]
84
+ # @return [Range]
85
+ def offense_range off
86
+ Range.new(offense_start_position(off), offense_ending_position(off))
87
+ end
88
+
89
+ # @param off [Hash{String => Hash{String => Integer}}]
90
+ # @return [Position]
91
+ def offense_start_position off
92
+ Position.new(off['location']['start_line'] - 1, off['location']['start_column'] - 1)
93
+ end
94
+
95
+ # @param off [Hash{String => Hash{String => Integer}}]
96
+ # @return [Position]
97
+ def offense_ending_position off
98
+ if off['location']['start_line'] != off['location']['last_line']
99
+ Position.new(off['location']['start_line'], 0)
100
+ else
101
+ start_line = off['location']['start_line'] - 1
102
+ # @type [Integer]
103
+ last_column = off['location']['last_column']
104
+ line = @source.code.lines[start_line]
105
+ col_off = if line.nil? || line.empty?
106
+ 1
107
+ else
108
+ 0
109
+ end
110
+
111
+ Position.new(
112
+ start_line, last_column - col_off
113
+ )
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -1,66 +1,68 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Diagnostics
5
- # Utility methods for the RuboCop diagnostics reporter.
6
- #
7
- module RubocopHelpers
8
- module_function
9
-
10
- # Requires a specific version of rubocop, or the latest installed version
11
- # if _version_ is `nil`.
12
- #
13
- # @param version [String, nil]
14
- # @raise [InvalidRubocopVersionError] if _version_ is not installed
15
- # @return [void]
16
- def require_rubocop(version = nil)
17
- begin
18
- gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
19
- gem_lib_path = File.join(gem_path, 'lib')
20
- $LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
21
- # @todo Gem::MissingSpecVersionError is undocumented for some reason
22
- # @sg-ignore
23
- rescue Gem::MissingSpecVersionError => e
24
- raise InvalidRubocopVersionError,
25
- "could not find '#{e.name}' (#{e.requirement}) - "\
26
- "did find: [#{e.specs.map { |s| s.version.version }.join(', ')}]"
27
- end
28
- require 'rubocop'
29
- end
30
-
31
- # Generate command-line options for the specified filename and code.
32
- #
33
- # @param filename [String]
34
- # @param code [String]
35
- # @return [Array(Array<String>, Array<String>)]
36
- def generate_options filename, code
37
- args = ['-f', 'j', '--force-exclusion', filename]
38
- base_options = RuboCop::Options.new
39
- options, paths = base_options.parse(args)
40
- options[:stdin] = code
41
- [options, paths]
42
- end
43
-
44
- # RuboCop internally uses capitalized drive letters for Windows paths,
45
- # so we need to convert the paths provided to the command.
46
- #
47
- # @param path [String]
48
- # @return [String]
49
- def fix_drive_letter path
50
- return path unless path.match(/^[a-z]:/)
51
- path[0].upcase + path[1..-1]
52
- end
53
-
54
- # @todo This is a smelly way to redirect output, but the RuboCop specs do
55
- # the same thing.
56
- # @return [String]
57
- def redirect_stdout
58
- redir = StringIO.new
59
- $stdout = redir
60
- yield if block_given?
61
- $stdout = STDOUT
62
- redir.string
63
- end
64
- end
65
- end
66
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Diagnostics
5
+ # Utility methods for the RuboCop diagnostics reporter.
6
+ #
7
+ module RubocopHelpers
8
+ module_function
9
+
10
+ # Requires a specific version of rubocop, or the latest installed version
11
+ # if _version_ is `nil`.
12
+ #
13
+ # @param version [String, nil]
14
+ # @raise [InvalidRubocopVersionError] if _version_ is not installed
15
+ # @return [void]
16
+ def require_rubocop(version = nil)
17
+ begin
18
+ # @type [String]
19
+ gem_path = Gem::Specification.find_by_name('rubocop', version).full_gem_path
20
+ gem_lib_path = File.join(gem_path, 'lib')
21
+ $LOAD_PATH.unshift(gem_lib_path) unless $LOAD_PATH.include?(gem_lib_path)
22
+ rescue Gem::MissingSpecVersionError => e
23
+ # @type [Array<Gem::Specification>]
24
+ specs = e.specs
25
+ raise InvalidRubocopVersionError,
26
+ "could not find '#{e.name}' (#{e.requirement}) - "\
27
+ "did find: [#{specs.map { |s| s.version.version }.join(', ')}]"
28
+ end
29
+ require 'rubocop'
30
+ end
31
+
32
+ # Generate command-line options for the specified filename and code.
33
+ #
34
+ # @param filename [String]
35
+ # @param code [String]
36
+ # @return [Array(Array<String>, Array<String>)]
37
+ def generate_options filename, code
38
+ args = ['-f', 'j', '--force-exclusion', filename]
39
+ base_options = RuboCop::Options.new
40
+ options, paths = base_options.parse(args)
41
+ # @sg-ignore
42
+ options[:stdin] = code
43
+ [options, paths]
44
+ end
45
+
46
+ # RuboCop internally uses capitalized drive letters for Windows paths,
47
+ # so we need to convert the paths provided to the command.
48
+ #
49
+ # @param path [String]
50
+ # @return [String]
51
+ def fix_drive_letter path
52
+ return path unless path.match(/^[a-z]:/)
53
+ path[0].upcase + path[1..-1]
54
+ end
55
+
56
+ # @todo This is a smelly way to redirect output, but the RuboCop specs do
57
+ # the same thing.
58
+ # @return [String]
59
+ def redirect_stdout
60
+ redir = StringIO.new
61
+ $stdout = redir
62
+ yield if block_given?
63
+ $stdout = STDOUT
64
+ redir.string
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,55 +1,55 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Diagnostics
5
- # TypeCheck reports methods with undefined return types, untagged
6
- # parameters, and invalid param tags.
7
- #
8
- class TypeCheck < Base
9
- # @return [Array<Hash>]
10
- def diagnose source, api_map
11
- # return [] unless args.include?('always') || api_map.workspaced?(source.filename)
12
- severity = Diagnostics::Severities::ERROR
13
- level = (args.reverse.find { |a| ['normal', 'typed', 'strict', 'strong'].include?(a) }) || :normal
14
- checker = Solargraph::TypeChecker.new(source.filename, api_map: api_map, level: level.to_sym)
15
- checker.problems
16
- .sort { |a, b| a.location.range.start.line <=> b.location.range.start.line }
17
- .map do |problem|
18
- {
19
- range: extract_first_line(problem.location, source),
20
- severity: severity,
21
- source: 'Typecheck',
22
- message: problem.message
23
- }
24
- end
25
- end
26
-
27
- private
28
-
29
- # @param location [Location]
30
- # @param source [Source]
31
- # @return [Hash]
32
- def extract_first_line location, source
33
- return location.range.to_hash if location.range.start.line == location.range.ending.line
34
- {
35
- start: {
36
- line: location.range.start.line,
37
- character: location.range.start.character
38
- },
39
- end: {
40
- line: location.range.start.line,
41
- character: last_character(location.range.start, source)
42
- }
43
- }
44
- end
45
-
46
- # @param position [Solargraph::Position]
47
- # @param source [Solargraph::Source]
48
- # @return [Integer]
49
- def last_character position, source
50
- cursor = Position.to_offset(source.code, position)
51
- source.code.index(/[\r\n]/, cursor) || source.code.length
52
- end
53
- end
54
- end
55
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Diagnostics
5
+ # TypeCheck reports methods with undefined return types, untagged
6
+ # parameters, and invalid param tags.
7
+ #
8
+ class TypeCheck < Base
9
+ # @return [Array<Hash>]
10
+ def diagnose source, api_map
11
+ # return [] unless args.include?('always') || api_map.workspaced?(source.filename)
12
+ severity = Diagnostics::Severities::ERROR
13
+ level = (args.reverse.find { |a| ['normal', 'typed', 'strict', 'strong'].include?(a) }) || :normal
14
+ checker = Solargraph::TypeChecker.new(source.filename, api_map: api_map, level: level.to_sym)
15
+ checker.problems
16
+ .sort { |a, b| a.location.range.start.line <=> b.location.range.start.line }
17
+ .map do |problem|
18
+ {
19
+ range: extract_first_line(problem.location, source),
20
+ severity: severity,
21
+ source: 'Typecheck',
22
+ message: problem.message
23
+ }
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # @param location [Location]
30
+ # @param source [Source]
31
+ # @return [Hash]
32
+ def extract_first_line location, source
33
+ return location.range.to_hash if location.range.start.line == location.range.ending.line
34
+ {
35
+ start: {
36
+ line: location.range.start.line,
37
+ character: location.range.start.character
38
+ },
39
+ end: {
40
+ line: location.range.start.line,
41
+ character: last_character(location.range.start, source)
42
+ }
43
+ }
44
+ end
45
+
46
+ # @param position [Solargraph::Position]
47
+ # @param source [Solargraph::Source]
48
+ # @return [Integer]
49
+ def last_character position, source
50
+ cursor = Position.to_offset(source.code, position)
51
+ source.code.index(/[\r\n]/, cursor) || source.code.length
52
+ end
53
+ end
54
+ end
55
+ end