solargraph 0.32.1 → 0.32.2
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/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +25 -0
- data/EXAMPLES.md +76 -0
- data/Gemfile +3 -0
- data/LANGUAGE_SERVER.md +51 -0
- data/LICENSE +21 -0
- data/OVERVIEW.md +37 -0
- data/README.md +106 -0
- data/Rakefile +14 -0
- data/SERVER.md +95 -0
- data/bin/solargraph +0 -0
- data/bin/solargraph-runtime +5 -5
- data/lib/solargraph.rb +54 -54
- data/lib/solargraph/api_map.rb +659 -659
- data/lib/solargraph/api_map/cache.rb +49 -49
- data/lib/solargraph/api_map/source_to_yard.rb +67 -67
- data/lib/solargraph/api_map/store.rb +201 -201
- data/lib/solargraph/bundle.rb +24 -24
- data/lib/solargraph/complex_type.rb +150 -150
- data/lib/solargraph/complex_type/type_methods.rb +124 -124
- data/lib/solargraph/complex_type/unique_type.rb +44 -44
- data/lib/solargraph/core_fills.rb +37 -37
- data/lib/solargraph/diagnostics.rb +52 -52
- data/lib/solargraph/diagnostics/base.rb +20 -20
- data/lib/solargraph/diagnostics/require_not_found.rb +28 -28
- data/lib/solargraph/diagnostics/rubocop.rb +98 -98
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +46 -46
- data/lib/solargraph/diagnostics/type_not_defined.rb +108 -108
- data/lib/solargraph/diagnostics/update_errors.rb +38 -38
- data/lib/solargraph/language_server/completion_item_kinds.rb +33 -33
- data/lib/solargraph/language_server/error_codes.rb +18 -18
- data/lib/solargraph/language_server/host.rb +684 -681
- data/lib/solargraph/language_server/host/cataloger.rb +54 -79
- data/lib/solargraph/language_server/host/diagnoser.rb +80 -80
- data/lib/solargraph/language_server/host/dispatch.rb +112 -113
- data/lib/solargraph/language_server/host/sources.rb +138 -138
- data/lib/solargraph/language_server/message.rb +90 -90
- data/lib/solargraph/language_server/message/base.rb +83 -83
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +40 -40
- data/lib/solargraph/language_server/message/exit_notification.rb +11 -11
- data/lib/solargraph/language_server/message/extended.rb +19 -19
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +86 -86
- data/lib/solargraph/language_server/message/extended/document.rb +18 -18
- data/lib/solargraph/language_server/message/extended/document_gems.rb +30 -30
- data/lib/solargraph/language_server/message/extended/environment.rb +20 -20
- data/lib/solargraph/language_server/message/extended/search.rb +18 -18
- data/lib/solargraph/language_server/message/initialize.rb +141 -141
- data/lib/solargraph/language_server/message/initialized.rb +23 -23
- data/lib/solargraph/language_server/message/shutdown.rb +11 -11
- data/lib/solargraph/language_server/message/text_document.rb +25 -25
- data/lib/solargraph/language_server/message/text_document/completion.rb +51 -51
- data/lib/solargraph/language_server/message/text_document/definition.rb +18 -18
- data/lib/solargraph/language_server/message/text_document/did_change.rb +13 -13
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +21 -21
- data/lib/solargraph/language_server/message/text_document/folding_range.rb +24 -24
- data/lib/solargraph/language_server/message/text_document/formatting.rb +50 -50
- data/lib/solargraph/language_server/message/text_document/hover.rb +31 -31
- data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +32 -32
- data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +9 -9
- data/lib/solargraph/language_server/message/text_document/references.rb +14 -14
- data/lib/solargraph/language_server/message/text_document/rename.rb +17 -17
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +19 -19
- data/lib/solargraph/language_server/message/workspace.rb +12 -12
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +29 -29
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +29 -27
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +24 -24
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +21 -21
- data/lib/solargraph/language_server/request.rb +22 -22
- data/lib/solargraph/language_server/symbol_kinds.rb +34 -34
- data/lib/solargraph/language_server/transport.rb +11 -11
- data/lib/solargraph/language_server/transport/adapter.rb +60 -60
- data/lib/solargraph/language_server/transport/data_reader.rb +66 -66
- data/lib/solargraph/language_server/uri_helpers.rb +25 -25
- data/lib/solargraph/library.rb +421 -419
- data/lib/solargraph/live_map.rb +126 -126
- data/lib/solargraph/live_map/cache.rb +38 -38
- data/lib/solargraph/location.rb +31 -31
- data/lib/solargraph/logging.rb +25 -25
- data/lib/solargraph/page.rb +68 -68
- data/lib/solargraph/pin.rb +50 -50
- data/lib/solargraph/pin/attribute.rb +41 -41
- data/lib/solargraph/pin/base.rb +280 -280
- data/lib/solargraph/pin/base_method.rb +76 -76
- data/lib/solargraph/pin/base_variable.rb +72 -72
- data/lib/solargraph/pin/block.rb +32 -32
- data/lib/solargraph/pin/block_parameter.rb +103 -103
- data/lib/solargraph/pin/class_variable.rb +9 -9
- data/lib/solargraph/pin/constant.rb +30 -30
- data/lib/solargraph/pin/conversions.rb +79 -79
- data/lib/solargraph/pin/documenting.rb +41 -41
- data/lib/solargraph/pin/duck_method.rb +14 -14
- data/lib/solargraph/pin/global_variable.rb +9 -9
- data/lib/solargraph/pin/instance_variable.rb +9 -9
- data/lib/solargraph/pin/keyword.rb +17 -17
- data/lib/solargraph/pin/local_variable.rb +23 -23
- data/lib/solargraph/pin/localized.rb +22 -22
- data/lib/solargraph/pin/method.rb +126 -126
- data/lib/solargraph/pin/method_alias.rb +30 -30
- data/lib/solargraph/pin/method_parameter.rb +40 -40
- data/lib/solargraph/pin/namespace.rb +54 -54
- data/lib/solargraph/pin/plugin/method.rb +25 -25
- data/lib/solargraph/pin/proxy_type.rb +35 -35
- data/lib/solargraph/pin/reference.rb +22 -22
- data/lib/solargraph/pin/reference/extend.rb +11 -11
- data/lib/solargraph/pin/reference/include.rb +11 -11
- data/lib/solargraph/pin/reference/require.rb +15 -15
- data/lib/solargraph/pin/reference/superclass.rb +11 -11
- data/lib/solargraph/pin/symbol.rb +44 -44
- data/lib/solargraph/pin/yard_pin.rb +10 -10
- data/lib/solargraph/pin/yard_pin/constant.rb +14 -14
- data/lib/solargraph/pin/yard_pin/method.rb +35 -35
- data/lib/solargraph/pin/yard_pin/namespace.rb +19 -19
- data/lib/solargraph/pin/yard_pin/yard_mixin.rb +14 -14
- data/lib/solargraph/plugin.rb +8 -8
- data/lib/solargraph/plugin/base.rb +41 -41
- data/lib/solargraph/plugin/canceler.rb +11 -11
- data/lib/solargraph/plugin/process.rb +172 -172
- data/lib/solargraph/plugin/runtime.rb +134 -134
- data/lib/solargraph/position.rb +110 -110
- data/lib/solargraph/range.rb +83 -83
- data/lib/solargraph/server_methods.rb +14 -14
- data/lib/solargraph/shell.rb +102 -102
- data/lib/solargraph/source.rb +521 -521
- data/lib/solargraph/source/chain.rb +120 -120
- data/lib/solargraph/source/chain/call.rb +107 -107
- data/lib/solargraph/source/chain/class_variable.rb +11 -11
- data/lib/solargraph/source/chain/constant.rb +30 -30
- data/lib/solargraph/source/chain/global_variable.rb +11 -11
- data/lib/solargraph/source/chain/head.rb +33 -33
- data/lib/solargraph/source/chain/instance_variable.rb +11 -11
- data/lib/solargraph/source/chain/link.rb +33 -33
- data/lib/solargraph/source/chain/literal.rb +21 -21
- data/lib/solargraph/source/chain/variable.rb +11 -11
- data/lib/solargraph/source/change.rb +77 -77
- data/lib/solargraph/source/cursor.rb +157 -157
- data/lib/solargraph/source/node_chainer.rb +96 -96
- data/lib/solargraph/source/node_methods.rb +225 -225
- data/lib/solargraph/source/source_chainer.rb +183 -183
- data/lib/solargraph/source_map.rb +169 -169
- data/lib/solargraph/source_map/clip.rb +145 -145
- data/lib/solargraph/source_map/completion.rb +21 -21
- data/lib/solargraph/source_map/mapper.rb +149 -149
- data/lib/solargraph/source_map/node_processor.rb +78 -78
- data/lib/solargraph/source_map/node_processor/alias_node.rb +19 -19
- data/lib/solargraph/source_map/node_processor/args_node.rb +28 -28
- data/lib/solargraph/source_map/node_processor/base.rb +68 -68
- data/lib/solargraph/source_map/node_processor/begin_node.rb +11 -11
- data/lib/solargraph/source_map/node_processor/block_node.rb +14 -14
- data/lib/solargraph/source_map/node_processor/casgn_node.rb +14 -14
- data/lib/solargraph/source_map/node_processor/cvasgn_node.rb +14 -14
- data/lib/solargraph/source_map/node_processor/def_node.rb +54 -54
- data/lib/solargraph/source_map/node_processor/defs_node.rb +21 -21
- data/lib/solargraph/source_map/node_processor/gvasgn_node.rb +12 -12
- data/lib/solargraph/source_map/node_processor/ivasgn_node.rb +18 -18
- data/lib/solargraph/source_map/node_processor/lvasgn_node.rb +16 -16
- data/lib/solargraph/source_map/node_processor/namespace_node.rb +26 -26
- data/lib/solargraph/source_map/node_processor/orasgn_node.rb +12 -12
- data/lib/solargraph/source_map/node_processor/sclass_node.rb +11 -11
- data/lib/solargraph/source_map/node_processor/send_node.rb +162 -162
- data/lib/solargraph/source_map/node_processor/sym_node.rb +11 -11
- data/lib/solargraph/source_map/region.rb +58 -58
- data/lib/solargraph/version.rb +3 -3
- data/lib/solargraph/views/environment.erb +53 -53
- data/lib/solargraph/workspace.rb +183 -183
- data/lib/solargraph/workspace/config.rb +170 -170
- data/lib/solargraph/yard_map.rb +298 -298
- data/lib/solargraph/yard_map/cache.rb +17 -17
- data/lib/solargraph/yard_map/core_docs.rb +163 -163
- data/lib/solargraph/yard_map/core_gen.rb +76 -76
- data/lib/yard-coregen.rb +16 -16
- data/lib/yard-solargraph.rb +18 -18
- data/solargraph.gemspec +37 -0
- data/travis-bundler.rb +10 -0
- metadata +19 -6
|
@@ -1,170 +1,170 @@
|
|
|
1
|
-
require 'yaml'
|
|
2
|
-
|
|
3
|
-
module Solargraph
|
|
4
|
-
class Workspace
|
|
5
|
-
# Configuration data for a workspace.
|
|
6
|
-
#
|
|
7
|
-
class Config
|
|
8
|
-
# The maximum number of files that can be added to a workspace.
|
|
9
|
-
# The workspace's .solargraph.yml can override this value.
|
|
10
|
-
MAX_FILES = 5000
|
|
11
|
-
|
|
12
|
-
# @return [String]
|
|
13
|
-
attr_reader :directory
|
|
14
|
-
|
|
15
|
-
# @return [Hash]
|
|
16
|
-
attr_reader :raw_data
|
|
17
|
-
|
|
18
|
-
# @param directory [String]
|
|
19
|
-
def initialize directory = ''
|
|
20
|
-
@directory = directory
|
|
21
|
-
include_globs = ['**/*.rb']
|
|
22
|
-
exclude_globs = ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*']
|
|
23
|
-
unless @directory.empty?
|
|
24
|
-
sfile = File.join(@directory, '.solargraph.yml')
|
|
25
|
-
if File.file?(sfile)
|
|
26
|
-
@raw_data = YAML.safe_load(File.read(sfile))
|
|
27
|
-
include_globs = @raw_data['include'] || include_globs
|
|
28
|
-
exclude_globs = @raw_data['exclude'] || []
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
@raw_data ||= {}
|
|
32
|
-
@raw_data['include'] ||= include_globs
|
|
33
|
-
@raw_data['exclude'] ||= exclude_globs
|
|
34
|
-
@raw_data['require'] ||= []
|
|
35
|
-
@raw_data['domains'] ||= []
|
|
36
|
-
@raw_data['reporters'] ||= %w[rubocop require_not_found]
|
|
37
|
-
@raw_data['plugins'] ||= []
|
|
38
|
-
@raw_data['require_paths'] ||= []
|
|
39
|
-
@raw_data['max_files'] ||= MAX_FILES
|
|
40
|
-
included
|
|
41
|
-
excluded
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# An array of files included in the workspace (before calculating excluded files).
|
|
45
|
-
#
|
|
46
|
-
# @return [Array<String>]
|
|
47
|
-
def included
|
|
48
|
-
return [] if directory.empty? || directory == '*'
|
|
49
|
-
@included ||= process_globs(@raw_data['include'])
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# An array of files excluded from the workspace.
|
|
53
|
-
#
|
|
54
|
-
# @return [Array<String>]
|
|
55
|
-
def excluded
|
|
56
|
-
return [] if directory.empty? || directory == '*'
|
|
57
|
-
@excluded ||= process_exclusions(@raw_data['exclude'])
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# The calculated array of (included - excluded) files in the workspace.
|
|
61
|
-
#
|
|
62
|
-
# @return [Array<String>]
|
|
63
|
-
def calculated
|
|
64
|
-
Solargraph.logger.info "Indexing workspace files in #{directory}" unless @calculated || directory.empty? || directory == '*'
|
|
65
|
-
@calculated ||= included - excluded
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# An array of domains configured for the workspace.
|
|
69
|
-
# A domain is a namespace that the ApiMap should include in the global
|
|
70
|
-
# namespace. It's typically used to identify available DSLs.
|
|
71
|
-
#
|
|
72
|
-
# @return [Array<String>]
|
|
73
|
-
def domains
|
|
74
|
-
raw_data['domains']
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# An array of required paths to add to the workspace.
|
|
78
|
-
#
|
|
79
|
-
# @return [Array<String>]
|
|
80
|
-
def required
|
|
81
|
-
raw_data['require']
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
# An array of load paths for required paths.
|
|
85
|
-
#
|
|
86
|
-
# @return [Array<String>]
|
|
87
|
-
def require_paths
|
|
88
|
-
raw_data['require_paths'] || []
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# An array of Solargraph plugins to install.
|
|
92
|
-
#
|
|
93
|
-
# @return [Array<String>]
|
|
94
|
-
def plugins
|
|
95
|
-
raw_data['plugins']
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# An array of reporters to use for diagnostics.
|
|
99
|
-
#
|
|
100
|
-
# @return [Array<String>]
|
|
101
|
-
def reporters
|
|
102
|
-
raw_data['reporters']
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# The maximum number of files to parse from the workspace.
|
|
106
|
-
#
|
|
107
|
-
# @return [Integer]
|
|
108
|
-
def max_files
|
|
109
|
-
raw_data['max_files']
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
private
|
|
113
|
-
|
|
114
|
-
# Get an array of files from the provided globs.
|
|
115
|
-
#
|
|
116
|
-
# @param globs [Array<String>]
|
|
117
|
-
# @return [Array<String>]
|
|
118
|
-
def process_globs globs
|
|
119
|
-
result = []
|
|
120
|
-
globs.each do |glob|
|
|
121
|
-
result.concat Dir[File.join directory, glob].map{ |f| f.gsub(/\\/, '/') }
|
|
122
|
-
end
|
|
123
|
-
result
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# Modify the included files based on excluded directories and get an
|
|
127
|
-
# array of additional files to exclude.
|
|
128
|
-
#
|
|
129
|
-
# @param globs [Array<String>]
|
|
130
|
-
# @return [Array<String>]
|
|
131
|
-
def process_exclusions globs
|
|
132
|
-
remainder = globs.select do |glob|
|
|
133
|
-
if glob_is_directory?(glob)
|
|
134
|
-
exdir = File.join(directory, glob_to_directory(glob))
|
|
135
|
-
included.delete_if { |file| file.start_with?(exdir) }
|
|
136
|
-
false
|
|
137
|
-
else
|
|
138
|
-
true
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
process_globs remainder
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# True if the glob translates to a whole directory.
|
|
145
|
-
#
|
|
146
|
-
# @example
|
|
147
|
-
# glob_is_directory?('path/to/dir') # => true
|
|
148
|
-
# glob_is_directory?('path/to/dir/**/*) # => true
|
|
149
|
-
# glob_is_directory?('path/to/file.txt') # => false
|
|
150
|
-
# glob_is_directory?('path/to/*.txt') # => false
|
|
151
|
-
#
|
|
152
|
-
# @param glob [String]
|
|
153
|
-
# @return [Boolean]
|
|
154
|
-
def glob_is_directory? glob
|
|
155
|
-
File.directory?(glob) || File.directory?(glob_to_directory(glob))
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# Translate a glob to a base directory if applicable
|
|
159
|
-
#
|
|
160
|
-
# @example
|
|
161
|
-
# glob_to_directory('path/to/dir/**/*') # => 'path/to/dir'
|
|
162
|
-
#
|
|
163
|
-
# @param glob [String]
|
|
164
|
-
# @return [String]
|
|
165
|
-
def glob_to_directory glob
|
|
166
|
-
glob.gsub(/(\/\*|\/\*\*\/\*\*?)$/, '')
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Workspace
|
|
5
|
+
# Configuration data for a workspace.
|
|
6
|
+
#
|
|
7
|
+
class Config
|
|
8
|
+
# The maximum number of files that can be added to a workspace.
|
|
9
|
+
# The workspace's .solargraph.yml can override this value.
|
|
10
|
+
MAX_FILES = 5000
|
|
11
|
+
|
|
12
|
+
# @return [String]
|
|
13
|
+
attr_reader :directory
|
|
14
|
+
|
|
15
|
+
# @return [Hash]
|
|
16
|
+
attr_reader :raw_data
|
|
17
|
+
|
|
18
|
+
# @param directory [String]
|
|
19
|
+
def initialize directory = ''
|
|
20
|
+
@directory = directory
|
|
21
|
+
include_globs = ['**/*.rb']
|
|
22
|
+
exclude_globs = ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*']
|
|
23
|
+
unless @directory.empty?
|
|
24
|
+
sfile = File.join(@directory, '.solargraph.yml')
|
|
25
|
+
if File.file?(sfile)
|
|
26
|
+
@raw_data = YAML.safe_load(File.read(sfile))
|
|
27
|
+
include_globs = @raw_data['include'] || include_globs
|
|
28
|
+
exclude_globs = @raw_data['exclude'] || []
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
@raw_data ||= {}
|
|
32
|
+
@raw_data['include'] ||= include_globs
|
|
33
|
+
@raw_data['exclude'] ||= exclude_globs
|
|
34
|
+
@raw_data['require'] ||= []
|
|
35
|
+
@raw_data['domains'] ||= []
|
|
36
|
+
@raw_data['reporters'] ||= %w[rubocop require_not_found]
|
|
37
|
+
@raw_data['plugins'] ||= []
|
|
38
|
+
@raw_data['require_paths'] ||= []
|
|
39
|
+
@raw_data['max_files'] ||= MAX_FILES
|
|
40
|
+
included
|
|
41
|
+
excluded
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# An array of files included in the workspace (before calculating excluded files).
|
|
45
|
+
#
|
|
46
|
+
# @return [Array<String>]
|
|
47
|
+
def included
|
|
48
|
+
return [] if directory.empty? || directory == '*'
|
|
49
|
+
@included ||= process_globs(@raw_data['include'])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# An array of files excluded from the workspace.
|
|
53
|
+
#
|
|
54
|
+
# @return [Array<String>]
|
|
55
|
+
def excluded
|
|
56
|
+
return [] if directory.empty? || directory == '*'
|
|
57
|
+
@excluded ||= process_exclusions(@raw_data['exclude'])
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The calculated array of (included - excluded) files in the workspace.
|
|
61
|
+
#
|
|
62
|
+
# @return [Array<String>]
|
|
63
|
+
def calculated
|
|
64
|
+
Solargraph.logger.info "Indexing workspace files in #{directory}" unless @calculated || directory.empty? || directory == '*'
|
|
65
|
+
@calculated ||= included - excluded
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# An array of domains configured for the workspace.
|
|
69
|
+
# A domain is a namespace that the ApiMap should include in the global
|
|
70
|
+
# namespace. It's typically used to identify available DSLs.
|
|
71
|
+
#
|
|
72
|
+
# @return [Array<String>]
|
|
73
|
+
def domains
|
|
74
|
+
raw_data['domains']
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# An array of required paths to add to the workspace.
|
|
78
|
+
#
|
|
79
|
+
# @return [Array<String>]
|
|
80
|
+
def required
|
|
81
|
+
raw_data['require']
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# An array of load paths for required paths.
|
|
85
|
+
#
|
|
86
|
+
# @return [Array<String>]
|
|
87
|
+
def require_paths
|
|
88
|
+
raw_data['require_paths'] || []
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# An array of Solargraph plugins to install.
|
|
92
|
+
#
|
|
93
|
+
# @return [Array<String>]
|
|
94
|
+
def plugins
|
|
95
|
+
raw_data['plugins']
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# An array of reporters to use for diagnostics.
|
|
99
|
+
#
|
|
100
|
+
# @return [Array<String>]
|
|
101
|
+
def reporters
|
|
102
|
+
raw_data['reporters']
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# The maximum number of files to parse from the workspace.
|
|
106
|
+
#
|
|
107
|
+
# @return [Integer]
|
|
108
|
+
def max_files
|
|
109
|
+
raw_data['max_files']
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
# Get an array of files from the provided globs.
|
|
115
|
+
#
|
|
116
|
+
# @param globs [Array<String>]
|
|
117
|
+
# @return [Array<String>]
|
|
118
|
+
def process_globs globs
|
|
119
|
+
result = []
|
|
120
|
+
globs.each do |glob|
|
|
121
|
+
result.concat Dir[File.join directory, glob].map{ |f| f.gsub(/\\/, '/') }
|
|
122
|
+
end
|
|
123
|
+
result
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Modify the included files based on excluded directories and get an
|
|
127
|
+
# array of additional files to exclude.
|
|
128
|
+
#
|
|
129
|
+
# @param globs [Array<String>]
|
|
130
|
+
# @return [Array<String>]
|
|
131
|
+
def process_exclusions globs
|
|
132
|
+
remainder = globs.select do |glob|
|
|
133
|
+
if glob_is_directory?(glob)
|
|
134
|
+
exdir = File.join(directory, glob_to_directory(glob))
|
|
135
|
+
included.delete_if { |file| file.start_with?(exdir) }
|
|
136
|
+
false
|
|
137
|
+
else
|
|
138
|
+
true
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
process_globs remainder
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# True if the glob translates to a whole directory.
|
|
145
|
+
#
|
|
146
|
+
# @example
|
|
147
|
+
# glob_is_directory?('path/to/dir') # => true
|
|
148
|
+
# glob_is_directory?('path/to/dir/**/*) # => true
|
|
149
|
+
# glob_is_directory?('path/to/file.txt') # => false
|
|
150
|
+
# glob_is_directory?('path/to/*.txt') # => false
|
|
151
|
+
#
|
|
152
|
+
# @param glob [String]
|
|
153
|
+
# @return [Boolean]
|
|
154
|
+
def glob_is_directory? glob
|
|
155
|
+
File.directory?(glob) || File.directory?(glob_to_directory(glob))
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Translate a glob to a base directory if applicable
|
|
159
|
+
#
|
|
160
|
+
# @example
|
|
161
|
+
# glob_to_directory('path/to/dir/**/*') # => 'path/to/dir'
|
|
162
|
+
#
|
|
163
|
+
# @param glob [String]
|
|
164
|
+
# @return [String]
|
|
165
|
+
def glob_to_directory glob
|
|
166
|
+
glob.gsub(/(\/\*|\/\*\*\/\*\*?)$/, '')
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
data/lib/solargraph/yard_map.rb
CHANGED
|
@@ -1,298 +1,298 @@
|
|
|
1
|
-
require 'yard'
|
|
2
|
-
|
|
3
|
-
module Solargraph
|
|
4
|
-
# The YardMap provides access to YARD documentation for the Ruby core, the
|
|
5
|
-
# stdlib, and gems.
|
|
6
|
-
#
|
|
7
|
-
class YardMap
|
|
8
|
-
autoload :Cache, 'solargraph/yard_map/cache'
|
|
9
|
-
autoload :CoreDocs, 'solargraph/yard_map/core_docs'
|
|
10
|
-
autoload :CoreGen, 'solargraph/yard_map/core_gen'
|
|
11
|
-
|
|
12
|
-
CoreDocs.require_minimum
|
|
13
|
-
@@stdlib_yardoc = CoreDocs.yardoc_stdlib_file
|
|
14
|
-
@@stdlib_paths = {}
|
|
15
|
-
YARD::Registry.load! @@stdlib_yardoc
|
|
16
|
-
YARD::Registry.all(:class, :module).each do |ns|
|
|
17
|
-
next if ns.file.nil?
|
|
18
|
-
path = ns.file.sub(/^(ext|lib)\//, '').sub(/\.(rb|c)$/, '')
|
|
19
|
-
next if path.start_with?('-')
|
|
20
|
-
@@stdlib_paths[path] ||= []
|
|
21
|
-
@@stdlib_paths[path].push ns
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# @return [Array<String>]
|
|
25
|
-
attr_reader :required
|
|
26
|
-
|
|
27
|
-
attr_writer :with_dependencies
|
|
28
|
-
|
|
29
|
-
# @param required [Array<String>]
|
|
30
|
-
# @param with_dependencies [Boolean]
|
|
31
|
-
def initialize(required: [], with_dependencies: true)
|
|
32
|
-
# HACK: YardMap needs its own copy of this array
|
|
33
|
-
@required = required.clone
|
|
34
|
-
@with_dependencies = with_dependencies
|
|
35
|
-
@gem_paths = {}
|
|
36
|
-
@stdlib_namespaces = []
|
|
37
|
-
process_requires
|
|
38
|
-
yardocs.uniq!
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# @return [Array<Solargraph::Pin::Base>]
|
|
42
|
-
def pins
|
|
43
|
-
@pins ||= []
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def with_dependencies?
|
|
47
|
-
@with_dependencies ||= true unless @with_dependencies == false
|
|
48
|
-
@with_dependencies
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# @param new_requires [Array<String>]
|
|
52
|
-
# @return [Boolean]
|
|
53
|
-
def change new_requires
|
|
54
|
-
if new_requires.uniq.sort == required.uniq.sort
|
|
55
|
-
false
|
|
56
|
-
else
|
|
57
|
-
required.clear
|
|
58
|
-
required.concat new_requires
|
|
59
|
-
process_requires
|
|
60
|
-
true
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# @return [Array<String>]
|
|
65
|
-
def yardocs
|
|
66
|
-
@yardocs ||= []
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# @return [Array<String>]
|
|
70
|
-
def unresolved_requires
|
|
71
|
-
@unresolved_requires ||= []
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# @param y [String]
|
|
75
|
-
# @return [YARD::Registry]
|
|
76
|
-
def load_yardoc y
|
|
77
|
-
if y.kind_of?(Array)
|
|
78
|
-
YARD::Registry.load y, true
|
|
79
|
-
else
|
|
80
|
-
YARD::Registry.load! y
|
|
81
|
-
end
|
|
82
|
-
rescue Exception => e
|
|
83
|
-
Solargraph::Logging.logger.warn "Error loading yardoc '#{y}' #{e.class} #{e.message}"
|
|
84
|
-
yardocs.delete y
|
|
85
|
-
nil
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# @return [Array<Solargraph::Pin::Base>]
|
|
89
|
-
def core_pins
|
|
90
|
-
@@core_pins ||= begin
|
|
91
|
-
result = []
|
|
92
|
-
load_yardoc CoreDocs.yardoc_file
|
|
93
|
-
YARD::Registry.each do |o|
|
|
94
|
-
result.concat generate_pins(o)
|
|
95
|
-
end
|
|
96
|
-
result
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# @param path [String]
|
|
101
|
-
# @return [Pin::Base]
|
|
102
|
-
def path_pin path
|
|
103
|
-
pins.select{ |p| p.path == path }.first
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
private
|
|
107
|
-
|
|
108
|
-
# @return [YardMap::Cache]
|
|
109
|
-
def cache
|
|
110
|
-
@cache ||= YardMap::Cache.new
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
# @param ns [YARD::CodeObjects::Namespace]
|
|
114
|
-
# @return [Array<Solargraph::Pin::Base>]
|
|
115
|
-
def recurse_namespace_object ns
|
|
116
|
-
result = []
|
|
117
|
-
ns.children.each do |c|
|
|
118
|
-
result.concat generate_pins(c)
|
|
119
|
-
result.concat recurse_namespace_object(c) if c.respond_to?(:children)
|
|
120
|
-
end
|
|
121
|
-
result
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# @param code_object [YARD::CodeObjects::Base]
|
|
125
|
-
# @return [Solargraph::Pin::Base]
|
|
126
|
-
def generate_pins code_object, spec = nil
|
|
127
|
-
result = []
|
|
128
|
-
location = object_location(code_object, spec)
|
|
129
|
-
if code_object.is_a?(YARD::CodeObjects::NamespaceObject)
|
|
130
|
-
result.push Solargraph::Pin::YardPin::Namespace.new(code_object, location)
|
|
131
|
-
if code_object.is_a?(YARD::CodeObjects::ClassObject) and !code_object.superclass.nil?
|
|
132
|
-
# @todo This method of superclass detection is a bit of a hack. If
|
|
133
|
-
# the superclass is a Proxy, it is assumed to be undefined in its
|
|
134
|
-
# yardoc and converted to a fully qualified namespace.
|
|
135
|
-
if code_object.superclass.is_a?(YARD::CodeObjects::Proxy)
|
|
136
|
-
superclass = "::#{code_object.superclass}"
|
|
137
|
-
else
|
|
138
|
-
superclass = code_object.superclass.to_s
|
|
139
|
-
end
|
|
140
|
-
result.push Solargraph::Pin::Reference::Superclass.new(location, code_object.path, superclass)
|
|
141
|
-
end
|
|
142
|
-
code_object.class_mixins.each do |m|
|
|
143
|
-
result.push Solargraph::Pin::Reference::Extend.new(location, code_object.path, m.path)
|
|
144
|
-
end
|
|
145
|
-
code_object.instance_mixins.each do |m|
|
|
146
|
-
result.push Solargraph::Pin::Reference::Include.new(location, code_object.path, m.path)
|
|
147
|
-
end
|
|
148
|
-
elsif code_object.is_a?(YARD::CodeObjects::MethodObject)
|
|
149
|
-
if code_object.name == :initialize && code_object.scope == :instance
|
|
150
|
-
# @todo Check the visibility of <Class>.new
|
|
151
|
-
result.push Solargraph::Pin::YardPin::Method.new(code_object, location, 'new', :class, :public)
|
|
152
|
-
result.push Solargraph::Pin::YardPin::Method.new(code_object, location, 'initialize', :instance, :private)
|
|
153
|
-
else
|
|
154
|
-
result.push Solargraph::Pin::YardPin::Method.new(code_object, location)
|
|
155
|
-
end
|
|
156
|
-
elsif code_object.is_a?(YARD::CodeObjects::ConstantObject)
|
|
157
|
-
result.push Solargraph::Pin::YardPin::Constant.new(code_object, location)
|
|
158
|
-
end
|
|
159
|
-
result
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
# @return [void]
|
|
163
|
-
def process_requires
|
|
164
|
-
pins.clear
|
|
165
|
-
unresolved_requires.clear
|
|
166
|
-
stdnames = {}
|
|
167
|
-
done = []
|
|
168
|
-
required.each do |r|
|
|
169
|
-
next if r.nil? || r.empty? || done.include?(r)
|
|
170
|
-
done.push r
|
|
171
|
-
cached = cache.get_path_pins(r)
|
|
172
|
-
unless cached.nil?
|
|
173
|
-
pins.concat cached
|
|
174
|
-
next
|
|
175
|
-
end
|
|
176
|
-
result = []
|
|
177
|
-
begin
|
|
178
|
-
spec = Gem::Specification.find_by_path(r) || Gem::Specification.find_by_name(r.split('/').first)
|
|
179
|
-
ver = spec.version.to_s
|
|
180
|
-
ver = ">= 0" if ver.empty?
|
|
181
|
-
yd = YARD::Registry.yardoc_file_for_gem(spec.name, ver)
|
|
182
|
-
# YARD detects gems for certain libraries that do not have a yardoc
|
|
183
|
-
# but exist in the stdlib. `fileutils` is an example. Treat those
|
|
184
|
-
# cases as errors and check the stdlib yardoc.
|
|
185
|
-
raise Gem::LoadError if yd.nil?
|
|
186
|
-
@gem_paths[spec.name] = spec.full_gem_path
|
|
187
|
-
unless yardocs.include?(yd)
|
|
188
|
-
yardocs.unshift yd
|
|
189
|
-
result.concat process_yardoc yd, spec
|
|
190
|
-
result.concat add_gem_dependencies(spec) if with_dependencies?
|
|
191
|
-
end
|
|
192
|
-
rescue Gem::LoadError => e
|
|
193
|
-
stdtmp = []
|
|
194
|
-
@@stdlib_paths.each_pair do |path, objects|
|
|
195
|
-
stdtmp.concat objects if path == r || path.start_with?("#{r}/")
|
|
196
|
-
end
|
|
197
|
-
if stdtmp.empty?
|
|
198
|
-
unresolved_requires.push r
|
|
199
|
-
else
|
|
200
|
-
stdnames[r] = stdtmp
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
result.delete_if(&:nil?)
|
|
204
|
-
unless result.empty?
|
|
205
|
-
cache.set_path_pins r, result
|
|
206
|
-
pins.concat result
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
pins.concat process_stdlib(stdnames)
|
|
210
|
-
pins.concat core_pins
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
# @param required_namespaces [Array<YARD::CodeObjects::Namespace>]
|
|
214
|
-
# @return [Array<Solargraph::Pin::Base>]
|
|
215
|
-
def process_stdlib required_namespaces
|
|
216
|
-
pins = []
|
|
217
|
-
unless required_namespaces.empty?
|
|
218
|
-
yard = load_yardoc @@stdlib_yardoc
|
|
219
|
-
done = []
|
|
220
|
-
required_namespaces.each_pair do |r, objects|
|
|
221
|
-
result = []
|
|
222
|
-
objects.each do |ns|
|
|
223
|
-
next if done.include?(ns.path)
|
|
224
|
-
done.push ns.path
|
|
225
|
-
result.concat generate_pins(ns)
|
|
226
|
-
result.concat recurse_namespace_object(ns)
|
|
227
|
-
end
|
|
228
|
-
result.delete_if(&:nil?)
|
|
229
|
-
cache.set_path_pins(r, result) unless result.empty?
|
|
230
|
-
pins.concat result
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
pins
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
# @param spec [Gem::Specification]
|
|
237
|
-
# @return [void]
|
|
238
|
-
def add_gem_dependencies spec
|
|
239
|
-
result = []
|
|
240
|
-
(spec.dependencies - spec.development_dependencies).each do |dep|
|
|
241
|
-
begin
|
|
242
|
-
depspec = Gem::Specification.find_by_name(dep.name)
|
|
243
|
-
next if depspec.nil? || @gem_paths.key?(depspec.name)
|
|
244
|
-
@gem_paths[depspec.name] = depspec.full_gem_path
|
|
245
|
-
gy = YARD::Registry.yardoc_file_for_gem(dep.name)
|
|
246
|
-
if gy.nil?
|
|
247
|
-
unresolved_requires.push dep.name
|
|
248
|
-
else
|
|
249
|
-
next if yardocs.include?(gy)
|
|
250
|
-
yardocs.unshift gy
|
|
251
|
-
result.concat process_yardoc gy, depspec
|
|
252
|
-
result.concat add_gem_dependencies(depspec)
|
|
253
|
-
end
|
|
254
|
-
rescue Gem::LoadError
|
|
255
|
-
# This error probably indicates a bug in an installed gem
|
|
256
|
-
Solargraph::Logging.logger.warn "Failed to resolve #{dep.name} gem dependency for #{spec.name}"
|
|
257
|
-
end
|
|
258
|
-
end
|
|
259
|
-
result
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
# @param y [String, nil]
|
|
263
|
-
# @return [Array<Pin::Base>]
|
|
264
|
-
def process_yardoc y, spec = nil
|
|
265
|
-
return [] if y.nil?
|
|
266
|
-
size = Dir.glob(File.join(y, '**', '*'))
|
|
267
|
-
.map{ |f| File.size(f) }
|
|
268
|
-
.inject(:+)
|
|
269
|
-
if !size.nil? && size > 20_000_000
|
|
270
|
-
Solargraph::Logging.logger.warn "Yardoc at #{y} is too large to process (#{size} bytes)"
|
|
271
|
-
return []
|
|
272
|
-
end
|
|
273
|
-
result = []
|
|
274
|
-
load_yardoc y
|
|
275
|
-
YARD::Registry.each do |o|
|
|
276
|
-
result.concat generate_pins(o, spec)
|
|
277
|
-
end
|
|
278
|
-
result
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
# @param obj [YARD::CodeObjects::Base]
|
|
282
|
-
# @return [Solargraph::Location]
|
|
283
|
-
def object_location obj, spec = nil
|
|
284
|
-
@object_file_cache ||= {}
|
|
285
|
-
return nil if spec.nil? || obj.file.nil? || obj.line.nil?
|
|
286
|
-
file = nil
|
|
287
|
-
if @object_file_cache.key?(obj.file)
|
|
288
|
-
file = @object_file_cache[obj.file]
|
|
289
|
-
else
|
|
290
|
-
tmp = File.join(spec.full_gem_path, obj.file)
|
|
291
|
-
file = tmp if File.exist?(tmp)
|
|
292
|
-
@object_file_cache[obj.file] = file
|
|
293
|
-
end
|
|
294
|
-
return nil if file.nil?
|
|
295
|
-
Solargraph::Location.new(file, Solargraph::Range.from_to(obj.line - 1, 0, obj.line - 1, 0))
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
end
|
|
1
|
+
require 'yard'
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
# The YardMap provides access to YARD documentation for the Ruby core, the
|
|
5
|
+
# stdlib, and gems.
|
|
6
|
+
#
|
|
7
|
+
class YardMap
|
|
8
|
+
autoload :Cache, 'solargraph/yard_map/cache'
|
|
9
|
+
autoload :CoreDocs, 'solargraph/yard_map/core_docs'
|
|
10
|
+
autoload :CoreGen, 'solargraph/yard_map/core_gen'
|
|
11
|
+
|
|
12
|
+
CoreDocs.require_minimum
|
|
13
|
+
@@stdlib_yardoc = CoreDocs.yardoc_stdlib_file
|
|
14
|
+
@@stdlib_paths = {}
|
|
15
|
+
YARD::Registry.load! @@stdlib_yardoc
|
|
16
|
+
YARD::Registry.all(:class, :module).each do |ns|
|
|
17
|
+
next if ns.file.nil?
|
|
18
|
+
path = ns.file.sub(/^(ext|lib)\//, '').sub(/\.(rb|c)$/, '')
|
|
19
|
+
next if path.start_with?('-')
|
|
20
|
+
@@stdlib_paths[path] ||= []
|
|
21
|
+
@@stdlib_paths[path].push ns
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Array<String>]
|
|
25
|
+
attr_reader :required
|
|
26
|
+
|
|
27
|
+
attr_writer :with_dependencies
|
|
28
|
+
|
|
29
|
+
# @param required [Array<String>]
|
|
30
|
+
# @param with_dependencies [Boolean]
|
|
31
|
+
def initialize(required: [], with_dependencies: true)
|
|
32
|
+
# HACK: YardMap needs its own copy of this array
|
|
33
|
+
@required = required.clone
|
|
34
|
+
@with_dependencies = with_dependencies
|
|
35
|
+
@gem_paths = {}
|
|
36
|
+
@stdlib_namespaces = []
|
|
37
|
+
process_requires
|
|
38
|
+
yardocs.uniq!
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
42
|
+
def pins
|
|
43
|
+
@pins ||= []
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def with_dependencies?
|
|
47
|
+
@with_dependencies ||= true unless @with_dependencies == false
|
|
48
|
+
@with_dependencies
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @param new_requires [Array<String>]
|
|
52
|
+
# @return [Boolean]
|
|
53
|
+
def change new_requires
|
|
54
|
+
if new_requires.uniq.sort == required.uniq.sort
|
|
55
|
+
false
|
|
56
|
+
else
|
|
57
|
+
required.clear
|
|
58
|
+
required.concat new_requires
|
|
59
|
+
process_requires
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [Array<String>]
|
|
65
|
+
def yardocs
|
|
66
|
+
@yardocs ||= []
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @return [Array<String>]
|
|
70
|
+
def unresolved_requires
|
|
71
|
+
@unresolved_requires ||= []
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @param y [String]
|
|
75
|
+
# @return [YARD::Registry]
|
|
76
|
+
def load_yardoc y
|
|
77
|
+
if y.kind_of?(Array)
|
|
78
|
+
YARD::Registry.load y, true
|
|
79
|
+
else
|
|
80
|
+
YARD::Registry.load! y
|
|
81
|
+
end
|
|
82
|
+
rescue Exception => e
|
|
83
|
+
Solargraph::Logging.logger.warn "Error loading yardoc '#{y}' #{e.class} #{e.message}"
|
|
84
|
+
yardocs.delete y
|
|
85
|
+
nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
89
|
+
def core_pins
|
|
90
|
+
@@core_pins ||= begin
|
|
91
|
+
result = []
|
|
92
|
+
load_yardoc CoreDocs.yardoc_file
|
|
93
|
+
YARD::Registry.each do |o|
|
|
94
|
+
result.concat generate_pins(o)
|
|
95
|
+
end
|
|
96
|
+
result
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @param path [String]
|
|
101
|
+
# @return [Pin::Base]
|
|
102
|
+
def path_pin path
|
|
103
|
+
pins.select{ |p| p.path == path }.first
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
# @return [YardMap::Cache]
|
|
109
|
+
def cache
|
|
110
|
+
@cache ||= YardMap::Cache.new
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# @param ns [YARD::CodeObjects::Namespace]
|
|
114
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
115
|
+
def recurse_namespace_object ns
|
|
116
|
+
result = []
|
|
117
|
+
ns.children.each do |c|
|
|
118
|
+
result.concat generate_pins(c)
|
|
119
|
+
result.concat recurse_namespace_object(c) if c.respond_to?(:children)
|
|
120
|
+
end
|
|
121
|
+
result
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @param code_object [YARD::CodeObjects::Base]
|
|
125
|
+
# @return [Solargraph::Pin::Base]
|
|
126
|
+
def generate_pins code_object, spec = nil
|
|
127
|
+
result = []
|
|
128
|
+
location = object_location(code_object, spec)
|
|
129
|
+
if code_object.is_a?(YARD::CodeObjects::NamespaceObject)
|
|
130
|
+
result.push Solargraph::Pin::YardPin::Namespace.new(code_object, location)
|
|
131
|
+
if code_object.is_a?(YARD::CodeObjects::ClassObject) and !code_object.superclass.nil?
|
|
132
|
+
# @todo This method of superclass detection is a bit of a hack. If
|
|
133
|
+
# the superclass is a Proxy, it is assumed to be undefined in its
|
|
134
|
+
# yardoc and converted to a fully qualified namespace.
|
|
135
|
+
if code_object.superclass.is_a?(YARD::CodeObjects::Proxy)
|
|
136
|
+
superclass = "::#{code_object.superclass}"
|
|
137
|
+
else
|
|
138
|
+
superclass = code_object.superclass.to_s
|
|
139
|
+
end
|
|
140
|
+
result.push Solargraph::Pin::Reference::Superclass.new(location, code_object.path, superclass)
|
|
141
|
+
end
|
|
142
|
+
code_object.class_mixins.each do |m|
|
|
143
|
+
result.push Solargraph::Pin::Reference::Extend.new(location, code_object.path, m.path)
|
|
144
|
+
end
|
|
145
|
+
code_object.instance_mixins.each do |m|
|
|
146
|
+
result.push Solargraph::Pin::Reference::Include.new(location, code_object.path, m.path)
|
|
147
|
+
end
|
|
148
|
+
elsif code_object.is_a?(YARD::CodeObjects::MethodObject)
|
|
149
|
+
if code_object.name == :initialize && code_object.scope == :instance
|
|
150
|
+
# @todo Check the visibility of <Class>.new
|
|
151
|
+
result.push Solargraph::Pin::YardPin::Method.new(code_object, location, 'new', :class, :public)
|
|
152
|
+
result.push Solargraph::Pin::YardPin::Method.new(code_object, location, 'initialize', :instance, :private)
|
|
153
|
+
else
|
|
154
|
+
result.push Solargraph::Pin::YardPin::Method.new(code_object, location)
|
|
155
|
+
end
|
|
156
|
+
elsif code_object.is_a?(YARD::CodeObjects::ConstantObject)
|
|
157
|
+
result.push Solargraph::Pin::YardPin::Constant.new(code_object, location)
|
|
158
|
+
end
|
|
159
|
+
result
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# @return [void]
|
|
163
|
+
def process_requires
|
|
164
|
+
pins.clear
|
|
165
|
+
unresolved_requires.clear
|
|
166
|
+
stdnames = {}
|
|
167
|
+
done = []
|
|
168
|
+
required.each do |r|
|
|
169
|
+
next if r.nil? || r.empty? || done.include?(r)
|
|
170
|
+
done.push r
|
|
171
|
+
cached = cache.get_path_pins(r)
|
|
172
|
+
unless cached.nil?
|
|
173
|
+
pins.concat cached
|
|
174
|
+
next
|
|
175
|
+
end
|
|
176
|
+
result = []
|
|
177
|
+
begin
|
|
178
|
+
spec = Gem::Specification.find_by_path(r) || Gem::Specification.find_by_name(r.split('/').first)
|
|
179
|
+
ver = spec.version.to_s
|
|
180
|
+
ver = ">= 0" if ver.empty?
|
|
181
|
+
yd = YARD::Registry.yardoc_file_for_gem(spec.name, ver)
|
|
182
|
+
# YARD detects gems for certain libraries that do not have a yardoc
|
|
183
|
+
# but exist in the stdlib. `fileutils` is an example. Treat those
|
|
184
|
+
# cases as errors and check the stdlib yardoc.
|
|
185
|
+
raise Gem::LoadError if yd.nil?
|
|
186
|
+
@gem_paths[spec.name] = spec.full_gem_path
|
|
187
|
+
unless yardocs.include?(yd)
|
|
188
|
+
yardocs.unshift yd
|
|
189
|
+
result.concat process_yardoc yd, spec
|
|
190
|
+
result.concat add_gem_dependencies(spec) if with_dependencies?
|
|
191
|
+
end
|
|
192
|
+
rescue Gem::LoadError => e
|
|
193
|
+
stdtmp = []
|
|
194
|
+
@@stdlib_paths.each_pair do |path, objects|
|
|
195
|
+
stdtmp.concat objects if path == r || path.start_with?("#{r}/")
|
|
196
|
+
end
|
|
197
|
+
if stdtmp.empty?
|
|
198
|
+
unresolved_requires.push r
|
|
199
|
+
else
|
|
200
|
+
stdnames[r] = stdtmp
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
result.delete_if(&:nil?)
|
|
204
|
+
unless result.empty?
|
|
205
|
+
cache.set_path_pins r, result
|
|
206
|
+
pins.concat result
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
pins.concat process_stdlib(stdnames)
|
|
210
|
+
pins.concat core_pins
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# @param required_namespaces [Array<YARD::CodeObjects::Namespace>]
|
|
214
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
215
|
+
def process_stdlib required_namespaces
|
|
216
|
+
pins = []
|
|
217
|
+
unless required_namespaces.empty?
|
|
218
|
+
yard = load_yardoc @@stdlib_yardoc
|
|
219
|
+
done = []
|
|
220
|
+
required_namespaces.each_pair do |r, objects|
|
|
221
|
+
result = []
|
|
222
|
+
objects.each do |ns|
|
|
223
|
+
next if done.include?(ns.path)
|
|
224
|
+
done.push ns.path
|
|
225
|
+
result.concat generate_pins(ns)
|
|
226
|
+
result.concat recurse_namespace_object(ns)
|
|
227
|
+
end
|
|
228
|
+
result.delete_if(&:nil?)
|
|
229
|
+
cache.set_path_pins(r, result) unless result.empty?
|
|
230
|
+
pins.concat result
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
pins
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# @param spec [Gem::Specification]
|
|
237
|
+
# @return [void]
|
|
238
|
+
def add_gem_dependencies spec
|
|
239
|
+
result = []
|
|
240
|
+
(spec.dependencies - spec.development_dependencies).each do |dep|
|
|
241
|
+
begin
|
|
242
|
+
depspec = Gem::Specification.find_by_name(dep.name)
|
|
243
|
+
next if depspec.nil? || @gem_paths.key?(depspec.name)
|
|
244
|
+
@gem_paths[depspec.name] = depspec.full_gem_path
|
|
245
|
+
gy = YARD::Registry.yardoc_file_for_gem(dep.name)
|
|
246
|
+
if gy.nil?
|
|
247
|
+
unresolved_requires.push dep.name
|
|
248
|
+
else
|
|
249
|
+
next if yardocs.include?(gy)
|
|
250
|
+
yardocs.unshift gy
|
|
251
|
+
result.concat process_yardoc gy, depspec
|
|
252
|
+
result.concat add_gem_dependencies(depspec)
|
|
253
|
+
end
|
|
254
|
+
rescue Gem::LoadError
|
|
255
|
+
# This error probably indicates a bug in an installed gem
|
|
256
|
+
Solargraph::Logging.logger.warn "Failed to resolve #{dep.name} gem dependency for #{spec.name}"
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
result
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# @param y [String, nil]
|
|
263
|
+
# @return [Array<Pin::Base>]
|
|
264
|
+
def process_yardoc y, spec = nil
|
|
265
|
+
return [] if y.nil?
|
|
266
|
+
size = Dir.glob(File.join(y, '**', '*'))
|
|
267
|
+
.map{ |f| File.size(f) }
|
|
268
|
+
.inject(:+)
|
|
269
|
+
if !size.nil? && size > 20_000_000
|
|
270
|
+
Solargraph::Logging.logger.warn "Yardoc at #{y} is too large to process (#{size} bytes)"
|
|
271
|
+
return []
|
|
272
|
+
end
|
|
273
|
+
result = []
|
|
274
|
+
load_yardoc y
|
|
275
|
+
YARD::Registry.each do |o|
|
|
276
|
+
result.concat generate_pins(o, spec)
|
|
277
|
+
end
|
|
278
|
+
result
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# @param obj [YARD::CodeObjects::Base]
|
|
282
|
+
# @return [Solargraph::Location]
|
|
283
|
+
def object_location obj, spec = nil
|
|
284
|
+
@object_file_cache ||= {}
|
|
285
|
+
return nil if spec.nil? || obj.file.nil? || obj.line.nil?
|
|
286
|
+
file = nil
|
|
287
|
+
if @object_file_cache.key?(obj.file)
|
|
288
|
+
file = @object_file_cache[obj.file]
|
|
289
|
+
else
|
|
290
|
+
tmp = File.join(spec.full_gem_path, obj.file)
|
|
291
|
+
file = tmp if File.exist?(tmp)
|
|
292
|
+
@object_file_cache[obj.file] = file
|
|
293
|
+
end
|
|
294
|
+
return nil if file.nil?
|
|
295
|
+
Solargraph::Location.new(file, Solargraph::Range.from_to(obj.line - 1, 0, obj.line - 1, 0))
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|