diff --git a/Gemfile b/Gemfile
index eb4a5c6b1..8e01926f9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -58,6 +58,7 @@ group :development, :test do
gem "bcrypt"
gem "xpath"
gem "kredis"
+ gem "kaminari-activerecord"
end
group :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index 624949cd9..776f2cf7d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -179,6 +179,10 @@ GEM
faraday (>= 1.10, < 3.0)
faraday-gzip (>= 1.0, < 3.0)
rack (>= 0.2)
+ kaminari-activerecord (1.2.2)
+ activerecord
+ kaminari-core (= 1.2.2)
+ kaminari-core (1.2.2)
kramdown (2.5.1)
rexml (>= 3.3.9)
kredis (1.7.0)
@@ -384,6 +388,7 @@ DEPENDENCIES
identity_cache
irb
json_api_client
+ kaminari-activerecord
kramdown (~> 2.5)
kredis
minitest
diff --git a/lib/tapioca/dsl/compilers/kaminari.rb b/lib/tapioca/dsl/compilers/kaminari.rb
new file mode 100644
index 000000000..ef5fd8b69
--- /dev/null
+++ b/lib/tapioca/dsl/compilers/kaminari.rb
@@ -0,0 +1,83 @@
+# typed: strict
+# frozen_string_literal: true
+
+return unless defined?(Kaminari)
+
+require "tapioca/dsl/helpers/active_record_constants_helper"
+
+module Tapioca
+ module Dsl
+ module Compilers
+ # `Tapioca::Dsl::Compilers::Kaminari` decorates RBI files for models
+ # using Kaminari.
+ #
+ # For example, with Kaminari installed and the following `ActiveRecord::Base` subclass:
+ #
+ # ~~~rb
+ # class Post < ApplicationRecord
+ # end
+ # ~~~
+ #
+ # This compiler will produce the RBI file `post.rbi` with the following content:
+ #
+ # ~~~rbi
+ # # post.rbi
+ # # typed: true
+ # class Post
+ # extend GeneratedRelationMethods
+ #
+ # module GeneratedRelationMethods
+ # sig do
+ # params(
+ # num: T.any(Integer, String)
+ # ).returns(T.all(PrivateRelation, Kaminari::PageScopeMethods, Kaminari::ActiveRecordRelationMethods))
+ # end
+ # def page(num = nil); end
+ # end
+ # end
+ # ~~~
+ class Kaminari < Compiler
+ extend T::Sig
+ include Helpers::ActiveRecordConstantsHelper
+
+ ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
+
+ sig { override.void }
+ def decorate
+ root.create_path(constant) do |model|
+ target_modules.each do |module_name, return_type|
+ model.create_module(module_name).create_method(
+ ::Kaminari.config.page_method_name.to_s,
+ parameters: [create_opt_param("num", type: "T.any(Integer, String)", default: "nil")],
+ return_type: "T.all(#{return_type}, Kaminari::PageScopeMethods, Kaminari::ActiveRecordRelationMethods)",
+ )
+ end
+
+ model.create_extend(RelationMethodsModuleName)
+ end
+ end
+
+ class << self
+ sig { override.returns(T::Enumerable[Module]) }
+ def gather_constants
+ descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
+ end
+ end
+
+ private
+
+ sig { returns(T::Array[[String, String]]) }
+ def target_modules
+ if compiler_enabled?("ActiveRecordRelations")
+ [
+ [RelationMethodsModuleName, RelationClassName],
+ [AssociationRelationMethodsModuleName, AssociationRelationClassName],
+ ]
+ else
+ [[RelationMethodsModuleName, "T.untyped"]]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/manual/compiler_kaminari.md b/manual/compiler_kaminari.md
new file mode 100644
index 000000000..1b9f31c6c
--- /dev/null
+++ b/manual/compiler_kaminari.md
@@ -0,0 +1,30 @@
+## Kaminari
+
+`Tapioca::Dsl::Compilers::Kaminari` decorates RBI files for models
+using Kaminari.
+
+For example, with Kaminari installed and the following `ActiveRecord::Base` subclass:
+
+~~~rb
+class Post < ApplicationRecord
+end
+~~~
+
+This compiler will produce the RBI file `post.rbi` with the following content:
+
+~~~rbi
+# post.rbi
+# typed: true
+class Post
+ extend GeneratedRelationMethods
+
+ module GeneratedRelationMethods
+ sig do
+ params(
+ num: T.any(Integer, String)
+ ).returns(T.all(PrivateRelation, Kaminari::PageScopeMethods, Kaminari::ActiveRecordRelationMethods))
+ end
+ def page(num = nil); end
+ end
+end
+~~~
diff --git a/manual/compilers.md b/manual/compilers.md
index 2f2960b1b..ab4bf6603 100644
--- a/manual/compilers.md
+++ b/manual/compilers.md
@@ -32,6 +32,7 @@ In the following section you will find all available DSL compilers:
* [GraphqlMutation](compiler_graphqlmutation.md)
* [IdentityCache](compiler_identitycache.md)
* [JsonApiClientResource](compiler_jsonapiclientresource.md)
+* [Kaminari](compiler_kaminari.md)
* [Kredis](compiler_kredis.md)
* [MixedInClassAttributes](compiler_mixedinclassattributes.md)
* [Protobuf](compiler_protobuf.md)
diff --git a/sorbet/rbi/gems/kaminari-activerecord@1.2.2.rbi b/sorbet/rbi/gems/kaminari-activerecord@1.2.2.rbi
new file mode 100644
index 000000000..0777268d0
--- /dev/null
+++ b/sorbet/rbi/gems/kaminari-activerecord@1.2.2.rbi
@@ -0,0 +1,106 @@
+# typed: true
+
+# DO NOT EDIT MANUALLY
+# This is an autogenerated file for types exported from the `kaminari-activerecord` gem.
+# Please instead update this file by running `bin/tapioca gem kaminari-activerecord`.
+
+
+# source://kaminari-activerecord/lib/kaminari/activerecord/version.rb#3
+module Kaminari
+ class << self
+ # source://kaminari-core/1.2.2lib/kaminari/config.rb#13
+ def config; end
+
+ # source://kaminari-core/1.2.2lib/kaminari/config.rb#9
+ def configure; end
+
+ # source://kaminari-core/1.2.2lib/kaminari/models/array_extension.rb#70
+ def paginate_array(array, limit: T.unsafe(nil), offset: T.unsafe(nil), total_count: T.unsafe(nil), padding: T.unsafe(nil)); end
+ end
+end
+
+# source://kaminari-activerecord/lib/kaminari/activerecord/active_record_extension.rb#6
+module Kaminari::ActiveRecordExtension
+ extend ::ActiveSupport::Concern
+
+ mixes_in_class_methods ::Kaminari::ActiveRecordExtension::ClassMethods
+end
+
+# source://kaminari-activerecord/lib/kaminari/activerecord/active_record_extension.rb#9
+module Kaminari::ActiveRecordExtension::ClassMethods
+ # Future subclasses will pick up the model extension
+ #
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_extension.rb#11
+ def inherited(kls); end
+end
+
+# source://kaminari-activerecord/lib/kaminari/activerecord/active_record_model_extension.rb#6
+module Kaminari::ActiveRecordModelExtension
+ extend ::ActiveSupport::Concern
+ include ::Kaminari::ConfigurationMethods
+
+ mixes_in_class_methods ::Kaminari::ConfigurationMethods::ClassMethods
+end
+
+# Active Record specific page scope methods implementations
+#
+# source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#5
+module Kaminari::ActiveRecordRelationMethods
+ # Used for page_entry_info
+ #
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#7
+ def entry_name(options = T.unsafe(nil)); end
+
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#12
+ def reset; end
+
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#17
+ def total_count(column_name = T.unsafe(nil), _options = T.unsafe(nil)); end
+
+ # Turn this Relation to a "without count mode" Relation.
+ # Note that the "without count mode" is supposed to be performant but has a feature limitation.
+ # Pro: paginates without casting an extra SELECT COUNT query
+ # Con: unable to know the total number of records/pages
+ #
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#50
+ def without_count; end
+end
+
+# source://kaminari-activerecord/lib/kaminari/activerecord/version.rb#4
+module Kaminari::Activerecord; end
+
+# source://kaminari-activerecord/lib/kaminari/activerecord/version.rb#5
+Kaminari::Activerecord::VERSION = T.let(T.unsafe(nil), String)
+
+# A module that makes AR::Relation paginatable without having to cast another SELECT COUNT query
+#
+# source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#56
+module Kaminari::PaginatableWithoutCount
+ # The page wouldn't be the last page if there's "limit + 1" record
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#109
+ def last_page?; end
+
+ # Overwrite AR::Relation#load to actually load one more record to judge if the page has next page
+ # then store the result in @_has_next ivar
+ #
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#90
+ def load; end
+
+ # Empty relation needs no pagination
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#114
+ def out_of_range?; end
+
+ # Force to raise an exception if #total_count is called explicitly.
+ #
+ # source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#120
+ def total_count; end
+end
+
+# source://kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#57
+module Kaminari::PaginatableWithoutCount::LimitValueSetter; end
diff --git a/sorbet/rbi/gems/kaminari-core@1.2.2.rbi b/sorbet/rbi/gems/kaminari-core@1.2.2.rbi
new file mode 100644
index 000000000..c976c218c
--- /dev/null
+++ b/sorbet/rbi/gems/kaminari-core@1.2.2.rbi
@@ -0,0 +1,657 @@
+# typed: true
+
+# DO NOT EDIT MANUALLY
+# This is an autogenerated file for types exported from the `kaminari-core` gem.
+# Please instead update this file by running `bin/tapioca gem kaminari-core`.
+
+
+# source://kaminari-core/lib/kaminari/core.rb#3
+module Kaminari
+ class << self
+ # source://kaminari-core/lib/kaminari/config.rb#13
+ def config; end
+
+ # @yield [config]
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#9
+ def configure; end
+
+ # Wrap an Array object to make it paginatable
+ # ==== Options
+ # * :limit - limit
+ # * :offset - offset
+ # * :total_count - total_count
+ # * :padding - padding
+ #
+ # source://kaminari-core/lib/kaminari/models/array_extension.rb#70
+ def paginate_array(array, limit: T.unsafe(nil), offset: T.unsafe(nil), total_count: T.unsafe(nil), padding: T.unsafe(nil)); end
+ end
+end
+
+# source://kaminari-core/lib/kaminari/config.rb#18
+class Kaminari::Config
+ # @return [Config] a new instance of Config
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#22
+ def initialize; end
+
+ # Returns the value of attribute default_per_page.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def default_per_page; end
+
+ # Sets the attribute default_per_page
+ #
+ # @param value the value to set the attribute default_per_page to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def default_per_page=(_arg0); end
+
+ # Returns the value of attribute left.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def left; end
+
+ # Sets the attribute left
+ #
+ # @param value the value to set the attribute left to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def left=(_arg0); end
+
+ # Returns the value of attribute max_pages.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def max_pages; end
+
+ # Sets the attribute max_pages
+ #
+ # @param value the value to set the attribute max_pages to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def max_pages=(_arg0); end
+
+ # Returns the value of attribute max_per_page.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def max_per_page; end
+
+ # Sets the attribute max_per_page
+ #
+ # @param value the value to set the attribute max_per_page to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def max_per_page=(_arg0); end
+
+ # Returns the value of attribute outer_window.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def outer_window; end
+
+ # Sets the attribute outer_window
+ #
+ # @param value the value to set the attribute outer_window to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def outer_window=(_arg0); end
+
+ # Returns the value of attribute page_method_name.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def page_method_name; end
+
+ # Sets the attribute page_method_name
+ #
+ # @param value the value to set the attribute page_method_name to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def page_method_name=(_arg0); end
+
+ # If param_name was given as a callable object, call it when returning
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#36
+ def param_name; end
+
+ # Sets the attribute param_name
+ #
+ # @param value the value to set the attribute param_name to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#20
+ def param_name=(_arg0); end
+
+ # Returns the value of attribute params_on_first_page.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def params_on_first_page; end
+
+ # Sets the attribute params_on_first_page
+ #
+ # @param value the value to set the attribute params_on_first_page to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def params_on_first_page=(_arg0); end
+
+ # Returns the value of attribute right.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def right; end
+
+ # Sets the attribute right
+ #
+ # @param value the value to set the attribute right to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def right=(_arg0); end
+
+ # Returns the value of attribute window.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def window; end
+
+ # Sets the attribute window
+ #
+ # @param value the value to set the attribute window to.
+ #
+ # source://kaminari-core/lib/kaminari/config.rb#19
+ def window=(_arg0); end
+end
+
+# source://kaminari-core/lib/kaminari/models/configuration_methods.rb#6
+module Kaminari::ConfigurationMethods
+ extend ::ActiveSupport::Concern
+
+ mixes_in_class_methods ::Kaminari::ConfigurationMethods::ClassMethods
+end
+
+# source://kaminari-core/lib/kaminari/models/configuration_methods.rb#8
+module Kaminari::ConfigurationMethods::ClassMethods
+ # This model's default +per_page+ value
+ # returns +default_per_page+ value unless explicitly overridden via paginates_per
+ #
+ # source://kaminari-core/lib/kaminari/models/configuration_methods.rb#19
+ def default_per_page; end
+
+ # Overrides the max_pages value per model when a value is given
+ # class Article < ActiveRecord::Base
+ # max_pages 100
+ # end
+ #
+ # Also returns this model's max_pages value (globally configured
+ # +max_pages+ value unless explicitly overridden) when no value is given
+ #
+ # source://kaminari-core/lib/kaminari/models/configuration_methods.rb#44
+ def max_pages(val = T.unsafe(nil)); end
+
+ # source://kaminari-core/lib/kaminari/models/configuration_methods.rb#54
+ def max_pages_per(val); end
+
+ # Overrides the max +per_page+ value per model
+ # class Article < ActiveRecord::Base
+ # max_paginates_per 100
+ # end
+ #
+ # source://kaminari-core/lib/kaminari/models/configuration_methods.rb#27
+ def max_paginates_per(val); end
+
+ # This model's max +per_page+ value
+ # returns +max_per_page+ value unless explicitly overridden via max_paginates_per
+ #
+ # source://kaminari-core/lib/kaminari/models/configuration_methods.rb#33
+ def max_per_page; end
+
+ # Overrides the default +per_page+ value per model
+ # class Article < ActiveRecord::Base
+ # paginates_per 10
+ # end
+ #
+ # source://kaminari-core/lib/kaminari/models/configuration_methods.rb#13
+ def paginates_per(val); end
+end
+
+# source://kaminari-core/lib/kaminari/engine.rb#4
+class Kaminari::Engine < ::Rails::Engine; end
+
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#4
+module Kaminari::Helpers; end
+
+# Link with page number that appears at the leftmost
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#103
+class Kaminari::Helpers::FirstPage < ::Kaminari::Helpers::Tag
+ include ::Kaminari::Helpers::Link
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#105
+ def page; end
+end
+
+# Non-link tag that stands for skipped pages...
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#161
+class Kaminari::Helpers::Gap < ::Kaminari::Helpers::Tag; end
+
+# Link with page number that appears at the rightmost
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#111
+class Kaminari::Helpers::LastPage < ::Kaminari::Helpers::Tag
+ include ::Kaminari::Helpers::Link
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#113
+ def page; end
+end
+
+# Tag that contains a link
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#74
+module Kaminari::Helpers::Link
+ # target page number
+ #
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#76
+ def page; end
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#83
+ def to_s(locals = T.unsafe(nil)); end
+
+ # the link's href
+ #
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#80
+ def url; end
+end
+
+# The "next" page of the current page
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#140
+class Kaminari::Helpers::NextPage < ::Kaminari::Helpers::Tag
+ include ::Kaminari::Helpers::Link
+
+ # TODO: Remove this initializer before 1.3.0.
+ #
+ # @return [NextPage] a new instance of NextPage
+ #
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#144
+ def initialize(template, params: T.unsafe(nil), param_name: T.unsafe(nil), theme: T.unsafe(nil), views_prefix: T.unsafe(nil), **options); end
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#155
+ def page; end
+end
+
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#5
+Kaminari::Helpers::PARAM_KEY_EXCEPT_LIST = T.let(T.unsafe(nil), Array)
+
+# A page
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#90
+class Kaminari::Helpers::Page < ::Kaminari::Helpers::Tag
+ include ::Kaminari::Helpers::Link
+
+ # target page number
+ #
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#93
+ def page; end
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#96
+ def to_s(locals = T.unsafe(nil)); end
+end
+
+# The main container tag
+#
+# source://kaminari-core/lib/kaminari/helpers/paginator.rb#9
+class Kaminari::Helpers::Paginator < ::Kaminari::Helpers::Tag
+ # @return [Paginator] a new instance of Paginator
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#10
+ def initialize(template, window: T.unsafe(nil), outer_window: T.unsafe(nil), left: T.unsafe(nil), right: T.unsafe(nil), inner_window: T.unsafe(nil), **options); end
+
+ # enumerate each page providing PageProxy object as the block parameter
+ # Because of performance reason, this doesn't actually enumerate all pages but pages that are seemingly relevant to the paginator.
+ # "Relevant" pages are:
+ # * pages inside the left outer window plus one for showing the gap tag
+ # * pages inside the inner window plus one on the left plus one on the right for showing the gap tags
+ # * pages inside the right outer window plus one for showing the gap tag
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#43
+ def each_page; end
+
+ # enumerate each page providing PageProxy object as the block parameter
+ # Because of performance reason, this doesn't actually enumerate all pages but pages that are seemingly relevant to the paginator.
+ # "Relevant" pages are:
+ # * pages inside the left outer window plus one for showing the gap tag
+ # * pages inside the inner window plus one on the left plus one on the right for showing the gap tags
+ # * pages inside the right outer window plus one for showing the gap tag
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#43
+ def each_relevant_page; end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#67
+ def first_page_tag; end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#67
+ def gap_tag; end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#67
+ def last_page_tag; end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#67
+ def next_page_tag; end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#61
+ def page_tag(page); end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#67
+ def prev_page_tag; end
+
+ # render given block as a view template
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#28
+ def render(&block); end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#73
+ def to_s; end
+
+ private
+
+ # delegates view helper methods to @template
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#81
+ def method_missing(name, *args, &block); end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#52
+ def relevant_pages(options); end
+end
+
+# Wraps a "page number" and provides some utility methods
+#
+# source://kaminari-core/lib/kaminari/helpers/paginator.rb#87
+class Kaminari::Helpers::Paginator::PageProxy
+ include ::Comparable
+
+ # @return [PageProxy] a new instance of PageProxy
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#90
+ def initialize(options, page, last); end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#177
+ def +(other); end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#181
+ def -(other); end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#185
+ def <=>(other); end
+
+ # current page or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#100
+ def current?; end
+
+ # Should we display the link tag?
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#165
+ def display_tag?; end
+
+ # the first page or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#105
+ def first?; end
+
+ # inside the inner window or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#144
+ def inside_window?; end
+
+ # the last page or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#110
+ def last?; end
+
+ # within the left outer window or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#134
+ def left_outer?; end
+
+ # the next page or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#120
+ def next?; end
+
+ # the page number
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#95
+ def number; end
+
+ # The page number exceeds the range of pages or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#155
+ def out_of_range?; end
+
+ # the previous page or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#115
+ def prev?; end
+
+ # relationship with the current page
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#125
+ def rel; end
+
+ # within the right outer window or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#139
+ def right_outer?; end
+
+ # Current page is an isolated gap or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#149
+ def single_gap?; end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#169
+ def to_i; end
+
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#173
+ def to_s; end
+
+ # The last rendered tag was "truncated" or not
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/helpers/paginator.rb#160
+ def was_truncated?; end
+end
+
+# The "previous" page of the current page
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#119
+class Kaminari::Helpers::PrevPage < ::Kaminari::Helpers::Tag
+ include ::Kaminari::Helpers::Link
+
+ # TODO: Remove this initializer before 1.3.0.
+ #
+ # @return [PrevPage] a new instance of PrevPage
+ #
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#123
+ def initialize(template, params: T.unsafe(nil), param_name: T.unsafe(nil), theme: T.unsafe(nil), views_prefix: T.unsafe(nil), **options); end
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#134
+ def page; end
+end
+
+# A tag stands for an HTML tag inside the paginator.
+# Basically, a tag has its own partial template file, so every tag can be
+# rendered into String using its partial template.
+#
+# The template file should be placed in your app/views/kaminari/ directory
+# with underscored class name (besides the "Tag" class. Tag is an abstract
+# class, so _tag partial is not needed).
+# e.g.) PrevLink -> app/views/kaminari/_prev_link.html.erb
+#
+# When no matching templates were found in your app, the engine's pre
+# installed template will be used.
+# e.g.) Paginator -> $GEM_HOME/kaminari-x.x.x/app/views/kaminari/_paginator.html.erb
+#
+# source://kaminari-core/lib/kaminari/helpers/tags.rb#19
+class Kaminari::Helpers::Tag
+ # @return [Tag] a new instance of Tag
+ #
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#20
+ def initialize(template, params: T.unsafe(nil), param_name: T.unsafe(nil), theme: T.unsafe(nil), views_prefix: T.unsafe(nil), **options); end
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#36
+ def page_url_for(page); end
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#31
+ def to_s(locals = T.unsafe(nil)); end
+
+ private
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#44
+ def params_for(page); end
+
+ # source://kaminari-core/lib/kaminari/helpers/tags.rb#63
+ def partial_path; end
+end
+
+# source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#4
+module Kaminari::PageScopeMethods
+ # Current page number
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#47
+ def current_page; end
+
+ # Current per-page number
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#58
+ def current_per_page; end
+
+ # First page of the collection?
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#77
+ def first_page?; end
+
+ # Last page of the collection?
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#82
+ def last_page?; end
+
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#21
+ def max_paginates_per(new_max_per_page); end
+
+ # Next page number in the collection
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#67
+ def next_page; end
+
+ # Out of range of the collection?
+ #
+ # @return [Boolean]
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#87
+ def out_of_range?; end
+
+ # @raise [ArgumentError]
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#27
+ def padding(num); end
+
+ # Specify the per_page value for the preceding page scope
+ # Model.page(3).per(10)
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#7
+ def per(num, max_per_page: T.unsafe(nil)); end
+
+ # Previous page number in the collection
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#72
+ def prev_page; end
+
+ # Total number of pages
+ #
+ # source://kaminari-core/lib/kaminari/models/page_scope_methods.rb#35
+ def total_pages; end
+end
+
+# Kind of Array that can paginate
+#
+# source://kaminari-core/lib/kaminari/models/array_extension.rb#6
+class Kaminari::PaginatableArray < ::Array
+ include ::Kaminari::ConfigurationMethods::ClassMethods
+
+ # ==== Options
+ # * :limit - limit
+ # * :offset - offset
+ # * :total_count - total_count
+ # * :padding - padding
+ #
+ # @return [PaginatableArray] a new instance of PaginatableArray
+ #
+ # source://kaminari-core/lib/kaminari/models/array_extension.rb#18
+ def initialize(original_array = T.unsafe(nil), limit: T.unsafe(nil), offset: T.unsafe(nil), total_count: T.unsafe(nil), padding: T.unsafe(nil)); end
+
+ # Used for page_entry_info
+ #
+ # source://kaminari-core/lib/kaminari/models/array_extension.rb#37
+ def entry_name(options = T.unsafe(nil)); end
+
+ # returns another chunk of the original array
+ #
+ # source://kaminari-core/lib/kaminari/models/array_extension.rb#49
+ def limit(num); end
+
+ # source://activesupport/7.1.5lib/active_support/core_ext/module/attr_internal.rb#33
+ def limit_value; end
+
+ # source://activesupport/7.1.5lib/active_support/core_ext/module/attr_internal.rb#33
+ def limit_value=(_arg0); end
+
+ # returns another chunk of the original array
+ #
+ # source://kaminari-core/lib/kaminari/models/array_extension.rb#59
+ def offset(num); end
+
+ # source://activesupport/7.1.5lib/active_support/core_ext/module/attr_internal.rb#33
+ def offset_value; end
+
+ # source://activesupport/7.1.5lib/active_support/core_ext/module/attr_internal.rb#33
+ def offset_value=(_arg0); end
+
+ # source://kaminari-core/lib/kaminari/models/array_extension.rb#43
+ def page(num = T.unsafe(nil)); end
+
+ # total item numbers of the original array
+ #
+ # source://kaminari-core/lib/kaminari/models/array_extension.rb#54
+ def total_count; end
+end
+
+# source://kaminari-core/lib/kaminari/models/array_extension.rb#9
+Kaminari::PaginatableArray::ENTRY = T.let(T.unsafe(nil), String)
+
+# source://kaminari-core/lib/kaminari/railtie.rb#5
+class Kaminari::Railtie < ::Rails::Railtie; end
+
+# source://kaminari-core/lib/kaminari/exceptions.rb#4
+class Kaminari::ZeroPerPageOperation < ::ZeroDivisionError; end
diff --git a/spec/tapioca/dsl/compilers/kaminari_spec.rb b/spec/tapioca/dsl/compilers/kaminari_spec.rb
new file mode 100644
index 000000000..db43873a8
--- /dev/null
+++ b/spec/tapioca/dsl/compilers/kaminari_spec.rb
@@ -0,0 +1,102 @@
+# typed: strict
+# frozen_string_literal: true
+
+require "spec_helper"
+
+module Tapioca
+ module Dsl
+ module Compilers
+ class KaminariSpec < ::DslSpec
+ describe "Tapioca::Dsl::Compilers::Kaminari" do
+ sig { void }
+ def before_setup
+ require "active_record"
+ require "kaminari/activerecord"
+ end
+
+ describe "initialize" do
+ it "gathers no constants if there are no ActiveRecord classes" do
+ assert_empty(gathered_constants)
+ end
+
+ it "gathers only ActiveRecord constants with no abstract classes" do
+ add_ruby_file("post.rb", <<~RUBY)
+ class Post < ActiveRecord::Base
+ end
+
+ class Product < ActiveRecord::Base
+ self.abstract_class = true
+ end
+
+ class User
+ end
+ RUBY
+
+ assert_equal(["Post"], gathered_constants)
+ end
+ end
+
+ describe "decorate" do
+ describe "with relations enabled" do
+ before do
+ require "tapioca/dsl/compilers/active_record_relations"
+ activate_other_dsl_compilers(ActiveRecordRelations)
+ end
+
+ it "generates an RBI file" do
+ add_ruby_file("post.rb", <<~RUBY)
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ expected = <<~RBI
+ # typed: strong
+
+ class Post
+ extend GeneratedRelationMethods
+
+ module GeneratedAssociationRelationMethods
+ sig { params(num: T.any(Integer, String)).returns(T.all(PrivateAssociationRelation, Kaminari::PageScopeMethods, Kaminari::ActiveRecordRelationMethods)) }
+ def page(num = nil); end
+ end
+
+ module GeneratedRelationMethods
+ sig { params(num: T.any(Integer, String)).returns(T.all(PrivateRelation, Kaminari::PageScopeMethods, Kaminari::ActiveRecordRelationMethods)) }
+ def page(num = nil); end
+ end
+ end
+ RBI
+
+ assert_equal(expected, rbi_for(:Post))
+ end
+ end
+
+ describe "without relations enabled" do
+ it "generates an RBI file" do
+ add_ruby_file("post.rb", <<~RUBY)
+ class Post < ActiveRecord::Base
+ end
+ RUBY
+
+ expected = <<~RBI
+ # typed: strong
+
+ class Post
+ extend GeneratedRelationMethods
+
+ module GeneratedRelationMethods
+ sig { params(num: T.any(Integer, String)).returns(T.all(T.untyped, Kaminari::PageScopeMethods, Kaminari::ActiveRecordRelationMethods)) }
+ def page(num = nil); end
+ end
+ end
+ RBI
+
+ assert_equal(expected, rbi_for(:Post))
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end