solargraph 0.46.0 → 0.54.5
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 +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +37 -41
- data/.github/workflows/typecheck.yml +34 -0
- data/.gitignore +9 -9
- data/.rspec +2 -2
- data/.yardopts +2 -2
- data/CHANGELOG.md +1338 -1115
- data/Gemfile +0 -0
- data/LICENSE +1 -1
- data/README.md +131 -128
- data/Rakefile +0 -0
- data/SPONSORS.md +10 -18
- data/bin/solargraph +0 -0
- data/lib/solargraph/api_map/cache.rb +109 -70
- data/lib/solargraph/api_map/index.rb +167 -0
- data/lib/solargraph/api_map/source_to_yard.rb +88 -81
- data/lib/solargraph/api_map/store.rb +260 -256
- data/lib/solargraph/api_map.rb +870 -686
- data/lib/solargraph/bench.rb +44 -27
- data/lib/solargraph/cache.rb +77 -0
- data/lib/solargraph/complex_type/type_methods.rb +217 -130
- data/lib/solargraph/complex_type/unique_type.rb +386 -75
- data/lib/solargraph/complex_type.rb +394 -221
- data/lib/solargraph/convention/base.rb +33 -33
- data/lib/solargraph/convention/gemfile.rb +15 -15
- data/lib/solargraph/convention/gemspec.rb +22 -22
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +47 -47
- data/lib/solargraph/converters/dd.rb +17 -12
- data/lib/solargraph/converters/dl.rb +15 -12
- data/lib/solargraph/converters/dt.rb +15 -12
- data/lib/solargraph/converters/misc.rb +1 -1
- data/lib/solargraph/diagnostics/base.rb +29 -29
- data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
- data/lib/solargraph/diagnostics/rubocop.rb +113 -98
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +66 -63
- data/lib/solargraph/diagnostics/severities.rb +15 -15
- data/lib/solargraph/diagnostics/type_check.rb +55 -54
- data/lib/solargraph/diagnostics/update_errors.rb +41 -41
- data/lib/solargraph/diagnostics.rb +55 -55
- data/lib/solargraph/doc_map.rb +188 -0
- data/lib/solargraph/environ.rb +45 -45
- data/lib/solargraph/equality.rb +33 -0
- data/lib/solargraph/gem_pins.rb +72 -0
- data/lib/solargraph/language_server/completion_item_kinds.rb +35 -35
- data/lib/solargraph/language_server/error_codes.rb +20 -20
- data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
- data/lib/solargraph/language_server/host/dispatch.rb +128 -111
- data/lib/solargraph/language_server/host/message_worker.rb +106 -59
- data/lib/solargraph/language_server/host/sources.rb +99 -156
- data/lib/solargraph/language_server/host.rb +861 -865
- data/lib/solargraph/language_server/message/base.rb +96 -89
- data/lib/solargraph/language_server/message/cancel_request.rb +13 -13
- data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
- data/lib/solargraph/language_server/message/client.rb +11 -11
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -58
- data/lib/solargraph/language_server/message/completion_item.rb +11 -11
- data/lib/solargraph/language_server/message/exit_notification.rb +13 -13
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +112 -100
- data/lib/solargraph/language_server/message/extended/document.rb +20 -20
- data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
- data/lib/solargraph/language_server/message/extended/download_core.rb +19 -23
- data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
- data/lib/solargraph/language_server/message/extended/search.rb +20 -20
- data/lib/solargraph/language_server/message/extended.rb +21 -21
- data/lib/solargraph/language_server/message/initialize.rb +191 -162
- data/lib/solargraph/language_server/message/initialized.rb +28 -27
- data/lib/solargraph/language_server/message/method_not_found.rb +16 -16
- data/lib/solargraph/language_server/message/method_not_implemented.rb +14 -14
- data/lib/solargraph/language_server/message/shutdown.rb +13 -13
- data/lib/solargraph/language_server/message/text_document/base.rb +19 -19
- data/lib/solargraph/language_server/message/text_document/code_action.rb +17 -17
- data/lib/solargraph/language_server/message/text_document/completion.rb +56 -59
- data/lib/solargraph/language_server/message/text_document/definition.rb +38 -38
- data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -15
- data/lib/solargraph/language_server/message/text_document/did_close.rb +15 -15
- data/lib/solargraph/language_server/message/text_document/did_open.rb +15 -15
- data/lib/solargraph/language_server/message/text_document/did_save.rb +17 -17
- data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -23
- data/lib/solargraph/language_server/message/text_document/folding_range.rb +26 -26
- data/lib/solargraph/language_server/message/text_document/formatting.rb +131 -126
- data/lib/solargraph/language_server/message/text_document/hover.rb +58 -54
- data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +34 -34
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
- data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
- data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -29
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +24 -0
- data/lib/solargraph/language_server/message/text_document.rb +28 -28
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -30
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -33
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
- data/lib/solargraph/language_server/message/workspace.rb +14 -14
- data/lib/solargraph/language_server/message.rb +94 -93
- data/lib/solargraph/language_server/message_types.rb +14 -14
- data/lib/solargraph/language_server/progress.rb +135 -0
- data/lib/solargraph/language_server/request.rb +24 -24
- data/lib/solargraph/language_server/symbol_kinds.rb +36 -36
- data/lib/solargraph/language_server/transport/adapter.rb +68 -53
- data/lib/solargraph/language_server/transport/data_reader.rb +74 -72
- data/lib/solargraph/language_server/transport.rb +13 -13
- data/lib/solargraph/language_server/uri_helpers.rb +49 -49
- data/lib/solargraph/language_server.rb +20 -19
- data/lib/solargraph/library.rb +663 -546
- data/lib/solargraph/location.rb +58 -37
- data/lib/solargraph/logging.rb +27 -27
- data/lib/solargraph/page.rb +89 -83
- data/lib/solargraph/parser/comment_ripper.rb +56 -52
- data/lib/solargraph/parser/node_methods.rb +83 -43
- data/lib/solargraph/parser/node_processor/base.rb +87 -77
- data/lib/solargraph/parser/node_processor.rb +45 -43
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +153 -135
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +18 -16
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +164 -148
- data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +23 -23
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +15 -15
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +43 -42
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +35 -25
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +23 -23
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/def_node.rb +50 -63
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +36 -36
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +23 -23
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +38 -38
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +28 -28
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +39 -39
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +16 -16
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +36 -36
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +42 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +259 -257
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sym_node.rb +18 -18
- data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/region.rb +66 -66
- data/lib/solargraph/parser/snippet.rb +15 -13
- data/lib/solargraph/parser.rb +22 -26
- data/lib/solargraph/pin/base.rb +378 -296
- data/lib/solargraph/pin/base_variable.rb +118 -84
- data/lib/solargraph/pin/block.rb +101 -72
- data/lib/solargraph/pin/callable.rb +147 -0
- data/lib/solargraph/pin/class_variable.rb +8 -8
- data/lib/solargraph/pin/closure.rb +57 -37
- data/lib/solargraph/pin/common.rb +70 -70
- data/lib/solargraph/pin/constant.rb +43 -43
- data/lib/solargraph/pin/conversions.rb +123 -96
- data/lib/solargraph/pin/delegated_method.rb +101 -0
- data/lib/solargraph/pin/documenting.rb +98 -105
- data/lib/solargraph/pin/duck_method.rb +16 -16
- data/lib/solargraph/pin/global_variable.rb +8 -8
- data/lib/solargraph/pin/instance_variable.rb +34 -30
- data/lib/solargraph/pin/keyword.rb +15 -15
- data/lib/solargraph/pin/keyword_param.rb +8 -8
- data/lib/solargraph/pin/local_variable.rb +67 -55
- data/lib/solargraph/pin/method.rb +527 -245
- data/lib/solargraph/pin/method_alias.rb +31 -31
- data/lib/solargraph/pin/namespace.rb +107 -91
- data/lib/solargraph/pin/parameter.rb +212 -201
- data/lib/solargraph/pin/proxy_type.rb +29 -29
- data/lib/solargraph/pin/reference/extend.rb +10 -10
- data/lib/solargraph/pin/reference/include.rb +10 -10
- data/lib/solargraph/pin/reference/override.rb +29 -29
- data/lib/solargraph/pin/reference/prepend.rb +10 -10
- data/lib/solargraph/pin/reference/require.rb +14 -14
- data/lib/solargraph/pin/reference/superclass.rb +10 -10
- data/lib/solargraph/pin/reference.rb +22 -14
- data/lib/solargraph/pin/search.rb +56 -56
- data/lib/solargraph/pin/signature.rb +17 -0
- data/lib/solargraph/pin/singleton.rb +11 -11
- data/lib/solargraph/pin/symbol.rb +47 -47
- data/lib/solargraph/pin.rb +41 -37
- data/lib/solargraph/position.rb +107 -100
- data/lib/solargraph/range.rb +98 -95
- data/lib/solargraph/rbs_map/conversions.rb +646 -0
- data/lib/solargraph/rbs_map/core_fills.rb +50 -0
- data/lib/solargraph/rbs_map/core_map.rb +28 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +33 -0
- data/lib/solargraph/rbs_map.rb +93 -0
- data/lib/solargraph/server_methods.rb +16 -16
- data/lib/solargraph/shell.rb +269 -226
- data/lib/solargraph/source/chain/array.rb +33 -0
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/block_variable.rb +13 -13
- data/lib/solargraph/source/chain/call.rb +303 -204
- data/lib/solargraph/source/chain/class_variable.rb +13 -13
- data/lib/solargraph/source/chain/constant.rb +89 -75
- data/lib/solargraph/source/chain/global_variable.rb +13 -13
- data/lib/solargraph/source/chain/hash.rb +33 -28
- data/lib/solargraph/source/chain/head.rb +19 -19
- data/lib/solargraph/source/chain/if.rb +28 -0
- data/lib/solargraph/source/chain/instance_variable.rb +13 -13
- data/lib/solargraph/source/chain/link.rb +98 -71
- data/lib/solargraph/source/chain/literal.rb +28 -23
- data/lib/solargraph/source/chain/or.rb +23 -23
- data/lib/solargraph/source/chain/q_call.rb +11 -11
- data/lib/solargraph/source/chain/variable.rb +13 -13
- data/lib/solargraph/source/chain/z_super.rb +30 -30
- data/lib/solargraph/source/chain.rb +252 -164
- data/lib/solargraph/source/change.rb +82 -79
- data/lib/solargraph/source/cursor.rb +167 -164
- data/lib/solargraph/source/source_chainer.rb +194 -191
- data/lib/solargraph/source/updater.rb +55 -54
- data/lib/solargraph/source.rb +495 -522
- data/lib/solargraph/source_map/clip.rb +232 -224
- data/lib/solargraph/source_map/completion.rb +23 -23
- data/lib/solargraph/source_map/data.rb +30 -0
- data/lib/solargraph/source_map/mapper.rb +255 -212
- data/lib/solargraph/source_map.rb +217 -180
- data/lib/solargraph/type_checker/checks.rb +120 -99
- data/lib/solargraph/type_checker/param_def.rb +35 -35
- data/lib/solargraph/type_checker/problem.rb +32 -32
- data/lib/solargraph/type_checker/rules.rb +62 -57
- data/lib/solargraph/type_checker.rb +672 -543
- data/lib/solargraph/version.rb +5 -5
- data/lib/solargraph/views/environment.erb +56 -58
- data/lib/solargraph/workspace/config.rb +239 -231
- data/lib/solargraph/workspace.rb +239 -215
- data/lib/solargraph/yard_map/cache.rb +25 -19
- data/lib/solargraph/yard_map/helpers.rb +16 -16
- data/lib/solargraph/yard_map/mapper/to_constant.rb +26 -25
- data/lib/solargraph/yard_map/mapper/to_method.rb +94 -78
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +28 -27
- data/lib/solargraph/yard_map/mapper.rb +78 -77
- data/lib/solargraph/yard_map/to_method.rb +86 -79
- data/lib/solargraph/yard_map.rb +18 -460
- data/lib/solargraph/yard_tags.rb +20 -0
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +72 -69
- data/solargraph.gemspec +21 -10
- metadata +184 -115
- data/.travis.yml +0 -19
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/convention/rspec.rb +0 -30
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/language_server/host/cataloger.rb +0 -56
- data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -35
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/def_node.rb +0 -63
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -54
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -144
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -315
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -22
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -57
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -45
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -21
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -277
- data/lib/solargraph/parser/rubyvm/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -63
- data/lib/solargraph/parser/rubyvm.rb +0 -40
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/lib/yard-solargraph.rb +0 -33
- data/yardoc/2.2.2.tar.gz +0 -0
data/lib/solargraph/library.rb
CHANGED
@@ -1,546 +1,663 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
#
|
73
|
-
#
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# True if the specified file
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
#
|
157
|
-
#
|
158
|
-
# @
|
159
|
-
# @
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
# @param
|
175
|
-
# @
|
176
|
-
# @
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
cursor
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
clip
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
# @param
|
207
|
-
# @
|
208
|
-
# @
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
#
|
221
|
-
#
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
#
|
296
|
-
#
|
297
|
-
# @
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
# @
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
#
|
336
|
-
# @
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
end
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
def
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
end
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
#
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
# @return [
|
506
|
-
def
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'observer'
|
5
|
+
|
6
|
+
module Solargraph
|
7
|
+
# A Library handles coordination between a Workspace and an ApiMap.
|
8
|
+
#
|
9
|
+
class Library
|
10
|
+
include Logging
|
11
|
+
include Observable
|
12
|
+
|
13
|
+
# @return [Solargraph::Workspace]
|
14
|
+
attr_reader :workspace
|
15
|
+
|
16
|
+
# @return [String, nil]
|
17
|
+
attr_reader :name
|
18
|
+
|
19
|
+
# @return [Source, nil]
|
20
|
+
attr_reader :current
|
21
|
+
|
22
|
+
# @return [LanguageServer::Progress, nil]
|
23
|
+
attr_reader :cache_progress
|
24
|
+
|
25
|
+
# @param workspace [Solargraph::Workspace]
|
26
|
+
# @param name [String, nil]
|
27
|
+
def initialize workspace = Solargraph::Workspace.new, name = nil
|
28
|
+
@workspace = workspace
|
29
|
+
@name = name
|
30
|
+
# @type [Integer, nil]
|
31
|
+
@total = nil
|
32
|
+
# @type [Source, nil]
|
33
|
+
@current = nil
|
34
|
+
@sync_count = 0
|
35
|
+
end
|
36
|
+
|
37
|
+
def inspect
|
38
|
+
# Let's not deal with insane data dumps in spec failures
|
39
|
+
to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
# True if the ApiMap is up to date with the library's workspace and open
|
43
|
+
# files.
|
44
|
+
#
|
45
|
+
# @return [Boolean]
|
46
|
+
def synchronized?
|
47
|
+
@sync_count < 2
|
48
|
+
end
|
49
|
+
|
50
|
+
# Attach a source to the library.
|
51
|
+
#
|
52
|
+
# The attached source does not need to be a part of the workspace. The
|
53
|
+
# library will include it in the ApiMap while it's attached. Only one
|
54
|
+
# source can be attached to the library at a time.
|
55
|
+
#
|
56
|
+
# @param source [Source, nil]
|
57
|
+
# @return [void]
|
58
|
+
def attach source
|
59
|
+
if @current && (!source || @current.filename != source.filename) && source_map_hash.key?(@current.filename) && !workspace.has_file?(@current.filename)
|
60
|
+
source_map_hash.delete @current.filename
|
61
|
+
source_map_external_require_hash.delete @current.filename
|
62
|
+
@external_requires = nil
|
63
|
+
end
|
64
|
+
changed = source && @current != source
|
65
|
+
@current = source
|
66
|
+
maybe_map @current
|
67
|
+
catalog if changed
|
68
|
+
end
|
69
|
+
|
70
|
+
# True if the specified file is currently attached.
|
71
|
+
#
|
72
|
+
# @param filename [String]
|
73
|
+
# @return [Boolean]
|
74
|
+
def attached? filename
|
75
|
+
!@current.nil? && @current.filename == filename
|
76
|
+
end
|
77
|
+
alias open? attached?
|
78
|
+
|
79
|
+
# Detach the specified file if it is currently attached to the library.
|
80
|
+
#
|
81
|
+
# @param filename [String]
|
82
|
+
# @return [Boolean] True if the specified file was detached
|
83
|
+
def detach filename
|
84
|
+
return false if @current.nil? || @current.filename != filename
|
85
|
+
attach nil
|
86
|
+
true
|
87
|
+
end
|
88
|
+
|
89
|
+
# True if the specified file is included in the workspace (but not
|
90
|
+
# necessarily open).
|
91
|
+
#
|
92
|
+
# @param filename [String]
|
93
|
+
# @return [Boolean]
|
94
|
+
def contain? filename
|
95
|
+
workspace.has_file?(filename)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Create a source to be added to the workspace. The file is ignored if it is
|
99
|
+
# neither open in the library nor included in the workspace.
|
100
|
+
#
|
101
|
+
# @param filename [String]
|
102
|
+
# @param text [String] The contents of the file
|
103
|
+
# @return [Boolean] True if the file was added to the workspace.
|
104
|
+
def create filename, text
|
105
|
+
return false unless contain?(filename) || open?(filename)
|
106
|
+
source = Solargraph::Source.load_string(text, filename)
|
107
|
+
workspace.merge(source)
|
108
|
+
true
|
109
|
+
end
|
110
|
+
|
111
|
+
# Create file sources from files on disk. A file is ignored if it is
|
112
|
+
# neither open in the library nor included in the workspace.
|
113
|
+
#
|
114
|
+
# @param filenames [Array<String>]
|
115
|
+
# @return [Boolean] True if at least one file was added to the workspace.
|
116
|
+
def create_from_disk *filenames
|
117
|
+
sources = filenames
|
118
|
+
.reject { |filename| File.directory?(filename) || !File.exist?(filename) }
|
119
|
+
.map { |filename| Solargraph::Source.load_string(File.read(filename), filename) }
|
120
|
+
result = workspace.merge(*sources)
|
121
|
+
sources.each { |source| maybe_map source }
|
122
|
+
result
|
123
|
+
end
|
124
|
+
|
125
|
+
# Delete files from the library. Deleting a file will make it unavailable
|
126
|
+
# for checkout and optionally remove it from the workspace unless the
|
127
|
+
# workspace configuration determines that it should still exist.
|
128
|
+
#
|
129
|
+
# @param filenames [Array<String>]
|
130
|
+
# @return [Boolean] True if any file was deleted
|
131
|
+
def delete *filenames
|
132
|
+
result = false
|
133
|
+
filenames.each do |filename|
|
134
|
+
detach filename
|
135
|
+
source_map_hash.delete(filename)
|
136
|
+
result ||= workspace.remove(filename)
|
137
|
+
end
|
138
|
+
result
|
139
|
+
end
|
140
|
+
|
141
|
+
# Close a file in the library. Closing a file will make it unavailable for
|
142
|
+
# checkout although it may still exist in the workspace.
|
143
|
+
#
|
144
|
+
# @param filename [String]
|
145
|
+
# @return [void]
|
146
|
+
def close filename
|
147
|
+
return unless @current&.filename == filename
|
148
|
+
|
149
|
+
@current = nil
|
150
|
+
catalog unless workspace.has_file?(filename)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Get completion suggestions at the specified file and location.
|
154
|
+
#
|
155
|
+
# @param filename [String] The file to analyze
|
156
|
+
# @param line [Integer] The zero-based line number
|
157
|
+
# @param column [Integer] The zero-based column number
|
158
|
+
# @return [SourceMap::Completion, nil]
|
159
|
+
# @todo Take a Location instead of filename/line/column
|
160
|
+
def completions_at filename, line, column
|
161
|
+
sync_catalog
|
162
|
+
position = Position.new(line, column)
|
163
|
+
cursor = Source::Cursor.new(read(filename), position)
|
164
|
+
mutex.synchronize { api_map.clip(cursor).complete }
|
165
|
+
rescue FileNotFoundError => e
|
166
|
+
handle_file_not_found filename, e
|
167
|
+
end
|
168
|
+
|
169
|
+
# Get definition suggestions for the expression at the specified file and
|
170
|
+
# location.
|
171
|
+
#
|
172
|
+
# @param filename [String] The file to analyze
|
173
|
+
# @param line [Integer] The zero-based line number
|
174
|
+
# @param column [Integer] The zero-based column number
|
175
|
+
# @return [Array<Solargraph::Pin::Base>, nil]
|
176
|
+
# @todo Take filename/position instead of filename/line/column
|
177
|
+
def definitions_at filename, line, column
|
178
|
+
sync_catalog
|
179
|
+
position = Position.new(line, column)
|
180
|
+
cursor = Source::Cursor.new(read(filename), position)
|
181
|
+
if cursor.comment?
|
182
|
+
source = read(filename)
|
183
|
+
offset = Solargraph::Position.to_offset(source.code, Solargraph::Position.new(line, column))
|
184
|
+
lft = source.code[0..offset-1].match(/\[[a-z0-9_:<, ]*?([a-z0-9_:]*)\z/i)
|
185
|
+
rgt = source.code[offset..-1].match(/^([a-z0-9_]*)(:[a-z0-9_:]*)?[\]>, ]/i)
|
186
|
+
if lft && rgt
|
187
|
+
tag = (lft[1] + rgt[1]).sub(/:+$/, '')
|
188
|
+
clip = mutex.synchronize { api_map.clip(cursor) }
|
189
|
+
clip.translate tag
|
190
|
+
else
|
191
|
+
[]
|
192
|
+
end
|
193
|
+
else
|
194
|
+
mutex.synchronize do
|
195
|
+
clip = api_map.clip(cursor)
|
196
|
+
clip.define.map { |pin| pin.realize(api_map) }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
rescue FileNotFoundError => e
|
200
|
+
handle_file_not_found(filename, e)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Get type definition suggestions for the expression at the specified file and
|
204
|
+
# location.
|
205
|
+
#
|
206
|
+
# @param filename [String] The file to analyze
|
207
|
+
# @param line [Integer] The zero-based line number
|
208
|
+
# @param column [Integer] The zero-based column number
|
209
|
+
# @return [Array<Solargraph::Pin::Base>, nil]
|
210
|
+
# @todo Take filename/position instead of filename/line/column
|
211
|
+
def type_definitions_at filename, line, column
|
212
|
+
sync_catalog
|
213
|
+
position = Position.new(line, column)
|
214
|
+
cursor = Source::Cursor.new(read(filename), position)
|
215
|
+
mutex.synchronize { api_map.clip(cursor).types }
|
216
|
+
rescue FileNotFoundError => e
|
217
|
+
handle_file_not_found filename, e
|
218
|
+
end
|
219
|
+
|
220
|
+
# Get signature suggestions for the method at the specified file and
|
221
|
+
# location.
|
222
|
+
#
|
223
|
+
# @param filename [String] The file to analyze
|
224
|
+
# @param line [Integer] The zero-based line number
|
225
|
+
# @param column [Integer] The zero-based column number
|
226
|
+
# @return [Array<Solargraph::Pin::Base>]
|
227
|
+
# @todo Take filename/position instead of filename/line/column
|
228
|
+
def signatures_at filename, line, column
|
229
|
+
sync_catalog
|
230
|
+
position = Position.new(line, column)
|
231
|
+
cursor = Source::Cursor.new(read(filename), position)
|
232
|
+
mutex.synchronize { api_map.clip(cursor).signify }
|
233
|
+
end
|
234
|
+
|
235
|
+
# @param filename [String]
|
236
|
+
# @param line [Integer]
|
237
|
+
# @param column [Integer]
|
238
|
+
# @param strip [Boolean] Strip special characters from variable names
|
239
|
+
# @param only [Boolean] Search for references in the current file only
|
240
|
+
# @return [Array<Solargraph::Location>]
|
241
|
+
# @todo Take a Location instead of filename/line/column
|
242
|
+
def references_from filename, line, column, strip: false, only: false
|
243
|
+
sync_catalog
|
244
|
+
cursor = Source::Cursor.new(read(filename), [line, column])
|
245
|
+
clip = mutex.synchronize { api_map.clip(cursor) }
|
246
|
+
pin = clip.define.first
|
247
|
+
return [] unless pin
|
248
|
+
result = []
|
249
|
+
files = if only
|
250
|
+
[api_map.source_map(filename)]
|
251
|
+
else
|
252
|
+
(workspace.sources + (@current ? [@current] : []))
|
253
|
+
end
|
254
|
+
files.uniq(&:filename).each do |source|
|
255
|
+
found = source.references(pin.name)
|
256
|
+
found.select! do |loc|
|
257
|
+
referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
|
258
|
+
referenced&.path == pin.path
|
259
|
+
end
|
260
|
+
if pin.path == 'Class#new'
|
261
|
+
caller = cursor.chain.base.infer(api_map, clip.send(:block), clip.locals).first
|
262
|
+
if caller.defined?
|
263
|
+
found.select! do |loc|
|
264
|
+
clip = api_map.clip_at(loc.filename, loc.range.start)
|
265
|
+
other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:block), clip.locals).first
|
266
|
+
caller == other
|
267
|
+
end
|
268
|
+
else
|
269
|
+
found.clear
|
270
|
+
end
|
271
|
+
end
|
272
|
+
# HACK: for language clients that exclude special characters from the start of variable names
|
273
|
+
if strip && match = cursor.word.match(/^[^a-z0-9_]+/i)
|
274
|
+
found.map! do |loc|
|
275
|
+
Solargraph::Location.new(loc.filename, Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line, loc.range.ending.column))
|
276
|
+
end
|
277
|
+
end
|
278
|
+
result.concat(found.sort do |a, b|
|
279
|
+
a.range.start.line <=> b.range.start.line
|
280
|
+
end)
|
281
|
+
end
|
282
|
+
result.uniq
|
283
|
+
end
|
284
|
+
|
285
|
+
# Get the pins at the specified location or nil if the pin does not exist.
|
286
|
+
#
|
287
|
+
# @param location [Location]
|
288
|
+
# @return [Array<Solargraph::Pin::Base>]
|
289
|
+
def locate_pins location
|
290
|
+
sync_catalog
|
291
|
+
mutex.synchronize { api_map.locate_pins(location).map { |pin| pin.realize(api_map) } }
|
292
|
+
end
|
293
|
+
|
294
|
+
# Match a require reference to a file.
|
295
|
+
#
|
296
|
+
# @param location [Location]
|
297
|
+
# @return [Location, nil]
|
298
|
+
def locate_ref location
|
299
|
+
map = source_map_hash[location.filename]
|
300
|
+
return if map.nil?
|
301
|
+
pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
|
302
|
+
return nil if pin.nil?
|
303
|
+
# @param full [String]
|
304
|
+
return_if_match = proc do |full|
|
305
|
+
if source_map_hash.key?(full)
|
306
|
+
return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
|
307
|
+
end
|
308
|
+
end
|
309
|
+
workspace.require_paths.each do |path|
|
310
|
+
full = File.join path, pin.name
|
311
|
+
return_if_match.(full)
|
312
|
+
return_if_match.(full << ".rb")
|
313
|
+
end
|
314
|
+
nil
|
315
|
+
rescue FileNotFoundError
|
316
|
+
nil
|
317
|
+
end
|
318
|
+
|
319
|
+
# Get an array of pins that match a path.
|
320
|
+
#
|
321
|
+
# @param path [String]
|
322
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
323
|
+
def get_path_pins path
|
324
|
+
sync_catalog
|
325
|
+
mutex.synchronize { api_map.get_path_suggestions(path) }
|
326
|
+
end
|
327
|
+
|
328
|
+
# @param query [String]
|
329
|
+
# @return [Enumerable<YARD::CodeObjects::Base>]
|
330
|
+
def document query
|
331
|
+
sync_catalog
|
332
|
+
mutex.synchronize { api_map.document query }
|
333
|
+
end
|
334
|
+
|
335
|
+
# @param query [String]
|
336
|
+
# @return [Array<String>]
|
337
|
+
def search query
|
338
|
+
sync_catalog
|
339
|
+
mutex.synchronize { api_map.search query }
|
340
|
+
end
|
341
|
+
|
342
|
+
# Get an array of all symbols in the workspace that match the query.
|
343
|
+
#
|
344
|
+
# @param query [String]
|
345
|
+
# @return [Array<Pin::Base>]
|
346
|
+
def query_symbols query
|
347
|
+
sync_catalog
|
348
|
+
mutex.synchronize { api_map.query_symbols query }
|
349
|
+
end
|
350
|
+
|
351
|
+
# Get an array of document symbols.
|
352
|
+
#
|
353
|
+
# Document symbols are composed of namespace, method, and constant pins.
|
354
|
+
# The results of this query are appropriate for building the response to a
|
355
|
+
# textDocument/documentSymbol message in the language server protocol.
|
356
|
+
#
|
357
|
+
# @param filename [String]
|
358
|
+
# @return [Array<Solargraph::Pin::Base>]
|
359
|
+
def document_symbols filename
|
360
|
+
sync_catalog
|
361
|
+
mutex.synchronize { api_map.document_symbols(filename) }
|
362
|
+
end
|
363
|
+
|
364
|
+
# @param path [String]
|
365
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
366
|
+
def path_pins path
|
367
|
+
sync_catalog
|
368
|
+
mutex.synchronize { api_map.get_path_suggestions(path) }
|
369
|
+
end
|
370
|
+
|
371
|
+
# @return [Array<SourceMap>]
|
372
|
+
def source_maps
|
373
|
+
source_map_hash.values
|
374
|
+
end
|
375
|
+
|
376
|
+
# Get the current text of a file in the library.
|
377
|
+
#
|
378
|
+
# @param filename [String]
|
379
|
+
# @return [String]
|
380
|
+
def read_text filename
|
381
|
+
source = read(filename)
|
382
|
+
source.code
|
383
|
+
end
|
384
|
+
|
385
|
+
# Get diagnostics about a file.
|
386
|
+
#
|
387
|
+
# @param filename [String]
|
388
|
+
# @return [Array<Hash>]
|
389
|
+
def diagnose filename
|
390
|
+
# @todo Only open files get diagnosed. Determine whether anything or
|
391
|
+
# everything in the workspace should get diagnosed, or if there should
|
392
|
+
# be an option to do so.
|
393
|
+
#
|
394
|
+
sync_catalog
|
395
|
+
return [] unless open?(filename)
|
396
|
+
result = []
|
397
|
+
source = read(filename)
|
398
|
+
|
399
|
+
# @type [Hash{Class<Solargraph::Diagnostics::Base> => Array<String>}]
|
400
|
+
repargs = {}
|
401
|
+
workspace.config.reporters.each do |line|
|
402
|
+
if line == 'all!'
|
403
|
+
Diagnostics.reporters.each do |reporter|
|
404
|
+
repargs[reporter] ||= []
|
405
|
+
end
|
406
|
+
else
|
407
|
+
args = line.split(':').map(&:strip)
|
408
|
+
name = args.shift
|
409
|
+
reporter = Diagnostics.reporter(name)
|
410
|
+
raise DiagnosticsError, "Diagnostics reporter #{name} does not exist" if reporter.nil?
|
411
|
+
repargs[reporter] ||= []
|
412
|
+
repargs[reporter].concat args
|
413
|
+
end
|
414
|
+
end
|
415
|
+
repargs.each_pair do |reporter, args|
|
416
|
+
result.concat reporter.new(*args.uniq).diagnose(source, api_map)
|
417
|
+
end
|
418
|
+
result
|
419
|
+
end
|
420
|
+
|
421
|
+
# Update the ApiMap from the library's workspace and open files.
|
422
|
+
#
|
423
|
+
# @return [void]
|
424
|
+
def catalog
|
425
|
+
@sync_count += 1
|
426
|
+
end
|
427
|
+
|
428
|
+
# @return [Bench]
|
429
|
+
def bench
|
430
|
+
Bench.new(
|
431
|
+
source_maps: source_map_hash.values,
|
432
|
+
workspace: workspace,
|
433
|
+
external_requires: external_requires,
|
434
|
+
live_map: @current ? source_map_hash[@current.filename] : nil
|
435
|
+
)
|
436
|
+
end
|
437
|
+
|
438
|
+
# Get an array of foldable ranges for the specified file.
|
439
|
+
#
|
440
|
+
# @deprecated The library should not need to handle folding ranges. The
|
441
|
+
# source itself has all the information it needs.
|
442
|
+
#
|
443
|
+
# @param filename [String]
|
444
|
+
# @return [Array<Range>]
|
445
|
+
def folding_ranges filename
|
446
|
+
read(filename).folding_ranges
|
447
|
+
end
|
448
|
+
|
449
|
+
# Create a library from a directory.
|
450
|
+
#
|
451
|
+
# @param directory [String] The path to be used for the workspace
|
452
|
+
# @param name [String, nil]
|
453
|
+
# @return [Solargraph::Library]
|
454
|
+
def self.load directory = '', name = nil
|
455
|
+
Solargraph::Library.new(Solargraph::Workspace.new(directory), name)
|
456
|
+
end
|
457
|
+
|
458
|
+
# Try to merge a source into the library's workspace. If the workspace is
|
459
|
+
# not configured to include the source, it gets ignored.
|
460
|
+
#
|
461
|
+
# @param source [Source]
|
462
|
+
# @return [Boolean] True if the source was merged into the workspace.
|
463
|
+
def merge source
|
464
|
+
result = workspace.merge(source)
|
465
|
+
maybe_map source
|
466
|
+
result
|
467
|
+
end
|
468
|
+
|
469
|
+
# @return [Hash{String => SourceMap}]
|
470
|
+
def source_map_hash
|
471
|
+
@source_map_hash ||= {}
|
472
|
+
end
|
473
|
+
|
474
|
+
def mapped?
|
475
|
+
(workspace.filenames - source_map_hash.keys).empty?
|
476
|
+
end
|
477
|
+
|
478
|
+
# @return [SourceMap, Boolean]
|
479
|
+
def next_map
|
480
|
+
return false if mapped?
|
481
|
+
src = workspace.sources.find { |s| !source_map_hash.key?(s.filename) }
|
482
|
+
if src
|
483
|
+
Logging.logger.debug "Mapping #{src.filename}"
|
484
|
+
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
485
|
+
source_map_hash[src.filename]
|
486
|
+
else
|
487
|
+
false
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
# @return [self]
|
492
|
+
def map!
|
493
|
+
workspace.sources.each do |src|
|
494
|
+
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
495
|
+
find_external_requires source_map_hash[src.filename]
|
496
|
+
end
|
497
|
+
self
|
498
|
+
end
|
499
|
+
|
500
|
+
# @return [Array<Solargraph::Pin::Base>]
|
501
|
+
def pins
|
502
|
+
@pins ||= []
|
503
|
+
end
|
504
|
+
|
505
|
+
# @return [Set<String>]
|
506
|
+
def external_requires
|
507
|
+
@external_requires ||= source_map_external_require_hash.values.flatten.to_set
|
508
|
+
end
|
509
|
+
|
510
|
+
private
|
511
|
+
|
512
|
+
# @return [Hash{String => Set<String>}]
|
513
|
+
def source_map_external_require_hash
|
514
|
+
@source_map_external_require_hash ||= {}
|
515
|
+
end
|
516
|
+
|
517
|
+
# @param source_map [SourceMap]
|
518
|
+
# @return [void]
|
519
|
+
def find_external_requires source_map
|
520
|
+
new_set = source_map.requires.map(&:name).to_set
|
521
|
+
# return if new_set == source_map_external_require_hash[source_map.filename]
|
522
|
+
_filenames = nil
|
523
|
+
filenames = ->{ _filenames ||= workspace.filenames.to_set }
|
524
|
+
source_map_external_require_hash[source_map.filename] = new_set.reject do |path|
|
525
|
+
workspace.require_paths.any? do |base|
|
526
|
+
full = File.join(base, path)
|
527
|
+
filenames[].include?(full) or filenames[].include?(full << ".rb")
|
528
|
+
end
|
529
|
+
end
|
530
|
+
@external_requires = nil
|
531
|
+
end
|
532
|
+
|
533
|
+
# @return [Mutex]
|
534
|
+
def mutex
|
535
|
+
@mutex ||= Mutex.new
|
536
|
+
end
|
537
|
+
|
538
|
+
# @return [ApiMap]
|
539
|
+
def api_map
|
540
|
+
@api_map ||= Solargraph::ApiMap.new
|
541
|
+
end
|
542
|
+
|
543
|
+
# Get the source for an open file or create a new source if the file
|
544
|
+
# exists on disk. Sources created from disk are not added to the open
|
545
|
+
# workspace files, i.e., the version on disk remains the authoritative
|
546
|
+
# version.
|
547
|
+
#
|
548
|
+
# @raise [FileNotFoundError] if the file does not exist
|
549
|
+
# @param filename [String]
|
550
|
+
# @return [Solargraph::Source]
|
551
|
+
def read filename
|
552
|
+
return @current if @current && @current.filename == filename
|
553
|
+
raise FileNotFoundError, "File not found: #{filename}" unless workspace.has_file?(filename)
|
554
|
+
workspace.source(filename)
|
555
|
+
end
|
556
|
+
|
557
|
+
# @param filename [String]
|
558
|
+
# @param error [FileNotFoundError]
|
559
|
+
# @return [nil]
|
560
|
+
def handle_file_not_found filename, error
|
561
|
+
if workspace.source(filename)
|
562
|
+
Solargraph.logger.debug "#{filename} is not cataloged in the ApiMap"
|
563
|
+
nil
|
564
|
+
else
|
565
|
+
raise error
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
# @param source [Source, nil]
|
570
|
+
# @return [void]
|
571
|
+
def maybe_map source
|
572
|
+
return unless source
|
573
|
+
return unless @current == source || workspace.has_file?(source.filename)
|
574
|
+
if source_map_hash.key?(source.filename)
|
575
|
+
new_map = Solargraph::SourceMap.map(source)
|
576
|
+
source_map_hash[source.filename] = new_map
|
577
|
+
else
|
578
|
+
source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
# @return [Set<Gem::Specification>]
|
583
|
+
def cache_errors
|
584
|
+
@cache_errors ||= Set.new
|
585
|
+
end
|
586
|
+
|
587
|
+
# @return [void]
|
588
|
+
def cache_next_gemspec
|
589
|
+
return if @cache_progress
|
590
|
+
spec = api_map.uncached_gemspecs.find { |spec| !cache_errors.include?(spec) }
|
591
|
+
return end_cache_progress unless spec
|
592
|
+
|
593
|
+
pending = api_map.uncached_gemspecs.length - cache_errors.length - 1
|
594
|
+
logger.info "Caching #{spec.name} #{spec.version}"
|
595
|
+
Thread.new do
|
596
|
+
cache_pid = Process.spawn(workspace.command_path, 'cache', spec.name, spec.version.to_s)
|
597
|
+
report_cache_progress spec.name, pending
|
598
|
+
Process.wait(cache_pid)
|
599
|
+
logger.info "Cached #{spec.name} #{spec.version}"
|
600
|
+
rescue Errno::EINVAL => _e
|
601
|
+
logger.info "Cached #{spec.name} #{spec.version} with EINVAL"
|
602
|
+
rescue StandardError => e
|
603
|
+
cache_errors.add spec
|
604
|
+
Solargraph.logger.warn "Error caching gemspec #{spec.name} #{spec.version}: [#{e.class}] #{e.message}"
|
605
|
+
ensure
|
606
|
+
end_cache_progress
|
607
|
+
catalog
|
608
|
+
sync_catalog
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
# @param gem_name [String]
|
613
|
+
# @param pending [Integer]
|
614
|
+
# @return [void]
|
615
|
+
def report_cache_progress gem_name, pending
|
616
|
+
@total ||= pending
|
617
|
+
@total = pending if pending > @total
|
618
|
+
finished = @total - pending
|
619
|
+
pct = if @total.zero?
|
620
|
+
0
|
621
|
+
else
|
622
|
+
((finished.to_f / @total.to_f) * 100).to_i
|
623
|
+
end
|
624
|
+
message = "#{gem_name}#{pending > 0 ? " (+#{pending})" : ''}"
|
625
|
+
# "
|
626
|
+
if @cache_progress
|
627
|
+
@cache_progress.report(message, pct)
|
628
|
+
else
|
629
|
+
@cache_progress = LanguageServer::Progress.new('Caching gem')
|
630
|
+
# If we don't send both a begin and a report, the progress notification
|
631
|
+
# might get stuck in the status bar forever
|
632
|
+
@cache_progress.begin(message, pct)
|
633
|
+
changed
|
634
|
+
notify_observers @cache_progress
|
635
|
+
@cache_progress.report(message, pct)
|
636
|
+
end
|
637
|
+
changed
|
638
|
+
notify_observers @cache_progress
|
639
|
+
end
|
640
|
+
|
641
|
+
# @return [void]
|
642
|
+
def end_cache_progress
|
643
|
+
changed if @cache_progress&.finish('done')
|
644
|
+
notify_observers @cache_progress
|
645
|
+
@cache_progress = nil
|
646
|
+
@total = nil
|
647
|
+
end
|
648
|
+
|
649
|
+
def sync_catalog
|
650
|
+
return if @sync_count == 0
|
651
|
+
|
652
|
+
mutex.synchronize do
|
653
|
+
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
654
|
+
api_map.catalog bench
|
655
|
+
source_map_hash.values.each { |map| find_external_requires(map) }
|
656
|
+
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
657
|
+
logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
|
658
|
+
cache_next_gemspec
|
659
|
+
@sync_count = 0
|
660
|
+
end
|
661
|
+
end
|
662
|
+
end
|
663
|
+
end
|