solargraph 0.58.0 → 0.59.0.dev.1

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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.gitattributes +2 -0
  4. data/.github/workflows/linting.yml +4 -5
  5. data/.github/workflows/plugins.yml +40 -36
  6. data/.github/workflows/rspec.yml +45 -13
  7. data/.github/workflows/typecheck.yml +2 -2
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +3 -0
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/bin/solargraph +8 -8
  13. data/lib/solargraph/api_map/cache.rb +110 -110
  14. data/lib/solargraph/api_map/constants.rb +289 -279
  15. data/lib/solargraph/api_map/index.rb +204 -193
  16. data/lib/solargraph/api_map/source_to_yard.rb +109 -97
  17. data/lib/solargraph/api_map/store.rb +387 -384
  18. data/lib/solargraph/api_map.rb +1000 -945
  19. data/lib/solargraph/complex_type/conformance.rb +176 -0
  20. data/lib/solargraph/complex_type/type_methods.rb +242 -228
  21. data/lib/solargraph/complex_type/unique_type.rb +632 -482
  22. data/lib/solargraph/complex_type.rb +549 -444
  23. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  24. data/lib/solargraph/convention/data_definition.rb +108 -105
  25. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  26. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  27. data/lib/solargraph/convention/struct_definition.rb +168 -164
  28. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  29. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  30. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  31. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  32. data/lib/solargraph/doc_map.rb +200 -439
  33. data/lib/solargraph/equality.rb +34 -34
  34. data/lib/solargraph/gem_pins.rb +97 -98
  35. data/lib/solargraph/language_server/host/dispatch.rb +131 -130
  36. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  37. data/lib/solargraph/language_server/host/sources.rb +100 -99
  38. data/lib/solargraph/language_server/host.rb +883 -878
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +109 -114
  40. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +42 -40
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +28 -26
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +60 -58
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +27 -25
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +25 -23
  49. data/lib/solargraph/library.rb +729 -683
  50. data/lib/solargraph/location.rb +87 -82
  51. data/lib/solargraph/logging.rb +57 -37
  52. data/lib/solargraph/parser/comment_ripper.rb +76 -69
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +483 -255
  54. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  55. data/lib/solargraph/parser/node_processor.rb +63 -62
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +167 -149
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +506 -486
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -46
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +41 -40
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +53 -52
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +296 -291
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  77. data/lib/solargraph/parser/region.rb +75 -69
  78. data/lib/solargraph/parser/snippet.rb +17 -17
  79. data/lib/solargraph/pin/base.rb +761 -729
  80. data/lib/solargraph/pin/base_variable.rb +418 -126
  81. data/lib/solargraph/pin/block.rb +126 -104
  82. data/lib/solargraph/pin/breakable.rb +13 -9
  83. data/lib/solargraph/pin/callable.rb +278 -231
  84. data/lib/solargraph/pin/closure.rb +68 -72
  85. data/lib/solargraph/pin/common.rb +94 -79
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +124 -123
  88. data/lib/solargraph/pin/delegated_method.rb +131 -120
  89. data/lib/solargraph/pin/documenting.rb +115 -114
  90. data/lib/solargraph/pin/instance_variable.rb +38 -34
  91. data/lib/solargraph/pin/keyword.rb +16 -20
  92. data/lib/solargraph/pin/local_variable.rb +31 -75
  93. data/lib/solargraph/pin/method.rb +720 -672
  94. data/lib/solargraph/pin/method_alias.rb +42 -34
  95. data/lib/solargraph/pin/namespace.rb +121 -115
  96. data/lib/solargraph/pin/parameter.rb +338 -275
  97. data/lib/solargraph/pin/proxy_type.rb +40 -39
  98. data/lib/solargraph/pin/reference/override.rb +47 -47
  99. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  100. data/lib/solargraph/pin/reference.rb +41 -39
  101. data/lib/solargraph/pin/search.rb +62 -61
  102. data/lib/solargraph/pin/signature.rb +69 -61
  103. data/lib/solargraph/pin/symbol.rb +53 -53
  104. data/lib/solargraph/pin/until.rb +18 -18
  105. data/lib/solargraph/pin/while.rb +18 -18
  106. data/lib/solargraph/pin.rb +46 -44
  107. data/lib/solargraph/pin_cache.rb +665 -245
  108. data/lib/solargraph/position.rb +118 -119
  109. data/lib/solargraph/range.rb +112 -112
  110. data/lib/solargraph/rbs_map/conversions.rb +846 -823
  111. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +72 -43
  113. data/lib/solargraph/rbs_map.rb +217 -163
  114. data/lib/solargraph/shell.rb +397 -352
  115. data/lib/solargraph/source/chain/call.rb +372 -337
  116. data/lib/solargraph/source/chain/constant.rb +28 -26
  117. data/lib/solargraph/source/chain/hash.rb +35 -34
  118. data/lib/solargraph/source/chain/if.rb +29 -28
  119. data/lib/solargraph/source/chain/instance_variable.rb +34 -13
  120. data/lib/solargraph/source/chain/literal.rb +53 -48
  121. data/lib/solargraph/source/chain/or.rb +31 -23
  122. data/lib/solargraph/source/chain.rb +294 -291
  123. data/lib/solargraph/source/change.rb +89 -82
  124. data/lib/solargraph/source/cursor.rb +172 -166
  125. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  126. data/lib/solargraph/source/source_chainer.rb +204 -194
  127. data/lib/solargraph/source/updater.rb +59 -55
  128. data/lib/solargraph/source.rb +524 -498
  129. data/lib/solargraph/source_map/clip.rb +237 -226
  130. data/lib/solargraph/source_map/data.rb +37 -34
  131. data/lib/solargraph/source_map/mapper.rb +282 -259
  132. data/lib/solargraph/source_map.rb +220 -212
  133. data/lib/solargraph/type_checker/problem.rb +34 -32
  134. data/lib/solargraph/type_checker/rules.rb +157 -84
  135. data/lib/solargraph/type_checker.rb +895 -814
  136. data/lib/solargraph/version.rb +5 -5
  137. data/lib/solargraph/workspace/config.rb +257 -255
  138. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  139. data/lib/solargraph/workspace/require_paths.rb +98 -97
  140. data/lib/solargraph/workspace.rb +362 -220
  141. data/lib/solargraph/yard_map/helpers.rb +45 -44
  142. data/lib/solargraph/yard_map/mapper/to_method.rb +134 -130
  143. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  144. data/lib/solargraph/yard_map/mapper.rb +84 -79
  145. data/lib/solargraph/yardoc.rb +97 -87
  146. data/lib/solargraph.rb +126 -105
  147. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  148. data/rbs/fills/tuple/tuple.rbs +28 -0
  149. data/rbs/shims/ast/0/node.rbs +5 -0
  150. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  151. data/rbs_collection.yaml +1 -1
  152. data/solargraph.gemspec +2 -1
  153. metadata +23 -17
  154. data/lib/solargraph/type_checker/checks.rb +0 -124
  155. data/lib/solargraph/type_checker/param_def.rb +0 -37
  156. data/lib/solargraph/yard_map/to_method.rb +0 -89
  157. data/sig/shims/ast/0/node.rbs +0 -5
  158. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  159. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  160. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  161. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  162. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  163. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  164. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  165. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  166. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,120 +1,131 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Pin
