foobara 0.0.141 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/CHANGELOG.md +23 -0
  4. data/projects/builtin_types/lib/foobara/builtin_types.rb +1 -0
  5. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/desugarizers/move_defaults_from_element_types_to_root.rb +9 -2
  6. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/desugarizers/symbolize_defaults.rb +1 -1
  7. data/projects/builtin_types/src/attributes/supported_transformers/defaults/type_declaration_extension/extend_attributes_type_declaration/type_declaration_validators/hash_with_symbolic_keys.rb +1 -1
  8. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/desugarizers/alphabetize_required.rb +5 -5
  9. data/projects/builtin_types/src/attributes/supported_validators/required/type_declaration_extension/extend_attributes_type_declaration/desugarizers/move_required_from_element_types_to_root.rb +12 -2
  10. data/projects/builtin_types/src/builtin_types.rb +1 -1
  11. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/class_desugarizer.rb +10 -2
  12. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/class_type_desugarizer.rb +7 -2
  13. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/instance_of_class_desugarizer.rb +3 -4
  14. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/instance_of_symbol_desugarizer.rb +3 -4
  15. data/projects/builtin_types/src/duck/supported_validators/instance_of/type_declaration_extension/extend_registered_type_declaration/type_declaration_validators/is_valid_class.rb +1 -1
  16. data/projects/builtin_types/src/duck/supported_validators/instance_of.rb +1 -0
  17. data/projects/builtin_types/src/duck/supported_validators/one_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/cast_one_of.rb +4 -3
  18. data/projects/builtin_types/src/duck/supported_validators/one_of/type_declaration_extension/extend_registered_type_declaration/desugarizers/module_desugarizer.rb +3 -3
  19. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations/type_declaration_extension/extend_tuple_type_declaration/desugarizers/set_size.rb +1 -1
  20. data/projects/builtin_types/src/tuple/supported_processors/element_type_declarations/type_declaration_extension/extend_tuple_type_declaration/type_declaration_validators/size_matches.rb +2 -4
  21. data/projects/command/src/command_pattern_implementation/concerns/inputs_type.rb +12 -12
  22. data/projects/command/src/command_pattern_implementation/concerns/reflection.rb +4 -2
  23. data/projects/command/src/command_pattern_implementation/concerns/result_type.rb +0 -4
  24. data/projects/command_connectors/src/command_connector.rb +6 -6
  25. data/projects/command_connectors/src/command_registry.rb +7 -4
  26. data/projects/command_connectors/src/transformed_command.rb +22 -8
  27. data/projects/command_connectors/src/transformers/auth_errors_transformer.rb +1 -0
  28. data/projects/command_connectors/src/transformers/entity_to_primary_key_inputs_transformer.rb +4 -0
  29. data/projects/common/src/error_collection.rb +1 -1
  30. data/projects/detached_entity/src/concerns/types.rb +7 -1
  31. data/projects/detached_entity/src/extensions/builtin_types/detached_entity/validators/model_instance_is_valid.rb +1 -1
  32. data/projects/detached_entity/src/extensions/type_declarations/handlers/extend_detached_entity_type_declaration/hash_desugarizer.rb +6 -9
  33. data/projects/detached_entity/src/extensions/type_declarations/handlers/extend_detached_entity_type_declaration/primary_key_desugarizer.rb +2 -1
  34. data/projects/domain/src/domain_module_extension.rb +12 -4
  35. data/projects/entity/src/concerns/types.rb +6 -1
  36. data/projects/foobara/lib/foobara/all.rb +4 -4
  37. data/projects/manifest/src/foobara/manifest/type.rb +11 -2
  38. data/projects/manifest/src/foobara/manifest/type_declaration.rb +46 -2
  39. data/projects/model/src/concerns/aliases.rb +8 -0
  40. data/projects/model/src/concerns/reflection.rb +2 -2
  41. data/projects/model/src/concerns/types.rb +35 -20
  42. data/projects/model/src/extensions/builtin_types/model/validators/model_instance_is_valid.rb +12 -8
  43. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/array_with_symbolic_elements.rb +1 -1
  44. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/attributes_handler_desugarizer.rb +15 -1
  45. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/delegates_desugarizer.rb +7 -5
  46. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/hash_desugarizer.rb +4 -7
  47. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/model_class_desugarizer.rb +0 -2
  48. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/move_private_from_element_types_to_root.rb +28 -9
  49. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/symbolize_private.rb +8 -7
  50. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration/to_type_transformer.rb +4 -7
  51. data/projects/model/src/extensions/type_declarations/handlers/extend_model_type_declaration.rb +14 -2
  52. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/hash_desugarizer.rb +8 -9
  53. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/model_class_type_desugarizer.rb +6 -2
  54. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/mutable_validator.rb +5 -2
  55. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/normalize_mutable_attributes_desugarizer.rb +8 -7
  56. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration/to_type_transformer.rb +4 -1
  57. data/projects/model/src/extensions/type_declarations/handlers/extend_registered_model_type_declaration.rb +20 -5
  58. data/projects/model/src/extensions/type_declarations/handlers/registered_type_declaration/model_class_desugarizer.rb +23 -5
  59. data/projects/model/src/extensions/type_declarations/lazy_element_types/model.rb +18 -0
  60. data/projects/model_attribute_helpers/src/attribute_helpers.rb +44 -26
  61. data/projects/namespace/src/is_namespace.rb +93 -49
  62. data/projects/namespace/src/namespace/lookup_mode.rb +13 -2
  63. data/projects/namespace/src/namespace_helpers.rb +1 -0
  64. data/projects/namespace/src/prefixless_registry.rb +2 -0
  65. data/projects/persistence/src/entity_base/transaction/concerns/state_transitions.rb +20 -1
  66. data/projects/persistence/src/entity_base/transaction.rb +14 -11
  67. data/projects/persistence/src/entity_base/transaction_table.rb +10 -49
  68. data/projects/persistence/src/entity_base.rb +39 -0
  69. data/projects/persistence/src/persistence.rb +4 -0
  70. data/projects/type_declarations/src/attributes.rb +15 -9
  71. data/projects/type_declarations/src/attributes_transformers/from_yaml.rb +1 -1
  72. data/projects/type_declarations/src/desugarizer_pipeline.rb +9 -0
  73. data/projects/type_declarations/src/dsl/attributes.rb +14 -5
  74. data/projects/type_declarations/src/handlers/extend_array_type_declaration/array_desugarizer.rb +24 -4
  75. data/projects/type_declarations/src/handlers/extend_array_type_declaration/element_type_declaration_desugarizer.rb +23 -9
  76. data/projects/type_declarations/src/handlers/extend_array_type_declaration/to_type_transformer.rb +3 -7
  77. data/projects/type_declarations/src/handlers/extend_array_type_declaration/type_set_to_array_desugarizer.rb +15 -4
  78. data/projects/type_declarations/src/handlers/extend_array_type_declaration.rb +12 -2
  79. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration/key_type_declaration_desugarizer.rb +48 -0
  80. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration/to_type_transformer.rb +3 -11
  81. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration/value_type_declaration_desugarizer.rb +51 -0
  82. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration.rb +12 -2
  83. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/dsl_desugarizer.rb +1 -1
  84. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/element_type_declarations_desugarizer.rb +17 -7
  85. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/hash_desugarizer.rb +16 -19
  86. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/to_type_transformer.rb +3 -6
  87. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration.rb +13 -2
  88. data/projects/type_declarations/src/handlers/extend_registered_type_declaration/to_type_transformer.rb +3 -3
  89. data/projects/type_declarations/src/handlers/extend_registered_type_declaration.rb +16 -4
  90. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/array_desugarizer.rb +20 -6
  91. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/to_type_transformer.rb +3 -9
  92. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration.rb +12 -2
  93. data/projects/type_declarations/src/handlers/registered_type_declaration/to_type_transformer.rb +7 -9
  94. data/projects/type_declarations/src/handlers/registered_type_declaration.rb +22 -7
  95. data/projects/type_declarations/src/lazy_element_types/array.rb +19 -0
  96. data/projects/type_declarations/src/lazy_element_types/attributes.rb +27 -0
  97. data/projects/type_declarations/src/lazy_element_types/hash.rb +38 -0
  98. data/projects/type_declarations/src/lazy_element_types/tuple.rb +23 -0
  99. data/projects/type_declarations/src/sensitive_type_remover.rb +6 -1
  100. data/projects/type_declarations/src/sensitive_type_removers/attributes.rb +2 -0
  101. data/projects/type_declarations/src/type_builder.rb +46 -21
  102. data/projects/type_declarations/src/type_declaration.rb +295 -0
  103. data/projects/type_declarations/src/type_declaration_handler.rb +10 -11
  104. data/projects/type_declarations/src/type_declarations.rb +12 -5
  105. data/projects/types/src/type.rb +26 -4
  106. data/projects/value/src/mutator.rb +1 -4
  107. data/projects/value/src/processor/casting.rb +7 -2
  108. data/projects/value/src/processor/pipeline.rb +9 -1
  109. data/projects/value/src/processor.rb +0 -2
  110. data/projects/value/src/transformer.rb +1 -3
  111. data/projects/value/src/validator.rb +0 -2
  112. data/projects/weak_object_set/src/weak_object_set.rb +2 -0
  113. metadata +24 -21
  114. data/projects/type_declarations/src/handlers/registered_type_declaration/desugarizer_metadata_cleanup_desugarizer.rb +0 -29
  115. data/projects/type_declarations/src/handlers/registered_type_declaration/short_type_name_desugarizer.rb +0 -63
  116. data/projects/type_declarations/src/handlers/registered_type_declaration/strict_desugarizer.rb +0 -32
  117. data/projects/type_declarations/src/handlers/registered_type_declaration/strict_stringified_desugarizer.rb +0 -39
  118. data/projects/type_declarations/src/handlers/registered_type_declaration/symbol_desugarizer.rb +0 -30
  119. data/projects/type_declarations/src/handlers/registered_type_declaration/type_desugarizer.rb +0 -24
