lib/steep/errors.rb in steep-0.1.0.pre2 vs lib/steep/errors.rb in steep-0.1.0

- old
+ new

@@ -6,44 +6,123 @@ def initialize(node:) @node = node end def location_to_str - "#{node.loc.expression.source_buffer.name}:#{node.loc.first_line}:#{node.loc.column}" + Rainbow("#{node.loc.expression.source_buffer.name}:#{node.loc.first_line}:#{node.loc.column}").red end + + def print_to(io) + source = node.loc.expression.source + io.puts "#{to_s} (#{Rainbow(source.split(/\n/).first).blue})" + end end + module ResultPrinter + def print_result_to(io, level: 2) + indent = " " * level + result.trace.each do |s, t| + case s + when Interface::Method + io.puts "#{indent}#{s.name}(#{s.type_name}) <: #{t.name}(#{t.type_name})" + when Interface::MethodType + io.puts "#{indent}#{s} <: #{t} (#{s.location.name}:#{s.location.start_line})" + else + io.puts "#{indent}#{s} <: #{t}" + end + end + io.puts "#{indent} #{result.error.message}" + end + + def print_to(io) + super + print_result_to io + end + end + class IncompatibleAssignment < Base attr_reader :lhs_type attr_reader :rhs_type + attr_reader :result - def initialize(node:, lhs_type:, rhs_type:) + include ResultPrinter + + def initialize(node:, lhs_type:, rhs_type:, result:) super(node: node) @lhs_type = lhs_type @rhs_type = rhs_type + @result = result end def to_s "#{location_to_str}: IncompatibleAssignment: lhs_type=#{lhs_type}, rhs_type=#{rhs_type}" end end + class IncompatibleArguments < Base + attr_reader :node + attr_reader :receiver_type + attr_reader :method_type + + def initialize(node:, receiver_type:, method_type:) + super(node: node) + @receiver_type = receiver_type + @method_type = method_type + end + + def to_s + "#{location_to_str}: IncompatibleArguments: receiver=#{receiver_type}, method_type=#{method_type}" + end + end + class ArgumentTypeMismatch < Base - attr_reader :type - attr_reader :method + attr_reader :node + attr_reader :expected + attr_reader :actual + attr_reader :receiver_type - def initialize(node:, type:, method:) + def initialize(node:, receiver_type:, expected:, actual:) super(node: node) - @type = type - @method = method + @receiver_type = receiver_type + @expected = expected + @actual = actual end def to_s - "#{location_to_str}: ArgumentTypeMismatch: type=#{type}, method=#{method}" + "#{location_to_str}: ArgumentTypeMismatch: receiver=#{receiver_type}, expected=#{expected}, actual=#{actual}" end end + class IncompatibleBlockParameters < Base + attr_reader :node + attr_reader :method_type + + def initialize(node:, method_type:) + super(node: node) + @method_type = method_type + end + + def to_s + "#{location_to_str}: IncompatibleBlockParameters: method_type=#{method_type}" + end + end + + class BlockParameterTypeMismatch < Base + attr_reader :expected + attr_reader :actual + + def initialize(node:, expected:, actual:) + super(node: node) + @expected = expected + @actual = actual + end + + def to_s + "#{location_to_str}: BlockParameterTypeMismatch: expected=#{expected}, actual=#{actual}" + end + end + class NoMethod < Base attr_reader :type attr_reader :method def initialize(node:, type:, method:) @@ -58,73 +137,171 @@ end class ReturnTypeMismatch < Base attr_reader :expected attr_reader :actual + attr_reader :result - def initialize(node:, expected:, actual:) + include ResultPrinter + + def initialize(node:, expected:, actual:, result:) super(node: node) @expected = expected @actual = actual + @result = result end def to_s "#{location_to_str}: ReturnTypeMismatch: expected=#{expected}, actual=#{actual}" end end class UnexpectedBlockGiven < Base - attr_reader :method - attr_reader :type + attr_reader :method_type - def initialize(node:, type:, method:) + def initialize(node:, method_type:) super(node: node) - @type = type - @method = method + @method_type = method_type end + + def to_s + "#{location_to_str}: UnexpectedBlockGiven: method_type=#{method_type.location&.source}" + end end + class RequiredBlockMissing < Base + attr_reader :method_type + + def initialize(node:, method_type:) + super(node: node) + @method_type = method_type + end + + def to_s + "#{location_to_str}: RequiredBlockMissing: method_type=#{method_type.location&.source}" + end + end + class BlockTypeMismatch < Base attr_reader :expected attr_reader :actual + attr_reader :result - def initialize(node:, expected:, actual:) + include ResultPrinter + + def initialize(node:, expected:, actual:, result:) super(node: node) @expected = expected @actual = actual + @result = result end def to_s "#{location_to_str}: BlockTypeMismatch: expected=#{expected}, actual=#{actual}" end end class BreakTypeMismatch < Base attr_reader :expected attr_reader :actual + attr_reader :result - def initialize(node:, expected:, actual:) + include ResultPrinter + + def initialize(node:, expected:, actual:, result:) super(node: node) @expected = expected @actual = actual + @result = result end + + def to_s + "#{location_to_str}: BreakTypeMismatch: expected=#{expected}, actual=#{actual}" + end end - class MethodParameterTypeMismatch < Base + class UnexpectedJump < Base def to_s - "#{location_to_str}: MethodParameterTypeMismatch: method=#{node.children[0]}" + "#{location_to_str}: UnexpectedJump" end end + class UnexpectedJumpValue < Base + def to_s + "#{location_to_str}: UnexpectedJumpValue" + end + end + + class MethodArityMismatch < Base + def to_s + "#{location_to_str}: MethodArityMismatch: method=#{node.children[0]}" + end + end + + class IncompatibleMethodTypeAnnotation < Base + attr_reader :interface_method + attr_reader :annotation_method + attr_reader :result + + include ResultPrinter + + def initialize(node:, interface_method:, annotation_method:, result:) + super(node: node) + @interface_method = interface_method + @annotation_method = annotation_method + @result = result + end + + def to_s + "#{location_to_str}: IncompatibleMethodTypeAnnotation: interface_method=#{interface_method.type_name}.#{interface_method.name}, annotation_method=#{annotation_method.name}" + end + end + + class MethodDefinitionWithOverloading < Base + attr_reader :method + + def initialize(node:, method:) + super(node: node) + @method = method + end + + def to_s + "#{location_to_str}: MethodDefinitionWithOverloading: method=#{method.name}, types=#{method.types.join(" | ")}" + end + end + + class MethodReturnTypeAnnotationMismatch < Base + attr_reader :method_type + attr_reader :annotation_type + attr_reader :result + + include ResultPrinter + + def initialize(node:, method_type:, annotation_type:, result:) + super(node: node) + @method_type = method_type + @annotation_type = annotation_type + @result = result + end + + def to_s + "#{location_to_str}: MethodReturnTypeAnnotationMismatch: method_type=#{method_type.return_type}, annotation_type=#{annotation_type}" + end + end + class MethodBodyTypeMismatch < Base attr_reader :expected attr_reader :actual + attr_reader :result - def initialize(node:, expected:, actual:) + include ResultPrinter + + def initialize(node:, expected:, actual:, result:) super(node: node) @expected = expected @actual = actual + @result = result end def to_s method = case node.type when :def @@ -192,16 +369,111 @@ def to_s "#{location_to_str}: UnexpectedDynamicMethod: module=#{module_name}, method=#{method_name}" end end + class UnknownConstantAssigned < Base + attr_reader :type + + def initialize(node:, type:) + super(node: node) + @type = type + end + + def to_s + "#{location_to_str}: UnknownConstantAssigned: type=#{type}" + end + end + class FallbackAny < Base def initialize(node:) @node = node end def to_s "#{location_to_str}: FallbackAny" + end + end + + class UnsatisfiableConstraint < Base + attr_reader :method_type + attr_reader :var + attr_reader :sub_type + attr_reader :super_type + attr_reader :result + + def initialize(node:, method_type:, var:, sub_type:, super_type:, result:) + super(node: node) + @method_type = method_type + @var = var + @sub_type = sub_type + @super_type = super_type + @result = result + end + + include ResultPrinter + + def to_s + "#{location_to_str}: UnsatisfiableConstraint: method_type=#{method_type}, constraint=#{sub_type} <: '#{var} <: #{super_type}" + end + end + + class IncompatibleAnnotation < Base + attr_reader :var_name + attr_reader :result + attr_reader :relation + + def initialize(node:, var_name:, result:, relation:) + super(node: node) + @var_name = var_name + @result = result + @relation = relation + end + + include ResultPrinter + + def to_s + "#{location_to_str}: IncompatibleAnnotation: var_name=#{var_name}, #{relation}" + end + end + + class IncompatibleTypeCase < Base + attr_reader :var_name + attr_reader :result + attr_reader :relation + + def initialize(node:, var_name:, result:, relation:) + super(node: node) + @var_name = var_name + @result = result + @relation = relation + end + + include ResultPrinter + + def to_s + "#{location_to_str}: IncompatibleTypeCase: var_name=#{var_name}, #{relation}" + end + end + + class ElseOnExhaustiveCase < Base + def initialize(node:, type:) + def to_s + "#{location_to_str}: ElseOnExhaustiveCase: type=#{type}" + end + end + end + + class UnexpectedSplat < Base + attr_reader :type + + def initialize(node:, type:) + super(node: node) + @type = type + end + + def to_s + "#{location_to_str}: UnexpectedSplat: type=#{type}" end end end end