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,522 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yard'
|
4
|
+
|
5
|
+
module Solargraph
|
6
|
+
# A Ruby file that has been parsed into an AST.
|
7
|
+
#
|
8
|
+
class Source
|
9
|
+
autoload :Updater, 'solargraph/source/updater'
|
10
|
+
autoload :Change, 'solargraph/source/change'
|
11
|
+
autoload :Mapper, 'solargraph/source/mapper'
|
12
|
+
autoload :EncodingFixes, 'solargraph/source/encoding_fixes'
|
13
|
+
autoload :Cursor, 'solargraph/source/cursor'
|
14
|
+
autoload :Chain, 'solargraph/source/chain'
|
15
|
+
autoload :SourceChainer, 'solargraph/source/source_chainer'
|
16
|
+
|
17
|
+
include EncodingFixes
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
attr_reader :filename
|
21
|
+
|
22
|
+
# @return [String]
|
23
|
+
attr_reader :code
|
24
|
+
|
25
|
+
# @return [Parser::AST::Node]
|
26
|
+
attr_reader :node
|
27
|
+
|
28
|
+
# @return [Hash{Integer => Array<String>}]
|
29
|
+
attr_reader :comments
|
30
|
+
|
31
|
+
# @todo Deprecate?
|
32
|
+
# @return [Integer]
|
33
|
+
attr_reader :version
|
34
|
+
|
35
|
+
# @param code [String]
|
36
|
+
# @param filename [String]
|
37
|
+
# @param version [Integer]
|
38
|
+
def initialize code, filename = nil, version = 0
|
39
|
+
@code = normalize(code)
|
40
|
+
@repaired = code
|
41
|
+
@filename = filename
|
42
|
+
@version = version
|
43
|
+
@domains = []
|
44
|
+
begin
|
45
|
+
@node, @comments = Solargraph::Parser.parse_with_comments(@code, filename)
|
46
|
+
@parsed = true
|
47
|
+
rescue Parser::SyntaxError, EncodingError => e
|
48
|
+
@node = nil
|
49
|
+
@comments = {}
|
50
|
+
@parsed = false
|
51
|
+
ensure
|
52
|
+
@code.freeze
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param range [Solargraph::Range]
|
57
|
+
# @return [String]
|
58
|
+
def at range
|
59
|
+
from_to range.start.line, range.start.character, range.ending.line, range.ending.character
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param l1 [Integer]
|
63
|
+
# @param c1 [Integer]
|
64
|
+
# @param l2 [Integer]
|
65
|
+
# @param c2 [Integer]
|
66
|
+
# @return [String]
|
67
|
+
def from_to l1, c1, l2, c2
|
68
|
+
b = Solargraph::Position.line_char_to_offset(@code, l1, c1)
|
69
|
+
e = Solargraph::Position.line_char_to_offset(@code, l2, c2)
|
70
|
+
@code[b..e-1]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Get the nearest node that contains the specified index.
|
74
|
+
#
|
75
|
+
# @param line [Integer]
|
76
|
+
# @param column [Integer]
|
77
|
+
# @return [AST::Node]
|
78
|
+
def node_at(line, column)
|
79
|
+
tree_at(line, column).first
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get an array of nodes containing the specified index, starting with the
|
83
|
+
# nearest node and ending with the root.
|
84
|
+
#
|
85
|
+
# @param line [Integer]
|
86
|
+
# @param column [Integer]
|
87
|
+
# @return [Array<AST::Node>]
|
88
|
+
def tree_at(line, column)
|
89
|
+
# offset = Position.line_char_to_offset(@code, line, column)
|
90
|
+
position = Position.new(line, column)
|
91
|
+
stack = []
|
92
|
+
inner_tree_at @node, position, stack
|
93
|
+
stack
|
94
|
+
end
|
95
|
+
|
96
|
+
# Start synchronizing the source. This method updates the code without
|
97
|
+
# parsing a new AST. The resulting Source object will be marked not
|
98
|
+
# synchronized (#synchronized? == false).
|
99
|
+
#
|
100
|
+
# @param updater [Source::Updater]
|
101
|
+
# @return [Source]
|
102
|
+
def start_synchronize updater
|
103
|
+
raise 'Invalid synchronization' unless updater.filename == filename
|
104
|
+
real_code = updater.write(@code)
|
105
|
+
src = Source.allocate
|
106
|
+
src.filename = filename
|
107
|
+
src.code = real_code
|
108
|
+
src.version = updater.version
|
109
|
+
src.parsed = parsed?
|
110
|
+
src.repaired = updater.repair(@repaired)
|
111
|
+
src.synchronized = false
|
112
|
+
src.node = @node
|
113
|
+
src.comments = @comments
|
114
|
+
src.error_ranges = error_ranges
|
115
|
+
src.last_updater = updater
|
116
|
+
return src.finish_synchronize unless real_code.lines.length == @code.lines.length
|
117
|
+
src
|
118
|
+
end
|
119
|
+
|
120
|
+
# Finish synchronizing a source that was updated via #start_synchronize.
|
121
|
+
# This method returns self if the source is already synchronized. Otherwise
|
122
|
+
# it parses the AST and returns a new synchronized Source.
|
123
|
+
#
|
124
|
+
# @return [Source]
|
125
|
+
def finish_synchronize
|
126
|
+
return self if synchronized?
|
127
|
+
synced = Source.new(@code, filename)
|
128
|
+
if synced.parsed?
|
129
|
+
synced.version = version
|
130
|
+
return synced
|
131
|
+
end
|
132
|
+
synced = Source.new(@repaired, filename)
|
133
|
+
synced.error_ranges.concat (error_ranges + last_updater.changes.map(&:range))
|
134
|
+
synced.code = @code
|
135
|
+
synced.synchronized = true
|
136
|
+
synced.version = version
|
137
|
+
synced
|
138
|
+
end
|
139
|
+
|
140
|
+
# Synchronize the Source with an update. This method applies changes to the
|
141
|
+
# code, parses the new code's AST, and returns the resulting Source object.
|
142
|
+
#
|
143
|
+
# @param updater [Source::Updater]
|
144
|
+
# @return [Source]
|
145
|
+
def synchronize updater
|
146
|
+
raise 'Invalid synchronization' unless updater.filename == filename
|
147
|
+
real_code = updater.write(@code)
|
148
|
+
if real_code == @code
|
149
|
+
@version = updater.version
|
150
|
+
return self
|
151
|
+
end
|
152
|
+
synced = Source.new(real_code, filename)
|
153
|
+
if synced.parsed?
|
154
|
+
synced.version = updater.version
|
155
|
+
return synced
|
156
|
+
end
|
157
|
+
incr_code = updater.repair(@repaired)
|
158
|
+
synced = Source.new(incr_code, filename)
|
159
|
+
synced.error_ranges.concat (error_ranges + updater.changes.map(&:range))
|
160
|
+
synced.code = real_code
|
161
|
+
synced.version = updater.version
|
162
|
+
synced
|
163
|
+
end
|
164
|
+
|
165
|
+
# @param position [Position, Array(Integer, Integer)]
|
166
|
+
# @return [Source::Cursor]
|
167
|
+
def cursor_at position
|
168
|
+
Cursor.new(self, position)
|
169
|
+
end
|
170
|
+
|
171
|
+
# @return [Boolean]
|
172
|
+
def parsed?
|
173
|
+
@parsed
|
174
|
+
end
|
175
|
+
|
176
|
+
def repaired?
|
177
|
+
@is_repaired ||= (@code != @repaired)
|
178
|
+
end
|
179
|
+
|
180
|
+
# @param position [Position]
|
181
|
+
# @return [Boolean]
|
182
|
+
def string_at? position
|
183
|
+
if Parser.rubyvm?
|
184
|
+
string_ranges.each do |range|
|
185
|
+
if synchronized?
|
186
|
+
return true if range.include?(position) || range.ending == position
|
187
|
+
else
|
188
|
+
return true if last_updater && last_updater.changes.one? && range.contain?(last_updater.changes.first.range.start)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
false
|
192
|
+
else
|
193
|
+
return false if Position.to_offset(code, position) >= code.length
|
194
|
+
string_nodes.each do |node|
|
195
|
+
range = Range.from_node(node)
|
196
|
+
next if range.ending.line < position.line
|
197
|
+
break if range.ending.line > position.line
|
198
|
+
return true if node.type == :str && range.include?(position) && range.start != position
|
199
|
+
return true if [:STR, :str].include?(node.type) && range.include?(position) && range.start != position
|
200
|
+
if node.type == :dstr
|
201
|
+
inner = node_at(position.line, position.column)
|
202
|
+
next if inner.nil?
|
203
|
+
inner_range = Range.from_node(inner)
|
204
|
+
next unless range.include?(inner_range.ending)
|
205
|
+
return true if inner.type == :str
|
206
|
+
inner_code = at(Solargraph::Range.new(inner_range.start, position))
|
207
|
+
return true if (inner.type == :dstr && inner_range.ending.character <= position.character) && !inner_code.end_with?('}') ||
|
208
|
+
(inner.type != :dstr && inner_range.ending.line == position.line && position.character <= inner_range.ending.character && inner_code.end_with?('}'))
|
209
|
+
end
|
210
|
+
break if range.ending.line > position.line
|
211
|
+
end
|
212
|
+
false
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def string_ranges
|
217
|
+
@string_ranges ||= Parser.string_ranges(node)
|
218
|
+
end
|
219
|
+
|
220
|
+
# @param position [Position]
|
221
|
+
# @return [Boolean]
|
222
|
+
def comment_at? position
|
223
|
+
comment_ranges.each do |range|
|
224
|
+
return true if range.include?(position) ||
|
225
|
+
(range.ending.line == position.line && range.ending.column < position.column)
|
226
|
+
break if range.ending.line > position.line
|
227
|
+
end
|
228
|
+
false
|
229
|
+
end
|
230
|
+
|
231
|
+
# @param name [String]
|
232
|
+
# @return [Array<Location>]
|
233
|
+
def references name
|
234
|
+
Parser.references self, name
|
235
|
+
end
|
236
|
+
|
237
|
+
# @return [Array<Range>]
|
238
|
+
def error_ranges
|
239
|
+
@error_ranges ||= []
|
240
|
+
end
|
241
|
+
|
242
|
+
# @param node [Parser::AST::Node]
|
243
|
+
# @return [String]
|
244
|
+
def code_for(node)
|
245
|
+
rng = Range.from_node(node)
|
246
|
+
b = Position.line_char_to_offset(@code, rng.start.line, rng.start.column)
|
247
|
+
e = Position.line_char_to_offset(@code, rng.ending.line, rng.ending.column)
|
248
|
+
frag = code[b..e-1].to_s
|
249
|
+
frag.strip.gsub(/,$/, '')
|
250
|
+
end
|
251
|
+
|
252
|
+
# @param node [Parser::AST::Node]
|
253
|
+
# @return [String]
|
254
|
+
def comments_for node
|
255
|
+
rng = Range.from_node(node)
|
256
|
+
stringified_comments[rng.start.line] ||= begin
|
257
|
+
buff = associated_comments[rng.start.line]
|
258
|
+
buff ? stringify_comment_array(buff) : nil
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# A location representing the file in its entirety.
|
263
|
+
#
|
264
|
+
# @return [Location]
|
265
|
+
def location
|
266
|
+
st = Position.new(0, 0)
|
267
|
+
en = Position.from_offset(code, code.length)
|
268
|
+
range = Range.new(st, en)
|
269
|
+
Location.new(filename, range)
|
270
|
+
end
|
271
|
+
|
272
|
+
FOLDING_NODE_TYPES = if Parser.rubyvm?
|
273
|
+
%i[
|
274
|
+
CLASS SCLASS MODULE DEFN DEFS IF WHILE UNLESS ITER STR HASH ARRAY LIST
|
275
|
+
].freeze
|
276
|
+
else
|
277
|
+
%i[
|
278
|
+
class sclass module def defs if str dstr array while unless kwbegin hash block
|
279
|
+
].freeze
|
280
|
+
end
|
281
|
+
|
282
|
+
# Get an array of ranges that can be folded, e.g., the range of a class
|
283
|
+
# definition or an if condition.
|
284
|
+
#
|
285
|
+
# See FOLDING_NODE_TYPES for the list of node types that can be folded.
|
286
|
+
#
|
287
|
+
# @return [Array<Range>]
|
288
|
+
def folding_ranges
|
289
|
+
@folding_ranges ||= begin
|
290
|
+
result = []
|
291
|
+
inner_folding_ranges node, result
|
292
|
+
result.concat foldable_comment_block_ranges
|
293
|
+
result
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
def synchronized?
|
298
|
+
@synchronized = true if @synchronized.nil?
|
299
|
+
@synchronized
|
300
|
+
end
|
301
|
+
|
302
|
+
# Get a hash of comments grouped by the line numbers of the associated code.
|
303
|
+
#
|
304
|
+
# @return [Hash{Integer => Array<Parser::Source::Comment>}]
|
305
|
+
def associated_comments
|
306
|
+
@associated_comments ||= begin
|
307
|
+
result = {}
|
308
|
+
buffer = String.new('')
|
309
|
+
last = nil
|
310
|
+
@comments.each_pair do |num, snip|
|
311
|
+
if !last || num == last + 1
|
312
|
+
buffer.concat "#{snip.text}\n"
|
313
|
+
else
|
314
|
+
result[first_not_empty_from(last + 1)] = buffer.clone
|
315
|
+
buffer.replace "#{snip.text}\n"
|
316
|
+
end
|
317
|
+
last = num
|
318
|
+
end
|
319
|
+
result[first_not_empty_from(last + 1)] = buffer unless buffer.empty? || last.nil?
|
320
|
+
result
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
private
|
325
|
+
|
326
|
+
def first_not_empty_from line
|
327
|
+
cursor = line
|
328
|
+
cursor += 1 while cursor < code_lines.length && code_lines[cursor].strip.empty?
|
329
|
+
cursor = line if cursor > code_lines.length - 1
|
330
|
+
cursor
|
331
|
+
end
|
332
|
+
|
333
|
+
# @param top [Parser::AST::Node]
|
334
|
+
# @param result [Array<Range>]
|
335
|
+
# @param parent [Symbol]
|
336
|
+
# @return [void]
|
337
|
+
def inner_folding_ranges top, result = [], parent = nil
|
338
|
+
return unless Parser.is_ast_node?(top)
|
339
|
+
if FOLDING_NODE_TYPES.include?(top.type)
|
340
|
+
# @todo Smelly exception for hash's first-level array in RubyVM
|
341
|
+
unless [:ARRAY, :LIST].include?(top.type) && parent == :HASH
|
342
|
+
range = Range.from_node(top)
|
343
|
+
if result.empty? || range.start.line > result.last.start.line
|
344
|
+
result.push range unless range.ending.line - range.start.line < 2
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
top.children.each do |child|
|
349
|
+
inner_folding_ranges(child, result, top.type)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
# Get a string representation of an array of comments.
|
354
|
+
#
|
355
|
+
# @param comments [String]
|
356
|
+
# @return [String]
|
357
|
+
def stringify_comment_array comments
|
358
|
+
ctxt = String.new('')
|
359
|
+
started = false
|
360
|
+
skip = nil
|
361
|
+
comments.lines.each { |l|
|
362
|
+
# Trim the comment and minimum leading whitespace
|
363
|
+
p = l.force_encoding('UTF-8').encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
|
364
|
+
if p.strip.empty?
|
365
|
+
next unless started
|
366
|
+
ctxt.concat p
|
367
|
+
else
|
368
|
+
here = p.index(/[^ \t]/)
|
369
|
+
skip = here if skip.nil? || here < skip
|
370
|
+
ctxt.concat p[skip..-1]
|
371
|
+
end
|
372
|
+
started = true
|
373
|
+
}
|
374
|
+
ctxt
|
375
|
+
end
|
376
|
+
|
377
|
+
# A hash of line numbers and their associated comments.
|
378
|
+
#
|
379
|
+
# @return [Hash{Integer => Array<String>}]
|
380
|
+
def stringified_comments
|
381
|
+
@stringified_comments ||= {}
|
382
|
+
end
|
383
|
+
|
384
|
+
# @return [Array<Parser::AST::Node>]
|
385
|
+
def string_nodes
|
386
|
+
@string_nodes ||= string_nodes_in(@node)
|
387
|
+
end
|
388
|
+
|
389
|
+
# @return [Array<Range>]
|
390
|
+
def comment_ranges
|
391
|
+
@comment_ranges ||= @comments.values.map(&:range)
|
392
|
+
end
|
393
|
+
|
394
|
+
# Get an array of foldable comment block ranges. Blocks are excluded if
|
395
|
+
# they are less than 3 lines long.
|
396
|
+
#
|
397
|
+
# @return [Array<Range>]
|
398
|
+
def foldable_comment_block_ranges
|
399
|
+
return [] unless synchronized?
|
400
|
+
result = []
|
401
|
+
grouped = []
|
402
|
+
comments.keys.each do |l|
|
403
|
+
if grouped.empty? || l == grouped.last + 1
|
404
|
+
grouped.push l
|
405
|
+
else
|
406
|
+
result.push Range.from_to(grouped.first, 0, grouped.last, 0) unless grouped.length < 3
|
407
|
+
grouped = [l]
|
408
|
+
end
|
409
|
+
end
|
410
|
+
result.push Range.from_to(grouped.first, 0, grouped.last, 0) unless grouped.length < 3
|
411
|
+
result
|
412
|
+
end
|
413
|
+
|
414
|
+
# @param n [Parser::AST::Node]
|
415
|
+
# @return [Array<Parser::AST::Node>]
|
416
|
+
def string_nodes_in n
|
417
|
+
result = []
|
418
|
+
if Parser.is_ast_node?(n)
|
419
|
+
if n.type == :str || n.type == :dstr || n.type == :STR || n.type == :DSTR
|
420
|
+
result.push n
|
421
|
+
else
|
422
|
+
n.children.each{ |c| result.concat string_nodes_in(c) }
|
423
|
+
end
|
424
|
+
end
|
425
|
+
result
|
426
|
+
end
|
427
|
+
|
428
|
+
# @param node [Parser::AST::Node]
|
429
|
+
# @param position [Position]
|
430
|
+
# @param stack [Array<Parser::AST::Node>]
|
431
|
+
# @return [void]
|
432
|
+
def inner_tree_at node, position, stack
|
433
|
+
return if node.nil?
|
434
|
+
here = Range.from_node(node)
|
435
|
+
if here.contain?(position) || colonized(here, position, node)
|
436
|
+
stack.unshift node
|
437
|
+
node.children.each do |c|
|
438
|
+
next unless Parser.is_ast_node?(c)
|
439
|
+
next if !Parser.rubyvm? && c.loc.expression.nil?
|
440
|
+
inner_tree_at(c, position, stack)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
def colonized range, position, node
|
446
|
+
node.type == :COLON2 &&
|
447
|
+
range.ending.line == position.line &&
|
448
|
+
range.ending.character == position.character - 2 &&
|
449
|
+
code[Position.to_offset(code, Position.new(position.line, position.character - 2)), 2] == '::'
|
450
|
+
end
|
451
|
+
|
452
|
+
protected
|
453
|
+
|
454
|
+
# @return [String]
|
455
|
+
attr_writer :filename
|
456
|
+
|
457
|
+
# @return [Integer]
|
458
|
+
attr_writer :version
|
459
|
+
|
460
|
+
# @param val [String]
|
461
|
+
# @return [String]
|
462
|
+
def code=(val)
|
463
|
+
@code_lines= nil
|
464
|
+
@code = val
|
465
|
+
end
|
466
|
+
|
467
|
+
# @return [Parser::AST::Node]
|
468
|
+
attr_writer :node
|
469
|
+
|
470
|
+
# @return [Array<Range>]
|
471
|
+
attr_writer :error_ranges
|
472
|
+
|
473
|
+
# @return [String]
|
474
|
+
attr_accessor :repaired
|
475
|
+
|
476
|
+
# @return [Boolean]
|
477
|
+
attr_writer :parsed
|
478
|
+
|
479
|
+
# @return [Array<Parser::Source::Comment>]
|
480
|
+
attr_writer :comments
|
481
|
+
|
482
|
+
# @return [Boolean]
|
483
|
+
attr_writer :synchronized
|
484
|
+
|
485
|
+
# @return [Source::Updater]
|
486
|
+
attr_accessor :last_updater
|
487
|
+
|
488
|
+
private
|
489
|
+
|
490
|
+
# @return [Array<String>]
|
491
|
+
def code_lines
|
492
|
+
@code_lines ||= code.lines
|
493
|
+
end
|
494
|
+
|
495
|
+
class << self
|
496
|
+
# @param filename [String]
|
497
|
+
# @return [Solargraph::Source]
|
498
|
+
def load filename
|
499
|
+
file = File.open(filename)
|
500
|
+
code = file.read
|
501
|
+
file.close
|
502
|
+
Source.load_string(code, filename)
|
503
|
+
end
|
504
|
+
|
505
|
+
# @param code [String]
|
506
|
+
# @param filename [String]
|
507
|
+
# @param version [Integer]
|
508
|
+
# @return [Solargraph::Source]
|
509
|
+
def load_string code, filename = nil, version = 0
|
510
|
+
Source.new code, filename, version
|
511
|
+
end
|
512
|
+
|
513
|
+
# @param comments [String]
|
514
|
+
# @return [YARD::DocstringParser]
|
515
|
+
def parse_docstring comments
|
516
|
+
# HACK: Pass a dummy code object to the parser for plugins that
|
517
|
+
# expect it not to be nil
|
518
|
+
YARD::Docstring.parser.parse(comments, YARD::CodeObjects::Base.new(:root, 'stub'))
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|