@@ -1,21 +1,20 @@
1
1
  module Foobara
2
2
  module TypeDeclarations
3
3
  module Handlers
4
+ # TODO: Can't we just delete this type entirely?
4
5
  class ExtendRegisteredModelTypeDeclaration < ExtendRegisteredTypeDeclaration
5
6
  class HashDesugarizer < TypeDeclarations::Desugarizer
6
7
  def applicable?(sugary_type_declaration)
7
- return false unless sugary_type_declaration.is_a?(::Hash)
8
+ return false unless sugary_type_declaration.hash?
8
9
 
9
10
  type_symbol = sugary_type_declaration[:type]
10
11
 
11
- if type_symbol
12
- if type_symbol.is_a?(::Symbol) && type_registered?(type_symbol)
13
- type = Foobara.foobara_root_namespace.foobara_lookup_type(
14
- type_symbol, mode: Namespace::LookupMode::ABSOLUTE
15
- )
12
+ if type_symbol.is_a?(::Symbol)
13
+ # TODO: cache this on a #base_type= helper
14
+ type = sugary_type_declaration.type ||
15
+ lookup_type(type_symbol, mode: Namespace::LookupMode::ABSOLUTE)
16
16
 
17
- type&.extends?(BuiltinTypes[expected_type_symbol])
18
- end
17
+ type&.extends?(BuiltinTypes[expected_type_symbol])
19
18
  end
