diff --git a/doc/contributor/updating-ruby.md b/doc/contributor/updating-ruby.md index 77226fb9e2bf..711187b2522f 100644 --- a/doc/contributor/updating-ruby.md +++ b/doc/contributor/updating-ruby.md @@ -122,6 +122,7 @@ cp -R lib/ruby/gems/*.0/gems $TRUFFLERUBY/lib/gems cp -R lib/ruby/gems/*.0/specifications $TRUFFLERUBY/lib/gems cd $TRUFFLERUBY +rm -rf lib/gems/gems/typeprof-* lib/gems/specifications/typeprof-*.gemspec ruby tool/patch-default-gemspecs.rb ``` @@ -130,7 +131,7 @@ ruby tool/patch-default-gemspecs.rb ``` rm -rf exe cp -R ~/.rubies/ruby-$VERSION/bin exe -rm -f exe/ruby +rm -f exe/ruby exe/typeprof ruby tool/patch_launchers.rb ``` diff --git a/exe/typeprof b/exe/typeprof deleted file mode 100755 index d68a1e4bdb9b..000000000000 --- a/exe/typeprof +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -# -# This file was generated by RubyGems. -# The above lines match the format expected by rubygems/installer.rb check_executable_overwrite -# bash section ignored by the Ruby interpreter - -# get the absolute path of the executable and resolve symlinks -SELF_PATH=$(cd "$(dirname "$0")" && pwd -P)/$(basename "$0") -while [ -h "$SELF_PATH" ]; do - # 1) cd to directory of the symlink - # 2) cd to the directory of where the symlink points - # 3) get the pwd - # 4) append the basename - DIR=$(dirname "$SELF_PATH") - SYM=$(readlink "$SELF_PATH") - SELF_PATH=$(cd "$DIR" && cd "$(dirname "$SYM")" && pwd)/$(basename "$SYM") -done -exec "$(dirname $SELF_PATH)/ruby" "$SELF_PATH" "$@" - -#!ruby -# -# This file was generated by RubyGems. -# -# The application 'typeprof' is installed as part of a gem, and -# this file is here to facilitate running it. -# - -require 'rubygems' - -Gem.use_gemdeps - -version = ">= 0.a" - -str = ARGV.first -if str - str = str.b[/\A_(.*)_\z/, 1] - if str and Gem::Version.correct?(str) - version = str - ARGV.shift - end -end - -if Gem.respond_to?(:activate_bin_path) -load Gem.activate_bin_path('typeprof', 'typeprof', version) -else -gem "typeprof", version -load Gem.bin_path("typeprof", "typeprof", version) -end diff --git a/lib/gems/gems/typeprof-0.21.2/Gemfile b/lib/gems/gems/typeprof-0.21.2/Gemfile deleted file mode 100644 index 27af03b9392e..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/Gemfile +++ /dev/null @@ -1,13 +0,0 @@ -source "https://rubygems.org" - -# Specify your gem's dependencies in typeprof.gemspec -gemspec - -group :development do - gem "rake" - gem "stackprof" - gem "test-unit" - gem "simplecov" - gem "simplecov-html" - gem "coverage-helpers" -end diff --git a/lib/gems/gems/typeprof-0.21.2/Gemfile.lock b/lib/gems/gems/typeprof-0.21.2/Gemfile.lock deleted file mode 100644 index cb049f9f241a..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/Gemfile.lock +++ /dev/null @@ -1,39 +0,0 @@ -PATH - remote: . - specs: - typeprof (0.21.2) - rbs (>= 1.8.1) - -GEM - remote: https://rubygems.org/ - specs: - coverage-helpers (1.0.0) - docile (1.4.0) - power_assert (2.0.1) - rake (13.0.1) - rbs (2.0.0) - simplecov (0.21.2) - docile (~> 1.1) - simplecov-html (~> 0.11) - simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) - simplecov_json_formatter (0.1.3) - stackprof (0.2.17) - test-unit (3.5.3) - power_assert - -PLATFORMS - ruby - x86_64-linux - -DEPENDENCIES - coverage-helpers - rake - simplecov - simplecov-html - stackprof - test-unit - typeprof! - -BUNDLED WITH - 2.2.15 diff --git a/lib/gems/gems/typeprof-0.21.2/LICENSE b/lib/gems/gems/typeprof-0.21.2/LICENSE deleted file mode 100644 index 522e4dd07ac3..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2019 Yusuke Endoh - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/lib/gems/gems/typeprof-0.21.2/README.md b/lib/gems/gems/typeprof-0.21.2/README.md deleted file mode 100644 index c0ba2dd0d6f4..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# TypeProf: A type analysis tool for Ruby code based on abstract interpretation - -## Synopsis - -```sh -gem install typeprof -typeprof app.rb -``` - -## Demo - -```rb -# test.rb -def foo(x) - if x > 10 - x.to_s - else - nil - end -end - -foo(42) -``` - -``` -$ typeprof test.rb -# Classes -class Object - def foo : (Integer) -> String? -end -``` - -## Documentation - -[English](doc/doc.md) / [日本語](doc/doc.ja.md) - -## Playground - -You can try typeprof gem on the Web via the URL below. - -https://mame.github.io/typeprof-playground/ diff --git a/lib/gems/gems/typeprof-0.21.2/Rakefile b/lib/gems/gems/typeprof-0.21.2/Rakefile deleted file mode 100644 index d433a1edc1b0..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/Rakefile +++ /dev/null @@ -1,10 +0,0 @@ -require "bundler/gem_tasks" -require "rake/testtask" - -Rake::TestTask.new(:test) do |t| - t.libs << "test" - t.libs << "lib" - t.test_files = FileList["test/**/*_test.rb"] -end - -task :default => :test diff --git a/lib/gems/gems/typeprof-0.21.2/exe/typeprof b/lib/gems/gems/typeprof-0.21.2/exe/typeprof deleted file mode 100755 index ccdecd097fdd..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/exe/typeprof +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env ruby - -require_relative "../lib/typeprof" - -config = TypeProf::CLI.parse(ARGV) -if config.options[:lsp] - TypeProf.start_lsp_server(config) -else - TypeProf.analyze(config) -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof.rb deleted file mode 100644 index 0e72cf61b2b6..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof.rb +++ /dev/null @@ -1,20 +0,0 @@ -module TypeProf end - -require_relative "typeprof/version" -require_relative "typeprof/config" -require_relative "typeprof/insns-def" -require_relative "typeprof/utils" -require_relative "typeprof/type" -require_relative "typeprof/container-type" -require_relative "typeprof/method" -require_relative "typeprof/block" -require_relative "typeprof/iseq" -require_relative "typeprof/arguments" -require_relative "typeprof/analyzer" -require_relative "typeprof/import" -require_relative "typeprof/export" -require_relative "typeprof/builtin" -require_relative "typeprof/cli" -require_relative "typeprof/code-range" - -require_relative "typeprof/lsp" if RUBY_VERSION >= "3" diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/analyzer.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/analyzer.rb deleted file mode 100644 index 85ef012d4928..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/analyzer.rb +++ /dev/null @@ -1,2563 +0,0 @@ -module TypeProf - class CRef - include Utils::StructuralEquality - - def initialize(outer, klass, singleton) - @outer = outer - @klass = klass - @singleton = singleton - # flags - # scope_visi (= method_visi * module_func_flag) - # refinements - end - - def extend(klass, singleton) - CRef.new(self, klass, singleton) - end - - attr_reader :outer, :klass, :singleton - - def pretty_print(q) - q.text "CRef[" - q.pp @klass - q.text "]" - end - end - - class Context - include Utils::StructuralEquality - - def initialize(iseq, cref, mid) - @iseq = iseq - @cref = cref - @mid = mid - end - - attr_reader :iseq, :cref, :mid - - def source_location(pc) - if @iseq - @iseq.source_location(pc) - else - "" - end - end - - def detailed_source_location(pc) - if @iseq - @iseq.detailed_source_location(pc) - else - nil - end - end - - def replace_cref(cref) - Context.new(@iseq, cref, @mid) - end - end - - class TypedContext - include Utils::StructuralEquality - - def initialize(caller_ep, mid) - @caller_ep = caller_ep - @mid = mid - end - - attr_reader :caller_ep, :mid - - def source_location(_pc) - if @caller_ep - @caller_ep.source_location - else - "" - end - end - - def detailed_source_location(_pc) - if @caller_ep - @caller_ep.source_location - else - nil - end - end - - def replace_cref(cref) - # What to do? - end - end - - class ExecutionPoint - include Utils::StructuralEquality - - def initialize(ctx, pc, outer) - @ctx = ctx - @pc = pc - @outer = outer - end - - def key - [@ctx.iseq, @pc] - end - - attr_reader :ctx, :pc, :outer - - def jump(pc) - ExecutionPoint.new(@ctx, pc, @outer) - end - - def next - ExecutionPoint.new(@ctx, @pc + 1, @outer) - end - - def replace_cref(cref) - ExecutionPoint.new(@ctx.replace_cref(cref), @pc, @outer) - end - - def source_location - @ctx.source_location(@pc) - end - - def detailed_source_location - @ctx.detailed_source_location(@pc) - end - - def absolute_path - @ctx.iseq.absolute_path - end - end - - class StaticEnv - include Utils::StructuralEquality - - def initialize(recv_ty, blk_ty, mod_func, pub_meth) - @recv_ty = recv_ty - @blk_ty = blk_ty - @mod_func = mod_func - @pub_meth = pub_meth - - return if recv_ty == :top #OK - recv_ty.each_child_global do |ty| - raise ty.inspect if !ty.is_a?(Type::Instance) && !ty.is_a?(Type::Class) && !ty.is_a?(Type::Symbol) && ty != Type.any - end - end - - attr_reader :recv_ty, :blk_ty, :mod_func, :pub_meth - - def merge(other) - recv_ty = @recv_ty.union(other.recv_ty) - blk_ty = @blk_ty.union(other.blk_ty) - mod_func = @mod_func & other.mod_func # ?? - pub_meth = @pub_meth & other.pub_meth # ?? - StaticEnv.new(recv_ty, blk_ty, mod_func, pub_meth) - end - end - - class Env - include Utils::StructuralEquality - - def initialize(static_env, locals, stack, type_params) - @static_env = static_env - @locals = locals - @stack = stack - @type_params = type_params - end - - attr_reader :static_env, :locals, :stack, :type_params - - def merge(other) - raise if @locals.size != other.locals.size - raise if @stack.size != other.stack.size - static_env = @static_env.merge(other.static_env) - locals = [] - @locals.zip(other.locals) {|ty1, ty2| locals << ty1.union(ty2) } - stack = [] - @stack.zip(other.stack) {|ty1, ty2| stack << ty1.union(ty2) } - if @type_params - raise if !other.type_params - if @type_params == other.type_params - type_params = @type_params - else - type_params = @type_params.internal_hash.dup - other.type_params.internal_hash.each do |id, elems| - elems2 = type_params[id] - if elems2 - if elems != elems2 - type_params[id] = elems.union(elems2) - end - else - type_params[id] = elems - end - end - type_params = Utils::HashWrapper.new(type_params) - end - else - raise if other.type_params - end - Env.new(static_env, locals, stack, type_params) - end - - def push(*tys) - tys.each do |ty| - raise "nil cannot be pushed to the stack" if ty.nil? - ty.each_child do |ty| - raise if ty.is_a?(Type::Var) - #raise if ty.is_a?(Type::Instance) && ty.klass.type_params.size > 1 - raise "Array cannot be pushed to the stack" if ty.is_a?(Type::Array) - raise "Hash cannot be pushed to the stack" if ty.is_a?(Type::Hash) - end - end - Env.new(@static_env, @locals, @stack + tys, @type_params) - end - - def pop(n) - stack = @stack.dup - tys = stack.pop(n) - nenv = Env.new(@static_env, @locals, stack, @type_params) - return nenv, tys - end - - def setn(i, ty) - stack = Utils.array_update(@stack, -i, ty) - Env.new(@static_env, @locals, stack, @type_params) - end - - def topn(i) - push(@stack[-i - 1]) - end - - def get_local(idx) - @locals[idx] - end - - def local_update(idx, ty) - Env.new(@static_env, Utils.array_update(@locals, idx, ty), @stack, @type_params) - end - - def get_container_elem_types(id) - @type_params.internal_hash[id] - end - - def deploy_type(id, elems) - type_params = Utils::HashWrapper.new(@type_params.internal_hash.merge({ id => elems })) - Env.new(@static_env, @locals, @stack, type_params) - end - - def enable_module_function - senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, true, @static_env.pub_meth) - Env.new(senv, @locals, @stack, @type_params) - end - - def method_public_set(flag) - senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, @static_env.mod_func, flag) - Env.new(senv, @locals, @stack, @type_params) - end - - def replace_recv_ty(ty) - senv = StaticEnv.new(ty, @static_env.blk_ty, @static_env.mod_func, @static_env.pub_meth) - Env.new(senv, @locals, @stack, @type_params) - end - - def replace_blk_ty(ty) - senv = StaticEnv.new(@static_env.recv_ty, ty, @static_env.mod_func, @static_env.pub_meth) - Env.new(senv, @locals, @stack, @type_params) - end - - def inspect - "Env[#{ @static_env.inspect }, locals:#{ @locals.inspect }, stack:#{ @stack.inspect }, type_params:#{ (@type_params&.internal_hash).inspect }]" - end - end - - class Scratch - def inspect - "#" - end - - def initialize - @entrypoints = [] - - @worklist = Utils::WorkList.new - - @ep2env = {} - - @class_defs = {} - @struct_defs = {} - - @iseq_method_to_ctxs = {} - - @alloc_site_to_global_id = {} - - @callsites, @return_envs = {}, {} - @block_to_ctx = {} - @method_signatures = {} - @block_signatures = {} - @return_values = {} - @gvar_table = VarTable.new - - @errors = [] - @reveal_types = {} - @backward_edges = {} - - @pending_execution = {} - @executed_iseqs = Utils::MutableSet.new - - @loaded_files = {} - - @rbs_reader = RBSReader.new - - @terminated = false - - @anonymous_struct_gen_id = 0 - - @types_being_shown = [] - @namespace = nil - - @lsp_completion = nil - @lsp_signature_help = CodeRangeTable.new - end - - def add_entrypoint(iseq) - @entrypoints << iseq - end - - attr_reader :return_envs, :loaded_files, :rbs_reader - - def get_env(ep) - @ep2env[ep] - end - - def merge_env(ep, env) - # TODO: this is wrong; it include not only proceeds but also indirect propagation like out-of-block variable modification - #add_edge(ep, @ep) - env2 = @ep2env[ep] - if env2 - nenv = env2.merge(env) - if nenv != env2 && !@worklist.member?(ep) - @worklist.insert(ep.key, ep) - end - @ep2env[ep] = nenv - else - @worklist.insert(ep.key, ep) - @ep2env[ep] = env - end - end - - attr_reader :class_defs - - class ClassDef # or ModuleDef - def initialize(kind, name, absolute_path, superclass) - raise unless name.is_a?(Array) - @kind = kind - @modules = { - :before => { true => [], false => [] }, # before = include/extend - :after => { true => [], false => [] }, # after = prepend - } - @name = name - @consts = {} - @methods = {} - @ivars = VarTable.new - @cvars = VarTable.new - @absolute_path = absolute_path - @namespace = nil - @superclass = superclass - @subclasses = [] - end - - attr_reader :kind, :modules, :methods, :ivars, :cvars, :absolute_path, :superclass, :subclasses - attr_accessor :name, :klass_obj - - def mix_module(kind, mod, type_args, singleton, absolute_path) - mod_, module_type_args, absolute_paths = @modules[kind][singleton].find {|m,| m == mod } - if mod_ - raise "inconsistent #{ kind == :after ? "include/extend" : "prepend" } type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil - else - absolute_paths = Utils::MutableSet.new - @modules[kind][singleton].unshift([mod, type_args, absolute_paths]) - end - absolute_paths << absolute_path - end - - def get_constant(name) - ty, locs = @consts[name] - ty = ty || Type.any # XXX: warn? - return ty, locs - end - - def add_constant(name, ty, def_ep) - if @consts[name] - # XXX: warn! - _, eps = @consts[name] - @consts[name] = [ty, eps + [def_ep&.detailed_source_location]] - return - end - @consts[name] = [ty, [def_ep&.detailed_source_location]] - end - - def consts - @consts.lazy.flat_map do |name, (ty, eps)| - eps.map do |ep| - [name, [ty, ep]] - end - end - end - - def add_class_open(name, open_ep) - ty, eps = @consts[name] - raise "call this only if the class is opened more than once" if ty.nil? - @consts[name] = [ty, eps + [open_ep&.detailed_source_location]] - end - - - def adjust_substitution_for_module(mods, mid, mthd, subst, &blk) - mods.each do |mod_def, type_args,| - if mod_def.klass_obj.type_params && type_args - subst2 = {} - mod_def.klass_obj.type_params.zip(type_args) do |(tyvar, *), tyarg| - tyvar = Type::Var.new(tyvar) - subst2[tyvar] = tyarg.substitute(subst, Config.current.options[:type_depth_limit]) - end - mod_def.adjust_substitution(false, mid, mthd, subst2, false, &blk) - end - end - end - - def adjust_substitution(singleton, mid, mthd, subst, direct, &blk) - adjust_substitution_for_module(@modules[:before][singleton], mid, mthd, subst, &blk) - - mthds = @methods[[singleton, mid]] - yield subst, direct if mthds&.include?(mthd) - - adjust_substitution_for_module(@modules[:after][singleton], mid, mthd, subst, &blk) - end - - def search_method(singleton, mid, visited, &blk) - # Currently, circular inclusion of modules is allowed - return if visited[self] - visited[self] = true - - @modules[:before][singleton].each do |mod_def,| - mod_def.search_method(false, mid, visited, &blk) - end - - mthds = @methods[[singleton, mid]] - yield mthds, @klass_obj, singleton if mthds - - @modules[:after][singleton].each do |mod_def,| - mod_def.search_method(false, mid, visited, &blk) - end - end - - def check_typed(mid, singleton, klass) - set = @methods[[singleton, mid]] - return nil unless set - set = set.select {|mdef| mdef.is_a?(klass) } - return nil if set.empty? - return set - end - - def check_typed_method(mid, singleton) - check_typed(mid, singleton, TypedMethodDef) - end - - def check_typed_attr(mid, singleton) - check_typed(mid, singleton, TypedAttrMethodDef) - end - - def add_method(mid, singleton, mdef) - @methods[[singleton, mid]] ||= Utils::MutableSet.new - @methods[[singleton, mid]] << mdef - # Need to restart...? - end - - def set_method(mid, singleton, mdef) - if mdef - @methods[[singleton, mid]] = Utils::MutableSet.new - @methods[[singleton, mid]] << mdef - else - @methods.delete([singleton, mid]) - end - end - end - - def mix_module(kind, mixing_mod, mixed_mod, type_args, singleton, caller_ep) - return if mixed_mod == Type.any - - mixing_mod = @class_defs[mixing_mod.idx] - mixed_mod.each_child do |mixed_mod| - if mixed_mod.is_a?(Type::Class) - mixed_mod = @class_defs[mixed_mod.idx] - if mixed_mod && mixed_mod.kind == :module - mixing_mod.mix_module(kind, mixed_mod, type_args, singleton, caller_ep ? caller_ep.ctx.iseq.absolute_path : nil) - else - warn(caller_ep, "attempted to #{ kind == :after ? "include/extend" : "prepend" } non-module; ignored") - end - end - end - end - - def cbase_path(cbase) - cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : [] - end - - def new_class(cbase, name, type_params, superclass, def_ep) - show_name = cbase_path(cbase) + [name] - idx = @class_defs.size - if superclass - superclass_def = @class_defs[superclass.idx] unless superclass == :__root__ - @class_defs[idx] = ClassDef.new(:class, show_name, def_ep&.absolute_path, superclass_def) - superclass_def.subclasses << idx if superclass_def - klass = Type::Class.new(:class, idx, type_params, superclass, show_name) - @class_defs[idx].klass_obj = klass - cbase ||= klass # for bootstrap - add_constant(cbase, name, klass, def_ep) - return klass - else - # module - @class_defs[idx] = ClassDef.new(:module, show_name, def_ep&.absolute_path, nil) - mod = Type::Class.new(:module, idx, type_params, nil, show_name) - @class_defs[idx].klass_obj = mod - add_constant(cbase, name, mod, def_ep) - return mod - end - end - - def add_superclass_type_args!(klass, tyargs) - klass.superclass_type_args = tyargs - end - - def new_struct(ep) - return @struct_defs[ep] if @struct_defs[ep] - - idx = @class_defs.size - superclass = Type::Builtin[:struct] - name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }" - # Should we pass a superclass here? - @class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path, nil) - #@class_defs[superclass.idx].subclasses << idx # needed? - klass = Type::Class.new(:class, idx, [], superclass, name) - add_superclass_type_args!(klass, [Type.any]) - @class_defs[idx].klass_obj = klass - - @struct_defs[ep] = klass - - klass - end - - attr_accessor :namespace - - def get_class_name(klass) - if klass == Type.any - "???" - else - path = @class_defs[klass.idx].name - if @namespace - i = 0 - i += 1 while @namespace[i] && @namespace[i] == path[i] - if path[i] - path[i..].join("::") - else - path.last.to_s - end - else - #"::" + path.join("::") - path.join("::") - end - end - end - - def adjust_substitution(klass, singleton, mid, mthd, subst, &blk) - direct = true - if klass.kind == :class - while klass != :__root__ - class_def = @class_defs[klass.idx] - class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk) - direct = false - if klass.superclass && klass.superclass_type_args - subst2 = {} - klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg| - tyvar = Type::Var.new(tyvar) - subst2[tyvar] = tyarg.substitute(subst, Config.current.options[:type_depth_limit]) - end - subst = subst2 - end - klass = klass.superclass - end - else - # module - class_def = @class_defs[klass.idx] - class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk) - end - end - - def traverse_subclasses(klass, &blk) - @class_defs[klass.idx].subclasses.each do |subclass| - yield @class_defs[subclass] - traverse_subclasses(@class_defs[subclass].klass_obj, &blk) - end - end - - def search_method(klass, singleton, mid, &blk) - # XXX: support method alias correctly - klass_orig = klass - if klass.kind == :class - while klass != :__root__ - class_def = @class_defs[klass.idx] - class_def.search_method(singleton, mid, {}, &blk) - klass = klass.superclass - end - else - # module - class_def = @class_defs[klass.idx] - class_def.search_method(singleton, mid, {}, &blk) - end - if singleton - search_method(Type::Builtin[klass_orig.kind], false, mid, &blk) - end - end - - def get_method(klass, singleton, include_subclasses, mid) - if include_subclasses - subclasses_mthds = [] - traverse_subclasses(klass) do |subclass| - subclass.search_method(singleton, mid, {}) do |mthds,| - subclasses_mthds.concat(mthds.to_a) - end - end - search_method(klass, singleton, mid) {|mthds,| return subclasses_mthds + mthds.to_a } - return subclasses_mthds - end - - search_method(klass, singleton, mid) {|mthds,| return mthds } - end - - def get_all_super_methods(klass, singleton, current_klass, mid) - hit = false - search_method(klass, singleton, mid) do |mthds, klass0, singleton0| - yield mthds, klass0, singleton0 if hit - hit = klass0 == current_klass - end - end - - def get_super_method(ctx, singleton) - klass = ctx.cref.klass - mid = ctx.mid - if klass.kind == :class - klass = klass.superclass - while klass != :__root__ - class_def = @class_defs[klass.idx] - mthd = class_def.get_method(mid, singleton) - return mthd if mthd - klass = klass.superclass - end - else - # module - class_def = @class_defs[klass.idx] - mthd = class_def.get_method(mid, singleton) - return mthd if mthd - end - nil - end - - def get_all_methods(klass, singleton, _include_subclasses) - names = {} - - if klass.kind == :class - while klass != :__root__ - # TODO: module - @class_defs[klass.idx].methods.each_key do |singleton0, name| - if singleton == singleton0 - names[name] = true - end - end - klass = klass.superclass - end - else - @class_defs[klass.idx].methods.each_key do |singleton0, name| - if singleton == singleton0 - names[name] = true - end - end - end - - names - end - - def get_constant(klass, name) - if klass == Type.any - [Type.any, nil] - elsif klass.is_a?(Type::Class) - @class_defs[klass.idx].get_constant(name) - else - [Type.any, nil] - end - end - - def search_constant(cref, name) - while cref != :bottom - ty, locs = get_constant(cref.klass, name) - return ty, locs if ty != Type.any - cref = cref.outer - end - - return Type.any, nil - end - - def add_constant(klass, name, value, def_ep) - if klass.is_a?(Type::Class) - @class_defs[klass.idx].add_constant(name, value, def_ep) - end - end - - def check_typed_method(klass, mid, singleton) - @class_defs[klass.idx].check_typed_method(mid, singleton) - end - - def check_typed_attr(klass, mid, singleton) - @class_defs[klass.idx].check_typed_attr(mid, singleton) - end - - def add_method(klass, mid, singleton, mdef) - @class_defs[klass.idx].add_method(mid, singleton, mdef) - mdef - end - - def set_method(klass, mid, singleton, mdef) - @class_defs[klass.idx].set_method(mid, singleton, mdef) - mdef - end - - def add_attr_method(klass, mid, ivar, kind, pub_meth, ep) - if kind == :reader || kind == :accessor - typed_mdef = check_typed_attr(klass, mid, ep.ctx.cref.singleton) - unless typed_mdef - add_method(klass, mid, false, ExecutedAttrMethodDef.new(ivar, :reader, pub_meth, ep)) - end - end - if kind == :writer || kind == :accessor - mid = :"#{ mid }=" - typed_mdef = check_typed_attr(klass, mid, ep.ctx.cref.singleton) - unless typed_mdef - add_method(klass, mid, false, ExecutedAttrMethodDef.new(ivar, :writer, pub_meth, ep)) - end - end - end - - def add_typed_attr_method(klass, mdef) - name = mdef.ivar[1..-1] - name = mdef.kind == :writer ? :"#{ name }=" : name.to_sym - add_method(klass, name, false, mdef) - end - - def add_iseq_method(klass, mid, iseq, cref, outer_ep, pub_meth) - add_method(klass, mid, false, ISeqMethodDef.new(iseq, cref, outer_ep, pub_meth)) - end - - def add_singleton_iseq_method(klass, mid, iseq, cref, outer_ep, pub_meth) - add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref, outer_ep, pub_meth)) - end - - def set_custom_method(klass, mid, impl, pub_meth = true) - set_method(klass, mid, false, CustomMethodDef.new(impl, pub_meth)) - end - - def set_singleton_custom_method(klass, mid, impl, pub_meth = true) - set_method(klass, mid, true, CustomMethodDef.new(impl, pub_meth)) - end - - def alias_method(klass, singleton, alias_mid, orig_mid, ep) - if klass == Type.any - self - else - mdefs = get_method(klass, singleton, false, orig_mid) # XXX: include_subclass == false?? - if mdefs - # dup is needed for `alias foo foo` (otherwise, "can't add a new key into hash during iteration" error occurs) - mdefs.dup.each do |mdef| - @class_defs[klass.idx].add_method(alias_mid, singleton, AliasMethodDef.new(orig_mid, mdef, ep)) - end - end - end - end - - def add_edge(ep, next_ep) - (@backward_edges[next_ep] ||= {})[ep] = true - end - - def add_iseq_method_call!(iseq_mdef, ctx) - @iseq_method_to_ctxs[iseq_mdef] ||= Utils::MutableSet.new - @iseq_method_to_ctxs[iseq_mdef] << ctx - end - - def add_executed_iseq(iseq) - @executed_iseqs << iseq - end - - def add_callsite!(callee_ctx, caller_ep, caller_env, &ctn) - if callee_ctx.is_a?(Context) - @executed_iseqs << callee_ctx.iseq - callee_type = callee_ctx.iseq.type - if caller_ep.ctx.is_a?(Context) && (callee_type == :method || callee_type == :block) - caller_ep.ctx.iseq&.add_called_iseq(caller_ep.pc, callee_ctx.iseq) - end - end - - @callsites[callee_ctx] ||= {} - @callsites[callee_ctx][caller_ep] = ctn - merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } - - ret_ty = @return_values[callee_ctx] ||= Type.bot - if ret_ty != Type.bot - ctn[ret_ty, caller_ep, @return_envs[caller_ep]] - end - end - - def add_method_signature!(callee_ctx, msig) - if @method_signatures[callee_ctx] - @method_signatures[callee_ctx] = @method_signatures[callee_ctx].merge(msig) - else - @method_signatures[callee_ctx] = msig - end - end - - def merge_return_env(caller_ep) - @return_envs[caller_ep] = yield @return_envs[caller_ep] - end - - def add_return_value!(callee_ctx, ret_ty) - @return_values[callee_ctx] ||= Type.bot - @return_values[callee_ctx] = @return_values[callee_ctx].union(ret_ty) - - @callsites[callee_ctx] ||= {} - @callsites[callee_ctx].each do |caller_ep, ctn| - ctn[ret_ty, caller_ep, @return_envs[caller_ep]] - end - end - - def add_block_to_ctx!(block_body, ctx) - raise if !block_body.is_a?(Block) - @block_to_ctx[block_body] ||= Utils::MutableSet.new - @block_to_ctx[block_body] << ctx - end - - def add_block_signature!(block_body, bsig) - if @block_signatures[block_body] - @block_signatures[block_body] = @block_signatures[block_body].merge(bsig) - else - @block_signatures[block_body] = bsig - end - end - - class VarTable - Entry = Struct.new(:rbs_declared, :read_continuations, :type, :absolute_paths, :write_eps) - - def initialize - @tbl = {} - end - - def add_read!(site, ep, &ctn) - entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new, Utils::MutableSet.new) - entry.read_continuations[ep] = ctn - entry.absolute_paths << ep.ctx.iseq.absolute_path if ep.ctx.is_a?(Context) - ty = entry.type - ty = Type.nil if ty == Type.bot - ctn[ty, ep, entry.write_eps] - end - - def add_write!(site, ty, ep, scratch) - entry = @tbl[site] ||= Entry.new(!ep, {}, Type.bot, Utils::MutableSet.new, Utils::MutableSet.new) - if ep - if entry.rbs_declared - unless Type.match?(ty, entry.type) - scratch.warn(ep, "inconsistent assignment to RBS-declared variable") - return - end - end - entry.absolute_paths << ep.ctx.iseq.absolute_path - entry.write_eps << ep - end - entry.type = entry.type.union(ty) - entry.read_continuations.each do |read_ep, ctn| - ctn[ty, read_ep, ep ? [ep] : []] - end - end - - def dump - @tbl - end - end - - def identify_class_for_ivar(recv, var) - klass, singleton = recv.method_dispatch_info - return nil unless klass - search_method(klass, singleton, var) do |mthds, klass0, singleton0| - if mthds.any? {|mthd| mthd.is_a?(AttrMethodDef) } - return klass0, singleton - end - end - return klass, singleton - end - - def get_ivar(recv, var) - recv = recv.base_type while recv.respond_to?(:base_type) - - klass, singleton = identify_class_for_ivar(recv, var.to_s[1..].to_sym) # search attr_reader - - if klass - return @class_defs[klass.idx], singleton - else - return nil - end - end - - def add_ivar_read!(recv, var, ep, &ctn) - recv.each_child do |recv| - class_def, singleton = get_ivar(recv, var) - next unless class_def - class_def.ivars.add_read!([singleton, var], ep, &ctn) - end - end - - def add_ivar_write!(recv, var, ty, ep) - recv.each_child do |recv| - class_def, singleton = get_ivar(recv, var) - next unless class_def - site = [singleton, var] - class_def.ivars.add_write!(site, ty, ep, self) - end - end - - def add_cvar_read!(klass, var, ep, &ctn) - klass.each_child do |klass| - next unless klass.is_a?(Type::Class) - class_def = @class_defs[klass.idx] - next unless class_def - class_def.cvars.add_read!(var, ep, &ctn) - end - end - - def add_cvar_write!(klass, var, ty, ep) - klass.each_child do |klass| - next unless klass.is_a?(Type::Class) - class_def = @class_defs[klass.idx] - next unless class_def - class_def.cvars.add_write!(var, ty, ep, self) - end - end - - def add_gvar_read!(var, ep, &ctn) - @gvar_table.add_read!(var, ep, &ctn) - end - - def add_gvar_write!(var, ty, ep) - @gvar_table.add_write!(var, ty, ep, self) - end - - def error(ep, msg) - p [ep.source_location, "[error] " + msg] if Config.current.verbose >= 2 - @errors << [ep, "[error] " + msg] - end - - def warn(ep, msg) - p [ep.source_location, "[warning] " + msg] if Config.current.verbose >= 2 - @errors << [ep, "[warning] " + msg] - end - - def reveal_type(ep, ty) - key = ep.source_location - puts "reveal:#{ ep.source_location }:#{ ty.screen_name(self) }" if Config.current.verbose >= 2 - if @reveal_types[key] - @reveal_types[key] = @reveal_types[key].union(ty) - else - @reveal_types[key] = ty - end - end - - def get_container_elem_types(env, ep, id) - if ep.outer - tmp_ep = ep - tmp_ep = tmp_ep.outer while tmp_ep.outer - env = @return_envs[tmp_ep] - end - env.get_container_elem_types(id) - end - - def update_container_elem_types(env, ep, id, base_type) - if ep.outer - tmp_ep = ep - tmp_ep = tmp_ep.outer while tmp_ep.outer - merge_return_env(tmp_ep) do |menv| - elems = menv.get_container_elem_types(id) - elems = yield elems - menv = menv.deploy_type(id, elems) - gid = @alloc_site_to_global_id[id] - if gid - ty = globalize_type(elems.to_local_type(id, base_type), env, ep) - add_ivar_write!(*gid, ty, ep) - end - menv - end - env - else - elems = env.get_container_elem_types(id) - elems = yield elems - env = env.deploy_type(id, elems) - gid = @alloc_site_to_global_id[id] - if gid - ty = globalize_type(elems.to_local_type(id, base_type), env, ep) - add_ivar_write!(*gid, ty, ep) - end - env - end - end - - def get_array_elem_type(env, ep, id, idx = nil) - elems = get_container_elem_types(env, ep, id) - - if elems - return elems[idx] || Type.nil if idx - return elems.squash_or_any - else - Type.any - end - end - - def get_hash_elem_type(env, ep, id, key_ty = nil) - elems = get_container_elem_types(env, ep, id) - - if elems - elems[globalize_type(key_ty, env, ep) || Type.any] - else - Type.any - end - end - - def type_profile(cancel_token = nil) - cancel_token ||= Utils::TimerCancelToken.new(Config.current.max_sec) - tick = Time.now - iter_counter = 0 - stat_eps = Utils::MutableSet.new - - prologue_ctx = Context.new(nil, nil, nil) - prologue_ep = ExecutionPoint.new(prologue_ctx, -1, nil) - prologue_env = Env.new(StaticEnv.new(Type.bot, Type.nil, false, true), [], [], Utils::HashWrapper.new({})) - - until @entrypoints.empty? - entrypoint = @entrypoints.shift - if entrypoint.is_a?(String) - file = entrypoint - next if @loaded_files[File.expand_path(file)] - iseq, = ISeq.compile(file) - else - iseq = entrypoint - end - - @loaded_files[iseq.absolute_path] = true - ep, env = TypeProf.starting_state(iseq) - merge_env(ep, env) - add_callsite!(ep.ctx, prologue_ep, prologue_env) {|ty, ep| } - - while true - until @worklist.empty? - ep = @worklist.deletemin - - iter_counter += 1 - if Config.current.options[:show_indicator] - tick2 = Time.now - if tick2 - tick >= 1 - tick = tick2 - $stderr << "\rType Profiling... (%d instructions @ %s)\e[K" % [iter_counter, ep.source_location] - $stderr.flush - end - end - - if (Config.current.max_iter && Config.current.max_iter <= iter_counter) || cancel_token.cancelled? - @terminated = true - break - end - - stat_eps << ep - step(ep) - end - - break if @terminated - - break unless Config.current.options[:stub_execution] - - begin - iseq, (kind, dummy_continuation) = @pending_execution.first - break if !iseq - @pending_execution.delete(iseq) - end while @executed_iseqs.include?(iseq) - - puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.current.verbose >= 2 - - break if !iseq - case kind - when :method - meth, ep, env = dummy_continuation - merge_env(ep, env) - add_iseq_method_call!(meth, ep.ctx) - - when :block - blk, epenvs = dummy_continuation - epenvs.each do |ep, env| - merge_env(ep, env) - add_block_to_ctx!(blk.block_body, ep.ctx) - end - end - end - end - - $stderr.print "\r\e[K" if Config.current.options[:show_indicator] - - stat_eps - end - - def report(stat_eps, output) - Reporters.show_message(@terminated, output) - - Reporters.show_error(@errors, @backward_edges, output) - - Reporters.show_reveal_types(self, @reveal_types, output) - - Reporters.show_gvars(self, @gvar_table, output) - - RubySignatureExporter.new(self, @class_defs, @iseq_method_to_ctxs).show(stat_eps, output) - end - - def report_lsp - errs = @errors.map do |ep, msg| - [ep&.detailed_source_location, msg] - end - - res = RubySignatureExporter.new(self, @class_defs, @iseq_method_to_ctxs).show_lsp - - path, loc = Config.current.options[:signature_help_loc] - if path - sig_help_res = [] - sig_help = @lsp_signature_help[loc] - if sig_help - recv = sig_help[:recv] - mid = sig_help[:mid] - singleton = sig_help[:singleton] - mdefs = sig_help[:mdefs] - node_id = sig_help[:node_id] - mdefs.each do |mdef| - case mdef - when ISeqMethodDef - ctxs = @iseq_method_to_ctxs[mdef] - next unless ctxs - - ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first - - method_name = mid - method_name = "self.#{ method_name }" if singleton - - str = recv.screen_name(self) - str += singleton ? "." : "#" - str += method_name.to_s - str += ": " - sig, _, sig_help = show_method_signature(ctx) - offset = str.size - sig_help = sig_help.transform_values {|r| (r.begin + offset ... r.end + offset) } - str += sig - sig_help_res << [str, sig_help, node_id] - when AliasMethodDef - # TODO - when TypedMethodDef - mdef.rbs_source&.[](1)&.each do |rbs| - # TODO: sig_help - sig_help_res << [rbs, {}, node_id] - end - end - end - end - end - - { - sigs: res, - errors: errs, - completion: @lsp_completion, - signature_help: sig_help_res, - } - end - - def globalize_type(ty, env, ep) - if ep.outer - tmp_ep = ep - tmp_ep = tmp_ep.outer while tmp_ep.outer - env = @return_envs[tmp_ep] - end - ty.globalize(env, {}, Config.current.options[:type_depth_limit]) - end - - def localize_type(ty, env, ep, alloc_site = AllocationSite.new(ep)) - if ep.outer - tmp_ep = ep - tmp_ep = tmp_ep.outer while tmp_ep.outer - target_env = @return_envs[tmp_ep] - target_env, ty = ty.localize(target_env, alloc_site, Config.current.options[:type_depth_limit]) - merge_return_env(tmp_ep) do |env| - env ? env.merge(target_env) : target_env - end - return env, ty - else - return ty.localize(env, alloc_site, Config.current.options[:type_depth_limit]) - end - end - - def pend_method_execution(iseq, meth, recv, mid, cref, ep) - ctx = Context.new(iseq, cref, mid) - ep = ExecutionPoint.new(ctx, 0, ep) - locals = [Type.nil] * iseq.locals.size - - fargs_format = iseq.fargs_format - lead_num = fargs_format[:lead_num] || 0 - post_num = fargs_format[:post_num] || 0 - post_index = fargs_format[:post_start] - rest_index = fargs_format[:rest_start] - keyword = fargs_format[:keyword] - kw_index = fargs_format[:kwbits] - keyword.size if keyword - kwrest_index = fargs_format[:kwrest] - block_index = fargs_format[:block_start] - opt = fargs_format[:opt] || [0] - - (lead_num + opt.size - 1).times {|i| locals[i] = Type.any } - post_num.times {|i| locals[i + post_index] = Type.any } if post_index - locals[rest_index] = Type.any if rest_index - if keyword - keyword.each_with_index do |kw, i| - case - when kw.is_a?(Symbol) # required keyword - locals[kw_index + i] = Type.any - when kw.size == 2 # optional keyword (default value is a literal) - _key, default_ty = *kw - default_ty = Type.guess_literal_type(default_ty) - default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal) - locals[kw_index + i] = default_ty.union(Type.any) - else # optional keyword (default value is an expression) - locals[kw_index + i] = Type.any - end - end - end - locals[kwrest_index] = Type.any if kwrest_index - locals[block_index] = Type.nil if block_index - - env = Env.new(StaticEnv.new(recv, Type.nil, false, true), locals, [], Utils::HashWrapper.new({})) - - if !@pending_execution[iseq] || @pending_execution[iseq][0] == :block - @pending_execution[iseq] = [:method, [meth, ep, env]] - end - end - - def pend_block_dummy_execution(blk, iseq, nep, nenv) - @pending_execution[iseq] ||= [:block, [blk, {}]] - if @pending_execution[iseq][0] == :block - if @pending_execution[iseq][1][1][nep] - @pending_execution[iseq][1][1][nep] = @pending_execution[iseq][1][1][nep].merge(nenv) - else - @pending_execution[iseq][1][1][nep] = nenv - end - else - # XXX: what to do? - end - end - - def get_instance_variable(recv, var, ep, env) - add_ivar_read!(recv, var, ep) do |ty, ep, write_eps| - alloc_site = AllocationSite.new(ep) - nenv, ty = localize_type(ty, env, ep, alloc_site) - case ty - when Type::Local - @alloc_site_to_global_id[ty.id] = [recv, var] # need overwrite check?? - end - write_eps.each do |write_ep| - ep.ctx.iseq.add_def_loc(ep.pc, write_ep.detailed_source_location) - end - yield ty, nenv - end - end - - def set_instance_variable(recv, var, ty, ep, env) - ty = globalize_type(ty, env, ep) - add_ivar_write!(recv, var, ty, ep) - end - - def step(ep) - env = @ep2env[ep] - raise "nil env" unless env - - insn = ep.ctx.iseq.insns[ep.pc] - operands = insn.operands - - if Config.current.verbose >= 2 - # XXX: more dedicated output - puts "DEBUG: stack=%p" % [env.stack] - puts "DEBUG: %s (%s) PC=%d insn=%s sp=%d" % [ep.source_location, ep.ctx.iseq.name, ep.pc, insn.insn, env.stack.size] - end - - case insn.insn - when :_iseq_body_start - # XXX: reconstruct and record the method signature - iseq = ep.ctx.iseq - lead_num = iseq.fargs_format[:lead_num] || 0 - opt = iseq.fargs_format[:opt] || [0] - rest_start = iseq.fargs_format[:rest_start] - post_start = iseq.fargs_format[:post_start] - post_num = iseq.fargs_format[:post_num] || 0 - kw_start = iseq.fargs_format[:kwbits] - keyword = iseq.fargs_format[:keyword] - kw_start -= keyword.size if kw_start - kw_rest = iseq.fargs_format[:kwrest] - block_start = iseq.fargs_format[:block_start] - - lead_tys = env.locals[0, lead_num].map {|ty| globalize_type(ty, env, ep) } - opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } : [] - if rest_start # XXX:squash - ty = globalize_type(env.locals[rest_start], env, ep) - rest_ty = Type.bot - ty.each_child_global do |ty| - if ty.is_a?(Type::Array) - rest_ty = rest_ty.union(ty.elems.squash) - else - # XXX: to_ary? - rest_ty = rest_ty.union(ty) - end - end - end - post_tys = (post_start ? env.locals[post_start, post_num] : []).map {|ty| globalize_type(ty, env, ep) } - if keyword - kw_tys = [] - keyword.each_with_index do |kw, i| - case - when kw.is_a?(Symbol) # required keyword - key = kw - req = true - when kw.size == 2 # optional keyword (default value is a literal) - key, default_ty = *kw - default_ty = Type.guess_literal_type(default_ty) - default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal) - req = false - else # optional keyword (default value is an expression) - key, = kw - req = false - end - ty = env.locals[kw_start + i] - ty = ty.union(default_ty) if default_ty - ty = globalize_type(ty, env, ep) - kw_tys << [req, key, ty] - end - end - kw_rest_ty = globalize_type(env.locals[kw_rest], env, ep) if kw_rest - kw_rest_ty = nil if kw_rest_ty == Type.nil - if block_start - blk_ty = globalize_type(env.locals[block_start], env, ep) - elsif iseq.type == :method - blk_ty = env.static_env.blk_ty - else - blk_ty = Type.nil - end - msig = MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty) - add_method_signature!(ep.ctx, msig) - when :putspecialobject - kind, = operands - ty = case kind - when 1 then Type::Instance.new(Type::Builtin[:vmcore]) - when 2, 3 # CBASE / CONSTBASE - ep.ctx.cref.klass - else - raise NotImplementedError, "unknown special object: #{ type }" - end - env = env.push(ty) - when :putnil - env = env.push(Type.nil) - when :putobject, :duparray - obj, = operands - env, ty = localize_type(Type.guess_literal_type(obj), env, ep) - env = env.push(ty) - when :putstring - str, = operands - ty = Type::Literal.new(str, Type::Instance.new(Type::Builtin[:str])) - env = env.push(ty) - when :putself - ty = env.static_env.recv_ty - if ty.is_a?(Type::Instance) - klass = ty.klass - if klass.type_params.size >= 1 - ty = Type::ContainerType.create_empty_instance(klass) - env, ty = localize_type(ty, env, ep, AllocationSite.new(ep)) - else - ty = Type::Instance.new(klass) - end - env, ty = localize_type(ty, env, ep) - end - env = env.push(ty) - when :newarray, :newarraykwsplat - len, = operands - env, elems = env.pop(len) - ty = Type::Array.new(Type::Array::Elements.new(elems), Type::Instance.new(Type::Builtin[:ary])) - env, ty = localize_type(ty, env, ep) - env = env.push(ty) - when :newhash - num, = operands - env, tys = env.pop(num) - - ty = Type.gen_hash do |h| - tys.each_slice(2) do |k_ty, v_ty| - k_ty = globalize_type(k_ty, env, ep) - h[k_ty] = v_ty - end - end - - env, ty = localize_type(ty, env, ep) - env = env.push(ty) - when :newhashfromarray - raise NotImplementedError, "newhashfromarray" - when :newrange - env, tys = env.pop(2) - # XXX: need generics - env = env.push(Type::Instance.new(Type::Builtin[:range])) - - when :concatstrings - num, = operands - env, = env.pop(num) - env = env.push(Type::Instance.new(Type::Builtin[:str])) - when :tostring, :anytostring - env, (_ty1, _ty2,) = env.pop(2) - env = env.push(Type::Instance.new(Type::Builtin[:str])) - when :objtostring - env, (_ty1,) = env.pop(1) - env = env.push(Type::Instance.new(Type::Builtin[:str])) - when :freezestring - # do nothing - when :toregexp - _regexp_opt, str_count = operands - env, tys = env.pop(str_count) - # TODO: check if tys are all strings? - env = env.push(Type::Instance.new(Type::Builtin[:regexp])) - when :intern - env, (ty,) = env.pop(1) - # XXX check if ty is String - env = env.push(Type::Instance.new(Type::Builtin[:sym])) - - when :definemethod - mid, iseq = operands - do_define_iseq_method(ep, env, mid, iseq, nil) - - when :definesmethod - mid, iseq = operands - env, (recv,) = env.pop(1) - cref = ep.ctx.cref - recv.each_child do |recv| - if recv.is_a?(Type::Class) - typed_mdef = check_typed_method(recv, mid, true) - if typed_mdef - mdef = ISeqMethodDef.new(iseq, cref, nil, env.static_env.pub_meth) - typed_mdef.each do |typed_mdef| - typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self) - end - else - meth = add_singleton_iseq_method(recv, mid, iseq, cref, nil, env.static_env.pub_meth) - end - - pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, nil) - else - recv = Type.any # XXX: what to do? - end - end - when :defineclass - id, iseq, flags = operands - env, (cbase, superclass) = env.pop(2) - case flags & 7 - when 0, 2 # CLASS / MODULE - type = (flags & 7) == 2 ? :module : :class - existing_klass, = get_constant(cbase, id) # TODO: multiple return values - if existing_klass.is_a?(Type::Class) - # record re-opening location - @class_defs[cbase.idx].add_class_open(id, ep) - klass = existing_klass - else - if existing_klass != Type.any - error(ep, "the class \"#{ id }\" is #{ existing_klass.screen_name(self) }") - end - if type == :class - if superclass.is_a?(Type::Class) - # okay - elsif superclass == Type.any - warn(ep, "superclass is any; Object is used instead") - superclass = Type::Builtin[:obj] - elsif superclass == Type.nil - superclass = Type::Builtin[:obj] - elsif superclass.is_a?(Type::Instance) - warn(ep, "superclass is an instance; Object is used instead") - superclass = Type::Builtin[:obj] - else - warn(ep, "superclass is not a class; Object is used instead") - superclass = Type::Builtin[:obj] - end - else # module - superclass = nil - end - if cbase.is_a?(Type::Class) - klass = new_class(cbase, id, [], superclass, ep) - if superclass - add_superclass_type_args!(klass, superclass.type_params.map { Type.any }) - - # inherited hook - aargs = ActualArguments.new([klass], nil, {}, Type.nil) - do_send(superclass, :inherited, aargs, ep, env) {|_ret_ty, _ep| } - end - else - klass = Type.any - end - end - singleton = false - when 1 # SINGLETON_CLASS - singleton = true - klass = cbase - if klass.is_a?(Type::Class) - elsif klass.is_a?(Type::Any) - else - warn(ep, "A singleton class is open for #{ klass.screen_name(self) }; handled as any") - klass = Type.any - end - else - raise NotImplementedError, "unknown defineclass flag: #{ flags }" - end - ncref = ep.ctx.cref.extend(klass, singleton) - recv = singleton ? Type.any : klass - blk = env.static_env.blk_ty - nctx = Context.new(iseq, ncref, nil) - nep = ExecutionPoint.new(nctx, 0, nil) - locals = [Type.nil] * iseq.locals.size - nenv = Env.new(StaticEnv.new(recv, blk, false, true), locals, [], Utils::HashWrapper.new({})) - merge_env(nep, nenv) - add_callsite!(nep.ctx, ep, env) do |ret_ty, ep, env| - nenv, ret_ty = localize_type(ret_ty, env, ep) - nenv = nenv.push(ret_ty) - merge_env(ep.next, nenv) - end - return - when :send - env, recvs, mid, aargs = setup_actual_arguments(:method, operands, ep, env) - recvs = Type.any if recvs == Type.bot - do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env| - nenv, ret_ty, = localize_type(ret_ty, env, ep) - nenv = nenv.push(ret_ty) - merge_env(ep.next, nenv) - end - return - when :recv_getlocal_send_branch - getlocal_operands, send_operands, branch_operands = operands - env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env) - recvs = Type.any if recvs == Type.bot - recvs.each_child do |recv| - do_send(recv, mid, aargs, ep, env) do |ret_ty, ep, env| - env, ret_ty, = localize_type(ret_ty, env, ep) - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - var_idx, _scope_idx, _escaped = getlocal_operands - flow_env = env.local_update(-var_idx+2, recv) - - case ret_ty - when Type::Instance.new(Type::Builtin[:true]) - merge_env(branchtype == :if ? ep_else : ep_then, flow_env) - when Type::Instance.new(Type::Builtin[:false]) - merge_env(branchtype == :if ? ep_then : ep_else, flow_env) - else - merge_env(ep_then, env) - merge_env(ep_else, env) - end - end - end - return - when :arg_getlocal_send_branch - getlocal_operands, send_operands, branch_operands = operands - env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env) - raise if aargs.lead_tys.size != 1 - aarg = aargs.lead_tys[0] - aarg = Type.any if aarg == Type.bot - recvs.each_child do |recv| - aarg.each_child do |aarg| - aargs_tmp = ActualArguments.new([aarg], nil, {}, aargs.blk_ty) - do_send(recv, mid, aargs_tmp, ep, env) do |ret_ty, ep, env| - env, ret_ty, = localize_type(ret_ty, env, ep) - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - var_idx, _scope_idx, _escaped = getlocal_operands - flow_env = env.local_update(-var_idx+2, aarg) - - case ret_ty - when Type::Instance.new(Type::Builtin[:true]) - merge_env(branchtype == :if ? ep_else : ep_then, flow_env) - when Type::Instance.new(Type::Builtin[:false]) - merge_env(branchtype == :if ? ep_then : ep_else, flow_env) - else - merge_env(ep_then, env) - merge_env(ep_else, env) - end - end - end - end - return - when :send_branch - send_operands, branch_operands = operands - env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env) - recvs = Type.any if recvs == Type.bot - do_send(recvs, mid, aargs, ep, env) do |ret_ty, ep, env| - env, ret_ty, = localize_type(ret_ty, env, ep) - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - case ret_ty - when Type::Instance.new(Type::Builtin[:true]) - merge_env(branchtype == :if ? ep_else : ep_then, env) - when Type::Instance.new(Type::Builtin[:false]) - merge_env(branchtype == :if ? ep_then : ep_else, env) - else - merge_env(ep_then, env) - merge_env(ep_else, env) - end - end - return - when :invokeblock - env, recvs, mid, aargs = setup_actual_arguments(:block, operands, ep, env) - blk = env.static_env.blk_ty - case - when blk == Type.nil - env = env.push(Type.any) - when blk == Type.any - #warn(ep, "block is any") - env = env.push(Type.any) - else # Proc - do_invoke_block(blk, aargs, ep, env) do |ret_ty, ep, env| - nenv, ret_ty, = localize_type(ret_ty, env, ep) - nenv = nenv.push(ret_ty) - merge_env(ep.next, nenv) - end - return - end - when :invokesuper - env, recv, _, aargs = setup_actual_arguments(:method, operands, ep, env) - mid = ep.ctx.mid - found = false - recv.each_child_global do |recv| - klass, singleton = recv.method_dispatch_info - next unless klass - get_all_super_methods(klass, singleton, ep.ctx.cref.klass, ep.ctx.mid) do |meths, klass| - found = true - meths.each do |meth| - # XXX: this decomposition is really needed?? - # It calls `Object.new` with union receiver which causes an error, but - # it may be a fault of builtin Object.new implementation. - meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env| - nenv, ret_ty, = localize_type(ret_ty, env, ep) - nenv = nenv.push(ret_ty) - merge_env(ep.next, nenv) - end - end - end - end - return if found - error(ep, "no superclass method: #{ env.static_env.recv_ty.screen_name(self) }##{ mid }") - env = env.push(Type.any) - when :invokebuiltin - raise NotImplementedError - when :leave - if env.stack.size != 1 - raise "stack inconsistency error: #{ env.stack.inspect }" - end - env, (ty,) = env.pop(1) - ty = globalize_type(ty, env, ep) - add_return_value!(ep.ctx, ty) - return - when :throw - throwtype, = operands - env, (ty,) = env.pop(1) - _no_escape = !!(throwtype & 0x8000) - throwtype = [:none, :return, :break, :next, :retry, :redo][throwtype & 0xff] - case throwtype - when :none - - when :return - ty = globalize_type(ty, env, ep) - tmp_ep = ep - tmp_ep = tmp_ep.outer while tmp_ep.outer - add_return_value!(tmp_ep.ctx, ty) - return - when :break - tmp_ep = ep - while true - if tmp_ep.ctx.iseq.type == :block - tmp_ep = tmp_ep.outer - nenv = @return_envs[tmp_ep].push(ty) - merge_env(tmp_ep.next, nenv) - break - end - _type, _iseq, cont, stack_depth = tmp_ep.ctx.iseq.catch_table[tmp_ep.pc]&.find {|type,| type == :break } - if cont - nenv = @return_envs[tmp_ep] || env - nenv, = nenv.pop(nenv.stack.size - stack_depth) - nenv = nenv.push(ty) - tmp_ep = tmp_ep.jump(cont) - merge_env(tmp_ep, nenv) - break - end - tmp_ep = tmp_ep.outer - end - when :next, :redo - # begin; rescue; next; end - tmp_ep = ep.outer - _type, _iseq, cont, stack_depth = tmp_ep.ctx.iseq.catch_table[tmp_ep.pc].find {|type,| type == throwtype } - nenv = @return_envs[tmp_ep] - nenv, = nenv.pop(nenv.stack.size - stack_depth) - nenv = nenv.push(ty) if throwtype == :next - tmp_ep = tmp_ep.jump(cont) - merge_env(tmp_ep, nenv) - when :retry - tmp_ep = ep.outer - _type, _iseq, cont, stack_depth = tmp_ep.ctx.iseq.catch_table[tmp_ep.pc].find {|type,| type == :retry } - nenv = @return_envs[tmp_ep] - nenv, = nenv.pop(nenv.stack.size - stack_depth) - tmp_ep = tmp_ep.jump(cont) - merge_env(tmp_ep, nenv) - else - p throwtype - raise NotImplementedError - end - return - when :once - iseq, = operands - - nctx = Context.new(iseq, ep.ctx.cref, ep.ctx.mid) - nep = ExecutionPoint.new(nctx, 0, ep) - raise if iseq.locals != [] - nenv = Env.new(env.static_env, [], [], nil) - merge_env(nep, nenv) - add_callsite!(nep.ctx, ep, env) do |ret_ty, ep, env| - nenv, ret_ty = localize_type(ret_ty, env, ep) - nenv = nenv.push(ret_ty) - merge_env(ep.next, nenv) - end - return - - when :branch # TODO: check how branchnil is used - branchtype, target, = operands - # branchtype: :if or :unless or :nil - env, (ty,) = env.pop(1) - ep_then = ep.next - ep_else = ep.jump(target) - - # TODO: it works for only simple cases: `x = nil; x || 1` - # It would be good to merge "dup; branchif" to make it context-sensitive-like - falsy = ty == Type.nil - - merge_env(ep_then, env) - merge_env(ep_else, env) unless branchtype == :if && falsy - return - when :jump - target, = operands - merge_env(ep.jump(target), env) - return - - when :setinstancevariable - var, = operands - env, (ty,) = env.pop(1) - recv = env.static_env.recv_ty - set_instance_variable(recv, var, ty, ep, env) - - when :getinstancevariable - var, = operands - recv = env.static_env.recv_ty - get_instance_variable(recv, var, ep, env) do |ty, nenv| - merge_env(ep.next, nenv.push(ty)) - end - return - - when :setclassvariable - var, = operands - env, (ty,) = env.pop(1) - cbase = ep.ctx.cref.klass - ty = globalize_type(ty, env, ep) - # TODO: if superclass has the variable, it should be updated - add_cvar_write!(cbase, var, ty, ep) - - when :getclassvariable - var, = operands - cbase = ep.ctx.cref.klass - # TODO: if superclass has the variable, it should be read - add_cvar_read!(cbase, var, ep) do |ty, ep| - nenv, ty = localize_type(ty, env, ep) - merge_env(ep.next, nenv.push(ty)) - end - return - - when :setglobal - var, = operands - env, (ty,) = env.pop(1) - ty = globalize_type(ty, env, ep) - add_gvar_write!(var, ty, ep) - - when :getglobal - var, = operands - ty = Type.builtin_global_variable_type(var) - if ty - ty, locs = get_constant(Type::Builtin[:obj], ty) if ty.is_a?(Symbol) - env, ty = localize_type(ty, env, ep) - env = env.push(ty) - else - add_gvar_read!(var, ep) do |ty, ep| - nenv, ty = localize_type(ty, env, ep) - merge_env(ep.next, nenv.push(ty)) - end - # need to return default nil of global variables - return - end - - when :getlocal - var_idx, scope_idx, _escaped = operands - if scope_idx == 0 - ty = env.get_local(-var_idx+2) - else - tmp_ep = ep - scope_idx.times do - tmp_ep = tmp_ep.outer - end - ty = @return_envs[tmp_ep].get_local(-var_idx+2) - end - env = env.push(ty) - when :getlocal_branch - getlocal_operands, branch_operands = operands - var_idx, _scope_idx, _escaped = getlocal_operands - ret_ty = env.get_local(-var_idx+2) - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - var_idx, _scope_idx, _escaped = getlocal_operands - - ret_ty.each_child do |ret_ty| - flow_env = env.local_update(-var_idx+2, ret_ty) - case ret_ty - when Type.any - merge_env(ep_then, flow_env) - merge_env(ep_else, flow_env) - when Type::Instance.new(Type::Builtin[:false]), Type.nil - merge_env(branchtype == :if ? ep_then : ep_else, flow_env) - else - merge_env(branchtype == :if ? ep_else : ep_then, flow_env) - end - end - return - when :getlocal_dup_branch - getlocal_operands, _dup_operands, branch_operands = operands - var_idx, _scope_idx, _escaped = getlocal_operands - ret_ty = env.get_local(-var_idx+2) - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - ret_ty.each_child do |ret_ty| - flow_env = env.local_update(-var_idx+2, ret_ty).push(ret_ty) - case ret_ty - when Type.any - merge_env(ep_then, flow_env) - merge_env(ep_else, flow_env) - when Type::Instance.new(Type::Builtin[:false]), Type.nil - merge_env(branchtype == :if ? ep_then : ep_else, flow_env) - else - merge_env(branchtype == :if ? ep_else : ep_then, flow_env) - end - end - return - when :dup_setlocal_branch - _dup_operands, setlocal_operands, branch_operands = operands - - env, (ret_ty,) = env.pop(1) - - var_idx, _scope_idx, _escaped = setlocal_operands - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - ret_ty.each_child do |ret_ty| - flow_env = env.local_update(-var_idx+2, ret_ty) - case ret_ty - when Type.any - merge_env(ep_then, flow_env) - merge_env(ep_else, flow_env) - when Type::Instance.new(Type::Builtin[:false]), Type.nil - merge_env(branchtype == :if ? ep_then : ep_else, flow_env) - else - merge_env(branchtype == :if ? ep_else : ep_then, flow_env) - end - end - return - when :getlocal_checkmatch_branch - getlocal_operands, branch_operands = operands - var_idx, _scope_idx, _escaped = getlocal_operands - ret_ty = env.get_local(-var_idx+2) - - env, (pattern_ty,) = env.pop(1) - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - var_idx, _scope_idx, _escaped = getlocal_operands - - ret_ty.each_child do |ret_ty| - flow_env = env.local_update(-var_idx+2, ret_ty) - ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Symbol) - ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Local) - if ret_ty.is_a?(Type::Instance) - if ret_ty.klass == pattern_ty # XXX: inheritance - merge_env(branchtype == :if ? ep_else : ep_then, flow_env) - else - merge_env(branchtype == :if ? ep_then : ep_else, flow_env) - end - else - merge_env(ep_then, flow_env) - merge_env(ep_else, flow_env) - end - end - return - when :setlocal, :setblockparam - var_idx, scope_idx, _escaped = operands - env, (ty,) = env.pop(1) - if scope_idx == 0 - env = env.local_update(-var_idx+2, ty) - else - tmp_ep = ep - scope_idx.times do - tmp_ep = tmp_ep.outer - end - merge_return_env(tmp_ep) do |env| - env.merge(env.local_update(-var_idx+2, ty)) - end - end - when :getconstant - name, = operands - env, (cbase, _allow_nil,) = env.pop(2) - if cbase == Type.nil - ty, locs = search_constant(ep.ctx.cref, name) - env, ty = localize_type(ty, env, ep) - env = env.push(ty) - elsif cbase == Type.any - env = env.push(Type.any) # XXX: warning needed? - else - ty, locs = get_constant(cbase, name) - env, ty = localize_type(ty, env, ep) - env = env.push(ty) - end - locs&.each do |loc| - ep.ctx.iseq.add_def_loc(ep.pc, loc) - end - when :setconstant - name, = operands - env, (ty, cbase) = env.pop(2) - old_ty, old_locs = get_constant(cbase, name) - if old_locs == [nil] # RBS defined - # TODO: it would be better to check if ty is consistent with old_ty (defined in RBS) - # instead of extending the type - env, old_ty = localize_type(globalize_type(old_ty, env, ep), env, ep) - ty = ty.union(old_ty) - elsif old_ty != Type.any # XXX??? - warn(ep, "already initialized constant #{ Type::Instance.new(cbase).screen_name(self) }::#{ name }") - end - ty.each_child do |ty| - if ty.is_a?(Type::Class) && cbase.is_a?(Type::Class) && ty.superclass == Type::Builtin[:struct] - @class_defs[ty.idx].name = cbase_path(cbase) + [name] - end - end - add_constant(cbase, name, globalize_type(ty, env, ep), ep) - - when :getspecial - key, type = operands - if type == 0 - case key - when 0 # VM_SVAR_LASTLINE - env = env.push(Type.any) # or String | NilClass only? - when 1 # VM_SVAR_BACKREF ($~) - merge_env(ep.next, env.push(Type::Instance.new(Type::Builtin[:matchdata]))) - merge_env(ep.next, env.push(Type.nil)) - return - else # flip-flop - env = env.push(Type.bool) - end - else - # NTH_REF ($1, $2, ...) / BACK_REF ($&, $+, ...) - merge_env(ep.next, env.push(Type::Instance.new(Type::Builtin[:str]))) - merge_env(ep.next, env.push(Type.nil)) - return - end - when :setspecial - key, = operands - if key >= 2 # flip-flop - env, = env.pop(1) - else - raise "unknown setspecial key: #{ key }" - end - - when :dup - env, (ty,) = env.pop(1) - env = env.push(ty).push(ty) - when :dup_branch - _dup_operands, branch_operands = operands - env, (ty,) = env.pop(1) - - branchtype, target, = branch_operands - # branchtype: :if or :unless or :nil - ep_then = ep.next - ep_else = ep.jump(target) - - ty.each_child do |ty| - flow_env = env.push(ty) - case ty - when Type.any - merge_env(ep_then, flow_env) - merge_env(ep_else, flow_env) - when Type::Instance.new(Type::Builtin[:false]), Type.nil - merge_env(branchtype == :if ? ep_then : ep_else, flow_env) - else - merge_env(branchtype == :if ? ep_else : ep_then, flow_env) - end - end - return - when :duphash - raw_hash, = operands - ty = Type.guess_literal_type(raw_hash) - env, ty = localize_type(globalize_type(ty, env, ep), env, ep) - env = env.push(ty) - when :dupn - n, = operands - _, tys = env.pop(n) - tys.each {|ty| env = env.push(ty) } - when :pop - env, = env.pop(1) - when :swap - env, (a, b) = env.pop(2) - env = env.push(a).push(b) - when :reverse - n, = operands - env, tys = env.pop(n) - tys.reverse_each {|ty| env = env.push(ty) } - when :defined - env, = env.pop(1) - sym_ty = Type::Symbol.new(nil, Type::Instance.new(Type::Builtin[:sym])) - env = env.push(Type.optional(sym_ty)) - when :checkmatch - flag, = operands - - # This flag means that the stack top is an array, and the check needs to be applied to find all elements - # However, currently TypeProf uses very conservative interpretation (all check returns both true and false), - # so we just ignore the flag now - _array = flag & 4 != 0 - - case flag & 3 - when 1 # VM_CHECKMATCH_TYPE_WHEN - env, = env.pop(2) - env = env.push(Type.bool) - when 2 # VM_CHECKMATCH_TYPE_CASE - env, = env.pop(2) - env = env.push(Type.bool) - when 3 # VM_CHECKMATCH_TYPE_RESCUE - env, = env.pop(2) - env = env.push(Type.bool) - else - raise "unknown checkmatch flag" - end - when :checkkeyword - env = env.push(Type.bool) - when :adjuststack - n, = operands - env, _ = env.pop(n) - when :nop - when :setn - idx, = operands - if idx >= 1 - env, (ty,) = env.pop(1) - env = env.setn(idx, ty).push(ty) - end - when :topn - idx, = operands - env = env.topn(idx) - - when :splatarray - env, (ty,) = env.pop(1) - # XXX: vm_splat_array - env = env.push(ty) - when :expandarray - num, flag = operands - env, (ary,) = env.pop(1) - splat = flag & 1 == 1 - from_head = flag & 2 == 0 - ary.each_child do |ary| - case ary - when Type::Local - if ary.kind == Type::Array - elems = get_container_elem_types(env, ep, ary.id) - elems ||= Type::Array::Elements.new([], Type.any) # XXX - else - elems = Type::Array::Elements.new([], Type.any) # XXX - end - do_expand_array(ep, env, elems, num, splat, from_head) - when Type::Any - nnum = num - nnum += 1 if splat - nenv = env - nnum.times do - nenv = nenv.push(Type.any) - end - add_edge(ep, ep) - merge_env(ep.next, nenv) - else - # TODO: call to_ary (or to_a?) - elems = Type::Array::Elements.new([ary], Type.bot) - do_expand_array(ep, env, elems, num, splat, from_head) - end - end - return - when :concatarray - env, (ary1, ary2) = env.pop(2) - if ary1.is_a?(Type::Local) && ary1.kind == Type::Array - elems1 = get_container_elem_types(env, ep, ary1.id) - if ary2.is_a?(Type::Local) && ary2.kind == Type::Array - elems2 = get_container_elem_types(env, ep, ary2.id) - elems = Type::Array::Elements.new([], elems1.squash.union(elems2.squash)) - env = update_container_elem_types(env, ep, ary1.id, ary1.base_type) { elems } - env = env.push(ary1) - else - elems = Type::Array::Elements.new([], Type.any) - env = update_container_elem_types(env, ep, ary1.id, ary1.base_type) { elems } - env = env.push(ary1) - end - else - ty = Type::Array.new(Type::Array::Elements.new([], Type.any), Type::Instance.new(Type::Builtin[:ary])) - env, ty = localize_type(ty, env, ep) - env = env.push(ty) - end - - when :checktype - kind, = operands - case kind - when 5 then klass = :str # T_STRING - when 7 then klass = :ary # T_ARRAY - when 8 then klass = :hash # T_HASH - else - raise NotImplementedError - end - env, (val,) = env.pop(1) - ty = Type.bot - val.each_child do |val| - #globalize_type(val, env, ep).each_child_global do |val| - val = val.base_type while val.respond_to?(:base_type) - case val - when Type::Instance.new(Type::Builtin[klass]) - ty = ty.union(Type::Instance.new(Type::Builtin[:true])) - when Type.any - ty = Type.bool - else - ty = ty.union(Type::Instance.new(Type::Builtin[:false])) - end - end - env = env.push(ty) - else - raise "Unknown insn: #{ insn.insn }" - end - - add_edge(ep, ep) - merge_env(ep.next, env) - - if ep.ctx.iseq.catch_table[ep.pc] - ep.ctx.iseq.catch_table[ep.pc].each do |type, iseq, cont, stack_depth| - next if type != :rescue && type != :ensure - next if env.stack.size < stack_depth - cont_ep = ep.jump(cont) - cont_env, = env.pop(env.stack.size - stack_depth) - nctx = Context.new(iseq, ep.ctx.cref, ep.ctx.mid) - nep = ExecutionPoint.new(nctx, 0, cont_ep) - locals = [Type.nil] * iseq.locals.size - nenv = Env.new(env.static_env, locals, [], Utils::HashWrapper.new({})) - merge_env(nep, nenv) - add_callsite!(nep.ctx, cont_ep, cont_env) do |ret_ty, ep, env| - nenv, ret_ty = localize_type(ret_ty, env, ep) - nenv = nenv.push(ret_ty) - merge_env(ep.jump(cont), nenv) - end - end - end - end - - private def do_expand_array(ep, env, elems, num, splat, from_head) - if from_head - lead_tys, rest_ary_ty = elems.take_first(num) - if splat - env, local_ary_ty = localize_type(rest_ary_ty, env, ep) - env = env.push(local_ary_ty) - end - lead_tys.reverse_each do |ty| - env = env.push(ty) - end - else - rest_ary_ty, following_tys = elems.take_last(num) - following_tys.each do |ty| - env = env.push(ty) - end - if splat - env, local_ary_ty = localize_type(rest_ary_ty, env, ep) - env = env.push(local_ary_ty) - end - end - merge_env(ep.next, env) - end - - private def setup_actual_arguments(kind, operands, ep, env) - opt, blk_iseq = operands - flags = opt[:flag] - mid = opt[:mid] - kw_arg = opt[:kw_arg] - argc = opt[:orig_argc] - argc += 1 if kind == :method # for the receiver - argc += kw_arg.size if kw_arg - - flag_args_splat = flags[ 0] != 0 - flag_args_blockarg = flags[ 1] != 0 - _flag_args_fcall = flags[ 2] != 0 - _flag_args_vcall = flags[ 3] != 0 - _flag_args_simple = flags[ 4] != 0 # unused in TP - _flag_blockiseq = flags[ 5] != 0 # unused in VM :-) - flag_args_kwarg = flags[ 6] != 0 - flag_args_kw_splat = flags[ 7] != 0 - _flag_tailcall = flags[ 8] != 0 - _flag_super = flags[ 9] != 0 - _flag_zsuper = flags[10] != 0 - - argc += 1 if flag_args_blockarg - - env, aargs = env.pop(argc) - - recv = aargs.shift if kind == :method - - if flag_args_blockarg - blk_ty = aargs.pop - elsif blk_iseq - blk_ty = Type::Proc.new(ISeqBlock.new(blk_iseq, ep), Type::Instance.new(Type::Builtin[:proc])) - else - blk_ty = Type.nil - end - - new_blk_ty = Type.bot - blk_ty.each_child do |blk_ty| - case blk_ty - when Type.nil - when Type.any - when Type::Proc - when Type::Symbol - blk_ty = Type::Proc.new(SymbolBlock.new(blk_ty.sym), Type::Instance.new(Type::Builtin[:proc])) - else - # XXX: attempt to call to_proc - error(ep, "wrong argument type #{ blk_ty.screen_name(self) } (expected Proc)") - blk_ty = Type.any - end - new_blk_ty = new_blk_ty.union(blk_ty) - end - blk_ty = new_blk_ty - - if flag_args_splat - # assert !flag_args_kwarg - rest_ty = aargs.last - aargs = aargs[0..-2] - if flag_args_kw_splat - # XXX: The types contained in ActualArguments are expected to be all local types. - # This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil. - # To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does), - # and globalize some types on the on-demand bases. - ty = globalize_type(rest_ty, env, ep) - if ty.is_a?(Type::Array) - _, (ty,) = ty.elems.take_last(1) - case ty - when Type::Hash - kw_tys = ty.elems.to_keywords - when Type::Union - hash_elems = nil - ty.elems&.each do |(container_kind, base_type), elems| - if container_kind == Type::Hash - elems.to_keywords - hash_elems = hash_elems ? hash_elems.union(elems) : elems - end - end - if hash_elems - kw_tys = hash_elems.to_keywords - else - kw_tys = { nil => Type.any } - end - else - warn(ep, "non hash is passed to **kwarg?") unless ty == Type.any - kw_tys = { nil => Type.any } - end - else - raise NotImplementedError - end - else - kw_tys = {} - end - aargs = ActualArguments.new(aargs, rest_ty, kw_tys, blk_ty) - elsif flag_args_kw_splat - last = aargs.last - # XXX: The types contained in ActualArguments are expected to be all local types. - # This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil. - # To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does), - # and globalize some types on the on-demand bases. - ty = globalize_type(last, env, ep) - case ty - when Type::Hash - aargs = aargs[0..-2] - kw_tys = ty.elems.to_keywords - when Type::Union - hash_elems = nil - ty.elems&.each do |(container_kind, base_type), elems| - if container_kind == Type::Hash - hash_elems = hash_elems ? hash_elems.union(elems) : elems - end - end - if hash_elems - kw_tys = hash_elems.to_keywords - else - kw_tys = { nil => Type.any } - end - when Type::Any - aargs = aargs[0..-2] - kw_tys = { nil => Type.any } - else - warn(ep, "non hash is passed to **kwarg?") - kw_tys = { nil => Type.any } - end - aargs = ActualArguments.new(aargs, nil, kw_tys, blk_ty) - elsif flag_args_kwarg - kw_vals = aargs.pop(kw_arg.size) - - kw_tys = {} - kw_arg.zip(kw_vals) do |key, v_ty| - kw_tys[key] = v_ty - end - - aargs = ActualArguments.new(aargs, nil, kw_tys, blk_ty) - else - aargs = ActualArguments.new(aargs, nil, {}, blk_ty) - end - - if blk_iseq - # pending dummy execution - nctx = Context.new(blk_iseq, ep.ctx.cref, ep.ctx.mid) - nep = ExecutionPoint.new(nctx, 0, ep) - nlocals = [Type.any] * blk_iseq.locals.size - nsenv = StaticEnv.new(env.static_env.recv_ty, Type.any, env.static_env.mod_func, env.static_env.pub_meth) - nenv = Env.new(nsenv, nlocals, [], nil) - pend_block_dummy_execution(blk_ty, blk_iseq, nep, nenv) - merge_return_env(ep) {|tenv| tenv ? tenv.merge(env) : env } - end - - aargs.node_id = opt[:node_id] - - return env, recv, mid, aargs - end - - def do_send(recvs, mid, aargs, ep, env, &ctn) - if mid == :__typeprof_lsp_completion - names = {} - recvs.each_child do |recv| - case recv - when Type::Void, Type::Any - else - klass, singleton, include_subclasses = recv.method_dispatch_info - names.merge!(get_all_methods(klass, singleton, include_subclasses)) if klass - end - end - @lsp_completion = names - return ctn[Type.any, ep, env] - end - - recvs.each_child do |recv| - case recv - when Type::Void - error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }") - ctn[Type.any, ep, env] - when Type::Any - ctn[Type.any, ep, env] - else - klass, singleton, include_subclasses = recv.method_dispatch_info - meths = get_method(klass, singleton, include_subclasses, mid) if klass - if meths - path, loc = Config.current.options[:signature_help_loc] - if path && path == ep.ctx.iseq.path && mid != :inherited # XXX: too ad-hoc!!! - path, code_range = ep&.detailed_source_location - if path && code_range&.contain_loc?(loc) - @lsp_signature_help[code_range] = { - recv: recv, - mid: mid, - singleton: singleton, - mdefs: meths, - node_id: aargs.node_id, - } - end - end - meths.each do |meth| - meth.do_send(recv, mid, aargs, ep, env, self, &ctn) - end - else - meths = get_method(klass, singleton, include_subclasses, :method_missing) if klass - if meths - aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym]))) - meths.each do |meth| - meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn) - end - else - error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }") - ctn[Type.any, ep, env] - end - end - end - end - end - - def do_invoke_block(blk, aargs, ep, env, replace_recv_ty: nil, replace_cref: nil, &ctn) - blk.each_child do |blk| - if blk.is_a?(Type::Proc) - blk.block_body.do_call(aargs, ep, env, self, replace_recv_ty: replace_recv_ty, replace_cref: replace_cref, &ctn) - else - warn(ep, "non-proc is passed as a block") if blk != Type.any - ctn[Type.any, ep, env] - end - end - end - - def do_define_iseq_method(ep, env, mid, iseq, outer_ep) - cref = ep.ctx.cref - if cref.klass.is_a?(Type::Class) - typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton) - recv = cref.klass - recv = Type::Instance.new(recv) unless ep.ctx.cref.singleton - if typed_mdef - mdef = ISeqMethodDef.new(iseq, cref, outer_ep, env.static_env.pub_meth) - typed_mdef.each do |typed_mdef| - typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self) - end - else - if ep.ctx.cref.singleton - meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true) - else - meth = add_iseq_method(cref.klass, mid, iseq, cref, outer_ep, env.static_env.pub_meth) - if env.static_env.mod_func - add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true) - end - end - end - - pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, outer_ep) - else - # XXX: what to do? - end - end - - def show_block_signature(blks) - bsig = nil - ret_ty = Type.bot - - blks.each do |blk| - blk.each_child_global do |blk| - bsig0 = @block_signatures[blk.block_body] - if bsig0 - if bsig - bsig = bsig.merge(bsig0) - else - bsig = bsig0 - end - end - - @block_to_ctx[blk.block_body]&.each do |blk_ctx| - ret_ty = ret_ty.union(@return_values[blk_ctx]) if @return_values[blk_ctx] - end - end - end - - bsig ||= BlockSignature.new([], [], nil, Type.nil) - - bsig, = bsig.screen_name(nil, self) - ret_ty = ret_ty.screen_name(self) - ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX? - - bsig = bsig + " " if bsig != "" - "{ #{ bsig }-> #{ ret_ty } }" - end - - def show_proc_signature(blks) - farg_tys, ret_ty = nil, Type.bot - - blks.each do |blk| - blk.each_child_global do |blk| - next if blk.block_body.is_a?(TypedBlock) # XXX: Support TypedBlock - next unless @block_to_ctx[blk.block_body] # this occurs when screen_name is called before type-profiling finished (e.g., error message) - @block_to_ctx[blk.block_body].each do |blk_ctx| - if farg_tys - if @method_signatures[blk_ctx] - farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx]) - else - # this occurs when screen_name is called before type-profiling finished (e.g., error message) - end - else - farg_tys = @method_signatures[blk_ctx] - end - - ret_ty = ret_ty.union(@return_values[blk_ctx]) if @return_values[blk_ctx] - end - end - end - - return Type.any.screen_name(self) if @types_being_shown.include?(farg_tys) || @types_being_shown.include?(ret_ty) - - begin - @types_being_shown << farg_tys << ret_ty - farg_tys, = farg_tys ? farg_tys.screen_name(nil, self) : ["(unknown)"] - ret_ty = ret_ty.screen_name(self) - ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX? - - farg_tys = farg_tys + " " if farg_tys != "" - "^#{ farg_tys }-> #{ ret_ty }" - ensure - @types_being_shown.pop(2) - end - end - - def show_method_signature(ctx) - farg_tys = @method_signatures[ctx] - return nil unless farg_tys - ret_ty = ctx.mid == :initialize ? Type::Void.new : @return_values[ctx] || Type.bot - - untyped = farg_tys.include_untyped?(self) || ret_ty.include_untyped?(self) - - farg_tys, ranges = farg_tys.screen_name(ctx.iseq, self) - ret_ty = ret_ty.screen_name(self) - ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX? - - return "#{ (farg_tys.empty? ? "" : "#{ farg_tys } ") }-> #{ ret_ty }", untyped, ranges - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/arguments.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/arguments.rb deleted file mode 100644 index 969f1a5e8035..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/arguments.rb +++ /dev/null @@ -1,414 +0,0 @@ -module TypeProf - # Arguments from caller side - class ActualArguments - def initialize(lead_tys, rest_ty, kw_tys, blk_ty) - @lead_tys = lead_tys - raise unless lead_tys - @rest_ty = rest_ty - @kw_tys = kw_tys # kw_tys should be {:key1 => Type, :key2 => Type, ...} or {nil => Type} - raise if !kw_tys.is_a?(::Hash) - @blk_ty = blk_ty - raise unless blk_ty - end - - def for_method_missing(mid) - ActualArguments.new([mid] + @lead_tys, @rest_ty, @kw_tys, @blk_ty) - end - - attr_reader :lead_tys, :rest_ty, :kw_tys, :blk_ty - attr_accessor :node_id - - def globalize(caller_env, visited, depth) - lead_tys = @lead_tys.map {|ty| ty.globalize(caller_env, visited, depth) } - rest_ty = @rest_ty.globalize(caller_env, visited, depth) if @rest_ty - kw_tys = @kw_tys.to_h do |key, ty| - [key, ty.globalize(caller_env, visited, depth)] - end - ActualArguments.new(lead_tys, rest_ty, kw_tys, @blk_ty) - end - - def limit_size(limit) - self - end - - def consistent_with_method_signature?(msig) - aargs = @lead_tys.dup - - # aargs: lead_tys, rest_ty - # msig: lead_tys, opt_tys, rest_ty, post_tys - if @rest_ty - lower_bound = [0, msig.lead_tys.size + msig.post_tys.size - aargs.size].max - upper_bound = [0, lower_bound + msig.opt_tys.size].max - (lower_bound..upper_bound).each do |n| - # BUG: @rest_ty is an Array, so need to squash - tmp_aargs = ActualArguments.new(@lead_tys + [@rest_ty] * n, nil, @kw_tys, @blk_ty) - subst = tmp_aargs.consistent_with_method_signature?(msig) # XXX: wrong subst handling in the loop! - return subst if subst - end - return nil - end - - subst = {} - if msig.rest_ty - return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size - aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg| - return nil unless subst2 = Type.match?(aarg, farg) - subst = Type.merge_substitution(subst, subst2) - end - aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg| - return nil unless subst2 = Type.match?(aarg, farg) - subst = Type.merge_substitution(subst, subst2) - end - msig.opt_tys.each do |farg| - break if aargs.empty? - aarg = aargs.shift - return nil unless subst2 = Type.match?(aarg, farg) - subst = Type.merge_substitution(subst, subst2) - end - aargs.each do |aarg| - return nil unless subst2 = Type.match?(aarg, msig.rest_ty) - subst = Type.merge_substitution(subst, subst2) - end - else - return nil if aargs.size < msig.lead_tys.size + msig.post_tys.size - return nil if aargs.size > msig.lead_tys.size + msig.post_tys.size + msig.opt_tys.size - aargs.shift(msig.lead_tys.size).zip(msig.lead_tys) do |aarg, farg| - return nil unless subst2 = Type.match?(aarg, farg) - subst = Type.merge_substitution(subst, subst2) - end - aargs.pop(msig.post_tys.size).zip(msig.post_tys) do |aarg, farg| - return nil unless subst2 = Type.match?(aarg, farg) - subst = Type.merge_substitution(subst, subst2) - end - aargs.zip(msig.opt_tys) do |aarg, farg| - return nil unless subst2 = Type.match?(aarg, farg) - subst = Type.merge_substitution(subst, subst2) - end - end - # XXX: msig.keyword_tys - - case msig.blk_ty - when Type::Proc - return nil if @blk_ty == Type.nil - when Type.nil - return nil if @blk_ty != Type.nil - when Type::Any - else - raise "unknown type of formal block signature" - end - - subst - end - - def argument_error(given, exp_lower, exp_upper) - case - when !exp_upper then exp = "#{ exp_lower }+" - when exp_lower == exp_upper then exp = "#{ exp_lower }" - else exp = "#{ exp_lower }..#{ exp_upper }" - end - "wrong number of arguments (given #{ given }, expected #{ exp })" - end - - def to_block_signature - if @rest_ty - rest_ty = Type.bot - @rest_ty.each_child_global do |ty| - if ty.is_a?(Type::Array) - rest_ty = rest_ty.union(ty.elems.squash) - else - # XXX: to_ary? - rest_ty = rest_ty.union(ty) - end - end - end - BlockSignature.new(@lead_tys, [], rest_ty, @blk_ty) - end - - def setup_formal_arguments(kind, locals, fargs_format) - lead_num = fargs_format[:lead_num] || 0 - post_num = fargs_format[:post_num] || 0 - post_index = fargs_format[:post_start] - rest_index = fargs_format[:rest_start] - keyword = fargs_format[:keyword] - kw_index = fargs_format[:kwbits] - keyword.size if keyword - kwrest_index = fargs_format[:kwrest] - block_index = fargs_format[:block_start] - opt = fargs_format[:opt] || [0] - ambiguous_param0 = fargs_format[:ambiguous_param0] - - lead_tys = @lead_tys - rest_ty = @rest_ty - - if kind == :block - # The rule of passing arguments to block: - # - # Let A is actual arguments and F is formal arguments. - # If F is NOT ambiguous_param0, and if length(A) == 1, and if A[0] is an Array, - # then replace A with A[0]. And then, F[i] = A[i] for all 0 <= i < length(F). - - # Handling the special case - if !ambiguous_param0 - if lead_tys.size == 1 && !rest_ty && @kw_tys.empty? # length(A) == 1 - ty = lead_tys[0] - case ty - when Type::Array - lead_tys = ty.elems.lead_tys - rest_ty = ty.elems.rest_ty - when Type::Union - if ty.elems - other_elems = {} - ty.elems.each do |(container_kind, base_type), elems| - if container_kind == Type::Array - rest_ty = rest_ty ? rest_ty.union(elems.squash) : elems.squash - else - other_elems[[container_kind, base_type]] = elems - end - end - end - lead_tys = [Type::Union.new(ty.types, other_elems)] - end - end - end - end - - # Normal case: copy actual args to formal args - if rest_ty - ty = Type.bot - additional_lead_size = nil - rest_ty.each_child_global do |ty0| - if ty0.is_a?(Type::Array) - additional_lead_size = [additional_lead_size, ty0.elems.lead_tys.size].compact.min - else - additional_lead_size = 0 - end - end - additional_lead_tys = [Type.bot] * (additional_lead_size || 0) - rest_ty.each_child_global do |ty0| - if ty0.is_a?(Type::Array) - tys, new_rest_ty = ty0.elems.take_first(additional_lead_size) - tys.each_with_index do |ty00, i| - additional_lead_tys[i] = additional_lead_tys[i].union(ty00) - end - ty = ty.union(new_rest_ty.elems.squash) - else - # XXX: to_ary? - ty = ty.union(ty0) - end - end - lead_tys += additional_lead_tys - rest_ty = ty - - # XXX: Strictly speaking, this is needed, but it brings false positives. Which is better? - #rest_ty = rest_ty.union(Type.nil) - - if rest_index - # foo(a0, a1, a2, ...(rest_ty)) --> - # def foo(l0, l1, o0=, o1=, *rest, p0, p1) - # lead_ty argc == 0: - - - - - - - - # lead_ty argc == 1: a0 - - - - - - - # lead_ty argc == 2: a0 a1 - - - - - - # lead_ty argc == 3: a0 a1 - - - a2 - - # lead_ty argc == 4: a0 a1 - - - a2 a3 - # lead_ty argc == 5: a0 a1 a2 - - a3 a4 - # lead_ty argc == 6: a0 a1 a2 a3 - a4 a5 - # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 a6 - # lead_ty argc == 8: a0 a1 a2 a3 a4|a5 a6 a7 - # - # l0 = a0 - # l1 = a1 - # o0 = a2 - # o1 = a3 - # rest = a4|a5|...|rest_ty (= cum_lead_tys[4]) - # p0 = a2|a3|...|rest_ty (= cum_lead_tys[2]) - # p1 = a3|a4|...|rest_ty (= cum_lead_tys[3]) - - cum_lead_tys = [] - ty = rest_ty - lead_tys.reverse_each do |ty0| - cum_lead_tys.unshift(ty = ty.union(ty0)) - end - - # l1, l2, o1, o2 - (lead_num + opt.size - 1).times {|i| locals[i] = lead_tys[i] || rest_ty } - opt_count = opt.size - 1 - - # rest - ty = cum_lead_tys[lead_num + opt.size - 1] || rest_ty - locals[rest_index] = Type::Array.new(Type::Array::Elements.new([], ty), Type::Instance.new(Type::Builtin[:ary])) - - # p0, p1 - off = [lead_num, lead_tys.size - post_num].max - post_num.times {|i| locals[post_index + i] = cum_lead_tys[off + i] || rest_ty } - else - # foo(a0, a1, a2, ...(rest_ty)) --> - # def foo(l0, l1, o0=, o1=, p0, p1) - # lead_ty argc == 0: - - - - - - - # lead_ty argc == 1: a0 - - - - - - # lead_ty argc == 2: a0 a1 - - - - - # lead_ty argc == 3: a0 a1 - - a2 - - # lead_ty argc == 4: a0 a1 - - a2 a3 - # lead_ty argc == 5: a0 a1 a2 - a3 a4 - # lead_ty argc == 6: a0 a1 a2 a3 a4 a5 - # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 (if there is a6, report error if kind is method, or ignore if kind is block) - # - # l0 = a0 - # l1 = a1 - # o0 = a2 - # o1 = a3 - # p0 = a2|a3|a4 - # p1 = a3|a4|a5 - - if kind == :method && lead_num + opt.size - 1 + post_num < lead_tys.size - return argument_error(lead_tys.size, lead_num + post_num, lead_num + post_num + opt.size - 1) - end - - # l1, l2, o1, o2 - (lead_num + opt.size - 1).times {|i| locals[i] = lead_tys[i] || rest_ty } - opt_count = opt.size - 1 - - # p0, p1 - post_num.times do |i| - candidates = lead_tys[lead_num, opt.size] || [] - candidates << rest_ty if candidates.size < opt.size - locals[post_index + i] = candidates.inject(&:union) - end - end - else - if rest_index - # foo(a0, a1, a2) --> - # def foo(l0, l1, o0=, o1=, *rest, p0, p1) - # lead_ty argc == 0: - - - - - - - (error if kind is method) - # lead_ty argc == 1: a0 - - - - - - (error if kind is method) - # lead_ty argc == 2: a0 a1 - - - - - (error if kind is method) - # lead_ty argc == 3: a0 a1 - - - a2 - (error if kind is method) - # lead_ty argc == 4: a0 a1 - - - a2 a3 - # lead_ty argc == 5: a0 a1 a2 - - a3 a4 - # lead_ty argc == 6: a0 a1 a2 a3 - a4 a5 - # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 a6 - # lead_ty argc == 8: a0 a1 a2 a3 a4|a5 a6 a7 - # - # len(a) < 4 -> error - # - # l0 = a0 - # l1 = a1 - # o0 = a2 - # o1 = a3 - # rest = a4|a5|...|a[[4,len(a)-3].max] - # p0 = a[[2,len(a)-2].max] - # p1 = a[[3,len(a)-1].max] - - if kind == :method && lead_tys.size < lead_num + post_num - return argument_error(lead_tys.size, lead_num + post_num, nil) - end - - # l0, l1 - lead_num.times {|i| locals[i] = lead_tys[i] || Type.nil } - - # o0, o1 - opt_count = (lead_tys.size - lead_num - post_num).clamp(0, opt.size - 1) - (opt.size - 1).times {|i| locals[lead_num + i] = i < opt_count ? lead_tys[lead_num + i] : Type.nil } - - # rest - rest_b = lead_num + opt_count - rest_e = [0, lead_tys.size - post_num].max - locals[rest_index] = Type::Array.new(Type::Array::Elements.new(lead_tys[rest_b...rest_e] || [], Type.bot), Type::Instance.new(Type::Builtin[:ary])) - - # p0, p1 - off = [lead_num, lead_tys.size - post_num].max - post_num.times {|i| locals[post_index + i] = lead_tys[off + i] || Type.nil } - else - # yield a0, a1, a2 --> - # do |l0, l1, o0=, o1=, p0, p1| - # lead_ty argc == 0: - - - - - - (error if kind is method) - # lead_ty argc == 1: a0 - - - - - (error if kind is method) - # lead_ty argc == 2: a0 a1 - - - - (error if kind is method) - # lead_ty argc == 3: a0 a1 - - a2 - (error if kind is method) - # lead_ty argc == 4: a0 a1 - - a2 a3 - # lead_ty argc == 5: a0 a1 a2 - a3 a4 - # lead_ty argc == 6: a0 a1 a2 a3 a4 a5 - # lead_ty argc == 7: a0 a1 a2 a3 a4 a5 (if there is a6, report error if kind is method, or ignore if kind is block) - # - # l0 = a0 - # l1 = a1 - # o0 = a2 - # o1 = a3 - # p0 = a2|a3|a4 - # p1 = a3|a4|a5 - - if kind == :method && (lead_tys.size < lead_num + post_num || lead_num + opt.size - 1 + post_num < lead_tys.size) - return argument_error(lead_tys.size, lead_num + post_num, lead_num + post_num + opt.size - 1) - end - - # l0, l1 - lead_num.times {|i| locals[i] = lead_tys[i] || Type.nil } - - # o0, o1 - opt_count = (lead_tys.size - lead_num - post_num).clamp(0, opt.size - 1) - (opt.size - 1).times {|i| locals[lead_num + i] = i < opt_count ? lead_tys[lead_num + i] : Type.nil } - - # p0, p1 - off = lead_num + opt_count - post_num.times {|i| locals[post_index + i] = lead_tys[off + i] || Type.nil } - end - end - - kw_tys = @kw_tys.dup - if keyword - keyword.each_with_index do |kw, i| - case - when kw.is_a?(Symbol) # required keyword - key = kw - req = true - when kw.size == 2 # optional keyword (default value is a literal) - key, default_ty = *kw - default_ty = Type.guess_literal_type(default_ty) - default_ty = default_ty.base_type if default_ty.is_a?(Type::Literal) - req = false - else # optional keyword (default value is an expression) - key, = kw - req = false - end - - if kw_tys.key?(key) - ty = kw_tys.delete(key) - else - ty = kw_tys[nil] || Type.bot - end - - if ty == Type.bot && req - return "no argument for required keywords" - end - - ty = ty.union(default_ty) if default_ty - locals[kw_index + i] = ty - end - end - - if kwrest_index - if kw_tys.key?(nil) - kw_rest_ty = Type.gen_hash {|h| h[Type.any] = kw_tys[nil] } - else - kw_rest_ty = Type.gen_hash do |h| - kw_tys.each do |key, ty| - sym = Type::Symbol.new(key, Type::Instance.new(Type::Builtin[:sym])) - h[sym] = ty - end - end - end - locals[kwrest_index] = kw_rest_ty - else - if !kw_tys.empty? - return "unknown keyword: #{ kw_tys.keys.join(", ") }" - end - end - - if block_index - locals[block_index] = @blk_ty - end - - start_pcs = opt[0..opt_count] - - return @blk_ty, start_pcs - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/block.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/block.rb deleted file mode 100644 index dc0b0f1d8e20..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/block.rb +++ /dev/null @@ -1,176 +0,0 @@ -module TypeProf - class Block - include Utils::StructuralEquality - end - - class ISeqBlock < Block - def initialize(iseq, ep) - @iseq = iseq - @outer_ep = ep - end - - attr_reader :iseq, :outer_ep - - def inspect - "#" - end - - def consistent?(other) - if other.is_a?(ISeqBlock) - self == other - else - true # XXX - end - end - - def substitute(_subst, _depth) - self - end - - def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn) - blk_env = scratch.return_envs[@outer_ep] - if replace_recv_ty - replace_recv_ty = scratch.globalize_type(replace_recv_ty, caller_env, caller_ep) - blk_env = blk_env.replace_recv_ty(replace_recv_ty) - end - aargs = scratch.globalize_type(aargs, caller_env, caller_ep) - - scratch.add_block_signature!(self, aargs.to_block_signature) - - locals = [Type.nil] * @iseq.locals.size - - blk_ty, start_pcs = aargs.setup_formal_arguments(:block, locals, @iseq.fargs_format) - if blk_ty.is_a?(String) - scratch.error(caller_ep, blk_ty) - ctn[Type.any, caller_ep, caller_env] - return - end - - cref = replace_cref || @outer_ep.ctx.cref - nctx = Context.new(@iseq, cref, nil) - callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep) - nenv = Env.new(blk_env.static_env, locals, [], nil) - alloc_site = AllocationSite.new(callee_ep) - locals.each_with_index do |ty, i| - alloc_site2 = alloc_site.add_id(i) - nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2) - nenv = nenv.local_update(i, ty) - end - - start_pcs.each do |start_pc| - scratch.merge_env(ExecutionPoint.new(nctx, start_pc, @outer_ep), nenv) - end - - scratch.add_block_to_ctx!(self, callee_ep.ctx) - scratch.add_callsite!(callee_ep.ctx, caller_ep, caller_env, &ctn) - end - end - - class TypedBlock < Block - def initialize(msig, ret_ty) - @msig = msig - @ret_ty = ret_ty - end - - attr_reader :msig, :ret_ty - - def consistent?(other) - if other.is_a?(ISeqBlock) - raise "assert false" - else - self == other - end - end - - def substitute(subst, depth) - msig = @msig.substitute(subst, depth) - ret_ty = @ret_ty.substitute(subst, depth) - TypedBlock.new(msig, ret_ty) - end - - def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn) - aargs = scratch.globalize_type(aargs, caller_env, caller_ep) - subst = aargs.consistent_with_method_signature?(@msig) - unless subst - scratch.warn(caller_ep, "The arguments is not compatibile to RBS block") - end - # check? - #subst = { Type::Var.new(:self) => caller_env.static_env.recv_ty } - # XXX: Update type vars - ret_ty = @ret_ty.remove_type_vars - ctn[ret_ty, caller_ep, caller_env] - end - end - - class SymbolBlock < Block - def initialize(sym) - @sym = sym - end - - attr_reader :iseq, :outer_ep - - def inspect - "#" - end - - def consistent?(other) - true # XXX - end - - def substitute(_subst, _depth) - self - end - - def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn) - if aargs.lead_tys.size >= 1 - recv = aargs.lead_tys[0] - recv = Type.any if recv == Type.bot - aargs = ActualArguments.new(aargs.lead_tys[1..], aargs.rest_ty, aargs.kw_tys, aargs.blk_ty) - elsif aargs.rest_ty - recv = aargs.rest_ty.elems.squash_or_any # XXX: need to shift - else - recv = Type.any - end - - scratch.add_block_signature!(self, aargs.to_block_signature) - - recv.each_child do |recv| - scratch.do_send(recv, @sym, aargs, caller_ep, caller_env, &ctn) - end - end - end - - class CustomBlock < Block - def initialize(caller_ep, mid, &blk) - @caller_ep = caller_ep - @mid = mid - @blk = blk - end - - def inspect - "#" - end - - def consistent?(other) - true # XXX - end - - def substitute(_subst, _depth) - self - end - - def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &ctn) - aargs = scratch.globalize_type(aargs, caller_env, caller_ep) - - dummy_ctx = TypedContext.new(@caller_ep, @mid) - - scratch.add_block_signature!(self, aargs.to_block_signature) - scratch.add_block_to_ctx!(self, dummy_ctx) - - @blk.call(aargs, caller_ep, caller_env, scratch, replace_recv_ty: replace_recv_ty, replace_cref: replace_cref) do |ret_ty, ep, env| - scratch.add_return_value!(dummy_ctx, ret_ty) - ctn[ret_ty, ep, env] - end - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/builtin.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/builtin.rb deleted file mode 100644 index 20074ca90f24..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/builtin.rb +++ /dev/null @@ -1,893 +0,0 @@ -module TypeProf - module Builtin - module_function - - def get_sym(target, ty, ep, scratch) - unless ty.is_a?(Type::Symbol) - scratch.warn(ep, "symbol expected") - return - end - sym = ty.sym - unless sym - scratch.warn(ep, "dynamic symbol is given to #{ target }; ignored") - return - end - sym - end - - def vmcore_set_method_alias(recv, mid, aargs, ep, env, scratch, &ctn) - klass, new_mid, old_mid = aargs.lead_tys - new_sym = get_sym("alias", new_mid, ep, scratch) or return - old_sym = get_sym("alias", old_mid, ep, scratch) or return - scratch.alias_method(klass, ep.ctx.cref.singleton, new_sym, old_sym, ep) - ctn[Type.nil, ep, env] - end - - def vmcore_undef_method(recv, mid, aargs, ep, env, scratch, &ctn) - # no-op - ctn[Type.nil, ep, env] - end - - def vmcore_hash_merge_kwd(recv, mid, aargs, ep, env, scratch, &ctn) - h1 = aargs.lead_tys[0] - h2 = aargs.lead_tys[1] - elems = nil - h1.each_child do |h1| - if h1.is_a?(Type::Local) && h1.kind == Type::Hash - h1_elems = scratch.get_container_elem_types(env, ep, h1.id) - h2.each_child do |h2| - if h2.is_a?(Type::Local) && h2.kind == Type::Hash - h2_elems = scratch.get_container_elem_types(env, ep, h2.id) - elems0 = h1_elems.union(h2_elems) - if elems - elems = elems.union(elems0) - else - elems = elems0 - end - end - end - end - end - elems ||= Type::Hash::Elements.new({Type.any => Type.any}) - base_ty = Type::Instance.new(Type::Builtin[:hash]) - ret_ty = Type::Hash.new(elems, base_ty) - ctn[ret_ty, ep, env] - end - - def vmcore_raise(recv, mid, aargs, ep, env, scratch, &ctn) - # no-op - end - - def lambda(recv, mid, aargs, ep, env, scratch, &ctn) - ctn[aargs.blk_ty, ep, env] - end - - def proc_call(recv, mid, aargs, ep, env, scratch, &ctn) - scratch.do_invoke_block(recv, aargs, ep, env, &ctn) - end - - def object_s_new(recv, mid, aargs, ep, env, scratch, &ctn) - if recv.type_params.size >= 1 - ty = Type::ContainerType.create_empty_instance(recv) - env, ty = scratch.localize_type(ty, env, ep, AllocationSite.new(ep).add_id(:object_s_new)) - else - ty = Type::Instance.new(recv) - end - meths = scratch.get_method(recv, false, false, :initialize) - meths.flat_map do |meth| - meth.do_send(ty, :initialize, aargs, ep, env, scratch) do |_ret_ty, ep, env| - ctn[ty, ep, env] - end - end - end - - def object_is_a?(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size == 1 - if recv.is_a?(Type::Instance) - if recv.klass == aargs.lead_tys[0] # XXX: inheritance - true_val = Type::Instance.new(Type::Builtin[:true]) - ctn[true_val, ep, env] - else - false_val = Type::Instance.new(Type::Builtin[:false]) - ctn[false_val, ep, env] - end - else - ctn[Type.bool, ep, env] - end - else - ctn[Type.bool, ep, env] - end - end - - def object_respond_to?(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size == 1 - sym = get_sym("respond_to?", aargs.lead_tys[0], ep, scratch) - if sym - klass, singleton = recv.method_dispatch_info - if scratch.get_method(klass, singleton, false, sym) - true_val = Type::Instance.new(Type::Builtin[:true]) - ctn[true_val, ep, env] - else - false_val = Type::Instance.new(Type::Builtin[:false]) - ctn[false_val, ep, env] - end - else - ctn[Type.bool, ep, env] - end - else - ctn[Type.bool, ep, env] - end - end - - def object_class(recv, mid, aargs, ep, env, scratch, &ctn) - if recv.is_a?(Type::Instance) - ctn[recv.klass, ep, env] - else - ctn[Type.any, ep, env] - end - end - - def object_send(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size >= 1 - mid_ty, = aargs.lead_tys - elsif aargs.rest_ty - mid_ty = aargs.rest_ty - else - return ctn[Type.any, ep, env] - end - aargs = ActualArguments.new(aargs.lead_tys[1..] || [], aargs.rest_ty, aargs.kw_tys, aargs.blk_ty) - found = false - mid_ty.each_child do |mid| - if mid.is_a?(Type::Symbol) - found = true - mid = mid.sym - scratch.do_send(recv, mid, aargs, ep, env, &ctn) - end - end - unless found - ctn[Type.any, ep, env] - end - end - - def object_instance_eval(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size >= 1 - scratch.warn(ep, "instance_eval with arguments is ignored") - ctn[Type.any, ep, env] - return - end - naargs = ActualArguments.new([recv], nil, {}, Type.nil) - nrecv = recv - nrecv = nrecv.base_type if nrecv.is_a?(Type::ContainerType) - scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: nrecv) do |ret_ty, ep| - ctn[ret_ty, ep, env] - end - end - - def module_eqq(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size == 1 - aargs.lead_tys[0].each_child do |aarg| - aarg = aarg.base_type if aarg.is_a?(Type::Symbol) # XXX - if aarg.is_a?(Type::Instance) - if aarg.klass == recv # XXX: inheritance - true_val = Type::Instance.new(Type::Builtin[:true]) - ctn[true_val, ep, env] - else - false_val = Type::Instance.new(Type::Builtin[:false]) - ctn[false_val, ep, env] - end - else - ctn[Type.bool, ep, env] - end - end - else - ctn[Type.bool, ep, env] - end - end - - def object_module_eval(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size >= 1 - scratch.warn(ep, "class_eval with arguments is ignored") - ctn[Type.any, ep, env] - return - end - naargs = ActualArguments.new([recv], nil, {}, Type.nil) - nrecv = recv - nrecv = nrecv.base_type if nrecv.is_a?(Type::ContainerType) - ncref = ep.ctx.cref.extend(nrecv, true) - scratch.do_invoke_block(aargs.blk_ty, naargs, ep, env, replace_recv_ty: nrecv, replace_cref: ncref) do |_ret_ty, ep| - ctn[recv, ep, env] - end - end - - def object_enum_for(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size >= 1 - mid_ty, = aargs.lead_tys - naargs = ActualArguments.new(aargs.lead_tys[1..], aargs.rest_ty, aargs.kw_tys, aargs.blk_ty) - elsif aargs.rest_ty - mid_ty = aargs.rest_ty - naargs = aargs - else - mid_ty = Type::Symbol.new(:each, Type::Instance.new(Type::Builtin[:sym])) - naargs = aargs - end - - elem_ty = Type.bot - enum_for_blk = CustomBlock.new(ep, mid) do |aargs, caller_ep, caller_env, scratch, replace_recv_ty:, replace_cref:, &blk_ctn| - if aargs.lead_tys.size >= 1 - elem_ty = elem_ty.union(aargs.lead_tys[0]) - else - elem_ty = elem_ty.union(Type.any) - end - ctn[Type::Cell.new(Type::Cell::Elements.new([elem_ty, Type.any]), Type::Instance.new(Type::Builtin[:enumerator])), ep, env] - blk_ctn[Type.any, caller_ep, caller_env] - end - enum_for_blk_ty = Type::Proc.new(enum_for_blk, Type::Instance.new(Type::Builtin[:proc])) - - naargs = ActualArguments.new(naargs.lead_tys, naargs.rest_ty, naargs.kw_tys, enum_for_blk_ty) - mid_ty.each_child do |mid| - if mid.is_a?(Type::Symbol) - mid = mid.sym - scratch.do_send(recv, mid, naargs, ep, env) do |_ret_ty, _ep| - ctn[Type::Cell.new(Type::Cell::Elements.new([elem_ty, Type.any]), Type::Instance.new(Type::Builtin[:enumerator])), ep, env] - end - end - end - end - - def object_privitive_method(recv, mid, aargs, ep, env, scratch, &ctn) - ctn[Type::Symbol.new(ep.ctx.mid, Type::Instance.new(Type::Builtin[:sym])), ep, env] - end - - def object_block_given?(recv, mid, aargs, ep, env, scratch, &ctn) - procs = Type.bot - no_proc = false - env.static_env.blk_ty.each_child do |blk_ty| - case blk_ty - when Type::Proc - procs = procs.union(blk_ty) - when Type.nil - no_proc = true - else - ctn[Type.bool, ep, env] - end - end - if procs != Type.bot - ctn[Type::Instance.new(Type::Builtin[:true]), ep, env.replace_blk_ty(procs)] - end - if no_proc - ctn[Type::Instance.new(Type::Builtin[:false]), ep, env.replace_blk_ty(Type.nil)] - end - end - - def module_include(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size != 1 - scratch.warn(ep, "Module#include without an argument is ignored") - ctn[Type.any, ep, env] - return - end - - unless recv.is_a?(Type::Class) - # XXX: warn? - return ctn[Type.any, ep, env] - end - - # support multiple arguments: include M1, M2 - arg = aargs.lead_tys[0] - arg.each_child do |arg| - if arg.is_a?(Type::Class) - aargs = ActualArguments.new([recv], nil, {}, Type.nil) - scratch.do_send(arg, :included, aargs, ep, env) {|_ret_ty, _ep| } - scratch.mix_module(:after, recv, arg, nil, ep.ctx.cref.singleton, ep) - end - end - ctn[recv, ep, env] - end - - def module_extend(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size != 1 - scratch.warn(ep, "Module#extend without an argument is ignored") - ctn[Type.any, ep, env] - return - end - - unless recv.is_a?(Type::Class) - # XXX: warn? - return ctn[Type.any, ep, env] - end - - arg = aargs.lead_tys[0] - arg.each_child do |arg| - if arg.is_a?(Type::Class) - aargs = ActualArguments.new([recv], nil, {}, Type.nil) - scratch.do_send(arg, :extended, aargs, ep, env) {|_ret_ty, _ep| } - # if ep.ctx.cref.singleton is true, the meta-meta level is ignored. Should we warn? - scratch.mix_module(:after, recv, arg, nil, true, ep) - end - end - ctn[recv, ep, env] - end - - def module_prepend(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size != 1 - scratch.warn(ep, "Module#prepend without an argument is ignored") - ctn[Type.any, ep, env] - return - end - - unless recv.is_a?(Type::Class) - # XXX: warn? - return ctn[Type.any, ep, env] - end - - arg = aargs.lead_tys[0] - arg.each_child do |arg| - if arg.is_a?(Type::Class) - scratch.mix_module(:before, recv, arg, nil, ep.ctx.cref.singleton, ep) - end - end - ctn[recv, ep, env] - end - - def module_module_function(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.empty? - ctn[recv, ep, env.enable_module_function] - else - aargs.lead_tys.each do |aarg| - sym = get_sym("module_function", aarg, ep, scratch) or next - meths = scratch.get_method(recv, false, false, sym) - meths.each do |mdef| - scratch.add_method(recv, sym, true, mdef) - end - end - ctn[recv, ep, env] - end - end - - def module_public(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.empty? - ctn[recv, ep, env.method_public_set(true)] - else - if recv.is_a?(Type::Class) - aargs.lead_tys.each do |aarg| - sym = get_sym("public", aarg, ep, scratch) or next - meths = scratch.get_method(recv, false, false, sym) - next unless meths - meths.each do |mdef| - mdef.pub_meth = true if mdef.respond_to?(:pub_meth=) - end - end - else - # XXX: warn? - end - ctn[recv, ep, env] - end - end - - def module_private(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.empty? - ctn[recv, ep, env.method_public_set(false)] - else - if recv.is_a?(Type::Class) - aargs.lead_tys.each do |aarg| - sym = get_sym("private", aarg, ep, scratch) or next - meths = scratch.get_method(recv, false, false, sym) - next unless meths - meths.each do |mdef| - mdef.pub_meth = false if mdef.respond_to?(:pub_meth=) - end - end - else - # XXX: warn? - end - ctn[recv, ep, env] - end - end - - def module_define_method(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size != 1 - scratch.warn(ep, "Module#define with #{ aargs.lead_tys.size } argument is ignored") - ctn[Type.any, ep, env] - return - end - - mid, = aargs.lead_tys - mid.each_child do |mid| - if mid.is_a?(Type::Symbol) - mid = mid.sym - aargs.blk_ty.each_child do |blk_ty| - if blk_ty.is_a?(Type::Proc) - blk = blk_ty.block_body - case blk - when ISeqBlock - scratch.do_define_iseq_method(ep, env, mid, blk.iseq, blk.outer_ep) - else - # XXX: what to do? - end - else - # XXX: what to do? - end - end - else - # XXX: what to do? - end - end - ctn[Type.any, ep, env] - end - - def module_attr_accessor(recv, mid, aargs, ep, env, scratch, &ctn) - aargs.lead_tys.each do |aarg| - sym = get_sym("attr_accessor", aarg, ep, scratch) or next - cref = ep.ctx.cref - scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :accessor, env.static_env.pub_meth, ep) - end - ctn[Type.nil, ep, env] - end - - def module_attr_reader(recv, mid, aargs, ep, env, scratch, &ctn) - aargs.lead_tys.each do |aarg| - sym = get_sym("attr_reader", aarg, ep, scratch) or next - cref = ep.ctx.cref - scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :reader, env.static_env.pub_meth, ep) - end - ctn[Type.nil, ep, env] - end - - def module_attr_writer(recv, mid, aargs, ep, env, scratch, &ctn) - aargs.lead_tys.each do |aarg| - sym = get_sym("attr_writer", aarg, ep, scratch) or next - cref = ep.ctx.cref - scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :writer, env.static_env.pub_meth, ep) - end - ctn[Type.nil, ep, env] - end - - def kernel_p(recv, mid, aargs, ep, env, scratch, &ctn) - aargs.lead_tys.each do |aarg| - scratch.reveal_type(ep, scratch.globalize_type(aarg, env, ep)) - end - ctn[aargs.lead_tys.size == 1 ? aargs.lead_tys.first : Type.any, ep, env] - end - - def array_aref(recv, mid, aargs, ep, env, scratch, &ctn) - return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array - - case aargs.lead_tys.size - when 1 - idx = aargs.lead_tys.first - if idx.is_a?(Type::Literal) - idx = idx.lit - idx = nil if !idx.is_a?(Integer) && !idx.is_a?(Range) - elsif idx == Type::Instance.new(Type::Builtin[:range]) - idx = (nil..nil) - else - idx = nil - end - ty = scratch.get_array_elem_type(env, ep, recv.id, idx) - ctn[ty, ep, env] - when 2 - ty = scratch.get_array_elem_type(env, ep, recv.id) - base_ty = Type::Instance.new(Type::Builtin[:ary]) - ret_ty = Type::Array.new(Type::Array::Elements.new([], ty), base_ty) - ctn[ret_ty, ep, env] - else - ctn[Type.any, ep, env] - end - end - - def array_aset(recv, mid, aargs, ep, env, scratch, &ctn) - return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array - - if aargs.lead_tys.size != 2 - # XXX: Support `ary[idx, len] = val` - #raise NotImplementedError # XXX - return ctn[Type.any, ep, env] - end - - idx = aargs.lead_tys.first - if idx.is_a?(Type::Literal) - idx = idx.lit - if !idx.is_a?(Integer) - # XXX: Support `ary[idx..end] = val` - #raise NotImplementedError # XXX - return ctn[Type.any, ep, env] - end - else - idx = nil - end - - ty = aargs.lead_tys.last - - env = scratch.update_container_elem_types(env, ep, recv.id, recv.base_type) do |elems| - elems.update(idx, ty) - end - - ctn[ty, ep, env] - end - - def array_pop(recv, mid, aargs, ep, env, scratch, &ctn) - return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Array - - if aargs.lead_tys.size != 0 - ctn[Type.any, ep, env] - return - end - - ty = scratch.get_array_elem_type(env, ep, recv.id) - ctn[ty, ep, env] - end - - def hash_aref(recv, mid, aargs, ep, env, scratch, &ctn) - return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Hash - - if aargs.lead_tys.size != 1 - ctn[Type.any, ep, env] - return - end - idx = aargs.lead_tys.first - recv.each_child do |recv| - if recv.is_a?(Type::Local) && recv.kind == Type::Hash - ty = scratch.get_hash_elem_type(env, ep, recv.id, idx) - ty = Type.nil if ty == Type.bot - else - ty = Type.any - end - ctn[ty, ep, env] - end - end - - def hash_aset(recv, mid, aargs, ep, env, scratch, &ctn) - return ctn[Type.any, ep, env] unless recv.is_a?(Type::Local) && recv.kind == Type::Hash - - if aargs.lead_tys.size != 2 - # XXX: error? - ctn[Type.any, ep, env] - return - end - - idx = aargs.lead_tys.first - idx = scratch.globalize_type(idx, env, ep) - ty = aargs.lead_tys.last - - unless recv.is_a?(Type::Local) && recv.kind == Type::Hash - # to ignore: class OptionMap < Hash - return ctn[ty, ep, env] - end - - env = scratch.update_container_elem_types(env, ep, recv.id, recv.base_type) do |elems| - elems.update(idx, ty) - end - - ctn[ty, ep, env] - end - - def struct_initialize(recv, mid, aargs, ep, env, scratch, &ctn) - struct_klass = recv.klass - while struct_klass.superclass != Type::Builtin[:struct] - struct_klass = struct_klass.superclass - end - if struct_klass.superclass != Type::Builtin[:struct] - ctn[Type.any, ep, env] - return - end - scratch.add_ivar_read!(Type::Instance.new(struct_klass), :_keyword_init, ep) do |keyword_init, ep| - scratch.add_ivar_read!(Type::Instance.new(struct_klass), :_members, ep) do |member_ary_ty, ep| - next if member_ary_ty == Type.nil - if keyword_init == Type::Instance.new(Type::Builtin[:true]) - # TODO: support kw_rest_ty - aargs.kw_tys.each do |key, val_ty| - found = false - member_ary_ty.elems.lead_tys.each do |sym| - if sym.sym == key - found = true - scratch.set_instance_variable(recv, sym.sym, val_ty, ep, env) - end - end - unless found - # TODO: what to do when not found? - end - end - else - member_ary_ty.elems.lead_tys.zip(aargs.lead_tys) do |sym, ty| - ty ||= Type.nil - scratch.set_instance_variable(recv, sym.sym, ty, ep, env) - end - end - end - end - ctn[recv, ep, env] - end - - def struct_s_new(recv, mid, aargs, ep, env, scratch, &ctn) - keyword_init = false - if aargs.kw_tys && aargs.kw_tys[:keyword_init] # XXX: more canonical way to extract keyword... - if aargs.kw_tys[:keyword_init] == Type::Instance.new(Type::Builtin[:true]) - keyword_init = true - end - end - - fields = aargs.lead_tys.map {|ty| get_sym("Struct.new", ty, ep, scratch) }.compact - struct_klass = scratch.new_struct(ep) - - scratch.set_singleton_custom_method(struct_klass, :new, Builtin.method(:object_s_new)) - scratch.set_singleton_custom_method(struct_klass, :[], Builtin.method(:object_s_new)) - fields.each do |field| - scratch.add_attr_method(struct_klass, field, field, :accessor, true, ep) - end - fields = fields.map {|field| Type::Symbol.new(field, Type::Instance.new(Type::Builtin[:sym])) } - base_ty = Type::Instance.new(Type::Builtin[:ary]) - fields = Type::Array.new(Type::Array::Elements.new(fields), base_ty) - scratch.add_ivar_write!(Type::Instance.new(struct_klass), :_members, fields, ep) - scratch.add_ivar_write!(Type::Instance.new(struct_klass), :_keyword_init, Type::Instance.new(Type::Builtin[:true]), ep) if keyword_init - #set_singleton_custom_method(struct_klass, :members, Builtin.method(:...)) - - ctn[struct_klass, ep, env] - end - - def self.file_load(path, ep, env, scratch, &ctn) - iseq, = ISeq.compile(path) - callee_ep, callee_env = TypeProf.starting_state(iseq) - scratch.merge_env(callee_ep, callee_env) - - scratch.add_callsite!(callee_ep.ctx, ep, env) do |_ret_ty, ep| - ret_ty = Type::Instance.new(Type::Builtin[:true]) - ctn[ret_ty, ep, env] - end - end - - def self.file_require(feature, scratch) - # XXX: dynamic RBS load is really needed?? Another idea: - # - # * RBS should be loaded in advance of analysis - # * require "some_gem/foo" should be ignored - # * require "app/foo" should always load .rb file (in this case, app/foo.rb) - return :done, :true if Import.import_library(scratch, feature) - - # Try to analyze the source code of the gem - begin - gem feature - rescue Gem::MissingSpecError, Gem::LoadError - end - - begin - filetype, path = $LOAD_PATH.resolve_feature_path(feature) - - if filetype == :rb - return :done, :false if scratch.loaded_files[path] - scratch.loaded_files[path] = true - - return :do, path if File.readable?(path) - - return :error, "failed to load: #{ path }" - else - return :error, "cannot load a .so file: #{ path }" - end - rescue LoadError - return :error, "failed to require: #{ feature }" - end - end - - def kernel_require(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size != 1 - # XXX: handle correctly - ctn[Type.any, ep, env] - return - end - - feature = aargs.lead_tys.first - if feature.is_a?(Type::Literal) - feature = feature.lit - - unless feature.is_a?(String) - return ctn[Type.any, ep, env] - end - - action, arg = Builtin.file_require(feature, scratch) - case action - when :do - Builtin.file_load(arg, ep, env, scratch, &ctn) - when :done - result = Type::Instance.new(Type::Builtin[arg]) - ctn[result, ep, env] - when :error - scratch.warn(ep, arg) - result = Type.bool - ctn[result, ep, env] - end - else - scratch.warn(ep, "require target cannot be identified statically") - result = Type.bool - ctn[result, ep, env] - end - end - - def kernel_require_relative(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size != 1 - # XXX: handle correctly - ctn[Type.any, ep, env] - return - end - - feature = aargs.lead_tys.first - if feature.is_a?(Type::Literal) - feature = feature.lit - - unless feature.is_a?(String) - return ctn[Type.any, ep, env] - end - - path = File.join(File.dirname(ep.ctx.iseq.absolute_path), feature) + ".rb" # XXX - - if scratch.loaded_files[path] - result = Type::Instance.new(Type::Builtin[:false]) - return ctn[result, ep, env] - end - scratch.loaded_files[path] = true - - return Builtin.file_load(path, ep, env, scratch, &ctn) if File.readable?(path) - - scratch.warn(ep, "failed to load: #{ path }") - else - scratch.warn(ep, "require target cannot be identified statically") - feature = nil - end - - result = Type::Instance.new(Type::Builtin[:true]) - ctn[result, ep, env] - end - - def kernel_autoload(recv, mid, aargs, ep, env, scratch, &ctn) - if aargs.lead_tys.size != 2 - # XXX: handle correctly - ctn[Type.any, ep, env] - return - end - - feature = aargs.lead_tys[1] - if feature.is_a?(Type::Literal) - feature = feature.lit - - action, arg = Builtin.file_require(feature, scratch) - case action - when :do - Builtin.file_load(arg, ep, env, scratch, &ctn) - when :done - when :error - scratch.warn(ep, arg) - end - ctn[Type.nil, ep, env] - else - scratch.warn(ep, "autoload target cannot be identified statically") - ctn[Type.nil, ep, env] - end - end - - def module_autoload(recv, mid, aargs, ep, env, scratch, &ctn) - kernel_autoload(recv, mid, aargs, ep, env, scratch, &ctn) - end - - def kernel_Array(recv, mid, aargs, ep, env, scratch, &ctn) - raise NotImplementedError if aargs.lead_tys.size != 1 - ty = aargs.lead_tys.first - ty = scratch.globalize_type(ty, env, ep) - all_ty = Type.bot - ty.each_child_global do |ty| - if ty.is_a?(Type::Array) - all_ty = all_ty.union(ty) - else - base_ty = Type::Instance.new(Type::Builtin[:ary]) - ret_ty = Type::Array.new(Type::Array::Elements.new([ty]), base_ty) - all_ty = all_ty.union(ret_ty) - end - end - ctn[all_ty, ep, env] - end - - def self.setup_initial_global_env(scratch) - klass_basic_obj = scratch.new_class(nil, :BasicObject, [], :__root__, nil) # cbase, name, superclass - klass_obj = scratch.new_class(nil, :Object, [], klass_basic_obj, nil) - scratch.add_constant(klass_obj, :Object, klass_obj, nil) - scratch.add_constant(klass_obj, :BasicObject, klass_basic_obj, nil) - - Type::Builtin[:basic_obj] = klass_basic_obj - Type::Builtin[:obj] = klass_obj - - Import.import_builtin(scratch) - - Type::Builtin[:vmcore] , = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil) - Type::Builtin[:int] , = scratch.get_constant(klass_obj, :Integer) - Type::Builtin[:float] , = scratch.get_constant(klass_obj, :Float) - Type::Builtin[:rational] , = scratch.get_constant(klass_obj, :Rational) - Type::Builtin[:complex] , = scratch.get_constant(klass_obj, :Complex) - Type::Builtin[:sym] , = scratch.get_constant(klass_obj, :Symbol) - Type::Builtin[:str] , = scratch.get_constant(klass_obj, :String) - Type::Builtin[:struct] , = scratch.get_constant(klass_obj, :Struct) - Type::Builtin[:ary] , = scratch.get_constant(klass_obj, :Array) - Type::Builtin[:hash] , = scratch.get_constant(klass_obj, :Hash) - Type::Builtin[:io] , = scratch.get_constant(klass_obj, :IO) - Type::Builtin[:proc] , = scratch.get_constant(klass_obj, :Proc) - Type::Builtin[:range] , = scratch.get_constant(klass_obj, :Range) - Type::Builtin[:regexp] , = scratch.get_constant(klass_obj, :Regexp) - Type::Builtin[:matchdata] , = scratch.get_constant(klass_obj, :MatchData) - Type::Builtin[:class] , = scratch.get_constant(klass_obj, :Class) - Type::Builtin[:module] , = scratch.get_constant(klass_obj, :Module) - Type::Builtin[:exc] , = scratch.get_constant(klass_obj, :Exception) - Type::Builtin[:encoding] , = scratch.get_constant(klass_obj, :Encoding) - Type::Builtin[:enumerator] , = scratch.get_constant(klass_obj, :Enumerator) - Type::Builtin[:kernel] , = scratch.get_constant(klass_obj, :Kernel) - - klass_vmcore = Type::Builtin[:vmcore] - klass_ary = Type::Builtin[:ary] - klass_hash = Type::Builtin[:hash] - klass_struct = Type::Builtin[:struct] - klass_proc = Type::Builtin[:proc] - klass_module = Type::Builtin[:module] - - scratch.set_custom_method(klass_vmcore, :"core#set_method_alias", Builtin.method(:vmcore_set_method_alias)) - scratch.set_custom_method(klass_vmcore, :"core#undef_method", Builtin.method(:vmcore_undef_method)) - scratch.set_custom_method(klass_vmcore, :"core#hash_merge_kwd", Builtin.method(:vmcore_hash_merge_kwd)) - scratch.set_custom_method(klass_vmcore, :"core#raise", Builtin.method(:vmcore_raise)) - - scratch.set_custom_method(klass_vmcore, :lambda, Builtin.method(:lambda)) - scratch.set_singleton_custom_method(klass_obj, :"new", Builtin.method(:object_s_new)) - scratch.set_custom_method(klass_obj, :p, Builtin.method(:kernel_p), false) - scratch.set_custom_method(klass_obj, :is_a?, Builtin.method(:object_is_a?)) - scratch.set_custom_method(klass_obj, :respond_to?, Builtin.method(:object_respond_to?)) - scratch.set_custom_method(klass_obj, :class, Builtin.method(:object_class)) - scratch.set_custom_method(klass_obj, :send, Builtin.method(:object_send)) - scratch.set_custom_method(klass_obj, :instance_eval, Builtin.method(:object_instance_eval)) - scratch.set_custom_method(klass_obj, :proc, Builtin.method(:lambda), false) - scratch.set_custom_method(klass_obj, :__method__, Builtin.method(:object_privitive_method), false) - scratch.set_custom_method(klass_obj, :block_given?, Builtin.method(:object_block_given?), false) - - scratch.set_custom_method(klass_obj, :enum_for, Builtin.method(:object_enum_for)) - scratch.set_custom_method(klass_obj, :to_enum, Builtin.method(:object_enum_for)) - - scratch.set_custom_method(klass_module, :include, Builtin.method(:module_include)) - scratch.set_custom_method(klass_module, :extend, Builtin.method(:module_extend)) - scratch.set_custom_method(klass_module, :prepend, Builtin.method(:module_prepend)) - scratch.set_custom_method(klass_module, :module_function, Builtin.method(:module_module_function), false) - scratch.set_custom_method(klass_module, :public, Builtin.method(:module_public), false) - scratch.set_custom_method(klass_module, :private, Builtin.method(:module_private), false) - scratch.set_custom_method(klass_module, :define_method, Builtin.method(:module_define_method)) - scratch.set_custom_method(klass_module, :attr_accessor, Builtin.method(:module_attr_accessor)) - scratch.set_custom_method(klass_module, :attr_reader, Builtin.method(:module_attr_reader)) - scratch.set_custom_method(klass_module, :attr_writer, Builtin.method(:module_attr_writer)) - scratch.set_custom_method(klass_module, :class_eval, Builtin.method(:object_module_eval)) - scratch.set_custom_method(klass_module, :module_eval, Builtin.method(:object_module_eval)) - scratch.set_custom_method(klass_module, :===, Builtin.method(:module_eqq)) - - scratch.set_custom_method(klass_proc, :[], Builtin.method(:proc_call)) - scratch.set_custom_method(klass_proc, :call, Builtin.method(:proc_call)) - - scratch.set_custom_method(klass_ary, :[], Builtin.method(:array_aref)) - scratch.set_custom_method(klass_ary, :[]=, Builtin.method(:array_aset)) - scratch.set_custom_method(klass_ary, :pop, Builtin.method(:array_pop)) - - scratch.set_custom_method(klass_hash, :[], Builtin.method(:hash_aref)) - scratch.set_custom_method(klass_hash, :[]=, Builtin.method(:hash_aset)) - - scratch.set_custom_method(klass_struct, :initialize, Builtin.method(:struct_initialize)) - scratch.set_singleton_custom_method(klass_struct, :new, Builtin.method(:struct_s_new)) - - scratch.set_custom_method(klass_obj, :require, Builtin.method(:kernel_require), false) - scratch.set_custom_method(klass_obj, :require_relative, Builtin.method(:kernel_require_relative), false) - scratch.set_custom_method(klass_obj, :Array, Builtin.method(:kernel_Array), false) - scratch.set_custom_method(klass_obj, :autoload, Builtin.method(:kernel_autoload), false) - scratch.set_custom_method(klass_module, :autoload, Builtin.method(:module_autoload)) - - # remove BasicObject#method_missing - scratch.set_method(klass_basic_obj, :method_missing, false, nil) - - # ENV: Hash[String, String] - str_ty = Type::Instance.new(Type::Builtin[:str]) - env_ty = Type.gen_hash {|h| h[str_ty] = Type.optional(str_ty) } - scratch.add_constant(klass_obj, :ENV, env_ty, nil) - - scratch.search_method(Type::Builtin[:kernel], false, :sprintf) do |mdefs,| - mdefs.each do |mdef| - scratch.add_method(klass_vmcore, :"core#sprintf", false, mdef) - end - end - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/cli.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/cli.rb deleted file mode 100644 index cdd3a7c401e9..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/cli.rb +++ /dev/null @@ -1,126 +0,0 @@ -require "optparse" - -module TypeProf - module CLI - module_function - - def parse(argv) - opt = OptionParser.new - - opt.banner = "Usage: #{ opt.program_name } [options] files..." - - output = nil - - # Verbose level: - # * 0: none - # * 1: default level - # * 2: debugging level - verbose = 1 - - options = {} - lsp_options = {} - dir_filter = nil - gem_rbs_features = [] - show_version = false - max_sec = max_iter = nil - collection_path = RBS::Collection::Config::PATH - - load_path_ext = [] - - opt.separator "" - opt.separator "Options:" - opt.on("-o OUTFILE", "Output to OUTFILE instead of stdout") {|v| output = v } - opt.on("-q", "--quiet", "Do not display progress indicator") { options[:show_indicator] = false } - opt.on("-v", "--verbose", "Alias to --show-errors") { options[:show_errors] = true } - opt.on("--version", "Display typeprof version") { show_version = true } - opt.on("-I DIR", "Add DIR to the load/require path") {|v| load_path_ext << v } - opt.on("-r FEATURE", "Require RBS of the FEATURE gem") {|v| gem_rbs_features << v } - opt.on("--collection PATH", "File path of collection configuration") { |v| collection_path = v } - opt.on("--no-collection", "Ignore collection configuration") { collection_path = nil } - opt.on("--lsp", "LSP mode") {|v| options[:lsp] = true } - - opt.separator "" - opt.separator "Analysis output options:" - opt.on("--include-dir DIR", "Include the analysis result of .rb file in DIR") do |dir| - # When `--include-dir` option is specified as the first directory option, - # typeprof will exclude any files by default unless a file path matches the explicit option - dir_filter ||= [[:exclude]] - dir_filter << [:include, File.expand_path(dir)] - end - opt.on("--exclude-dir DIR", "Exclude the analysis result of .rb file in DIR") do |dir| - # When `--exclude-dir` option is specified as the first directory option, - # typeprof will include any files by default, except Ruby's install directory and Gem directories - dir_filter ||= ConfigData::DEFAULT_DIR_FILTER - dir_filter << [:exclude, File.expand_path(dir)] - end - opt.on("--exclude-untyped", "Exclude (comment out) all entries including untyped") {|v| options[:exclude_untyped] = v } - opt.on("--[no-]show-typeprof-version", "Display TypeProf version in a header") {|v| options[:show_typeprof_version] = v } - opt.on("--[no-]show-errors", "Display possible errors found during the analysis") {|v| options[:show_errors] = v } - opt.on("--[no-]show-untyped", "Display \"Foo | untyped\" instead of \"Foo\"") {|v| options[:show_untyped] = v } - opt.on("--[no-]show-parameter-names", "Display parameter names for methods") {|v| options[:show_parameter_names] = v } - opt.on("--[no-]show-source-locations", "Display definition source locations for methods") {|v| options[:show_source_locations] = v } - - opt.separator "" - opt.separator "Analysis limit options:" - opt.on("--max-second SECOND", Float, "Limit the maxium time of analysis (in second)") {|v| max_sec = v } - opt.on("--max-iteration TIMES", Integer, "Limit the maxium instruction count of analysis") {|v| max_iter = v } - - opt.separator "" - opt.separator "Advanced options:" - opt.on("--[no-]stub-execution", "Force to call all unreachable methods with \"untyped\" arguments") {|v| options[:stub_execution] = v } - opt.on("--type-depth-limit DEPTH", Integer, "Limit the maximum depth of nested types") {|v| options[:type_depth_limit] = v } - opt.on("--union-width-limit WIDTH", Integer, "Limit the maximum count of class instances in one union type") {|v| options[:union_width_limit] = v } - opt.on("--debug", "Display analysis log (for debugging purpose)") { verbose = 2 } - opt.on("--[no-]stackprof MODE", /\Acpu|wall|object\z/, "Enable stackprof (for debugging purpose)") {|v| options[:stackprof] = v.to_sym } - - opt.separator "" - opt.separator "LSP options:" - opt.on("--port PORT", Integer, "Specify a port number to listen for requests on") {|v| lsp_options[:port] = v } - opt.on("--stdio", "Use stdio for LSP transport") {|v| lsp_options[:stdio] = v } - - opt.parse!(argv) - - $LOAD_PATH.unshift(*load_path_ext) - - dir_filter ||= ConfigData::DEFAULT_DIR_FILTER - rb_files = [] - rbs_files = [] - argv.each do |path| - if File.extname(path) == ".rbs" - rbs_files << path - else - rb_files << path - end - end - - puts "typeprof #{ VERSION }" if show_version - if rb_files.empty? && !options[:lsp] - exit if show_version - raise OptionParser::InvalidOption.new("no input files") - end - - if !options[:lsp] && !lsp_options.empty? - exit if show_version - raise OptionParser::InvalidOption.new("lsp options with non-lsp mode") - end - - ConfigData.new( - rb_files: rb_files, - rbs_files: rbs_files, - output: output, - gem_rbs_features: gem_rbs_features, - collection_path: collection_path, - verbose: verbose, - dir_filter: dir_filter, - max_sec: max_sec, - max_iter: max_iter, - options: options, - lsp_options: lsp_options, - ) - - rescue OptionParser::InvalidOption - puts $! - exit - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/code-range.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/code-range.rb deleted file mode 100644 index d97627ed3296..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/code-range.rb +++ /dev/null @@ -1,177 +0,0 @@ -module TypeProf - class CodeLocation - # In Ruby, lineno is 1-origin, and column is 0-origin - def initialize(lineno, column) - @lineno = lineno - @column = column - end - - def inspect - "(%d,%d)" % [@lineno, @column] - end - - attr_reader :lineno, :column - - def self.from_lsp(lsp_loc) - # In the Language Server Protocol, lineno and column are both 0-origin - CodeLocation.new(lsp_loc[:line] + 1, lsp_loc[:character]) - end - - def to_lsp - { line: @lineno - 1, character: @column } - end - - def advance_cursor(offset, source_text) - new_lineno = @lineno - new_column = @column - while offset > 0 - line_text = source_text.lines[new_lineno - 1] - if new_column + offset >= line_text.length - advanced = line_text.length - new_column - offset -= advanced - new_lineno += 1 - new_column = 0 - else - new_column += offset - break - end - end - CodeLocation.new(new_lineno, new_column) - end - - def <=>(other) - ret = @lineno <=> other.lineno - return ret if ret != 0 - @column <=> other.column - end - - include Comparable - end - - class CodeRange - def initialize(first, last) - @first, @last = first, last - end - - def inspect - "%p-%p" % [@first, @last] - end - - attr_reader :first - attr_reader :last - - def self.from_lsp(lsp_range) - CodeRange.new(CodeLocation.from_lsp(lsp[:start]), CodeLocation.from_lsp(lsp[:end])) - end - - def self.from_rbs(rbs_loc) - CodeRange.new( - CodeLocation.new(rbs_loc.start_line, rbs_loc.start_column), - CodeLocation.new(rbs_loc.end_line, rbs_loc.end_column), - ) - end - - def to_lsp - { start: @first.to_lsp, end: @last.to_lsp } - end - - def contain_loc?(loc) - @first <= loc && loc < @last - end - - def contain?(other) - @first <= other.first && other.last <= @last - end - - def overlap?(other) - if @first <= other.first - return @last > other.first - else - return @first < other.last - end - end - end - - class CodeRangeTable - Entry = Struct.new(:range, :value, :children) - - class Entry - def inspect - "[%p, %p, %p]" % [range, value, children] - end - end - - def initialize(list = []) - @list = list # Array[Entry] - end - - def []=(range, value) - i_b = @list.bsearch_index {|e| e.range.last > range.first } || @list.size - i_e = @list.bsearch_index {|e| e.range.first >= range.last } || @list.size - if i_b < i_e - # for all i in i_b...i_e, @list[i] overlaps with the range - if i_e - i_b == 1 - if range.contain?(@list[i_b].range) - @list[i_b] = Entry[range, value, CodeRangeTable.new(@list[i_b, 1])] - elsif @list[i_b].range.contain?(range) - @list[i_b].children[range] = value - else - raise - end - else - if range.contain?(@list[i_b].range) && range.contain?(@list[i_e - 1].range) - @list[i_b...i_e] = [Entry[range, value, CodeRangeTable.new(@list[i_b...i_e])]] - else - raise - end - end - else - @list[i_b, 0] = [Entry[range, value, CodeRangeTable.new]] - end - end - - def [](loc) - e = @list.bsearch {|e| e.range.last > loc } - if e && e.range.contain_loc?(loc) - return e.children[loc] || e.value - end - return nil - end - end -end - -if $0 == __FILE__ - include TypeProf - cr1 = CodeRange.new(CodeLocation.new(1, 0), CodeLocation.new(1, 2)) - cr2 = CodeRange.new(CodeLocation.new(1, 2), CodeLocation.new(1, 4)) - cr3 = CodeRange.new(CodeLocation.new(2, 0), CodeLocation.new(2, 2)) - cr4 = CodeRange.new(CodeLocation.new(2, 3), CodeLocation.new(2, 5)) - cr1and2 = CodeRange.new(CodeLocation.new(1, 0), CodeLocation.new(1, 5)) - cr3and4 = CodeRange.new(CodeLocation.new(2, 0), CodeLocation.new(2, 5)) - [[cr1, "A"], [cr2, "B"], [cr3, "C"], [cr4, "D"], [cr1and2, "AB"], [cr3and4, "CD"]].permutation do |ary| - tbl = CodeRangeTable.new - ary.each do |cr, v| - tbl[cr] = v - end - values = [] - [1, 2].each do |lineno| - (0..5).each do |column| - values << tbl[CodeLocation.new(lineno, column)] - end - end - raise if values != ["A", "A", "B", "B", "AB", nil, "C", "C", "CD", "D", "D", nil] - end - - source = <<~EOS - AB - CDE - F - EOS - a_loc = CodeLocation.new(1, 0) - b_loc = a_loc.advance_cursor(1, source) - raise unless b_loc.inspect == "(1,1)" - c_loc = a_loc.advance_cursor(3, source) - raise unless c_loc.inspect == "(2,0)" - f_loc = c_loc.advance_cursor(4, source) - raise unless f_loc.inspect == "(3,0)" -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/config.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/config.rb deleted file mode 100644 index f6c323f08bab..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/config.rb +++ /dev/null @@ -1,158 +0,0 @@ -require "rbconfig" - -module TypeProf - ConfigData = Struct.new( - :rb_files, - :rbs_files, - :output, - :gem_rbs_features, - :collection_path, - :verbose, - :dir_filter, - :max_iter, - :max_sec, - :options, - :lsp_options, - :lsp, - keyword_init: true - ) - - class TypeProfError < StandardError - def report(output) - output.puts "# Analysis Error" - output.puts message - end - end - - class ConfigData - def initialize(**opt) - opt[:output] ||= $stdout - opt[:gem_rbs_features] ||= [] - opt[:dir_filter] ||= DEFAULT_DIR_FILTER - opt[:verbose] ||= 0 - opt[:options] ||= {} - opt[:options] = { - exclude_untyped: false, - show_typeprof_version: true, - show_indicator: true, - show_untyped: false, - show_errors: false, - show_parameter_names: true, - show_source_locations: false, - stub_execution: true, - type_depth_limit: 5, - union_width_limit: 10, - stackprof: nil, - }.merge(opt[:options]) - opt[:lsp_options] = { - port: 0, - stdio: false, - }.merge(opt[:lsp_options] || {}) - super(**opt) - end - - def check_dir_filter(path) - dir_filter.reverse_each do |cond, dir| - return cond unless dir - return cond if path.start_with?(dir) - end - end - - DEFAULT_DIR_FILTER = [ - [:include], - [:exclude, RbConfig::CONFIG["prefix"]], - [:exclude, Gem.dir], - [:exclude, Gem.user_dir], - ] - end - - module Config - def self.current - Thread.current[:typeprof_config] - end - - def self.set_current(config) - Thread.current[:typeprof_config] = config - end - end - - def self.analyze(config, cancel_token = nil) - # Deploy the config to the TypeProf::Config (Note: This is thread local) - Config.set_current(config) - - if Config.current.options[:stackprof] - require "stackprof" - out = "typeprof-stackprof-#{ Config.current.options[:stackprof] }.dump" - StackProf.start(mode: Config.current.options[:stackprof], out: out, raw: true) - end - - scratch = Scratch.new - Builtin.setup_initial_global_env(scratch) - - Config.current.gem_rbs_features.each do |feature| - Import.import_library(scratch, feature) - end - - rbs_files = [] - rbs_codes = [] - Config.current.rbs_files.each do |rbs| - if rbs.is_a?(Array) # [String name, String content] - rbs_codes << rbs - else - rbs_files << rbs - end - end - Import.import_rbs_files(scratch, rbs_files) - rbs_codes.each do |name, content| - Import.import_rbs_code(scratch, name, content) - end - - def_code_range_table = nil - caller_code_range_table = nil - Config.current.rb_files.each do |rb| - if rb.is_a?(Array) # [String name, String content] - iseq, def_tbl, caller_tbl = ISeq.compile_str(*rb.reverse) - def_code_range_table ||= def_tbl - caller_code_range_table ||= caller_tbl - else - iseq = rb - end - scratch.add_entrypoint(iseq) - end - - result = scratch.type_profile(cancel_token) - - if Config.current.options[:lsp] - return scratch.report_lsp, def_code_range_table, caller_code_range_table - end - - if Config.current.output.respond_to?(:write) - scratch.report(result, Config.current.output) - else - open(Config.current.output, "w") do |output| - scratch.report(result, output) - end - end - - rescue TypeProfError => exc - exc.report(Config.current.output) - - return nil - ensure - if Config.current.options[:stackprof] && defined?(StackProf) - StackProf.stop - StackProf.results - end - end - - def self.starting_state(iseq) - cref = CRef.new(:bottom, Type::Builtin[:obj], false) # object - recv = Type::Instance.new(Type::Builtin[:obj]) - ctx = Context.new(iseq, cref, nil) - ep = ExecutionPoint.new(ctx, 0, nil) - locals = [Type.nil] * iseq.locals.size - env = Env.new(StaticEnv.new(recv, Type.nil, false, false), locals, [], Utils::HashWrapper.new({})) - - return ep, env - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/container-type.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/container-type.rb deleted file mode 100644 index 5cf50c41b7f7..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/container-type.rb +++ /dev/null @@ -1,912 +0,0 @@ -module TypeProf - class AllocationSite - include Utils::StructuralEquality - - def initialize(val, parent = nil) - raise if !val.is_a?(Utils::StructuralEquality) && !val.is_a?(Integer) && !val.is_a?(Symbol) - @val = val - @parent = parent - end - - attr_reader :val, :parent - - def add_id(val) - AllocationSite.new(val, self) - end - end - - class Type # or AbstractValue - # Cell, Array, and Hash are types for global interface, e.g., TypedISeq. - # Do not push such types to local environment, stack, etc. - - class ContainerType < Type - def match?(other) - return nil if self.class != other.class - return nil unless @base_type.consistent?(other.base_type) - @elems.match?(other.elems) - end - - def each_free_type_variable(&blk) - @elems.each_free_type_variable(&blk) - end - - def consistent?(other) - raise "must not be used" - end - - def self.create_empty_instance(klass) - base_type = Type::Instance.new(klass) - case klass - when Type::Builtin[:ary] # XXX: check inheritance... - Type::Array.new(Type::Array::Elements.new([], Type.bot), base_type) - when Type::Builtin[:hash] - Type.gen_hash(base_type) {|h| } - else - Type::Cell.new(Type::Cell::Elements.new([Type.bot] * klass.type_params.size), base_type) - end - end - - def include_untyped?(scratch) - return true if @base_type.include_untyped?(scratch) - return true if @elems.include_untyped?(scratch) - false - end - end - - # The most basic container type for default type parameter class - class Cell < ContainerType - def initialize(elems, base_type) - raise if !elems.is_a?(Cell::Elements) - @elems = elems # Cell::Elements - raise unless base_type - @base_type = base_type - if base_type.klass.type_params.size != elems.elems.size - raise - end - end - - attr_reader :elems, :base_type - - def inspect - "Type::Cell[#{ @elems.inspect }, base_type: #{ @base_type.inspect }]" - end - - def screen_name(scratch) - str = @elems.screen_name(scratch) - if str.start_with?("*") - str = @base_type.screen_name(scratch) + str[1..] - end - str - end - - def localize(env, alloc_site, depth) - return env, Type.any if depth <= 0 - alloc_site = alloc_site.add_id(:cell).add_id(@base_type) - env, elems = @elems.localize(env, alloc_site, depth) - ty = Local.new(Cell, alloc_site, @base_type) - env = env.deploy_type(alloc_site, elems) - return env, ty - end - - def limit_size(limit) - return Type.any if limit <= 0 - Cell.new(@elems.limit_size(limit - 1), @base_type) - end - - def method_dispatch_info - raise - end - - def substitute(subst, depth) - return Type.any if depth <= 0 - elems = @elems.substitute(subst, depth) - Cell.new(elems, @base_type) - end - - def generate_substitution - subst = {} - tyvars = @base_type.klass.type_params.map {|name,| Type::Var.new(name) } - tyvars.zip(@elems.elems) do |tyvar, elem| - if subst[tyvar] - subst[tyvar] = subst[tyvar].union(elem) - else - subst[tyvar] = elem - end - end - subst - end - - class Elements # Cell - include Utils::StructuralEquality - - def initialize(elems) - @elems = elems - end - - def self.dummy_elements - Elements.new([]) # XXX - end - - attr_reader :elems - - def to_local_type(id, base_ty) - Type::Local.new(Cell, id, base_ty) - end - - def globalize(env, visited, depth) - Elements.new(@elems.map {|ty| ty.globalize(env, visited, depth) }) - end - - def localize(env, alloc_site, depth) - elems = @elems.map.with_index do |ty, i| - alloc_site2 = alloc_site.add_id(i) - env, ty = ty.localize(env, alloc_site2, depth) - ty - end - return env, Elements.new(elems) - end - - def limit_size(limit) - Elements.new(@elems.map {|ty| ty.limit_size(limit) }) - end - - def screen_name(scratch) - "*[#{ @elems.map {|ty| ty.screen_name(scratch) }.join(", ") }]" - end - - def pretty_print(q) - q.group(9, "Elements[", "]") do - q.seplist(@elems) do |elem| - q.pp elem - end - end - end - - def match?(other) - return nil if @elems.size != other.elems.size - subst = nil - @elems.zip(other.elems) do |ty0, ty1| - subst2 = Type.match?(ty0, ty1) - return nil unless subst2 - subst = Type.merge_substitution(subst, subst2) - end - subst - end - - def each_free_type_variable(&blk) - @elems.each do |ty| - ty.each_free_type_variable(&blk) - end - end - - def substitute(subst, depth) - Elements.new(@elems.map {|ty| ty.substitute(subst, depth) }) - end - - def [](idx) - @elems[idx] - end - - def update(idx, ty) - Elements.new(Utils.array_update(@elems, idx, @elems[idx].union(ty))) - end - - def union(other) - return self if self == other - if @elems.size != other.elems.size - raise "#{ @elems.size } != #{ other.elems.size }" - end - elems = [] - @elems.zip(other.elems) do |ty0, ty1| - elems << ty0.union(ty1) - end - Elements.new(elems) - end - - def include_untyped?(scratch) - return @elems.any? {|ty| ty.include_untyped?(scratch) } - end - end - end - - # Do not insert Array type to local environment, stack, etc. - class Array < ContainerType - def initialize(elems, base_type) - raise unless elems.is_a?(Array::Elements) - @elems = elems # Array::Elements - raise unless base_type - @base_type = base_type - end - - attr_reader :elems, :base_type - - def inspect - "Type::Array[#{ @elems.inspect }, base_type: #{ @base_type.inspect }]" - #@base_type.inspect - end - - def screen_name(scratch) - str = @elems.screen_name(scratch) - if str =~ /\A\*\[(.*)\]\z/ - str = @base_type.klass.type_params.map {|var_name,| var_name == :Elem ? $1 : "untyped" }.join(", ") - str = "#{ @base_type.screen_name(scratch) }[#{ str }]" - end - str - end - - def localize(env, alloc_site, depth) - return env, Type.any if depth <= 0 - alloc_site = alloc_site.add_id(:ary).add_id(@base_type) - env, elems = @elems.localize(env, alloc_site, depth - 1) - ty = Local.new(Array, alloc_site, @base_type) - env = env.deploy_type(alloc_site, elems) - return env, ty - end - - def limit_size(limit) - return Type.any if limit <= 0 - Array.new(@elems.limit_size(limit - 1), @base_type) - end - - def method_dispatch_info - raise - end - - def substitute(subst, depth) - return Type.any if depth <= 0 - elems = @elems.substitute(subst, depth - 1) - Array.new(elems, @base_type) - end - - def generate_substitution - { Type::Var.new(:Elem) => @elems.squash } - end - - class Elements # Array - include Utils::StructuralEquality - - def initialize(lead_tys, rest_ty = Type.bot) - raise unless lead_tys.all? {|ty| ty.is_a?(Type) } - raise unless rest_ty.is_a?(Type) - @lead_tys, @rest_ty = lead_tys, rest_ty - end - - def self.dummy_elements - Elements.new([], Type.any) - end - - attr_reader :lead_tys, :rest_ty - - def to_local_type(id, base_ty) - Type::Local.new(Array, id, base_ty) - end - - def globalize(env, visited, depth) - lead_tys = [] - @lead_tys.each do |ty| - lead_tys << ty.globalize(env, visited, depth) - end - rest_ty = @rest_ty&.globalize(env, visited, depth) - Elements.new(lead_tys, rest_ty) - end - - def localize(env, alloc_site, depth) - lead_tys = @lead_tys.map.with_index do |ty, i| - alloc_site2 = alloc_site.add_id(i) - env, ty = ty.localize(env, alloc_site2, depth) - ty - end - alloc_site_rest = alloc_site.add_id(:rest) - env, rest_ty = @rest_ty.localize(env, alloc_site_rest, depth) - return env, Elements.new(lead_tys, rest_ty) - end - - def limit_size(limit) - Elements.new(@lead_tys.map {|ty| ty.limit_size(limit) }, @rest_ty.limit_size(limit)) - end - - def screen_name(scratch) - if @rest_ty == Type.bot - if @lead_tys.empty? - # This is heuristic: in general, an empty array is a wrong guess. - # Note that an empty array is representable as "[ ]" in RBS, but - # users often have to modify it to "Array[something]". - # In this term, "Array[untyped]" is considered more useful than "[ ]". - return "Array[untyped]" - end - s = @lead_tys.map do |ty| - ty.screen_name(scratch) - end - s << "*" + @rest_ty.screen_name(scratch) if @rest_ty != Type.bot - return "[#{ s.join(", ") }]" - end - - "*[#{ squash.screen_name(scratch) }]" - rescue SystemStackError - p squash - exit! - end - - def pretty_print(q) - q.group(9, "Elements[", "]") do - q.seplist(@lead_tys + [@rest_ty]) do |elem| - q.pp elem - end - end - end - - def match?(other) - n = [@lead_tys.size, other.lead_tys.size].min - rest_ty1 = @lead_tys[n..].inject(@rest_ty) {|ty1, ty2| ty1.union(ty2) } - rest_ty2 = other.lead_tys[n..].inject(other.rest_ty) {|ty1, ty2| ty1.union(ty2) } - subst = nil - (@lead_tys[0, n] + [rest_ty1]).zip(other.lead_tys[0, n] + [rest_ty2]) do |ty0, ty1| - subst2 = Type.match?(ty0, ty1) - return nil unless subst2 - subst = Type.merge_substitution(subst, subst2) - end - subst - end - - def each_free_type_variable(&blk) - @lead_tys.each do |ty| - ty.each_free_type_variable(&blk) - end - @rest_ty&.each_free_type_variable(&blk) - end - - def substitute(subst, depth) - lead_tys = @lead_tys.map {|ty| ty.substitute(subst, depth) } - rest_ty = @rest_ty.substitute(subst, depth) - Elements.new(lead_tys, rest_ty) - end - - def squash - @lead_tys.inject(@rest_ty) {|ty1, ty2| ty1.union(ty2) } #.union(Type.nil) # is this needed? - end - - def squash_or_any - ty = squash - ty == Type.bot ? Type.any : ty - end - - def [](idx) - if idx.is_a?(Range) - if @rest_ty == Type.bot - lead_tys = @lead_tys[idx] - if lead_tys - rest_ty = Type.bot - else - return Type.nil - end - else - b, e = idx.begin, idx.end - b = 0 if !b - if !e - lead_tys = @lead_tys[idx] || [] - rest_ty = @rest_ty - elsif b >= 0 - if e >= 0 - if b <= e - if e < @lead_tys.size - lead_tys = @lead_tys[idx] - rest_ty = Type.bot - else - lead_tys = @lead_tys[idx] || [] - rest_ty = @rest_ty - end - else - return Type.nil - end - else - lead_tys = @lead_tys[idx] || [] - e = idx.exclude_end? ? e : e == -1 ? @lead_tys.size : e + 1 - rest_ty = (@lead_tys[e + 1..] || []).inject(@rest_ty) {|ty0, ty1| ty0.union(ty1) } - end - else - lead_tys = [] - if e >= 0 - rest_ty = e < @lead_tys.size ? Type.bot : @rest_ty - range = [0, @lead_tys.size + b].max .. (idx.exclude_end? ? e - 1 : e) - rest_ty = @lead_tys[range].inject(rest_ty) {|ty0, ty1| ty0.union(ty1) } - else - if b <= e - range = [0, @lead_tys.size + b].max .. (idx.exclude_end? ? e - 1 : e) - rest_ty = @lead_tys[range].inject(@rest_ty) {|ty0, ty1| ty0.union(ty1) } - else - return Type.nil - end - end - end - end - base_ty = Type::Instance.new(Type::Builtin[:ary]) - Array.new(Elements.new(lead_tys, rest_ty), base_ty) - elsif idx >= 0 - if idx < @lead_tys.size - @lead_tys[idx] - elsif @rest_ty == Type.bot - Type.nil - else - @rest_ty - end - else - i = @lead_tys.size + idx - i = [i, 0].max - ty = @rest_ty - @lead_tys[i..].each do |ty2| - ty = ty.union(ty2) - end - ty - end - end - - def update(idx, ty) - if idx - if idx >= 0 - if idx < @lead_tys.size - lead_tys = Utils.array_update(@lead_tys, idx, ty) - Elements.new(lead_tys, @rest_ty) - else - rest_ty = @rest_ty.union(ty) - Elements.new(@lead_tys, rest_ty) - end - else - i = @lead_tys.size + idx - if @rest_ty == Type.bot - if i >= 0 - lead_tys = Utils.array_update(@lead_tys, i, ty) - Elements.new(lead_tys, Type.bot) - else - # TODO: out of bound? should we emit an error? - Elements.new(@lead_tys, Type.bot) - end - else - i = [i, 0].max - lead_tys = @lead_tys[0, i] + @lead_tys[i..].map {|ty2| ty2.union(ty) } - rest_ty = @rest_ty.union(ty) - Elements.new(@lead_tys, rest_ty) - end - end - else - lead_tys = @lead_tys.map {|ty1| ty1.union(ty) } - rest_ty = @rest_ty.union(ty) - Elements.new(lead_tys, rest_ty) - end - end - - def append(ty) - if @rest_ty == Type.bot - if @lead_tys.size < 5 # XXX: should be configurable, or ...? - lead_tys = @lead_tys + [ty] - Elements.new(lead_tys, @rest_ty) - else - Elements.new(@lead_tys, ty) - end - else - Elements.new(@lead_tys, @rest_ty.union(ty)) - end - end - - def union(other) - return self if self == other - raise "Hash::Elements merge Array::Elements" if other.is_a?(Hash::Elements) - - lead_count = [@lead_tys.size, other.lead_tys.size].min - lead_tys = (0...lead_count).map do |i| - @lead_tys[i].union(other.lead_tys[i]) - end - - rest_ty = @rest_ty.union(other.rest_ty) - (@lead_tys[lead_count..-1] + other.lead_tys[lead_count..-1]).each do |ty| - rest_ty = rest_ty.union(ty) - end - - Elements.new(lead_tys, rest_ty) - end - - def take_first(num) - base_ty = Type::Instance.new(Type::Builtin[:ary]) - if @lead_tys.size >= num - lead_tys = @lead_tys[0, num] - rest_ary_ty = Array.new(Elements.new(@lead_tys[num..-1], @rest_ty), base_ty) - return lead_tys, rest_ary_ty - else - lead_tys = @lead_tys.dup - until lead_tys.size == num - # .union(Type.nil) is needed for `a, b, c = [42]` to assign nil to b and c - lead_tys << @rest_ty.union(Type.nil) - end - rest_ary_ty = Array.new(Elements.new([], @rest_ty), base_ty) - return lead_tys, rest_ary_ty - end - end - - def take_last(num) - base_ty = Type::Instance.new(Type::Builtin[:ary]) - if @rest_ty == Type.bot - if @lead_tys.size >= num - following_tys = @lead_tys[-num, num] - rest_ary_ty = Array.new(Elements.new(@lead_tys[0...-num], Type.bot), base_ty) - return rest_ary_ty, following_tys - else - following_tys = @lead_tys[-num, num] || [] - until following_tys.size == num - following_tys.unshift(Type.nil) - end - rest_ary_ty = Array.new(Elements.new([], Type.bot), base_ty) - return rest_ary_ty, following_tys - end - else - lead_tys = @lead_tys.dup - last_ty = rest_ty - following_tys = [] - until following_tys.size == num - last_ty = last_ty.union(lead_tys.pop) unless lead_tys.empty? - following_tys.unshift(last_ty) - end - rest_ty = lead_tys.inject(last_ty) {|ty1, ty2| ty1.union(ty2) } - rest_ary_ty = Array.new(Elements.new([], rest_ty), base_ty) - return rest_ary_ty, following_tys - end - end - - def include_untyped?(scratch) - return true if @lead_tys.any? {|ty| ty.include_untyped?(scratch) } - return true if @rest_ty.include_untyped?(scratch) - false - end - end - end - - class Hash < ContainerType - def initialize(elems, base_type) - @elems = elems - raise unless elems - @base_type = base_type - end - - attr_reader :elems, :base_type - - def inspect - "Type::Hash#{ @elems.inspect }" - end - - def screen_name(scratch) - @elems.screen_name(scratch) - end - - def localize(env, alloc_site, depth) - return env, Type.any if depth <= 0 - alloc_site = alloc_site.add_id(:hash).add_id(@base_type) - env, elems = @elems.localize(env, alloc_site, depth - 1) - ty = Local.new(Hash, alloc_site, @base_type) - env = env.deploy_type(alloc_site, elems) - return env, ty - end - - def limit_size(limit) - return Type.any if limit <= 0 - Hash.new(@elems.limit_size(limit - 1), @base_type) - end - - def method_dispatch_info - raise - end - - def substitute(subst, depth) - return Type.any if depth <= 0 - elems = @elems.substitute(subst, depth - 1) - Hash.new(elems, @base_type) - end - - def generate_substitution - tyvar_k = Type::Var.new(:K) - tyvar_v = Type::Var.new(:V) - k_ty0, v_ty0 = @elems.squash - # XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type? - { tyvar_k => k_ty0, tyvar_v => v_ty0 } - end - - class Elements # Hash - include Utils::StructuralEquality - - def initialize(map_tys) - map_tys.each do |k_ty, v_ty| - raise unless k_ty.is_a?(Type) - raise unless v_ty.is_a?(Type) - raise if k_ty.is_a?(Type::Union) - raise if k_ty.is_a?(Type::Local) - raise if k_ty.is_a?(Type::Array) - raise if k_ty.is_a?(Type::Hash) - end - @map_tys = map_tys - end - - def self.dummy_elements - Elements.new({Type.any => Type.any}) - end - - attr_reader :map_tys - - def to_local_type(id, base_ty) - Type::Local.new(Hash, id, base_ty) - end - - def globalize(env, visited, depth) - map_tys = {} - @map_tys.each do |k_ty, v_ty| - v_ty = v_ty.globalize(env, visited, depth) - if map_tys[k_ty] - map_tys[k_ty] = map_tys[k_ty].union(v_ty) - else - map_tys[k_ty] = v_ty - end - end - Elements.new(map_tys) - end - - def localize(env, alloc_site, depth) - map_tys = @map_tys.to_h do |k_ty, v_ty| - alloc_site2 = alloc_site.add_id(k_ty) - env, v_ty = v_ty.localize(env, alloc_site2, depth) - [k_ty, v_ty] - end - return env, Elements.new(map_tys) - end - - def limit_size(limit) - map_tys = {} - @map_tys.each do |k_ty, v_ty| - k_ty = k_ty.limit_size(limit) - v_ty = v_ty.limit_size(limit) - if map_tys[k_ty] - map_tys[k_ty] = map_tys[k_ty].union(v_ty) - else - map_tys[k_ty] = v_ty - end - end - Elements.new(map_tys) - end - - def screen_name(scratch) - if !@map_tys.empty? && @map_tys.all? {|k_ty,| k_ty.is_a?(Type::Symbol) } - s = @map_tys.map do |k_ty, v_ty| - v = v_ty.screen_name(scratch) - "#{ k_ty.sym }: #{ v }" - end.join(", ") - "{#{ s }}" - else - k_ty = v_ty = Type.bot - @map_tys.each do |k, v| - k_ty = k_ty.union(k) - v_ty = v_ty.union(v) - end - k_ty = Type.any if k_ty == Type.bot - v_ty = Type.any if v_ty == Type.bot - k_ty = k_ty.screen_name(scratch) - v_ty = v_ty.screen_name(scratch) - "Hash[#{ k_ty }, #{ v_ty }]" - end - end - - def pretty_print(q) - q.group(9, "Elements[", "]") do - q.seplist(@map_tys) do |k_ty, v_ty| - q.group do - q.pp k_ty - q.text '=>' - q.group(1) do - q.breakable '' - q.pp v_ty - end - end - end - end - end - - def match?(other) - subst = nil - other.map_tys.each do |k1, v1| - subst2 = nil - @map_tys.each do |k0, v0| - subst3 = Type.match?(k0, k1) - if subst3 - subst4 = Type.match?(v0, v1) - if subst4 - subst2 = Type.merge_substitution(subst2, subst3) - subst2 = Type.merge_substitution(subst2, subst4) - end - end - end - return nil unless subst2 - subst = Type.merge_substitution(subst, subst2) - end - subst - end - - def each_free_type_variable(&blk) - @map_tys.each do |k, v| - k.each_free_type_variable(&blk) - v.each_free_type_variable(&blk) - end - end - - def substitute(subst, depth) - map_tys = {} - @map_tys.each do |k_ty_orig, v_ty_orig| - k_ty = k_ty_orig.substitute(subst, depth) - v_ty = v_ty_orig.substitute(subst, depth) - k_ty.each_child_global do |k_ty| - # This is a temporal hack to mitigate type explosion - k_ty = Type.any if k_ty.is_a?(Type::Array) - k_ty = Type.any if k_ty.is_a?(Type::Hash) - if map_tys[k_ty] - map_tys[k_ty] = map_tys[k_ty].union(v_ty) - else - map_tys[k_ty] = v_ty - end - end - end - Elements.new(map_tys) - end - - def squash - all_k_ty, all_v_ty = Type.bot, Type.bot - @map_tys.each do |k_ty, v_ty| - all_k_ty = all_k_ty.union(k_ty) - all_v_ty = all_v_ty.union(v_ty) - end - return all_k_ty, all_v_ty - end - - def [](key_ty) - val_ty = Type.bot - @map_tys.each do |k_ty, v_ty| - if Type.match?(k_ty, key_ty) - val_ty = val_ty.union(v_ty) - end - end - val_ty - end - - def update(idx, ty) - map_tys = @map_tys.dup - idx.each_child_global do |idx| - # This is a temporal hack to mitigate type explosion - idx = Type.any if idx.is_a?(Type::Array) - idx = Type.any if idx.is_a?(Type::Hash) - - if map_tys[idx] - map_tys[idx] = map_tys[idx].union(ty) - else - map_tys[idx] = ty - end - end - Elements.new(map_tys) - end - - def union(other) - return self if self == other - raise "Array::Elements merge Hash::Elements" if other.is_a?(Array::Elements) - - map_tys = @map_tys.dup - other.map_tys.each do |k_ty, v_ty| - if map_tys[k_ty] - map_tys[k_ty] = map_tys[k_ty].union(v_ty) - else - map_tys[k_ty] = v_ty - end - end - - Elements.new(map_tys) - end - - def to_keywords - kw_tys = {} - @map_tys.each do |key_ty, val_ty| - if key_ty.is_a?(Type::Symbol) - kw_tys[key_ty.sym] = val_ty - else - all_val_ty = Type.bot - @map_tys.each do |_key_ty, val_ty| - all_val_ty = all_val_ty.union(val_ty) - end - return { nil => all_val_ty } - end - end - kw_tys - end - - def include_untyped?(scratch) - @map_tys.each do |key, val| - return true if key.include_untyped?(scratch) - return true if val.include_untyped?(scratch) - end - false - end - end - end - - class Local < ContainerType - def initialize(kind, id, base_type) - @kind = kind - raise if @kind != Cell && @kind != Array && @kind != Hash - @id = id - raise unless base_type - @base_type = base_type - end - - attr_reader :kind, :id, :base_type - - def inspect - "Type::Local[#{ @kind }, #{ @id }, base_type: #{ @base_type.inspect }]" - end - - def screen_name(scratch) - #raise "Local type must not be included in signature" - "Local[#{ @kind }]" - end - - def globalize(env, visited, depth) - if visited[self] || depth <= 0 - Type.any - else - visited[self] = true - elems = env.get_container_elem_types(@id) - if elems - elems = elems.globalize(env, visited, depth - 1) - else - # TODO: currently out-of-scope array cannot be accessed - elems = @kind::Elements.dummy_elements - end - visited.delete(self) - @kind.new(elems, @base_type) - end - end - - def method_dispatch_info - @base_type.method_dispatch_info - end - - def update_container_elem_type(subst, env, caller_ep, scratch) - case - when @kind == Cell - tyvars = @base_type.klass.type_params.map {|name,| Type::Var.new(name) } - # XXX: This should be skipped when the called methods belongs to superclass - tyvars.each_with_index do |tyvar, idx| - ty = subst[tyvar] - if ty - env, ty = scratch.localize_type(ty, env, caller_ep) - env = scratch.update_container_elem_types(env, caller_ep, @id, @base_type) do |elems| - elems.update(idx, ty) - end - end - end - when @kind == Array - tyvar_elem = Type::Var.new(:Elem) - if subst[tyvar_elem] - ty = subst[tyvar_elem] - env, ty = scratch.localize_type(ty, env, caller_ep) - env = scratch.update_container_elem_types(env, caller_ep, @id, @base_type) do |elems| - elems.update(nil, ty) - end - end - when @kind == Hash - tyvar_k = Type::Var.new(:K) - tyvar_v = Type::Var.new(:V) - if subst[tyvar_k] && subst[tyvar_v] - k_ty = subst[tyvar_k] - v_ty = subst[tyvar_v] - alloc_site = AllocationSite.new(caller_ep) - env, k_ty = scratch.localize_type(k_ty, env, caller_ep, alloc_site.add_id(:k)) - env, v_ty = scratch.localize_type(v_ty, env, caller_ep, alloc_site.add_id(:v)) - env = scratch.update_container_elem_types(env, caller_ep, @id, @base_type) do |elems| - elems.update(k_ty, v_ty) - end - end - end - env - end - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/export.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/export.rb deleted file mode 100644 index d9e5d5fce3d9..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/export.rb +++ /dev/null @@ -1,589 +0,0 @@ -module TypeProf - module Reporters - module_function - - def generate_analysis_trace(state, visited, backward_edge) - return nil if visited[state] - visited[state] = true - prev_states = backward_edges[state] - if prev_states - prev_states.each_key do |pstate| - trace = generate_analysis_trace(pstate, visited, backward_edge) - return [state] + trace if trace - end - nil - else - [] - end - end - - def filter_backtrace(trace) - ntrace = [trace.first] - trace.each_cons(2) do |ep1, ep2| - ntrace << ep2 if ep1.ctx != ep2.ctx - end - ntrace - end - - def show_message(terminated, output) - if Config.current.options[:show_typeprof_version] - output.puts "# TypeProf #{ VERSION }" - output.puts - end - if terminated - output.puts "# CAUTION: Type profiling was terminated prematurely because of the limitation" - output.puts - end - end - - def show_error(errors, backward_edge, output) - return if errors.empty? - return unless Config.current.options[:show_errors] - - output.puts "# Errors" - errors.each do |ep, msg| - if ENV["TP_DETAIL"] - backtrace = filter_backtrace(generate_analysis_trace(ep, {}, backward_edge)) - else - backtrace = [ep] - end - loc, *backtrace = backtrace.map do |ep| - ep&.source_location - end - output.puts "#{ loc }: #{ msg }" - backtrace.each do |loc| - output.puts " from #{ loc }" - end - end - output.puts - end - - def show_reveal_types(scratch, reveal_types, output) - return if reveal_types.empty? - - output.puts "# Revealed types" - reveal_types.each do |source_location, ty| - output.puts "# #{ source_location } #=> #{ ty.screen_name(scratch) }" - end - output.puts - end - - def show_gvars(scratch, gvars, output) - gvars = gvars.dump.filter_map do |gvar_name, entry| - if entry.type != Type.bot && !entry.rbs_declared - [gvar_name, entry] - end - end - # A signature for global variables is not supported in RBS - return if gvars.empty? - - output.puts "# Global variables" - gvars.each do |gvar_name, entry| - output.puts "#{ gvar_name }: #{ entry.type.screen_name(scratch) }" - end - output.puts - end - end - - class RubySignatureExporter - def initialize( - scratch, - class_defs, iseq_method_to_ctxs - ) - @scratch = scratch - @class_defs = class_defs - @iseq_method_to_ctxs = iseq_method_to_ctxs - end - - def conv_class(namespace, class_def, inner_classes) - @scratch.namespace = namespace - - if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass - omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj] - superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass) - type_args = class_def.klass_obj.superclass_type_args - if type_args && !type_args.empty? - superclass += "[#{ type_args.map {|ty| ty.screen_name(@scratch) }.join(", ") }]" - end - end - - @scratch.namespace = class_def.name - - consts = {} - class_def.consts.each do |name, (ty, loc)| - next unless loc - next if ty.is_a?(Type::Class) - next if Config.current.check_dir_filter(loc[0]) == :exclude - consts[name] = ty.screen_name(@scratch) - end - - modules = class_def.modules.to_h do |kind, mods| - mods = mods.to_h do |singleton, mods| - mods = mods.filter_map do |mod_def, _type_args, absolute_paths| - next if absolute_paths.all? {|path| !path || Config.current.check_dir_filter(path) == :exclude } - Type::Instance.new(mod_def.klass_obj).screen_name(@scratch) - end - [singleton, mods] - end - [kind, mods] - end - - visibilities = {} - source_locations = {} - methods = {} - ivars = class_def.ivars.dump - cvars = class_def.cvars.dump - - class_def.methods.each do |(singleton, mid), mdefs| - mdefs.each do |mdef| - case mdef - when ISeqMethodDef - ctxs = @iseq_method_to_ctxs[mdef] - next unless ctxs - - ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first - - next if Config.current.check_dir_filter(ctx.iseq.absolute_path) == :exclude - - method_name = mid - method_name = "self.#{ method_name }" if singleton - - key = [:iseq, method_name] - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= ctx.iseq.source_location(0) - (methods[key] ||= []) << @scratch.show_method_signature(ctx) - when AliasMethodDef - next if mdef.def_ep && Config.current.check_dir_filter(mdef.def_ep.source_location) == :exclude - alias_name, orig_name = mid, mdef.orig_mid - if singleton - alias_name = "self.#{ alias_name }" - orig_name = "self.#{ orig_name }" - end - key = [:alias, alias_name] - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= mdef.def_ep&.source_location - methods[key] = orig_name - when ExecutedAttrMethodDef - absolute_path = mdef.def_ep.ctx.iseq.absolute_path - next if !absolute_path || Config.current.check_dir_filter(absolute_path) == :exclude - mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=") - method_name = mid - method_name = "self.#{ mid }" if singleton - method_name = [method_name, :"@#{ mid }" != mdef.ivar] - key = [:attr, method_name] - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= mdef.def_ep.source_location - if methods[key] - if methods[key][0] != mdef.kind - methods[key][0] = :accessor - end - else - entry = ivars[[singleton, mdef.ivar]] - ty = entry ? entry.type : Type.any - methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)] - end - when TypedMethodDef - if mdef.rbs_source - method_name, sigs = mdef.rbs_source - key = [:rbs, method_name] - methods[key] = sigs - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= mdef.iseq&.source_location(0) - end - when TypedAttrMethodDef - if mdef.rbs_source - mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=") - method_name = mid - method_name = [method_name, :"@#{ mid }" != mdef.ivar] - key = [:rbs_attr, method_name] - visibilities[key] ||= mdef.pub_meth - if methods[key] - if methods[key][0] != mdef.kind - methods[key][0] = :accessor - end - else - entry = ivars[[singleton, mdef.ivar]] - ty = entry ? entry.type : Type.any - methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)] - end - end - end - end - end - - superclass_ivars = {} - while (superclass_def = (superclass_def || class_def).superclass) - superclass_ivars.merge!(superclass_def.ivars.dump) - end - - ivars = ivars.map do |(singleton, var), entry| - next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude } - ty = entry.type - next unless var.to_s.start_with?("@") - - if (_, existing = superclass_ivars.find {|((s, v), _)| s == singleton && v == var }) - existing_types = existing.type.is_a?(Type::Union) ? existing.type.types : [existing.type] - entry_types = entry.type.is_a?(Type::Union) ? entry.type.types : [entry.type] - if entry_types.all? { |t| existing_types.include?(t) } - # This type is a subset of the parent type - next - end - end - - var = "self.#{ var }" if singleton - next if methods[[:attr, [singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]] - next if entry.rbs_declared - [var, ty.screen_name(@scratch)] - end.compact - - cvars = cvars.map do |var, entry| - next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude } - next if entry.rbs_declared - [var, entry.type.screen_name(@scratch)] - end.compact - - if !class_def.absolute_path || Config.current.check_dir_filter(class_def.absolute_path) == :exclude - if methods.keys.all? {|type,| type == :rbs } - return nil if consts.empty? && modules[:before][true].empty? && modules[:before][false].empty? && modules[:after][true].empty? && modules[:after][false].empty? && ivars.empty? && cvars.empty? && inner_classes.empty? - end - end - - @scratch.namespace = nil - - ClassData.new( - kind: class_def.kind, - name: class_def.name, - superclass: superclass, - consts: consts, - modules: modules, - ivars: ivars, - cvars: cvars, - methods: methods, - visibilities: visibilities, - source_locations: source_locations, - inner_classes: inner_classes, - ) - end - - def conv_class_lsp(namespace, class_def) - @scratch.namespace = namespace - - if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass - omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj] - superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass) - type_args = class_def.klass_obj.superclass_type_args - if type_args && !type_args.empty? - superclass += "[#{ type_args.map {|ty| ty.screen_name(@scratch) }.join(", ") }]" - end - end - - @scratch.namespace = class_def.name - - consts = {} - class_def.consts.each do |name, (ty, loc)| - next unless loc - next if ty.is_a?(Type::Class) - next if Config.current.check_dir_filter(loc[0]) == :exclude - consts[name] = ty.screen_name(@scratch) - end - - modules = class_def.modules.to_h do |kind, mods| - mods = mods.to_h do |singleton, mods| - mods = mods.filter_map do |mod_def, _type_args, absolute_paths| - next if absolute_paths.all? {|path| !path || Config.current.check_dir_filter(path) == :exclude } - Type::Instance.new(mod_def.klass_obj).screen_name(@scratch) - end - [singleton, mods] - end - [kind, mods] - end - - visibilities = {} - source_locations = {} - methods = {} - ivars = class_def.ivars.dump - cvars = class_def.cvars.dump - - class_def.methods.each do |(singleton, mid), mdefs| - mdefs.each do |mdef| - case mdef - when ISeqMethodDef - ctxs = @iseq_method_to_ctxs[mdef] - next unless ctxs - - ctx = ctxs.find {|ctx| ctx.mid == mid } || ctxs.first - - next if Config.current.check_dir_filter(ctx.iseq.absolute_path) == :exclude - - method_name = mid - method_name = "self.#{ method_name }" if singleton - - key = [:iseq, method_name] - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= [ctx.iseq.source_location(0)] - sig = @scratch.show_method_signature(ctx) - (methods[key] ||= []) << sig if sig - when AliasMethodDef - alias_name, orig_name = mid, mdef.orig_mid - if singleton - alias_name = "self.#{ alias_name }" - orig_name = "self.#{ orig_name }" - end - key = [:alias, alias_name] - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= [mdef.def_ep&.source_location] - methods[key] = orig_name - when ExecutedAttrMethodDef - next if !mdef.def_ep - absolute_path = mdef.def_ep.ctx.iseq.absolute_path - next if !absolute_path || Config.current.check_dir_filter(absolute_path) == :exclude - mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=") - method_name = mid - method_name = "self.#{ mid }" if singleton - method_name = [method_name, :"@#{ mid }" != mdef.ivar] - key = [:attr, method_name] - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= [mdef.def_ep.source_location] - if methods[key] - if methods[key][0] != mdef.kind - methods[key][0] = :accessor - end - else - entry = ivars[[singleton, mdef.ivar]] - ty = entry ? entry.type : Type.any - methods[key] = [mdef.kind, ty.screen_name(@scratch), ty.include_untyped?(@scratch)] - end - when TypedMethodDef - if mdef.rbs_source - method_name, sigs, rbs_code_range = mdef.rbs_source - key = [:rbs, method_name] - methods[key] = sigs - visibilities[key] ||= mdef.pub_meth - source_locations[key] ||= [mdef.iseq&.source_location(0), rbs_code_range] - end - end - end - end - - ivars = ivars.map do |(singleton, var), entry| - next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude } - ty = entry.type - next unless var.to_s.start_with?("@") - var = "self.#{ var }" if singleton - next if methods[[:attr, [singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]] - next if entry.rbs_declared - [var, ty.screen_name(@scratch)] - end.compact - - cvars = cvars.map do |var, entry| - next if entry.absolute_paths.all? {|path| Config.current.check_dir_filter(path) == :exclude } - next if entry.rbs_declared - [var, entry.type.screen_name(@scratch)] - end.compact - - if !class_def.absolute_path || Config.current.check_dir_filter(class_def.absolute_path) == :exclude - if methods.keys.all? {|type,| type == :rbs } - return nil if consts.empty? && modules[:before][true].empty? && modules[:before][false].empty? && modules[:after][true].empty? && modules[:after][false].empty? && ivars.empty? && cvars.empty? - end - end - - @scratch.namespace = nil - - ClassData.new( - kind: class_def.kind, - name: class_def.name, - superclass: superclass, - consts: consts, - modules: modules, - ivars: ivars, - cvars: cvars, - methods: methods, - visibilities: visibilities, - source_locations: source_locations, - ) - end - - ClassData = Struct.new(:kind, :name, :superclass, :consts, :modules, :ivars, :cvars, :methods, :visibilities, :source_locations, :inner_classes, keyword_init: true) - - def show_lsp - res = [] - @class_defs.each_value do |class_def| - class_data = conv_class_lsp([], class_def) - next unless class_data - class_data.methods.each do |key, arg| - source_location, rbs_code_range = class_data.source_locations[key] - type, (method_name, hidden) = key - case type - when :attr, :rbs_attr - kind, ty, untyped = *arg - line = "attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }" - when :rbs - sigs = arg.sort.join(" | ") - line = "# def #{ method_name }: #{ sigs }" - when :iseq - sigs = [] - untyped = false - arg.each do |sig, untyped0| - sigs << sig - untyped ||= untyped0 - end - sigs = sigs.sort.join(" | ") - line = "def #{ method_name }: #{ sigs }" - when :alias - orig_name = arg - line = "alias #{ method_name } #{ orig_name }" - end - if source_location =~ /:(\d+)$/ - res << [$`, $1.to_i, line, rbs_code_range, class_data.kind, class_data.name] - end - end - end - res - end - - def show(stat_eps, output) - # make the class hierarchy - root = {} - @class_defs.each_value do |class_def| - h = root - class_def.name.each do |name| - h = h[name] ||= {} - end - h[:class_def] = class_def - end - - hierarchy = build_class_hierarchy([], root) - - output.puts "# Classes" # and Modules - - prev_nil = true - show_class_hierarchy(0, hierarchy).each do |line| - if line == nil - output.puts line unless prev_nil - prev_nil = true - else - output.puts line - prev_nil = false - end - end - - if ENV["TP_STAT"] - output.puts "" - output.puts "# TypeProf statistics:" - output.puts "# %d execution points" % stat_eps.size - end - - if ENV["TP_COVERAGE"] - coverage = {} - stat_eps.each do |ep| - path = ep.ctx.iseq.path - lineno = ep.ctx.iseq.insns[ep.pc].lineno - 1 - (coverage[path] ||= [])[lineno] ||= 0 - (coverage[path] ||= [])[lineno] += 1 - end - File.binwrite("typeprof-analysis-coverage.dump", Marshal.dump(coverage)) - end - end - - def build_class_hierarchy(namespace, hierarchy) - hierarchy.map do |name, h| - class_def = h.delete(:class_def) - class_data = conv_class(namespace, class_def, build_class_hierarchy(namespace + [name], h)) - class_data - end.compact - end - - def show_class_hierarchy(depth, hierarchy) - lines = [] - hierarchy.each do |class_data| - lines << nil - lines.concat show_class_data(depth, class_data) - end - lines - end - - def show_const(namespace, path) - return path.last.to_s if namespace == path - i = 0 - i += 1 while namespace[i] && namespace[i] == path[i] - path[i..].join("::") - end - - def show_class_data(depth, class_data) - indent = " " * depth - name = class_data.name.last - superclass = " < " + class_data.superclass if class_data.superclass - first_line = indent + "#{ class_data.kind } #{ name }#{ superclass }" - lines = [] - class_data.consts.each do |name, ty| - lines << (indent + " #{ name }: #{ ty }") - end - class_data.modules.each do |kind, mods| - mods.each do |singleton, mods| - case - when kind == :before && singleton then directive = nil - when kind == :before && !singleton then directive = "prepend" - when kind == :after && singleton then directive = "extend" - when kind == :after && !singleton then directive = "include" - end - mods.each do |mod| - lines << (indent + " #{ directive } #{ mod }") if directive - end - end - end - class_data.ivars.each do |var, ty| - lines << (indent + " #{ var }: #{ ty }") unless var.start_with?("_") - end - class_data.cvars.each do |var, ty| - lines << (indent + " #{ var }: #{ ty }") - end - lines << nil - prev_vis = true - class_data.methods.each do |key, arg| - vis = class_data.visibilities[key] - if prev_vis != vis - lines << nil - lines << (indent + " #{ vis ? "public" : "private" }") - prev_vis = vis - end - source_location = class_data.source_locations[key] - if Config.current.options[:show_source_locations] && source_location - lines << nil - lines << (indent + " # #{ source_location }") - end - type, (method_name, hidden) = key - case type - when :rbs_attr - kind, ty, untyped = *arg - lines << (indent + "# attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }") - when :attr - kind, ty, untyped = *arg - exclude = Config.current.options[:exclude_untyped] && untyped ? "#" : " " # XXX - lines << (indent + "#{ exclude } attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }") - when :rbs - arg = arg.map { |a| a.split("\n").join("\n" + indent + "#" + " " * (method_name.size + 5)) } - sigs = arg.sort.join("\n" + indent + "#" + " " * (method_name.size + 5) + "| ") - lines << (indent + "# def #{ method_name }: #{ sigs }") - when :iseq - sigs = [] - untyped = false - arg.each do |sig, untyped0| - sigs << sig - untyped ||= untyped0 - end - sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 6) + "| ") - exclude = Config.current.options[:exclude_untyped] && untyped ? "#" : " " # XXX - lines << (indent + "#{ exclude } def #{ method_name }: #{ sigs }") - when :alias - orig_name = arg - lines << (indent + " alias #{ method_name } #{ orig_name }") - end - end - lines.concat show_class_hierarchy(depth + 1, class_data.inner_classes) - lines.shift until lines.empty? || lines.first - lines.pop until lines.empty? || lines.last - lines.unshift first_line - lines << (indent + "end") - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/import.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/import.rb deleted file mode 100644 index 23b678230f32..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/import.rb +++ /dev/null @@ -1,815 +0,0 @@ -require "rbs" - -module TypeProf - class RBSReader - def initialize - @repo = RBS::Repository.new - collection_path = Config.current.collection_path - if collection_path&.exist? - collection_lock = RBS::Collection::Config.lockfile_of(collection_path) - @repo.add(collection_lock.repo_path) - end - @env, @loaded_gems, @builtin_env_json = RBSReader.get_builtin_env - end - - @builtin_env = @builtin_env_json = nil - def self.get_builtin_env - @loaded_gems = [] - unless @builtin_env - @builtin_env = RBS::Environment.new - - loader = RBS::EnvironmentLoader.new - - # TODO: invalidate this cache when rbs_collection.yml was changed - collection_path = Config.current.collection_path - if collection_path&.exist? - collection_lock = RBS::Collection::Config.lockfile_of(collection_path) - collection_lock.gems.each {|gem| @loaded_gems << gem["name"] } - loader.add_collection(collection_lock) - end - - new_decls = loader.load(env: @builtin_env).map {|decl,| decl } - @builtin_env_json = load_rbs(@builtin_env, new_decls) - end - - return @builtin_env.dup, @loaded_gems.dup, @builtin_env_json - end - - def load_builtin - @builtin_env_json - end - - class RBSCollectionDefined < StandardError; end - - def load_library(lib) - loader = RBS::EnvironmentLoader.new(core_root: nil, repository: @repo) - if @loaded_gems.include?(lib) - raise RBSCollectionDefined - end - @loaded_gems << lib - loader.add(library: lib) - - case lib - when 'bigdecimal-math' - loader.add(library: 'bigdecimal') - when "yaml" - loader.add(library: "pstore") - loader.add(library: "dbm") - when "logger" - loader.add(library: "monitor") - when "csv" - loader.add(library: "forwardable") - when "prime" - loader.add(library: "singleton") - end - - new_decls = loader.load(env: @env).map {|decl,| decl } - RBSReader.load_rbs(@env, new_decls) - end - - def load_paths(paths) - loader = RBS::EnvironmentLoader.new(core_root: nil, repository: @repo) - paths.each {|path| loader.add(path: path) } - new_decls = loader.load(env: @env).map {|decl,| decl } - RBSReader.load_rbs(@env, new_decls) - end - - def load_rbs_string(name, content) - buffer = RBS::Buffer.new(name: name, content: content) - new_decls = [] - RBS::Parser.parse_signature(buffer).each do |decl| - @env << decl - new_decls << decl - end - RBSReader.load_rbs(@env, new_decls) - end - - def self.load_rbs(env, new_decls) - all_env = env.resolve_type_names - resolver = RBS::TypeNameResolver.from_env(all_env) - cur_env = RBS::Environment.new - new_decls.each do |decl| - cur_env << env.resolve_declaration(resolver, decl, outer: [], prefix: RBS::Namespace.root) - end - - RBS2JSON.new(all_env, cur_env).dump_json - end - end - - class RBS2JSON - def initialize(all_env, cur_env) - @all_env, @cur_env = all_env, cur_env - @alias_resolution_stack = {} - end - - def dump_json - { - classes: conv_classes, - constants: conv_constants, - globals: conv_globals, - } - end - - # constant_name = [Symbol] - # - # { constant_name => type } - def conv_constants - constants = {} - @cur_env.constant_decls.each do |name, decl| - klass = conv_type_name(name) - constants[klass] = conv_type(decl.decl.type) - end - constants - end - - # gvar_name = Symbol (:$gvar) - # - # { gvar_name => type } - def conv_globals - gvars = {} - @cur_env.global_decls.each do |name, decl| - decl = decl.decl - gvars[name] = conv_type(decl.type) - end - gvars - end - - def conv_classes - json = {} - - each_class_decl do |name, decls| - klass = conv_type_name(name) - super_class_name, super_class_args = get_super_class(name, decls) - if super_class_name - name = conv_type_name(super_class_name) - type_args = super_class_args.map {|type| conv_type(type) } - superclass = [name, type_args] - end - - type_params = nil - modules = { include: [], extend: [], prepend: [] } - methods = {} - attr_methods = {} - ivars = {} - cvars = {} - rbs_sources = {} - visibility = true - - decls.each do |decl| - decl = decl.decl - - type_params2 = decl.type_params - # A hack to deal with the imcompatibility between rbs 1.8 and 2.0 - type_params2 = type_params2.params if type_params2.respond_to?(:params) - type_params2 = type_params2.map {|param| [param.name, param.variance] } - raise "inconsistent type parameter declaration" if type_params && type_params != type_params2 - type_params = type_params2 - - decl.members.each do |member| - case member - when RBS::AST::Members::MethodDefinition - name = member.name - - method_types = member.types.map do |method_type| - case method_type - when RBS::MethodType then method_type - when :super then raise NotImplementedError - end - end - - method_def = conv_method_def(method_types, visibility) - rbs_source = [ - (member.kind == :singleton ? "self." : "") + member.name.to_s, - member.types.map {|type| type.location.source }, - [member.location.name, CodeRange.from_rbs(member.location)], - ] - if member.instance? - methods[[false, name]] = method_def - rbs_sources[[false, name]] = rbs_source - end - if member.singleton? - methods[[true, name]] = method_def - rbs_sources[[true, name]] = rbs_source - end - when RBS::AST::Members::AttrReader - ty = conv_type(member.type) - attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty, visibility) - rbs_sources[[false, member.name]] = attr_rbs_source(member) - when RBS::AST::Members::AttrWriter - ty = conv_type(member.type) - attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty, visibility) - rbs_sources[[false, member.name]] = attr_rbs_source(member) - when RBS::AST::Members::AttrAccessor - ty = conv_type(member.type) - attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty, visibility) - rbs_sources[[false, member.name]] = attr_rbs_source(member) - when RBS::AST::Members::Alias - # XXX: an alias to attr methods? - if member.instance? - method_def = methods[[false, member.old_name]] - methods[[false, member.new_name]] = method_def if method_def - end - if member.singleton? - method_def = methods[[true, member.old_name]] - methods[[true, member.new_name]] = method_def if method_def - end - - when RBS::AST::Members::Include - name = member.name - if name.kind == :class - # including a module - mod = conv_type_name(name) - type_args = member.args.map {|type| conv_type(type) } - modules[:include] << [mod, type_args] - else - # including an interface - mod = conv_type_name(name) - type_args = member.args.map {|type| conv_type(type) } - modules[:include] << [mod, type_args] - end - - when RBS::AST::Members::Extend - name = member.name - if name.kind == :class - mod = conv_type_name(name) - type_args = member.args.map {|type| conv_type(type) } - modules[:extend] << [mod, type_args] - else - # extending a module with an interface is not supported yet - end - - when RBS::AST::Members::Prepend - name = member.name - if name.kind == :class - mod = conv_type_name(name) - type_args = member.args.map {|type| conv_type(type) } - modules[:prepend] << [mod, type_args] - else - # extending a module with an interface is not supported yet - end - - when RBS::AST::Members::InstanceVariable - ivars[member.name] = conv_type(member.type) - when RBS::AST::Members::ClassVariable - cvars[member.name] = conv_type(member.type) - - when RBS::AST::Members::Public - visibility = true - when RBS::AST::Members::Private - visibility = false - - # The following declarations are ignoreable because they are handled in other level - when RBS::AST::Declarations::Constant - when RBS::AST::Declarations::Alias # type alias - when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module - when RBS::AST::Declarations::Interface - - else - warn "Importing #{ member.class.name } is not supported yet" - end - end - end - - json[klass] = { - type_params: type_params, - superclass: superclass, - members: { - modules: modules, - methods: methods, - attr_methods: attr_methods, - ivars: ivars, - cvars: cvars, - rbs_sources: rbs_sources, - }, - } - end - - json - end - - def each_class_decl - # topological sort - # * superclasses and modules appear earlier than their subclasses (Object is earlier than String) - # * namespace module appers earlier than its children (Process is earlier than Process::Status) - visited = {} - queue = @cur_env.class_decls.keys.map {|name| [:visit, name] }.reverse - until queue.empty? - event, name = queue.pop - case event - when :visit - if !visited[name] - visited[name] = true - queue << [:new, name] - @all_env.class_decls[name].decls.each do |decl| - decl = decl.decl - next if decl.is_a?(RBS::AST::Declarations::Module) - each_reference(decl) {|name| queue << [:visit, name] } - end - queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty? - end - when :new - decls = @cur_env.class_decls[name] - yield name, decls.decls if decls - end - end - - @cur_env.interface_decls.each do |name, decl| - yield name, [decl] - end - end - - def each_reference(decl, &blk) - yield decl.name - if decl.super_class - name = decl.super_class.name - else - name = RBS::BuiltinNames::Object.name - end - return if decl.name == RBS::BuiltinNames::BasicObject.name - return if decl.name == name - decls = @all_env.class_decls[name] - if decls - decls.decls.each do |decl| - each_reference(decl.decl, &blk) - end - end - end - - def get_super_class(name, decls) - return nil if name == RBS::BuiltinNames::BasicObject.name - - decls.each do |decl| - decl = decl.decl - case decl - when RBS::AST::Declarations::Class - super_class = decl.super_class - return super_class.name, super_class.args if super_class - when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface - return nil - else - raise "unknown declaration: %p" % decl.class - end - end - - return RBS::BuiltinNames::Object.name, [] - end - - def conv_method_def(rbs_method_types, visibility) - sig_rets = rbs_method_types.map do |method_type| - conv_func(method_type.type_params, method_type.type, method_type.block) - end - { - sig_rets: sig_rets, - visibility: visibility, - } - end - - def conv_func(type_params, func, block) - blk = block ? conv_block(block) : nil - - lead_tys = func.required_positionals.map {|type| conv_type(type.type) } - opt_tys = func.optional_positionals.map {|type| conv_type(type.type) } - rest_ty = func.rest_positionals - rest_ty = conv_type(rest_ty.type) if rest_ty - opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] } - req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] } - rest_kw_ty = func.rest_keywords - rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty - - ret_ty = conv_type(func.return_type) - - { - type_params: type_params, - lead_tys: lead_tys, - opt_tys: opt_tys, - rest_ty: rest_ty, - req_kw_tys: req_kw_tys, - opt_kw_tys: opt_kw_tys, - rest_kw_ty: rest_kw_ty, - blk: blk, - ret_ty: ret_ty, - } - end - - def attr_method_def(kind, name, ty, visibility) - { - kind: kind, - ivar: name, - ty: ty, - visibility: visibility, - } - end - - def attr_rbs_source(member) - [ - member.name.to_s, - member.type.location.source, - [member.location.name, CodeRange.from_rbs(member.location)], - ] - end - - def conv_block(rbs_block) - blk = rbs_block.type - - lead_tys = blk.required_positionals.map {|type| conv_type(type.type) } - opt_tys = blk.optional_positionals.map {|type| conv_type(type.type) } - rest_ty = blk.rest_positionals - rest_ty = conv_type(rest_ty.type) if rest_ty - opt_kw_tys = blk.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] } - req_kw_tys = blk.required_keywords.to_h {|key, type| [key, conv_type(type.type)] } - rest_kw_ty = blk.rest_keywords - rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty - - ret_ty = conv_type(blk.return_type) - - { - required_block: rbs_block.required, - lead_tys: lead_tys, - opt_tys: opt_tys, - rest_ty: rest_ty, - req_kw_tys: req_kw_tys, - opt_kw_tys: opt_kw_tys, - rest_kw_ty: rest_kw_ty, - blk: blk, - ret_ty: ret_ty, - } - end - - def conv_type(ty) - case ty - when RBS::Types::ClassSingleton - [:class, conv_type_name(ty.name)] - when RBS::Types::ClassInstance - klass = conv_type_name(ty.name) - case klass - when [:Array] - raise if ty.args.size != 1 - [:array, [:Array], [], conv_type(ty.args.first)] - when [:Hash] - raise if ty.args.size != 2 - key, val = ty.args - [:hash, [:Hash], [conv_type(key), conv_type(val)]] - when [:Enumerator] - raise if ty.args.size != 2 - [:array, [:Enumerator], [], conv_type(ty.args.first)] - else - if ty.args.empty? - [:instance, klass] - else - [:cell, [:instance, klass], ty.args.map {|ty| conv_type(ty) }] - end - end - when RBS::Types::Bases::Bool then [:bool] - when RBS::Types::Bases::Any then [:any] - when RBS::Types::Bases::Top then [:any] - when RBS::Types::Bases::Void then [:void] - when RBS::Types::Bases::Self then [:self] - when RBS::Types::Bases::Nil then [:nil] - when RBS::Types::Bases::Bottom then [:union, []] - when RBS::Types::Variable then [:var, ty.name] - when RBS::Types::Tuple - tys = ty.types.map {|ty2| conv_type(ty2) } - [:array, [:Array], tys, [:union, []]] - when RBS::Types::Literal - case ty.literal - when Integer then [:int] - when String then [:str] - when true then [:true] - when false then [:false] - when Symbol then [:sym, ty.literal] - else - p ty.literal - raise NotImplementedError - end - when RBS::Types::Alias - if @alias_resolution_stack[ty.name] - [:any] - else - begin - @alias_resolution_stack[ty.name] = true - alias_decl = @all_env.alias_decls[ty.name] - alias_decl ? conv_type(alias_decl.decl.type) : [:any] - ensure - @alias_resolution_stack.delete(ty.name) - end - end - when RBS::Types::Union - [:union, ty.types.map {|ty2| conv_type(ty2) }.compact] - when RBS::Types::Intersection - [:intersection, ty.types.map {|ty2| conv_type(ty2) }.compact] - when RBS::Types::Optional - [:optional, conv_type(ty.type)] - when RBS::Types::Interface - # XXX: Currently, only a few builtin interfaces are supported - case ty.to_s - when "::_ToS" then [:str] - when "::_ToStr" then [:str] - when "::_ToInt" then [:int] - when "::_ToAry[U]" then [:array, [:Array], [], [:var, :U]] - else - [:instance, conv_type_name(ty.name)] - end - when RBS::Types::Bases::Instance then [:any] # XXX: not implemented yet - when RBS::Types::Bases::Class then [:any] # XXX: not implemented yet - when RBS::Types::Record - [:hash_record, [:Hash], ty.fields.map {|key, ty| [key, conv_type(ty)] }] - when RBS::Types::Proc - [:proc, conv_func(nil, ty.type, nil)] - else - warn "unknown RBS type: %p" % ty.class - [:any] - end - end - - def conv_type_name(name) - name.namespace.path + [name.name] - end - end - - class Import - def self.import_builtin(scratch) - Import.new(scratch, scratch.rbs_reader.load_builtin).import - end - - def self.import_library(scratch, feature) - begin - json = scratch.rbs_reader.load_library(feature) - rescue RBS::EnvironmentLoader::UnknownLibraryError - return nil - rescue RBS::DuplicatedDeclarationError, RBSReader::RBSCollectionDefined - return true - end - # need cache? - Import.new(scratch, json).import - end - - def self.import_rbs_files(scratch, rbs_paths) - rbs_paths = rbs_paths.map {|rbs_path| Pathname(rbs_path) } - Import.new(scratch, scratch.rbs_reader.load_paths(rbs_paths)).import(true) - end - - def self.import_rbs_code(scratch, rbs_name, rbs_code) - Import.new(scratch, scratch.rbs_reader.load_rbs_string(rbs_name, rbs_code)).import(true) - end - - def initialize(scratch, json) - @scratch = scratch - @json = json - end - - def import(explicit = false) - classes = @json[:classes].map do |classpath, cdef| - type_params = cdef[:type_params] - superclass, superclass_type_args = cdef[:superclass] - members = cdef[:members] - - name = classpath.last - superclass = path_to_klass(superclass) if superclass - base_klass = path_to_klass(classpath[0..-2]) - - klass, = @scratch.get_constant(base_klass, name) - if klass.is_a?(Type::Any) - klass = @scratch.new_class(base_klass, name, type_params, superclass, nil) - - # There builtin classes are needed to interpret RBS declarations - case classpath - when [:NilClass] then Type::Builtin[:nil] = klass - when [:TrueClass] then Type::Builtin[:true] = klass - when [:FalseClass] then Type::Builtin[:false] = klass - when [:Integer] then Type::Builtin[:int] = klass - when [:String] then Type::Builtin[:str] = klass - when [:Symbol] then Type::Builtin[:sym] = klass - when [:Array] then Type::Builtin[:ary] = klass - when [:Hash] then Type::Builtin[:hash] = klass - when [:Proc] then Type::Builtin[:proc] = klass - end - end - - [klass, superclass_type_args, members] - end - - classes.each do |klass, superclass_type_args, members| - @scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) }) - modules = members[:modules] - methods = members[:methods] - attr_methods = members[:attr_methods] - ivars = members[:ivars] - cvars = members[:cvars] - rbs_sources = members[:rbs_sources] - - modules.each do |kind, mods| - mods.each do |mod, type_args| - type_args = type_args&.map {|ty| conv_type(ty) } - case kind - when :include - @scratch.mix_module(:after, klass, path_to_klass(mod), type_args, false, nil) - when :extend - @scratch.mix_module(:after, klass, path_to_klass(mod), type_args, true, nil) - when :prepend - @scratch.mix_module(:before, klass, path_to_klass(mod), type_args, false, nil) - end - end - end - - methods.each do |(singleton, method_name), mdef| - rbs_source = explicit ? rbs_sources[[singleton, method_name]] : nil - mdef = conv_method_def(method_name, mdef, rbs_source) - @scratch.add_method(klass, method_name, singleton, mdef) - end - - attr_methods.each do |(singleton, method_name), mdef| - rbs_source = explicit ? rbs_sources[[singleton, method_name]] : nil - ty = conv_type(mdef[:ty]).remove_type_vars - mdefs = conv_attr_defs(mdef, rbs_source) - mdefs.each do |mdef| - @scratch.add_typed_attr_method(klass, mdef) - end - @scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ mdef[:ivar] }", ty, nil) - end - - ivars.each do |ivar_name, ty| - ty = conv_type(ty).remove_type_vars - @scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil) - end - - cvars.each do |ivar_name, ty| - ty = conv_type(ty).remove_type_vars - @scratch.add_cvar_write!(klass, ivar_name, ty, nil) - end - end - - @json[:constants].each do |classpath, value| - base_klass = path_to_klass(classpath[0..-2]) - value = conv_type(value).remove_type_vars - @scratch.add_constant(base_klass, classpath[-1], value, nil) - end - - @json[:globals].each do |name, ty| - ty = conv_type(ty).remove_type_vars - @scratch.add_gvar_write!(name, ty, nil) - end - - true - end - - def conv_method_def(method_name, mdef, rbs_source) - sig_rets = mdef[:sig_rets].flat_map do |sig_ret| - conv_func(sig_ret) - end - - TypedMethodDef.new(sig_rets, rbs_source, mdef[:visibility]) - end - - def conv_attr_defs(mdef, rbs_source) - ivar = :"@#{ mdef[:ivar] }" - kind = mdef[:kind] - pub_meth = mdef[:visibility] - - defs = [] - if kind == :reader || kind == :accessor - defs << TypedAttrMethodDef.new(ivar, :reader, pub_meth, rbs_source) - end - if kind == :writer || kind == :accessor - defs << TypedAttrMethodDef.new(ivar, :writer, pub_meth, rbs_source) - end - raise if defs.empty? - defs - end - - def conv_func(sig_ret) - #type_params = sig_ret[:type_params] # XXX - lead_tys = sig_ret[:lead_tys] - opt_tys = sig_ret[:opt_tys] - rest_ty = sig_ret[:rest_ty] - req_kw_tys = sig_ret[:req_kw_tys] - opt_kw_tys = sig_ret[:opt_kw_tys] - rest_kw_ty = sig_ret[:rest_kw_ty] - blk = sig_ret[:blk] - ret_ty = sig_ret[:ret_ty] - - lead_tys = lead_tys.map {|ty| conv_type(ty) } - opt_tys = opt_tys.map {|ty| conv_type(ty) } - rest_ty = conv_type(rest_ty) if rest_ty - kw_tys = [] - req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] } - opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] } - if rest_kw_ty - ty = conv_type(rest_kw_ty) - kw_rest_ty = Type.gen_hash do |h| - k_ty = Type::Instance.new(Type::Builtin[:sym]) - h[k_ty] = ty - end - end - - blks = conv_block(blk) - - ret_ty = conv_type(ret_ty) - - blks.map do |blk| - [MethodSignature.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, blk), ret_ty] - end - end - - def conv_block(blk) - return [Type.nil] unless blk - - required_block = blk[:required_block] - lead_tys = blk[:lead_tys] - opt_tys = blk[:opt_tys] - rest_ty = blk[:rest_ty] - req_kw_tys = blk[:req_kw_tys] - opt_kw_tys = blk[:opt_kw_tys] - rest_kw_ty = blk[:rest_kw_ty] - ret_ty = blk[:ret_ty] - - lead_tys = lead_tys.map {|ty| conv_type(ty) } - opt_tys = opt_tys.map {|ty| conv_type(ty) } - rest_ty = conv_type(rest_ty) if rest_ty - kw_tys = [] - req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] } - opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] } - if rest_kw_ty - ty = conv_type(rest_kw_ty) - kw_rest_ty = Type.gen_hash do |h| - k_ty = Type::Instance.new(Type::Builtin[:sym]) - h[k_ty] = ty - end - end - - msig = MethodSignature.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, Type.nil) - - ret_ty = conv_type(ret_ty) - - ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])] - ret << Type.nil unless required_block - ret - end - - def conv_type(ty) - case ty.first - when :class then path_to_klass(ty[1]) - when :instance then Type::Instance.new(path_to_klass(ty[1])) - when :cell - Type::Cell.new(Type::Cell::Elements.new(ty[2].map {|ty| conv_type(ty) }), conv_type(ty[1])) - when :any then Type.any - when :void then Type::Void.new - when :nil then Type.nil - when :optional then Type.optional(conv_type(ty[1])) - when :bool then Type.bool - when :self then Type::Var.new(:self) - when :int then Type::Instance.new(Type::Builtin[:int]) - when :str then Type::Instance.new(Type::Builtin[:str]) - when :sym then Type::Symbol.new(ty.last, Type::Instance.new(Type::Builtin[:sym])) - when :true then Type::Instance.new(Type::Builtin[:true]) - when :false then Type::Instance.new(Type::Builtin[:false]) - when :array - _, path, lead_tys, rest_ty = ty - lead_tys = lead_tys.map {|ty| conv_type(ty) } - rest_ty = conv_type(rest_ty) - base_type = Type::Instance.new(path_to_klass(path)) - Type::Array.new(Type::Array::Elements.new(lead_tys, rest_ty), base_type) - when :hash - _, path, (k, v) = ty - Type.gen_hash(Type::Instance.new(path_to_klass(path))) do |h| - k_ty = conv_type(k) - v_ty = conv_type(v) - h[k_ty] = v_ty - end - when :hash_record - _, path, key_tys = ty - Type.gen_hash(Type::Instance.new(path_to_klass(path))) do |h| - key_tys.each do |key, ty| - k_ty = Type::Symbol.new(key, Type::Instance.new(Type::Builtin[:sym])) - v_ty = conv_type(ty) - h[k_ty] = v_ty - end - end - when :union - tys = ty[1] - Type::Union.create(Utils::Set[*tys.map {|ty2| conv_type(ty2) }], nil) # XXX: Array and Hash support - when :intersection - tys = ty[1] - conv_type(tys.first) # XXX: This is wrong! We need to support intersection type - when :var - Type::Var.new(ty[1]) - when :proc - msig, ret_ty = conv_func(ty[1]).first # Currently, RBS Proc does not accept a block, so the size should be always one - Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Instance.new(Type::Builtin[:proc])) - else - pp ty - raise NotImplementedError - end - end - - def path_to_klass(path) - klass = Type::Builtin[:obj] - path.each do |name| - klass, = @scratch.get_constant(klass, name) - if klass == Type.any - raise TypeProfError.new("A constant `#{ path.join("::") }' is used but not defined in RBS") - end - end - klass - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/insns-def.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/insns-def.rb deleted file mode 100644 index 4bc595139f57..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/insns-def.rb +++ /dev/null @@ -1,63 +0,0 @@ -TypeProf::INSN_TABLE = {:nop=>[], - :getlocal=>["lindex_t", "rb_num_t"], - :setlocal=>["lindex_t", "rb_num_t"], - :getblockparam=>["lindex_t", "rb_num_t"], - :setblockparam=>["lindex_t", "rb_num_t"], - :getblockparamproxy=>["lindex_t", "rb_num_t"], - :getspecial=>["rb_num_t", "rb_num_t"], - :setspecial=>["rb_num_t"], - :getinstancevariable=>["ID", "IVC"], - :setinstancevariable=>["ID", "IVC"], - :getclassvariable=>["ID"], - :setclassvariable=>["ID"], - :getconstant=>["ID"], - :setconstant=>["ID"], - :getglobal=>["GENTRY"], - :setglobal=>["GENTRY"], - :putnil=>[], - :putself=>[], - :putobject=>["VALUE"], - :putspecialobject=>["rb_num_t"], - :putstring=>["VALUE"], - :concatstrings=>["rb_num_t"], - :tostring=>[], - :objtostring=>[], - :anytostring=>[], - :freezestring=>["VALUE"], - :toregexp=>["rb_num_t", "rb_num_t"], - :intern=>[], - :newarray=>["rb_num_t"], - :newarraykwsplat=>["rb_num_t"], - :duparray=>["VALUE"], - :duphash=>["VALUE"], - :expandarray=>["rb_num_t", "rb_num_t"], - :concatarray=>[], - :splatarray=>["VALUE"], - :newhash=>["rb_num_t"], - :newrange=>["rb_num_t"], - :pop=>[], - :dup=>[], - :dupn=>["rb_num_t"], - :swap=>[], - :reverse=>["rb_num_t"], - :topn=>["rb_num_t"], - :setn=>["rb_num_t"], - :adjuststack=>["rb_num_t"], - :defined=>["rb_num_t", "VALUE", "VALUE"], - :checkmatch=>["rb_num_t"], - :checkkeyword=>["lindex_t", "lindex_t"], - :checktype=>["rb_num_t"], - :defineclass=>["ID", "ISEQ", "rb_num_t"], - :definemethod=>["ID", "ISEQ"], - :definesmethod=>["ID", "ISEQ"], - :send=>["CALL_DATA", "ISEQ"], - :invokesuper=>["CALL_DATA", "ISEQ"], - :invokeblock=>["CALL_DATA"], - :leave=>[], - :throw=>["rb_num_t"], - :jump=>["OFFSET"], - :branchif=>["OFFSET"], - :branchunless=>["OFFSET"], - :branchnil=>["OFFSET"], - :once=>["ISEQ", "ISE"], - :invokebuiltin=>["RB_BUILTIN"]} diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/iseq.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/iseq.rb deleted file mode 100644 index 208e051fb3d7..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/iseq.rb +++ /dev/null @@ -1,831 +0,0 @@ -module TypeProf - class ISeq - # https://github.com/ruby/ruby/pull/4468 - CASE_WHEN_CHECKMATCH = RubyVM::InstructionSequence.compile("case 1; when Integer; end").to_a.last.any? {|insn,| insn == :checkmatch } - # https://github.com/ruby/ruby/blob/v3_0_2/vm_core.h#L1206 - VM_ENV_DATA_SIZE = 3 - # Check if Ruby 3.1 or later - RICH_AST = begin RubyVM::AbstractSyntaxTree.parse("1", keep_script_lines: true).node_id; true; rescue; false; end - - FileInfo = Struct.new( - :node_id2node, - :definition_table, - :caller_table, - :created_iseqs, - ) - - class << self - def compile(file) - compile_core(nil, file) - end - - def compile_str(str, path = nil) - compile_core(str, path) - end - - private def compile_core(str, path) - opt = RubyVM::InstructionSequence.compile_option - opt[:inline_const_cache] = false - opt[:peephole_optimization] = false - opt[:specialized_instruction] = false - opt[:operands_unification] = false - opt[:coverage_enabled] = false - - parse_opts = {} - parse_opts[:keep_script_lines] = true if RICH_AST - - unless defined?(RubyVM::InstructionSequence) - puts "Currently, TypeProf can work on a Ruby implementation that supports RubyVM::InstructionSequence, such as CRuby." - exit 1 - end - - if str - node = RubyVM::AbstractSyntaxTree.parse(str, **parse_opts) - iseq = RubyVM::InstructionSequence.compile(str, path, **opt) - else - node = RubyVM::AbstractSyntaxTree.parse_file(path, **parse_opts) - iseq = RubyVM::InstructionSequence.compile_file(path, **opt) - end - - node_id2node = {} - build_ast_node_id_table(node, node_id2node) if RICH_AST - - file_info = FileInfo.new(node_id2node, CodeRangeTable.new, CodeRangeTable.new, []) - iseq_rb = new(iseq.to_a, file_info) - iseq_rb.collect_local_variable_info(file_info) if RICH_AST - file_info.created_iseqs.each do |iseq| - iseq.unify_instructions - end - - return iseq_rb, file_info.definition_table, file_info.caller_table - end - - private def build_ast_node_id_table(node, tbl = {}) - tbl[node.node_id] = node - node.children.each do |child| - build_ast_node_id_table(child, tbl) if child.is_a?(RubyVM::AbstractSyntaxTree::Node) - end - tbl - end - - def code_range_from_node(node) - CodeRange.new( - CodeLocation.new(node.first_lineno, node.first_column), - CodeLocation.new(node.last_lineno, node.last_column), - ) - end - - def find_node_by_id(node, id) - node = RubyVM::AbstractSyntaxTree.parse(node) if node.is_a?(String) - - return node if id == node.node_id - - node.children.each do |child| - if child.is_a?(RubyVM::AbstractSyntaxTree::Node) - ret = find_node_by_id(child, id) - return ret if ret - end - end - - nil - end - end - - Insn = Struct.new(:insn, :operands, :lineno, :code_range, :definitions) - class Insn - def check?(insn_cmp, operands_cmp = nil) - return insn == insn_cmp && (!operands_cmp || operands == operands_cmp) - end - end - - ISEQ_FRESH_ID = [0] - - def initialize(iseq, file_info) - file_info.created_iseqs << self - - @id = (ISEQ_FRESH_ID[0] += 1) - - _magic, _major_version, _minor_version, _format_type, misc, - @name, @path, @absolute_path, @start_lineno, @type, - @locals, @fargs_format, catch_table, insns = *iseq - - fl, fc, ll, lc = misc[:code_location] - @iseq_code_range = CodeRange.new(CodeLocation.new(fl, fc), CodeLocation.new(ll, lc)) - - convert_insns(insns, misc[:node_ids] || [], file_info) - - add_body_start_marker(insns) - - add_exception_cont_marker(insns, catch_table) - - labels = create_label_table(insns) - - @insns = setup_insns(insns, labels, file_info) - - @fargs_format[:opt] = @fargs_format[:opt].map {|l| labels[l] } if @fargs_format[:opt] - - @catch_table = [] - catch_table.map do |type, iseq, first, last, cont, stack_depth| - iseq = iseq ? ISeq.new(iseq, file_info) : nil - target = labels[cont] - entry = [type, iseq, target, stack_depth] - labels[first].upto(labels[last]) do |i| - @catch_table[i] ||= [] - @catch_table[i] << entry - end - end - - def_node_id = misc[:def_node_id] - if def_node_id && file_info.node_id2node[def_node_id] && (@type == :method || @type == :block) - def_node = file_info.node_id2node[def_node_id] - method_name_token_range = extract_method_name_token_range(def_node) - if method_name_token_range - @callers = Utils::MutableSet.new - file_info.caller_table[method_name_token_range] = @callers - end - end - - rename_insn_types - end - - def extract_method_name_token_range(node) - case @type - when :method - regex = if node.type == :DEFS - /^def\s+(?:\w+)\s*\.\s*(\w+)/ - else - /^def\s+(\w+)/ - end - return nil unless node.source =~ regex - zero_loc = CodeLocation.new(1, 0) - name_start = $~.begin(1) - name_length = $~.end(1) - name_start - name_head_loc = zero_loc.advance_cursor(name_start, node.source) - name_tail_loc = name_head_loc.advance_cursor(name_length, node.source) - return CodeRange.new( - CodeLocation.new( - node.first_lineno + (name_head_loc.lineno - 1), - name_head_loc.lineno == 1 ? node.first_column + name_head_loc.column : name_head_loc.column - ), - CodeLocation.new( - node.first_lineno + (name_tail_loc.lineno - 1), - name_tail_loc.lineno == 1 ? node.first_column + name_tail_loc.column : name_tail_loc.column - ), - ) - when :block - return ISeq.code_range_from_node(node) - end - end - - def source_location(pc) - "#{ @path }:#{ @insns[pc].lineno }" - end - - def detailed_source_location(pc) - code_range = @insns[pc].code_range - if code_range - [@path, code_range] - else - [@path] - end - end - - def add_called_iseq(pc, callee_iseq) - if callee_iseq && @insns[pc].definitions - @insns[pc].definitions << [callee_iseq.path, callee_iseq.iseq_code_range] - end - if callee_iseq.callers - callee_iseq.callers << [@path, @insns[pc].code_range] - end - end - - def add_def_loc(pc, detailed_loc) - if detailed_loc && @insns[pc].definitions - @insns[pc].definitions << detailed_loc - end - end - - attr_reader :name, :path, :absolute_path, :start_lineno, :type, :locals, :fargs_format, :catch_table, :insns - attr_reader :id, :iseq_code_range, :callers - - def pretty_print(q) - q.text "ISeq[" - q.group do - q.nest(1) do - q.breakable "" - q.text "@type= #{ @type }" - q.breakable ", " - q.text "@name= #{ @name }" - q.breakable ", " - q.text "@path= #{ @path }" - q.breakable ", " - q.text "@absolute_path= #{ @absolute_path }" - q.breakable ", " - q.text "@start_lineno= #{ @start_lineno }" - q.breakable ", " - q.text "@fargs_format= #{ @fargs_format.inspect }" - q.breakable ", " - q.text "@insns=" - q.group(2) do - @insns.each_with_index do |(insn, *operands), i| - q.breakable - q.group(2, "#{ i }: #{ insn.to_s }", "") do - q.pp operands - end - end - end - end - q.breakable - end - q.text "]" - end - - def <=>(other) - @id <=> other.id - end - - # Remove lineno entry and convert instructions to Insn instances - def convert_insns(insns, node_ids, file_info) - ninsns = [] - lineno = 0 - insns.each do |e| - case e - when Integer # lineno - lineno = e - when Symbol # label or trace - ninsns << e - when Array - insn, *operands = e - node_id = node_ids.shift - node = file_info.node_id2node[node_id] - if node - code_range = ISeq.code_range_from_node(node) - case insn - when :send, :invokesuper - opt, blk_iseq = operands - opt[:node_id] = node_id - if blk_iseq - misc = blk_iseq[4] # iseq's "misc" field - misc[:def_node_id] = node_id - end - when :definemethod, :definesmethod - iseq = operands[1] - misc = iseq[4] # iseq's "misc" field - misc[:def_node_id] = node_id - end - end - ninsns << Insn.new(insn, operands, lineno, code_range, nil) - else - raise "unknown iseq entry: #{ e }" - end - end - insns.replace(ninsns) - end - - # Insert a dummy instruction "_iseq_body_start" - def add_body_start_marker(insns) - case @type - when :method, :block - # skip initialization code of optional arguments - if @fargs_format[:opt] - label = @fargs_format[:opt].last - i = insns.index(label) + 1 - else - i = insns.find_index {|insn| insn.is_a?(Insn) } - end - - # skip initialization code of keyword arguments - while insns[i][0] == :checkkeyword - raise if insns[i + 1].insn != :branchif - label = insns[i + 1].operands[0] - i = insns.index(label) + 1 - end - - insns.insert(i, Insn.new(:_iseq_body_start, [], @start_lineno, nil, nil)) - end - end - - # Insert "nop" instruction to continuation point of exception handlers - def add_exception_cont_marker(insns, catch_table) - # rescue/ensure clauses need to have a dedicated return addresses - # because they requires to be virtually called. - # So, this preprocess adds "nop" to make a new insn for their return addresses - exception_cont_labels = {} - catch_table.map! do |type, iseq, first, last, cont, stack_depth| - if type == :rescue || type == :ensure - exception_cont_labels[cont] = true - cont = :"#{ cont }_exception_cont" - end - [type, iseq, first, last, cont, stack_depth] - end - - i = 0 - while i < insns.size - e = insns[i] - if exception_cont_labels[e] - insns.insert(i, :"#{ e }_exception_cont", Insn.new(:nop, [])) - i += 2 - end - i += 1 - end - end - - def create_label_table(insns) - pc = 0 - labels = {} - insns.each do |e| - if e.is_a?(Symbol) - labels[e] = pc - else - pc += 1 - end - end - labels - end - - def setup_insns(insns, labels, file_info) - ninsns = [] - insns.each do |e| - case e - when Symbol # label or trace - nil - when Insn - operands = (INSN_TABLE[e.insn] || []).zip(e.operands).map do |type, operand| - case type - when "ISEQ" - operand && ISeq.new(operand, file_info) - when "lindex_t", "rb_num_t", "VALUE", "ID", "GENTRY", "CALL_DATA" - operand - when "OFFSET" - labels[operand] || raise("unknown label: #{ operand }") - when "IVC", "ISE" - raise unless operand.is_a?(Integer) - :_cache_operand - else - raise "unknown operand type: #{ type }" - end - end - - if e.code_range && should_collect_defs(e.insn) - definition = Utils::MutableSet.new - file_info.definition_table[e.code_range] = definition - end - - ninsns << Insn.new(e.insn, operands, e.lineno, e.code_range, definition) - else - raise "unknown iseq entry: #{ e }" - end - end - ninsns - end - - def should_collect_defs(insn_kind) - case insn_kind - when :send, :getinstancevariable, :getconstant - return true - else - return false - end - end - - # Collect local variable use and definition info recursively - def collect_local_variable_info(file_info, absolute_level = 0, parent_variable_tables = {}) - # e.g. - # variable_tables[abs_level][idx] = [[path, code_range]] - current_variables = [] - variable_tables = parent_variable_tables.merge({ - absolute_level => current_variables - }) - - dummy_def_range = CodeRange.new( - CodeLocation.new(@start_lineno, 0), - CodeLocation.new(@start_lineno, 1), - ) - # Fill tail elements with parameters - (@fargs_format[:lead_num] || 0).times do |offset| - current_variables[VM_ENV_DATA_SIZE + @locals.length - offset - 1] ||= Utils::MutableSet.new - current_variables[VM_ENV_DATA_SIZE + @locals.length - offset - 1] << [@path, dummy_def_range] - end - - @insns.each do |insn| - next unless insn.insn == :getlocal || insn.insn == :setlocal - - idx = insn.operands[0] - # note: level is relative value to the current level - level = insn.operands[1] - target_abs_level = absolute_level - level - variable_tables[target_abs_level] ||= {} - variable_tables[target_abs_level][idx] ||= Utils::MutableSet.new - - case insn.insn - when :setlocal - variable_tables[target_abs_level][idx] << [path, insn.code_range] - when :getlocal - file_info.definition_table[insn.code_range] = variable_tables[target_abs_level][idx] - end - end - - @insns.each do |insn| - insn.operands.each do |operand| - next unless operand.is_a?(ISeq) - operand.collect_local_variable_info( - file_info, absolute_level + 1, - variable_tables - ) - end - end - end - - def rename_insn_types - @insns.each do |insn| - case insn.insn - when :branchif - insn.insn, insn.operands = :branch, [:if] + insn.operands - when :branchunless - insn.insn, insn.operands = :branch, [:unless] + insn.operands - when :branchnil - insn.insn, insn.operands = :branch, [:nil] + insn.operands - when :getblockparam, :getblockparamproxy - insn.insn = :getlocal - end - end - end - - # Unify some instructions for flow-sensitive analysis - def unify_instructions - # This method rewrites instructions to enable flow-sensitive analysis. - # - # Consider `if x; ...; else; ... end`. - # When the variable `x` is of type "Integer | nil", - # we want to make sure that `x` is "Integer" in then clause. - # So, we need to split the environment to two ones: - # one is that `x` is of type "Integer", and the other is that - # `x` is type "nil". - # - # However, `if x` is compiled to "getlocal; branch". - # TypeProf evaluates them as follows: - # - # * "getlocal" pushes the value of `x` to the stack, amd - # * "branch" checks the value on the top of the stack - # - # TypeProf does not keep where the value comes from, so - # it is difficult to split the environment when evaluating "branch". - # - # This method rewrites "getlocal; branch" to "nop; getlocal_branch". - # The two instructions are unified to "getlocal_branch" instruction, - # so TypeProf can split the environment. - # - # This is a very fragile appoach because it highly depends on the compiler of Ruby. - - # gather branch targets - # TODO: catch_table should be also considered - branch_targets = {} - @insns.each do |insn| - case insn.insn - when :branch - branch_targets[insn.operands[1]] = true - when :jump - branch_targets[insn.operands[0]] = true - end - end - - # flow-sensitive analysis for `case var; when A; when B; when C; end` - # find a pattern: getlocal, (dup, putobject(true), getconstant(class name), checkmatch, branch)* for ..Ruby 3.0 - # find a pattern: getlocal, (putobject(true), getconstant(class name), top(1), send(===), branch)* for Ruby 3.1.. - case_branch_list = [] - if CASE_WHEN_CHECKMATCH - (@insns.size - 1).times do |i| - insn = @insns[i] - next unless insn.insn == :getlocal && insn.operands[1] == 0 - getlocal_operands = insn.operands - nops = [i] - new_insns = [] - j = i + 1 - while true - case @insns[j].insn - when :dup - break unless @insns[j + 1].check?(:putnil, []) - break unless @insns[j + 2].check?(:putobject, [true]) - break unless @insns[j + 3].check?(:getconstant) # TODO: support A::B::C - break unless @insns[j + 4].check?(:checkmatch, [2]) - break unless @insns[j + 5].check?(:branch) - target_pc = @insns[j + 5].operands[1] - break unless @insns[target_pc].check?(:pop, []) - nops << j << (j + 4) << target_pc - branch_operands = @insns[j + 5][1] - new_insns << [j + 5, Insn.new(:getlocal_checkmatch_branch, [getlocal_operands, branch_operands])] - j += 6 - when :pop - nops << j - case_branch_list << [nops, new_insns] - break - else - break - end - end - end - else - (@insns.size - 1).times do |i| - insn = @insns[i] - next unless insn.insn == :getlocal && insn.operands[1] == 0 - getlocal_operands = insn.operands - nops = [] - new_insns = [] - j = i + 1 - while true - insn = @insns[j] - if insn.check?(:putnil, []) - break unless @insns[j + 1].check?(:putobject, [true]) - break unless @insns[j + 2].check?(:getconstant) # TODO: support A::B::C - break unless @insns[j + 3].check?(:topn, [1]) - break unless @insns[j + 4].check?(:send) && @insns[j + 4].operands[0].slice(:mid, :flag, :orig_argc) == {:mid=>:===, :flag=>20, :orig_argc=>1} - break unless @insns[j + 5].check?(:branch) - target_pc = @insns[j + 5].operands[1] - break unless @insns[target_pc].check?(:pop, []) - nops << (j + 4) #<< target_pc - send_operands = @insns[j + 4][1] - branch_operands = @insns[j + 5][1] - new_insns << [j + 5, Insn.new(:arg_getlocal_send_branch, [getlocal_operands, send_operands, branch_operands])] - j += 6 - elsif insn.check?(:pop, []) - #nops << j - case_branch_list << [nops, new_insns] - break - else - break - end - end - end - end - case_branch_list.each do |nops, new_insns| - nops.each {|i| @insns[i] = Insn.new(:nop, []) } - new_insns.each {|i, insn| @insns[i] = insn } - end - - # find a pattern: getlocal(recv), ..., send (is_a?, respond_to?), branch - recv_getlocal_send_branch_list = [] - (@insns.size - 1).times do |i| - insn = @insns[i] - if insn.insn == :getlocal && insn.operands[1] == 0 - j = i + 1 - sp = 1 - while @insns[j] - sp = check_send_branch(sp, j) - if sp == :match - recv_getlocal_send_branch_list << [i, j] - break - end - break if !sp - j += 1 - end - end - end - recv_getlocal_send_branch_list.each do |i, j| - next if (i + 1 .. j + 1).any? {|i| branch_targets[i] } - getlocal_operands = @insns[i].operands - send_operands = @insns[j].operands - branch_operands = @insns[j + 1].operands - @insns[j] = Insn.new(:nop, []) - @insns[j + 1] = Insn.new(:recv_getlocal_send_branch, [getlocal_operands, send_operands, branch_operands]) - end - - # find a pattern: getlocal, send (===), branch - arg_getlocal_send_branch_list = [] - (@insns.size - 1).times do |i| - insn1 = @insns[i] - next unless insn1.insn == :getlocal && insn1.operands[1] == 0 - insn2 = @insns[i + 1] - next unless insn2.insn == :send - send_operands = insn2.operands[0] - next unless send_operands[:flag] == 16 && send_operands[:orig_argc] == 1 - insn3 = @insns[i + 2] - next unless insn3.insn == :branch - arg_getlocal_send_branch_list << i - end - arg_getlocal_send_branch_list.each do |i| - next if (i .. i + 2).any? {|i| branch_targets[i] } - getlocal_operands = @insns[i].operands - send_operands = @insns[i + 1].operands - branch_operands = @insns[i + 2].operands - @insns[i + 1] = Insn.new(:nop, []) - @insns[i + 2] = Insn.new(:arg_getlocal_send_branch, [getlocal_operands, send_operands, branch_operands]) - end - - # find a pattern: send (block_given?), branch - send_branch_list = [] - (@insns.size - 1).times do |i| - insn = @insns[i] - if insn.insn == :send - insn = @insns[i + 1] - if insn.insn == :branch - send_branch_list << i - end - end - end - send_branch_list.each do |i| - next if branch_targets[i + 1] - send_operands = @insns[i].operands - branch_operands = @insns[i + 1].operands - @insns[i] = Insn.new(:nop, []) - @insns[i + 1] = Insn.new(:send_branch, [send_operands, branch_operands]) - end - - # find a pattern: getlocal, dup, branch - (@insns.size - 2).times do |i| - next if branch_targets[i + 1] || branch_targets[i + 2] - insn0 = @insns[i] - insn1 = @insns[i + 1] - insn2 = @insns[i + 2] - if insn0.insn == :getlocal && insn1.insn == :dup && insn2.insn == :branch && insn0.operands[1] == 0 - getlocal_operands = insn0.operands - dup_operands = insn1.operands - branch_operands = insn2.operands - @insns[i ] = Insn.new(:nop, []) - @insns[i + 1] = Insn.new(:nop, []) - @insns[i + 2] = Insn.new(:getlocal_dup_branch, [getlocal_operands, dup_operands, branch_operands]) - end - end - - # find a pattern: dup, setlocal, branch - (@insns.size - 2).times do |i| - next if branch_targets[i + 1] || branch_targets[i + 2] - insn0 = @insns[i] - insn1 = @insns[i + 1] - insn2 = @insns[i + 2] - if insn0.insn == :dup && insn1.insn == :setlocal && insn2.insn == :branch && insn1.operands[1] == 0 - dup_operands = insn0.operands - setlocal_operands = insn1.operands - branch_operands = insn2.operands - @insns[i ] = Insn.new(:nop, []) - @insns[i + 1] = Insn.new(:nop, []) - @insns[i + 2] = Insn.new(:dup_setlocal_branch, [dup_operands, setlocal_operands, branch_operands]) - end - end - - # find a pattern: dup, branch - (@insns.size - 1).times do |i| - next if branch_targets[i + 1] - insn0 = @insns[i] - insn1 = @insns[i + 1] - if insn0.insn == :dup && insn1.insn == :branch - dup_operands = insn0.operands - branch_operands = insn1.operands - @insns[i ] = Insn.new(:nop, []) - @insns[i + 1] = Insn.new(:dup_branch, [dup_operands, branch_operands]) - end - end - - # find a pattern: getlocal, branch - (@insns.size - 1).times do |i| - next if branch_targets[i + 1] - insn0 = @insns[i] - insn1 = @insns[i + 1] - if insn0.insn == :getlocal && insn0.operands[1] == 0 && insn1.insn == :branch - getlocal_operands = insn0.operands - branch_operands = insn1.operands - @insns[i ] = Insn.new(:nop, []) - @insns[i + 1] = Insn.new(:getlocal_branch, [getlocal_operands, branch_operands]) - end - end - end - - def check_send_branch(sp, j) - insn = @insns[j] - operands = insn.operands - - case insn.insn - when :putspecialobject, :putnil, :putobject, :duparray, :putstring, - :putself - sp += 1 - when :newarray, :newarraykwsplat, :newhash, :concatstrings - len, = operands - sp =- len - return nil if sp <= 0 - sp += 1 - when :newhashfromarray - raise NotImplementedError, "newhashfromarray" - when :newrange, :tostring, :objtostring, :anytostring - sp -= 2 - return nil if sp <= 0 - sp += 1 - when :freezestring - # XXX: should leverage this information? - when :toregexp - _regexp_opt, len = operands - sp -= len - return nil if sp <= 0 - sp += 1 - when :intern - sp -= 1 - return nil if sp <= 0 - sp += 1 - when :definemethod, :definesmethod - when :defineclass - sp -= 2 - when :send, :invokesuper - opt, = operands - _flags = opt[:flag] - _mid = opt[:mid] - kw_arg = opt[:kw_arg] - argc = opt[:orig_argc] - argc += 1 # receiver - argc += kw_arg.size if kw_arg - sp -= argc - return :match if insn.insn == :send && sp == 0 && @insns[j + 1].insn == :branch - sp += 1 - when :arg_getlocal_send_branch - return # not implemented - when :invokeblock - opt, = operands - sp -= opt[:orig_argc] - return nil if sp <= 0 - sp += 1 - when :invokebuiltin - raise NotImplementedError - when :leave, :throw - return - when :once - return # not implemented - when :branch, :jump - return # not implemented - when :setinstancevariable, :setclassvariable, :setglobal - sp -= 1 - when :setlocal, :setblockparam - return # conservative - when :getinstancevariable, :getclassvariable, :getglobal, - :getlocal, :getblockparam, :getblockparamproxy, :getlocal_checkmatch_branch - sp += 1 - when :getconstant - sp -= 2 - return nil if sp <= 0 - sp += 1 - when :setconstant - sp -= 2 - when :getspecial - sp += 1 - when :setspecial - # flip-flop - raise NotImplementedError, "setspecial" - when :dup - sp += 1 - when :duphash - sp += 1 - when :dupn - n, = operands - sp += n - when :pop - sp -= 1 - when :swap - sp -= 2 - return nil if sp <= 0 - sp += 2 - when :reverse - n, = operands - sp -= n - return nil if sp <= 0 - sp += n - when :defined - sp -= 1 - return nil if sp <= 0 - sp += 1 - when :checkmatch - sp -= 2 - return nil if sp <= 0 - sp += 1 - when :checkkeyword - sp += 1 - when :adjuststack - n, = operands - sp -= n - when :nop - when :setn - return nil # not implemented - when :topn - sp += 1 - when :splatarray - sp -= 1 - return nil if sp <= 0 - sp += 1 - when :expandarray - num, flag = operands - splat = flag & 1 == 1 - sp -= 1 - return nil if sp <= 0 - sp += num + (splat ? 1 : 0) - when :concatarray - sp -= 2 - return nil if sp <= 0 - sp += 1 - when :checktype - sp -= 1 - return nil if sp <= 0 - sp += 1 - else - raise "Unknown insn: #{ insn }" - end - - return nil if sp <= 0 - sp - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/lsp.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/lsp.rb deleted file mode 100644 index 0c892466cbf6..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/lsp.rb +++ /dev/null @@ -1,884 +0,0 @@ -require "socket" -require "json" -require "uri" - -module TypeProf - def self.start_lsp_server(config) - if config.lsp_options[:stdio] - reader = LSP::Reader.new($stdin) - writer = LSP::Writer.new($stdout) - # pipe all builtin print output to stderr to avoid conflicting with lsp - $stdout = $stderr - TypeProf::LSP::Server.new(config, reader, writer).run - else - Socket.tcp_server_sockets("localhost", config.lsp_options[:port]) do |servs| - serv = servs[0].local_address - $stdout << JSON.generate({ - host: serv.ip_address, - port: serv.ip_port, - pid: $$, - }) - $stdout.flush - - $stdout = $stderr - - Socket.accept_loop(servs) do |sock| - sock.set_encoding("UTF-8") - begin - reader = LSP::Reader.new(sock) - writer = LSP::Writer.new(sock) - TypeProf::LSP::Server.new(config, reader, writer).run - ensure - sock.close - end - exit - end - end - end - end - - module LSP - CompletionSession = Struct.new(:results, :row, :start_col_offset) - class CompletionSession - def reusable?(other_row, other_start_col_offset) - other_row == self.row && other_start_col_offset == self.start_col_offset - end - end - - class Text - class AnalysisToken < Utils::CancelToken - def initialize - @timer = Utils::TimerCancelToken.new(1) - @cancelled = false - end - - def cancel - @cancelled = true - end - - def cancelled? - @timer.cancelled? || @cancelled - end - end - - def initialize(server, uri, text, version) - @server = server - @uri = uri - @text = text - @version = version - @sigs = nil - - @last_analysis_cancel_token = nil - @analysis_queue = Queue.new - @analysis_thread = Thread.new do - loop do - work = @analysis_queue.pop - begin - work.call - rescue Exception - puts "Rescued exception:" - puts $!.full_message - puts - end - end - end - - # analyze synchronously to respond the first codeLens request - res, def_table, caller_table = self.analyze(uri, text) - on_text_changed_analysis(res, def_table, caller_table) - end - - attr_reader :text, :version, :sigs, :caller_table - attr_accessor :definition_table - - def lines - @text.lines - end - - def apply_changes(changes, version) - @definition_table = nil - text = @text.empty? ? [] : @text.lines - changes.each do |change| - case change - in { - range: { - start: { line: start_row, character: start_col }, - end: { line: end_row , character: end_col } - }, - text: change_text, - } - else - raise - end - text << "" if start_row == text.size - text << "" if end_row == text.size - if start_row == end_row - text[start_row][start_col...end_col] = change_text - else - text[start_row][start_col..] = "" - text[end_row][...end_col] = "" - change_text = change_text.lines - case change_text.size - when 0 - text[start_row] += text[end_row] - text[start_row + 1 .. end_row] = [] - when 1 - text[start_row] += change_text.first + text[end_row] - text[start_row + 1 .. end_row] = [] - else - text[start_row] += change_text.shift - text[end_row].prepend(change_text.pop) - text[start_row + 1 ... end_row - 1] = change_text - end - end - end - @text = text.join - @version = version - - on_text_changed - end - - def new_code_completion_session(row, start_offset, end_offset) - lines = @text.lines - lines[row][start_offset, end_offset] = ".__typeprof_lsp_completion" - tmp_text = lines.join - res, = analyze(@uri, tmp_text) - if res && res[:completion] - results = res[:completion].keys.map do |name| - { - label: name, - kind: 2, # Method - } - end - return CompletionSession.new(results, row, start_offset) - else - nil - end - end - - def code_complete(loc, trigger_kind) - case loc - in { line: row, character: col } - end - unless row < @text.lines.length && col >= 1 && @text.lines[row][0, col] =~ /\.\w*$/ - return nil - end - start_offset = $~.begin(0) - end_offset = $&.size - - case trigger_kind - when LSP::CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS - unless @current_completion_session&.reusable?(row, start_offset) - puts "no reusable completion session but got TRIGGER_FOR_INCOMPLETE_COMPLETIONS" - @current_completion_session = new_code_completion_session(row, start_offset, end_offset) - end - return @current_completion_session.results - else - @current_completion_session = new_code_completion_session(row, start_offset, end_offset) - return @current_completion_session&.results - end - end - - private def locate_arg_index_in_signature_help(node, loc, sig_help) - case node.type - when :FCALL - _mid, args_node = node.children - when :CALL - _recv, _mid, args_node = node.children - end - - idx = 0 - - if args_node - arg_nodes = args_node.children.compact - - arg_indexes = {} - hash = arg_nodes.pop if arg_nodes.last&.type == :HASH - - arg_nodes.each_with_index do |node, i| - # Ingore arguments after rest argument - break if node.type == :LIST || node.type == :ARGSCAT - - arg_indexes[i] = ISeq.code_range_from_node(node) - end - - # Handle keyword arguments - if hash - hash.children.last.children.compact.each_slice(2) do |node1, node2| - # key: expression - # ^^^^ ^^^^^^^^^^ - # node1 node2 - key = node1.children.first - arg_indexes[key] = - CodeRange.new( - CodeLocation.new(node1.first_lineno, node1.first_lineno), - CodeLocation.new(node2.last_lineno, node2.last_lineno), - ) - end - end - - if arg_indexes.size >= 1 && arg_indexes.values.last.last < loc - # There is the cursor after the last argument: "foo(111, 222,|)" - idx = arg_indexes.size - 1 - prev_cr = arg_indexes.values.last - if prev_cr.last.lineno == loc.lineno - line = @text.lines[prev_cr.last.lineno - 1] - idx += 1 if line[prev_cr.last.column..loc.column].include?(",") - end - else - # There is the cursor within any argument: "foo(111,|222)" or foo(111, 22|2)" - prev_cr = nil - arg_indexes.each do |i, cr| - idx = sig_help.keys.index(i) - if loc < cr.first - break if !prev_cr || prev_cr.last.lineno != loc.lineno - line = @text.lines[prev_cr.last.lineno - 1] - idx -= 1 unless line[prev_cr.last.column..loc.column].include?(",") - break - end - break if loc <= cr.last - prev_cr = cr - end - end - end - - idx - end - - def signature_help(loc, trigger_kind) - loc = CodeLocation.from_lsp(loc) - - res, = analyze(@uri, @text, signature_help_loc: loc) - - if res - res[:signature_help].filter_map do |sig_str, sig_help, node_id| - node = ISeq.find_node_by_id(@text, node_id) - if node && ISeq.code_range_from_node(node).contain_loc?(loc) - idx = locate_arg_index_in_signature_help(node, loc, sig_help) - - { - label: sig_str, - parameters: sig_help.values.map do |r| - { - label: [r.begin, r.end], - } - end, - activeParameter: idx, - } - end - end - else - nil - end - end - - def analyze(uri, text, cancel_token: nil, signature_help_loc: nil) - config = @server.typeprof_config.dup - path = URI(uri).path - config.rb_files = [[path, text]] - config.rbs_files = ["typeprof.rbs"] # XXX - config.verbose = 0 - config.max_sec = 1 - config.options[:show_errors] = true - config.options[:show_indicator] = false - config.options[:lsp] = true - config.options[:signature_help_loc] = [path, signature_help_loc] if signature_help_loc - - TypeProf.analyze(config, cancel_token) - rescue SyntaxError - end - - def push_analysis_queue(&work) - @analysis_queue.push(work) - end - - def on_text_changed - cancel_token = AnalysisToken.new - @last_analysis_cancel_token&.cancel - @last_analysis_cancel_token = cancel_token - - uri = @uri - text = @text - self.push_analysis_queue do - if cancel_token.cancelled? - next - end - res, def_table, caller_table = self.analyze(uri, text, cancel_token: cancel_token) - unless cancel_token.cancelled? - on_text_changed_analysis(res, def_table, caller_table) - end - end - end - - def on_text_changed_analysis(res, definition_table, caller_table) - @definition_table = definition_table - @caller_table = caller_table - return unless res - - @sigs = [] - res[:sigs].each do |file, lineno, sig_str, rbs_code_range, class_kind, class_name| - uri0 = "file://" + file - if @uri == uri0 - command = { title: sig_str } - if rbs_code_range - command[:command] = "typeprof.jumpToRBS" - command[:arguments] = [uri0, { line: lineno - 1, character: 0 }, @server.root_uri + "/" + rbs_code_range[0], rbs_code_range[1].to_lsp] - else - command[:command] = "typeprof.createPrototypeRBS" - command[:arguments] = [class_kind, class_name, sig_str] - end - @sigs << { - range: { - start: { line: lineno - 1, character: 0 }, - end: { line: lineno - 1, character: 1 }, - }, - command: command, - } - end - end - - diagnostics = {} - res[:errors]&.each do |(file, code_range), msg| - next unless file and code_range - uri0 = "file://" + file - diagnostics[uri0] ||= [] - diagnostics[uri0] << { - range: code_range.to_lsp, - severity: 1, - source: "TypeProf", - message: msg, - } - end - - @server.send_request("workspace/codeLens/refresh") - - @server.send_notification( - "textDocument/publishDiagnostics", - { - uri: @uri, - version: version, - diagnostics: diagnostics[@uri] || [], - } - ) - end - end - - class Message - def initialize(server, json) - @server = server - @id = json[:id] - @method = json[:method] - @params = json[:params] - end - - def run - p [:ignored, @method] - end - - def respond(result) - raise "do not respond to notification" if @id == nil - @server.send_response(id: @id, result: result) - end - - def respond_error(error) - raise "do not respond to notification" if @id == nil - @server.send_response(id: @id, error: error) - end - - Classes = [] - def self.inherited(klass) - Classes << klass - end - - Table = Hash.new(Message) - def self.build_table - Classes.each {|klass| Table[klass::METHOD] = klass } - end - - def self.find(method) - Table[method] - end - end - - module ErrorCodes - ParseError = -32700 - InvalidRequest = -32600 - MethodNotFound = -32601 - InvalidParams = -32602 - InternalError = -32603 - end - - class Message::Initialize < Message - METHOD = "initialize" - def run - @server.root_uri = @params[:rootUri] - pwd = Dir.pwd - @params[:workspaceFolders]&.each do |folder| - folder => { uri:, } - if pwd == URI(uri).path - @server.root_uri = uri - end - end - - respond( - capabilities: { - textDocumentSync: { - openClose: true, - change: 2, # Incremental - }, - completionProvider: { - triggerCharacters: ["."], - }, - signatureHelpProvider: { - triggerCharacters: ["(", ","], - }, - #codeActionProvider: { - # codeActionKinds: ["quickfix", "refactor"], - # resolveProvider: false, - #}, - codeLensProvider: { - resolveProvider: true, - }, - executeCommandProvider: { - commands: [ - "typeprof.createPrototypeRBS", - "typeprof.enableSignature", - "typeprof.disableSignature", - ], - }, - definitionProvider: true, - typeDefinitionProvider: true, - referencesProvider: true, - }, - serverInfo: { - name: "typeprof", - version: "0.0.0", - }, - ) - - puts "TypeProf for IDE is started successfully" - end - end - - class Message::Initialized < Message - METHOD = "initialized" - def run - end - end - - class Message::Shutdown < Message - METHOD = "shutdown" - def run - respond(nil) - end - end - - class Message::Exit < Message - METHOD = "exit" - def run - exit - end - end - - module Message::Workspace - end - - class Message::Workspace::DidChangeWatchedFiles < Message - METHOD = "workspace/didChangeWatchedFiles" - def run - #p "workspace/didChangeWatchedFiles" - #pp @params - end - end - - class Message::Workspace::ExecuteCommand < Message - METHOD = "workspace/executeCommand" - def run - case @params[:command] - when "typeprof.enableSignature" - @server.signature_enabled = true - @server.send_request("workspace/codeLens/refresh") - when "typeprof.disableSignature" - @server.signature_enabled = false - @server.send_request("workspace/codeLens/refresh") - when "typeprof.createPrototypeRBS" - class_kind, class_name, sig_str = @params[:arguments] - code_range = - CodeRange.new( - CodeLocation.new(1, 0), - CodeLocation.new(1, 0), - ) - text = [] - text << "#{ class_kind } #{ class_name.join("::") }\n" - text << " #{ sig_str }\n" - text << "end\n\n" - text = text.join - @server.send_request( - "workspace/applyEdit", - edit: { - changes: { - @server.root_uri + "/typeprof.rbs" => [ - { - range: code_range.to_lsp, - newText: text, - } - ], - }, - }, - ) do |res| - code_range = - CodeRange.new( - CodeLocation.new(1, 0), - CodeLocation.new(3, 3), # 3 = "end".size - ) - @server.send_request( - "window/showDocument", - uri: @server.root_uri + "/typeprof.rbs", - takeFocus: true, - selection: code_range.to_lsp, - ) - end - respond(nil) - else - respond_error( - code: ErrorCodes::InvalidRequest, - message: "Unknown command: #{ @params[:command] }", - ) - end - end - end - - module Message::TextDocument - end - - class Message::TextDocument::DidOpen < Message - METHOD = "textDocument/didOpen" - def run - case @params - in { textDocument: { uri:, version:, text: } } - else - raise - end - if uri.start_with?(@server.root_uri) - @server.open_texts[uri] = Text.new(@server, uri, text, version) - end - end - end - - class Message::TextDocument::DidChange < Message - METHOD = "textDocument/didChange" - def run - case @params - in { textDocument: { uri:, version: }, contentChanges: changes } - else - raise - end - @server.open_texts[uri]&.apply_changes(changes, version) - end - - def cancel - puts "cancel" - end - end - - class Message::TextDocument::DidClose < Message - METHOD = "textDocument/didClose" - def run - case @params - in { textDocument: { uri: } } - else - raise - end - @server.open_texts.delete(uri) - end - end - - class Message::TextDocument::Definition < Message - METHOD = "textDocument/definition" - def run - case @params - in { - textDocument: { uri:, }, - position: loc, - } - else - raise - end - - definition_table = @server.open_texts[uri]&.definition_table - code_locations = definition_table[CodeLocation.from_lsp(loc)] if definition_table - if code_locations - respond( - code_locations.map do |path, code_range| - { - uri: "file://" + path, - range: code_range.to_lsp, - } - end - ) - else - respond(nil) - end - end - end - - class Message::TextDocument::TypeDefinition < Message - METHOD = "textDocument/typeDefinition" - def run - respond(nil) - # jump example - #respond( - # uri: "file:///path/to/typeprof/vscode/sandbox/test.rbs", - # range: { - # start: { line: 1, character: 4 }, - # end: { line: 1, character: 7 }, - # }, - #) - end - end - - class Message::TextDocument::References < Message - METHOD = "textDocument/references" - def run - case @params - in { - textDocument: { uri:, }, - position: loc, - } - else - raise - end - - caller_table = @server.open_texts[uri]&.caller_table - code_locations = caller_table[CodeLocation.from_lsp(loc)] if caller_table - if code_locations - respond( - code_locations.map do |path, code_range| - { - uri: "file://" + path, - range: code_range.to_lsp, - } - end - ) - else - respond(nil) - end - end - end - - module CompletionTriggerKind - INVOKED = 1 - TRIGGER_CHARACTER = 2 - TRIGGER_FOR_INCOMPLETE_COMPLETIONS = 3 - end - - class Message::TextDocument::Completion < Message - METHOD = "textDocument/completion" - def run - case @params - in { - textDocument: { uri:, }, - position: loc, - context: { - triggerKind: trigger_kind - }, - } - in { - textDocument: { uri:, }, - position: loc, - } - trigger_kind = 1 - else - raise - end - - items = @server.open_texts[uri]&.code_complete(loc, trigger_kind) - - if items - respond( - { - isIncomplete: true, - items: items - } - ) - else - respond(nil) - end - end - end - - class Message::TextDocument::SignatureHelp < Message - METHOD = "textDocument/signatureHelp" - def run - case @params - in { - textDocument: { uri:, }, - position: loc, - context: { - triggerKind: trigger_kind - }, - } - in { - textDocument: { uri:, }, - position: loc, - } - trigger_kind = 1 - else - raise - end - - items = @server.open_texts[uri]&.signature_help(loc, trigger_kind) - - if items - respond({ - signatures: items - }) - else - respond(nil) - end - end - end - - class Message::TextDocument::CodeLens < Message - METHOD = "textDocument/codeLens" - def run - case @params - in { textDocument: { uri: } } - else - raise - end - - text = @server.open_texts[uri] - if text && @server.signature_enabled - # enqueue in the analysis queue because codeLens is order sensitive - text.push_analysis_queue do - respond(text.sigs) - end - else - respond(nil) - end - end - end - - class Message::CancelRequest < Message - METHOD = "$/cancelRequest" - def run - req = @server.running_requests_from_client[@params[:id]] - #p [:cancel, @params[:id]] - req.cancel if req.respond_to?(:cancel) - end - end - - Message.build_table - - class Reader - class ProtocolError < StandardError - end - - def initialize(io) - @io = io - end - - def read - while line = @io.gets - line2 = @io.gets - if line =~ /\AContent-length: (\d+)\r\n\z/i && line2 == "\r\n" - len = $1.to_i - json = JSON.parse(@io.read(len), symbolize_names: true) - yield json - else - raise ProtocolError, "LSP broken header" - end - end - end - end - - class Writer - def initialize(io) - @io = io - end - - def write(**json) - json = JSON.generate(json.merge(jsonrpc: "2.0")) - @io << "Content-Length: #{ json.bytesize }\r\n\r\n" << json - @io.flush - end - - module ErrorCodes - ParseError = -32700 - InvalidRequest = -32600 - MethodNotFound = -32601 - InvalidParams = -32602 - InternalError = -32603 - end - end - - module Helpers - def pos(line, character) - { line: line, character: character } - end - - def range(s, e) - { start: s, end: e } - end - end - - class Server - class Exit < StandardError; end - - include Helpers - - def initialize(config, reader, writer) - @typeprof_config = config - @reader = reader - @writer = writer - @tx_mutex = Mutex.new - @request_id = 0 - @running_requests_from_client = {} - @running_requests_from_server = {} - @open_texts = {} - @sigs = {} # tmp - @signature_enabled = true - end - - attr_reader :typeprof_config, :open_texts, :sigs, :running_requests_from_client - attr_accessor :root_uri, :signature_enabled - - def run - @reader.read do |json| - if json[:method] - # request or notification - msg = Message.find(json[:method]).new(self, json) - @running_requests_from_client[json[:id]] = msg if json[:id] - msg.run - else - callback = @running_requests_from_server.delete(json[:id]) - callback&.call(json[:params]) - end - end - rescue Exit - end - - def send_response(**msg) - @running_requests_from_client.delete(msg[:id]) - exclusive_write(**msg) - end - - def send_notification(method, params = nil) - exclusive_write(method: method, params: params) - end - - def send_request(method, **params, &blk) - id = @request_id += 1 - @running_requests_from_server[id] = blk - exclusive_write(id: id, method: method, params: params) - end - - def exclusive_write(**json) - @tx_mutex.synchronize do - @writer.write(**json) - end - end - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/method.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/method.rb deleted file mode 100644 index 18e2686a4912..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/method.rb +++ /dev/null @@ -1,344 +0,0 @@ -module TypeProf - class MethodDef - attr_accessor :pub_meth - - include Utils::StructuralEquality - end - - class ISeqMethodDef < MethodDef - def initialize(iseq, cref, outer_ep, pub_meth) - @iseq = iseq - raise if iseq.nil? - @cref = cref - @outer_ep = outer_ep - @pub_meth = pub_meth - end - - attr_reader :iseq - - def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn) - recv = recv.base_type while recv.respond_to?(:base_type) - recv = scratch.globalize_type(recv, caller_env, caller_ep) - aargs = scratch.globalize_type(aargs, caller_env, caller_ep) - - locals = [Type.nil] * @iseq.locals.size - - blk_ty, start_pcs = aargs.setup_formal_arguments(:method, locals, @iseq.fargs_format) - if blk_ty.is_a?(String) - scratch.error(caller_ep, blk_ty) - ctn[Type.any, caller_ep, caller_env] - return - end - - nctx = Context.new(@iseq, @cref, mid) - callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep) - nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({})) - alloc_site = AllocationSite.new(callee_ep) - locals.each_with_index do |ty, i| - alloc_site2 = alloc_site.add_id(i) - # nenv is top-level, so it is okay to call Type#localize directly - nenv, ty = ty.localize(nenv, alloc_site2, Config.current.options[:type_depth_limit]) - nenv = nenv.local_update(i, ty) - end - - start_pcs.each do |start_pc| - scratch.merge_env(ExecutionPoint.new(nctx, start_pc, @outer_ep), nenv) - end - - scratch.add_iseq_method_call!(self, nctx) - scratch.add_callsite!(nctx, caller_ep, caller_env, &ctn) - end - - def do_check_send(msig, recv, mid, ep, scratch) - klass, singleton = recv.method_dispatch_info - cur_subst = {} - direct_method = true - scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct| - direct_method &&= direct - cur_subst = Type.merge_substitution(cur_subst, subst) - end - - lead_num = @iseq.fargs_format[:lead_num] || 0 - post_num = @iseq.fargs_format[:post_num] || 0 - rest_start = @iseq.fargs_format[:rest_start] - opt = @iseq.fargs_format[:opt] || [0] - - # TODO: check keywords - if rest_start - # almost ok - else - if msig.rest_ty - scratch.error(ep, "RBS says that a rest argument is accepted, but the method definition does not accept one") - return - end - if msig.lead_tys.size + msig.post_tys.size < lead_num + post_num - scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at least %d arguments" % [msig.lead_tys.size + msig.post_tys.size, lead_num + post_num]) - return - end - if msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size > lead_num + opt.size - 1 + post_num - scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at most %d arguments" % [msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size, lead_num + opt.size - 1 + post_num]) - return - end - end - - lead_num = @iseq.fargs_format[:lead_num] || 0 - post_start = @iseq.fargs_format[:post_start] - kw_start = @iseq.fargs_format[:kwbits] - keyword = @iseq.fargs_format[:keyword] - kw_start -= keyword.size if kw_start - kw_rest = @iseq.fargs_format[:kwrest] - block_start = @iseq.fargs_format[:block_start] - - # XXX: need to check .rbs msig and .rb fargs - - ctx = Context.new(@iseq, @cref, mid) - callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep) - - locals = [Type.nil] * @iseq.locals.size - nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({})) - alloc_site = AllocationSite.new(callee_ep) - idx = 0 - msig.lead_tys.each_with_index do |ty, i| - alloc_site2 = alloc_site.add_id(idx += 1) - ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars - nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2) - nenv = nenv.local_update(i, ty) - end - if msig.opt_tys - msig.opt_tys.each_with_index do |ty, i| - alloc_site2 = alloc_site.add_id(idx += 1) - ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars - nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2) - nenv = nenv.local_update(lead_num + i, ty) - end - end - if msig.rest_ty - alloc_site2 = alloc_site.add_id(idx += 1) - ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary])) - ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars - nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2) - nenv = nenv.local_update(rest_start, rest_ty) - end - if msig.post_tys - msig.post_tys.each_with_index do |ty, i| - alloc_site2 = alloc_site.add_id(idx += 1) - ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars - nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2) - nenv = nenv.local_update(post_start + i, ty) - end - end - if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest - msig.kw_tys.each do |_, key, ty| - i = keyword.index {|callee_key,| callee_key == key } - unless i - # warn - next - end - alloc_site2 = alloc_site.add_id(key) - ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars - nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2) - nenv = nenv.local_update(kw_start + i, ty) - end - end - if msig.kw_rest_ty - ty = msig.kw_rest_ty - alloc_site2 = alloc_site.add_id(:**) - ty = ty.substitute(cur_subst, Config.current.options[:type_depth_limit]).remove_type_vars - nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2) - nenv = nenv.local_update(kw_rest, ty) - end - nenv = nenv.local_update(block_start, msig.blk_ty) if block_start - - opt.each do |start_pc| - scratch.merge_env(callee_ep.jump(start_pc), nenv) - end - scratch.add_executed_iseq(@iseq) - - ctx - end - end - - class AliasMethodDef < MethodDef - def initialize(orig_mid, mdef, def_ep) - @orig_mid = orig_mid - @mdef = mdef - @pub_meth = mdef.pub_meth - @def_ep = def_ep - end - - attr_reader :orig_mid, :mdef, :def_ep - - def do_send(recv, _mid, aargs, caller_ep, caller_env, scratch, &ctn) - @mdef.do_send(recv, @orig_mid, aargs, caller_ep, caller_env, scratch, &ctn) - end - - def do_check_send(msig, recv, mid, ep, scratch) - @mdef.do_check_send(msig, recv, mid, ep, scratch) - end - end - - class AttrMethodDef < MethodDef - def initialize(ivar, kind, pub_meth) - @ivar = ivar - @kind = kind # :reader | :writer - @pub_meth = pub_meth - end - - attr_reader :ivar, :kind - - def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn) - case @kind - when :reader - if aargs.lead_tys.size == 0 - scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep| - ctn[ty, caller_ep, caller_env] - end - else - ctn[Type.any, caller_ep, caller_env] - end - when :writer - if aargs.lead_tys.size == 1 - ty = aargs.lead_tys[0] - scratch.set_instance_variable(recv, @ivar, ty, caller_ep, caller_env) - ctn[ty, caller_ep, caller_env] - else - ctn[Type.any, caller_ep, caller_env] - end - end - end - end - - class ExecutedAttrMethodDef < AttrMethodDef - def initialize(ivar, kind, pub_meth, def_ep) - super(ivar, kind, pub_meth) - @def_ep = def_ep - end - - attr_reader :def_ep - end - - class TypedAttrMethodDef < AttrMethodDef - def initialize(ivar, kind, pub_meth, rbs_source) - @rbs_source = rbs_source - - super(ivar, kind, pub_meth) - end - - attr_reader :rbs_source - end - - class TypedMethodDef < MethodDef - def initialize(sig_rets, rbs_source, pub_meth) # sig_rets: Array<[MethodSignature, (return)Type]> - @sig_rets = sig_rets - @rbs_source = rbs_source - @pub_meth = pub_meth - @iseq = nil - end - - attr_reader :rbs_source, :iseq - - def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn) - recv = scratch.globalize_type(recv_orig, caller_env, caller_ep) - - klass, singleton = recv_orig.method_dispatch_info - cur_subst = {} - direct_method = true - scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct| - direct_method &&= direct - cur_subst = Type.merge_substitution(cur_subst, subst) - end - - found = false - aargs = scratch.globalize_type(aargs, caller_env, caller_ep) - @sig_rets.each do |msig, ret_ty| - ncaller_env = caller_env - #pp [mid, aargs, msig] - # XXX: support self type in msig - subst = aargs.consistent_with_method_signature?(msig) - next unless subst - - if direct_method && recv_orig.is_a?(Type::Local) - ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch) - end - - subst = Type.merge_substitution(subst, cur_subst) - # need to check self tyvar? - subst[Type::Var.new(:self)] = recv - - found = true - if aargs.blk_ty.is_a?(Type::Proc) - #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX - dummy_ctx = TypedContext.new(caller_ep, mid) - dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep) - s_recv = recv - s_recv = s_recv.base_type while s_recv.respond_to?(:base_type) - dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({})) - if msig.blk_ty.is_a?(Type::Proc) - scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn) - bsig = msig.blk_ty.block_body.msig - alloc_site = AllocationSite.new(caller_ep).add_id(self) - nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i| - ty = ty.substitute(subst, Config.current.options[:type_depth_limit]).remove_type_vars - dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i)) - ty - end - 0.upto(bsig.opt_tys.size) do |n| - naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block? - scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env| - subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty) - if subst2 - subst2 = Type.merge_substitution(subst, subst2) - if direct_method && recv_orig.is_a?(Type::Local) - ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch) - scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env } - end - ret_ty2 = ret_ty.substitute(subst2, Config.current.options[:type_depth_limit]).remove_type_vars - else - ret_ty2 = Type.any - end - # XXX: check the return type from the block - # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ??? - scratch.add_return_value!(dummy_ctx, ret_ty2) - end - # scratch.add_return_value!(dummy_ctx, ret_ty) ? - # This makes `def foo; 1.times { return "str" }; end` return Integer|String - end - else - # XXX: a block is passed to a method that does not accept block. - # Should we call the passed block with any arguments? - ret_ty = ret_ty.remove_type_vars - ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot - end - else - ret_ty = ret_ty.substitute(subst, Config.current.options[:type_depth_limit]) - ret_ty = ret_ty.remove_type_vars - ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot - end - end - - unless found - scratch.error(caller_ep, "failed to resolve overload: #{ recv.screen_name(scratch) }##{ mid }") - ctn[Type.any, caller_ep, caller_env] - end - end - - def do_match_iseq_mdef(iseq_mdef, recv, mid, env, ep, scratch) - recv = scratch.globalize_type(recv, env, ep) - @sig_rets.each do |msig, _ret_ty| - iseq_mdef.do_check_send(msig, recv, mid, ep, scratch) - end - @iseq ||= iseq_mdef.iseq - end - end - - class CustomMethodDef < MethodDef - def initialize(impl, pub_meth) - @impl = impl - @pub_meth = pub_meth - end - - def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn) - @impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn] - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/type.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/type.rb deleted file mode 100644 index 7a45951e6634..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/type.rb +++ /dev/null @@ -1,1130 +0,0 @@ -module TypeProf - class Type # or AbstractValue - include Utils::StructuralEquality - - def initialize - raise "cannot instantiate abstract type" - end - - Builtin = {} - - def globalize(_env, _visited, _depth) - self - end - - def localize(env, _alloc_site, _depth) - return env, self - end - - def limit_size(limit) - self - end - - def self.match?(ty1, ty2) - # both ty1 and ty2 should be global - # ty1 is always concrete; it should not have type variables - # ty2 might be abstract; it may have type variables - case ty2 - when Type::Var - { ty2 => ty1 } - when Type::Any - {} - when Type::Union - subst = nil - ty2.each_child_global do |ty2| - # this is very conservative to create subst: - # Type.match?( int | str, int | X) creates { X => int | str } but should be { X => str }??? - subst2 = Type.match?(ty1, ty2) - next unless subst2 - subst = Type.merge_substitution(subst, subst2) - end - subst - else - case ty1 - when Type::Var then raise "should not occur" - when Type::Any - subst = {} - ty2.each_free_type_variable do |tyvar| - subst[tyvar] = Type.any - end - subst - when Type::Union - subst = nil - ty1.each_child_global do |ty1| - subst2 = Type.match?(ty1, ty2) - next unless subst2 - subst = Type.merge_substitution(subst, subst2) - end - subst - else - if ty2.is_a?(Type::ContainerType) - # ty2 may have type variables - return nil if ty1.class != ty2.class - ty1.match?(ty2) - elsif ty1.is_a?(Type::ContainerType) - nil - else - ty1.consistent?(ty2) ? {} : nil - end - end - end - end - - def self.merge_substitution(subst1, subst2) - if subst1 - subst1 = subst1.dup - subst2.each do |tyvar, ty| - if subst1[tyvar] - subst1[tyvar] = subst1[tyvar].union(ty) - else - subst1[tyvar] = ty - end - end - subst1 - else - subst2 - end - end - - def each_child - yield self - end - - def each_child_global - yield self - end - - def each_free_type_variable - end - - def union(other) - return self if self == other # fastpath - - ty1, ty2 = self, other - - case - when ty1.is_a?(Union) - ty1_types = ty1.types - ty1_elems = ty1.elems - when ty1.is_a?(Array) || ty1.is_a?(Hash) - ty1_types = Utils::Set[] - ty1_elems = {[ty1.class, ty1.base_type] => ty1.elems} - else - ty1_types = ty1_elems = nil - end - - case - when ty2.is_a?(Union) - ty2_types = ty2.types - ty2_elems = ty2.elems - when ty2.is_a?(Array) || ty2.is_a?(Hash) - ty2_types = Utils::Set[] - ty2_elems = {[ty2.class, ty2.base_type] => ty2.elems} - else - ty2_types = ty2_elems = nil - end - - if ty1_types && ty2_types - ty = ty1_types.sum(ty2_types) - all_elems = ty1_elems.dup || {} - ty2_elems&.each do |key, elems| - all_elems[key] = union_elems(all_elems[key], elems) - end - all_elems = nil if all_elems.empty? - - Type::Union.create(ty, all_elems) - elsif ty1_types - Type::Union.create(ty1_types.add(ty2), ty1_elems) - elsif ty2_types - Type::Union.create(ty2_types.add(ty1), ty2_elems) - else - Type::Union.create(Utils::Set[ty1, ty2], nil) - end - end - - private def union_elems(e1, e2) - if e1 - if e2 - e1.union(e2) - else - e1 - end - else - e2 - end - end - - def substitute(_subst, _depth) - raise "cannot substitute abstract type: #{ self.class }" - end - - def generate_substitution - {} - end - - DummySubstitution = Object.new - def DummySubstitution.[](_) - Type.any - end - - def remove_type_vars - substitute(DummySubstitution, Config.current.options[:type_depth_limit]) - end - - def include_untyped?(_scratch) - false - end - - class Any < Type - def initialize - end - - def inspect - "Type::Any" - end - - def screen_name(scratch) - "untyped" - end - - def method_dispatch_info - nil - end - - def consistent?(_other) - raise "should not be called" - end - - def substitute(_subst, _depth) - self - end - - def include_untyped?(_scratch) - true - end - end - - class Void < Any - def inspect - "Type::Void" - end - - def screen_name(scratch) - "void" - end - end - - - class Union < Type - def self.create(tys, elems) - if tys.size == 1 && !elems - tys.each {|ty| return ty } - elsif tys.size == 0 - if elems && elems.size == 1 - (container_kind, base_type), nelems = elems.first - # container_kind = Type::Array or Type::Hash - container_kind.new(nelems, base_type) - else - new(tys, elems) - end - else - class_instances = [] - non_class_instances = [] - degenerated = false - tys.each do |ty| - if ty != Type::Instance.new(Type::Builtin[:nil]) && ty.is_a?(Type::Instance) && ty.klass.kind == :class - class_instances << ty - degenerated = true if ty.include_subclasses - else - non_class_instances << ty - end - end - if (Config.current.options[:union_width_limit] >= 2 && class_instances.size >= Config.current.options[:union_width_limit]) || (degenerated && class_instances.size >= 2) - create(Utils::Set[Instance.new_degenerate(class_instances), *non_class_instances], elems) - else - new(tys, elems) - end - end - end - - def initialize(tys, elems) - raise unless tys.is_a?(Utils::Set) - @types = tys # Set - - # invariant check - local = nil - tys.each do |ty| - raise ty.inspect unless ty.is_a?(Type) - local = true if ty.is_a?(Local) - end - raise if local && elems - - @elems = elems - raise elems.inspect if elems && !elems.is_a?(::Hash) - end - - def each_free_type_variable(&blk) - each_child_global do |ty| - ty.each_free_type_variable(&blk) - end - end - - def limit_size(limit) - return Type.any if limit <= 0 - tys = Utils::Set[] - @types.each do |ty| - tys = tys.add(ty.limit_size(limit - 1)) - end - elems = @elems&.to_h do |key, elems| - [key, elems.limit_size(limit - 1)] - end - Union.new(tys, elems) - end - - attr_reader :types, :elems - - def each_child(&blk) # local - @types.each(&blk) - raise if @elems - end - - def each_child_global(&blk) - @types.each(&blk) - @elems&.each do |(container_kind, base_type), elems| - yield container_kind.new(elems, base_type) - end - end - - def inspect - a = [] - a << "Type::Union{#{ @types.to_a.map {|ty| ty.inspect }.join(", ") }" - @elems&.each do |(container_kind, base_type), elems| - a << ", #{ container_kind.new(elems, base_type).inspect }" - end - a << "}" - a.join - end - - def screen_name(scratch) - types = @types.to_a - @elems&.each do |(container_kind, base_type), elems| - types << container_kind.new(elems, base_type) - end - if types.size == 0 - "bot" - else - types = types.to_a - optional = !!types.delete(Type::Instance.new(Type::Builtin[:nil])) - bool = false - if types.include?(Type::Instance.new(Type::Builtin[:false])) && - types.include?(Type::Instance.new(Type::Builtin[:true])) - types.delete(Type::Instance.new(Type::Builtin[:false])) - types.delete(Type::Instance.new(Type::Builtin[:true])) - bool = true - end - types.delete(Type.any) unless Config.current.options[:show_untyped] - proc_tys, types = types.partition {|ty| ty.is_a?(Proc) } - types = types.map {|ty| ty.screen_name(scratch) } - types << scratch.show_proc_signature(proc_tys) unless proc_tys.empty? - types << "bool" if bool - types = types.sort - if optional - case types.size - when 0 then "nil" - when 1 then types.first + "?" - else - "(#{ types.join (" | ") })?" - end - else - types.join (" | ") - end - end - end - - def globalize(env, visited, depth) - return Type.any if depth <= 0 - tys = Utils::Set[] - if @elems - # XXX: If @elems is non nil, the Union type should global, so calling globalize against such a type should not occur. - # However, currently, ActualArguments may contain global types for flag_args_kw_splat case. - # This should be fixed in future in ActualArguments side. See Scratch#setup_actual_arguments. - #raise - end - - elems = @elems ? @elems.dup : {} - @types.each do |ty| - ty = ty.globalize(env, visited, depth - 1) - case ty - when Type::Array, Type::Hash - key = [ty.class, ty.base_type] - elems[key] = union_elems(elems[key], ty.elems) - else - tys = tys.add(ty) - end - end - elems = nil if elems.empty? - - Type::Union.create(tys, elems) - end - - def localize(env, alloc_site, depth) - return env, Type.any if depth <= 0 - tys = @types.map do |ty| - env, ty2 = ty.localize(env, alloc_site, depth - 1) - ty2 - end - @elems&.each do |(container_kind, base_type), elems| - ty = container_kind.new(elems, base_type) - env, ty = ty.localize(env, alloc_site, depth - 1) - tys = tys.add(ty) - end - ty = Union.create(tys, nil) - return env, ty - end - - def consistent?(_other) - raise "should not be called" - end - - def substitute(subst, depth) - return Type.any if depth <= 0 - unions = [] - tys = Utils::Set[] - @types.each do |ty| - ty = ty.substitute(subst, depth - 1) - case ty - when Union - unions << ty - else - tys = tys.add(ty) - end - end - elems = @elems&.to_h do |(container_kind, base_type), elems| - [[container_kind, base_type], elems.substitute(subst, depth - 1)] - end - ty = Union.create(tys, elems) - unions.each do |ty0| - ty = ty.union(ty0) - end - ty - end - - def include_untyped?(scratch) - @types.each do |ty| - return true if ty.include_untyped?(scratch) - end - @elems&.each do |(container_kind, base_type), elems| - return true if base_type.include_untyped?(scratch) - return true if elems.include_untyped?(scratch) - end - false - end - end - - def self.any - Thread.current[:any] ||= Any.new - end - - def self.bot - Thread.current[:bot] ||= Union.new(Utils::Set[], nil) - end - - def self.bool - Thread.current[:bool] ||= Union.new(Utils::Set[ - Instance.new(Type::Builtin[:true]), - Instance.new(Type::Builtin[:false]) - ], nil) - end - - def self.nil - Thread.current[:nil] ||= Instance.new(Type::Builtin[:nil]) - end - - def self.optional(ty) - ty.union(Type.nil) - end - - class Var < Type - def initialize(name) - @name = name - end - - def screen_name(scratch) - "Var[#{ @name }]" - end - - def each_free_type_variable - yield self - end - - def substitute(subst, depth) - if subst[self] - subst[self].limit_size(depth) - else - self - end - end - - def consistent?(_other) - raise "should not be called: #{ self }" - end - - def add_subst!(ty, subst) - if subst[self] - subst[self] = subst[self].union(ty) - else - subst[self] = ty - end - true - end - end - - class Class < Type # or Module - def initialize(kind, idx, type_params, superclass, name) - @kind = kind # :class | :module - @idx = idx - @type_params = type_params - @superclass = superclass - raise if @kind == :class && !@superclass - @_name = name - end - - attr_reader :kind, :idx, :type_params, :superclass - attr_accessor :superclass_type_args - - def inspect - if @_name - "#{ @_name }@#{ @idx }" - else - "Class[#{ @idx }]" - end - end - - def screen_name(scratch) - "singleton(#{ scratch.get_class_name(self) })" - end - - def method_dispatch_info - [self, true, false] - end - - def consistent?(other) - case other - when Type::Class - ty = self - loop do - # ad-hoc - return false if !ty || !other # module - - return true if ty.idx == other.idx - return false if ty.idx == 0 # Object - ty = ty.superclass - end - when Type::Instance - return true if other.klass == Type::Builtin[:obj] || other.klass == Type::Builtin[:class] || other.klass == Type::Builtin[:module] - return false - else - false - end - end - - def substitute(_subst, _depth) - self - end - end - - class Instance < Type - def initialize(klass, include_subclasses=false) - raise unless klass - raise if klass == Type.any - raise if klass.is_a?(Type::Instance) - raise if klass.is_a?(Type::Union) - @klass = klass - @include_subclasses = include_subclasses - end - - def self.new_degenerate(instances) - klass = instances.first.klass - ancestors = [] - ancestor_idxs = {} - while klass != :__root__ - ancestor_idxs[klass] = ancestors.size - ancestors << klass - klass = klass.superclass - end - common_superclass = nil - instances[1..].each do |instance| - klass = instance.klass - while !ancestor_idxs[klass] - klass = klass.superclass - end - common_superclass = klass - ancestor_idxs[klass].times do |i| - ancestor_idxs.delete(ancestors[i]) - ancestors[i] = nil - end - end - new(common_superclass, true) - end - - attr_reader :klass, :include_subclasses - - def inspect - "I[#{ @klass.inspect }]" - end - - def screen_name(scratch) - case @klass - when Type::Builtin[:nil] then "nil" - when Type::Builtin[:true] then "true" - when Type::Builtin[:false] then "false" - else - scratch.get_class_name(@klass) + (@include_subclasses ? "" : "") - end - end - - def method_dispatch_info - [@klass, false, @include_subclasses] - end - - def consistent?(other) - case other - when Type::Instance - @klass.consistent?(other.klass) - when Type::Class - return true if @klass == Type::Builtin[:obj] || @klass == Type::Builtin[:class] || @klass == Type::Builtin[:module] - return false - else - false - end - end - - def substitute(subst, depth) - Instance.new(@klass.substitute(subst, depth)) - end - end - - # This is an internal object in MRI, so a user program cannot create this object explicitly - class ISeq < Type - def initialize(iseq) - @iseq = iseq - end - - attr_reader :iseq - - def inspect - "Type::ISeq[#{ @iseq }]" - end - - def screen_name(_scratch) - raise NotImplementedError - end - end - - class Proc < Type - def initialize(block_body, base_type) - @block_body, @base_type = block_body, base_type - end - - attr_reader :block_body, :base_type - - def consistent?(other) - case other - when Type::Proc - @block_body.consistent?(other.block_body) - else - self == other - end - end - - def method_dispatch_info - @base_type.method_dispatch_info - end - - def substitute(subst, depth) - Proc.new(@block_body.substitute(subst, depth), @base_type) - end - - def screen_name(scratch) - scratch.show_proc_signature([self]) - end - - def include_untyped?(scratch) - false # XXX: need to check the block signatures recursively - end - end - - class Symbol < Type - def initialize(sym, base_type) - @sym = sym - @base_type = base_type - end - - attr_reader :sym, :base_type - - def inspect - "Type::Symbol[#{ @sym ? @sym.inspect : "(dynamic symbol)" }, #{ @base_type.inspect }]" - end - - def consistent?(other) - case other - when Symbol - @sym == other.sym - else - @base_type.consistent?(other) - end - end - - def screen_name(scratch) - if @sym - @sym.inspect - else - @base_type.screen_name(scratch) - end - end - - def method_dispatch_info - @base_type.method_dispatch_info - end - - def substitute(_subst, _depth) - self # dummy - end - end - - # A local type - class Literal < Type - def initialize(lit, base_type) - @lit = lit - @base_type = base_type - end - - attr_reader :lit, :base_type - - def inspect - "Type::Literal[#{ @lit.inspect }, #{ @base_type.inspect }]" - end - - def screen_name(scratch) - @base_type.screen_name(scratch) + "<#{ @lit.inspect }>" - end - - def globalize(_env, _visited, _depth) - @base_type - end - - def method_dispatch_info - @base_type.method_dispatch_info - end - - def consistent?(_other) - raise "should not called" - end - end - - class HashGenerator - def initialize - @map_tys = {} - end - - attr_reader :map_tys - - def []=(k_ty, v_ty) - k_ty.each_child_global do |k_ty| - # This is a temporal hack to mitigate type explosion - k_ty = Type.any if k_ty.is_a?(Type::Array) - k_ty = Type.any if k_ty.is_a?(Type::Hash) - - if @map_tys[k_ty] - @map_tys[k_ty] = @map_tys[k_ty].union(v_ty) - else - @map_tys[k_ty] = v_ty - end - end - end - end - - def self.gen_hash(base_ty = Type::Instance.new(Type::Builtin[:hash])) - hg = HashGenerator.new - yield hg - Type::Hash.new(Type::Hash::Elements.new(hg.map_tys), base_ty) - end - - def self.guess_literal_type(obj) - case obj - when ::Symbol - Type::Symbol.new(obj, Type::Instance.new(Type::Builtin[:sym])) - when ::Integer - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:int])) - when ::Rational - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:rational])) - when ::Complex - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:complex])) - when ::Float - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:float])) - when ::Class - return Type.any if obj < Exception - case obj - when ::Object - Type::Builtin[:obj] - when ::Array - Type::Builtin[:ary] - else - raise "unknown class: #{ obj.inspect }" - end - when ::TrueClass - Type::Instance.new(Type::Builtin[:true]) - when ::FalseClass - Type::Instance.new(Type::Builtin[:false]) - when ::Array - base_ty = Type::Instance.new(Type::Builtin[:ary]) - lead_tys = obj.map {|arg| guess_literal_type(arg) } - Type::Array.new(Type::Array::Elements.new(lead_tys), base_ty) - when ::Hash - Type.gen_hash do |h| - obj.each do |k, v| - k_ty = guess_literal_type(k).globalize(nil, {}, Config.current.options[:type_depth_limit]) - v_ty = guess_literal_type(v) - h[k_ty] = v_ty - end - end - when ::String - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:str])) - when ::Regexp - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:regexp])) - when ::NilClass - Type.nil - when ::Range - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:range])) - when ::Encoding - Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:encoding])) - else - raise "unknown object: #{ obj.inspect }" - end - end - - def self.builtin_global_variable_type(var) - case var - when :$_, :$/, :$\, :$,, :$; - Type.optional(Type::Instance.new(Type::Builtin[:str])) - when :$0, :$PROGRAM_NAME - Type::Instance.new(Type::Builtin[:str]) - when :$~ - Type.optional(Type::Instance.new(Type::Builtin[:matchdata])) - when :$., :$$ - Type::Instance.new(Type::Builtin[:int]) - when :$? - Type.optional(Type::Instance.new(Type::Builtin[:int])) - when :$! - Type.optional(Type::Instance.new(Type::Builtin[:exc])) - when :$@ - str = Type::Instance.new(Type::Builtin[:str]) - base_ty = Type::Instance.new(Type::Builtin[:ary]) - Type.optional(Type::Array.new(Type::Array::Elements.new([], str), base_ty)) - when :$*, :$:, :$LOAD_PATH, :$", :$LOADED_FEATURES - str = Type::Instance.new(Type::Builtin[:str]) - base_ty = Type::Instance.new(Type::Builtin[:ary]) - Type::Array.new(Type::Array::Elements.new([], str), base_ty) - when :$< - :ARGF - when :$> - :STDOUT - when :$DEBUG - Type.bool - when :$FILENAME - Type::Instance.new(Type::Builtin[:str]) - when :$stdin - :STDIN - when :$stdout - :STDOUT - when :$stderr - :STDERR - when :$VERBOSE - Type.bool.union(Type.nil) - else - nil - end - end - end - - class Signature - include Utils::StructuralEquality - - def screen_name(iseq, scratch) - fargs_str = "(" - sig_help = {} - add_farg = -> farg, name, help: false, key: sig_help.size do - name = "`#{ name }`" if RBS::Parser::KEYWORDS.key?(name.to_s) - name = "noname" if name.is_a?(Integer) || name == :"*" - fargs_str << ", " if fargs_str != "(" - i = fargs_str.size - fargs_str << (Config.current.options[:show_parameter_names] && name ? "#{ farg } #{ name }" : farg) - sig_help[key] = (i...fargs_str.size) - end - - @lead_tys.zip(iseq ? iseq.locals : []) do |ty, name| - add_farg.call(ty.screen_name(scratch), name, help: true) - end - - @opt_tys&.zip(iseq ? iseq.locals[@lead_tys.size, @opt_tys.size] : []) do |ty, name| - add_farg.call("?" + ty.screen_name(scratch), name, help: true) - end - - if @rest_ty - if iseq - rest_index = iseq.fargs_format[:rest_start] - name = rest_index ? iseq.locals[rest_index] : nil - end - add_farg.call("*" + @rest_ty.screen_name(scratch), name) - end - - if iseq - post_start = iseq.fargs_format[:post_start] - names = post_start ? iseq.locals[post_start, @post_tys.size] : [] - end - @post_tys&.zip(names || []) do |ty, name| - add_farg.call(ty.screen_name(scratch), name) - end - - @kw_tys&.each do |req, sym, ty| - opt = req ? "" : "?" - add_farg.call("#{ opt }#{ sym }: #{ ty.screen_name(scratch) }", nil, help: true, key: sym) - end - - if @kw_rest_ty - all_val_ty = Type.bot - @kw_rest_ty.each_child_global do |ty| - if ty == Type.any - val_ty = ty - else - # ty is a Type::Hash - _key_ty, val_ty = ty.elems.squash - end - all_val_ty = all_val_ty.union(val_ty) - end - add_farg.call("**" + all_val_ty.screen_name(scratch), nil) - end - - fargs_str << ")" - - fargs_str = "" if fargs_str == "()" - - # Dirty Hack: Stop the iteration at most once! - # I'll remove this hack if RBS removes the limitation of nesting blocks - return fargs_str, sig_help if caller_locations.any? {|frame| frame.label == "show_block_signature" } - - optional = false - blks = [] - @blk_ty.each_child_global do |ty| - if ty.is_a?(Type::Proc) - blks << ty - else - # XXX: how should we handle types other than Type.nil - optional = true - end - end - if blks != [] - fargs_str << " " if fargs_str != "" - fargs_str << "?" if optional - fargs_str << scratch.show_block_signature(blks) - end - - return fargs_str, sig_help - end - end - - class MethodSignature < Signature - def initialize(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty) - @lead_tys = lead_tys - @opt_tys = opt_tys - raise unless opt_tys.is_a?(Array) - @rest_ty = rest_ty - @post_tys = post_tys - raise unless post_tys - @kw_tys = kw_tys - kw_tys.each {|a| raise if a.size != 3 } if kw_tys - @kw_rest_ty = kw_rest_ty - kw_rest_ty&.each_child_global do |ty| - raise ty.inspect if ty != Type.any && !ty.is_a?(Type::Hash) - end - @blk_ty = blk_ty - end - - def include_untyped?(scratch) - return true if @lead_tys.any? {|ty| ty.include_untyped?(scratch) } - return true if @opt_tys.any? {|ty| ty.include_untyped?(scratch) } - return true if @rest_ty&.include_untyped?(scratch) - return true if @post_tys.any? {|ty| ty.include_untyped?(scratch) } - return true if @kw_tys&.any? {|_, _, ty| ty.include_untyped?(scratch) } - return true if @kw_rest_ty&.include_untyped?(scratch) - return true if @blk_ty&.include_untyped?(scratch) - false - end - - attr_reader :lead_tys, :opt_tys, :rest_ty, :post_tys, :kw_tys, :kw_rest_ty, :blk_ty - - def substitute(subst, depth) - lead_tys = @lead_tys.map {|ty| ty.substitute(subst, depth - 1) } - opt_tys = @opt_tys.map {|ty| ty.substitute(subst, depth - 1) } - rest_ty = @rest_ty&.substitute(subst, depth - 1) - post_tys = @post_tys.map {|ty| ty.substitute(subst, depth - 1) } - kw_tys = @kw_tys.map {|req, key, ty| [req, key, ty.substitute(subst, depth - 1)] } - kw_rest_ty = @kw_rest_ty&.substitute(subst, depth - 1) - blk_ty = @blk_ty.substitute(subst, depth - 1) - MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty) - end - - def merge_as_block_arguments(other) - lead_tys1, opt_tys1, rest_ty1, post_tys1 = @lead_tys, @opt_tys, @rest_ty, @post_tys - lead_tys2, opt_tys2, rest_ty2, post_tys2 = other.lead_tys, other.opt_tys, other.rest_ty, other.post_tys - - case - when lead_tys1.size > lead_tys2.size - n = lead_tys2.size - lead_tys1, opt_tys1 = lead_tys1[0, n], lead_tys1[n..] + opt_tys1 - when lead_tys1.size < lead_tys2.size - n = lead_tys1.size - lead_tys2, opt_tys2 = lead_tys2[0, n], lead_tys2[n..] + opt_tys2 - end - case - when post_tys1.size > post_tys2.size - i = post_tys1.size - post_tys2.size - if rest_ty1 - rest_ty1 = post_tys[0, i].inject(rest_ty1) {|ty1, ty2| ty1.union(ty2) } - post_tys1 = post_tys1[i..] - else - opt_tys1, post_tys1 = opt_tys1 + post_tys1[0, i], post_tys1[i..] - end - when post_tys1.size < post_tys2.size - i = post_tys2.size - post_tys1.size - if rest_ty2 - rest_ty2 = post_tys[0, i].inject(rest_ty2) {|ty1, ty2| ty1.union(ty2) } - post_tys2 = post_tys2[i..] - else - opt_tys2, post_tys2 = opt_tys2 + post_tys2[0, i], post_tys2[i..] - end - end - - # XXX: tweak keywords too - - msig1 = MethodSignature.new(lead_tys1, opt_tys1, rest_ty1, post_tys1, @kw_tys, @kw_rest_ty, @blk_ty) - msig2 = MethodSignature.new(lead_tys2, opt_tys2, rest_ty2, post_tys2, other.kw_tys, other.kw_rest_ty, other.blk_ty) - msig1.merge(msig2) - end - - def merge(other) - raise if @lead_tys.size != other.lead_tys.size - raise if @post_tys.size != other.post_tys.size - if @kw_tys && other.kw_tys - kws1 = {} - @kw_tys.each {|req, kw, _| kws1[kw] = req } - kws2 = {} - other.kw_tys.each {|req, kw, _| kws2[kw] = req } - (kws1.keys & kws2.keys).each do |kw| - raise if !!kws1[kw] != !!kws2[kw] - end - elsif @kw_tys || other.kw_tys - (@kw_tys || other.kw_tys).each do |req,| - raise if req - end - end - lead_tys = @lead_tys.zip(other.lead_tys).map {|ty1, ty2| ty1.union(ty2) } - if @opt_tys || other.opt_tys - opt_tys = [] - [@opt_tys.size, other.opt_tys.size].max.times do |i| - ty1 = @opt_tys[i] - ty2 = other.opt_tys[i] - ty = ty1 ? ty2 ? ty1.union(ty2) : ty1 : ty2 - opt_tys << ty - end - end - if @rest_ty || other.rest_ty - if @rest_ty && other.rest_ty - rest_ty = @rest_ty.union(other.rest_ty) - else - rest_ty = @rest_ty || other.rest_ty - end - end - post_tys = @post_tys.zip(other.post_tys).map {|ty1, ty2| ty1.union(ty2) } - if @kw_tys && other.kw_tys - kws1 = {} - @kw_tys.each {|req, kw, ty| kws1[kw] = [req, ty] } - kws2 = {} - other.kw_tys.each {|req, kw, ty| kws2[kw] = [req, ty] } - kw_tys = (kws1.keys | kws2.keys).map do |kw| - req1, ty1 = kws1[kw] - _req2, ty2 = kws2[kw] - ty1 ||= Type.bot - ty2 ||= Type.bot - [!!req1, kw, ty1.union(ty2)] - end - elsif @kw_tys || other.kw_tys - kw_tys = @kw_tys || other.kw_tys - else - kw_tys = nil - end - if @kw_rest_ty || other.kw_rest_ty - if @kw_rest_ty && other.kw_rest_ty - kw_rest_ty = @kw_rest_ty.union(other.kw_rest_ty) - else - kw_rest_ty = @kw_rest_ty || other.kw_rest_ty - end - end - blk_ty = @blk_ty.union(other.blk_ty) if @blk_ty - MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty) - end - end - - class BlockSignature < Signature - def initialize(lead_tys, opt_tys, rest_ty, blk_ty) - @lead_tys = lead_tys - @opt_tys = opt_tys - @rest_ty = rest_ty - @blk_ty = blk_ty - # TODO: kw_tys - end - - attr_reader :lead_tys, :opt_tys, :rest_ty, :blk_ty - - def merge(bsig) - if @rest_ty && bsig.rest_ty - rest_ty = @rest_ty.union(bsig.rest_ty) - BlockSignature.new(@lead_tys, [], rest_ty, @blk_ty.union(bsig.blk_ty)) - elsif @rest_ty || bsig.rest_ty - rest_ty = @rest_ty || bsig.rest_ty - rest_ty = @opt_tys.inject(rest_ty, &:union) - rest_ty = bsig.opt_tys.inject(rest_ty, &:union) - - lead_tys = [] - [@lead_tys.size, bsig.lead_tys.size].max.times do |i| - ty1 = @lead_tys[i] - ty2 = bsig.lead_tys[i] - if ty1 && ty2 - lead_tys << ty1.union(ty2) - else - rest_ty = rest_ty.union(ty1 || ty2) - end - end - - BlockSignature.new(lead_tys, [], rest_ty, @blk_ty.union(bsig.blk_ty)) - else - lead_tys = [] - n = [@lead_tys.size, bsig.lead_tys.size].min - n.times do |i| - lead_tys << @lead_tys[i].union(bsig.lead_tys[i]) - end - opt_tys1 = @lead_tys[n..] + @opt_tys - opt_tys2 = bsig.lead_tys[n..] + bsig.opt_tys - opt_tys = [] - [opt_tys1.size, opt_tys2.size].max.times do |i| - if opt_tys1[i] && opt_tys2[i] - opt_tys << opt_tys1[i].union(opt_tys2[i]) - else - opt_tys << (opt_tys1[i] || opt_tys2[i]) - end - end - BlockSignature.new(lead_tys, opt_tys, nil, @blk_ty.union(bsig.blk_ty)) - end - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/utils.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/utils.rb deleted file mode 100644 index 41c169e33f7c..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/utils.rb +++ /dev/null @@ -1,212 +0,0 @@ -module TypeProf - module Utils - def self.array_update(ary, idx, elem) - idx %= ary.size - ary[0...idx] + [elem] + ary[idx+1..-1] - end - - module StructuralEquality - def self.included(klass) - klass.instance_eval do - def new(*args) - (Thread.current[:table] ||= {})[[self] + args] ||= super - end - end - end - end - - class Set - include StructuralEquality - - attr_reader :tbl - - def self.[](*values) - tbl = {} - values.each do |v| - tbl[v] = true - end - new(tbl) - end - - def initialize(tbl) - @tbl = tbl - @tbl.freeze - end - - def each(&blk) - @tbl.each_key(&blk) - end - - include Enumerable - - def sum(other) - if @tbl.size == 0 - other - elsif other.tbl.size == 0 - self - else - Set.new(@tbl.merge(other.tbl)) - end - end - - def add(new_val) - tbl = @tbl.dup - tbl[new_val] = true - Set.new(tbl) - end - - def size - @tbl.size - end - - def map(&blk) - tbl = {} - each do |elem| - v = yield(elem) - tbl[v] = true - end - Set.new(tbl) - end - - def inspect - s = [] - each {|v| s << v.inspect } - "{#{ s.join(", ") }}" - end - - def include?(elem) - @tbl[elem] - end - - def intersection(other) - tbl = {} - h = 0 - each do |elem| - if other.include?(elem) - tbl << elem - h ^= elem.hash - end - end - Set.new(tbl, h) - end - end - - class MutableSet - def initialize(*values) - @hash = {} - values.each {|v| @hash[v] = v } - end - - def each(&blk) - @hash.each_key(&blk) - end - - include Enumerable - - def <<(v) - @hash[v] = true - end - - def [](v) - @hash[v] - end - - def delete(v) - @hash.delete(v) - end - - def inspect - s = [] - each {|v| s << v.inspect } - "{#{ s.join(", ") }}" - end - - def size - @hash.size - end - - def to_set - Set[*@hash.keys] - end - end - - class HashWrapper - include StructuralEquality - - def initialize(hash) - @internal_hash = hash.freeze - end - - attr_reader :internal_hash - end - - class WorkList - def initialize - @heap = [] - @set = MutableSet.new - end - - def insert(key, val) - i = @heap.size - @heap << [key, val] - while i > 0 && (@heap[i][0] <=> @heap[i / 2][0]) < 0 - @heap[i], @heap[i / 2] = @heap[i / 2], @heap[i] - i /= 2 - end - @set << val - end - - def member?(val) - @set[val] - end - - def deletemin - return nil if @heap.empty? - val = @heap[0][1] - @set.delete(val) - if @heap.size == 1 - @heap.pop - return val - end - @heap[0] = @heap.pop - i = 0 - while (j = i * 2 + 1) < @heap.size - j += 1 if j + 1 < @heap.size && (@heap[j][0] <=> @heap[j + 1][0]) >= 0 - break if (@heap[i][0] <=> @heap[j][0]) < 0 - @heap[i], @heap[j] = @heap[j], @heap[i] - i = j - end - return val - end - - def size - @heap.size - end - - def empty? - @heap.empty? - end - - def inspect - "#<#{ self.class }:#{ @heap.map {|_key, val| val }.inspect }>" - end - end - - class CancelToken - def cancelled? - return false - end - end - - class TimerCancelToken < CancelToken - def initialize(max_sec) - @max_sec = max_sec - @start_time = Time.now - end - - def cancelled? - @max_sec && Time.now - @start_time >= @max_sec - end - end - end -end diff --git a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/version.rb b/lib/gems/gems/typeprof-0.21.2/lib/typeprof/version.rb deleted file mode 100644 index 1d523e45e553..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/lib/typeprof/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module TypeProf - VERSION = "0.21.2" -end diff --git a/lib/gems/gems/typeprof-0.21.2/tools/coverage.rb b/lib/gems/gems/typeprof-0.21.2/tools/coverage.rb deleted file mode 100644 index 9a7b4eb0cd1f..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/tools/coverage.rb +++ /dev/null @@ -1,14 +0,0 @@ -require "coverage" -require "coverage/helpers" - -cov = Coverage::Helpers.load("coverage.dump") -cov.delete("") -cov2 = {} -cov.each do |path, data| - path = path.sub(/^exe\/..\//, "") - data2 = Coverage.line_stub(path) - data.each_with_index {|v, i| data2[i] = v if v } - cov2[path] = data2 -end -File.write("coverage.info", Coverage::Helpers.to_lcov_info(cov2)) -system("genhtml", "-o", "coverage", "coverage.info") diff --git a/lib/gems/gems/typeprof-0.21.2/tools/setup-insns-def.rb b/lib/gems/gems/typeprof-0.21.2/tools/setup-insns-def.rb deleted file mode 100644 index ab3572e77d68..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/tools/setup-insns-def.rb +++ /dev/null @@ -1,30 +0,0 @@ -require "pp" - -unless ARGV[0] - puts "usage: #$0 /path/to/ruby/trunk/insns.def" - exit -end - -r = %r( - ^DEFINE_INSN\n - (?\w+)\n - \((?.*)\)\n - \((?.*)\)\n - \((?.*)\)\n - (?://(?.*)\n)? -)x - -INSN_TABLE = {} -Insn = Struct.new(:operands, :inputs, :outputs) -File.read(ARGV[0]).scan(r) do - name, operands, _inputs, _outputs, _inc = - $~[:name], $~[:operands], $~[:inputs], $~[:outputs], $~[:inc] - next if name.start_with?("opt_") - next if name == "bitblt" || name == "answer" - operands = operands.split(",").map {|s| s.strip }.map do |s| - s.split(" ").map {|s| s.strip }[0] - end - INSN_TABLE[name.to_sym] = operands -end -target = File.join(__dir__, "../lib/typeprof/insns-def.rb") -File.write(target, "TypeProf::INSN_TABLE = " + INSN_TABLE.pretty_inspect) diff --git a/lib/gems/gems/typeprof-0.21.2/typeprof-lsp b/lib/gems/gems/typeprof-0.21.2/typeprof-lsp deleted file mode 100644 index c98bfd1b016f..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/typeprof-lsp +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/home/mame/work/ruby/local/bin/bundle exec exe/typeprof --repo ../gem_rbs_collection/gems -Ilib --lsp diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/.gitignore b/lib/gems/gems/typeprof-0.21.2/vscode/.gitignore deleted file mode 100644 index bb759cc2a536..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/out -node_modules -.vscode/* -!.vscode/launch.json -*.vsix diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/.vscode/launch.json b/lib/gems/gems/typeprof-0.21.2/vscode/.vscode/launch.json deleted file mode 100644 index 52ee54421eba..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": "0.1.0", - "configurations": [ - { - "name": "Launch Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], - "stopOnEntry": false, - "sourceMaps": true, - "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], - "preLaunchTask": "npm: vscode:prepublish" - } - ] -} diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/.vscodeignore b/lib/gems/gems/typeprof-0.21.2/vscode/.vscodeignore deleted file mode 100644 index 92b1cde4be4a..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/.vscodeignore +++ /dev/null @@ -1,7 +0,0 @@ -/sandbox -.vscode/** -/src -**/*.ts -**/*.js.map -**/tsconfig.json -development.md \ No newline at end of file diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/README.md b/lib/gems/gems/typeprof-0.21.2/vscode/README.md deleted file mode 100644 index ae7b283fd1a6..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Ruby TypeProf VSCode Integration - -*NOTE: This extenstion is very preliminary.* - -This is a VSCode extension to help you write Ruby code by using an code analyzer called [Ruby TypeProf](https://github.com/ruby/typeprof/) as a backend. - -## How to use this extension - -*TBD* - -Requirements: - -1. Use Ruby 3.1.0 or later, and TypeProf 0.20.0 or later -2. Add `gem "typeprof"` to your `Gemfile`, and execute `bundle install` - -Troubleshooting: - -*TBD* - -## How to develop this extension - -See [development.md](https://github.com/ruby/typeprof/blob/master/development.md). \ No newline at end of file diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/development.md b/lib/gems/gems/typeprof-0.21.2/vscode/development.md deleted file mode 100644 index d361cea857cf..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/development.md +++ /dev/null @@ -1,31 +0,0 @@ -# LSP client for vscode - -Note: this is under development - -## How to run - -``` -$ cd vscode -$ npm install -$ npx run tsc -p ./ -$ cd .. -$ code --extensionDevelopmentPath=vscode/ . -``` - -Alternatively, you can do it in vscode itself. - -``` -$ cd vscode -$ code -``` - -And then press F5 to run another vscode with extension. - -## How to release - -``` -$ npm run package -$ npx vsce publish -``` - -See also: https://code.visualstudio.com/api/working-with-extensions/publishing-extension \ No newline at end of file diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/package-lock.json b/lib/gems/gems/typeprof-0.21.2/vscode/package-lock.json deleted file mode 100644 index dfda09792b60..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/package-lock.json +++ /dev/null @@ -1,3249 +0,0 @@ -{ - "name": "ruby-typeprof", - "version": "0.20.1", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "ruby-typeprof", - "version": "0.20.1", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "vscode-languageclient": "^7.0.0" - }, - "devDependencies": { - "@types/node": "^14.14.37", - "typescript": "^4.2.3", - "vsce": "^1.103.1", - "vscode": "^1.1.37" - }, - "engines": { - "vscode": "^1.54.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/node": { - "version": "14.17.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.32.tgz", - "integrity": "sha512-JcII3D5/OapPGx+eJ+Ik1SQGyt6WvuqdRfh9jUwL6/iHGjmyOriBDciBUu7lEIBTL2ijxwrR70WUnw5AEDmFvQ==", - "dev": true - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "node_modules/denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", - "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "node_modules/es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "dependencies": { - "es6-promise": "^4.0.3" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "node_modules/he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/keytar": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", - "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^3.0.0", - "prebuild-install": "^6.0.0" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dev": true, - "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "node_modules/mkdirp/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "node_modules/mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "dependencies": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/mocha/node_modules/commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true - }, - "node_modules/node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", - "dev": true, - "dependencies": { - "semver": "^5.4.1" - } - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", - "dev": true, - "dependencies": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", - "dev": true - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dev": true, - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.6.tgz", - "integrity": "sha512-xcQpTEAJw2DP7GqVNECh4dD+riS+C1qndXLfBCJ3xk0kqprtGN491P5KlmrDbKdtuW8NEcP/5ChxiJI3S9WYTA==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", - "dev": true - }, - "node_modules/url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/vsce": { - "version": "1.103.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.103.1.tgz", - "integrity": "sha512-98oKQKKRp7J/vTIk1cuzom5cezZpYpRHs3WlySdsrTCrAEipB/HvaPTc4VZ3hGZHzHXS9P5p2L0IllntJeXwiQ==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "vsce" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/vscode": { - "version": "1.1.37", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.37.tgz", - "integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==", - "deprecated": "This package is deprecated in favor of @types/vscode and vscode-test. For more information please read: https://code.visualstudio.com/updates/v1_36#_splitting-vscode-package-into-typesvscode-and-vscodetest", - "dev": true, - "dependencies": { - "glob": "^7.1.2", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "mocha": "^5.2.0", - "semver": "^5.4.1", - "source-map-support": "^0.5.0", - "vscode-test": "^0.4.1" - }, - "bin": { - "vscode-install": "bin/install" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", - "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", - "dependencies": { - "minimatch": "^3.0.4", - "semver": "^7.3.4", - "vscode-languageserver-protocol": "3.16.0" - }, - "engines": { - "vscode": "^1.52.0" - } - }, - "node_modules/vscode-languageclient/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", - "dependencies": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" - } - }, - "node_modules/vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" - }, - "node_modules/vscode-test": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.4.3.tgz", - "integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/vscode-test/node_modules/agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "dependencies": { - "es6-promisify": "^5.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/vscode-test/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/vscode-test/node_modules/http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "dependencies": { - "agent-base": "4", - "debug": "3.1.0" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/vscode-test/node_modules/https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "dependencies": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/vscode-test/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - } - }, - "dependencies": { - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/node": { - "version": "14.17.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.32.tgz", - "integrity": "sha512-JcII3D5/OapPGx+eJ+Ik1SQGyt6WvuqdRfh9jUwL6/iHGjmyOriBDciBUu7lEIBTL2ijxwrR70WUnw5AEDmFvQ==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "azure-devops-node-api": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.0.1.tgz", - "integrity": "sha512-YMdjAw9l5p/6leiyIloxj3k7VIvYThKjvqgiQn88r3nhT93ENwsoDS3A83CyJ4uTWzCZ5f5jCi6c27rTU5Pz+A==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } - }, - "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, - "requires": { - "mimic-response": "^2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "denodeify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", - "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", - "dev": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true - }, - "domhandler": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", - "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "keytar": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", - "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", - "dev": true, - "requires": { - "node-addon-api": "^3.0.0", - "prebuild-install": "^6.0.0" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - } - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true - }, - "node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", - "dev": true, - "requires": { - "semver": "^5.4.1" - } - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "requires": { - "semver": "^5.1.0" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", - "dev": true, - "requires": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", - "dev": true - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true - }, - "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dev": true, - "requires": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "typed-rest-client": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.6.tgz", - "integrity": "sha512-xcQpTEAJw2DP7GqVNECh4dD+riS+C1qndXLfBCJ3xk0kqprtGN491P5KlmrDbKdtuW8NEcP/5ChxiJI3S9WYTA==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", - "dev": true - }, - "url-join": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", - "integrity": "sha1-dBxsL0WWxIMNZxhGCSDQySIC3Hg=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "vsce": { - "version": "1.103.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.103.1.tgz", - "integrity": "sha512-98oKQKKRp7J/vTIk1cuzom5cezZpYpRHs3WlySdsrTCrAEipB/HvaPTc4VZ3hGZHzHXS9P5p2L0IllntJeXwiQ==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "denodeify": "^1.2.1", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "lodash": "^4.17.15", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "osenv": "^0.1.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^1.1.0", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - } - }, - "vscode": { - "version": "1.1.37", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.37.tgz", - "integrity": "sha512-vJNj6IlN7IJPdMavlQa1KoFB3Ihn06q1AiN3ZFI/HfzPNzbKZWPPuiU+XkpNOfGU5k15m4r80nxNPlM7wcc0wg==", - "dev": true, - "requires": { - "glob": "^7.1.2", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "mocha": "^5.2.0", - "semver": "^5.4.1", - "source-map-support": "^0.5.0", - "vscode-test": "^0.4.1" - } - }, - "vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==" - }, - "vscode-languageclient": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", - "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", - "requires": { - "minimatch": "^3.0.4", - "semver": "^7.3.4", - "vscode-languageserver-protocol": "3.16.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", - "requires": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" - } - }, - "vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==" - }, - "vscode-test": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-0.4.3.tgz", - "integrity": "sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==", - "dev": true, - "requires": { - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1" - }, - "dependencies": { - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - } - } -} diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/package.json b/lib/gems/gems/typeprof-0.21.2/vscode/package.json deleted file mode 100644 index 719acc1b264f..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/package.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "name": "ruby-typeprof", - "displayName": "Ruby TypeProf", - "version": "0.20.1", - "publisher": "mame", - "author": { - "name": "Yusuke Endoh" - }, - "repository": { - "type": "git", - "url": "https://github.com/ruby/typeprof/tree/master/vscode" - }, - "license": "MIT", - "categories": [ - "Programming Languages" - ], - "keywords": [ - "Ruby", - "language server" - ], - "engines": { - "vscode": "^1.54.0" - }, - "extensionKind": [ - "workspace" - ], - "activationEvents": [ - "onLanguage:ruby" - ], - "contributes": { - "commands": [ - { - "command": "typeprof.restart", - "title": "Restart", - "category": "TypeProf" - } - ], - "configuration": [ - { - "title": "Ruby TypeProf", - "properties": { - "typeprof.server.path": { - "type": [ - "null", - "string" - ], - "default": null, - "description": "Path to typeprof executable. (e.g. /usr/local/bin/bundle)" - } - } - } - ] - }, - "main": "./out/src/extension", - "scripts": { - "vscode:prepublish": "tsc -p ./", - "compile": "tsc -watch -p ./", - "postinstall": "node ./node_modules/vscode/bin/install", - "test": "node ./node_modules/vscode/bin/test", - "package": "vsce package" - }, - "devDependencies": { - "@types/node": "^14.14.37", - "typescript": "^4.2.3", - "vsce": "^1.103.1", - "vscode": "^1.1.37" - }, - "dependencies": { - "vscode-languageclient": "^7.0.0" - } -} diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/sandbox/test.rb b/lib/gems/gems/typeprof-0.21.2/vscode/sandbox/test.rb deleted file mode 100644 index 3bd8340e3f3f..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/sandbox/test.rb +++ /dev/null @@ -1,24 +0,0 @@ -class C - def initialize - end - - def get_foo - :Foo_foo - end - - def get_bar - :Foo_bar - end -end - -class D - def get_foo - :Foo2_foo - end -end - -C.new.get_foo -C.new.get_bar - -x = rand < 0.5 ? C.new : D.new -x.get_foo \ No newline at end of file diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/src/extension.ts b/lib/gems/gems/typeprof-0.21.2/vscode/src/extension.ts deleted file mode 100644 index bf32a6f20209..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/src/extension.ts +++ /dev/null @@ -1,302 +0,0 @@ -"use strict"; - -import * as vscode from "vscode"; -import { - LanguageClient, - LanguageClientOptions, - ServerOptions, -} from "vscode-languageclient/node"; -import * as net from "net"; -import * as child_process from "child_process"; -import { existsSync } from "fs"; - -interface Invoking { - kind: "invoking"; - workspaceFolder: vscode.WorkspaceFolder; - process: child_process.ChildProcessWithoutNullStreams; -} -interface Running { - kind: "running"; - workspaceFolder: vscode.WorkspaceFolder; - client: LanguageClient; -} -type State = Invoking | Running; - -const CONFIGURATION_ROOT_SECTION = "typeprof"; - -function addToggleButton(context: vscode.ExtensionContext) { - let statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); - statusBarItem.command = "typeprof.toggle"; - statusBarItem.text = "TypeProf $(eye)"; - statusBarItem.show(); - - const disposable = vscode.commands.registerCommand("typeprof.toggle", - (arg0: any, arg1: any, arg2: any, arg3: any) => { - if (statusBarItem.text == "TypeProf $(eye)") { - statusBarItem.text = "TypeProf $(eye-closed)"; - vscode.commands.executeCommand("typeprof.disableSignature"); - } - else { - statusBarItem.text = "TypeProf $(eye)"; - vscode.commands.executeCommand("typeprof.enableSignature"); - } - } - ); - - context.subscriptions.push(disposable); -} - -function addJumpToRBS(context: vscode.ExtensionContext) { - const disposable = vscode.commands.registerCommand("typeprof.jumpToRBS", - (arg0: any, arg1: any, arg2: any, arg3: any) => { - const uri0 = vscode.Uri.parse(arg0); - const pos0 = new vscode.Position(arg1.line, arg1.character); - const uri1 = vscode.Uri.parse(arg2); - const pos1 = new vscode.Position(arg3.start.line, arg3.start.character); - const pos2 = new vscode.Position(arg3.end.line, arg3.end.character); - const range = new vscode.Range(pos1, pos2); - const loc = new vscode.Location(uri1, range); - vscode.commands.executeCommand("editor.action.peekLocations", uri0, pos0, [loc], "peek"); - } - ); - - context.subscriptions.push(disposable); -} - -function executeTypeProf(folder: vscode.WorkspaceFolder, arg: String): child_process.ChildProcessWithoutNullStreams { - const configuration = vscode.workspace.getConfiguration(CONFIGURATION_ROOT_SECTION); - const customServerPath = configuration.get("server.path"); - const cwd = folder.uri.fsPath; - - let cmd: string; - if (existsSync(`${cwd}/bin/typeprof`)) { - cmd = "./bin/typeprof"; - } - else if (customServerPath) { - cmd = customServerPath; - } - else if (existsSync(`${cwd}/Gemfile`)) { - cmd = "bundle exec typeprof"; - } - else { - cmd = "typeprof"; - } - cmd = cmd + " " + arg; - - const shell = process.env.SHELL; - let typeprof: child_process.ChildProcessWithoutNullStreams; - if (shell && (shell.endsWith("bash") || shell.endsWith("zsh") || shell.endsWith("fish"))) { - typeprof = child_process.spawn(shell, ["-c", "-l", cmd], { cwd }); - } - else if (process.platform === "win32") { - typeprof = child_process.spawn("C:\\Windows\\System32\\cmd.exe", ["/c", cmd], { cwd }); - } - else { - typeprof = child_process.spawn(cmd, { cwd }); - } - - return typeprof; -} - -function getTypeProfVersion(folder: vscode.WorkspaceFolder, outputChannel: vscode.OutputChannel, callback: (version: string) => void): child_process.ChildProcessWithoutNullStreams { - const typeprof = executeTypeProf(folder, "--version"); - let output = ""; - - const log = (msg: string) => { - outputChannel.appendLine("[vscode] " + msg); - console.info(msg); - }; - - typeprof.stdout?.on("data", out => { output += out; }); - typeprof.stderr?.on("data", (out: Buffer) => { - const str = ("" + out).trim(); - for (const line of str.split("\n")) { - log("stderr: " + line); - } - }); - typeprof.on("error", e => { - log(`typeprof is not supported for this folder: ${folder}`); - log(`because: ${e}`); - }); - typeprof.on("exit", (code) => { - if (code == 0) { - const str = output.trim(); - log(`typeprof version: ${str}`) - const version = /^typeprof (\d+).(\d+).(\d+)$/.exec(str); - if (version) { - const major = Number(version[1]); - const minor = Number(version[2]); - const _teeny = Number(version[3]); - if (major >= 1 || (major == 0 && minor >= 20)) { - callback(str); - } - else { - log(`typeprof version ${str} is too old; please use 0.20.0 or later for IDE feature`); - } - } - else { - log(`typeprof --version showed unknown message`); - } - } - else { - log(`failed to invoke typeprof: error code ${code}`); - } - typeprof.kill() - }); - return typeprof; -} - -function getTypeProfStream(folder: vscode.WorkspaceFolder, error: (msg: string) => void): - Promise<{ host: string; port: number; pid: number; stop: () => void }> -{ - return new Promise((resolve, reject) => { - const typeprof = executeTypeProf(folder, "--lsp"); - - let buffer = ""; - typeprof.stdout.on("data", (data) => { - buffer += data; - try { - const json = JSON.parse(data); - json["stop"] = () => typeprof.kill("SIGINT"); - resolve(json); - } catch (err) {} - }); - - let err = ""; - typeprof.stderr.on("data", (data) => { - err += data; - while (true) { - const i = err.indexOf("\n"); - if (i < 0) break; - error(err.slice(0, i)); - err = err.slice(i + 1); - } - }); - - typeprof.on("exit", (code) => reject(`error code ${code}`)); - }); -} - -function invokeTypeProf(folder: vscode.WorkspaceFolder, outputChannel: vscode.OutputChannel): LanguageClient { - let client: LanguageClient; - - const reportError = (msg: string) => client.info(msg); - - const serverOptions: ServerOptions = async () => { - const { host, port, stop } = await getTypeProfStream(folder, reportError); - const socket: net.Socket = net.createConnection(port, host); - socket.on("close", (_had_error) => stop()); - - return { - reader: socket, - writer: socket, - }; - }; - - const clientOptions: LanguageClientOptions = { - documentSelector: [ - { scheme: "file", language: "ruby" }, - { scheme: "file", language: "rbs" }, - ], - outputChannel, - synchronize: { - fileEvents: - vscode.workspace.createFileSystemWatcher("{**/*.rb,**/*.rbs}"), - }, - }; - - client = new LanguageClient("Ruby TypeProf", serverOptions, clientOptions); - - return client; -} - -const clientSessions: Map = new Map(); - -function startTypeProf(folder: vscode.WorkspaceFolder) { - const outputChannel = vscode.window.createOutputChannel("Ruby TypeProf"); - const showStatus = (msg: string) => { - outputChannel.appendLine("[vscode] " + msg); - vscode.window.setStatusBarMessage(msg, 3000); - } - outputChannel.appendLine("[vscode] Try to start TypeProf for IDE"); - - const typeprof = getTypeProfVersion(folder, outputChannel, (version) => { - if (!version) { - showStatus(`Ruby TypeProf is not configured; Try to add "gem 'typeprof'" to Gemfile`); - clientSessions.delete(folder); - return; - } - showStatus(`Starting Ruby TypeProf (${version})...`); - const client = invokeTypeProf(folder, outputChannel); - client.onReady() - .then(() => { - showStatus("Ruby TypeProf is running"); - }) - .catch((e: any) => { - showStatus(`Failed to start Ruby TypeProf: ${e}`); - }); - client.start(); - clientSessions.set(folder, { kind: "running", workspaceFolder: folder, client }); - }); - - clientSessions.set(folder, { kind: "invoking", workspaceFolder: folder, process: typeprof }); -} - -function stopTypeProf(state: State) { - switch (state.kind) { - case "invoking": - state.process.kill(); - - break; - case "running": - state.client.stop(); - break; - } - clientSessions.delete(state.workspaceFolder); -} - -function restartTypeProf() { - vscode.workspace.workspaceFolders?.forEach((folder) => { - let state = clientSessions.get(folder); - if (state) stopTypeProf(state); - startTypeProf(folder); - }); -} - -function ensureTypeProf() { - if (!vscode.workspace.workspaceFolders) return; - - const activeFolders = new Set(vscode.workspace.workspaceFolders); - - clientSessions.forEach((state) => { - if (!activeFolders.has(state.workspaceFolder)) { - stopTypeProf(state); - } - }); - - activeFolders.forEach((folder) => { - if (folder.uri.scheme === "file" && !clientSessions.has(folder)) { - startTypeProf(folder); - } - }); -} - -function addRestartCommand(context: vscode.ExtensionContext) { - const disposable = vscode.commands.registerCommand("typeprof.restart", () => { - restartTypeProf(); - }); - context.subscriptions.push(disposable); -} - -export function activate(context: vscode.ExtensionContext) { - addToggleButton(context); - addJumpToRBS(context); - addRestartCommand(context) - ensureTypeProf(); -} - -export function deactivate() { - clientSessions.forEach((state) => { - stopTypeProf(state); - }); -} diff --git a/lib/gems/gems/typeprof-0.21.2/vscode/tsconfig.json b/lib/gems/gems/typeprof-0.21.2/vscode/tsconfig.json deleted file mode 100644 index ff1881d2d078..000000000000 --- a/lib/gems/gems/typeprof-0.21.2/vscode/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es6", - "outDir": "out", - "lib": ["es6"], - "sourceMap": true, - "rootDir": ".", - "strict": true - }, - "exclude": [ - "node_modules", - ".vscode-test" - ] -} \ No newline at end of file diff --git a/lib/gems/specifications/typeprof-0.21.2.gemspec b/lib/gems/specifications/typeprof-0.21.2.gemspec deleted file mode 100644 index 73f2c7675d28..000000000000 --- a/lib/gems/specifications/typeprof-0.21.2.gemspec +++ /dev/null @@ -1,35 +0,0 @@ -# -*- encoding: utf-8 -*- -# stub: typeprof 0.21.2 ruby lib - -Gem::Specification.new do |s| - s.name = "typeprof".freeze - s.version = "0.21.2" - - s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= - s.metadata = { "homepage_uri" => "https://github.com/ruby/typeprof", "source_code_uri" => "https://github.com/ruby/typeprof" } if s.respond_to? :metadata= - s.require_paths = ["lib".freeze] - s.authors = ["Yusuke Endoh".freeze] - s.bindir = "exe".freeze - s.date = "2021-12-28" - s.description = "TypeProf performs a type analysis of non-annotated Ruby code.\n\nIt abstractly executes input Ruby code in a level of types instead of values, gathers what types are passed to and returned by methods, and prints the analysis result in RBS format, a standard type description format for Ruby 3.0.\n\nThis tool is planned to be bundled with Ruby 3.0.\n".freeze - s.email = ["mame@ruby-lang.org".freeze] - s.executables = ["typeprof".freeze] - s.files = ["exe/typeprof".freeze] - s.homepage = "https://github.com/ruby/typeprof".freeze - s.licenses = ["MIT".freeze] - s.required_ruby_version = Gem::Requirement.new(">= 2.7".freeze) - s.rubygems_version = "3.3.7".freeze - s.summary = "TypeProf is a type analysis tool for Ruby code based on abstract interpretation".freeze - - s.installed_by_version = "3.3.7" if s.respond_to? :installed_by_version - - if s.respond_to? :specification_version then - s.specification_version = 4 - end - - if s.respond_to? :add_runtime_dependency then - s.add_runtime_dependency(%q.freeze, [">= 1.8.1"]) - else - s.add_dependency(%q.freeze, [">= 1.8.1"]) - end -end diff --git a/mx.truffleruby/mx_truffleruby.py b/mx.truffleruby/mx_truffleruby.py index 2846dd0f9972..229f8dc05f70 100644 --- a/mx.truffleruby/mx_truffleruby.py +++ b/mx.truffleruby/mx_truffleruby.py @@ -267,7 +267,6 @@ def verify_ci(args): 'bin/rdbg', 'bin/rdoc', 'bin/ri', - 'bin/typeprof', ], library_configs=[ mx_sdk_vm.LanguageLibraryConfig( diff --git a/spec/tags/truffle/launcher_tags.txt b/spec/tags/truffle/launcher_tags.txt index d3569233dc48..784eb4ff23df 100644 --- a/spec/tags/truffle/launcher_tags.txt +++ b/spec/tags/truffle/launcher_tags.txt @@ -78,14 +78,8 @@ slow:The launcher supports running racc2y symlinked slow:The launcher supports running y2racc symlinked slow:The launcher warns if the locale is not set properly slow:The launcher runs rbs as an -S command -slow:The launcher runs typeprof as an -S command slow:The launcher supports running rbs in any of the bin/ directories -slow:The launcher supports running typeprof in any of the bin/ directories slow:The launcher supports running rbs symlinked -slow:The launcher supports running typeprof symlinked -fails(https://github.com/ruby/typeprof/issues/64):The launcher runs typeprof as an -S command -fails(https://github.com/ruby/typeprof/issues/64):The launcher supports running typeprof in any of the bin/ directories -fails(https://github.com/ruby/typeprof/issues/64):The launcher supports running typeprof symlinked slow:The launcher prints help:ruby containing ruby language options slow:The launcher runs rdbg as an -S command slow:The launcher supports running rdbg in any of the bin/ directories diff --git a/spec/truffle/launcher_spec.rb b/spec/truffle/launcher_spec.rb index 05902e51c223..a39fc94f38d8 100644 --- a/spec/truffle/launcher_spec.rb +++ b/spec/truffle/launcher_spec.rb @@ -31,7 +31,6 @@ ri: escape["ri #{@default_gems['rdoc']}"], ruby: /^truffleruby .* like ruby #{Regexp.escape RUBY_VERSION}/, truffleruby: /^truffleruby .* like ruby #{Regexp.escape RUBY_VERSION}/, - typeprof: escape["typeprof #{@bundled_gems['typeprof']}"], } before :all do diff --git a/test/truffle/gems/default-bundled-gems/Gemfile b/test/truffle/gems/default-bundled-gems/Gemfile index 43951d7cc4fd..965ee602df3a 100644 --- a/test/truffle/gems/default-bundled-gems/Gemfile +++ b/test/truffle/gems/default-bundled-gems/Gemfile @@ -78,4 +78,3 @@ gem "test-unit", "3.5.3" gem "rbs", "2.1.0" gem "rexml", "3.2.5" gem "rss", "0.2.9" -gem "typeprof", "0.21.2" diff --git a/test/truffle/gems/default-bundled-gems/Gemfile.lock b/test/truffle/gems/default-bundled-gems/Gemfile.lock index 94513017f58e..4539a2ce4846 100644 --- a/test/truffle/gems/default-bundled-gems/Gemfile.lock +++ b/test/truffle/gems/default-bundled-gems/Gemfile.lock @@ -98,8 +98,6 @@ GEM tmpdir (0.1.2) fileutils tsort (0.1.0) - typeprof (0.21.2) - rbs (>= 1.8.1) un (0.2.0) uri (0.11.0) weakref (0.1.1) @@ -184,7 +182,6 @@ DEPENDENCIES timeout (= 0.2.0) tmpdir (= 0.1.2) tsort (= 0.1.0) - typeprof (= 0.21.2) un (= 0.2.0) uri (= 0.11.0) weakref (= 0.1.1) diff --git a/versions.json b/versions.json index 97cc781b70d8..006d231a3836 100644 --- a/versions.json +++ b/versions.json @@ -18,8 +18,7 @@ "test-unit": "3.5.3", "rbs": "2.1.0", "rexml": "3.2.5", - "rss": "0.2.9", - "typeprof": "0.21.2" + "rss": "0.2.9" } } }