jimeh-solargraph 0.40.4.0
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/.github/workflows/ci.yml +54 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +24 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +1003 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +123 -0
- data/Rakefile +25 -0
- data/SPONSORS.md +15 -0
- data/bin/solargraph +5 -0
- data/jimeh-solargraph.gemspec +44 -0
- data/lib/.rubocop.yml +21 -0
- data/lib/solargraph.rb +67 -0
- data/lib/solargraph/api_map.rb +752 -0
- data/lib/solargraph/api_map/bundler_methods.rb +27 -0
- data/lib/solargraph/api_map/cache.rb +70 -0
- data/lib/solargraph/api_map/source_to_yard.rb +81 -0
- data/lib/solargraph/api_map/store.rb +256 -0
- data/lib/solargraph/bench.rb +30 -0
- data/lib/solargraph/compat.rb +23 -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 +47 -0
- data/lib/solargraph/convention/base.rb +33 -0
- data/lib/solargraph/convention/gemfile.rb +15 -0
- data/lib/solargraph/convention/gemspec.rb +22 -0
- data/lib/solargraph/convention/rspec.rb +21 -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/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 +45 -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 +78 -0
- data/lib/solargraph/environ.rb +45 -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 +746 -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 +100 -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 +105 -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 +426 -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 +311 -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 +257 -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 +80 -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 +301 -0
- data/lib/solargraph/parser/rubyvm/node_processors.rb +62 -0
- data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +86 -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 +26 -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 +277 -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 +36 -0
- data/lib/solargraph/pin/base.rb +296 -0
- data/lib/solargraph/pin/base_variable.rb +84 -0
- data/lib/solargraph/pin/block.rb +62 -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 +96 -0
- data/lib/solargraph/pin/documenting.rb +105 -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 +245 -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/position.rb +100 -0
- data/lib/solargraph/range.rb +95 -0
- data/lib/solargraph/server_methods.rb +16 -0
- data/lib/solargraph/shell.rb +222 -0
- data/lib/solargraph/source.rb +537 -0
- data/lib/solargraph/source/chain.rb +154 -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 +30 -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 +190 -0
- data/lib/solargraph/source/updater.rb +54 -0
- data/lib/solargraph/source_map.rb +188 -0
- data/lib/solargraph/source_map/clip.rb +224 -0
- data/lib/solargraph/source_map/completion.rb +23 -0
- data/lib/solargraph/source_map/mapper.rb +215 -0
- data/lib/solargraph/type_checker.rb +503 -0
- data/lib/solargraph/type_checker/checks.rb +99 -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 +57 -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 +230 -0
- data/lib/solargraph/yard_map.rb +435 -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_fills.rb +185 -0
- data/lib/solargraph/yard_map/core_gen.rb +76 -0
- data/lib/solargraph/yard_map/helpers.rb +16 -0
- data/lib/solargraph/yard_map/mapper.rb +77 -0
- data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
- data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +140 -0
- data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
- data/lib/solargraph/yard_map/to_method.rb +79 -0
- data/lib/yard-solargraph.rb +30 -0
- data/yardoc/2.2.2.tar.gz +0 -0
- metadata +564 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
class SourceMap
|
5
|
+
# A static analysis tool for obtaining definitions, completions,
|
6
|
+
# signatures, and type inferences from a cursor.
|
7
|
+
#
|
8
|
+
class Clip
|
9
|
+
# @param api_map [ApiMap]
|
10
|
+
# @param cursor [Source::Cursor]
|
11
|
+
def initialize api_map, cursor
|
12
|
+
@api_map = api_map
|
13
|
+
@cursor = cursor
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Array<Pin::Base>]
|
17
|
+
def define
|
18
|
+
return [] if cursor.comment? || cursor.chain.literal?
|
19
|
+
result = cursor.chain.define(api_map, block, locals)
|
20
|
+
result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Completion]
|
25
|
+
def complete
|
26
|
+
return package_completions([]) if !source_map.source.parsed? || cursor.string?
|
27
|
+
return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
|
28
|
+
return Completion.new([], cursor.range) if cursor.chain.literal?
|
29
|
+
if cursor.comment?
|
30
|
+
tag_complete
|
31
|
+
else
|
32
|
+
code_complete
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Array<Pin::Base>]
|
37
|
+
def signify
|
38
|
+
return [] unless cursor.argument?
|
39
|
+
chain = Parser.chain(cursor.recipient_node, cursor.filename)
|
40
|
+
chain.define(api_map, context_pin, locals).select { |pin| pin.is_a?(Pin::Method) }
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [ComplexType]
|
44
|
+
def infer
|
45
|
+
result = cursor.chain.infer(api_map, block, locals)
|
46
|
+
return result unless result.tag == 'self'
|
47
|
+
ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get an array of all the locals that are visible from the cursors's
|
51
|
+
# position. Locals can be local variables, method parameters, or block
|
52
|
+
# parameters. The array starts with the nearest local pin.
|
53
|
+
#
|
54
|
+
# @return [Array<Solargraph::Pin::Base>]
|
55
|
+
def locals
|
56
|
+
loc_pos = context_pin.location.range.contain?(cursor.position) ? cursor.position : context_pin.location.range.ending
|
57
|
+
adj_pos = Position.new(loc_pos.line, (loc_pos.column.zero? ? 0 : loc_pos.column - 1))
|
58
|
+
@locals ||= source_map.locals.select { |pin|
|
59
|
+
pin.visible_from?(block, adj_pos)
|
60
|
+
}.reverse
|
61
|
+
end
|
62
|
+
|
63
|
+
def gates
|
64
|
+
block.gates
|
65
|
+
end
|
66
|
+
|
67
|
+
def in_block?
|
68
|
+
return @in_block unless @in_block.nil?
|
69
|
+
@in_block = begin
|
70
|
+
tree = cursor.source.tree_at(cursor.position.line, cursor.position.column)
|
71
|
+
Parser.is_ast_node?(tree[1]) && [:block, :ITER].include?(tree[1].type)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param phrase [String]
|
76
|
+
# @return [Array<Solargraph::Pin::Base>]
|
77
|
+
def translate phrase
|
78
|
+
chain = Parser.chain(Parser.parse(phrase))
|
79
|
+
chain.define(api_map, block, locals)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# @return [ApiMap]
|
85
|
+
attr_reader :api_map
|
86
|
+
|
87
|
+
# @return [Source::Cursor]
|
88
|
+
attr_reader :cursor
|
89
|
+
|
90
|
+
# @return [SourceMap]
|
91
|
+
def source_map
|
92
|
+
@source_map ||= api_map.source_map(cursor.filename)
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [Solargraph::Pin::Base]
|
96
|
+
def block
|
97
|
+
@block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
|
98
|
+
end
|
99
|
+
|
100
|
+
# The context at the current position.
|
101
|
+
#
|
102
|
+
# @return [Pin::Base]
|
103
|
+
def context_pin
|
104
|
+
@context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
|
105
|
+
end
|
106
|
+
|
107
|
+
# @return [Array<Pin::Base>]
|
108
|
+
def yielded_self_pins
|
109
|
+
return [] unless block.is_a?(Pin::Block) && block.receiver
|
110
|
+
chain = Parser.chain(block.receiver, source_map.source.filename)
|
111
|
+
receiver_pin = chain.define(api_map, context_pin, locals).first
|
112
|
+
return [] if receiver_pin.nil?
|
113
|
+
result = []
|
114
|
+
ys = receiver_pin.docstring.tag(:yieldpublic)
|
115
|
+
unless ys.nil? || ys.types.empty?
|
116
|
+
ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
|
117
|
+
result.concat api_map.get_complex_type_methods(ysct, '', false)
|
118
|
+
end
|
119
|
+
result
|
120
|
+
end
|
121
|
+
|
122
|
+
# @return [Array<Pin::KeywordParam]
|
123
|
+
def complete_keyword_parameters
|
124
|
+
return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
|
125
|
+
pins = signify
|
126
|
+
result = []
|
127
|
+
done = []
|
128
|
+
pins.each do |pin|
|
129
|
+
pin.parameters.each do |param|
|
130
|
+
next if done.include?(param.name)
|
131
|
+
done.push param.name
|
132
|
+
next unless param.keyword?
|
133
|
+
result.push Pin::KeywordParam.new(pin.location, "#{param.name}:")
|
134
|
+
end
|
135
|
+
if !pin.parameters.empty? && pin.parameters.last.kwrestarg?
|
136
|
+
pin.docstring.tags(:param).each do |tag|
|
137
|
+
next if done.include?(tag.name)
|
138
|
+
done.push tag.name
|
139
|
+
result.push Pin::KeywordParam.new(pin.location, "#{tag.name}:")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
result
|
144
|
+
end
|
145
|
+
|
146
|
+
# @param result [Array<Pin::Base>]
|
147
|
+
# @return [Completion]
|
148
|
+
def package_completions result
|
149
|
+
frag_start = cursor.start_of_word.to_s.downcase
|
150
|
+
filtered = result.uniq(&:name).select { |s|
|
151
|
+
s.name.downcase.start_with?(frag_start) &&
|
152
|
+
(!s.is_a?(Pin::Method) || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
|
153
|
+
}
|
154
|
+
Completion.new(filtered, cursor.range)
|
155
|
+
end
|
156
|
+
|
157
|
+
def tag_complete
|
158
|
+
result = []
|
159
|
+
match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
|
160
|
+
if match
|
161
|
+
full = match[1]
|
162
|
+
if full.include?('::')
|
163
|
+
if full.end_with?('::')
|
164
|
+
result.concat api_map.get_constants(full[0..-3], *gates)
|
165
|
+
else
|
166
|
+
result.concat api_map.get_constants(full.split('::')[0..-2].join('::'), *gates)
|
167
|
+
end
|
168
|
+
else
|
169
|
+
result.concat api_map.get_constants('', full.end_with?('::') ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
package_completions(result)
|
173
|
+
end
|
174
|
+
|
175
|
+
def code_complete
|
176
|
+
result = []
|
177
|
+
result.concat complete_keyword_parameters
|
178
|
+
if cursor.chain.constant? || cursor.start_of_constant?
|
179
|
+
full = cursor.chain.links.first.word
|
180
|
+
type = if cursor.chain.undefined?
|
181
|
+
cursor.chain.base.infer(api_map, context_pin, locals)
|
182
|
+
else
|
183
|
+
if full.include?('::') && cursor.chain.links.length == 1
|
184
|
+
ComplexType.try_parse(full.split('::')[0..-2].join('::'))
|
185
|
+
elsif cursor.chain.links.length > 1
|
186
|
+
ComplexType.try_parse(full)
|
187
|
+
else
|
188
|
+
ComplexType::UNDEFINED
|
189
|
+
end
|
190
|
+
end
|
191
|
+
if type.undefined?
|
192
|
+
if full.include?('::')
|
193
|
+
result.concat api_map.get_constants(full, *gates)
|
194
|
+
else
|
195
|
+
result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
|
196
|
+
end
|
197
|
+
else
|
198
|
+
result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
|
199
|
+
end
|
200
|
+
else
|
201
|
+
type = cursor.chain.base.infer(api_map, block, locals)
|
202
|
+
result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
|
203
|
+
if cursor.chain.links.length == 1
|
204
|
+
if cursor.word.start_with?('@@')
|
205
|
+
return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
|
206
|
+
elsif cursor.word.start_with?('@')
|
207
|
+
return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
|
208
|
+
elsif cursor.word.start_with?('$')
|
209
|
+
return package_completions(api_map.get_global_variable_pins)
|
210
|
+
end
|
211
|
+
result.concat locals
|
212
|
+
result.concat api_map.get_constants(context_pin.context.namespace, *gates)
|
213
|
+
result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
|
214
|
+
result.concat api_map.get_methods('Kernel')
|
215
|
+
# result.concat ApiMap.keywords
|
216
|
+
result.concat api_map.keyword_pins
|
217
|
+
result.concat yielded_self_pins
|
218
|
+
end
|
219
|
+
end
|
220
|
+
package_completions(result)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
class SourceMap
|
5
|
+
# The result of a completion request containing the pins that describe
|
6
|
+
# completion options and the range to be replaced.
|
7
|
+
#
|
8
|
+
class Completion
|
9
|
+
# @return [Array<Solargraph::Pin::Base>]
|
10
|
+
attr_reader :pins
|
11
|
+
|
12
|
+
# @return [Solargraph::Range]
|
13
|
+
attr_reader :range
|
14
|
+
|
15
|
+
# @param pins [Array<Solargraph::Pin::Base>]
|
16
|
+
# @param range [Solargraph::Range]
|
17
|
+
def initialize pins, range
|
18
|
+
@pins = pins
|
19
|
+
@range = range
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Solargraph
|
4
|
+
class SourceMap
|
5
|
+
# The Mapper generates pins and other data for SourceMaps.
|
6
|
+
#
|
7
|
+
# This class is used internally by the SourceMap class. Users should not
|
8
|
+
# normally need to call it directly.
|
9
|
+
#
|
10
|
+
class Mapper
|
11
|
+
# include Source::NodeMethods
|
12
|
+
|
13
|
+
private_class_method :new
|
14
|
+
|
15
|
+
MACRO_REGEXP = /(@\!method|@\!attribute|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
|
16
|
+
|
17
|
+
# Generate the data.
|
18
|
+
#
|
19
|
+
# @param source [Source]
|
20
|
+
# @return [Array]
|
21
|
+
def map source
|
22
|
+
@source = source
|
23
|
+
@filename = source.filename
|
24
|
+
@code = source.code
|
25
|
+
@comments = source.comments
|
26
|
+
@pins, @locals = Parser.map(source)
|
27
|
+
process_comment_directives
|
28
|
+
[@pins, @locals]
|
29
|
+
# rescue Exception => e
|
30
|
+
# Solargraph.logger.warn "Error mapping #{source.filename}: [#{e.class}] #{e.message}"
|
31
|
+
# Solargraph.logger.warn e.backtrace.join("\n")
|
32
|
+
# [[], []]
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param filename [String]
|
36
|
+
# @param code [String]
|
37
|
+
# @return [Array]
|
38
|
+
def unmap filename, code
|
39
|
+
s = Position.new(0, 0)
|
40
|
+
e = Position.from_offset(code, code.length)
|
41
|
+
location = Location.new(filename, Range.new(s, e))
|
42
|
+
[[Pin::Namespace.new(location: location, name: '')], []]
|
43
|
+
end
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# @param source [Source]
|
47
|
+
# @return [Array]
|
48
|
+
def map source
|
49
|
+
return new.unmap(source.filename, source.code) unless source.parsed?
|
50
|
+
new.map source
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Array<Solargraph::Pin::Base>]
|
55
|
+
def pins
|
56
|
+
@pins ||= []
|
57
|
+
end
|
58
|
+
|
59
|
+
def closure_at(position)
|
60
|
+
@pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
|
61
|
+
end
|
62
|
+
|
63
|
+
def process_comment source_position, comment_position, comment
|
64
|
+
return unless comment =~ MACRO_REGEXP
|
65
|
+
cmnt = remove_inline_comment_hashes(comment)
|
66
|
+
parse = Solargraph::Source.parse_docstring(cmnt)
|
67
|
+
last_line = 0
|
68
|
+
# @param d [YARD::Tags::Directive]
|
69
|
+
parse.directives.each do |d|
|
70
|
+
line_num = find_directive_line_number(cmnt, d.tag.tag_name, last_line)
|
71
|
+
pos = Solargraph::Position.new(comment_position.line + line_num - 1, comment_position.column)
|
72
|
+
process_directive(source_position, pos, d)
|
73
|
+
last_line = line_num + 1
|
74
|
+
# @todo The below call assumes the topmost comment line. The above
|
75
|
+
# process occasionally emits incorrect comment positions due to
|
76
|
+
# blank lines in comment blocks, but at least it processes all the
|
77
|
+
# directives.
|
78
|
+
# process_directive(source_position, comment_position, d)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param comment [String]
|
83
|
+
# @return [Integer]
|
84
|
+
def find_directive_line_number comment, tag, start
|
85
|
+
# Avoid overruning the index
|
86
|
+
return start unless start < comment.lines.length
|
87
|
+
num = comment.lines[start..-1].find_index do |line|
|
88
|
+
# Legacy method directives might be `@method` instead of `@!method`
|
89
|
+
# @todo Legacy syntax should probably emit a warning
|
90
|
+
line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
|
91
|
+
end
|
92
|
+
num.to_i + start
|
93
|
+
end
|
94
|
+
|
95
|
+
# @param source_position [Position]
|
96
|
+
# @param comment_position [Position]
|
97
|
+
# @param directive [YARD::Tags::Directive]
|
98
|
+
# @return [void]
|
99
|
+
def process_directive source_position, comment_position, directive
|
100
|
+
docstring = Solargraph::Source.parse_docstring(directive.tag.text).to_docstring
|
101
|
+
location = Location.new(@filename, Range.new(comment_position, comment_position))
|
102
|
+
case directive.tag.tag_name
|
103
|
+
when 'method'
|
104
|
+
namespace = closure_at(source_position) || @pins.first
|
105
|
+
if namespace.location.range.start.line < comment_position.line
|
106
|
+
namespace = closure_at(comment_position)
|
107
|
+
end
|
108
|
+
begin
|
109
|
+
src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
|
110
|
+
region = Parser::Region.new(source: src, closure: namespace)
|
111
|
+
gen_pin = Parser.process_node(src.node, region).first.last
|
112
|
+
return if gen_pin.nil?
|
113
|
+
# Move the location to the end of the line so it gets recognized
|
114
|
+
# as originating from a comment
|
115
|
+
shifted = Solargraph::Position.new(comment_position.line, @code.lines[comment_position.line].to_s.chomp.length)
|
116
|
+
# @todo: Smelly instance variable access
|
117
|
+
gen_pin.instance_variable_set(:@comments, docstring.all.to_s)
|
118
|
+
gen_pin.instance_variable_set(:@location, Solargraph::Location.new(@filename, Range.new(shifted, shifted)))
|
119
|
+
gen_pin.instance_variable_set(:@explicit, false)
|
120
|
+
@pins.push gen_pin
|
121
|
+
rescue Parser::SyntaxError => e
|
122
|
+
# @todo Handle error in directive
|
123
|
+
end
|
124
|
+
when 'attribute'
|
125
|
+
return if directive.tag.name.nil?
|
126
|
+
namespace = closure_at(source_position)
|
127
|
+
t = (directive.tag.types.nil? || directive.tag.types.empty?) ? nil : directive.tag.types.flatten.join('')
|
128
|
+
if t.nil? || t.include?('r')
|
129
|
+
pins.push Solargraph::Pin::Method.new(
|
130
|
+
location: location,
|
131
|
+
closure: namespace,
|
132
|
+
name: directive.tag.name,
|
133
|
+
comments: docstring.all.to_s,
|
134
|
+
scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
|
135
|
+
visibility: :public,
|
136
|
+
explicit: false,
|
137
|
+
attribute: true
|
138
|
+
)
|
139
|
+
end
|
140
|
+
if t.nil? || t.include?('w')
|
141
|
+
pins.push Solargraph::Pin::Method.new(
|
142
|
+
location: location,
|
143
|
+
closure: namespace,
|
144
|
+
name: "#{directive.tag.name}=",
|
145
|
+
comments: docstring.all.to_s,
|
146
|
+
scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
|
147
|
+
visibility: :public,
|
148
|
+
attribute: true
|
149
|
+
)
|
150
|
+
pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
|
151
|
+
if pins.last.return_type.defined?
|
152
|
+
pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
|
153
|
+
end
|
154
|
+
end
|
155
|
+
when 'parse'
|
156
|
+
begin
|
157
|
+
ns = closure_at(source_position)
|
158
|
+
src = Solargraph::Source.load_string(directive.tag.text, @source.filename)
|
159
|
+
region = Parser::Region.new(source: src, closure: ns)
|
160
|
+
# @todo These pins may need to be marked not explicit
|
161
|
+
index = @pins.length
|
162
|
+
loff = if @code.lines[comment_position.line].strip.end_with?('@!parse')
|
163
|
+
comment_position.line + 1
|
164
|
+
else
|
165
|
+
comment_position.line
|
166
|
+
end
|
167
|
+
Parser.process_node(src.node, region, @pins)
|
168
|
+
@pins[index..-1].each do |p|
|
169
|
+
# @todo Smelly instance variable access
|
170
|
+
p.location.range.start.instance_variable_set(:@line, p.location.range.start.line + loff)
|
171
|
+
p.location.range.ending.instance_variable_set(:@line, p.location.range.ending.line + loff)
|
172
|
+
end
|
173
|
+
rescue Parser::SyntaxError => e
|
174
|
+
# @todo Handle parser errors in !parse directives
|
175
|
+
end
|
176
|
+
when 'domain'
|
177
|
+
namespace = closure_at(source_position)
|
178
|
+
namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
|
179
|
+
when 'override'
|
180
|
+
pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def remove_inline_comment_hashes comment
|
185
|
+
ctxt = ''
|
186
|
+
num = nil
|
187
|
+
started = false
|
188
|
+
comment.lines.each { |l|
|
189
|
+
# Trim the comment and minimum leading whitespace
|
190
|
+
p = l.gsub(/^#/, '')
|
191
|
+
if num.nil? && !p.strip.empty?
|
192
|
+
num = p.index(/[^ ]/)
|
193
|
+
started = true
|
194
|
+
elsif started && !p.strip.empty?
|
195
|
+
cur = p.index(/[^ ]/)
|
196
|
+
num = cur if cur < num
|
197
|
+
end
|
198
|
+
ctxt += "#{p[num..-1]}" if started
|
199
|
+
}
|
200
|
+
ctxt
|
201
|
+
end
|
202
|
+
|
203
|
+
# @return [void]
|
204
|
+
def process_comment_directives
|
205
|
+
return unless @code =~ MACRO_REGEXP
|
206
|
+
code_lines = @code.lines
|
207
|
+
@source.associated_comments.each do |line, comments|
|
208
|
+
src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
|
209
|
+
com_pos = Position.new(line + 1 - comments.lines.length, 0)
|
210
|
+
process_comment(src_pos, com_pos, comments)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|