20
19
  end
21
20
 
@@ -24,7 +23,7 @@ module Foobara
24
23
  end
25
24
 
26
25
  def desugarize(sugary_type_declaration)
27
- Util.symbolize_keys(sugary_type_declaration)
26
+ sugary_type_declaration.symbolize_keys!
28
27
  end
29
28
 
30
29
  def priority
@@ -4,7 +4,7 @@ module Foobara
4
4
  class ExtendRegisteredModelTypeDeclaration < ExtendRegisteredTypeDeclaration
5
5
  class ModelClassTypeDesugarizer < TypeDeclarations::Desugarizer
6
6
  def applicable?(sugary_type_declaration)
7
- if sugary_type_declaration.is_a?(::Hash) && sugary_type_declaration.key?(:type)
7
+ if sugary_type_declaration.hash? && sugary_type_declaration.key?(:type)
8
8
  type = sugary_type_declaration[:type]
9
9
  type.is_a?(::Class) && type < Model
10
10
  end
@@ -12,7 +12,11 @@ module Foobara
12
12
 
13
13
  def desugarize(hash)
14
14
  model_class = hash[:type]
15
- hash.merge(type: model_class.model_type.foobara_manifest_reference.to_sym)
15
+ hash[:type] = model_class.model_type.foobara_manifest_reference.to_sym
16
+
17
+ hash.handle_symbolic_declaration
18
+
19
+ hash
16
20
  end
17
21
 
18
22
  def priority
@@ -21,9 +21,12 @@ module Foobara
21
21
 
22
22
  def validation_errors(strict_type_declaration)
23
23
  mutable = strict_type_declaration[:mutable]
24
- return if [true, false].include?(mutable)
24
+ return if mutable == true || mutable == false
25
+
26
+ model_type = strict_type_declaration.type
27
+
28
+ model_type ||= type_for_declaration(strict_type_declaration[:type])
25
29
 
26
- model_type = type_for_declaration(strict_type_declaration[:type])
27
30
  valid_attribute_names = model_type.element_types.element_types.keys
28
31
 
29
32
  mutable.map do |key|
@@ -4,22 +4,23 @@ module Foobara
4
4
  class ExtendRegisteredModelTypeDeclaration < ExtendRegisteredTypeDeclaration
5
5
  class NormalizeMutableAttributesDesugarizer < TypeDeclarations::Desugarizer
