Module: Typisch::DSL
- Included in:
- DSLContext
- Defined in:
- lib/typisch/dsl.rb
Overview
Apologies this is a bit messy. Should probably do a bit of a tidy-up once the dust has settled around the DSL syntax.
It’s a layer ontop of the core type model though - could be worse, it could be horribly intertwined with the model itself :)
Defined Under Namespace
Classes: DerivedObjectContext, ObjectContext
Instance Method Summary collapse
- #_normalize_object_args(default_class, klass_or_properties = nil, properties = nil) ⇒ Object
-
#_object(klass, properties, derive_from = nil, &block) ⇒ Object
back-end for object, which takes args in a normalized format.
-
#annotate(description_or_options, options = nil) ⇒ Object
annotations apply to the next register’d type.
- #derived_from(original_type, *args, &block_arg) ⇒ Object
- #nullable(t) ⇒ Object
- #object(*args, &block) ⇒ Object
- #register(name, *type_args, &type_block_arg) ⇒ Object
- #register_type_for_class(klass, *object_type_args, &object_type_block_arg) ⇒ Object
- #register_version_type_for_class(klass, version, *object_type_args, &object_type_block_arg) ⇒ Object
- #registry ⇒ Object
- #sequence(*args) ⇒ Object
- #string(refinements = nil) ⇒ Object
- #tuple(*types) ⇒ Object
- #type(arg, *more_args, &block_arg) ⇒ Object
- #union(*types) ⇒ Object
Instance Method Details
#_normalize_object_args(default_class, klass_or_properties = nil, properties = nil) ⇒ Object
93 94 95 96 97 98 99 |
# File 'lib/typisch/dsl.rb', line 93 def _normalize_object_args(default_class, klass_or_properties=nil, properties=nil) case klass_or_properties when ::Hash then [default_class, klass_or_properties] when ::NilClass then [default_class, {}] when ::Module then [klass_or_properties, properties || {}] end end |
#_object(klass, properties, derive_from = nil, &block) ⇒ Object
back-end for object, which takes args in a normalized format
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/typisch/dsl.rb', line 102 def _object(klass, properties, derive_from=nil, &block) if block object_context = if derive_from DerivedObjectContext.new(self, derive_from) else ObjectContext.new(self) end object_context.instance_eval(&block) properties.merge!(object_context.properties) end properties.keys.each do |k| type_args, type_block_arg = properties[k] properties[k] = type(*type_args, &type_block_arg) end type = Type::Object.new(klass.to_s, properties) if block && (prop_annot = object_context.property_annotations) type.annotations[:properties] = prop_annot end type end |
#annotate(description_or_options, options = nil) ⇒ Object
annotations apply to the next register’d type.
annotate “Some description”, :some_other => ‘annotations’ annotate :description => “Some description”, :some_other => ‘annotations’
41 42 43 44 45 46 47 48 49 |
# File 'lib/typisch/dsl.rb', line 41 def annotate(, =nil) if .is_a?(::String) ||= {}; [:description] = else = end @pending_annotations ||= {} @pending_annotations.merge!() end |
#derived_from(original_type, *args, &block_arg) ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/typisch/dsl.rb', line 131 def derived_from(original_type, *args, &block_arg) if args.empty? && !block_arg original_type elsif args.last.is_a?(::Hash) && (version = args.last[:version]) && original_type.name # slightly messy; we rely on the convention that 'versions' of named types are registered # as :"#{name}__#{version}", this allows you to specify or override the version when # deriving from a type, even if it is still just a named placeholder, by manipulating the # name. original_name = original_type.name.to_s.sub(/__.*$/, '') :"#{original_name}__#{version}" else original_type = type(original_type).target case original_type when Type::Object klass, properties = _normalize_object_args(original_type.class_or_module, *args) _object(klass, properties, original_type, &block_arg) when Type::Sequence slice_overrides = (args.last.is_a?(::Hash) && args.last[:slice]) ? args.pop : {} Type::Sequence.new(derived_from(original_type.type, *args, &block_arg), slice_overrides) when Type::Union non_null = original_type.excluding_null raise "DSL doesn't support deriving from union types (except simple unions with null)" if Type::Union === non_null nullable(derived_from(non_null, *args, &block_arg)) else raise "DSL doesn't support deriving from #{original_type.class} types" if args.length > 0 || block_arg original_type end end end |
#nullable(t) ⇒ Object
127 128 129 |
# File 'lib/typisch/dsl.rb', line 127 def nullable(t) union(type(t), :null) end |
#object(*args, &block) ⇒ Object
88 89 90 91 |
# File 'lib/typisch/dsl.rb', line 88 def object(*args, &block) klass, properties = _normalize_object_args(::Object, *args) _object(klass, properties, &block) end |
#register(name, *type_args, &type_block_arg) ⇒ Object
14 15 16 17 18 19 20 21 |
# File 'lib/typisch/dsl.rb', line 14 def register(name, *type_args, &type_block_arg) result = registry[name] = type(*type_args, &type_block_arg) if @pending_annotations result.annotations.merge!(@pending_annotations) @pending_annotations = nil end result end |
#register_type_for_class(klass, *object_type_args, &object_type_block_arg) ⇒ Object
23 24 25 26 27 28 |
# File 'lib/typisch/dsl.rb', line 23 def register_type_for_class(klass, *object_type_args, &object_type_block_arg) name = :"#{klass}" type = register(name, :object, klass, *object_type_args, &object_type_block_arg) registry.register_type_for_class(klass, type) type end |
#register_version_type_for_class(klass, version, *object_type_args, &object_type_block_arg) ⇒ Object
30 31 32 33 34 35 |
# File 'lib/typisch/dsl.rb', line 30 def register_version_type_for_class(klass, version, *object_type_args, &object_type_block_arg) name = :"#{klass}__#{version}" type = register(name, :object, klass, *object_type_args, &object_type_block_arg) registry.register_version_type_for_class(klass, version, type) type end |
#registry ⇒ Object
10 11 12 |
# File 'lib/typisch/dsl.rb', line 10 def registry raise NotImplementedError end |
#sequence(*args) ⇒ Object
74 75 76 77 78 79 80 81 82 |
# File 'lib/typisch/dsl.rb', line 74 def sequence(*args) = {} if (opts = args.last and opts.is_a?(::Hash)) [:slice] = opts.delete(:slice) if opts.has_key?(:slice) [:total_length] = opts.delete(:total_length) if opts.has_key?(:total_length) args.pop if opts.empty? end Type::Sequence.new(type(*args), ) end |
#string(refinements = nil) ⇒ Object
70 71 72 |
# File 'lib/typisch/dsl.rb', line 70 def string(refinements=nil) refinements ? Type::String.new(refinements) : registry[:string] end |
#tuple(*types) ⇒ Object
84 85 86 |
# File 'lib/typisch/dsl.rb', line 84 def tuple(*types) Type::Tuple.new(*types.map {|t| type(t)}) end |
#type(arg, *more_args, &block_arg) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/typisch/dsl.rb', line 51 def type(arg, *more_args, &block_arg) case arg when Type arg when ::Symbol if more_args.empty? && !block_arg registry[arg] elsif more_args.last.is_a?(::Hash) && !block_arg && (version = more_args.last[:version]) registry[:"#{arg}__#{version}"] else send(arg, *more_args, &block_arg) end when ::Module type(:"#{arg}", *more_args, &block_arg) else raise ArgumentError, "expected Type or type name or class, but was given #{arg.class}" end end |