Runtime assertions for Ruby literal.fun
ruby
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

Refactor literal attributes

+47 -54
+1
lib/literal.rb
··· 5 5 6 6 autoload :Attributable, "literal/attributable" 7 7 autoload :Attribute, "literal/attribute" 8 + autoload :Attributes, "literal/attributes" 8 9 autoload :ConcurrentArray, "literal/concurrent_array" 9 10 autoload :ConcurrentHash, "literal/concurrent_hash" 10 11 autoload :Data, "literal/data"
+13 -17
lib/literal/attributable.rb
··· 7 7 8 8 include Literal::Types 9 9 10 - Visibility = [:private, :protected, :public].freeze 10 + Visibility = Set[false, :private, :protected, :public].freeze 11 11 12 12 def attribute(name, type, special = nil, reader: false, writer: false, positional: false, default: nil, &coercion) 13 13 if default && !(Proc === default || default.frozen?) 14 - raise Literal::ArgumentError.new("The `default` must be a frozen value or a Proc.") 14 + raise Literal::ArgumentError.new("The default must be a frozen object or a Proc.") 15 15 end 16 16 17 - unless false == reader || Visibility.include?(reader) 18 - raise Literal::ArgumentError.new("The `reader` must be one of #{Visibility.map(&:inspect).join(', ')}.") 17 + unless Visibility.include?(reader) 18 + raise Literal::ArgumentError.new("The reader must be one of #{Visibility.map(&:inspect).join(', ')}.") 19 19 end 20 20 21 - unless false == writer || Visibility.include?(writer) 22 - raise Literal::ArgumentError.new("The `writer` must be one of #{Visibility.map(&:inspect).join(', ')}.") 23 - end 24 - 25 - if special && positional 26 - raise Literal::ArgumentError.new("The #{name} attribute cannot be #{special} and positional.") 21 + unless Visibility.include?(writer) 22 + raise Literal::ArgumentError.new("The writer must be one of #{Visibility.map(&:inspect).join(', ')}.") 27 23 end 28 24 29 - if :class == name && reader 30 - raise Literal::ArgumentError.new("The `:class` attribute should not be defined as a reader because it breaks Ruby's `Object#class` method, which Literal itself depends on.") 25 + if reader && :class == name 26 + raise Literal::ArgumentError.new( 27 + "The `:class` attribute should not be defined as a reader because it breaks Ruby's `Object#class` method, which Literal itself depends on.", 28 + ) 31 29 end 32 30 33 31 attribute = Literal::Attribute.new( ··· 42 40 ) 43 41 44 42 literal_attributes[name] = attribute 45 - 46 - include literal_extension 47 - 48 43 define_literal_methods(attribute) 44 + include literal_extension 49 45 end 50 46 51 47 def inherited(subclass) ··· 74 70 75 71 #{generate_literal_initializer} 76 72 77 - #{generate_literal_reader(attribute) if attribute.reader?} 73 + #{generate_literal_reader(attribute) if attribute.reader} 78 74 79 - #{generate_literal_writer(attribute) if attribute.writer?} 75 + #{generate_literal_writer(attribute) if attribute.writer} 80 76 RUBY 81 77 end 82 78
+4 -4
lib/literal/attributable/formatter.rb
··· 45 45 end 46 46 47 47 def DefaultAssignment(node) 48 - text "if Literal::Null == #{node.attribute.escaped}" 48 + text "if Literal::Null == #{node.attribute.escaped_name}" 49 49 50 50 indent do 51 - text "#{node.attribute.escaped} = @literal_attributes[:#{node.attribute.name}].default_value" 51 + text "#{node.attribute.escaped_name} = @literal_attributes[:#{node.attribute.name}].default_value" 52 52 end 53 53 54 54 newline ··· 73 73 end 74 74 75 75 def KeywordEscape(node) 76 - text "#{node.attribute.escaped} = binding.local_variable_get(:#{node.attribute.name})" 76 + text "#{node.attribute.escaped_name} = binding.local_variable_get(:#{node.attribute.name})" 77 77 end 78 78 79 79 def KeywordParam(node) 80 - if node.attribute.default? 80 + if node.attribute.default 81 81 text "#{node.attribute.name}: Literal::Null" 82 82 elsif node.attribute.type === nil 83 83 text "#{node.attribute.name}: nil"
+2
lib/literal/attributable/generators.rb
··· 3 3 module Literal::Attributable::Generators 4 4 autoload :Base, "literal/attributable/generators/base" 5 5 autoload :Initializer, "literal/attributable/generators/initializer" 6 + autoload :IVarInitializer, "literal/attributable/generators/i_var_initializer" 7 + autoload :IVarReader, "literal/attributable/generators/i_var_reader" 6 8 autoload :StructInitializer, "literal/attributable/generators/struct_initializer" 7 9 autoload :StructReader, "literal/attributable/generators/struct_reader" 8 10 autoload :Reader, "literal/attributable/generators/reader"
+1 -1
lib/literal/attributable/generators/data_initializer.rb
··· 24 24 collection: Ref.new("@attributes"), 25 25 key: Symbol.new(attribute.name), 26 26 ), 27 - right: Ref.new("#{attribute.escaped}.frozen? ? #{attribute.escaped} : #{attribute.escaped}.freeze"), 27 + right: Ref.new("#{attribute.escaped_name}.frozen? ? #{attribute.escaped_name} : #{attribute.escaped_name}.freeze"), 28 28 ) 29 29 end 30 30 end
+1 -1
lib/literal/attributable/generators/i_var_initializer.rb
··· 7 7 def assign_value(attribute) 8 8 Assignment.new( 9 9 left: Ref.new("@#{attribute.name}"), 10 - right: Ref.new(attribute.escaped), 10 + right: Ref.new(attribute.escaped_name), 11 11 ) 12 12 end 13 13 end
+5 -5
lib/literal/attributable/generators/initializer.rb
··· 28 28 BlockParam.new(attribute:) 29 29 else 30 30 if attribute.positional 31 - if attribute.default? 31 + if attribute.default 32 32 PositionalParam.new( 33 33 name: attribute.name, 34 34 default: "Literal::Null", ··· 82 82 end 83 83 84 84 def escape_keyword(attribute) 85 - KeywordEscape.new(attribute) if attribute.escape? 85 + KeywordEscape.new(attribute) if attribute.ruby_keyword? 86 86 end 87 87 88 88 def coerce_attribute(attribute) 89 - AttributeCoercion.new(attribute) if attribute.coercion? 89 + AttributeCoercion.new(attribute) if attribute.coercion 90 90 end 91 91 92 92 def assign_default(attribute) 93 - DefaultAssignment.new(attribute) if attribute.default? 93 + DefaultAssignment.new(attribute) if attribute.default 94 94 end 95 95 96 96 def check_type(attribute) 97 97 TypeCheck.new( 98 98 attribute_name: attribute.name, 99 - variable_name: attribute.escaped, 99 + variable_name: attribute.escaped_name, 100 100 ) 101 101 end 102 102
+1 -1
lib/literal/attributable/generators/struct_initializer.rb
··· 26 26 collection: Ref.new("@attributes"), 27 27 key: Symbol.new(attribute.name), 28 28 ), 29 - right: Ref.new(attribute.escaped), 29 + right: Ref.new(attribute.escaped_name), 30 30 ) 31 31 end 32 32 end
+3 -23
lib/literal/attribute.rb
··· 1 1 # frozen_string_literal: true 2 2 3 3 class Literal::Attribute 4 - RUBY_KEYWORDS = %i[alias and begin break case class def do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield].to_h { |k| [k, "___#{k}___"] }.freeze 4 + RUBY_KEYWORDS = %i[alias and begin break case class def do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield].to_h { |k| [k, "__#{k}__"] }.freeze 5 5 6 6 def initialize(name:, type:, special:, reader:, writer:, positional:, default:, coercion:) 7 7 @name = name ··· 16 16 17 17 attr_reader :name, :type, :special, :reader, :writer, :positional, :default, :coercion 18 18 19 - def reader? 20 - !!@reader 21 - end 22 - 23 - def writer? 24 - !!@writer 25 - end 26 - 27 - def default? 28 - nil != @default 29 - end 30 - 31 - def positional? 32 - !!@positional 33 - end 34 - 35 - def coercion? 36 - !!@coercion 37 - end 38 - 39 19 def coerce(value, context:) 40 20 context.instance_exec(value, &@coercion) 41 21 end 42 22 43 - def escape? 23 + def ruby_keyword? 44 24 !!RUBY_KEYWORDS[@name] 45 25 end 46 26 47 - def escaped 27 + def escaped_name 48 28 RUBY_KEYWORDS[@name] || @name 49 29 end 50 30
+15
lib/literal/attributes.test.rb
··· 1 + # frozen_string_literal: true 2 + 3 + class Person 4 + extend Literal::Attributes 5 + 6 + attribute :name, String, reader: :public 7 + attribute :age, Integer, reader: :public 8 + end 9 + 10 + test do 11 + person = Person.new(name: "John", age: 30) 12 + 13 + expect(person.name) == "John" 14 + expect(person.age) == 30 15 + end
+1 -2
lib/literal/visitor.rb
··· 1 1 # frozen_string_literal: true 2 2 3 + # @api private 3 4 class Literal::Visitor 4 5 def visit(node) 5 6 node.accept(self) ··· 15 16 end 16 17 end 17 18 end 18 - 19 - Literal.private_constant(:Visitor)