6
6
  def applicable?(value)
7
- if value.is_a?(::Hash) && value.key?(:mutable) && value.key?(:type)
7
+ if value.hash? && value.key?(:mutable) && value.key?(:type)
8
8
  mutable = value[:mutable]
9
9
 
10
- return false if [true, false].include?(mutable)
10
+ return false if mutable == true || mutable == false
11
11
 
12
12
  if !mutable.is_a?(::Array) || (mutable.is_a?(::Array) && mutable.any? { |k| !k.is_a?(::Symbol) })
13
- type = type_for_declaration(value[:type])
14
- type.extends?(BuiltinTypes[:model])
13
+ type = value.type ||
14
+ lookup_type(value[:type], mode: Namespace::LookupMode::ABSOLUTE_SINGLE_NAMESPACE)
15
+
16
+ type&.extends?(BuiltinTypes[:model])
15
17
  end
16
18
  end
17
19
  end
18
20
 
19
21
  def desugarize(rawish_type_declaration)
20
- rawish_type_declaration.merge(
21
- mutable: Util.array(rawish_type_declaration[:mutable]).map!(&:to_sym)
22
- )
22
+ rawish_type_declaration[:mutable] = Util.array(rawish_type_declaration[:mutable]).map!(&:to_sym)
23
+ rawish_type_declaration
23
24
  end
24
25
  end
25
26
  end
@@ -2,6 +2,7 @@ module Foobara
2
2
  module TypeDeclarations
3
3
  module Handlers
4
4
  class ExtendRegisteredModelTypeDeclaration < ExtendRegisteredTypeDeclaration
5
+ # TODO: seems like we can delete this handler entirely?
5
6
  class ToTypeTransformer < ExtendRegisteredTypeDeclaration::ToTypeTransformer
6
7
  # TODO: make declaration validator for model_class and model_base_class
7
8
  def target_classes(strict_type_declaration)
@@ -14,7 +15,9 @@ module Foobara
14
15
  end
15
16
 
16
17
  def declaration_to_type(strict_type_declaration)
17
- type_for_declaration(strict_type_declaration[:type])
18
+ # TODO: cache this on a #base_type= helper
19
+ strict_type_declaration.type ||
20
+ lookup_type(strict_type_declaration[:type], mode: Namespace::LookupMode::ABSOLUTE_SINGLE_NAMESPACE)
18
21
  end
19
22
  end
20
23
  end
@@ -4,17 +4,32 @@ module Foobara
4
4
  # Why doesn't this inherit from ExtendModelTypeDeclaration
5
5
  class ExtendRegisteredModelTypeDeclaration < ExtendRegisteredTypeDeclaration
6
6
  def applicable?(sugary_type_declaration)
7
- strict_type_declaration = desugarize(sugary_type_declaration)
7
+ strict_type_declaration = if sugary_type_declaration.strict?
8
+ # :nocov:
9
+ sugary_type_declaration
10
+ # :nocov:
11
+ else
12
+ desugarize(sugary_type_declaration.clone)
13
+ end
8
14
 
9
- if strict_type_declaration.is_a?(::Hash) && strict_type_declaration.key?(:type)
15
+ if strict_type_declaration.hash? && strict_type_declaration.key?(:type)
10
16
  type_symbol = strict_type_declaration[:type]
11
17
 
12
18
  return false if type_symbol == expected_type_symbol
13
19
  return false unless type_symbol.is_a?(::Symbol) || type_symbol.is_a?(::String)
14
20
 
15
- if type_registered?(type_symbol)
16
- type = lookup_type!(type_symbol)
17
- type.extends?(BuiltinTypes[expected_type_symbol])
21
+ # TODO: cache this on a #base_type= helper
22
+ type = strict_type_declaration.type ||
23
+ lookup_type(type_symbol, mode: Namespace::LookupMode::ABSOLUTE)
24
+
25
+ if type
26
+ if type.extends?(BuiltinTypes[expected_type_symbol])
27
+ unless sugary_type_declaration.equal?(strict_type_declaration)
28
+ sugary_type_declaration.assign(strict_type_declaration)
29
+ end
30
+
31
+ true
32
+ end
18
33
  end
19
34
  end
20
35
  end
@@ -4,13 +4,31 @@ module Foobara
4
4
  class RegisteredTypeDeclaration < TypeDeclarationHandler
5
5
  class ModelClassDesugarizer < TypeDeclarations::Desugarizer
6
6
  def applicable?(sugary_type_declaration)
7
- sugary_type_declaration.is_a?(Class) && sugary_type_declaration < Model
7
+ sugary_type_declaration.class? && sugary_type_declaration.declaration_data < Model
8
8
  end
