sorbet 0.5.5841

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b72f815f0182861350618922777098663e7c5815
4
+ data.tar.gz: 6de4663adb5d10acce279bd249fbcb208c60aeaf
5
+ SHA512:
6
+ metadata.gz: fadbd2ab259b46e1481791454260ec447d38eb490766e7ae3c68b9845493e6799059e0605a0ae1c9b3ddcc0d086acabb1b808dde091f740401e6af2398abfc63
7
+ data.tar.gz: ebc49c3a2518b9de112670bb24989b544753e586bc7dbf74975e8a9b9becbb397318ecdb3afa90c0a006f042f6045ef665afe57c6589646b4760775b3fb377f6
data/bin/srb ADDED
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env bash
2
+ #!/usr/bin/env ruby
3
+
4
+ # A total hack, but this file is both a valid ruby script and a bash script.
5
+ =begin 2>/dev/null
6
+
7
+ # From here on in, it is all bash until the last line
8
+
9
+ help_and_exit() {
10
+ cat <<EOF
11
+ A type checker for Ruby
12
+
13
+ Usage:
14
+ srb Same as "srb t"
15
+ srb (init | initialize) Initializes the \`sorbet\` directory
16
+ srb rbi [options] Manage the \`sorbet\` directory
17
+ srb (t | tc | typecheck) [options] Typechecks the code
18
+
19
+ Options:
20
+ -h, --help View help for this subcommand.
21
+ --version Show version.
22
+
23
+ For full help:
24
+ https://sorbet.org
25
+ EOF
26
+ exit 0
27
+ }
28
+
29
+ subcommand=$1
30
+ shift
31
+
32
+ # /path/to/gems/sorbet-0.0.1/bin/srb
33
+ srb_path="${BASH_SOURCE[0]}"
34
+
35
+ compute_md5() {
36
+ if command -v md5sum > /dev/null; then
37
+ md5sum "$1"
38
+ elif command -v md5 > /dev/null; then
39
+ md5 -r "$1"
40
+ else
41
+ # this is quite a bit slower
42
+ ruby -e 'require "digest"; puts Digest::MD5.hexdigest(File.read(ARGV[0]))' "$1"
43
+ fi
44
+ }
45
+
46
+ typecheck() {
47
+ args=("$@")
48
+ cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/sorbet/gem-rbis"
49
+
50
+ if [ -z "$SRB_SKIP_GEM_RBIS" ] && [ -f Gemfile.lock ]; then
51
+ [ -d "$cache_dir" ] || mkdir -p "$cache_dir"
52
+ cache_hash=$(compute_md5 Gemfile.lock | awk '{ print $1 }')
53
+ cache_file="${cache_dir}/${cache_hash}"
54
+ if [ ! -f "$cache_file" ]; then
55
+ $0 rbi find-gem-rbis > /dev/null
56
+ fi
57
+ args+=("@$cache_file")
58
+ fi
59
+
60
+ if [ -n "$SRB_SORBET_EXE" ]; then
61
+ # shellcheck disable=SC2086
62
+ "$SRB_SORBET_EXE" "${args[@]}"
63
+ else
64
+ # We're using bash string operations here to avoid forking.
65
+ # Using dirname / basename / etc. would mean ~15ms for each call.
66
+
67
+ # /path/to/gems/sorbet-0.0.1
68
+ without_bin_srb="${srb_path%/bin/srb}"
69
+ # -0.0.1
70
+ version_suffix="${without_bin_srb##*/sorbet}"
71
+ # /path/to/gems
72
+ gems_path="${without_bin_srb%/sorbet*}"
73
+
74
+ # /path/to/gems/sorbet-static-0.0.1-darwin-17/libexec/sorbet
75
+ # (assumes people only have one platform-depdendent gem installed per version)
76
+ guess_sorbet=("$gems_path/sorbet-static$version_suffix"*/libexec/sorbet)
77
+
78
+ if [[ -f "${guess_sorbet[0]}" ]]; then
79
+ sorbet="${guess_sorbet[0]}"
80
+ else
81
+ # 0.0.1
82
+ version="${version_suffix#-}"
83
+ # Resort to locating using the GEM_PATH, this takes ~200ms
84
+ sorbet="$(VISUAL=echo gem open sorbet-static -v "${version}")/libexec/sorbet"
85
+ fi
86
+
87
+ # if we still don't know the sorbet binary
88
+ # perhaps this is the java platform
89
+ if ! [[ -f "${sorbet}" ]]; then
90
+ if gem env platform | grep -q "java"; then
91
+ # certain platforms (i.e. java) include multiple binaries
92
+ # mac.sorbet & linux.sorbet -- since they can't use the host platform (i.e. darwin or linux)
93
+ # to collect the correct sorbet binary
94
+ case "$(uname -s)" in
95
+ Linux*) prefix="linux.";;
96
+ Darwin*) prefix="mac.";;
97
+ *) prefix=""
98
+ esac
99
+
100
+ guess_sorbet=("$gems_path/sorbet-static$version_suffix"*/libexec/"${prefix}sorbet")
101
+ if [[ -f "${guess_sorbet[0]}" ]]; then
102
+ sorbet="${guess_sorbet[0]}"
103
+ fi
104
+
105
+ fi
106
+ fi
107
+
108
+ # shellcheck disable=SC2086
109
+ "${sorbet}" "${args[@]}"
110
+ fi
111
+ }
112
+
113
+ # Dynamically computing the path to the srb-rbi script lets this script work
114
+ # the same way in local development and when packaged as a gem. Either:
115
+ #
116
+ # /path/to/gems/sorbet-0.0.1/bin/srb-rbi
117
+ # path/to/bin/srb-rbi
118
+ srb_rbi_path="$srb_path-rbi"
119
+
120
+ case $subcommand in
121
+ "initialize" | "init")
122
+ "$srb_rbi_path" "init"
123
+ ;;
124
+
125
+ "rbi")
126
+ "$srb_rbi_path" "$@"
127
+ ;;
128
+
129
+ "" | "typecheck" | "tc" | "t")
130
+ if [ ! -d sorbet ] && [ "$#" -eq 0 ]; then
131
+ echo "No sorbet/ directory found. Maybe you want to run 'srb init'?"
132
+ echo
133
+ help_and_exit
134
+ fi
135
+ typecheck "$@"
136
+ ;;
137
+
138
+ "--version")
139
+ typecheck --version
140
+ ;;
141
+
142
+ *)
143
+ echo "Unknown subcommand \`$subcommand\`"
144
+ help_and_exit
145
+ esac
146
+
147
+ exit $?
148
+ # The closing comment for ruby to be ok with this file
149
+ =end
150
+ exec(__FILE__, *ARGV)
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class Sorbet; end
4
+ module Sorbet::Private; end
5
+
6
+ require_relative '../lib/t'
7
+ require_relative '../lib/step_interface'
8
+ require_relative '../lib/create-config'
9
+ require_relative '../lib/gem-generator-tracepoint'
10
+ require_relative '../lib/hidden-definition-finder'
11
+ require_relative '../lib/fetch-rbis'
12
+ require_relative '../lib/find-gem-rbis'
13
+ require_relative '../lib/suggest-typed'
14
+ require_relative '../lib/todo-rbi'
15
+
16
+ module Sorbet::Private::Main
17
+ def self.usage
18
+ "Usage: srb rbi <command>
19
+ This script gets your current directory ready for using Sorbet by making all sorts of files in ./sorbet/. You should commit them to version control.
20
+
21
+ We recommend running it without any options which will execute all the commands in order. If you only need a certain piece, you can pass a command to just run that part.
22
+
23
+ You should re-run this script if your program ever stops typechecking due to dynamic code in your project.
24
+
25
+ Common Commands:
26
+ help Print this message
27
+ <empty> | update Run all initialization commands
28
+
29
+ Specific Commands:
30
+ config Recreate sorbet/config
31
+ sorbet-typed Download community maintained type definitions for gems
32
+ gems Generate arity-only type definitions by requiring the gem
33
+ hidden-definitions Load all your code and generate type definitions for any dynamic code
34
+ todo Run Sorbet and generate constants which Sorbet errors on
35
+ suggest-typed Put the highest `typed:` sigil in each of your files
36
+ find-gem-rbis Find all `rbi/` directories in your gems and list them in `~/.cache/sorbet`
37
+ "
38
+ end
39
+
40
+ def self.emojify(emoji, msg)
41
+ if STDOUT.isatty && RUBY_PLATFORM =~ /darwin/
42
+ "#{emoji} #{msg}"
43
+ else
44
+ msg
45
+ end
46
+ end
47
+
48
+ def self.yellow(msg)
49
+ if STDOUT.isatty
50
+ "\u001b[0;33m#{msg}\u001b[0m"
51
+ else
52
+ msg
53
+ end
54
+ end
55
+
56
+ def self.cyan(msg)
57
+ if STDOUT.isatty
58
+ "\u001b[0;36m#{msg}\u001b[0m"
59
+ else
60
+ msg
61
+ end
62
+ end
63
+
64
+ def self.init
65
+ puts "
66
+ #{emojify("👋", "Hey there!")}
67
+
68
+ This script will get this project ready to use with Sorbet by creating a
69
+ sorbet/ folder for your project. It will contain:
70
+
71
+ - a config file
72
+ - a bunch of 'RBI files'
73
+
74
+ RBI stands for 'Ruby Interface'; these files define classes, methods, and
75
+ constants that exist, but which Sorbet doesn't always know about.
76
+
77
+ #{emojify("⚠️ ", "Heads up:")}
78
+
79
+ To set up your project, this script will take two potentially destructive
80
+ actions:
81
+
82
+ 1. It will #{yellow("require every file in your project")}. Specifically, every script in
83
+ your project will be run, unless that script checks #{cyan("if __FILE__ == $PROGRAM_NAME")}
84
+ before running any code, or has the magic comment #{cyan("# typed: ignore")} in it.
85
+
86
+ 2. It will add a #{yellow("comment to the top of every file")} (like #{cyan("# typed: false")} or
87
+ #{cyan("# typed: true")}, depending on how many errors were found in that file.)
88
+
89
+ "
90
+ if ENV['SRB_YES'] != nil
91
+ puts "SRB_YES set, continuing"
92
+ else
93
+ STDOUT.write(emojify("❔", "Would you like to continue? [Y/n] "))
94
+ if STDIN.isatty && STDOUT.isatty
95
+ begin
96
+ input = STDIN.gets&.strip
97
+ if input.nil? || (input != '' && input != 'y' && input != 'Y')
98
+ puts "\nAborting"
99
+ Kernel.exit(1)
100
+ end
101
+ rescue Interrupt
102
+ puts "\nAborting"
103
+ Kernel.exit(1)
104
+ end
105
+ else
106
+ puts "\nNot running interactivly. Set SRB_YES=1 environment variable to proceed"
107
+ Kernel.exit(1)
108
+ end
109
+ end
110
+
111
+ # Create sorbet/config file
112
+ make_step(Sorbet::Private::CreateConfig).call
113
+
114
+ # Pull in the hand-written RBIs
115
+ make_step(Sorbet::Private::FetchRBIs).call
116
+
117
+ # Generate the RBIs from bundler
118
+ make_step(Sorbet::Private::GemGeneratorTracepoint).call
119
+
120
+ # Find the hidden methods
121
+ make_step(Sorbet::Private::HiddenMethodFinder).call
122
+
123
+ # Run sorbet and make constants to fix errors
124
+ make_step(Sorbet::Private::TodoRBI).call
125
+
126
+ # Run type suggestion once, and then generate the todo.rbi again.
127
+ #
128
+ # The first time we suggest typed sigils, a few files may be ignored if they
129
+ # use Ruby features Sorbet does not support. However, since we ran the
130
+ # todo.rbi generation before they were ignored, we discovered the constants
131
+ # that they defined and did not add the constants to todo.rbi file.
132
+ #
133
+ # Regenerating after one run of sigil suggestion will put those constants
134
+ # into the todo.rbi file.
135
+ Sorbet::Private::SuggestTyped.suggest_typed
136
+ Sorbet::Private::TodoRBI.main
137
+
138
+ # Put some `typed:` sigils
139
+ make_step(Sorbet::Private::SuggestTyped).call
140
+
141
+ puts "
142
+ #{emojify("✅", "Done!")}
143
+
144
+ This project is now set up for use with Sorbet. The sorbet/ folder should exist
145
+ and look something like this:
146
+
147
+ sorbet/
148
+ #{emojify("├──", " ")}config # Default options to be passed to sorbet on every run
149
+ #{emojify("└──", " ")}rbi/
150
+ #{emojify("├──", " ")}sorbet-typed/ # Community written type definition files for your gems
151
+ #{emojify("├──", " ")}gems/ # Autogenerated type definitions for your gems (from reflection)
152
+ #{emojify("├──", " ")}hidden-definitions/ # All definitions that exist at runtime, but Sorbet couldn't see statically
153
+ #{emojify("└──", " ")}todo.rbi # Constants which were still missing, even after the three steps above.
154
+
155
+ Please check this whole folder into version control.
156
+
157
+ #{emojify("➡️ ", "What's next?")}
158
+
159
+ Up to you! First things first, you'll probably want to typecheck your project:
160
+
161
+ #{cyan("srb tc")}
162
+
163
+ Other than that, it's up to you!
164
+ We recommend skimming these docs to get a feel for how to use Sorbet:
165
+
166
+ - Gradual Type Checking (#{cyan("https://sorbet.org/docs/gradual")})
167
+ - Enabling Static Checks (#{cyan("https://sorbet.org/docs/static")})
168
+ - RBI Files (#{cyan("https://sorbet.org/docs/rbi")})
169
+
170
+ If instead you want to explore your files locally, here are some things to try:
171
+
172
+ - Upgrade a file marked #{cyan("# typed: false")} to #{cyan("# typed: true")}.
173
+ Then, run #{cyan("srb tc")} and try to fix any errors.
174
+ - Add signatures to your methods with `sig`.
175
+ For how, read: #{cyan("https://sorbet.org/docs/sigs")}
176
+ - Check whether things that show up in the TODO RBI file actually exist in your project.
177
+ It's possible some of these constants are typos.
178
+ - Upgrade a file marked #{cyan("# typed: ignore")} to #{cyan("# typed: false")}.
179
+ Then, run #{cyan("srb rbi hidden-definitions && srb tc")} and try to fix any errors.
180
+
181
+ #{emojify("🙌", "Please don't hesitate to give us your feedback!")}
182
+ "
183
+ end
184
+
185
+ def self.main(argv)
186
+ if argv.length == 0
187
+ puts self.usage
188
+ exit(1)
189
+ end
190
+
191
+ command = case (argv[0])
192
+ when 'help', '--help'
193
+ puts self.usage
194
+ exit(1)
195
+ when 'init', 'update'
196
+ self.init
197
+ return
198
+ when 'config', Sorbet::Private::CreateConfig.output_file
199
+ make_step(Sorbet::Private::CreateConfig)
200
+ when 'sorbet-typed', Sorbet::Private::FetchRBIs.output_file, Sorbet::Private::FetchRBIs::SORBET_RBI_LIST
201
+ make_step(Sorbet::Private::FetchRBIs)
202
+ when 'gems', Sorbet::Private::GemGeneratorTracepoint.output_file
203
+ -> do
204
+ make_step(Sorbet::Private::GemGeneratorTracepoint).call
205
+ make_step(Sorbet::Private::SuggestTyped).call
206
+ end
207
+ when 'hidden-definitions', Sorbet::Private::HiddenMethodFinder.output_file
208
+ make_step(Sorbet::Private::HiddenMethodFinder)
209
+ when 'todo', Sorbet::Private::TodoRBI.output_file
210
+ make_step(Sorbet::Private::TodoRBI)
211
+ when 'suggest-typed'
212
+ make_step(Sorbet::Private::SuggestTyped)
213
+
214
+ when 'find-gem-rbis', "#{ENV['HOME']}/.cache/sorbet/gem-rbis", "#{ENV['HOME']}/.cache/sorbet/gem-rbis/"
215
+ make_step(Sorbet::Private::FindGemRBIs)
216
+
217
+ else
218
+ puts "Unknown command: #{argv[0]}"
219
+ puts self.usage
220
+ exit(1)
221
+ end
222
+
223
+ puts "Running command: #{argv[0]}"
224
+ command.call
225
+ nil
226
+ end
227
+
228
+ T::Sig::WithoutRuntime.sig {params(step: Sorbet::Private::StepInterface).returns(T.proc.void)}
229
+ def self.make_step(step)
230
+ -> do
231
+ puts "Generating: #{step.output_file}" if step.output_file
232
+ step.main
233
+ end
234
+ end
235
+ end
236
+
237
+ Sorbet::Private::Main.main(ARGV)
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ require_relative './real_stdlib'
5
+ require_relative './status'
6
+
7
+ # This class walks global namespace to find all modules and discover all of their names.
8
+ # At the time you ask for it it, it takes a "spashot" of the world.
9
+ # If new modules were defined after an instance of this class was created,
10
+ # they won't be visible through a previously returned instance.
11
+ class Sorbet::Private::ConstantLookupCache
12
+
13
+ ConstantEntry = Struct.new(:const_name, :found_name, :primary_name, :aliases, :const, :owner)
14
+
15
+ # We won't be able to see if someone mankeypatches these.
16
+ DEPRECATED_CONSTANTS = [
17
+ '::Bignum',
18
+ '::Config',
19
+ '::Data',
20
+ '::FALSE',
21
+ '::Fixnum',
22
+ '::NIL',
23
+ '::TRUE',
24
+ '::TimeoutError',
25
+ 'ERB::Compiler::SimpleScanner2',
26
+ 'Net::OpenSSL',
27
+ 'Object::Bignum',
28
+ 'Object::Config',
29
+ 'Object::Data',
30
+ 'Object::FALSE',
31
+ 'Object::Fixnum',
32
+ 'Object::NIL',
33
+ 'Object::TRUE',
34
+ 'Object::TimeoutError',
35
+ 'OpenSSL::Cipher::Cipher',
36
+ 'OpenSSL::Cipher::Digest',
37
+ 'OpenSSL::Digest::Cipher',
38
+ 'OpenSSL::Digest::Digest',
39
+ 'OpenSSL::SSL::SSLContext::METHODS',
40
+ 'Pry::Platform',
41
+ 'Pry::Prompt::MAP',
42
+ 'Sequel::BeforeHookFailed',
43
+ 'Sequel::Database::ResetIdentifierMangling',
44
+ 'Sequel::Error::AdapterNotFound',
45
+ 'Sequel::Error::InvalidOperation',
46
+ 'Sequel::Error::InvalidValue',
47
+ 'Sequel::Error::PoolTimeoutError',
48
+ 'Sequel::Error::Rollback',
49
+ 'Sequel::Model::ANONYMOUS_MODEL_CLASSES',
50
+ 'Sequel::Model::ANONYMOUS_MODEL_CLASSES_MUTEX',
51
+ 'Sequel::UnbindDuplicate',
52
+ 'Sequel::Unbinder',
53
+ 'YARD::Parser::Ruby::Legacy::RipperParser',
54
+ 'Java::ComHeadiusRacc::Cparse::CparseParams::NEVER',
55
+ 'Java::ComHeadiusRacc::Cparse::CparseParams::UNDEF',
56
+ 'Java::ComHeadiusRacc::Cparse::Parser::NEVER',
57
+ 'Java::ComHeadiusRacc::Cparse::Parser::UNDEF',
58
+ 'Java::OrgJruby::RubyBasicObject::NEVER',
59
+ 'Java::OrgJruby::RubyBasicObject::UNDEF',
60
+ 'Java::OrgJruby::RubyClass::NEVER',
61
+ 'Java::OrgJruby::RubyClass::UNDEF',
62
+ 'Java::OrgJruby::RubyModule::NEVER',
63
+ 'Java::OrgJruby::RubyModule::UNDEF',
64
+ 'Java::OrgJruby::RubyObject::NEVER',
65
+ 'Java::OrgJruby::RubyObject::UNDEF',
66
+ ].freeze
67
+
68
+ def initialize
69
+ @all_constants = {}
70
+ dfs_module(Object, nil, @all_constants, nil)
71
+ Sorbet::Private::Status.done
72
+ @consts_by_name = {}
73
+ @all_constants.each_value do |struct|
74
+ fill_primary_name(struct)
75
+ @consts_by_name[struct.primary_name] = struct.const
76
+ end
77
+ end
78
+
79
+ def all_module_names
80
+ ret = @all_constants.select {|_k, v| Sorbet::Private::RealStdlib.real_is_a?(v.const, Module)}.map do |_key, struct|
81
+ raise "should never happen" if !struct.primary_name
82
+ struct.primary_name
83
+ end
84
+ ret
85
+ end
86
+
87
+ def all_named_modules
88
+ ret = @all_constants.select {|_k, v| Sorbet::Private::RealStdlib.real_is_a?(v.const, Module)}.map do |_key, struct|
89
+ raise "should never happen" if !struct.primary_name
90
+ struct.const
91
+ end
92
+ ret
93
+ end
94
+
95
+ def all_module_aliases
96
+ ret = {}
97
+
98
+ @all_constants.map do |_key, struct|
99
+ next if struct.nil? || !Sorbet::Private::RealStdlib.real_is_a?(struct.const, Module) || struct.aliases.size < 2
100
+ if struct.owner != nil
101
+ ret[struct.primary_name] = struct.aliases.reject do |name|
102
+ # ignore the primary
103
+ next true if name == struct.primary_name
104
+
105
+ prefix, _, _ = name.rpartition('::')
106
+
107
+ # an alias that exists at the top-level
108
+ next false if prefix == ""
109
+
110
+ # if the prefix is the same syntactically, then this is a good alias
111
+ next false if prefix == struct.owner.primary_name
112
+
113
+ # skip the alias if the owner is the same
114
+ other_owner_const = Sorbet::Private::RealStdlib.real_const_get(Object, prefix, false)
115
+ struct.owner.const == other_owner_const
116
+ end
117
+ else
118
+ # top-level names
119
+ ret[struct.primary_name] = struct.aliases.reject {|name| name == struct.primary_name }
120
+ end
121
+ end
122
+ ret
123
+ end
124
+
125
+ def class_by_name(name)
126
+ @consts_by_name[name]
127
+ end
128
+
129
+ def name_by_class(klass)
130
+ @all_constants[Sorbet::Private::RealStdlib.real_object_id(klass)]&.primary_name
131
+ end
132
+
133
+ private def dfs_module(mod, prefix, ret, owner)
134
+ raise "error #{prefix}: #{mod} is not a module" if !Sorbet::Private::RealStdlib.real_is_a?(mod, Module)
135
+ name = Sorbet::Private::RealStdlib.real_name(mod)
136
+ Sorbet::Private::Status.say("Naming #{name}", print_without_tty: false)
137
+ return if name == 'RSpec::ExampleGroups' # These are all anonymous classes and will be quadratic in the number of classes to name them. We also know they don't have any hidden definitions
138
+ begin
139
+ constants = Sorbet::Private::RealStdlib.real_constants(mod)
140
+ rescue TypeError
141
+ puts "Failed to call `constants` on #{prefix}"
142
+ return nil
143
+ end
144
+ go_deeper = [] # make this a bfs to prefer shorter names
145
+ constants.each do |nested|
146
+ begin
147
+ next if Sorbet::Private::RealStdlib.real_autoload?(mod, nested) # some constants aren't autoloaded even after require_everything, e.g. StateMachine::Graph
148
+
149
+ begin
150
+ next if DEPRECATED_CONSTANTS.include?("#{prefix}::#{nested}") # avoid stdout spew
151
+ rescue NameError
152
+ # If it isn't to_s-able, that is ok, it won't be in our deprecated list
153
+ nil
154
+ end
155
+
156
+ begin
157
+ nested_constant = Sorbet::Private::RealStdlib.real_const_get(mod, nested, false) # rubocop:disable PrisonGuard/NoDynamicConstAccess
158
+ rescue LoadError => err
159
+ puts "Got #{err.class} when trying to get nested name #{name}::#{nested}"
160
+ next
161
+ rescue NameError, ArgumentError => err
162
+ puts "Got #{err.class} when trying to get nested name #{name}::#{nested}_"
163
+ # some stuff fails to load, like
164
+ # `const_get': uninitialized constant YARD::Parser::Ruby::Legacy::RipperParser (NameError)
165
+ # Did you mean? YARD::Parser::Ruby::Legacy::RipperParser
166
+ end
167
+
168
+ object_id = Sorbet::Private::RealStdlib.real_object_id(nested_constant)
169
+ maybe_seen_already = ret[object_id]
170
+ if Object.eql?(mod) || !prefix
171
+ nested_name = nested.to_s
172
+ else
173
+ nested_name = prefix + "::" + nested.to_s
174
+ end
175
+ if maybe_seen_already
176
+ if nested_name != maybe_seen_already.primary_name
177
+ maybe_seen_already.aliases << nested_name
178
+ maybe_seen_already.owner = owner
179
+ end
180
+ if maybe_seen_already.primary_name.nil? && Sorbet::Private::RealStdlib.real_is_a?(nested_constant, Module)
181
+ realName = Sorbet::Private::RealStdlib.real_name(nested_constant)
182
+ maybe_seen_already.primary_name = realName
183
+ end
184
+ else
185
+ entry = ConstantEntry.new(nested, nested_name, nil, [nested_name], nested_constant, owner)
186
+ ret[object_id] = entry
187
+
188
+ if Sorbet::Private::RealStdlib.real_is_a?(nested_constant, Module) && Object != nested_constant
189
+ go_deeper << [entry, nested_constant, nested_name]
190
+ end
191
+ end
192
+
193
+ end
194
+ end
195
+
196
+ # Horrible horrible hack to get private constants that are `include`d.
197
+ # This doesn't recurse so you can't get private constants inside the private
198
+ # constants, but I really hope you don't need those...
199
+ Sorbet::Private::RealStdlib.real_ancestors(mod).each do |ancestor|
200
+ object_id = Sorbet::Private::RealStdlib.real_object_id(ancestor)
201
+ name = Sorbet::Private::RealStdlib.real_name(ancestor)
202
+ next unless name
203
+ next if ret[object_id]
204
+ prefix, _, const_name = name.rpartition('::')
205
+ entry = ConstantEntry.new(const_name.to_sym, name, name, [name], ancestor, nil)
206
+ ret[object_id] = entry
207
+ end
208
+ sorted_deeper = go_deeper.sort_by do |entry, nested_constant, nested_name|
209
+ Sorbet::Private::RealStdlib.real_name(nested_constant)
210
+ end
211
+ sorted_deeper.each do |entry, nested_constant, nested_name|
212
+ dfs_module(nested_constant, nested_name, ret, entry)
213
+ end
214
+ nil
215
+ end
216
+
217
+ private def fill_primary_name(struct)
218
+ return if struct.primary_name
219
+ if !struct.owner
220
+ struct.primary_name = struct.found_name
221
+ else
222
+ fill_primary_name(struct.owner)
223
+ struct.primary_name = struct.owner.primary_name + "::" + struct.const_name.to_s
224
+ end
225
+ end
226
+ end