solargraph 0.39.7
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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +28 -0
- data/.yardopts +2 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +104 -0
- data/Rakefile +14 -0
- data/SPONSORS.md +9 -0
- data/bin/solargraph +5 -0
- data/lib/.rubocop.yml +21 -0
- data/lib/solargraph.rb +66 -0
- data/lib/solargraph/api_map.rb +745 -0
- data/lib/solargraph/api_map/bundler_methods.rb +27 -0
- data/lib/solargraph/api_map/cache.rb +66 -0
- data/lib/solargraph/api_map/source_to_yard.rb +81 -0
- data/lib/solargraph/api_map/store.rb +267 -0
- data/lib/solargraph/bundle.rb +26 -0
- data/lib/solargraph/complex_type.rb +213 -0
- data/lib/solargraph/complex_type/type_methods.rb +127 -0
- data/lib/solargraph/complex_type/unique_type.rb +75 -0
- data/lib/solargraph/convention.rb +38 -0
- data/lib/solargraph/convention/base.rb +25 -0
- data/lib/solargraph/convention/gemfile.rb +18 -0
- data/lib/solargraph/convention/gemspec.rb +25 -0
- data/lib/solargraph/convention/rspec.rb +24 -0
- data/lib/solargraph/converters/dd.rb +12 -0
- data/lib/solargraph/converters/dl.rb +12 -0
- data/lib/solargraph/converters/dt.rb +12 -0
- data/lib/solargraph/converters/misc.rb +1 -0
- data/lib/solargraph/core_fills.rb +159 -0
- data/lib/solargraph/diagnostics.rb +55 -0
- data/lib/solargraph/diagnostics/base.rb +29 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +37 -0
- data/lib/solargraph/diagnostics/rubocop.rb +90 -0
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +64 -0
- data/lib/solargraph/diagnostics/severities.rb +15 -0
- data/lib/solargraph/diagnostics/type_check.rb +54 -0
- data/lib/solargraph/diagnostics/update_errors.rb +41 -0
- data/lib/solargraph/documentor.rb +76 -0
- data/lib/solargraph/environ.rb +40 -0
- data/lib/solargraph/language_server.rb +19 -0
- data/lib/solargraph/language_server/completion_item_kinds.rb +35 -0
- data/lib/solargraph/language_server/error_codes.rb +20 -0
- data/lib/solargraph/language_server/host.rb +741 -0
- data/lib/solargraph/language_server/host/cataloger.rb +56 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +81 -0
- data/lib/solargraph/language_server/host/dispatch.rb +112 -0
- data/lib/solargraph/language_server/host/sources.rb +156 -0
- data/lib/solargraph/language_server/message.rb +92 -0
- data/lib/solargraph/language_server/message/base.rb +85 -0
- data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
- data/lib/solargraph/language_server/message/client.rb +11 -0
- data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
- data/lib/solargraph/language_server/message/completion_item.rb +11 -0
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +57 -0
- data/lib/solargraph/language_server/message/exit_notification.rb +13 -0
- data/lib/solargraph/language_server/message/extended.rb +21 -0
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +95 -0
- data/lib/solargraph/language_server/message/extended/document.rb +20 -0
- data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -0
- data/lib/solargraph/language_server/message/extended/download_core.rb +23 -0
- data/lib/solargraph/language_server/message/extended/environment.rb +25 -0
- data/lib/solargraph/language_server/message/extended/search.rb +20 -0
- data/lib/solargraph/language_server/message/initialize.rb +153 -0
- data/lib/solargraph/language_server/message/initialized.rb +26 -0
- data/lib/solargraph/language_server/message/method_not_found.rb +16 -0
- data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -0
- data/lib/solargraph/language_server/message/shutdown.rb +13 -0
- data/lib/solargraph/language_server/message/text_document.rb +28 -0
- data/lib/solargraph/language_server/message/text_document/base.rb +19 -0
- data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -0
- data/lib/solargraph/language_server/message/text_document/completion.rb +57 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
- data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +23 -0
- data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +78 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +44 -0
- data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -0
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -0
- data/lib/solargraph/language_server/message/text_document/references.rb +16 -0
- data/lib/solargraph/language_server/message/text_document/rename.rb +19 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +29 -0
- data/lib/solargraph/language_server/message/workspace.rb +14 -0
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +33 -0
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -0
- data/lib/solargraph/language_server/message_types.rb +14 -0
- data/lib/solargraph/language_server/request.rb +24 -0
- data/lib/solargraph/language_server/symbol_kinds.rb +36 -0
- data/lib/solargraph/language_server/transport.rb +13 -0
- data/lib/solargraph/language_server/transport/adapter.rb +56 -0
- data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
- data/lib/solargraph/language_server/uri_helpers.rb +49 -0
- data/lib/solargraph/library.rb +414 -0
- data/lib/solargraph/location.rb +37 -0
- data/lib/solargraph/logging.rb +27 -0
- data/lib/solargraph/page.rb +83 -0
- data/lib/solargraph/parser.rb +26 -0
- data/lib/solargraph/parser/comment_ripper.rb +52 -0
- data/lib/solargraph/parser/legacy.rb +12 -0
- data/lib/solargraph/parser/legacy/class_methods.rb +109 -0
- data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
- data/lib/solargraph/parser/legacy/node_chainer.rb +118 -0
- data/lib/solargraph/parser/legacy/node_methods.rb +300 -0
- data/lib/solargraph/parser/legacy/node_processors.rb +54 -0
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +23 -0
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +35 -0
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +15 -0
- data/lib/solargraph/parser/legacy/node_processors/block_node.rb +22 -0
- data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +25 -0
- data/lib/solargraph/parser/legacy/node_processors/cvasgn_node.rb +23 -0
- data/lib/solargraph/parser/legacy/node_processors/def_node.rb +63 -0
- data/lib/solargraph/parser/legacy/node_processors/defs_node.rb +36 -0
- data/lib/solargraph/parser/legacy/node_processors/gvasgn_node.rb +23 -0
- data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +38 -0
- data/lib/solargraph/parser/legacy/node_processors/lvasgn_node.rb +28 -0
- data/lib/solargraph/parser/legacy/node_processors/namespace_node.rb +39 -0
- data/lib/solargraph/parser/legacy/node_processors/orasgn_node.rb +16 -0
- data/lib/solargraph/parser/legacy/node_processors/resbody_node.rb +36 -0
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +21 -0
- data/lib/solargraph/parser/legacy/node_processors/send_node.rb +234 -0
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +18 -0
- data/lib/solargraph/parser/node_methods.rb +43 -0
- data/lib/solargraph/parser/node_processor.rb +43 -0
- data/lib/solargraph/parser/node_processor/base.rb +77 -0
- data/lib/solargraph/parser/region.rb +66 -0
- data/lib/solargraph/parser/rubyvm.rb +40 -0
- data/lib/solargraph/parser/rubyvm/class_methods.rb +150 -0
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +135 -0
- data/lib/solargraph/parser/rubyvm/node_methods.rb +284 -0
- data/lib/solargraph/parser/rubyvm/node_processors.rb +61 -0
- data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +62 -0
- data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +22 -0
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +22 -0
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +64 -0
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +57 -0
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +38 -0
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +39 -0
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +20 -0
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +27 -0
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +39 -0
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +31 -0
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +45 -0
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +21 -0
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +255 -0
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
- data/lib/solargraph/parser/snippet.rb +13 -0
- data/lib/solargraph/pin.rb +39 -0
- data/lib/solargraph/pin/attribute.rb +49 -0
- data/lib/solargraph/pin/base.rb +296 -0
- data/lib/solargraph/pin/base_method.rb +141 -0
- data/lib/solargraph/pin/base_variable.rb +84 -0
- data/lib/solargraph/pin/block.rb +48 -0
- data/lib/solargraph/pin/class_variable.rb +8 -0
- data/lib/solargraph/pin/closure.rb +37 -0
- data/lib/solargraph/pin/common.rb +70 -0
- data/lib/solargraph/pin/constant.rb +43 -0
- data/lib/solargraph/pin/conversions.rb +97 -0
- data/lib/solargraph/pin/documenting.rb +110 -0
- data/lib/solargraph/pin/duck_method.rb +16 -0
- data/lib/solargraph/pin/global_variable.rb +8 -0
- data/lib/solargraph/pin/instance_variable.rb +30 -0
- data/lib/solargraph/pin/keyword.rb +15 -0
- data/lib/solargraph/pin/keyword_param.rb +8 -0
- data/lib/solargraph/pin/local_variable.rb +21 -0
- data/lib/solargraph/pin/localized.rb +43 -0
- data/lib/solargraph/pin/method.rb +111 -0
- data/lib/solargraph/pin/method_alias.rb +31 -0
- data/lib/solargraph/pin/namespace.rb +85 -0
- data/lib/solargraph/pin/parameter.rb +206 -0
- data/lib/solargraph/pin/proxy_type.rb +29 -0
- data/lib/solargraph/pin/reference.rb +14 -0
- data/lib/solargraph/pin/reference/extend.rb +10 -0
- data/lib/solargraph/pin/reference/include.rb +10 -0
- data/lib/solargraph/pin/reference/override.rb +29 -0
- data/lib/solargraph/pin/reference/prepend.rb +10 -0
- data/lib/solargraph/pin/reference/require.rb +14 -0
- data/lib/solargraph/pin/reference/superclass.rb +10 -0
- data/lib/solargraph/pin/singleton.rb +11 -0
- data/lib/solargraph/pin/symbol.rb +47 -0
- data/lib/solargraph/pin/yard_pin.rb +12 -0
- data/lib/solargraph/pin/yard_pin/constant.rb +25 -0
- data/lib/solargraph/pin/yard_pin/method.rb +65 -0
- data/lib/solargraph/pin/yard_pin/namespace.rb +27 -0
- data/lib/solargraph/pin/yard_pin/yard_mixin.rb +26 -0
- data/lib/solargraph/position.rb +112 -0
- data/lib/solargraph/range.rb +95 -0
- data/lib/solargraph/server_methods.rb +16 -0
- data/lib/solargraph/shell.rb +221 -0
- data/lib/solargraph/source.rb +533 -0
- data/lib/solargraph/source/chain.rb +172 -0
- data/lib/solargraph/source/chain/block_variable.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +203 -0
- data/lib/solargraph/source/chain/class_variable.rb +13 -0
- data/lib/solargraph/source/chain/constant.rb +75 -0
- data/lib/solargraph/source/chain/global_variable.rb +13 -0
- data/lib/solargraph/source/chain/head.rb +35 -0
- data/lib/solargraph/source/chain/instance_variable.rb +13 -0
- data/lib/solargraph/source/chain/link.rb +67 -0
- data/lib/solargraph/source/chain/literal.rb +23 -0
- data/lib/solargraph/source/chain/or.rb +23 -0
- data/lib/solargraph/source/chain/variable.rb +13 -0
- data/lib/solargraph/source/chain/z_super.rb +184 -0
- data/lib/solargraph/source/change.rb +79 -0
- data/lib/solargraph/source/cursor.rb +164 -0
- data/lib/solargraph/source/encoding_fixes.rb +23 -0
- data/lib/solargraph/source/source_chainer.rb +189 -0
- data/lib/solargraph/source/updater.rb +54 -0
- data/lib/solargraph/source_map.rb +170 -0
- data/lib/solargraph/source_map/clip.rb +190 -0
- data/lib/solargraph/source_map/completion.rb +23 -0
- data/lib/solargraph/source_map/mapper.rb +199 -0
- data/lib/solargraph/stdlib_fills.rb +32 -0
- data/lib/solargraph/type_checker.rb +498 -0
- data/lib/solargraph/type_checker/checks.rb +95 -0
- data/lib/solargraph/type_checker/param_def.rb +35 -0
- data/lib/solargraph/type_checker/problem.rb +32 -0
- data/lib/solargraph/type_checker/rules.rb +53 -0
- data/lib/solargraph/version.rb +5 -0
- data/lib/solargraph/views/_method.erb +62 -0
- data/lib/solargraph/views/_name_type_tag.erb +10 -0
- data/lib/solargraph/views/_namespace.erb +24 -0
- data/lib/solargraph/views/document.erb +23 -0
- data/lib/solargraph/views/environment.erb +58 -0
- data/lib/solargraph/views/layout.erb +44 -0
- data/lib/solargraph/views/search.erb +11 -0
- data/lib/solargraph/workspace.rb +209 -0
- data/lib/solargraph/workspace/config.rb +215 -0
- data/lib/solargraph/yard_map.rb +420 -0
- data/lib/solargraph/yard_map/cache.rb +19 -0
- data/lib/solargraph/yard_map/core_docs.rb +170 -0
- data/lib/solargraph/yard_map/core_gen.rb +76 -0
- data/lib/solargraph/yard_map/mapper.rb +71 -0
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +136 -0
- data/lib/yard-solargraph.rb +30 -0
- data/solargraph.gemspec +41 -0
- data/travis-bundler.rb +11 -0
- data/yardoc/2.2.2.tar.gz +0 -0
- metadata +575 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Source
|
|
5
|
+
# Information about a position in a source, including the word located
|
|
6
|
+
# there.
|
|
7
|
+
#
|
|
8
|
+
class Cursor
|
|
9
|
+
# @return [Position]
|
|
10
|
+
attr_reader :position
|
|
11
|
+
|
|
12
|
+
# @return [Source]
|
|
13
|
+
attr_reader :source
|
|
14
|
+
|
|
15
|
+
# @param source [Source]
|
|
16
|
+
# @param position [Position, Array(Integer, Integer)]
|
|
17
|
+
def initialize source, position
|
|
18
|
+
@source = source
|
|
19
|
+
@position = Position.normalize(position)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @return [String]
|
|
23
|
+
def filename
|
|
24
|
+
source.filename
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# The whole word at the current position. Given the text `foo.bar`, the
|
|
28
|
+
# word at position(0,6) is `bar`.
|
|
29
|
+
#
|
|
30
|
+
# @return [String]
|
|
31
|
+
def word
|
|
32
|
+
@word ||= start_of_word + end_of_word
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# The part of the word before the current position. Given the text
|
|
36
|
+
# `foo.bar`, the start_of_word at position(0, 6) is `ba`.
|
|
37
|
+
#
|
|
38
|
+
# @return [String]
|
|
39
|
+
def start_of_word
|
|
40
|
+
@start_of_word ||= begin
|
|
41
|
+
match = source.code[0..offset-1].to_s.match(start_word_pattern)
|
|
42
|
+
result = (match ? match[0] : '')
|
|
43
|
+
# Including the preceding colon if the word appears to be a symbol
|
|
44
|
+
result = ":#{result}" if source.code[0..offset-result.length-1].end_with?(':') and !source.code[0..offset-result.length-1].end_with?('::')
|
|
45
|
+
result
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The part of the word after the current position. Given the text
|
|
50
|
+
# `foo.bar`, the end_of_word at position (0,6) is `r`.
|
|
51
|
+
#
|
|
52
|
+
# @return [String]
|
|
53
|
+
def end_of_word
|
|
54
|
+
@end_of_word ||= begin
|
|
55
|
+
match = source.code[offset..-1].to_s.match(end_word_pattern)
|
|
56
|
+
match ? match[0] : ''
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return [Boolean]
|
|
61
|
+
def start_of_constant?
|
|
62
|
+
source.code[offset-2, 2] == '::'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The range of the word at the current position.
|
|
66
|
+
#
|
|
67
|
+
# @return [Range]
|
|
68
|
+
def range
|
|
69
|
+
@range ||= begin
|
|
70
|
+
s = Position.from_offset(source.code, offset - start_of_word.length)
|
|
71
|
+
e = Position.from_offset(source.code, offset + end_of_word.length)
|
|
72
|
+
Solargraph::Range.new(s, e)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @return [Chain]
|
|
77
|
+
def chain
|
|
78
|
+
@chain ||= SourceChainer.chain(source, position)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# True if the statement at the cursor is an argument to a previous
|
|
82
|
+
# method.
|
|
83
|
+
#
|
|
84
|
+
# Given the code `process(foo)`, a cursor pointing at `foo` would
|
|
85
|
+
# identify it as an argument being passed to the `process` method.
|
|
86
|
+
#
|
|
87
|
+
# If #argument? is true, the #recipient method will return a cursor that
|
|
88
|
+
# points to the method receiving the argument.
|
|
89
|
+
#
|
|
90
|
+
# @return [Boolean]
|
|
91
|
+
def argument?
|
|
92
|
+
# @argument ||= !signature_position.nil?
|
|
93
|
+
@argument ||= !recipient.nil?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# @return [Boolean]
|
|
97
|
+
def comment?
|
|
98
|
+
@comment ||= source.comment_at?(position)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# @return [Boolean]
|
|
102
|
+
def string?
|
|
103
|
+
@string ||= source.string_at?(position)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Get a cursor pointing to the method that receives the current statement
|
|
107
|
+
# as an argument.
|
|
108
|
+
#
|
|
109
|
+
# @return [Cursor, nil]
|
|
110
|
+
def recipient
|
|
111
|
+
@recipient ||= begin
|
|
112
|
+
node = recipient_node
|
|
113
|
+
node ? Cursor.new(source, Range.from_node(node).ending) : nil
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
alias receiver recipient
|
|
117
|
+
|
|
118
|
+
def node
|
|
119
|
+
@node ||= source.node_at(position.line, position.column)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @return [Position]
|
|
123
|
+
def node_position
|
|
124
|
+
@node_position ||= begin
|
|
125
|
+
if start_of_word.empty?
|
|
126
|
+
match = source.code[0, offset].match(/[\s]*(\.|:+)[\s]*$/)
|
|
127
|
+
if match
|
|
128
|
+
Position.from_offset(source.code, offset - match[0].length)
|
|
129
|
+
else
|
|
130
|
+
position
|
|
131
|
+
end
|
|
132
|
+
else
|
|
133
|
+
position
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def recipient_node
|
|
139
|
+
@recipient_node ||= Solargraph::Parser::NodeMethods.find_recipient_node(self)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @return [Integer]
|
|
143
|
+
def offset
|
|
144
|
+
@offset ||= Position.to_offset(source.code, position)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
# A regular expression to find the start of a word from an offset.
|
|
150
|
+
#
|
|
151
|
+
# @return [Regexp]
|
|
152
|
+
def start_word_pattern
|
|
153
|
+
/(@{1,2}|\$)?([a-z0-9_]|[^\u0000-\u007F])*\z/i
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# A regular expression to find the end of a word from an offset.
|
|
157
|
+
#
|
|
158
|
+
# @return [Regexp]
|
|
159
|
+
def end_word_pattern
|
|
160
|
+
/^([a-z0-9_]|[^\u0000-\u007F])*[\?\!]?/i
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Source
|
|
5
|
+
module EncodingFixes
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
# Convert strings to normalized UTF-8.
|
|
9
|
+
#
|
|
10
|
+
# @param string [String]
|
|
11
|
+
# @return [String]
|
|
12
|
+
def normalize string
|
|
13
|
+
begin
|
|
14
|
+
string.dup.force_encoding('UTF-8')
|
|
15
|
+
rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError, ::Encoding::InvalidByteSequenceError => e
|
|
16
|
+
# @todo Improve error handling
|
|
17
|
+
Solargraph::Logging.logger.warn "Normalize error: #{e.message}"
|
|
18
|
+
string
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Source
|
|
5
|
+
# Information about a location in a source, including the location's word
|
|
6
|
+
# and signature, literal values at the base of signatures, and whether the
|
|
7
|
+
# location is inside a string or comment. ApiMaps use Fragments to provide
|
|
8
|
+
# results for completion and definition queries.
|
|
9
|
+
#
|
|
10
|
+
class SourceChainer
|
|
11
|
+
# include Source::NodeMethods
|
|
12
|
+
|
|
13
|
+
private_class_method :new
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
# @param source [Source]
|
|
17
|
+
# @param position [Position]
|
|
18
|
+
# @return [Source::Chain]
|
|
19
|
+
def chain source, position
|
|
20
|
+
# raise "Not a source" unless source.is_a?(Source)
|
|
21
|
+
new(source, position).chain
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @param source [Source]
|
|
26
|
+
# @param position [Position]
|
|
27
|
+
def initialize source, position
|
|
28
|
+
@source = source
|
|
29
|
+
@position = position
|
|
30
|
+
@calculated_literal = false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @return [Source::Chain]
|
|
34
|
+
def chain
|
|
35
|
+
return Chain.new([Chain::Literal.new('Symbol')]) if phrase.start_with?(':') && !phrase.start_with?('::')
|
|
36
|
+
begin
|
|
37
|
+
return Chain.new([]) if phrase.end_with?('..')
|
|
38
|
+
node = nil
|
|
39
|
+
parent = nil
|
|
40
|
+
if !source.repaired? && source.parsed? && source.synchronized?
|
|
41
|
+
tree = source.tree_at(position.line, position.column)
|
|
42
|
+
# node, parent = source.tree_at(position.line, position.column)[0..2]
|
|
43
|
+
tree.shift while tree.length > 1 && tree.first.type == :SCOPE
|
|
44
|
+
node, parent = tree[0..2]
|
|
45
|
+
elsif source.parsed? && source.repaired? && end_of_phrase == '.'
|
|
46
|
+
node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
|
|
47
|
+
node = Parser.parse(fixed_phrase) if node.nil?
|
|
48
|
+
else
|
|
49
|
+
node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2] unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
|
|
50
|
+
# Exception for positions that chain literal nodes in unsynchronized sources
|
|
51
|
+
node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
|
|
52
|
+
node = Parser.parse(fixed_phrase) if node.nil?
|
|
53
|
+
end
|
|
54
|
+
rescue Parser::SyntaxError
|
|
55
|
+
return Chain.new([Chain::UNDEFINED_CALL])
|
|
56
|
+
end
|
|
57
|
+
return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
|
|
58
|
+
# chain = NodeChainer.chain(node, source.filename, parent && parent.type == :block)
|
|
59
|
+
chain = Parser.chain(node, source.filename, parent && [:ITER, :block].include?(parent.type))
|
|
60
|
+
if source.repaired? || !source.parsed? || !source.synchronized?
|
|
61
|
+
if end_of_phrase.strip == '.'
|
|
62
|
+
chain.links.push Chain::UNDEFINED_CALL
|
|
63
|
+
elsif end_of_phrase.strip == '::'
|
|
64
|
+
chain.links.push Chain::UNDEFINED_CONSTANT
|
|
65
|
+
end
|
|
66
|
+
elsif chain.links.last.is_a?(Source::Chain::Constant) && end_of_phrase.strip == '::'
|
|
67
|
+
chain.links.push Source::Chain::UNDEFINED_CONSTANT
|
|
68
|
+
end
|
|
69
|
+
chain
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
# @return [Position]
|
|
75
|
+
attr_reader :position
|
|
76
|
+
|
|
77
|
+
# @return [Solargraph::Source]
|
|
78
|
+
attr_reader :source
|
|
79
|
+
|
|
80
|
+
# @return [String]
|
|
81
|
+
def phrase
|
|
82
|
+
@phrase ||= source.code[signature_data..offset-1]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @return [String]
|
|
86
|
+
def fixed_phrase
|
|
87
|
+
@fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @return [Position]
|
|
91
|
+
def fixed_position
|
|
92
|
+
@fixed_position ||= Position.from_offset(source.code, offset - end_of_phrase.length)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @return [String]
|
|
96
|
+
def end_of_phrase
|
|
97
|
+
@end_of_phrase ||= begin
|
|
98
|
+
match = phrase.match(/[\s]*(\.{1}|::)[\s]*$/)
|
|
99
|
+
if match
|
|
100
|
+
match[0]
|
|
101
|
+
else
|
|
102
|
+
''
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# True if the current offset is inside a string.
|
|
108
|
+
#
|
|
109
|
+
# @return [Boolean]
|
|
110
|
+
def string?
|
|
111
|
+
# @string ||= (node.type == :str or node.type == :dstr)
|
|
112
|
+
@string ||= @source.string_at?(position)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @return [Integer]
|
|
116
|
+
def offset
|
|
117
|
+
@offset ||= get_offset(position.line, position.column)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# @param line [Integer]
|
|
121
|
+
# @param column [Integer]
|
|
122
|
+
# @return [Integer]
|
|
123
|
+
def get_offset line, column
|
|
124
|
+
Position.line_char_to_offset(@source.code, line, column)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def signature_data
|
|
128
|
+
@signature_data ||= get_signature_data_at(offset)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def get_signature_data_at index
|
|
132
|
+
brackets = 0
|
|
133
|
+
squares = 0
|
|
134
|
+
parens = 0
|
|
135
|
+
index -=1
|
|
136
|
+
in_whitespace = false
|
|
137
|
+
while index >= 0
|
|
138
|
+
pos = Position.from_offset(@source.code, index)
|
|
139
|
+
break if index > 0 and @source.comment_at?(pos)
|
|
140
|
+
break if brackets > 0 or parens > 0 or squares > 0
|
|
141
|
+
char = @source.code[index, 1]
|
|
142
|
+
break if char.nil? # @todo Is this the right way to handle this?
|
|
143
|
+
if brackets.zero? and parens.zero? and squares.zero? and [' ', "\r", "\n", "\t"].include?(char)
|
|
144
|
+
in_whitespace = true
|
|
145
|
+
else
|
|
146
|
+
if brackets.zero? and parens.zero? and squares.zero? and in_whitespace
|
|
147
|
+
unless char == '.' or @source.code[index+1..-1].strip.start_with?('.')
|
|
148
|
+
old = @source.code[index+1..-1]
|
|
149
|
+
nxt = @source.code[index+1..-1].lstrip
|
|
150
|
+
index += (@source.code[index+1..-1].length - @source.code[index+1..-1].lstrip.length)
|
|
151
|
+
break
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
if char == ')'
|
|
155
|
+
parens -=1
|
|
156
|
+
elsif char == ']'
|
|
157
|
+
squares -=1
|
|
158
|
+
elsif char == '}'
|
|
159
|
+
brackets -= 1
|
|
160
|
+
elsif char == '('
|
|
161
|
+
parens += 1
|
|
162
|
+
elsif char == '{'
|
|
163
|
+
brackets += 1
|
|
164
|
+
elsif char == '['
|
|
165
|
+
squares += 1
|
|
166
|
+
end
|
|
167
|
+
if brackets.zero? and parens.zero? and squares.zero?
|
|
168
|
+
break if ['"', "'", ',', ';', '%'].include?(char)
|
|
169
|
+
break if ['!', '?'].include?(char) && index < offset - 1
|
|
170
|
+
break if char == '$'
|
|
171
|
+
if char == '@'
|
|
172
|
+
index -= 1
|
|
173
|
+
if @source.code[index, 1] == '@'
|
|
174
|
+
index -= 1
|
|
175
|
+
end
|
|
176
|
+
break
|
|
177
|
+
end
|
|
178
|
+
elsif parens == 1 || brackets == 1 || squares == 1
|
|
179
|
+
break
|
|
180
|
+
end
|
|
181
|
+
in_whitespace = false
|
|
182
|
+
end
|
|
183
|
+
index -= 1
|
|
184
|
+
end
|
|
185
|
+
index + 1
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Source
|
|
5
|
+
# Updaters contain changes to be applied to a source. The source applies
|
|
6
|
+
# the update via the Source#synchronize method.
|
|
7
|
+
#
|
|
8
|
+
class Updater
|
|
9
|
+
# @return [String]
|
|
10
|
+
attr_reader :filename
|
|
11
|
+
|
|
12
|
+
# @return [Integer]
|
|
13
|
+
attr_reader :version
|
|
14
|
+
|
|
15
|
+
# @return [Array<Change>]
|
|
16
|
+
attr_reader :changes
|
|
17
|
+
|
|
18
|
+
# @param filename [String] The file to update.
|
|
19
|
+
# @param version [Integer] A version number associated with this update.
|
|
20
|
+
# @param changes [Array<Solargraph::Source::Change>] The changes.
|
|
21
|
+
def initialize filename, version, changes
|
|
22
|
+
@filename = filename
|
|
23
|
+
@version = version
|
|
24
|
+
@changes = changes
|
|
25
|
+
@input = nil
|
|
26
|
+
@did_nullify = nil
|
|
27
|
+
@output = nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param text [String]
|
|
31
|
+
# @param nullable [Boolean]
|
|
32
|
+
# @return [String]
|
|
33
|
+
def write text, nullable = false
|
|
34
|
+
can_nullify = (nullable and changes.length == 1)
|
|
35
|
+
return @output if @input == text and can_nullify == @did_nullify
|
|
36
|
+
@input = text
|
|
37
|
+
@output = text
|
|
38
|
+
@did_nullify = can_nullify
|
|
39
|
+
changes.each do |ch|
|
|
40
|
+
@output = ch.write(@output, can_nullify)
|
|
41
|
+
end
|
|
42
|
+
@output
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [String]
|
|
46
|
+
def repair text
|
|
47
|
+
changes.each do |ch|
|
|
48
|
+
text = ch.repair(text)
|
|
49
|
+
end
|
|
50
|
+
text
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'jaro_winkler'
|
|
4
|
+
require 'yard'
|
|
5
|
+
require 'yard-solargraph'
|
|
6
|
+
|
|
7
|
+
module Solargraph
|
|
8
|
+
# An index of pins and other ApiMap-related data for a Source.
|
|
9
|
+
#
|
|
10
|
+
class SourceMap
|
|
11
|
+
autoload :Mapper, 'solargraph/source_map/mapper'
|
|
12
|
+
autoload :Clip, 'solargraph/source_map/clip'
|
|
13
|
+
autoload :Completion, 'solargraph/source_map/completion'
|
|
14
|
+
|
|
15
|
+
# @return [Source]
|
|
16
|
+
attr_reader :source
|
|
17
|
+
|
|
18
|
+
# @return [Array<Pin::Base>]
|
|
19
|
+
attr_reader :pins
|
|
20
|
+
|
|
21
|
+
# @return [Array<Pin::Base>]
|
|
22
|
+
attr_reader :locals
|
|
23
|
+
|
|
24
|
+
# @param source [Source]
|
|
25
|
+
# @param pins [Array<Pin::Base>]
|
|
26
|
+
# @param locals [Array<Pin::Base>]
|
|
27
|
+
def initialize source, pins, locals
|
|
28
|
+
# HACK: Keep the library from changing this
|
|
29
|
+
@source = source.dup
|
|
30
|
+
@pins = pins
|
|
31
|
+
@locals = locals
|
|
32
|
+
environ.merge Convention.for(source)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [String]
|
|
36
|
+
def filename
|
|
37
|
+
source.filename
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [String]
|
|
41
|
+
def code
|
|
42
|
+
source.code
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [Array<Pin::Reference::Require>]
|
|
46
|
+
def requires
|
|
47
|
+
@requires ||= pins.select{ |p| p.is_a?(Pin::Reference::Require) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Environ]
|
|
51
|
+
def environ
|
|
52
|
+
@environ ||= Environ.new
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return [Array<Pin::Base>]
|
|
56
|
+
def document_symbols
|
|
57
|
+
@document_symbols ||= pins.select { |pin|
|
|
58
|
+
pin.path && !pin.path.empty?
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @param query [String]
|
|
63
|
+
# @return [Array<Pin::Base>]
|
|
64
|
+
def query_symbols query
|
|
65
|
+
document_symbols.select{ |pin| fuzzy_string_match(pin.path, query) || fuzzy_string_match(pin.name, query) }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @param position [Position]
|
|
69
|
+
# @return [Source::Cursor]
|
|
70
|
+
def cursor_at position
|
|
71
|
+
Source::Cursor.new(source, position)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @param path [String]
|
|
75
|
+
# @return [Pin::Base]
|
|
76
|
+
def first_pin path
|
|
77
|
+
pins.select { |p| p.path == path }.first
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# @param location [Solargraph::Location]
|
|
81
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
82
|
+
def locate_pins location
|
|
83
|
+
# return nil unless location.start_with?("#{filename}:")
|
|
84
|
+
(pins + locals).select { |pin| pin.location == location }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def locate_named_path_pin line, character
|
|
88
|
+
_locate_pin line, character, Pin::Namespace, Pin::Method
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def locate_block_pin line, character
|
|
92
|
+
_locate_pin line, character, Pin::Namespace, Pin::Method, Pin::Block
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @param other_map [SourceMap]
|
|
96
|
+
# @return [Boolean]
|
|
97
|
+
def try_merge! other_map
|
|
98
|
+
return false if pins.length != other_map.pins.length || locals.length != other_map.locals.length || requires.map(&:name).uniq.sort != other_map.requires.map(&:name).uniq.sort
|
|
99
|
+
pins.each_index do |i|
|
|
100
|
+
return false unless pins[i].try_merge!(other_map.pins[i])
|
|
101
|
+
end
|
|
102
|
+
locals.each_index do |i|
|
|
103
|
+
return false unless locals[i].try_merge!(other_map.locals[i])
|
|
104
|
+
end
|
|
105
|
+
@source = other_map.source
|
|
106
|
+
true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @param name [String]
|
|
110
|
+
# @return [Array<Location>]
|
|
111
|
+
def references name
|
|
112
|
+
source.references name
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @param location [Location]
|
|
116
|
+
# @return [Array<Pin::LocalVariable>]
|
|
117
|
+
def locals_at(location)
|
|
118
|
+
return [] if location.filename != filename
|
|
119
|
+
locals.select { |pin| pin.visible_at?(location) }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
class << self
|
|
123
|
+
# @param filename [String]
|
|
124
|
+
# @return [SourceMap]
|
|
125
|
+
def load filename
|
|
126
|
+
source = Solargraph::Source.load(filename)
|
|
127
|
+
SourceMap.map(source)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# @param code [String]
|
|
131
|
+
# @param filename [String, nil]
|
|
132
|
+
# @return [SourceMap]
|
|
133
|
+
def load_string code, filename = nil
|
|
134
|
+
source = Solargraph::Source.load_string(code, filename)
|
|
135
|
+
SourceMap.map(source)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# @param source [Source]
|
|
139
|
+
# @return [SourceMap]
|
|
140
|
+
def map source
|
|
141
|
+
result = SourceMap::Mapper.map(source)
|
|
142
|
+
new(source, *result)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
private
|
|
147
|
+
|
|
148
|
+
# @param line [Integer]
|
|
149
|
+
# @param character [Integer]
|
|
150
|
+
# @param klasses [Array<Class>]
|
|
151
|
+
# @return [Pin::Base]
|
|
152
|
+
def _locate_pin line, character, *klasses
|
|
153
|
+
position = Position.new(line, character)
|
|
154
|
+
found = nil
|
|
155
|
+
pins.each do |pin|
|
|
156
|
+
found = pin if (klasses.empty? || klasses.any? { |kls| pin.is_a?(kls) } ) && pin.location.range.contain?(position)
|
|
157
|
+
break if pin.location.range.start.line > line
|
|
158
|
+
end
|
|
159
|
+
# Assuming the root pin is always valid
|
|
160
|
+
found || pins.first
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# @param str1 [String]
|
|
164
|
+
# @param str2 [String]
|
|
165
|
+
# @return [Boolean]
|
|
166
|
+
def fuzzy_string_match str1, str2
|
|
167
|
+
JaroWinkler.distance(str1, str2) > 0.6
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|