9
9
 
10
- def desugarize(model_class)
11
- {
12
- type: model_class.model_type.foobara_manifest_reference.to_sym
13
- }
10
+ def desugarize(declaration)
11
+ model_class = declaration.declaration_data
12
+
13
+ declaration.declaration_data = model_class.model_type.foobara_manifest_reference.to_sym
14
+
15
+ type = model_class.model_type
16
+
17
+ if type
18
+ declaration.type = type
19
+ declaration.reference_checked = true
20
+ else
21
+ # :nocov:
22
+ declaration.reference_checked = false
23
+ # :nocov:
24
+ end
25
+
26
+ declaration.is_absolutified = true
27
+ declaration.is_strict = true
28
+ declaration.is_duped = true
29
+ declaration.is_deep_duped = true
30
+
31
+ declaration
14
32
  end
15
33
 
16
34
  def priority
@@ -0,0 +1,18 @@
1
+ module Foobara
2
+ module TypeDeclarations
3
+ module LazyElementTypes
4
+ module Model
5
+ module_function
6
+
7
+ def resolve(type)
8
+ attributes_type_declaration = type.declaration_data[:attributes_declaration]
9
+
10
+ type.element_types = TypeDeclarations.strict do
11
+ handler = Domain.current.foobara_type_builder.handler_for_class(Handlers::ExtendAttributesTypeDeclaration)
12
+ handler.process_value!(TypeDeclaration.new(attributes_type_declaration))
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -54,7 +54,7 @@ module Foobara
54
54
  end
55
55
 
56
56
  unless include_delegates
57
- declaration = Foobara::TypeDeclarations::Attributes.reject(declaration, *delegates.keys)
57
+ declaration = Foobara::TypeDeclarations::Attributes.reject(declaration, *foobara_delegates.keys)
58
58
  end
59
59
 
60
60
  Domain.current.foobara_type_from_declaration(declaration)
@@ -80,9 +80,11 @@ module Foobara
80
80
  if type.extends?(BuiltinTypes[:entity])
81
81
  target_class = type.target_class
82
82
 
83
- entry = foobara_type_declaration_value_at(declaration, DataPath.new(data_path).path)
84
- entry.clear
85
- entry.merge!(target_class.foobara_attributes_for_aggregate_update(initial: false))
83
+ set_foobara_type_declaration_value_at(
84
+ declaration,
85
+ DataPath.new(data_path).path,
86
+ target_class.foobara_attributes_for_aggregate_update(initial: false)
87
+ )
86
88
  end
87
89
  end
88
90
 
@@ -111,9 +113,12 @@ module Foobara
111
113
  # TODO: do we really need declaration_data? Why cant we use the type directly?
112
114
  # TODO: make this work with the type directly for performance reasons.
113
115
  primary_key_type_declaration = target_class.foobara_primary_key_type.declaration_data
114
- entry = foobara_type_declaration_value_at(declaration, DataPath.new(data_path).path)
115
- entry.clear
116
- entry.merge!(primary_key_type_declaration)
116
+
117
+ set_foobara_type_declaration_value_at(
118
+ declaration,
119
+ DataPath.new(data_path).path,
120
+ primary_key_type_declaration
121
+ )
117
122
  end
118
123
  end
119
124
 
@@ -131,31 +136,44 @@ module Foobara
131
136
  TypeDeclarations::Handlers::ExtendAttributesTypeDeclaration
132
137
  )
133
138
 
134
- handler.desugarize(
135
- type: "::attributes",
136
- element_type_declarations:
137
- )
139
+ declaration = TypeDeclaration.new(type: :attributes, element_type_declarations:)
140
+ declaration.is_absolutified = true
141
+ declaration.is_duped = true
142
+
143
+ handler.desugarize(declaration).declaration_data
138
144
  end
139
145
 
140
146
  private
141
147
 
142
- def foobara_type_declaration_value_at(declaration, path_parts)
143
- return declaration if path_parts.empty?
144
-
148
+ def set_foobara_type_declaration_value_at(declaration, path_parts, value)
145
149
  path_part, *path_parts = path_parts
146
150
 
