module RBS
  interface _MethodName
    def kind: () -> (:instance | :singleton)

    def type_name: () -> TypeName

    def method_name: () -> Symbol
  end

  module MethodNameHelper : _MethodName
    def method_name_string: () -> String
  end

  # Error class for errors defined in RBS.
  #
  class BaseError < StandardError
  end

  interface _Location
    %a{pure} def location: () -> Location[untyped, untyped]?
  end

  module DetailedMessageable : _Location, Exception
    def detailed_message: (?highlight: boolish, **untyped) -> String
  end

  # Error class for errors raised during parsing.
  #
  class ParsingError < BaseError
    include DetailedMessageable

    attr_reader location: Location[untyped, untyped]
    attr_reader error_message: String
    attr_reader token_type: String

    def initialize: (Location[untyped, untyped], String error_message, String token_type) -> void

    def error_value: () -> String

    def token_str: () -> String
  end

  class Parser
    SemanticsError: singleton(ParsingError)
    SyntaxError: singleton(ParsingError)
    LexerError: singleton(ParsingError)
  end

  # Error class for errors raised during loading environments.
  #
  class LoadingError < BaseError
  end

  # Error class for errors raised during building definitions.
  #
  class DefinitionError < BaseError
  end

  class InvalidTypeApplicationError < DefinitionError
    attr_reader type_name: TypeName
    attr_reader args: Array[Types::t]
    attr_reader params: Array[Symbol]
    attr_reader type_params: Array[AST::TypeParam]
    attr_reader location: Location[untyped, untyped]?

    def initialize: (type_name: TypeName, args: Array[Types::t], params: Array[AST::TypeParam], location: Location[untyped, untyped]?) -> void

    def self.check!: (type_name: TypeName, args: Array[Types::t], params: Array[AST::TypeParam], location: Location[untyped, untyped]?) -> void

    def self.check2!: (env: Environment, type_name: TypeName, args: Array[Types::t], location: Location[untyped, untyped]?) -> void
  end

  class RecursiveAncestorError < DefinitionError
    attr_reader ancestors: Array[Definition::Ancestor::t]
    attr_reader location: Location[untyped, untyped]?

    def initialize: (ancestors: Array[Definition::Ancestor::t], location: Location[untyped, untyped]?) -> void

    def self.check!: (Definition::Ancestor::t, ancestors: Array[Definition::Ancestor::t], location: Location[untyped, untyped]?) -> void
  end

  class NoTypeFoundError < DefinitionError
    include DetailedMessageable

    attr_reader type_name: TypeName
    attr_reader location: Location[untyped, untyped]?

    def initialize: (type_name: TypeName, location: Location[untyped, untyped]?) -> void

    def self.check!: (TypeName, env: Environment, location: Location[untyped, untyped]?) -> TypeName
  end

  class NoSuperclassFoundError < DefinitionError
    attr_reader type_name: TypeName
    attr_reader location: Location[untyped, untyped]?

    def initialize: (type_name: TypeName, location: Location[untyped, untyped]?) -> void

    def self.check!: (TypeName, env: Environment, location: Location[untyped, untyped]?) -> void
  end

  class NoSelfTypeFoundError < DefinitionError
    include DetailedMessageable

    attr_reader type_name: TypeName
    attr_reader location: Location[untyped, untyped]?

    def initialize: (type_name: TypeName, location: Location[untyped, untyped]?) -> void

    # The type name in `self` is automatically normalized
    #
    def self.check!: (AST::Declarations::Module::Self, env: Environment) -> void
  end

  class NoMixinFoundError < DefinitionError
    include DetailedMessageable

    attr_reader type_name: TypeName
    attr_reader member: AST::Members::t

    def initialize: (type_name: TypeName, member: AST::Members::t) -> void

    def location: () -> Location[untyped, untyped]?

    def self.check!: (TypeName, env: Environment, member: AST::Members::t) -> void
  end

  class DuplicatedMethodDefinitionError < DefinitionError
    include DetailedMessageable

    type ty = Types::ClassSingleton | Types::ClassInstance | Types::Interface
    type original = DefinitionBuilder::MethodBuilder::Methods::Definition::original

    attr_reader type: ty
    attr_reader method_name: Symbol
    attr_reader members: Array[original]

    def initialize: (type: ty, method_name: Symbol, members: Array[original]) -> void

    def type_name: () -> TypeName

    def qualified_method_name: () -> String

    def location: () -> Location[untyped, untyped]?

    def other_locations: () -> Array[Location[untyped, untyped]?]
  end

  # An interface mixin causes a duplication of a method definition
  #
  # ```rbs
  # interface _Foo1
  #   def foo: () -> void
  # end
  #
  # interface _Foo2
  #   def foo: () -> void
  # end
  #
  # class Foo
  #   include _Foo1
  #   include _Foo2    # <= The error will be reported here (or the line of _Foo1)
  # end
  # ```
  #
  class DuplicatedInterfaceMethodDefinitionError < DefinitionError
    include DetailedMessageable

    type ty = Types::ClassSingleton | Types::ClassInstance | Types::Interface
    type mixin_member = AST::Members::Include | AST::Members::Extend

    attr_reader type: ty
    attr_reader method_name: Symbol
    attr_reader member: mixin_member

    def initialize: (type: ty, method_name: Symbol, member: mixin_member) -> void

    def type_name: () -> TypeName

    def qualified_method_name: () -> String

    def location: () -> AST::Members::Mixin::loc?
  end

  # The `alias` member declares an alias from unknown method
  #
  class UnknownMethodAliasError < DefinitionError
    include DetailedMessageable

    attr_reader type_name: TypeName
    attr_reader original_name: Symbol
    attr_reader aliased_name: Symbol
    attr_reader location: Location[untyped, untyped]?

    def initialize: (type_name: TypeName, original_name: Symbol, aliased_name: Symbol, location: Location[untyped, untyped]?) -> void
  end

  class SuperclassMismatchError < DefinitionError
    attr_reader name: TypeName
    attr_reader entry: Environment::ClassEntry

    def initialize: (name: TypeName, entry: Environment::ClassEntry) -> void
  end

  # The *overloading* method definition cannot find *non-overloading* method definition
  #
  class InvalidOverloadMethodError < DefinitionError
    include DetailedMessageable

    attr_reader type_name: TypeName
    attr_reader method_name: Symbol
    attr_reader kind: :instance | :singleton
    attr_reader members: Array[AST::Members::MethodDefinition]

    def initialize: (type_name: TypeName, method_name: Symbol, kind: :instance | :singleton, members: Array[AST::Members::MethodDefinition]) -> void

    def location: () -> AST::Members::MethodDefinition::loc?
  end

  class GenericParameterMismatchError < LoadingError
    attr_reader name: TypeName
    attr_reader decl: AST::Declarations::Class | AST::Declarations::Module

    def initialize: (name: TypeName, decl: AST::Declarations::Class | AST::Declarations::Module) -> void
  end

  class DuplicatedDeclarationError < LoadingError
    attr_reader name: TypeName | Symbol
    attr_reader decls: Array[AST::Declarations::t]

    def initialize: (TypeName | Symbol, *AST::Declarations::t) -> void
  end

  class InvalidVarianceAnnotationError < DefinitionError
    include DetailedMessageable

    attr_reader type_name: TypeName
    attr_reader param: AST::TypeParam
    attr_reader location: Location[untyped, untyped]?

    def initialize: (type_name: TypeName, param: AST::TypeParam, location: Location[untyped, untyped]?) -> void
  end

  class RecursiveAliasDefinitionError < DefinitionError
    include DetailedMessageable

    type ty = Types::ClassInstance | Types::ClassSingleton | Types::Interface
    type defn = DefinitionBuilder::MethodBuilder::Methods::Definition

    attr_reader type: ty
    attr_reader defs: Array[defn]

    def initialize: (type: ty, defs: Array[defn]) -> void

    def location: () -> Location[untyped, untyped]?
  end

  # MixinClassError is raised if a include/prepend/extend has a class (not a module) to mix-in
  #
  class MixinClassError < DefinitionError
    include DetailedMessageable

    type member = AST::Members::Include | AST::Members::Prepend | AST::Members::Extend

    attr_reader type_name: TypeName
    attr_reader member: member

    def initialize: (type_name: TypeName, member: member) -> void

    def location: () -> Location[untyped, untyped]?

    def self.check!: (type_name: TypeName, env: Environment, member: member) -> void

    def mixin_name: () -> String
  end

  # InheritModuleError is raised if a class definition inherits a module (not a class)
  #
  class InheritModuleError < DefinitionError
    include DetailedMessageable

    attr_reader super_decl: AST::Declarations::Class::Super

    def initialize: (AST::Declarations::Class::Super) -> void

    def location: () -> Location[untyped, untyped]?

    # Confirms if `super` inherits specifies a class
    #
    # Automatically normalize the name of super.
    #
    def self.check!: (AST::Declarations::Class::Super, env: Environment) -> void
  end

  class RecursiveTypeAliasError < BaseError
    include DetailedMessageable

    attr_reader alias_names: Array[TypeName]
    attr_reader location: Location[untyped, untyped]?

    def initialize: (alias_names: Array[TypeName], location: Location[untyped, untyped]?) -> void

    def name: () -> String
  end

  class NonregularTypeAliasError < BaseError
    include DetailedMessageable

    # Diagnostic reported from `TypeAliasRegularity`.
    attr_reader diagnostic: TypeAliasRegularity::Diagnostic

    # Location of the definition.
    attr_reader location: Location[untyped, untyped]?

    def initialize: (diagnostic: TypeAliasRegularity::Diagnostic, location: Location[untyped, untyped]?) -> void
  end

  class CyclicTypeParameterBound < BaseError
    include DetailedMessageable

    attr_reader location: Location[untyped, untyped]?

    # Array of parameters which contains cyclic dependencies.
    attr_reader params: Array[AST::TypeParam]

    # Type name
    attr_reader type_name: TypeName

    # Method name
    attr_reader method_name: Symbol?

    def initialize: (type_name: TypeName, method_name: Symbol?, params: Array[AST::TypeParam], location: Location[untyped, untyped]?) -> void
  end

  # A module/class alias declaration has inconsistent right-hand-side
  #
  # ```rbs
  # module Foo = Object     # Error
  # class Bar = Kernel      # Error
  # ```
  #
  class InconsistentClassModuleAliasError < BaseError
    include DetailedMessageable

    attr_reader alias_entry: Environment::ModuleAliasEntry | Environment::ClassAliasEntry

    def initialize: (Environment::ModuleAliasEntry | Environment::ClassAliasEntry) -> void

    def location: () -> AST::Declarations::AliasDecl::loc?
  end

  # A module/class alias declaration is cyclic
  #
  class CyclicClassAliasDefinitionError < BaseError
    include DetailedMessageable

    attr_reader alias_entry: Environment::ModuleAliasEntry | Environment::ClassAliasEntry

    def initialize: (Environment::ModuleAliasEntry | Environment::ClassAliasEntry) -> void

    def location: () -> AST::Declarations::AliasDecl::loc?
  end

  class WillSyntaxError < BaseError
    include RBS::DetailedMessageable

    def initialize: (String message, location: Location[untyped, untyped]?) -> void

    attr_reader location: Location[untyped, untyped]?
  end

  class TypeParamDefaultReferenceError < BaseError
    include DetailedMessageable

    attr_reader type_param: AST::TypeParam

    def initialize: (AST::TypeParam, location: Location[untyped, untyped]?) -> void

    attr_reader location: Location[untyped, untyped]?

    def self.check!: (Array[AST::TypeParam]) -> void
  end
end
