solargraph 0.32.1 → 0.32.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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +25 -0
  6. data/EXAMPLES.md +76 -0
  7. data/Gemfile +3 -0
  8. data/LANGUAGE_SERVER.md +51 -0
  9. data/LICENSE +21 -0
  10. data/OVERVIEW.md +37 -0
  11. data/README.md +106 -0
  12. data/Rakefile +14 -0
  13. data/SERVER.md +95 -0
  14. data/bin/solargraph +0 -0
  15. data/bin/solargraph-runtime +5 -5
  16. data/lib/solargraph.rb +54 -54
  17. data/lib/solargraph/api_map.rb +659 -659
  18. data/lib/solargraph/api_map/cache.rb +49 -49
  19. data/lib/solargraph/api_map/source_to_yard.rb +67 -67
  20. data/lib/solargraph/api_map/store.rb +201 -201
  21. data/lib/solargraph/bundle.rb +24 -24
  22. data/lib/solargraph/complex_type.rb +150 -150
  23. data/lib/solargraph/complex_type/type_methods.rb +124 -124
  24. data/lib/solargraph/complex_type/unique_type.rb +44 -44
  25. data/lib/solargraph/core_fills.rb +37 -37
  26. data/lib/solargraph/diagnostics.rb +52 -52
  27. data/lib/solargraph/diagnostics/base.rb +20 -20
  28. data/lib/solargraph/diagnostics/require_not_found.rb +28 -28
  29. data/lib/solargraph/diagnostics/rubocop.rb +98 -98
  30. data/lib/solargraph/diagnostics/rubocop_helpers.rb +46 -46
  31. data/lib/solargraph/diagnostics/type_not_defined.rb +108 -108
  32. data/lib/solargraph/diagnostics/update_errors.rb +38 -38
  33. data/lib/solargraph/language_server/completion_item_kinds.rb +33 -33
  34. data/lib/solargraph/language_server/error_codes.rb +18 -18
  35. data/lib/solargraph/language_server/host.rb +684 -681
  36. data/lib/solargraph/language_server/host/cataloger.rb +54 -79
  37. data/lib/solargraph/language_server/host/diagnoser.rb +80 -80
  38. data/lib/solargraph/language_server/host/dispatch.rb +112 -113
  39. data/lib/solargraph/language_server/host/sources.rb +138 -138
  40. data/lib/solargraph/language_server/message.rb +90 -90
  41. data/lib/solargraph/language_server/message/base.rb +83 -83
  42. data/lib/solargraph/language_server/message/completion_item/resolve.rb +40 -40
  43. data/lib/solargraph/language_server/message/exit_notification.rb +11 -11
  44. data/lib/solargraph/language_server/message/extended.rb +19 -19
  45. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +86 -86
  46. data/lib/solargraph/language_server/message/extended/document.rb +18 -18
  47. data/lib/solargraph/language_server/message/extended/document_gems.rb +30 -30
  48. data/lib/solargraph/language_server/message/extended/environment.rb +20 -20
  49. data/lib/solargraph/language_server/message/extended/search.rb +18 -18
  50. data/lib/solargraph/language_server/message/initialize.rb +141 -141
  51. data/lib/solargraph/language_server/message/initialized.rb +23 -23
  52. data/lib/solargraph/language_server/message/shutdown.rb +11 -11
  53. data/lib/solargraph/language_server/message/text_document.rb +25 -25
  54. data/lib/solargraph/language_server/message/text_document/completion.rb +51 -51
  55. data/lib/solargraph/language_server/message/text_document/definition.rb +18 -18
  56. data/lib/solargraph/language_server/message/text_document/did_change.rb +13 -13
  57. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +21 -21
  58. data/lib/solargraph/language_server/message/text_document/folding_range.rb +24 -24
  59. data/lib/solargraph/language_server/message/text_document/formatting.rb +50 -50
  60. data/lib/solargraph/language_server/message/text_document/hover.rb +31 -31
  61. data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +32 -32
  62. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +9 -9
  63. data/lib/solargraph/language_server/message/text_document/references.rb +14 -14
  64. data/lib/solargraph/language_server/message/text_document/rename.rb +17 -17
  65. data/lib/solargraph/language_server/message/text_document/signature_help.rb +19 -19
  66. data/lib/solargraph/language_server/message/workspace.rb +12 -12
  67. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -29
  68. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +29 -27
  69. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
  70. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +21 -21
  71. data/lib/solargraph/language_server/request.rb +22 -22
  72. data/lib/solargraph/language_server/symbol_kinds.rb +34 -34
  73. data/lib/solargraph/language_server/transport.rb +11 -11
  74. data/lib/solargraph/language_server/transport/adapter.rb +60 -60
  75. data/lib/solargraph/language_server/transport/data_reader.rb +66 -66
  76. data/lib/solargraph/language_server/uri_helpers.rb +25 -25
  77. data/lib/solargraph/library.rb +421 -419
  78. data/lib/solargraph/live_map.rb +126 -126
  79. data/lib/solargraph/live_map/cache.rb +38 -38
  80. data/lib/solargraph/location.rb +31 -31
  81. data/lib/solargraph/logging.rb +25 -25
  82. data/lib/solargraph/page.rb +68 -68
  83. data/lib/solargraph/pin.rb +50 -50
  84. data/lib/solargraph/pin/attribute.rb +41 -41
  85. data/lib/solargraph/pin/base.rb +280 -280
  86. data/lib/solargraph/pin/base_method.rb +76 -76
  87. data/lib/solargraph/pin/base_variable.rb +72 -72
  88. data/lib/solargraph/pin/block.rb +32 -32
  89. data/lib/solargraph/pin/block_parameter.rb +103 -103
  90. data/lib/solargraph/pin/class_variable.rb +9 -9
  91. data/lib/solargraph/pin/constant.rb +30 -30
  92. data/lib/solargraph/pin/conversions.rb +79 -79
  93. data/lib/solargraph/pin/documenting.rb +41 -41
  94. data/lib/solargraph/pin/duck_method.rb +14 -14
  95. data/lib/solargraph/pin/global_variable.rb +9 -9
  96. data/lib/solargraph/pin/instance_variable.rb +9 -9
  97. data/lib/solargraph/pin/keyword.rb +17 -17
  98. data/lib/solargraph/pin/local_variable.rb +23 -23
  99. data/lib/solargraph/pin/localized.rb +22 -22
  100. data/lib/solargraph/pin/method.rb +126 -126
  101. data/lib/solargraph/pin/method_alias.rb +30 -30
  102. data/lib/solargraph/pin/method_parameter.rb +40 -40
  103. data/lib/solargraph/pin/namespace.rb +54 -54
  104. data/lib/solargraph/pin/plugin/method.rb +25 -25
  105. data/lib/solargraph/pin/proxy_type.rb +35 -35
  106. data/lib/solargraph/pin/reference.rb +22 -22
  107. data/lib/solargraph/pin/reference/extend.rb +11 -11
  108. data/lib/solargraph/pin/reference/include.rb +11 -11
  109. data/lib/solargraph/pin/reference/require.rb +15 -15
  110. data/lib/solargraph/pin/reference/superclass.rb +11 -11
  111. data/lib/solargraph/pin/symbol.rb +44 -44
  112. data/lib/solargraph/pin/yard_pin.rb +10 -10
  113. data/lib/solargraph/pin/yard_pin/constant.rb +14 -14
  114. data/lib/solargraph/pin/yard_pin/method.rb +35 -35
  115. data/lib/solargraph/pin/yard_pin/namespace.rb +19 -19
  116. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +14 -14
  117. data/lib/solargraph/plugin.rb +8 -8
  118. data/lib/solargraph/plugin/base.rb +41 -41
  119. data/lib/solargraph/plugin/canceler.rb +11 -11
  120. data/lib/solargraph/plugin/process.rb +172 -172
  121. data/lib/solargraph/plugin/runtime.rb +134 -134
  122. data/lib/solargraph/position.rb +110 -110
  123. data/lib/solargraph/range.rb +83 -83
  124. data/lib/solargraph/server_methods.rb +14 -14
  125. data/lib/solargraph/shell.rb +102 -102
  126. data/lib/solargraph/source.rb +521 -521
  127. data/lib/solargraph/source/chain.rb +120 -120
  128. data/lib/solargraph/source/chain/call.rb +107 -107
  129. data/lib/solargraph/source/chain/class_variable.rb +11 -11
  130. data/lib/solargraph/source/chain/constant.rb +30 -30
  131. data/lib/solargraph/source/chain/global_variable.rb +11 -11
  132. data/lib/solargraph/source/chain/head.rb +33 -33
  133. data/lib/solargraph/source/chain/instance_variable.rb +11 -11
  134. data/lib/solargraph/source/chain/link.rb +33 -33
  135. data/lib/solargraph/source/chain/literal.rb +21 -21
  136. data/lib/solargraph/source/chain/variable.rb +11 -11
  137. data/lib/solargraph/source/change.rb +77 -77
  138. data/lib/solargraph/source/cursor.rb +157 -157
  139. data/lib/solargraph/source/node_chainer.rb +96 -96
  140. data/lib/solargraph/source/node_methods.rb +225 -225
  141. data/lib/solargraph/source/source_chainer.rb +183 -183
  142. data/lib/solargraph/source_map.rb +169 -169
  143. data/lib/solargraph/source_map/clip.rb +145 -145
  144. data/lib/solargraph/source_map/completion.rb +21 -21
  145. data/lib/solargraph/source_map/mapper.rb +149 -149
  146. data/lib/solargraph/source_map/node_processor.rb +78 -78
  147. data/lib/solargraph/source_map/node_processor/alias_node.rb +19 -19
  148. data/lib/solargraph/source_map/node_processor/args_node.rb +28 -28
  149. data/lib/solargraph/source_map/node_processor/base.rb +68 -68
  150. data/lib/solargraph/source_map/node_processor/begin_node.rb +11 -11
  151. data/lib/solargraph/source_map/node_processor/block_node.rb +14 -14
  152. data/lib/solargraph/source_map/node_processor/casgn_node.rb +14 -14
  153. data/lib/solargraph/source_map/node_processor/cvasgn_node.rb +14 -14
  154. data/lib/solargraph/source_map/node_processor/def_node.rb +54 -54
  155. data/lib/solargraph/source_map/node_processor/defs_node.rb +21 -21
  156. data/lib/solargraph/source_map/node_processor/gvasgn_node.rb +12 -12
  157. data/lib/solargraph/source_map/node_processor/ivasgn_node.rb +18 -18
  158. data/lib/solargraph/source_map/node_processor/lvasgn_node.rb +16 -16
  159. data/lib/solargraph/source_map/node_processor/namespace_node.rb +26 -26
  160. data/lib/solargraph/source_map/node_processor/orasgn_node.rb +12 -12
  161. data/lib/solargraph/source_map/node_processor/sclass_node.rb +11 -11
  162. data/lib/solargraph/source_map/node_processor/send_node.rb +162 -162
  163. data/lib/solargraph/source_map/node_processor/sym_node.rb +11 -11
  164. data/lib/solargraph/source_map/region.rb +58 -58
  165. data/lib/solargraph/version.rb +3 -3
  166. data/lib/solargraph/views/environment.erb +53 -53
  167. data/lib/solargraph/workspace.rb +183 -183
  168. data/lib/solargraph/workspace/config.rb +170 -170
  169. data/lib/solargraph/yard_map.rb +298 -298
  170. data/lib/solargraph/yard_map/cache.rb +17 -17
  171. data/lib/solargraph/yard_map/core_docs.rb +163 -163
  172. data/lib/solargraph/yard_map/core_gen.rb +76 -76
  173. data/lib/yard-coregen.rb +16 -16
  174. data/lib/yard-solargraph.rb +18 -18
  175. data/solargraph.gemspec +37 -0
  176. data/travis-bundler.rb +10 -0
  177. metadata +19 -6