147
- declaration = case path_part
148
- when :"#"
149
- declaration[:element_type_declaration]
150
- when Symbol, Integer
151
- declaration[:element_type_declarations][path_part]
152
- else
153
- # :nocov:
154
- raise "Bad path part #{path_part}"
155
- # :nocov:
156
- end
157
-
158
- foobara_type_declaration_value_at(declaration, path_parts)
151
+ case path_part
152
+ when :"#"
153
+ if path_parts.empty?
154
+ declaration[:element_type_declaration] = value
155
+ else
156
+ set_foobara_type_declaration_value_at(
157
+ declaration[:element_type_declaration],
158
+ path_parts,
159
+ value
160
+ )
161
+ end
162
+ when Symbol, Integer
163
+ if path_parts.empty?
164
+ declaration[:element_type_declarations][path_part] = value
165
+ else
166
+ set_foobara_type_declaration_value_at(
167
+ declaration[:element_type_declarations][path_part],
168
+ path_parts,
169
+ value
170
+ )
171
+ end
172
+ else
173
+ # :nocov:
174
+ raise "Bad path part #{path_part}"
175
+ # :nocov:
176
+ end
159
177
  end
160
178
  end
161
179
  end
@@ -3,6 +3,16 @@ require_relative "scoped"
3
3
  module Foobara
4
4
  class Namespace
5
5
  module IsNamespace
6
+ class << self
7
+ def lru_cache
8
+ @lru_cache ||= Foobara::LruCache.new(100)
9
+ end
10
+
11
+ def clear_lru_cache!
12
+ @lru_cache = nil
13
+ end
14
+ end
15
+
6
16
  include Scoped
7
17
 
8
18
  def scoped_clear_caches
@@ -88,8 +98,13 @@ module Foobara
88
98
  scopedish
89
99
  end
90
100
 
101
+ # TODO: make this thread-safe
91
102
  def foobara_register(scoped)
92
103
  foobara_registry.register(scoped)
104
+
105
+ # TODO: do we really need to clear the whole cache? Why not just the possible
106
+ # impacted keys based on scoped.scoped_path ?
107
+ IsNamespace.clear_lru_cache!
93
108
  # awkward??
94
109
  scoped.scoped_namespace = self
95
110
 
@@ -108,6 +123,8 @@ module Foobara
108
123
  foobara_registry.unregister(scoped)
109
124
  foobara_children.delete(scoped)
110
125
  scoped.scoped_namespace = nil
126
+
127
+ IsNamespace.clear_lru_cache!
111
128
  end
112
129
 
113
130
  def foobara_unregister_all
@@ -116,33 +133,33 @@ module Foobara
116
133
  end
117
134
  end
118
135
 
119
- def foobara_lookup(
120
- path,
121
- filter: nil,
122
- mode: LookupMode::GENERAL,
123
- visited: Set.new,
124
- initial: true
125
- )
136
+ def lru_cache
137
+ IsNamespace.lru_cache
138
+ end
139
+
140
+ def foobara_lookup(path, filter: nil, mode: LookupMode::GENERAL)
141
+ LookupMode.validate!(mode)
126
142
  path = Namespace.to_registry_path(path)
127
- visited_key = [path, mode, initial, self]
143
+
144
+ lru_cache.cached([path, mode, self, filter]) do
145
+ visited = Set.new
146
+ foobara_lookup_without_cache(path, filter:, mode:, visited:)
147
+ end
148
+ end
149
+
150
+ def foobara_lookup_without_cache(path, filter:, mode:, visited:)
151
+ visited_key = [path, mode, self]
128
152
  return nil if visited.include?(visited_key)
129
153
 
130
154
  visited << visited_key
131
155
 
132
- LookupMode.validate!(mode)
133
-
134
156
  if mode == LookupMode::RELAXED
135
- scoped = foobara_lookup(
136
- path,
137
- filter:,
138
- mode: LookupMode::GENERAL,
139
- visited:,
140
- initial: false
141
- )
157
+ scoped = foobara_lookup_without_cache(path, filter:, mode: LookupMode::GENERAL, visited:)
158
+
142
159
  return scoped if scoped
143
160
 
144
161
  candidates = foobara_children.map do |namespace|
145
- namespace.foobara_lookup(path, filter:, mode:, visited:, initial: false)
162
+ namespace.foobara_lookup_without_cache(path, filter:, mode:, visited:)
146
163
  end.compact
147
164
 
148
165
  if candidates.size > 1
@@ -152,8 +169,10 @@ module Foobara
152
169
  # :nocov:
153
170
  end
154
171
 
155
- return candidates.first ||
156
- foobara_parent_namespace&.foobara_lookup(path, filter:, mode:, visited:, initial: false)
172
+ scoped = candidates.first ||
173
+ foobara_parent_namespace&.foobara_lookup_without_cache(path, filter:, mode:, visited:)
174
+
175
+ return scoped
157
176
  end
158
177
 
159
178
  if path[0] == ""
@@ -165,7 +184,31 @@ module Foobara
165
184
  path = path[(foobara_root_namespace.scoped_path.size + 1)..]
166
185
  end
167
186
 
