cosmicgraph 0.49.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/FUNDING.yml +1 -0
- data/.github/workflows/rspec.yml +41 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +1150 -0
- data/Gemfile +7 -0
- data/LICENSE +21 -0
- data/README.md +136 -0
- data/Rakefile +25 -0
- data/SPONSORS.md +15 -0
- data/bin/solargraph +5 -0
- data/cosmicgraph.gemspec +44 -0
- data/lib/.rubocop.yml +22 -0
- data/lib/solargraph/api_map/bundler_methods.rb +22 -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 +268 -0
- data/lib/solargraph/api_map.rb +704 -0
- data/lib/solargraph/bench.rb +27 -0
- data/lib/solargraph/cache.rb +51 -0
- data/lib/solargraph/complex_type/type_methods.rb +134 -0
- data/lib/solargraph/complex_type/unique_type.rb +132 -0
- data/lib/solargraph/complex_type.rb +254 -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/rakefile.rb +17 -0
- data/lib/solargraph/convention/rspec.rb +30 -0
- data/lib/solargraph/convention.rb +49 -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/base.rb +29 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +53 -0
- data/lib/solargraph/diagnostics/rubocop.rb +112 -0
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +65 -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/diagnostics.rb +55 -0
- data/lib/solargraph/documentor.rb +76 -0
- data/lib/solargraph/environ.rb +45 -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/cataloger.rb +56 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +89 -0
- data/lib/solargraph/language_server/host/dispatch.rb +111 -0
- data/lib/solargraph/language_server/host/message_worker.rb +59 -0
- data/lib/solargraph/language_server/host/sources.rb +156 -0
- data/lib/solargraph/language_server/host.rb +869 -0
- data/lib/solargraph/language_server/message/base.rb +89 -0
- data/lib/solargraph/language_server/message/cancel_request.rb +13 -0
- data/lib/solargraph/language_server/message/client/register_capability.rb +15 -0
- data/lib/solargraph/language_server/message/client.rb +11 -0
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -0
- data/lib/solargraph/language_server/message/completion_item.rb +11 -0
- data/lib/solargraph/language_server/message/exit_notification.rb +13 -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 +19 -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/extended.rb +21 -0
- data/lib/solargraph/language_server/message/initialize.rb +164 -0
- data/lib/solargraph/language_server/message/initialized.rb +27 -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/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 +59 -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_highlight.rb +16 -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 +126 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +56 -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 +24 -0
- data/lib/solargraph/language_server/message/text_document.rb +28 -0
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +30 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -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/workspace.rb +14 -0
- data/lib/solargraph/language_server/message.rb +93 -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/adapter.rb +53 -0
- data/lib/solargraph/language_server/transport/data_reader.rb +72 -0
- data/lib/solargraph/language_server/transport.rb +13 -0
- data/lib/solargraph/language_server/uri_helpers.rb +49 -0
- data/lib/solargraph/language_server.rb +19 -0
- data/lib/solargraph/library.rb +547 -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/comment_ripper.rb +52 -0
- data/lib/solargraph/parser/legacy/class_methods.rb +135 -0
- data/lib/solargraph/parser/legacy/flawed_builder.rb +16 -0
- data/lib/solargraph/parser/legacy/node_chainer.rb +148 -0
- data/lib/solargraph/parser/legacy/node_methods.rb +325 -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 +42 -0
- data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +35 -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 +42 -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/legacy/node_processors.rb +54 -0
- data/lib/solargraph/parser/legacy.rb +12 -0
- data/lib/solargraph/parser/node_methods.rb +43 -0
- data/lib/solargraph/parser/node_processor/base.rb +77 -0
- data/lib/solargraph/parser/node_processor.rb +43 -0
- data/lib/solargraph/parser/region.rb +66 -0
- data/lib/solargraph/parser/rubyvm/class_methods.rb +149 -0
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +160 -0
- data/lib/solargraph/parser/rubyvm/node_methods.rb +315 -0
- data/lib/solargraph/parser/rubyvm/node_processors/alias_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +85 -0
- data/lib/solargraph/parser/rubyvm/node_processors/begin_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +42 -0
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +33 -0
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +23 -0
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +75 -0
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +68 -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 +32 -0
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +15 -0
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +279 -0
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +18 -0
- data/lib/solargraph/parser/rubyvm/node_processors.rb +63 -0
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
- data/lib/solargraph/parser/rubyvm.rb +40 -0
- data/lib/solargraph/parser/snippet.rb +13 -0
- data/lib/solargraph/parser.rb +26 -0
- data/lib/solargraph/pin/base.rb +299 -0
- data/lib/solargraph/pin/base_variable.rb +84 -0
- data/lib/solargraph/pin/block.rb +73 -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 +92 -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 +55 -0
- data/lib/solargraph/pin/method.rb +335 -0
- data/lib/solargraph/pin/method_alias.rb +31 -0
- data/lib/solargraph/pin/namespace.rb +94 -0
- data/lib/solargraph/pin/parameter.rb +206 -0
- data/lib/solargraph/pin/proxy_type.rb +29 -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/reference.rb +14 -0
- data/lib/solargraph/pin/search.rb +56 -0
- data/lib/solargraph/pin/signature.rb +23 -0
- data/lib/solargraph/pin/singleton.rb +11 -0
- data/lib/solargraph/pin/symbol.rb +47 -0
- data/lib/solargraph/pin.rb +38 -0
- data/lib/solargraph/position.rb +100 -0
- data/lib/solargraph/range.rb +95 -0
- data/lib/solargraph/rbs_map/conversions.rb +394 -0
- data/lib/solargraph/rbs_map/core_fills.rb +61 -0
- data/lib/solargraph/rbs_map/core_map.rb +38 -0
- data/lib/solargraph/rbs_map/core_signs.rb +33 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
- data/lib/solargraph/rbs_map.rb +73 -0
- data/lib/solargraph/server_methods.rb +16 -0
- data/lib/solargraph/shell.rb +234 -0
- data/lib/solargraph/source/chain/block_variable.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +215 -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/hash.rb +28 -0
- data/lib/solargraph/source/chain/head.rb +19 -0
- data/lib/solargraph/source/chain/instance_variable.rb +13 -0
- data/lib/solargraph/source/chain/link.rb +71 -0
- data/lib/solargraph/source/chain/literal.rb +23 -0
- data/lib/solargraph/source/chain/or.rb +23 -0
- data/lib/solargraph/source/chain/q_call.rb +11 -0
- data/lib/solargraph/source/chain/variable.rb +13 -0
- data/lib/solargraph/source/chain/z_super.rb +30 -0
- data/lib/solargraph/source/chain.rb +179 -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 +191 -0
- data/lib/solargraph/source/updater.rb +54 -0
- data/lib/solargraph/source.rb +522 -0
- data/lib/solargraph/source_map/clip.rb +229 -0
- data/lib/solargraph/source_map/completion.rb +23 -0
- data/lib/solargraph/source_map/mapper.rb +241 -0
- data/lib/solargraph/source_map.rb +180 -0
- data/lib/solargraph/type_checker/checks.rb +112 -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/type_checker.rb +549 -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/config.rb +231 -0
- data/lib/solargraph/workspace.rb +212 -0
- data/lib/solargraph/yard_map/cache.rb +19 -0
- data/lib/solargraph/yard_map/helpers.rb +16 -0
- data/lib/solargraph/yard_map/mapper/to_constant.rb +25 -0
- data/lib/solargraph/yard_map/mapper/to_method.rb +81 -0
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +27 -0
- data/lib/solargraph/yard_map/mapper.rb +77 -0
- data/lib/solargraph/yard_map/to_method.rb +79 -0
- data/lib/solargraph/yard_map.rb +301 -0
- data/lib/solargraph.rb +69 -0
- data/lib/yard-solargraph.rb +33 -0
- metadata +587 -0
@@ -0,0 +1,229 @@
|
|
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
|
+
if result.tag == 'Class'
|
47
|
+
# HACK: Exception to return Object from Class#new
|
48
|
+
dfn = cursor.chain.define(api_map, block, locals).first
|
49
|
+
return ComplexType.try_parse('Object') if dfn && dfn.path == 'Class#new'
|
50
|
+
end
|
51
|
+
return result unless result.tag == 'self'
|
52
|
+
ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get an array of all the locals that are visible from the cursors's
|
56
|
+
# position. Locals can be local variables, method parameters, or block
|
57
|
+
# parameters. The array starts with the nearest local pin.
|
58
|
+
#
|
59
|
+
# @return [Array<Solargraph::Pin::Base>]
|
60
|
+
def locals
|
61
|
+
@locals ||= source_map.locals_at(location)
|
62
|
+
end
|
63
|
+
|
64
|
+
def gates
|
65
|
+
block.gates
|
66
|
+
end
|
67
|
+
|
68
|
+
def in_block?
|
69
|
+
return @in_block unless @in_block.nil?
|
70
|
+
@in_block = begin
|
71
|
+
tree = cursor.source.tree_at(cursor.position.line, cursor.position.column)
|
72
|
+
Parser.is_ast_node?(tree[1]) && [:block, :ITER].include?(tree[1].type)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param phrase [String]
|
77
|
+
# @return [Array<Solargraph::Pin::Base>]
|
78
|
+
def translate phrase
|
79
|
+
chain = Parser.chain(Parser.parse(phrase))
|
80
|
+
chain.define(api_map, block, locals)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# @return [ApiMap]
|
86
|
+
attr_reader :api_map
|
87
|
+
|
88
|
+
# @return [Source::Cursor]
|
89
|
+
attr_reader :cursor
|
90
|
+
|
91
|
+
# @return [SourceMap]
|
92
|
+
def source_map
|
93
|
+
@source_map ||= api_map.source_map(cursor.filename)
|
94
|
+
end
|
95
|
+
|
96
|
+
def location
|
97
|
+
Location.new(source_map.filename, Solargraph::Range.new(cursor.position, cursor.position))
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [Solargraph::Pin::Base]
|
101
|
+
def block
|
102
|
+
@block ||= source_map.locate_block_pin(cursor.node_position.line, cursor.node_position.character)
|
103
|
+
end
|
104
|
+
|
105
|
+
# The context at the current position.
|
106
|
+
#
|
107
|
+
# @return [Pin::Base]
|
108
|
+
def context_pin
|
109
|
+
@context_pin ||= source_map.locate_named_path_pin(cursor.node_position.line, cursor.node_position.character)
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return [Array<Pin::Base>]
|
113
|
+
def yielded_self_pins
|
114
|
+
return [] unless block.is_a?(Pin::Block) && block.receiver
|
115
|
+
chain = Parser.chain(block.receiver, source_map.source.filename)
|
116
|
+
receiver_pin = chain.define(api_map, context_pin, locals).first
|
117
|
+
return [] if receiver_pin.nil?
|
118
|
+
result = []
|
119
|
+
ys = receiver_pin.docstring.tag(:yieldpublic)
|
120
|
+
unless ys.nil? || ys.types.empty?
|
121
|
+
ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
|
122
|
+
result.concat api_map.get_complex_type_methods(ysct, '', false)
|
123
|
+
end
|
124
|
+
result
|
125
|
+
end
|
126
|
+
|
127
|
+
# @return [Array<Pin::KeywordParam]
|
128
|
+
def complete_keyword_parameters
|
129
|
+
return [] unless cursor.argument? && cursor.chain.links.one? && cursor.word =~ /^[a-z0-9_]*:?$/
|
130
|
+
pins = signify
|
131
|
+
result = []
|
132
|
+
done = []
|
133
|
+
pins.each do |pin|
|
134
|
+
pin.parameters.each do |param|
|
135
|
+
next if done.include?(param.name)
|
136
|
+
done.push param.name
|
137
|
+
next unless param.keyword?
|
138
|
+
result.push Pin::KeywordParam.new(pin.location, "#{param.name}:")
|
139
|
+
end
|
140
|
+
if !pin.parameters.empty? && pin.parameters.last.kwrestarg?
|
141
|
+
pin.docstring.tags(:param).each do |tag|
|
142
|
+
next if done.include?(tag.name)
|
143
|
+
done.push tag.name
|
144
|
+
result.push Pin::KeywordParam.new(pin.location, "#{tag.name}:")
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
result
|
149
|
+
end
|
150
|
+
|
151
|
+
# @param result [Array<Pin::Base>]
|
152
|
+
# @return [Completion]
|
153
|
+
def package_completions result
|
154
|
+
frag_start = cursor.start_of_word.to_s.downcase
|
155
|
+
filtered = result.uniq(&:name).select { |s|
|
156
|
+
s.name.downcase.start_with?(frag_start) &&
|
157
|
+
(!s.is_a?(Pin::Method) || s.name.match(/^[a-z0-9_]+(\!|\?|=)?$/i))
|
158
|
+
}
|
159
|
+
Completion.new(filtered, cursor.range)
|
160
|
+
end
|
161
|
+
|
162
|
+
def tag_complete
|
163
|
+
result = []
|
164
|
+
match = source_map.code[0..cursor.offset-1].match(/[\[<, ]([a-z0-9_:]*)\z/i)
|
165
|
+
if match
|
166
|
+
full = match[1]
|
167
|
+
if full.include?('::')
|
168
|
+
if full.end_with?('::')
|
169
|
+
result.concat api_map.get_constants(full[0..-3], *gates)
|
170
|
+
else
|
171
|
+
result.concat api_map.get_constants(full.split('::')[0..-2].join('::'), *gates)
|
172
|
+
end
|
173
|
+
else
|
174
|
+
result.concat api_map.get_constants('', full.end_with?('::') ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
package_completions(result)
|
178
|
+
end
|
179
|
+
|
180
|
+
def code_complete
|
181
|
+
result = []
|
182
|
+
result.concat complete_keyword_parameters
|
183
|
+
if cursor.chain.constant? || cursor.start_of_constant?
|
184
|
+
full = cursor.chain.links.first.word
|
185
|
+
type = if cursor.chain.undefined?
|
186
|
+
cursor.chain.base.infer(api_map, context_pin, locals)
|
187
|
+
else
|
188
|
+
if full.include?('::') && cursor.chain.links.length == 1
|
189
|
+
ComplexType.try_parse(full.split('::')[0..-2].join('::'))
|
190
|
+
elsif cursor.chain.links.length > 1
|
191
|
+
ComplexType.try_parse(full)
|
192
|
+
else
|
193
|
+
ComplexType::UNDEFINED
|
194
|
+
end
|
195
|
+
end
|
196
|
+
if type.undefined?
|
197
|
+
if full.include?('::')
|
198
|
+
result.concat api_map.get_constants(full, *gates)
|
199
|
+
else
|
200
|
+
result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
|
201
|
+
end
|
202
|
+
else
|
203
|
+
result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
|
204
|
+
end
|
205
|
+
else
|
206
|
+
type = cursor.chain.base.infer(api_map, block, locals)
|
207
|
+
result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
|
208
|
+
if cursor.chain.links.length == 1
|
209
|
+
if cursor.word.start_with?('@@')
|
210
|
+
return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
|
211
|
+
elsif cursor.word.start_with?('@')
|
212
|
+
return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
|
213
|
+
elsif cursor.word.start_with?('$')
|
214
|
+
return package_completions(api_map.get_global_variable_pins)
|
215
|
+
end
|
216
|
+
result.concat locals
|
217
|
+
result.concat api_map.get_constants(context_pin.context.namespace, *gates)
|
218
|
+
result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
|
219
|
+
result.concat api_map.get_methods('Kernel')
|
220
|
+
# result.concat ApiMap.keywords
|
221
|
+
result.concat api_map.keyword_pins.to_a
|
222
|
+
result.concat yielded_self_pins
|
223
|
+
end
|
224
|
+
end
|
225
|
+
package_completions(result)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
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,241 @@
|
|
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|@\!visibility|@\!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
|
+
@pins.each { |p| p.source = :code }
|
28
|
+
@locals.each { |l| l.source = :code }
|
29
|
+
process_comment_directives
|
30
|
+
[@pins, @locals]
|
31
|
+
# rescue Exception => e
|
32
|
+
# Solargraph.logger.warn "Error mapping #{source.filename}: [#{e.class}] #{e.message}"
|
33
|
+
# Solargraph.logger.warn e.backtrace.join("\n")
|
34
|
+
# [[], []]
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param filename [String]
|
38
|
+
# @param code [String]
|
39
|
+
# @return [Array]
|
40
|
+
def unmap filename, code
|
41
|
+
s = Position.new(0, 0)
|
42
|
+
e = Position.from_offset(code, code.length)
|
43
|
+
location = Location.new(filename, Range.new(s, e))
|
44
|
+
[[Pin::Namespace.new(location: location, name: '')], []]
|
45
|
+
end
|
46
|
+
|
47
|
+
class << self
|
48
|
+
# @param source [Source]
|
49
|
+
# @return [Array]
|
50
|
+
def map source
|
51
|
+
return new.unmap(source.filename, source.code) unless source.parsed?
|
52
|
+
new.map source
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Array<Solargraph::Pin::Base>]
|
57
|
+
def pins
|
58
|
+
@pins ||= []
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param position [Solargraph::Position]
|
62
|
+
# @return [Solargraph::Pin::Closure]
|
63
|
+
def closure_at(position)
|
64
|
+
pins.select{|pin| pin.is_a?(Pin::Closure) and pin.location.range.contain?(position)}.last
|
65
|
+
end
|
66
|
+
|
67
|
+
def process_comment source_position, comment_position, comment
|
68
|
+
return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ MACRO_REGEXP
|
69
|
+
cmnt = remove_inline_comment_hashes(comment)
|
70
|
+
parse = Solargraph::Source.parse_docstring(cmnt)
|
71
|
+
last_line = 0
|
72
|
+
# @param d [YARD::Tags::Directive]
|
73
|
+
parse.directives.each do |d|
|
74
|
+
line_num = find_directive_line_number(cmnt, d.tag.tag_name, last_line)
|
75
|
+
pos = Solargraph::Position.new(comment_position.line + line_num - 1, comment_position.column)
|
76
|
+
process_directive(source_position, pos, d)
|
77
|
+
last_line = line_num + 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param comment [String]
|
82
|
+
# @return [Integer]
|
83
|
+
def find_directive_line_number comment, tag, start
|
84
|
+
# Avoid overruning the index
|
85
|
+
return start unless start < comment.lines.length
|
86
|
+
num = comment.lines[start..-1].find_index do |line|
|
87
|
+
# Legacy method directives might be `@method` instead of `@!method`
|
88
|
+
# @todo Legacy syntax should probably emit a warning
|
89
|
+
line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
|
90
|
+
end
|
91
|
+
num.to_i + start
|
92
|
+
end
|
93
|
+
|
94
|
+
# @param source_position [Position]
|
95
|
+
# @param comment_position [Position]
|
96
|
+
# @param directive [YARD::Tags::Directive]
|
97
|
+
# @return [void]
|
98
|
+
def process_directive source_position, comment_position, directive
|
99
|
+
docstring = Solargraph::Source.parse_docstring(directive.tag.text).to_docstring
|
100
|
+
location = Location.new(@filename, Range.new(comment_position, comment_position))
|
101
|
+
case directive.tag.tag_name
|
102
|
+
when 'method'
|
103
|
+
namespace = closure_at(source_position) || @pins.first
|
104
|
+
if namespace.location.range.start.line < comment_position.line
|
105
|
+
namespace = closure_at(comment_position)
|
106
|
+
end
|
107
|
+
begin
|
108
|
+
src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
|
109
|
+
region = Parser::Region.new(source: src, closure: namespace)
|
110
|
+
gen_pin = Parser.process_node(src.node, region).first.last
|
111
|
+
return if gen_pin.nil?
|
112
|
+
# Move the location to the end of the line so it gets recognized
|
113
|
+
# as originating from a comment
|
114
|
+
shifted = Solargraph::Position.new(comment_position.line, @code.lines[comment_position.line].to_s.chomp.length)
|
115
|
+
# @todo: Smelly instance variable access
|
116
|
+
gen_pin.instance_variable_set(:@comments, docstring.all.to_s)
|
117
|
+
gen_pin.instance_variable_set(:@location, Solargraph::Location.new(@filename, Range.new(shifted, shifted)))
|
118
|
+
gen_pin.instance_variable_set(:@explicit, false)
|
119
|
+
@pins.push gen_pin
|
120
|
+
rescue Parser::SyntaxError => e
|
121
|
+
# @todo Handle error in directive
|
122
|
+
end
|
123
|
+
when 'attribute'
|
124
|
+
return if directive.tag.name.nil?
|
125
|
+
namespace = closure_at(source_position)
|
126
|
+
t = (directive.tag.types.nil? || directive.tag.types.empty?) ? nil : directive.tag.types.flatten.join('')
|
127
|
+
if t.nil? || t.include?('r')
|
128
|
+
pins.push Solargraph::Pin::Method.new(
|
129
|
+
location: location,
|
130
|
+
closure: namespace,
|
131
|
+
name: directive.tag.name,
|
132
|
+
comments: docstring.all.to_s,
|
133
|
+
scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
|
134
|
+
visibility: :public,
|
135
|
+
explicit: false,
|
136
|
+
attribute: true
|
137
|
+
)
|
138
|
+
end
|
139
|
+
if t.nil? || t.include?('w')
|
140
|
+
pins.push Solargraph::Pin::Method.new(
|
141
|
+
location: location,
|
142
|
+
closure: namespace,
|
143
|
+
name: "#{directive.tag.name}=",
|
144
|
+
comments: docstring.all.to_s,
|
145
|
+
scope: namespace.is_a?(Pin::Singleton) ? :class : :instance,
|
146
|
+
visibility: :public,
|
147
|
+
attribute: true
|
148
|
+
)
|
149
|
+
pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
|
150
|
+
if pins.last.return_type.defined?
|
151
|
+
pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
when 'visibility'
|
155
|
+
begin
|
156
|
+
kind = directive.tag.text&.to_sym
|
157
|
+
return unless [:private, :protected, :public].include?(kind)
|
158
|
+
|
159
|
+
name = directive.tag.name
|
160
|
+
closure = closure_at(source_position) || @pins.first
|
161
|
+
if closure.location.range.start.line < comment_position.line
|
162
|
+
closure = closure_at(comment_position)
|
163
|
+
end
|
164
|
+
if closure.is_a?(Pin::Method) && no_empty_lines?(comment_position.line, source_position.line)
|
165
|
+
# @todo Smelly instance variable access
|
166
|
+
closure.instance_variable_set(:@visibility, kind)
|
167
|
+
else
|
168
|
+
matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == namespace && pin.context.scope == namespace.is_a?(Pin::Singleton) ? :class : :instance }
|
169
|
+
matches.each do |pin|
|
170
|
+
# @todo Smelly instance variable access
|
171
|
+
pin.instance_variable_set(:@visibility, kind)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
when 'parse'
|
176
|
+
begin
|
177
|
+
ns = closure_at(source_position)
|
178
|
+
src = Solargraph::Source.load_string(directive.tag.text, @source.filename)
|
179
|
+
region = Parser::Region.new(source: src, closure: ns)
|
180
|
+
# @todo These pins may need to be marked not explicit
|
181
|
+
index = @pins.length
|
182
|
+
loff = if @code.lines[comment_position.line].strip.end_with?('@!parse')
|
183
|
+
comment_position.line + 1
|
184
|
+
else
|
185
|
+
comment_position.line
|
186
|
+
end
|
187
|
+
Parser.process_node(src.node, region, @pins)
|
188
|
+
@pins[index..-1].each do |p|
|
189
|
+
# @todo Smelly instance variable access
|
190
|
+
p.location.range.start.instance_variable_set(:@line, p.location.range.start.line + loff)
|
191
|
+
p.location.range.ending.instance_variable_set(:@line, p.location.range.ending.line + loff)
|
192
|
+
end
|
193
|
+
rescue Parser::SyntaxError => e
|
194
|
+
# @todo Handle parser errors in !parse directives
|
195
|
+
end
|
196
|
+
when 'domain'
|
197
|
+
namespace = closure_at(source_position) || Pin::ROOT_PIN
|
198
|
+
namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
|
199
|
+
when 'override'
|
200
|
+
pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def no_empty_lines?(line1, line2)
|
205
|
+
@code.lines[line1..line2].none? { |line| line.strip.empty? }
|
206
|
+
end
|
207
|
+
|
208
|
+
def remove_inline_comment_hashes comment
|
209
|
+
ctxt = ''
|
210
|
+
num = nil
|
211
|
+
started = false
|
212
|
+
comment.lines.each { |l|
|
213
|
+
# Trim the comment and minimum leading whitespace
|
214
|
+
p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#/, '')
|
215
|
+
if num.nil? && !p.strip.empty?
|
216
|
+
num = p.index(/[^ ]/)
|
217
|
+
started = true
|
218
|
+
elsif started && !p.strip.empty?
|
219
|
+
cur = p.index(/[^ ]/)
|
220
|
+
num = cur if cur < num
|
221
|
+
end
|
222
|
+
ctxt += "#{p[num..-1]}" if started
|
223
|
+
}
|
224
|
+
ctxt
|
225
|
+
end
|
226
|
+
|
227
|
+
# @return [void]
|
228
|
+
def process_comment_directives
|
229
|
+
return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ MACRO_REGEXP
|
230
|
+
code_lines = @code.lines
|
231
|
+
@source.associated_comments.each do |line, comments|
|
232
|
+
src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
|
233
|
+
com_pos = Position.new(line + 1 - comments.lines.length, 0)
|
234
|
+
process_comment(src_pos, com_pos, comments)
|
235
|
+
end
|
236
|
+
rescue StandardError => e
|
237
|
+
raise e.class, "Error processing comment directives in #{@filename}: #{e.message}"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yard'
|
4
|
+
require 'yard-solargraph'
|
5
|
+
require 'set'
|
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_local(self) unless filename.nil?
|
33
|
+
@pin_class_hash = pins.to_set.classify(&:class).transform_values(&:to_a)
|
34
|
+
@pin_select_cache = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def pins_by_class klass
|
38
|
+
@pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
|
39
|
+
end
|
40
|
+
|
41
|
+
def rebindable_method_names
|
42
|
+
@rebindable_method_names ||= pins_by_class(Pin::Method)
|
43
|
+
.select { |pin| pin.comments && pin.comments.include?('@yieldself') }
|
44
|
+
.map(&:name)
|
45
|
+
.to_set
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [String]
|
49
|
+
def filename
|
50
|
+
source.filename
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [String]
|
54
|
+
def code
|
55
|
+
source.code
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Array<Pin::Reference::Require>]
|
59
|
+
def requires
|
60
|
+
pins_by_class(Pin::Reference::Require)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Environ]
|
64
|
+
def environ
|
65
|
+
@environ ||= Environ.new
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Array<Pin::Base>]
|
69
|
+
def document_symbols
|
70
|
+
@document_symbols ||= pins.select { |pin|
|
71
|
+
pin.path && !pin.path.empty?
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param query [String]
|
76
|
+
# @return [Array<Pin::Base>]
|
77
|
+
def query_symbols query
|
78
|
+
Pin::Search.new(document_symbols, query).results
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param position [Position]
|
82
|
+
# @return [Source::Cursor]
|
83
|
+
def cursor_at position
|
84
|
+
Source::Cursor.new(source, position)
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param path [String]
|
88
|
+
# @return [Pin::Base]
|
89
|
+
def first_pin path
|
90
|
+
pins.select { |p| p.path == path }.first
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param location [Solargraph::Location]
|
94
|
+
# @return [Array<Solargraph::Pin::Base>]
|
95
|
+
def locate_pins location
|
96
|
+
# return nil unless location.start_with?("#{filename}:")
|
97
|
+
(pins + locals).select { |pin| pin.location == location }
|
98
|
+
end
|
99
|
+
|
100
|
+
def locate_named_path_pin line, character
|
101
|
+
_locate_pin line, character, Pin::Namespace, Pin::Method
|
102
|
+
end
|
103
|
+
|
104
|
+
def locate_block_pin line, character
|
105
|
+
_locate_pin line, character, Pin::Namespace, Pin::Method, Pin::Block
|
106
|
+
end
|
107
|
+
|
108
|
+
# @param other_map [SourceMap]
|
109
|
+
# @return [Boolean]
|
110
|
+
def try_merge! other_map
|
111
|
+
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
|
112
|
+
pins.each_index do |i|
|
113
|
+
return false unless pins[i].try_merge!(other_map.pins[i])
|
114
|
+
end
|
115
|
+
locals.each_index do |i|
|
116
|
+
return false unless locals[i].try_merge!(other_map.locals[i])
|
117
|
+
end
|
118
|
+
@source = other_map.source
|
119
|
+
true
|
120
|
+
end
|
121
|
+
|
122
|
+
# @param name [String]
|
123
|
+
# @return [Array<Location>]
|
124
|
+
def references name
|
125
|
+
source.references name
|
126
|
+
end
|
127
|
+
|
128
|
+
# @param location [Location]
|
129
|
+
# @return [Array<Pin::LocalVariable>]
|
130
|
+
def locals_at(location)
|
131
|
+
return [] if location.filename != filename
|
132
|
+
closure = locate_named_path_pin(location.range.start.line, location.range.start.character)
|
133
|
+
locals.select { |pin| pin.visible_at?(closure, location) }
|
134
|
+
end
|
135
|
+
|
136
|
+
class << self
|
137
|
+
# @param filename [String]
|
138
|
+
# @return [SourceMap]
|
139
|
+
def load filename
|
140
|
+
source = Solargraph::Source.load(filename)
|
141
|
+
SourceMap.map(source)
|
142
|
+
end
|
143
|
+
|
144
|
+
# @param code [String]
|
145
|
+
# @param filename [String, nil]
|
146
|
+
# @return [SourceMap]
|
147
|
+
def load_string code, filename = nil
|
148
|
+
source = Solargraph::Source.load_string(code, filename)
|
149
|
+
SourceMap.map(source)
|
150
|
+
end
|
151
|
+
|
152
|
+
# @param source [Source]
|
153
|
+
# @return [SourceMap]
|
154
|
+
def map source
|
155
|
+
result = SourceMap::Mapper.map(source)
|
156
|
+
new(source, *result)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
# @param line [Integer]
|
163
|
+
# @param character [Integer]
|
164
|
+
# @param klasses [Array<Class>]
|
165
|
+
# @return [Pin::Base]
|
166
|
+
def _locate_pin line, character, *klasses
|
167
|
+
position = Position.new(line, character)
|
168
|
+
found = nil
|
169
|
+
pins.each do |pin|
|
170
|
+
# @todo Attribute pins should not be treated like closures, but
|
171
|
+
# there's probably a better way to handle it
|
172
|
+
next if pin.is_a?(Pin::Method) && pin.attribute?
|
173
|
+
found = pin if (klasses.empty? || klasses.any? { |kls| pin.is_a?(kls) } ) && pin.location.range.contain?(position)
|
174
|
+
break if pin.location.range.start.line > line
|
175
|
+
end
|
176
|
+
# Assuming the root pin is always valid
|
177
|
+
found || pins.first
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|