5
- # A DelegatedMethod is a more complicated version of a MethodAlias that
6
- # allows aliasing a method from a different closure (class/module etc).
7
- class DelegatedMethod < Pin::Method
8
- # A DelegatedMethod can be constructed with either a :resolved_method
9
- # pin, or a :receiver_chain. When a :receiver_chain is supplied, it
10
- # will be used to *dynamically* resolve a receiver type within the
11
- # given closure/scope, and the delegated method will then be resolved
12
- # to a method pin on that type.
13
- #
14
- # @param method [Method, nil] an already resolved method pin.
15
- # @param receiver [Source::Chain, nil] the source code used to resolve the receiver for this delegated method.
16
- # @param name [String]
17
- # @param receiver_method_name [String] the method name that will be called on the receiver (defaults to :name).
18
- def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)
19
- raise ArgumentError, 'either :method or :receiver is required' if (method && receiver) || (!method && !receiver)
20
- super(name: name, **splat)
21
-
22
- @receiver_chain = receiver
23
- @resolved_method = method
24
- @receiver_method_name = receiver_method_name
25
- end
26
-
27
- def inner_desc
28
- "#{name} => #{@receiver_chain}##{@receiver_method_name}"
29
- end
30
-
31
- def location
32
- return super if super
33
-
34
- @resolved_method&.send(:location)
35
- end
36
-
37
-
38
- def type_location
39
- return super if super
40
-
41
- @resolved_method&.send(:type_location)
42
- end
43
-
44
- %i[comments parameters return_type signatures].each do |method|
45
- define_method(method) do
46
- # @sg-ignore Need to set context correctly in define_method blocks
47
- @resolved_method ? @resolved_method.send(method) : super()
48
- end
49
- end
50
-
51
- %i[typify realize infer probe].each do |method|
52
- # @param api_map [ApiMap]
53
- define_method(method) do |api_map|
54
- resolve_method(api_map)
55
- # @sg-ignore Need to set context correctly in define_method blocks
56
- @resolved_method ? @resolved_method.send(method, api_map) : super(api_map)
57
- end
58
- end
59
-
60
- # @param api_map [ApiMap]
61
- def resolvable?(api_map)
62
- resolve_method(api_map)
63
- !!@resolved_method
64
- end
65
-
66
- private
67
-
68
- # Resolves the receiver chain and method name to a method pin, resetting any previously resolution.
69
- #
70
- # @param api_map [ApiMap]
71
- # @return [Pin::Method, nil]
72
- def resolve_method api_map
73
- return if @resolved_method
74
-
75
- resolver = @receiver_chain.define(api_map, self, []).first
76
-
77
- unless resolver
78
- Solargraph.logger.warn \
79
- "Delegated receiver for #{path} was resolved to nil from `#{print_chain(@receiver_chain)}'"
80
- return
81
- end
82
-
83
- receiver_type = resolver.return_type
84
-
85
- return if receiver_type.undefined?
86
-
87
- receiver_path, method_scope =
88
- if @receiver_chain.constant?
89
- # HACK: the `return_type` of a constant is Class<Whatever>, but looking up a method expects
90
- # the arguments `"Whatever"` and `scope: :class`.
91
- [receiver_type.to_s.sub(/^Class<(.+)>$/, '\1'), :class]
92
- else
93
- [receiver_type.to_s, :instance]
94
- end
95
-
96
- method_stack = api_map.get_method_stack(receiver_path, @receiver_method_name, scope: method_scope)
97
- @resolved_method = method_stack.first
98
- end
99
-
100
- # helper to print a source chain as code, probably not 100% correct.
101
- #
102
- # @param chain [Source::Chain]
103
- # @return [String]
104
- def print_chain(chain)
105
- out = +''
106
- chain.links.each_with_index do |link, index|
107
- if index > 0
108
- if Source::Chain::Constant
109
- out << '::' unless link.word.start_with?('::')
110
- else
111
- out << '.'
112
- end
113
- end
114
- out << link.word
115
- end
116
- out
117
- end
118
- end
119
- end
120
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ # A DelegatedMethod is a more complicated version of a MethodAlias that
6
+ # allows aliasing a method from a different closure (class/module etc).
7
+ class DelegatedMethod < Pin::Method
8
+ # A DelegatedMethod can be constructed with either a :resolved_method
9
+ # pin, or a :receiver_chain. When a :receiver_chain is supplied, it
10
+ # will be used to *dynamically* resolve a receiver type within the
11
+ # given closure/scope, and the delegated method will then be resolved
12
+ # to a method pin on that type.
13
+ #
14
+ # @param method [Method, nil] an already resolved method pin.
15
+ # @param receiver [Source::Chain, nil] the source code used to resolve the receiver for this delegated method.
16
+ # @param name [String, nil]
17
+ # @param receiver_method_name [String, nil] the method name that will be called on the receiver (defaults to :name).
18
+ def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)
19
+ raise ArgumentError, 'either :method or :receiver is required' if (method && receiver) || (!method && !receiver)
20
+ # @sg-ignore Need to add nil check here
21
+ super(name: name, **splat)
22
+
23
+ @receiver_chain = receiver
24
+ @resolved_method = method
25
+ @receiver_method_name = receiver_method_name
26
+ end
27
+
28
+ def inner_desc
29
+ "#{name} => #{@receiver_chain}##{@receiver_method_name}"
30
+ end
31
+
32
+ def location
33
+ return super if super
34
+
35
+ @resolved_method&.send(:location)
36
+ end
37
+
38
+
39
+ def type_location
40
+ return super if super
41
+
42
+ @resolved_method&.send(:type_location)
43
+ end
44
+
45
+ %i[comments parameters return_type signatures].each do |method|
46
+ define_method(method) do
47
+ # @sg-ignore Need to set context correctly in define_method blocks
48
+ @resolved_method ? @resolved_method.send(method) : super()
49
+ end
50
+ end
51
+
52
+ %i[typify realize infer probe].each do |method|
53
+ # @param api_map [ApiMap]
54
+ define_method(method) do |api_map|
55
+ resolve_method(api_map)
56
+ # @sg-ignore Need to set context correctly in define_method blocks
57
+ @resolved_method ? @resolved_method.send(method, api_map) : super(api_map)
58
+ end
59
+ end
60
+
61
+ # @param api_map [ApiMap]
62
+ def resolvable?(api_map)
63
+ resolve_method(api_map)
64
+ !!@resolved_method
65
+ end
66
+
67
+ private
68
+
69
+ # Resolves the receiver chain and method name to a method pin, resetting any previously resolution.
70
+ #
71
+ # @param api_map [ApiMap]
72
+ # @return [Pin::Method, nil]
73
+ # @sg-ignore Declared return type ::Solargraph::Pin::Method, nil
74
+ # does not match inferred type nil, false for
75
+ # Solargraph::Pin::DelegatedMethod#resolve_method
76
+ def resolve_method api_map
77
+ return if @resolved_method
78
+
79
+ # @sg-ignore Need to add nil check here
80
+ resolver = @receiver_chain.define(api_map, self, []).first
81
+
82
+ unless resolver
83
+ # @sg-ignore Need to add nil check here
84
+ Solargraph.logger.warn "Delegated receiver for #{path} was resolved to nil from `#{print_chain(@receiver_chain)}'"
85
+ return
86
+ end
87
+
88
+ # @sg-ignore Need to add nil check here
89
+ receiver_type = resolver.return_type
90
+
91
+ # @sg-ignore Need to add nil check here
92
+ return if receiver_type.undefined?
93
+
94
+ receiver_path, method_scope =
95
+ # @sg-ignore Need to add nil check here
96
+ if @receiver_chain.constant?
97
+ # HACK: the `return_type` of a constant is Class<Whatever>, but looking up a method expects
98
+ # the arguments `"Whatever"` and `scope: :class`.
99
+ # @sg-ignore Need to add nil check here
100
+ [receiver_type.to_s.sub(/^Class<(.+)>$/, '\1'), :class]
101
+ else
102
+ # @sg-ignore Need to add nil check here
103
+ [receiver_type.to_s, :instance]
104
+ end
105
+
106
+ # @sg-ignore Need to add nil check here
107
+ method_stack = api_map.get_method_stack(receiver_path, @receiver_method_name, scope: method_scope)
108
+ @resolved_method = method_stack.first
109
+ end
110
+
111
+ # helper to print a source chain as code, probably not 100% correct.
112
+ #
113
+ # @param chain [Source::Chain]
114
+ # @return [String]
115
+ def print_chain(chain)
116
+ out = +''
117
+ chain.links.each_with_index do |link, index|
118
+ if index > 0
119
+ if Source::Chain::Constant
120
+ out << '::' unless link.word.start_with?('::')
121
+ else
122
+ out << '.'
123
+ end
124
+ end
125
+ out << link.word
126
+ end
127
+ out
128
+ end
129
+ end
130
+ end
131
+ end
@@ -1,114 +1,115 @@
1
- # frozen_string_literal: true
2
-
3
- require 'kramdown'
4
- require 'kramdown-parser-gfm'
5
- require 'yard'
6
- require 'reverse_markdown'
7
- require 'solargraph/converters/dl'
8
- require 'solargraph/converters/dt'
9
- require 'solargraph/converters/dd'
10
- require 'solargraph/converters/misc'
11
-
12
- # @todo upstream this definition
13
-
14
- # @!parse
15
- # module ::Kramdown
16
- # class Document
17
- # # @return [String]
18
- # def to_html; end
19
- # end
20
- # end
21
- # module ReverseMarkdown
22
- # # @param input [String]
23
- # # @param options [Hash]
24
- # # @return [String]
25
- # def self.convert(input, options = {}); end
26
- # end
27
-
28
- module Solargraph
29
- module Pin
30
- # A module to add the Pin::Base#documentation method.
31
- #
32
- module Documenting
33
- # A documentation formatter that either performs Markdown conversion for
34
- # text, or applies backticks for code blocks.
35
- #
36
- class DocSection
37
- # @return [String]
38
- attr_reader :plaintext
39
-
40
- # @param code [Boolean] True if this section is a code block
41
- def initialize code
42
- @plaintext = String.new('')
43
- @code = code
44
- end
45
-
46
- def code?
47
- @code
48
- end
49
-
50
- # @param text [String]
51
- # @return [String]
52
- def concat text
53
- @plaintext.concat text
54
- end
55
-
56
- def to_s
57
- return to_code if code?
58
- to_markdown
59
- end
60
-
61
- private
62
-
63
- # @return [String]
64
- def to_code
65
- "\n```ruby\n#{Documenting.normalize_indentation(@plaintext)}#{@plaintext.end_with?("\n") ? '' : "\n"}```\n\n"
66
- end
67
-
68
- # @return [String]
69
- def to_markdown
70
- ReverseMarkdown.convert Kramdown::Document.new(@plaintext, input: 'GFM').to_html
71
- end
72
- end
73
-
74
- # @return [String]
75
- def documentation
76
- @documentation ||= begin
77
- # Using DocSections allows for code blocks that start with an empty
78
- # line and at least two spaces of indentation. This is a common
79
- # convention in Ruby core documentation, e.g., String#split.
80
- sections = [DocSection.new(false)]
81
- Documenting.normalize_indentation(Documenting.strip_html_comments(docstring.to_s.gsub("\t", ' '))).lines.each do |l|
82
- if l.start_with?(' ')
83
- # Code block
84
- sections.push DocSection.new(true) unless sections.last.code?
85
- elsif sections.last.code?
86
- # Regular documentation
87
- sections.push DocSection.new(false)
88
- end
89
- sections.last.concat l
90
- end
91
- sections.map(&:to_s).join.strip
92
- end
93
- end
94
-
95
- # @param text [String]
96
- # @return [String]
97
- def self.strip_html_comments text
98
- text.gsub(/<!--([\s\S]*?)-->/, '').strip
99
- end
100
-
101
- # @param text [String]
102
- # @return [String]
103
- def self.normalize_indentation text
104
- left = text.lines.map do |line|
105
- match = line.match(/^ +/)
106
- next 0 unless match
107
- match[0].length
108
- end.min
109
- return text if left.nil? || left.zero?
110
- text.lines.map { |line| line[left..] }.join
111
- end
112
- end
113
- end
114
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'kramdown'
4
+ require 'kramdown-parser-gfm'
5
+ require 'yard'
6
+ require 'reverse_markdown'
7
+ require 'solargraph/converters/dl'
8
+ require 'solargraph/converters/dt'
9
+ require 'solargraph/converters/dd'
10
+ require 'solargraph/converters/misc'
11
+
12
+ # @todo upstream this definition
13
+
14
+ # @!parse
15
+ # module ::Kramdown
16
+ # class Document
17
+ # # @return [String]
18
+ # def to_html; end
19
+ # end
20
+ # end
21
+ # module ReverseMarkdown
22
+ # # @param input [String]
23
+ # # @param options [Hash]
24
+ # # @return [String]
25
+ # def self.convert(input, options = {}); end
26
+ # end
27
+
28
+ module Solargraph
29
+ module Pin
30
+ # A module to add the Pin::Base#documentation method.
31
+ #
32
+ module Documenting
33
+ # A documentation formatter that either performs Markdown conversion for
34
+ # text, or applies backticks for code blocks.
35
+ #
36
+ class DocSection
37
+ # @return [String]
38
+ attr_reader :plaintext
39
+
40
+ # @param code [Boolean] True if this section is a code block
41
+ def initialize code
42
+ @plaintext = String.new('')
43
+ @code = code
44
+ end
45
+
46
+ def code?
47
+ @code
48
+ end
49
+
50
+ # @param text [String]
51
+ # @return [String]
52
+ def concat text
53
+ @plaintext.concat text
54
+ end
55
+
56
+ def to_s
57
+ return to_code if code?
58
+ to_markdown
59
+ end
60
+
61
+ private
62
+
63
+ # @return [String]
64
+ def to_code
65
+ "\n```ruby\n#{Documenting.normalize_indentation(@plaintext)}#{@plaintext.end_with?("\n") ? '' : "\n"}```\n\n"
66
+ end
67
+
68
+ # @return [String]
69
+ def to_markdown
70
+ ReverseMarkdown.convert Kramdown::Document.new(@plaintext, input: 'GFM').to_html
71
+ end
72
+ end
73
+
74
+ # @return [String]
75
+ def documentation
76
+ @documentation ||= begin
77
+ # Using DocSections allows for code blocks that start with an empty
78
+ # line and at least two spaces of indentation. This is a common
79
+ # convention in Ruby core documentation, e.g., String#split.
80
+ sections = [DocSection.new(false)]
81
+ Documenting.normalize_indentation(Documenting.strip_html_comments(docstring.to_s.gsub("\t", ' '))).lines.each do |l|
82
+ if l.start_with?(' ')
83
+ # Code block
84
+ sections.push DocSection.new(true) unless sections.last.code?
85
+ elsif sections.last.code?
86
+ # Regular documentation
87
+ sections.push DocSection.new(false)
88
+ end
89
+ sections.last.concat l
90
+ end
91
+ sections.map(&:to_s).join.strip
92
+ end
93
+ end
94
+
95
+ # @param text [String]
96
+ # @return [String]
97
+ def self.strip_html_comments text
98
+ text.gsub(/<!--([\s\S]*?)-->/, '').strip
99
+ end
100
+
101
+ # @param text [String]
102
+ # @return [String]
103
+ def self.normalize_indentation text
104
+ left = text.lines.map do |line|
105
+ match = line.match(/^ +/)
106
+ next 0 unless match
107
+ # @sg-ignore Need to add nil check here
108
+ match[0].length
109
+ end.min
110
+ return text if left.nil? || left.zero?
111
+ text.lines.map { |line| line[left..] }.join
112
+ end
113
+ end
114
+ end
115
+ end
@@ -1,34 +1,38 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Pin
5
- class InstanceVariable < BaseVariable
6
- # @return [ComplexType]
7
- def binder
8
- closure.binder
9
- end
10
-
11
- # @return [::Symbol]
12
- def scope
13
- closure.binder.scope
14
- end
15
-
16
- # @return [ComplexType]
17
- def context
18
- @context ||= begin
19
- result = super
20
- if scope == :class
21
- ComplexType.parse("::Class<#{result.rooted_namespace}>")
22
- else
23
- result.reduce_class_type
24
- end
25
- end
26
- end
27
-
28
- # @param other [InstanceVariable]
29
- def nearly? other
30
- super && binder == other.binder
31
- end
32
- end
33
- end
34
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class InstanceVariable < BaseVariable
6
+ # @sg-ignore Need to add nil check here
7
+ # @return [ComplexType, ComplexType::UniqueType]
8
+ def binder
9
+ # @sg-ignore Need to add nil check here
10
+ closure.binder
11
+ end
12
+
13
+ # @sg-ignore Need to add nil check here
14
+ # @return [::Symbol]
15
+ def scope
16
+ # @sg-ignore Need to add nil check here
17
+ closure.binder.scope
18
+ end
19
+
20
+ # @return [ComplexType]
21
+ def context
22
+ @context ||= begin
23
+ result = super
24
+ if scope == :class
25
+ ComplexType.parse("::Class<#{result.rooted_namespace}>")
26
+ else
27
+ result.reduce_class_type
28
+ end
29
+ end
30
+ end
31
+
32
+ # @param other [InstanceVariable]
33
+ def nearly? other
34
+ super && binder == other.binder
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,20 +1,16 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Pin
5
- class Keyword < Base
6
- def initialize(name, **kwargs)
7
- # @sg-ignore "Unrecognized keyword argument kwargs to Solargraph::Pin::Base#initialize"
8
- super(name: name, **kwargs)
9
- end
10
-
11
- def closure
12
- @closure ||= Pin::ROOT_PIN
13
- end
14
-
15
- def name
16
- @name
17
- end
18
- end
19
- end
20
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class Keyword < Base
6
+ def initialize(name, **kwargs)
7
+ # @sg-ignore "Unrecognized keyword argument kwargs to Solargraph::Pin::Base#initialize"
8
+ super(name: name, **kwargs)
9
+ end
10
+
11
+ def closure
12
+ @closure ||= Pin::ROOT_PIN
13
+ end
14
+ end
15
+ end
16
+ end