168
- return foobara_root_namespace.foobara_lookup(path, filter:, mode: LookupMode::ABSOLUTE, initial: true)
187
+ return foobara_lookup_without_cache(path, filter:, mode: LookupMode::ABSOLUTE, visited:)
188
+ end
189
+
190
+ root = foobara_root_namespace
191
+
192
+ if mode == LookupMode::ABSOLUTE
193
+ [
194
+ root,
195
+ *root.foobara_depends_on_namespaces.map(&:foobara_root_namespace)
196
+ ].uniq.each do |namespace|
197
+ scoped = namespace.foobara_lookup_without_cache(path,
198
+ filter:,
199
+ mode: LookupMode::CHILDREN_ONLY,
200
+ visited:)
201
+ return scoped if scoped
202
+ end
203
+
204
+ return nil
205
+ end
206
+
207
+ if mode == LookupMode::ABSOLUTE_SINGLE_NAMESPACE
208
+ return foobara_root_namespace.foobara_lookup_without_cache(path,
209
+ filter:,
210
+ mode: LookupMode::CHILDREN_ONLY,
211
+ visited:)
169
212
  end
170
213
 
171
214
  partial = foobara_registry.lookup(path, filter)
@@ -187,18 +230,27 @@ module Foobara
187
230
  end
188
231
 
189
232
  scoped = _lookup_in(path, to_consider, filter:, visited:)
190
- return scoped if scoped
191
233
 
