Class: Literal::Property

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/literal/property.rb

Constant Summary collapse

ORDER =
{ :positional => 0, :* => 1, :keyword => 2, :** => 3, :& => 4 }.freeze
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
VISIBILITY_OPTIONS =
Set[false, :private, :protected, :public].freeze
KIND_OPTIONS =
Set[:positional, :*, :keyword, :**, :&].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, type:, kind:, reader:, writer:, predicate:, default:, description:, coercion:) ⇒ Property

Returns a new instance of Property.



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/literal/property.rb', line 12

def initialize(name:, type:, kind:, reader:, writer:, predicate:, default:, description:, coercion:)
	@name = name
	@type = type
	@kind = kind
	@reader = reader
	@writer = writer
	@predicate = predicate
	@default = default
	@description = description
	@coercion = coercion
end

Instance Attribute Details

#coercionObject (readonly)

Returns the value of attribute coercion.



24
25
26
# File 'lib/literal/property.rb', line 24

def coercion
  @coercion
end

#defaultObject (readonly)

Returns the value of attribute default.



24
25
26
# File 'lib/literal/property.rb', line 24

def default
  @default
end

#descriptionObject (readonly)

Returns the value of attribute description.



24
25
26
# File 'lib/literal/property.rb', line 24

def description
  @description
end

#kindObject (readonly)

Returns the value of attribute kind.



24
25
26
# File 'lib/literal/property.rb', line 24

def kind
  @kind
end

#nameObject (readonly)

Returns the value of attribute name.



24
25
26
# File 'lib/literal/property.rb', line 24

def name
  @name
end

#predicateObject (readonly)

Returns the value of attribute predicate.



24
25
26
# File 'lib/literal/property.rb', line 24

def predicate
  @predicate
end

#readerObject (readonly)

Returns the value of attribute reader.



24
25
26
# File 'lib/literal/property.rb', line 24

def reader
  @reader
end

#typeObject (readonly)

Returns the value of attribute type.



24
25
26
# File 'lib/literal/property.rb', line 24

def type
  @type
end

#writerObject (readonly)

Returns the value of attribute writer.



24
25
26
# File 'lib/literal/property.rb', line 24

def writer
  @writer
end

Instance Method Details

#<=>(other) ⇒ Object



80
81
82
# File 'lib/literal/property.rb', line 80

def <=>(other)
	ORDER[@kind] <=> ORDER[other.kind]
end

#block?Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/literal/property.rb', line 50

def block?
	@kind == :&
end

#check(value) ⇒ Object

Raises:



103
104
105
106
107
# File 'lib/literal/property.rb', line 103

def check(value, &)
	raise ArgumentError.new("Cannot check type without a block") unless block_given?

	Literal.check(value, @type, &)
end

#check_initializer(receiver, value) ⇒ Object



113
114
115
# File 'lib/literal/property.rb', line 113

def check_initializer(receiver, value)
	Literal.check(value, @type) { |c| c.fill_receiver(receiver:, method: "#initialize", label: param) }
end

#check_writer(receiver, value) ⇒ Object



109
110
111
# File 'lib/literal/property.rb', line 109

def check_writer(receiver, value)
	Literal.check(value, @type) { |c| c.fill_receiver(receiver:, method: "##{@name.name}=(value)") }
end

#coerce(value, context:) ⇒ Object



84
85
86
# File 'lib/literal/property.rb', line 84

def coerce(value, context:)
	context.instance_exec(value, &@coercion)
end

#default?Boolean

Returns:

  • (Boolean)


54
55
56
57
# File 'lib/literal/property.rb', line 54

def default?
	return true if splat? || double_splat?
	nil != @default
end

#default_value(receiver) ⇒ Object



96
97
98
99
100
101
# File 'lib/literal/property.rb', line 96

def default_value(receiver)
	case @default
		when Proc then receiver.instance_exec(&@default)
		else @default
	end
end

#description?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/literal/property.rb', line 59

def description?
	!!@description
end

#double_splat?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/literal/property.rb', line 46

def double_splat?
	@kind == :**
end

#escaped_nameObject



92
93
94
# File 'lib/literal/property.rb', line 92

def escaped_name
	RUBY_KEYWORDS[@name] || @name.name
end

#generate_initializer_handle_property(buffer = +"")) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/literal/property.rb', line 153

def generate_initializer_handle_property(buffer = +"")
	buffer << "  # " << @name.name << "\n" <<
		"  __property__ = __properties__[:" << @name.name << "]\n"

	if @kind == :keyword && ruby_keyword?
		generate_initializer_escape_keyword(buffer)
	end

	if default?
		generate_initializer_assign_default(buffer)
	end

	if @coercion
		generate_initializer_coerce_property(buffer)
	end

	generate_initializer_check_type(buffer)
	generate_initializer_assign_value(buffer)
end

#generate_predicate_method(buffer = +"")) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/literal/property.rb', line 141

def generate_predicate_method(buffer = +"")
	buffer <<
		(@predicate ? @predicate.name : "public") <<
		" def " <<
		@name.name <<
		"?\n" <<
		"  !!@" <<
		@name.name <<
		"\n" <<
		"end\n"
end

#generate_reader_method(buffer = +"")) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/literal/property.rb', line 117

def generate_reader_method(buffer = +"")
	buffer <<
		(@reader ? @reader.name : "public") <<
		"\ndef " <<
		@name.name <<
		"\n  value = @" <<
		@name.name <<
		"\n  value\nend\n"
end

#generate_writer_method(buffer = +"")) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/literal/property.rb', line 127

def generate_writer_method(buffer = +"")
	buffer <<
		(@writer ? @writer.name : "public") <<
		" def " <<
		@name.name <<
		"=(value)\n" <<
		"  self.class.literal_properties[:" <<
		@name.name <<
		"].check_writer(self, value)\n" <<
		"  @" << @name.name << " = value\n" <<
		"rescue Literal::TypeError => error\n  error.set_backtrace(caller(1))\n  raise\n" <<
		"end\n"
end

#keyword?Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/literal/property.rb', line 34

def keyword?
	@kind == :keyword
end

#optional?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/literal/property.rb', line 26

def optional?
	default? || @type === nil
end

#paramObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/literal/property.rb', line 63

def param
	case @kind
	when :*
		"*#{escaped_name}"
	when :**
		"**#{escaped_name}"
	when :&
		"&#{escaped_name}"
	when :positional
		escaped_name
	when :keyword
		"#{@name.name}:"
	else
		raise "You should never see this error."
	end
end

#positional?Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/literal/property.rb', line 38

def positional?
	@kind == :positional
end

#required?Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/literal/property.rb', line 30

def required?
	!optional?
end

#ruby_keyword?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/literal/property.rb', line 88

def ruby_keyword?
	!!RUBY_KEYWORDS[@name]
end

#splat?Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/literal/property.rb', line 42

def splat?
	@kind == :*
end