class RBS::TypeAliasRegularity - rbs: Ruby Standard Library Documentation

# class RBS::TypeAliasRegularity

### Attributes

builder[R]
diagnostics[R]
env[R]

### Public Class Methods

new(env:) click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 16
    def initialize(env:)
      @env = env
      @builder = DefinitionBuilder.new(env: env)
      @diagnostics = {}
    end

validate(env:) click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 120
    def self.validate(env:)
      self.new(env: env).tap do |validator|
        validator.validate()
      end
    end

### Public Instance Methods

build_alias_type(name) click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 61
    def build_alias_type(name)
      entry = env.type_alias_decls[name] or return
      unless entry.decl.type_params.empty?
        as = entry.decl.type_params.each.map {|param| Types::Variable.new(name: param.name, location: nil) }
        Types::Alias.new(name: name, args: as, location: nil)
      end
    end

compatible_args?(args1, args2) click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 69
    def compatible_args?(args1, args2)
      if args1.size == args2.size
        args1.zip(args2).all? do |t1, t2|
          t1.is_a?(Types::Bases::Any) ||
            t2.is_a?(Types::Bases::Any) ||
            t1 == t2
        end
      end
    end

each_alias_type(type) { |type| ... } click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 110
    def each_alias_type(type, &block)
      if type.is_a?(RBS::Types::Alias)
        yield type
      end

      type.each_type do |ty|
        each_alias_type(ty, &block)
      end
    end

each_mutual_alias_defs() { |set| ... } click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 83
    def each_mutual_alias_defs(&block)
      # @type var each_node: ^() { (TypeName) -> void } -> void
      each_node = -> (&block) do
        env.type_alias_decls.each_value do |decl|
          if normalized = env.normalize_type_name?(decl.name)
            block[normalized]
          end
        end
      end

      # @type var each_child: ^(TypeName) { (TypeName) -> void } -> void
      each_child = -> (name, &block) do
        if env.type_alias_decls.key?(name)
          type = builder.expand_alias1(name)
          each_alias_type(type) do |ty|
            if normalized = env.normalize_type_name?(ty.name)
              block[normalized]
            end
          end
        end
      end

      TSort.each_strongly_connected_component(each_node, each_child) do |names|
        yield Set.new(names)
      end
    end

nonregular?(type_name) click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 79
    def nonregular?(type_name)
      diagnostics[env.normalize_type_name!(type_name)]
    end

validate() click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 22
    def validate
      diagnostics.clear

      each_mutual_alias_defs do |names|
        # Find the first generic type alias in strongly connected component.
        # This is to skip the regularity check when the alias is not generic.
        names.each do |name|
          # @type break: nil
          if type = build_alias_type(name)
            # Running validation only once from the first generic type is enough, because they are mutual recursive definition.
            validate_alias_type(type, names, {})
            break
          end
        end
      end
    end

validate_alias_type(alias_type, names, types) click to toggle source

    # File rbs-3.8.0/lib/rbs/type_alias_regularity.rb, line 39
    def validate_alias_type(alias_type, names, types)
      alias_name = env.normalize_type_name?(alias_type.name) or return

      if names.include?(alias_name)
        if ex_type = types[alias_name]
          unless compatible_args?(ex_type.args, alias_type.args)
            diagnostics[alias_name] ||=
              Diagnostic.new(type_name: alias_type.name, nonregular_type: alias_type)
          end

          return
        else
          types[alias_type.name] = alias_type
        end

        expanded = builder.expand_alias2(alias_name, alias_type.args)
        each_alias_type(expanded) do |at|
          validate_alias_type(at, names, types)
        end
      end
    end