192
- if [LookupMode::GENERAL, LookupMode::STRICT].include?(mode) && foobara_parent_namespace
193
- scoped = foobara_parent_namespace.foobara_lookup(
194
- path, filter:, mode: LookupMode::STRICT, visited:, initial: false
234
+ if scoped
235
+ return scoped
236
+ end
237
+
238
+ if (mode == LookupMode::GENERAL || mode == LookupMode::STRICT) && foobara_parent_namespace
239
+ scoped = foobara_parent_namespace.foobara_lookup_without_cache(
240
+ path, filter:, mode: LookupMode::STRICT, visited:
195
241
  )
196
- return scoped if scoped
242
+
243
+ if scoped
244
+ return scoped
245
+ end
197
246
  end
198
247
 
199
248
  if mode == LookupMode::GENERAL
200
249
  scoped = _lookup_in(path, foobara_depends_on_namespaces, filter:, visited:)
201
- return scoped if scoped
250
+
251
+ if scoped
252
+ return scoped
253
+ end
202
254
  end
203
255
 
204
256
  to_consider = case mode
@@ -209,7 +261,7 @@ module Foobara
209
261
  end
210
262
 
211
263
  candidates = to_consider.map do |namespace|
212
- namespace.foobara_lookup(path, filter:, mode:, visited:, initial: false)
264
+ namespace.foobara_lookup_without_cache(path, filter:, mode:, visited:)
213
265
  end.compact
214
266
 
215
267
  if candidates.size > 1
@@ -218,19 +270,7 @@ module Foobara
218
270
  # :nocov:
219
271
  end
220
272
 
221
- scoped = candidates.first || partial
222
- return scoped if scoped
223
-
224
- # As a last resort we'll see if we're trying to fetch a builtin type from a different namespace
225
- # TODO: these lookup modes are really confusing and were designed prior to having multiple root
226
- # namespaces playing a role in command connectors.
227
- if initial
228
- scoped = Namespace.global.foobara_lookup(path, filter:, mode: LookupMode::ABSOLUTE, visited:, initial: false)
229
-
230
- if scoped.is_a?(Types::Type) && scoped.builtin?
231
- scoped
232
- end
233
- end
273
+ candidates.first || partial
234
274
  end
235
275
 
236
276
  def foobara_parent_namespace
@@ -252,9 +292,10 @@ module Foobara
252
292
  def foobara_each(filter: nil, mode: Namespace::LookupMode::GENERAL, &)
253
293
  foobara_registry.each_scoped(filter:, &)
254
294
 
255
- return if mode == Namespace::LookupMode::DIRECT
256
-
257
- if [Namespace::LookupMode::GENERAL, Namespace::LookupMode::ABSOLUTE].include?(mode)
295
+ if mode == LookupMode::GENERAL ||
296
+ mode == LookupMode::CHILDREN_ONLY ||
297
+ mode == LookupMode::ABSOLUTE ||
298
+ mode == LookupMode::ABSOLUTE_SINGLE_NAMESPACE
258
299
  foobara_children.each do |child|
259
300
  child.foobara_each(filter:, mode:, &)
260
301
  end
@@ -338,6 +379,10 @@ module Foobara
338
379
  Foobara::Namespace::UnambiguousRegistry
339
380
  when Foobara::Namespace::BaseRegistry::WouldMakeRegistryAmbiguousError
340
381
  Foobara::Namespace::AmbiguousRegistry
382
+ else
383
+ # :nocov:
384
+ raise ArgumentError, "Not sure how to upgrade a #{error.class}"
385
+ # :nocov:
341
386
  end
342
387
 
343
388
  old_registry = foobara_registry
@@ -366,19 +411,18 @@ module Foobara
366
411
  end
367
412
 
368
413
  matching_children.sort_by(&:first).reverse.each do |(matching_child_score, matching_child)|
369
- scoped = matching_child.foobara_lookup(
414
+ scoped = matching_child.foobara_lookup_without_cache(
370
415
  path[matching_child_score..],
371
- mode: LookupMode::ABSOLUTE,
416
+ mode: LookupMode::CHILDREN_ONLY,
372
417
  filter:,
373
- visited:,
374
- initial: false
418
+ visited:
375
419
  )
376
420
 
377
421
  return scoped if scoped
378
422
  end
379
423
 
380
424
  last_resort.uniq.each do |namespace|
381
- scoped = namespace.foobara_lookup(path, filter:, mode: LookupMode::ABSOLUTE, visited:, initial: false)
425
+ scoped = namespace.foobara_lookup_without_cache(path, filter:, mode: LookupMode::CHILDREN_ONLY, visited:)
382
426
  return scoped if scoped
383
427
  end
384
428
 
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  class Namespace
3
- # TODO: need to define these better...
3
+ # TODO: need to define these better/more intuitively
4
4
  # use-cases
5
5
  # 1. general: just general lookup. find it wherever the heck it might be
6
6
  # children: y
@@ -17,6 +17,14 @@ module Foobara
17
17
  # 4. absolute
18
18
  # children: y
19
19
  # parent: n
20
+ # dependent: y
21
+ # 5. absolute_single_namespace
22
+ # children: y
23
+ # parent: n
24
+ # dependent: n
25
+ # 6. children_only (internal use... absolute and absolute_single_namespace jump to top, children only does not)
26
+ # children: y
27
+ # parent: n
20
28
  # dependent: n
21
29
  # TODO: don't we have an enumerated class/project for this?
22
30
  module LookupMode
@@ -25,7 +33,10 @@ module Foobara
25
33
  DIRECT = :direct
26
34
  STRICT = :strict
27
35
  ABSOLUTE = :absolute
28
- ALL = [GENERAL, RELAXED, DIRECT, STRICT, ABSOLUTE].freeze
36
+ ABSOLUTE_SINGLE_NAMESPACE = :absolute_single_namespace
37
+ CHILDREN_ONLY = :children_only
38
+
39
+ ALL = [GENERAL, RELAXED, DIRECT, STRICT, ABSOLUTE, ABSOLUTE_SINGLE_NAMESPACE, CHILDREN_ONLY].freeze
29
40
 
30
41
  class << self
31
42
  def validate!(mode)
@@ -243,6 +243,7 @@ module Foobara
243
243
  # I guess we could just iterate over all objects and patch up any with matching prefixes?
244
244
  # is this expensive to have to look at all of them or no? I guess at least it's a one-time thing.
245
245
  # TODO: somehow look things up by prefixes since we know mod's path
246
+ # TODO: can't there be multiple namespace roots??
246
247
  Foobara.foobara_root_namespace.foobara_each do |scoped|
247
248
  parent = scoped.scoped_namespace
248
249
  next if parent == mod
@@ -41,6 +41,8 @@ module Foobara
41
41
  registry.each_value(&)
42
42
  end
43
43
 
44
+ private
45
+
44
46
  def to_key(scoped)
45
47
  if scoped.scoped_prefix
46
48
  raise RegisteringScopedWithPrefixError,
@@ -80,7 +80,26 @@ module Foobara
80
80
 
81
81
  # TODO: this belongs elsewhere
82
82
  def each_table(&)
83
- tables.values.each(&)
83
+ @ordered_tables ||= if tables.size <= 1
84
+ tables.values
85
+ else
86
+ entity_class_to_table = {}
87
+ entity_classes = []
88
+
89
+ tables.each_value do |table|
90
+ entity_class = table.entity_class
91
+ entity_classes << entity_class
92
+ entity_class_to_table[entity_class] = table
93
+ end
94
+
95
+ ordered_entity_classes = EntityBase.order_entity_classes(entity_classes)
96
+
97
+ ordered_entity_classes.map do |entity_class|
98
+ entity_class_to_table[entity_class]
99
+ end
100
+ end
101
+
102
+ @ordered_tables.each(&)
84
103
  end
85
104
 
86
105
  def rollback!(because_of = nil)