From 42a8325492e486ffed848051f559bbd4cd7d4b38 Mon Sep 17 00:00:00 2001 From: Jason Hawk Harris Date: Wed, 3 Jun 2026 12:09:48 -0500 Subject: [PATCH] Audit and broaden snapshot coverage of indexer behavior. --- test/scip/testdata/abstract_interface.rb | 70 ++++++++++++ .../testdata/abstract_interface.snapshot.rb | 108 ++++++++++++++++++ test/scip/testdata/generics.rb | 50 ++++++++ test/scip/testdata/generics.snapshot.rb | 84 ++++++++++++++ test/scip/testdata/metaprog.rb | 24 ++++ test/scip/testdata/metaprog.snapshot.rb | 38 ++++++ test/scip/testdata/nested_constants.rb | 35 ++++++ .../testdata/nested_constants.snapshot.rb | 70 ++++++++++++ test/scip/testdata/prepend_extend.rb | 52 +++++++++ test/scip/testdata/prepend_extend.snapshot.rb | 90 +++++++++++++++ test/scip/testdata/requires.rb | 13 +++ test/scip/testdata/requires.snapshot.rb | 18 +++ test/scip/testdata/requires_ancestor.rb | 29 +++++ .../testdata/requires_ancestor.snapshot.rb | 44 +++++++ test/scip/testdata/singleton_class.rb | 28 +++++ .../scip/testdata/singleton_class.snapshot.rb | 48 ++++++++ test/scip/testdata/super_call.rb | 28 +++++ test/scip/testdata/super_call.snapshot.rb | 49 ++++++++ test/scip/testdata/t_helpers.rb | 40 +++++++ test/scip/testdata/t_helpers.snapshot.rb | 77 +++++++++++++ test/scip/testdata/typed_ignore.rb | 12 ++ test/scip/testdata/typed_ignore.snapshot.rb | 19 +++ test/scip/testdata/typed_strong.rb | 30 +++++ test/scip/testdata/typed_strong.snapshot.rb | 56 +++++++++ test/scip/testdata/yield_block.rb | 24 ++++ test/scip/testdata/yield_block.snapshot.rb | 42 +++++++ 26 files changed, 1178 insertions(+) create mode 100644 test/scip/testdata/abstract_interface.rb create mode 100644 test/scip/testdata/abstract_interface.snapshot.rb create mode 100644 test/scip/testdata/generics.rb create mode 100644 test/scip/testdata/generics.snapshot.rb create mode 100644 test/scip/testdata/metaprog.rb create mode 100644 test/scip/testdata/metaprog.snapshot.rb create mode 100644 test/scip/testdata/nested_constants.rb create mode 100644 test/scip/testdata/nested_constants.snapshot.rb create mode 100644 test/scip/testdata/prepend_extend.rb create mode 100644 test/scip/testdata/prepend_extend.snapshot.rb create mode 100644 test/scip/testdata/requires.rb create mode 100644 test/scip/testdata/requires.snapshot.rb create mode 100644 test/scip/testdata/requires_ancestor.rb create mode 100644 test/scip/testdata/requires_ancestor.snapshot.rb create mode 100644 test/scip/testdata/singleton_class.rb create mode 100644 test/scip/testdata/singleton_class.snapshot.rb create mode 100644 test/scip/testdata/super_call.rb create mode 100644 test/scip/testdata/super_call.snapshot.rb create mode 100644 test/scip/testdata/t_helpers.rb create mode 100644 test/scip/testdata/t_helpers.snapshot.rb create mode 100644 test/scip/testdata/typed_ignore.rb create mode 100644 test/scip/testdata/typed_ignore.snapshot.rb create mode 100644 test/scip/testdata/typed_strong.rb create mode 100644 test/scip/testdata/typed_strong.snapshot.rb create mode 100644 test/scip/testdata/yield_block.rb create mode 100644 test/scip/testdata/yield_block.snapshot.rb diff --git a/test/scip/testdata/abstract_interface.rb b/test/scip/testdata/abstract_interface.rb new file mode 100644 index 000000000..4468041bc --- /dev/null +++ b/test/scip/testdata/abstract_interface.rb @@ -0,0 +1,70 @@ +# typed: strict + +# Exercises abstract!, interface!, final!, sealed!, mixes_in_class_methods. + +module Drawable + extend T::Sig + extend T::Helpers + interface! + + sig { abstract.returns(String) } + def draw; end +end + +class Shape + extend T::Sig + extend T::Helpers + abstract! + + sig { abstract.returns(Integer) } + def area; end +end + +class Square < Shape + extend T::Sig + include Drawable + + sig { override.returns(Integer) } + def area + 16 + end + + sig { override.returns(String) } + def draw + "square" + end +end + +class FinalLeaf + extend T::Sig + extend T::Helpers + final! + + sig(:final) { returns(Integer) } + def value + 42 + end +end + +module SealedHierarchy + extend T::Helpers + sealed! +end + +module ClassMethodsMixin + extend T::Sig + + sig { returns(String) } + def class_helper + "class!" + end +end + +module InstanceMethodsMixin + extend T::Helpers + mixes_in_class_methods(ClassMethodsMixin) +end + +class WithMixedIn + include InstanceMethodsMixin +end diff --git a/test/scip/testdata/abstract_interface.snapshot.rb b/test/scip/testdata/abstract_interface.snapshot.rb new file mode 100644 index 000000000..12c4f3eb6 --- /dev/null +++ b/test/scip/testdata/abstract_interface.snapshot.rb @@ -0,0 +1,108 @@ + # typed: strict + + # Exercises abstract!, interface!, final!, sealed!, mixes_in_class_methods. + + module Drawable +# ^^^^^^^^ definition [..] Drawable# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + extend T::Helpers +# ^^^^^^ reference [..] Kernel#extend(). + interface! + + sig { abstract.returns(String) } +# ^^^^^^ reference [..] String# + def draw; end +# ^^^^ definition [..] Drawable#draw(). + end + + class Shape +# ^^^^^ definition [..] Shape# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + extend T::Helpers +# ^^^^^^ reference [..] Kernel#extend(). + abstract! + + sig { abstract.returns(Integer) } +# ^^^^^^^ reference [..] Integer# + def area; end +# ^^^^ definition [..] Shape#area(). + end + + class Square < Shape +# ^^^^^^ definition [..] Square# +# ^^^^^ reference [..] Shape# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + include Drawable +# ^^^^^^^ reference [..] Module#include(). +# ^^^^^^^^ reference [..] Drawable# +# ^^^^^^^^ reference [..] Drawable# + + sig { override.returns(Integer) } +# ^^^^^^^ reference [..] Integer# + def area +# ^^^^ definition [..] Square#area(). + 16 + end + + sig { override.returns(String) } +# ^^^^^^ reference [..] String# + def draw +# ^^^^ definition [..] Square#draw(). + "square" + end + end + + class FinalLeaf +# ^^^^^^^^^ definition [..] FinalLeaf# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + extend T::Helpers +# ^^^^^^ reference [..] Kernel#extend(). + final! + + sig(:final) { returns(Integer) } +# ^^^^^^^ reference [..] Integer# + def value +# ^^^^^ definition [..] FinalLeaf#value(). + 42 + end + end + + module SealedHierarchy +# ^^^^^^^^^^^^^^^ definition [..] SealedHierarchy# + extend T::Helpers +# ^^^^^^ reference [..] Kernel#extend(). + sealed! + end + + module ClassMethodsMixin +# ^^^^^^^^^^^^^^^^^ definition [..] ClassMethodsMixin# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + + sig { returns(String) } +# ^^^^^^ reference [..] String# + def class_helper +# ^^^^^^^^^^^^ definition [..] ClassMethodsMixin#class_helper(). + "class!" + end + end + + module InstanceMethodsMixin +# ^^^^^^^^^^^^^^^^^^^^ definition [..] InstanceMethodsMixin# + extend T::Helpers +# ^^^^^^ reference [..] Kernel#extend(). + mixes_in_class_methods(ClassMethodsMixin) +# ^^^^^^^^^^^^^^^^^ reference [..] ClassMethodsMixin# + end + + class WithMixedIn +# ^^^^^^^^^^^ definition [..] WithMixedIn# + include InstanceMethodsMixin +# ^^^^^^^ reference [..] Module#include(). +# ^^^^^^^^^^^^^^^^^^^^ reference [..] InstanceMethodsMixin# +# ^^^^^^^^^^^^^^^^^^^^ reference [..] InstanceMethodsMixin# + end diff --git a/test/scip/testdata/generics.rb b/test/scip/testdata/generics.rb new file mode 100644 index 000000000..6f8096223 --- /dev/null +++ b/test/scip/testdata/generics.rb @@ -0,0 +1,50 @@ +# typed: true + +# Exercises the TypeArgument / TypeMember descriptor branches in +# scip_indexer/SCIPSymbolRef.cc symbolForExpr (Descriptor::TypeParameter, +# Descriptor::Type). + +class GenericBox + extend T::Sig + extend T::Generic + + Elem = type_member + + sig { params(x: Elem).void } + def initialize(x) + @x = x + end + + sig { returns(Elem) } + def get + @x + end +end + +module MyGenericMixin + extend T::Generic + + Item = type_member +end + +class WithTypeTemplate + extend T::Generic + + Tag = type_template +end + +class WithTypeParameters + extend T::Sig + + sig { type_parameters(:U).params(x: T.type_parameter(:U)).returns(T.type_parameter(:U)) } + def identity(x) + x + end +end + +def use_generics + box = GenericBox.new(1) + _ = box.get + _ = WithTypeParameters.new.identity(42) + return +end diff --git a/test/scip/testdata/generics.snapshot.rb b/test/scip/testdata/generics.snapshot.rb new file mode 100644 index 000000000..ff75e5bc3 --- /dev/null +++ b/test/scip/testdata/generics.snapshot.rb @@ -0,0 +1,84 @@ + # typed: true + + # Exercises the TypeArgument / TypeMember descriptor branches in + # scip_indexer/SCIPSymbolRef.cc symbolForExpr (Descriptor::TypeParameter, + # Descriptor::Type). + + class GenericBox +# ^^^^^^^^^^ definition [..] GenericBox# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + extend T::Generic +# ^^^^^^ reference [..] Kernel#extend(). + + Elem = type_member +# ^^^^ definition local 3$119448696 + + sig { params(x: Elem).void } +# ^^^^ definition local 2$3465713227 + def initialize(x) +# ^^^^^^^^^^ definition [..] GenericBox#initialize(). +# ^ definition local 1$3465713227 + @x = x +# ^^ definition [..] GenericBox#`@x`. +# ^^^^^^ reference [..] GenericBox#`@x`. +# ^ reference local 1$3465713227 + end + + sig { returns(Elem) } + def get +# ^^^ definition [..] GenericBox#get(). + @x +# ^^ reference [..] GenericBox#`@x`. + end + end + + module MyGenericMixin +# ^^^^^^^^^^^^^^ definition [..] MyGenericMixin# + extend T::Generic +# ^^^^^^ reference [..] Kernel#extend(). + + Item = type_member +# ^^^^ definition local 2$119448696 + end + + class WithTypeTemplate +# ^^^^^^^^^^^^^^^^ definition [..] WithTypeTemplate# + extend T::Generic +# ^^^^^^ reference [..] Kernel#extend(). + + Tag = type_template +# ^^^ definition local 2$119448696 + end + + class WithTypeParameters +# ^^^^^^^^^^^^^^^^^^ definition [..] WithTypeParameters# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + + sig { type_parameters(:U).params(x: T.type_parameter(:U)).returns(T.type_parameter(:U)) } + def identity(x) +# ^^^^^^^^ definition [..] WithTypeParameters#identity(). +# ^ definition local 1$2839884955 + x +# ^ reference local 1$2839884955 + end + end + + def use_generics +# ^^^^^^^^^^^^ definition [..] Object#use_generics(). + box = GenericBox.new(1) +# ^^^ definition local 1$1376823943 +# ^^^^^^^^^^ reference [..] GenericBox# +# ^^^ reference [..] Class#new(). + _ = box.get +# ^ definition local 3$1376823943 +# ^^^ reference local 1$1376823943 +# ^^^ reference [..] GenericBox#get(). + _ = WithTypeParameters.new.identity(42) +# ^ reference (write) local 3$1376823943 +# ^^^^^^^^^^^^^^^^^^ reference [..] WithTypeParameters# +# ^^^ reference [..] Class#new(). +# ^^^^^^^^ reference [..] WithTypeParameters#identity(). + return + end diff --git a/test/scip/testdata/metaprog.rb b/test/scip/testdata/metaprog.rb new file mode 100644 index 000000000..52a252307 --- /dev/null +++ b/test/scip/testdata/metaprog.rb @@ -0,0 +1,24 @@ +# typed: false + +# Common metaprogramming constructs. Currently not specially handled by the +# indexer (define_method body is a normal block; method_missing / respond_to_missing? +# are normal method defs). + +class Dynamo + define_method(:dynamic) do |x| + x + 1 + end + + def method_missing(name, *args, &blk) + "missed " + name.to_s + end + + def respond_to_missing?(name, include_private = false) + true + end +end + +def use_meta + Dynamo.new.dynamic(1) + Dynamo.new.unknown_method +end diff --git a/test/scip/testdata/metaprog.snapshot.rb b/test/scip/testdata/metaprog.snapshot.rb new file mode 100644 index 000000000..485758575 --- /dev/null +++ b/test/scip/testdata/metaprog.snapshot.rb @@ -0,0 +1,38 @@ + # typed: false + + # Common metaprogramming constructs. Currently not specially handled by the + # indexer (define_method body is a normal block; method_missing / respond_to_missing? + # are normal method defs). + + class Dynamo +# ^^^^^^ definition [..] Dynamo# + define_method(:dynamic) do |x| +# ^^^^^^^^^^^^^ reference [..] Module#define_method(). +# ^ definition local 1$119448696 + x + 1 +# ^ reference local 1$119448696 + end + + def method_missing(name, *args, &blk) +# ^^^^^^^^^^^^^^ definition [..] Dynamo#method_missing(). +# ^^^^ definition local 1$2090704463 + "missed " + name.to_s +# ^^^^ reference local 1$2090704463 +# ^^^^ reference [..] Kernel#to_s(). + end + + def respond_to_missing?(name, include_private = false) +# ^^^^^^^^^^^^^^^^^^^ definition [..] Dynamo#`respond_to_missing?`(). + true + end + end + + def use_meta +# ^^^^^^^^ definition [..] Object#use_meta(). + Dynamo.new.dynamic(1) +# ^^^^^^ reference [..] Dynamo# +# ^^^ reference [..] Class#new(). + Dynamo.new.unknown_method +# ^^^^^^ reference [..] Dynamo# +# ^^^ reference [..] Class#new(). + end diff --git a/test/scip/testdata/nested_constants.rb b/test/scip/testdata/nested_constants.rb new file mode 100644 index 000000000..31f659497 --- /dev/null +++ b/test/scip/testdata/nested_constants.rb @@ -0,0 +1,35 @@ +# typed: true + +# 3+-level constant qualifier walks in class names, ancestors, and references. +# Exercises the recursion in saveQualifierReferences. + +module Outer + module Inner + module Deep + class Base + def m; end + end + + module Mixin + def helper + "h" + end + end + end + end +end + +# 4-level qualifier in class header and in superclass position. +class Outer::Inner::Deep::Derived < Outer::Inner::Deep::Base +end + +# Qualified include in an ancestor expression. +class WithDeepMixin + include Outer::Inner::Deep::Mixin +end + +def use_nested + _ = Outer::Inner::Deep::Base.new + _ = WithDeepMixin.new.helper + return +end diff --git a/test/scip/testdata/nested_constants.snapshot.rb b/test/scip/testdata/nested_constants.snapshot.rb new file mode 100644 index 000000000..5bac23e6a --- /dev/null +++ b/test/scip/testdata/nested_constants.snapshot.rb @@ -0,0 +1,70 @@ + # typed: true + + # 3+-level constant qualifier walks in class names, ancestors, and references. + # Exercises the recursion in saveQualifierReferences. + + module Outer +# ^^^^^ definition [..] Outer# + module Inner +# ^^^^^ definition [..] Outer#Inner# + module Deep +# ^^^^ definition [..] Outer#Inner#Deep# + class Base +# ^^^^ definition [..] Outer#Inner#Deep#Base# + def m; end +# ^ definition [..] Outer#Inner#Deep#Base#m(). + end + + module Mixin +# ^^^^^ definition [..] Outer#Inner#Deep#Mixin# + def helper +# ^^^^^^ definition [..] Outer#Inner#Deep#Mixin#helper(). + "h" + end + end + end + end + end + + # 4-level qualifier in class header and in superclass position. + class Outer::Inner::Deep::Derived < Outer::Inner::Deep::Base +# ^^^^^ reference [..] Outer# +# ^^^^^ reference [..] Outer#Inner# +# ^^^^ reference [..] Outer#Inner#Deep# +# ^^^^^^^ definition [..] Outer#Inner#Deep#Derived# +# ^^^^^ reference [..] Outer# +# ^^^^^ reference [..] Outer#Inner# +# ^^^^ reference [..] Outer#Inner#Deep# +# ^^^^ reference [..] Outer#Inner#Deep#Base# + end + + # Qualified include in an ancestor expression. + class WithDeepMixin +# ^^^^^^^^^^^^^ definition [..] WithDeepMixin# + include Outer::Inner::Deep::Mixin +# ^^^^^^^ reference [..] Module#include(). +# ^^^^^ reference [..] Outer# +# ^^^^^ reference [..] Outer#Inner# +# ^^^^^ reference [..] Outer#Inner# +# ^^^^ reference [..] Outer#Inner#Deep# +# ^^^^ reference [..] Outer#Inner#Deep# +# ^^^^^ reference [..] Outer#Inner#Deep#Mixin# +# ^^^^^ reference [..] Outer#Inner#Deep#Mixin# + end + + def use_nested +# ^^^^^^^^^^ definition [..] Object#use_nested(). + _ = Outer::Inner::Deep::Base.new +# ^ definition local 1$4031378110 +# ^^^^^ reference [..] Outer# +# ^^^^^ reference [..] Outer#Inner# +# ^^^^ reference [..] Outer#Inner#Deep# +# ^^^^ reference [..] Outer#Inner#Deep#Base# +# ^^^ reference [..] Class#new(). + _ = WithDeepMixin.new.helper +# ^ reference (write) local 1$4031378110 +# ^^^^^^^^^^^^^ reference [..] WithDeepMixin# +# ^^^ reference [..] Class#new(). +# ^^^^^^ reference [..] Outer#Inner#Deep#Mixin#helper(). + return + end diff --git a/test/scip/testdata/prepend_extend.rb b/test/scip/testdata/prepend_extend.rb new file mode 100644 index 000000000..96d835526 --- /dev/null +++ b/test/scip/testdata/prepend_extend.rb @@ -0,0 +1,52 @@ +# typed: true + +# Exercises prepend and user-level extend mixin relationships; +# the existing mixin.rb only covers include. Shared @field is used so the +# field-inheritance / mixin-transitive code paths get a chance to surface +# `is_reference` relationships for prepend/extend. + +module Greeter + def hello + "hi" + end + + def set_via_greeter + @field = "g" + end +end + +module PrependedMod + def hello + "prepended " + super + end + + def set_via_prepend + @field = "p" + end +end + +module ClassyMethods + def klass_hi + "class hi" + end +end + +class CombinedMix + include Greeter + prepend PrependedMod + extend ClassyMethods + + def read_field + @field + end +end + +def use_combined + c = CombinedMix.new + c.set_via_greeter + c.set_via_prepend + _ = c.hello + _ = c.read_field + _ = CombinedMix.klass_hi + return +end diff --git a/test/scip/testdata/prepend_extend.snapshot.rb b/test/scip/testdata/prepend_extend.snapshot.rb new file mode 100644 index 000000000..32f967d8a --- /dev/null +++ b/test/scip/testdata/prepend_extend.snapshot.rb @@ -0,0 +1,90 @@ + # typed: true + + # Exercises prepend and user-level extend mixin relationships; + # the existing mixin.rb only covers include. Shared @field is used so the + # field-inheritance / mixin-transitive code paths get a chance to surface + # `is_reference` relationships for prepend/extend. + + module Greeter +# ^^^^^^^ definition [..] Greeter# + def hello +# ^^^^^ definition [..] Greeter#hello(). + "hi" + end + + def set_via_greeter +# ^^^^^^^^^^^^^^^ definition [..] Greeter#set_via_greeter(). + @field = "g" +# ^^^^^^ definition [..] Greeter#`@field`. +# ^^^^^^^^^^^^ reference [..] Greeter#`@field`. + end + end + + module PrependedMod +# ^^^^^^^^^^^^ definition [..] PrependedMod# + def hello +# ^^^^^ definition [..] PrependedMod#hello(). + "prepended " + super + end + + def set_via_prepend +# ^^^^^^^^^^^^^^^ definition [..] PrependedMod#set_via_prepend(). + @field = "p" +# ^^^^^^ definition [..] PrependedMod#`@field`. +# ^^^^^^^^^^^^ reference [..] PrependedMod#`@field`. + end + end + + module ClassyMethods +# ^^^^^^^^^^^^^ definition [..] ClassyMethods# + def klass_hi +# ^^^^^^^^ definition [..] ClassyMethods#klass_hi(). + "class hi" + end + end + + class CombinedMix +# ^^^^^^^^^^^ definition [..] CombinedMix# + include Greeter +# ^^^^^^^ reference [..] Module#include(). +# ^^^^^^^ reference [..] Greeter# +# ^^^^^^^ reference [..] Greeter# + prepend PrependedMod +# ^^^^^^^ reference [..] Module#prepend(). +# ^^^^^^^^^^^^ reference [..] PrependedMod# + extend ClassyMethods +# ^^^^^^ reference [..] Kernel#extend(). +# ^^^^^^^^^^^^^ reference [..] ClassyMethods# + + def read_field +# ^^^^^^^^^^ definition [..] CombinedMix#read_field(). + @field +# ^^^^^^ reference [..] CombinedMix#`@field`. + end + end + + def use_combined +# ^^^^^^^^^^^^ definition [..] Object#use_combined(). + c = CombinedMix.new +# ^ definition local 1$1415327550 +# ^^^^^^^^^^^ reference [..] CombinedMix# +# ^^^ reference [..] Class#new(). + c.set_via_greeter +# ^ reference local 1$1415327550 +# ^^^^^^^^^^^^^^^ reference [..] Greeter#set_via_greeter(). + c.set_via_prepend +# ^ reference local 1$1415327550 + _ = c.hello +# ^ definition local 3$1415327550 +# ^ reference local 1$1415327550 +# ^^^^^ reference [..] Greeter#hello(). + _ = c.read_field +# ^ reference (write) local 3$1415327550 +# ^ reference local 1$1415327550 +# ^^^^^^^^^^ reference [..] CombinedMix#read_field(). + _ = CombinedMix.klass_hi +# ^ reference (write) local 3$1415327550 +# ^^^^^^^^^^^ reference [..] CombinedMix# +# ^^^^^^^^ reference [..] ClassyMethods#klass_hi(). + return + end diff --git a/test/scip/testdata/requires.rb b/test/scip/testdata/requires.rb new file mode 100644 index 000000000..d9fd6ff59 --- /dev/null +++ b/test/scip/testdata/requires.rb @@ -0,0 +1,13 @@ +# typed: false + +# `require` and `require_relative` calls. They lower to ordinary Send +# instructions; this fixture documents what the indexer emits for them. + +require 'json' +require 'set' +require_relative 'non_existent_helper' + +def lazy_load + require 'csv' + return +end diff --git a/test/scip/testdata/requires.snapshot.rb b/test/scip/testdata/requires.snapshot.rb new file mode 100644 index 000000000..563500542 --- /dev/null +++ b/test/scip/testdata/requires.snapshot.rb @@ -0,0 +1,18 @@ + # typed: false + + # `require` and `require_relative` calls. They lower to ordinary Send + # instructions; this fixture documents what the indexer emits for them. + + require 'json' +#^^^^^^^ reference [..] Kernel#require(). + require 'set' +#^^^^^^^ reference [..] Kernel#require(). + require_relative 'non_existent_helper' +#^^^^^^^^^^^^^^^^ reference [..] Kernel#require_relative(). + + def lazy_load +# ^^^^^^^^^ definition [..] Object#lazy_load(). + require 'csv' +# ^^^^^^^ reference [..] Kernel#require(). + return + end diff --git a/test/scip/testdata/requires_ancestor.rb b/test/scip/testdata/requires_ancestor.rb new file mode 100644 index 000000000..3c4482a1b --- /dev/null +++ b/test/scip/testdata/requires_ancestor.rb @@ -0,0 +1,29 @@ +# typed: strict + +# Exercises T::Helpers `requires_ancestor { ... }`. + +module Greetable + extend T::Helpers + extend T::Sig + abstract! + + requires_ancestor { Kernel } + + sig { abstract.returns(String) } + def name; end + + sig { void } + def greet + puts("Hello, " + name) + end +end + +class GreetableClass + extend T::Sig + include Greetable + + sig { override.returns(String) } + def name + "World" + end +end diff --git a/test/scip/testdata/requires_ancestor.snapshot.rb b/test/scip/testdata/requires_ancestor.snapshot.rb new file mode 100644 index 000000000..cda83deb9 --- /dev/null +++ b/test/scip/testdata/requires_ancestor.snapshot.rb @@ -0,0 +1,44 @@ + # typed: strict + + # Exercises T::Helpers `requires_ancestor { ... }`. + + module Greetable +# ^^^^^^^^^ definition [..] Greetable# + extend T::Helpers +# ^^^^^^ reference [..] Kernel#extend(). + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + abstract! + + requires_ancestor { Kernel } +# ^^^^^^ reference [..] Kernel# + + sig { abstract.returns(String) } +# ^^^^^^ reference [..] String# + def name; end +# ^^^^ definition [..] Greetable#name(). + + sig { void } + def greet +# ^^^^^ definition [..] Greetable#greet(). + puts("Hello, " + name) +# ^^^^ reference [..] Greetable#name(). + end + end + + class GreetableClass +# ^^^^^^^^^^^^^^ definition [..] GreetableClass# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + include Greetable +# ^^^^^^^ reference [..] Module#include(). +# ^^^^^^^^^ reference [..] Greetable# +# ^^^^^^^^^ reference [..] Greetable# + + sig { override.returns(String) } +# ^^^^^^ reference [..] String# + def name +# ^^^^ definition [..] GreetableClass#name(). + "World" + end + end diff --git a/test/scip/testdata/singleton_class.rb b/test/scip/testdata/singleton_class.rb new file mode 100644 index 000000000..94946ddf9 --- /dev/null +++ b/test/scip/testdata/singleton_class.rb @@ -0,0 +1,28 @@ +# typed: true + +# Methods and class instance variables defined inside `class << self`. +# Currently noted as "BUG: Emitting a definition for 'self' here seems wrong." +# in field_inheritance.rb. This fixture captures the current behavior so a +# future fix has a regression target. + +class K + class << self + def class_method + @counter = 0 + end + + def read_counter + @counter + end + + attr_accessor :name + end +end + +def use_K + K.class_method + _ = K.read_counter + K.name = "k" + _ = K.name + return +end diff --git a/test/scip/testdata/singleton_class.snapshot.rb b/test/scip/testdata/singleton_class.snapshot.rb new file mode 100644 index 000000000..f084e5a43 --- /dev/null +++ b/test/scip/testdata/singleton_class.snapshot.rb @@ -0,0 +1,48 @@ + # typed: true + + # Methods and class instance variables defined inside `class << self`. + # Currently noted as "BUG: Emitting a definition for 'self' here seems wrong." + # in field_inheritance.rb. This fixture captures the current behavior so a + # future fix has a regression target. + + class K +# ^ definition [..] K# + class << self +# ^^^^ definition [..] ``# + def class_method +# ^^^^^^^^^^^^ definition [..] ``#class_method(). + @counter = 0 +# ^^^^^^^^ definition [..] ``#`@counter`. +# ^^^^^^^^^^^^ reference [..] ``#`@counter`. + end + + def read_counter +# ^^^^^^^^^^^^ definition [..] ``#read_counter(). + @counter +# ^^^^^^^^ reference [..] ``#`@counter`. + end + + attr_accessor :name +# ^^^^ definition [..] ``#`name=`(). +# ^^^^ definition [..] ``#name(). + end + end + + def use_K +# ^^^^^ definition [..] Object#use_K(). + K.class_method +# ^ reference [..] K# +# ^^^^^^^^^^^^ reference [..] ``#class_method(). + _ = K.read_counter +# ^ definition local 2$2530843406 +# ^ reference [..] K# +# ^^^^^^^^^^^^ reference [..] ``#read_counter(). + K.name = "k" +# ^ reference [..] K# +# ^^^^^^ reference [..] ``#`name=`(). + _ = K.name +# ^ reference (write) local 2$2530843406 +# ^ reference [..] K# +# ^^^^ reference [..] ``#name(). + return + end diff --git a/test/scip/testdata/super_call.rb b/test/scip/testdata/super_call.rb new file mode 100644 index 000000000..c60b08a7d --- /dev/null +++ b/test/scip/testdata/super_call.rb @@ -0,0 +1,28 @@ +# typed: true + +# Explicit-arg super (as opposed to implicit-arg, which is implicit_super_arg.rb) +# Documents whether scip-ruby emits a reference to the parent method at `super`. + +class Parent + def greet(name) + "Hi, " + name + end +end + +class Child < Parent + def greet(name) + super(name) + end +end + +class GrandChild < Child + def greet(name) + base = super("child of " + name) + base + "!" + end +end + +def trigger + _ = GrandChild.new.greet("x") + return +end diff --git a/test/scip/testdata/super_call.snapshot.rb b/test/scip/testdata/super_call.snapshot.rb new file mode 100644 index 000000000..748baee44 --- /dev/null +++ b/test/scip/testdata/super_call.snapshot.rb @@ -0,0 +1,49 @@ + # typed: true + + # Explicit-arg super (as opposed to implicit-arg, which is implicit_super_arg.rb) + # Documents whether scip-ruby emits a reference to the parent method at `super`. + + class Parent +# ^^^^^^ definition [..] Parent# + def greet(name) +# ^^^^^ definition [..] Parent#greet(). +# ^^^^ definition local 1$4213039946 + "Hi, " + name +# ^^^^ reference local 1$4213039946 + end + end + + class Child < Parent +# ^^^^^ definition [..] Child# +# ^^^^^^ reference [..] Parent# + def greet(name) +# ^^^^^ definition [..] Child#greet(). +# ^^^^ definition local 1$4213039946 + super(name) +# ^^^^ reference local 1$4213039946 + end + end + + class GrandChild < Child +# ^^^^^^^^^^ definition [..] GrandChild# +# ^^^^^ reference [..] Child# + def greet(name) +# ^^^^^ definition [..] GrandChild#greet(). +# ^^^^ definition local 1$4213039946 + base = super("child of " + name) +# ^^^^ definition local 2$4213039946 +# ^^^^ reference local 1$4213039946 + base + "!" +# ^^^^ reference local 2$4213039946 + end + end + + def trigger +# ^^^^^^^ definition [..] Object#trigger(). + _ = GrandChild.new.greet("x") +# ^ definition local 2$1967206915 +# ^^^^^^^^^^ reference [..] GrandChild# +# ^^^ reference [..] Class#new(). +# ^^^^^ reference [..] GrandChild#greet(). + return + end diff --git a/test/scip/testdata/t_helpers.rb b/test/scip/testdata/t_helpers.rb new file mode 100644 index 000000000..81055096c --- /dev/null +++ b/test/scip/testdata/t_helpers.rb @@ -0,0 +1,40 @@ +# typed: true + +# T.must, T.assert_type!, T.absurd, T.bind. Other T.* operations +# (T.let, T.cast, T.unsafe, T.reveal_type) are already covered elsewhere. + +class Container + extend T::Sig + + sig { params(x: T.nilable(String)).returns(Integer) } + def use_must(x) + T.must(x).length + end + + sig { params(x: T.untyped).returns(Integer) } + def use_assert_type(x) + T.assert_type!(x, Integer) + x + 1 + end + + Variant = T.type_alias { T.any(Integer, String) } + + sig { params(x: Variant).returns(Integer) } + def use_absurd(x) + case x + when Integer then x + 1 + when String then x.length + else + T.absurd(x) + end + end + + sig { returns(T.proc.void) } + def use_bind + proc do + T.bind(self, Integer) + _ = self + 1 + nil + end + end +end diff --git a/test/scip/testdata/t_helpers.snapshot.rb b/test/scip/testdata/t_helpers.snapshot.rb new file mode 100644 index 000000000..249f49cde --- /dev/null +++ b/test/scip/testdata/t_helpers.snapshot.rb @@ -0,0 +1,77 @@ + # typed: true + + # T.must, T.assert_type!, T.absurd, T.bind. Other T.* operations + # (T.let, T.cast, T.unsafe, T.reveal_type) are already covered elsewhere. + + class Container +# ^^^^^^^^^ definition [..] Container# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + + sig { params(x: T.nilable(String)).returns(Integer) } +# ^^^^^^ reference [..] String# +# ^^^^^^^ reference [..] Integer# + def use_must(x) +# ^^^^^^^^ definition [..] Container#use_must(). +# ^ definition local 1$2138952860 + T.must(x).length +# ^ reference [..] T# +# ^^^^ reference [..] ``#must(). +# ^ reference local 1$2138952860 +# ^^^^^^ reference [..] String#length(). + end + + sig { params(x: T.untyped).returns(Integer) } +# ^^^^^^^ reference [..] Integer# + def use_assert_type(x) +# ^^^^^^^^^^^^^^^ definition [..] Container#use_assert_type(). +# ^ definition local 1$3012239264 + T.assert_type!(x, Integer) +# ^ reference local 1$3012239264 +# ^^^^^^^ definition local 2$3012239264 +# ^^^^^^^ reference [..] Integer# + x + 1 +# ^ reference local 1$3012239264 + end + + Variant = T.type_alias { T.any(Integer, String) } +# ^^^^^^^ definition [..] Container#Variant. +# ^^^^^^^ reference [..] Integer# +# ^^^^^^ reference [..] String# + + sig { params(x: Variant).returns(Integer) } +# ^^^^^^^ reference [..] Container#Variant. +# ^^^^^^^ reference [..] Integer# + def use_absurd(x) +# ^^^^^^^^^^ definition [..] Container#use_absurd(). +# ^ definition local 1$4004738816 + case x +# ^ reference local 1$4004738816 + when Integer then x + 1 +# ^^^^^^^ reference [..] Integer# +# ^ reference local 1$4004738816 +# ^ reference [..] Integer#+(). + when String then x.length +# ^^^^^^ reference [..] String# +# ^ reference local 1$4004738816 +# ^^^^^^ reference [..] String#length(). + else + T.absurd(x) + end + end + + sig { returns(T.proc.void) } + def use_bind +# ^^^^^^^^ definition [..] Container#use_bind(). + proc do +# ^^^^ reference [..] Kernel#proc(). + T.bind(self, Integer) +# ^^^^^^^ definition local 1$1938721546 +# ^^^^^^^ reference [..] Integer# + _ = self + 1 +# ^ definition local 3$1938721546 +# ^ reference [..] Integer#+(). + nil + end + end + end diff --git a/test/scip/testdata/typed_ignore.rb b/test/scip/testdata/typed_ignore.rb new file mode 100644 index 000000000..f612084a6 --- /dev/null +++ b/test/scip/testdata/typed_ignore.rb @@ -0,0 +1,12 @@ +# typed: ignore + +# `typed: ignore` files are parsed but not typechecked. This locks in what +# (if anything) the indexer emits for such files. + +class IgnoredKlass + def m + @field = 1 + end +end + +IgnoredKlass.new.m diff --git a/test/scip/testdata/typed_ignore.snapshot.rb b/test/scip/testdata/typed_ignore.snapshot.rb new file mode 100644 index 000000000..e989b21c3 --- /dev/null +++ b/test/scip/testdata/typed_ignore.snapshot.rb @@ -0,0 +1,19 @@ + # typed: ignore + + # `typed: ignore` files are parsed but not typechecked. This locks in what + # (if anything) the indexer emits for such files. + + class IgnoredKlass +# ^^^^^^^^^^^^ definition [..] IgnoredKlass# + def m +# ^ definition [..] IgnoredKlass#m(). + @field = 1 +# ^^^^^^ definition [..] IgnoredKlass#`@field`. +# ^^^^^^^^^^ reference [..] IgnoredKlass#`@field`. + end + end + + IgnoredKlass.new.m +#^^^^^^^^^^^^ reference [..] IgnoredKlass# +# ^^^ reference [..] Class#new(). +# ^ reference [..] IgnoredKlass#m(). diff --git a/test/scip/testdata/typed_strong.rb b/test/scip/testdata/typed_strong.rb new file mode 100644 index 000000000..3b8827573 --- /dev/null +++ b/test/scip/testdata/typed_strong.rb @@ -0,0 +1,30 @@ +# typed: strong + +# At `typed: strong` Sorbet requires that nothing be T.untyped. Locks in +# indexer behavior for fully-typed code. + +class StrongClass + extend T::Sig + + sig { params(x: Integer).returns(Integer) } + def add_one(x) + x + 1 + end + + sig { params(x: String).returns(String) } + def shout(x) + x.upcase + end +end + +class StrongUse + extend T::Sig + + sig { void } + def call_them + s = StrongClass.new + _ = s.add_one(1) + _ = s.shout("hi") + nil + end +end diff --git a/test/scip/testdata/typed_strong.snapshot.rb b/test/scip/testdata/typed_strong.snapshot.rb new file mode 100644 index 000000000..7dabf47d7 --- /dev/null +++ b/test/scip/testdata/typed_strong.snapshot.rb @@ -0,0 +1,56 @@ + # typed: strong + + # At `typed: strong` Sorbet requires that nothing be T.untyped. Locks in + # indexer behavior for fully-typed code. + + class StrongClass +# ^^^^^^^^^^^ definition [..] StrongClass# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + + sig { params(x: Integer).returns(Integer) } +# ^^^^^^^ reference [..] Integer# +# ^^^^^^^ reference [..] Integer# + def add_one(x) +# ^^^^^^^ definition [..] StrongClass#add_one(). +# ^ definition local 1$272034907 + x + 1 +# ^ reference local 1$272034907 +# ^ reference [..] Integer#+(). + end + + sig { params(x: String).returns(String) } +# ^^^^^^ reference [..] String# +# ^^^^^^ reference [..] String# + def shout(x) +# ^^^^^ definition [..] StrongClass#shout(). +# ^ definition local 1$3089998242 + x.upcase +# ^ reference local 1$3089998242 +# ^^^^^^ reference [..] String#upcase(). + end + end + + class StrongUse +# ^^^^^^^^^ definition [..] StrongUse# + extend T::Sig +# ^^^^^^ reference [..] Kernel#extend(). + + sig { void } + def call_them +# ^^^^^^^^^ definition [..] StrongUse#call_them(). + s = StrongClass.new +# ^ definition local 1$1369514212 +# ^^^^^^^^^^^ reference [..] StrongClass# +# ^^^ reference [..] Class#new(). + _ = s.add_one(1) +# ^ definition local 3$1369514212 +# ^ reference local 1$1369514212 +# ^^^^^^^ reference [..] StrongClass#add_one(). + _ = s.shout("hi") +# ^ reference (write) local 3$1369514212 +# ^ reference local 1$1369514212 +# ^^^^^ reference [..] StrongClass#shout(). + nil + end + end diff --git a/test/scip/testdata/yield_block.rb b/test/scip/testdata/yield_block.rb new file mode 100644 index 000000000..f8b16f57c --- /dev/null +++ b/test/scip/testdata/yield_block.rb @@ -0,0 +1,24 @@ +# typed: true + +# Documents what (if anything) we emit around `yield`. CFGTraversal's switch +# in SCIPIndexer.cc treats YieldLoadArg / LoadYieldParams / YieldParamPresent +# as no-ops. + +def with_yield(x) + yield x + yield x + 1 +end + +def with_yield_no_args + yield + yield +end + +def use_blocks + total = 0 + with_yield(10) do |v| + total += v + end + with_yield_no_args { total += 1 } + total +end diff --git a/test/scip/testdata/yield_block.snapshot.rb b/test/scip/testdata/yield_block.snapshot.rb new file mode 100644 index 000000000..51c486f82 --- /dev/null +++ b/test/scip/testdata/yield_block.snapshot.rb @@ -0,0 +1,42 @@ + # typed: true + + # Documents what (if anything) we emit around `yield`. CFGTraversal's switch + # in SCIPIndexer.cc treats YieldLoadArg / LoadYieldParams / YieldParamPresent + # as no-ops. + + def with_yield(x) +# ^^^^^^^^^^ definition [..] Object#with_yield(). +# ^ definition local 1$1452685967 + yield x +# ^ reference local 1$1452685967 + yield x + 1 +# ^ reference local 1$1452685967 + end + + def with_yield_no_args +# ^^^^^^^^^^^^^^^^^^ definition [..] Object#with_yield_no_args(). + yield + yield + end + + def use_blocks +# ^^^^^^^^^^ definition [..] Object#use_blocks(). + total = 0 +# ^^^^^ definition local 1$1737801135 + with_yield(10) do |v| +# ^^^^^^^^^^ reference [..] Object#with_yield(). +# ^ definition local 2$1737801135 + total += v +# ^^^^^ reference (write) local 1$1737801135 +# ^^^^^ reference local 1$1737801135 +# ^^^^^^^^^^ reference local 1$1737801135 +# ^ reference local 2$1737801135 + end + with_yield_no_args { total += 1 } +# ^^^^^^^^^^^^^^^^^^ reference [..] Object#with_yield_no_args(). +# ^^^^^ reference (write) local 1$1737801135 +# ^^^^^ reference local 1$1737801135 +# ^^^^^^^^^^ reference local 1$1737801135 + total +# ^^^^^ reference local 1$1737801135 + end