@@ -1,11 +1,11 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class ClassVariable < Link
5
- def resolve api_map, name_pin, locals
6
- api_map.get_class_variable_pins(name_pin.context.namespace).select{|p| p.name == word}
7
- end
8
- end
9
- end
10
- end
11
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class ClassVariable < Link
5
+ def resolve api_map, name_pin, locals
6
+ api_map.get_class_variable_pins(name_pin.context.namespace).select{|p| p.name == word}
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,30 +1,30 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class Constant < Link
5
- def initialize word
6
- @word = word
7
- end
8
-
9
- def resolve api_map, name_pin, locals
10
- return [Pin::ROOT_PIN] if word.empty?
11
- if word.start_with?('::')
12
- context = ''
13
- bottom = word[2..-1]
14
- else
15
- context = name_pin.context.namespace
16
- bottom = word
17
- end
18
- if bottom.include?('::')
19
- ns = bottom.split('::')[0..-2].join('::')
20
- else
21
- ns = ''
22
- end
23
- result = api_map.get_constants(ns, context)
24
- last_name = bottom.split('::').last
25
- result.select{ |p| p.name == last_name }
26
- end
27
- end
28
- end
29
- end
30
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class Constant < Link
5
+ def initialize word
6
+ @word = word
7
+ end
8
+
9
+ def resolve api_map, name_pin, locals
10
+ return [Pin::ROOT_PIN] if word.empty?
11
+ if word.start_with?('::')
12
+ context = ''
13
+ bottom = word[2..-1]
14
+ else
15
+ context = name_pin.context.namespace
16
+ bottom = word
17
+ end
18
+ if bottom.include?('::')
19
+ ns = bottom.split('::')[0..-2].join('::')
20
+ else
21
+ ns = ''
22
+ end
23
+ result = api_map.get_constants(ns, context)
24
+ last_name = bottom.split('::').last
25
+ result.select{ |p| p.name == last_name }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,11 +1,11 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class GlobalVariable < Link
5
- def resolve api_map, name_pin, locals
6
- api_map.get_global_variable_pins.select{|p| p.name == word}
7
- end
8
- end
9
- end
10
- end
11
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class GlobalVariable < Link
5
+ def resolve api_map, name_pin, locals
6
+ api_map.get_global_variable_pins.select{|p| p.name == word}
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,33 +1,33 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- # Chain::Head is a link for ambiguous words, e.g.; `String` can refer to
5
- # either a class (`String`) or a function (`Kernel#String`).
6
- #
7
- # @note Chain::Head is only intended to handle `self` and `super`.
8
- class Head < Link
9
- def resolve api_map, name_pin, locals
10
- return [self_pin(name_pin.context)] if word == 'self'
11
- return super_pins(api_map, name_pin) if word == 'super'
12
- []
13
- end
14
-
15
- private
16
-
17
- # @param context [ComplexType]
18
- # @return [Pin::ProxyType]
19
- def self_pin(context)
20
- Pin::ProxyType.anonymous(context)
21
- end
22
-
23
- # @param api_map [ApiMap]
24
- # @param name_pin [Pin::Base]
25
- # @return [Array<Pin::Base>]
26
- def super_pins api_map, name_pin
27
- pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
28
- pins.reject{|p| p.path == name_pin.path}
29
- end
30
- end
31
- end
32
- end
33
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ # Chain::Head is a link for ambiguous words, e.g.; `String` can refer to
5
+ # either a class (`String`) or a function (`Kernel#String`).
6
+ #
7
+ # @note Chain::Head is only intended to handle `self` and `super`.
8
+ class Head < Link
9
+ def resolve api_map, name_pin, locals
10
+ return [self_pin(name_pin.context)] if word == 'self'
11
+ return super_pins(api_map, name_pin) if word == 'super'
12
+ []
13
+ end
14
+
15
+ private
16
+
17
+ # @param context [ComplexType]
18
+ # @return [Pin::ProxyType]
19
+ def self_pin(context)
20
+ Pin::ProxyType.anonymous(context)
21
+ end
22
+
23
+ # @param api_map [ApiMap]
24
+ # @param name_pin [Pin::Base]
25
+ # @return [Array<Pin::Base>]
26
+ def super_pins api_map, name_pin
27
+ pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
28
+ pins.reject{|p| p.path == name_pin.path}
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,11 +1,11 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class InstanceVariable < Link
5
- def resolve api_map, name_pin, locals
6
- api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select{|p| p.name == word}
7
- end
8
- end
9
- end
10
- end
11
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class InstanceVariable < Link
5
+ def resolve api_map, name_pin, locals
6
+ api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select{|p| p.name == word}
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,33 +1,33 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class Link
5
- attr_reader :word
6
-
7
- def initialize word = '<undefined>'
8
- @word = word
9
- end
10
-
11
- def undefined?
12
- word == '<undefined>'
13
- end
14
-
15
- def constant?
16
- is_a?(Chain::Constant)
17
- end
18
-
19
- # @param api_map [ApiMap]
20
- # @param name_pin [Pin::Base]
21
- # @param locals [Array<Pin::Base>]
22
- # @return [Array<Pin::Base>]
23
- def resolve api_map, name_pin, locals
24
- []
25
- end
26
-
27
- def == other
28
- self.class == other.class and word == other.word
29
- end
30
- end
31
- end
32
- end
33
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class Link
5
+ attr_reader :word
6
+
7
+ def initialize word = '<undefined>'
8
+ @word = word
9
+ end
10
+
11
+ def undefined?
12
+ word == '<undefined>'
13
+ end
14
+
15
+ def constant?
16
+ is_a?(Chain::Constant)
17
+ end
18
+
19
+ # @param api_map [ApiMap]
20
+ # @param name_pin [Pin::Base]
21
+ # @param locals [Array<Pin::Base>]
22
+ # @return [Array<Pin::Base>]
23
+ def resolve api_map, name_pin, locals
24
+ []
25
+ end
26
+
27
+ def == other
28
+ self.class == other.class and word == other.word
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,21 +1,21 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class Literal < Link
5
- def word
6
- @word ||= "<#{@type}>"
7
- end
8
-
9
- # @param type [String]
10
- def initialize type
11
- @type = type
12
- @complex_type = ComplexType.try_parse(type).first
13
- end
14
-
15
- def resolve api_map, name_pin, locals
16
- [Pin::ProxyType.anonymous(@complex_type)]
17
- end
18
- end
19
- end
20
- end
21
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class Literal < Link
5
+ def word
6
+ @word ||= "<#{@type}>"
7
+ end
8
+
9
+ # @param type [String]
10
+ def initialize type
11
+ @type = type
12
+ @complex_type = ComplexType.try_parse(type).first
13
+ end
14
+
15
+ def resolve api_map, name_pin, locals
16
+ [Pin::ProxyType.anonymous(@complex_type)]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,11 +1,11 @@
1
- module Solargraph
2
- class Source
3
- class Chain
4
- class Variable < Link
5
- def resolve api_map, name_pin, locals
6
- api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select{|p| p.name == word}
7
- end
8
- end
9
- end
10
- end
11
- end
1
+ module Solargraph
2
+ class Source
3
+ class Chain
4
+ class Variable < Link
5
+ def resolve api_map, name_pin, locals
6
+ api_map.get_instance_variable_pins(name_pin.context.namespace, name_pin.context.scope).select{|p| p.name == word}
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,77 +1,77 @@
1
- module Solargraph
2
- class Source
3
- # A change to be applied to text.
4
- #
5
- class Change
6
- include EncodingFixes
7
-
8
- # @return [Range]
9
- attr_reader :range
10
-
11
- # @return [String]
12
- attr_reader :new_text
13
-
14
- # @param range [Range] The starting and ending positions of the change.
15
- # If nil, the original text will be overwritten.
16
- # @param new_text [String] The text to be changed.
17
- def initialize range, new_text
18
- @range = range
19
- @new_text = new_text
20
- end
21
-
22
- # Write the change to the specified text.
23
- #
24
- # @param text [String] The text to be changed.
25
- # @param nullable [Boolean] If true, minor changes that could generate
26
- # syntax errors will be repaired.
27
- # @return [String] The updated text.
28
- def write text, nullable = false
29
- if nullable and !range.nil? and new_text.match(/[\.\[\{\(@\$:]$/)
30
- [':', '@'].each do |dupable|
31
- next unless new_text == dupable
32
- offset = Position.to_offset(text, range.start)
33
- if text[offset - 1] == dupable
34
- p = Position.from_offset(text, offset - 1)
35
- r = Change.new(Range.new(p, range.start), ' ')
36
- text = r.write(text)
37
- end
38
- break
39
- end
40
- commit text, "#{new_text[0..-2]} "
41
- elsif range.nil?
42
- new_text
43
- else
44
- commit text, new_text
45
- end
46
- end
47
-
48
- # Repair an update by replacing the new text with similarly formatted
49
- # whitespace.
50
- #
51
- # @param text [String] The text to be changed.
52
- # @return [String] The updated text.
53
- def repair text
54
- fixed = new_text.gsub(/[^\s]/, ' ')
55
- if range.nil?
56
- fixed
57
- else
58
- result = commit text, fixed
59
- off = Position.to_offset(text, range.start)
60
- match = result[0, off].match(/[\.:]+\z/)
61
- if match
62
- result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..-1]
63
- end
64
- result
65
- end
66
- end
67
-
68
- private
69
-
70
- def commit text, insert
71
- start_offset = Position.to_offset(text, range.start)
72
- end_offset = Position.to_offset(text, range.ending)
73
- (start_offset == 0 ? '' : text[0..start_offset-1].to_s) + normalize(insert) + text[end_offset..-1].to_s
74
- end
75
- end
76
- end
77
- end
1
+ module Solargraph
2
+ class Source
3
+ # A change to be applied to text.
4
+ #
5
+ class Change
6
+ include EncodingFixes
7
+
8
+ # @return [Range]
9
+ attr_reader :range
10
+
11
+ # @return [String]
12
+ attr_reader :new_text
13
+
14
+ # @param range [Range] The starting and ending positions of the change.
15
+ # If nil, the original text will be overwritten.
16
+ # @param new_text [String] The text to be changed.
17
+ def initialize range, new_text
18
+ @range = range
19
+ @new_text = new_text
20
+ end
21
+
22
+ # Write the change to the specified text.
23
+ #
24
+ # @param text [String] The text to be changed.
25
+ # @param nullable [Boolean] If true, minor changes that could generate
26
+ # syntax errors will be repaired.
27
+ # @return [String] The updated text.
28
+ def write text, nullable = false
29
+ if nullable and !range.nil? and new_text.match(/[\.\[\{\(@\$:]$/)
30
+ [':', '@'].each do |dupable|
31
+ next unless new_text == dupable
32
+ offset = Position.to_offset(text, range.start)
33
+ if text[offset - 1] == dupable
34
+ p = Position.from_offset(text, offset - 1)
35
+ r = Change.new(Range.new(p, range.start), ' ')
36
+ text = r.write(text)
37
+ end
38
+ break
39
+ end
40
+ commit text, "#{new_text[0..-2]} "
41
+ elsif range.nil?
42
+ new_text
43
+ else
44
+ commit text, new_text
45
+ end
46
+ end
47
+
48
+ # Repair an update by replacing the new text with similarly formatted
49
+ # whitespace.
50
+ #
51
+ # @param text [String] The text to be changed.
52
+ # @return [String] The updated text.
53
+ def repair text
54
+ fixed = new_text.gsub(/[^\s]/, ' ')
55
+ if range.nil?
56
+ fixed
57
+ else
58
+ result = commit text, fixed
59
+ off = Position.to_offset(text, range.start)
60
+ match = result[0, off].match(/[\.:]+\z/)
61
+ if match
62
+ result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..-1]
63
+ end
64
+ result
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def commit text, insert
71
+ start_offset = Position.to_offset(text, range.start)
72
+ end_offset = Position.to_offset(text, range.ending)
73
+ (start_offset == 0 ? '' : text[0..start_offset-1].to_s) + normalize(insert) + text[end_offset..-1].to_s
74
+ end
75
+ end
76
+ end
77
+ end