hecks 3.3.0 → 3.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 288ec2962d96e6d9772c6fd6155d15461f69259cd7f69e107e308a2710fcb668
4
- data.tar.gz: e71d1ec056df32604dc6ef8de8cab5069ae998faa74d89acd377d79b217820ed
3
+ metadata.gz: b6180e44456a48f89b02b8812b4f327fe1642f98756e8e4c0b1bb295a04f826b
4
+ data.tar.gz: 6bc10cd76fb9c112ce9d7a5b82295a2e2a4c101d1b10b195ab48cd1afefd75c7
5
5
  SHA512:
6
- metadata.gz: a2586bb29d327f576976c7573236abfde1f60deba2eec7529b13ea34fc1b4ea917abe996fd44076cb76690835fb7089f4d18f38d0693d0aa14da2a106334a1a7
7
- data.tar.gz: 1101c11307086a6df1833e6cd7b4fb5fdaa5b0d265b0a4569fa9d4df5d85f27039975f46135dd90619ad69e50d553172eb82d203633177595503f9bbfb67998a
6
+ metadata.gz: 56cfe2cebc08a7aac900d8ef700590aa66855ea0baf28eebb9096f0f74c4d51da5ef42167cffdc6f1bcc733c3cacf8e329bf1352821655247c36e17275614123
7
+ data.tar.gz: 37cc4287ecf68af46b507dff79b3041de0a6e28fe2a1a7e5d89bea393b74d5f84eead4e11509c0f16d47d11ec8abfe9b292d73ec14845d9466e086dcec3bf350
@@ -57,9 +57,12 @@ module Hecks
57
57
  end
58
58
  end
59
59
 
60
- # The release that drops the deprecated spellings of `attaches`; independent of
61
- # `Hecks::Doors::REMOVAL`, which covers the older `Facade` aliases.
62
- REMOVAL = "3.4.0".freeze
60
+ # Spellings of `attaches` that 3.4.0 removed, each with the form that replaces it. They
61
+ # are refused by name so an old hecksagon fails loudly, never as a stray default bind.
62
+ REMOVED_WORDS = {
63
+ "uses_framework" => ->(name) { "attaches #{name.to_s.inspect}" },
64
+ "uses_embryonaut_bluebook" => ->(name) { "attaches #{name.to_s.inspect}, from: :vendor" }
65
+ }.freeze
63
66
 
64
67
  attr_reader :binds, :subscriptions, :attachments
65
68
 
@@ -100,20 +103,6 @@ module Hecks
100
103
  from == :vendor ? attach_vendored(name) : attach_gem(name)
101
104
  end
102
105
 
103
- # The deprecated spelling of `attaches "Name"` for a framework member.
104
- def uses_framework(name)
105
- deprecated_word("uses_framework", "attaches #{name.to_s.inspect}")
106
- @attachments << Attachment.new(name: name.to_s, source: :gem)
107
- self.class.with_real_modules { Hecks::Framework.load!(name) }
108
- Hecks.current_registry&.mark_bounded(name.to_s)
109
- end
110
-
111
- # The deprecated spelling of `attaches "name", from: :vendor`.
112
- def uses_embryonaut_bluebook(name)
113
- deprecated_word("uses_embryonaut_bluebook", "attaches #{name.to_s.inspect}, from: :vendor")
114
- attach_vendored(name)
115
- end
116
-
117
106
  # Declares a port at the hecksagon's root — the chapter as a whole, not one aggregate.
118
107
  def port_impl(name, &block)
119
108
  bluebook_ir = Hecks.current_registry.bluebook(@domain) or
@@ -170,15 +159,11 @@ module Hecks
170
159
  end
171
160
  private :attach_vendored
172
161
 
173
- # Tells the author that a word is going away.
174
- def deprecated_word(word, instead)
175
- warn "[hecks] `#{word}` is deprecated and is removed in #{REMOVAL}; use `#{instead}`"
176
- end
177
- private :deprecated_word
178
-
179
162
  # Records any verb the grammar doesn't own as a domain-wide default bind, e.g. bare
180
163
  # `persisted_by "Heki"` at the top of a block, applied unless an aggregate overrides it.
181
164
  def method_missing(verb, *args, **kwargs, &block)
165
+ refuse_removed_word(verb, args.first)
166
+
182
167
  # Grammar words (like `port`) get first refusal via explicit dispatch; only when that's
183
168
  # not admitted does the open-ended `persisted_by`-style bind vocabulary below apply.
184
169
  result = word_gate_dispatch(verb, args, kwargs, block)
@@ -191,6 +176,19 @@ module Hecks
191
176
  self
192
177
  end
193
178
 
179
+ # Raises for a word 3.4.0 removed, naming the spelling that replaces it.
180
+ #
181
+ # @param verb [Symbol] the word the hecksagon block called
182
+ # @param name [Object, nil] its first argument, echoed into the replacement
183
+ # @raise [Malformed] when the word is one of `REMOVED_WORDS`
184
+ def refuse_removed_word(verb, name)
185
+ instead = REMOVED_WORDS[verb.to_s]
186
+ return unless instead
187
+
188
+ raise Malformed, "`#{verb}` was removed in 3.4.0; use `#{instead.call(name)}`"
189
+ end
190
+ private :refuse_removed_word
191
+
194
192
  def respond_to_missing?(_name, _include_private = false) = true
195
193
 
196
194
  # Evaluates a `Hecks.hecksagon` block with bare `Domain::Aggregate` constants resolving to
@@ -113,7 +113,7 @@ module Hecks
113
113
  # The aggregates, with their commands: the part a later interview offers to merge.
114
114
  # @api private
115
115
  def fragment(interview)
116
- things = accepted(interview, :things)
116
+ things = accepted(interview, :things).uniq { |t| word(t[:name]) }
117
117
  actions = accepted(interview, :actions)
118
118
  placed = things.map { |t| word(t[:name]) }
119
119
  blocks = things.map { |thing| aggregate(interview, thing, actions) }
@@ -151,7 +151,7 @@ module Hecks
151
151
  def shape_of(interview, thing, actions)
152
152
  name = word(thing[:name])
153
153
  identifier = Naming.snake(word(thing[:identifier]))
154
- mine = actions.select { |a| word(a[:thing]) == name }
154
+ mine = InterviewShape.merged_actions(actions.select { |a| word(a[:thing]) == name })
155
155
  steps = accepted(interview, :transitions).select { |s| word(s[:thing]) == name }
156
156
  found = accepted(interview, :fields).select { |f| word(f[:thing]) == name }
157
157
  type = identifier_type(name, identifier)
@@ -121,6 +121,25 @@ module Hecks
121
121
  " end", *loose.map { |step| loose_line(step) }]
122
122
  end
123
123
 
124
+ # One action for each name: an expert who refines an answer gets the same action accepted more
125
+ # than once, and a command can be declared only once. The first one's event and place in the
126
+ # interview stay; what each takes is joined, who does it is joined, and it creates if any did.
127
+ #
128
+ # @param actions [Array<Hash>] a thing's accepted actions
129
+ # @return [Array<Hash>] the actions, with each name once and in the order first accepted
130
+ def merged_actions(actions)
131
+ actions.group_by { |action| InterviewDraft.word(action[:name]) }.values.map do |group|
132
+ group.first.merge(creates: group.any? { |a| a[:creates] }, takes: joined(group, :takes, ", "),
133
+ by: joined(group, :by, " or "))
134
+ end
135
+ end
136
+
137
+ # @api private
138
+ def joined(group, key, separator)
139
+ parts = group.flat_map { |a| a[key].to_s.split(separator == ", " ? /\s*,\s*/ : /\s+or\s+/) }
140
+ parts.map(&:strip).reject(&:empty?).uniq.join(separator)
141
+ end
142
+
124
143
  # @api private
125
144
  def field_row(finding, taken, identifier, lifecycle)
126
145
  field = Naming.snake(InterviewDraft.word(finding[:name]))
data/lib/hecks/corpus.rb CHANGED
@@ -241,8 +241,7 @@ module Hecks
241
241
  "of rust/src/generated, and there is no directory to fuzz")
242
242
  }.freeze
243
243
 
244
- # Every place a Rust-facing domain's own `attaches` (or the deprecated `uses_framework` /
245
- # `uses_embryonaut_bluebook`) attachment could be declared.
244
+ # Every place a Rust-facing domain's own `attaches` attachment could be declared.
246
245
  #
247
246
  # @param root [String] repository root to search under
248
247
  # @return [String] every reachable hecksagon file's own text, joined by newlines
@@ -310,11 +309,10 @@ module Hecks
310
309
 
311
310
  # The stamp hecks project_rust writes into metadata.rs, e.g.
312
311
  # `examples/pizzas` or `the self-hosted language (...)`, with any
313
- # ` (attaches "X")`/` (attaches "x", from: :vendor)` suffix stripped (the deprecated
314
- # `uses_framework` / `uses_embryonaut_bluebook` spellings too).
312
+ # ` (attaches "X")`/` (attaches "x", from: :vendor)` suffix stripped.
315
313
  SOURCE_STAMP = /
316
314
  GENERATED\ by\ hecks\ project_rust\ —\ (.+?)
317
- (?:\ \((?:attaches|uses_framework|uses_embryonaut_bluebook)\ "\w+"(?:,\ from:\ :vendor)?\))?
315
+ (?:\ \(attaches\ "\w+"(?:,\ from:\ :vendor)?\))?
318
316
  's\ own\ canonical\ IR,
319
317
  /x
320
318
 
data/lib/hecks/doors.rb CHANGED
@@ -1,23 +1,6 @@
1
1
  module Hecks
2
2
  # The class-free public surface, installed per boot by `Runtime::Loader.bind_runtime`.
3
3
  module Doors
4
- # The removal release of the `Facade` and `install_facade:` spellings.
5
- REMOVAL = "3.4.0".freeze
6
-
7
- module_function
8
-
9
- # Resolves the boot switch from the current keyword and its deprecated spelling.
10
- #
11
- # @param install_doors [Boolean] the `install_doors:` keyword
12
- # @param install_facade [Boolean, nil] the deprecated `install_facade:` keyword; nil when
13
- # the caller did not pass it
14
- # @return [Boolean] whether to install the Ruby door constants
15
- def install?(install_doors, install_facade = nil)
16
- return install_doors if install_facade.nil?
17
-
18
- warn "[hecks] `install_facade:` is deprecated and is removed in #{REMOVAL}; use `install_doors:`"
19
- install_facade
20
- end
21
4
  end
22
5
 
23
6
  # Installs facade constants at top level, replacing only what it installed itself.
@@ -12,9 +12,6 @@ module Hecks
12
12
  # A vendored package named by `attaches "name", from: :vendor`.
13
13
  VENDORED_ATTACHED = /attaches\s*\(?\s*"([\w-]+)"\s*\)?\s*,\s*from:\s*:vendor/
14
14
 
15
- # A vendored package named by the deprecated `uses_embryonaut_bluebook "name"`.
16
- VENDORED_DEPRECATED = /uses_embryonaut_bluebook\s*\(?\s*"([\w-]+)"/
17
-
18
15
  module_function
19
16
 
20
17
  # Copies `domain_path` to a tmpdir, rebinds its persistence to `adapter`, and
@@ -74,7 +71,7 @@ module Hecks
74
71
  def carry_vendored_bluebooks!(source, destination)
75
72
  names = Dir.glob(File.join(destination, "**", "*.hecksagon")).flat_map do |path|
76
73
  text = File.read(path)
77
- (text.scan(VENDORED_DEPRECATED) + text.scan(VENDORED_ATTACHED)).flatten
74
+ text.scan(VENDORED_ATTACHED).flatten
78
75
  end
79
76
  names.uniq.each do |name|
80
77
  package = File.join(File.dirname(source), "vendor", "embryonaut_bluebooks", name)
@@ -16,7 +16,7 @@ module Hecks
16
16
  POSTGRES_ERA_VARIABLE = /^\s*([a-z_]\w*)\s*=\s*"PostgresEra"\s*(?:#.*)?$/
17
17
 
18
18
  # Captures the member a hecksagon attaches; authorization is read off its declaration.
19
- FRAMEWORK_ATTACHED = /(?:attaches|uses_framework)\s*\(?\s*"([^"]+)"/
19
+ FRAMEWORK_ATTACHED = /attaches\s*\(?\s*"([^"]+)"/
20
20
 
21
21
  # A command-level `role "..."`, the only construct a role check can compare a caller against.
22
22
  ROLE_GATED = /^\s*role\s+"/
@@ -83,9 +83,6 @@ Hecks.bluebook "Hecksagon" do
83
83
  member word: "hecksagon", context: "File", body: "keywords", inner: "Hecksagon", opens: "Hecksagon", fills: ""
84
84
  member word: "subscribe", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "subscriptions"
85
85
  member word: "attaches", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "attachments"
86
- # Deprecated spellings of `attaches`; they warn and are removed in 3.4.0.
87
- member word: "uses_framework", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "attachments", status: "deprecated"
88
- member word: "uses_embryonaut_bluebook", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "attachments", status: "deprecated"
89
86
  member word: "port", context: "Hecksagon", body: "keywords", inner: "DomainPort", opens: "DomainPort", fills: "", calls: "port_impl"
90
87
  # A cross-domain reaction wired here rather than in the bluebook; reuses the Policy context.
91
88
  # No `calls:` — HecksagonBuilder#translates is an ordinary method, found before `word_gate`.
@@ -116,8 +113,6 @@ Hecks.bluebook "Hecksagon" do
116
113
  member keyword: "subscribe", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "subscriptions"
117
114
  member keyword: "attaches", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "attachments"
118
115
  member keyword: "attaches", context: "Hecksagon", at: "", named: "from", kind: "symbol", required: "false", fills: "source"
119
- member keyword: "uses_framework", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "attachments"
120
- member keyword: "uses_embryonaut_bluebook", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "attachments"
121
116
  member keyword: "port", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "name"
122
117
  member keyword: "translates", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "name"
123
118
 
@@ -27,9 +27,9 @@ module Hecks
27
27
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted dispatcher
28
28
  # @raise [Errno::ENOENT] if `path` names no domain directory
29
29
  # @raise [Runtime::WiringError] if a boot gate finds a wiring problem
30
- def self.boot(path, shared: nil, install_doors: true, install_facade: nil, environment: FROM_ENV)
30
+ def self.boot(path, shared: nil, install_doors: true, environment: FROM_ENV)
31
31
  described = describe(path, shared: shared, environment: environment)
32
- boot_described(described, install_doors: install_doors, install_facade: install_facade)
32
+ boot_described(described, install_doors: install_doors)
33
33
  end
34
34
 
35
35
  # Finishes a boot from declarations `describe` already loaded: runs every boot gate and binds
@@ -37,16 +37,15 @@ module Hecks
37
37
  #
38
38
  # @param described [Described] what `describe` answered for the domain to boot
39
39
  # @param install_doors [Boolean] install the `Widget::Item.Add(...)` global facade sugar
40
- # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`
41
40
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted dispatcher
42
41
  # @raise [Runtime::WiringError] if a boot gate finds a wiring problem
43
- def self.boot_described(described, install_doors: true, install_facade: nil)
42
+ def self.boot_described(described, install_doors: true)
44
43
  registry = described.registry
45
44
  run_boot_gates!(registry, described.directory)
46
45
  dispatcher = dispatcher_for(registry)
47
46
  redrive_outbox!(dispatcher)
48
47
  seed_privacy_markings!(dispatcher, registry)
49
- Doors.install?(install_doors, install_facade) ? bind_runtime(dispatcher) : dispatcher
48
+ install_doors ? bind_runtime(dispatcher) : dispatcher
50
49
  end
51
50
 
52
51
  # What `describe` answers: the loaded declarations and nothing bound to run them.
@@ -153,7 +152,7 @@ module Hecks
153
152
  # defaults to `HECKS_ENVIRONMENT`, and an explicit nil loads none
154
153
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted dispatcher
155
154
  # @raise [Runtime::WiringError] if a boot gate finds a wiring problem
156
- def self.boot_files(paths, shared: nil, install_doors: true, install_facade: nil, environment: FROM_ENV)
155
+ def self.boot_files(paths, shared: nil, install_doors: true, environment: FROM_ENV)
157
156
  loading = Ports::Loading.bootstrap
158
157
  files = Array(paths).map { |path| File.expand_path(path) }
159
158
  directory = File.dirname(files.first)
@@ -168,7 +167,7 @@ module Hecks
168
167
 
169
168
  run_boot_gates!(registry, directory)
170
169
  dispatcher = dispatcher_for(registry)
171
- Doors.install?(install_doors, install_facade) ? bind_runtime(dispatcher) : dispatcher
170
+ install_doors ? bind_runtime(dispatcher) : dispatcher
172
171
  end
173
172
 
174
173
  # Runs every registered boot gate against `registry`, in order:
data/lib/hecks/runtime.rb CHANGED
@@ -43,13 +43,11 @@ module Hecks
43
43
  # @param path [String] path to a domain directory, or a file inside one
44
44
  # @param shared [String, nil] a shared-root override
45
45
  # @param install_doors [Boolean] whether to install the Ruby facade constants
46
- # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
47
46
  # @param environment [String, nil] the environment name for `Adapters::Folder#load_domain`
48
47
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
49
48
  # to the booted domain
50
- def boot(path, shared: nil, install_doors: true, install_facade: nil, environment: Runtime::Loader::FROM_ENV)
51
- Loader.boot(path, shared: shared, install_doors: install_doors, environment: environment,
52
- install_facade: install_facade)
49
+ def boot(path, shared: nil, install_doors: true, environment: Runtime::Loader::FROM_ENV)
50
+ Loader.boot(path, shared: shared, install_doors: install_doors, environment: environment)
53
51
  end
54
52
 
55
53
  # Loads a domain's declarations without binding any adapter. See Loader.describe.
@@ -66,11 +64,10 @@ module Hecks
66
64
  #
67
65
  # @param described [Runtime::Loader::Described] what `describe` answered
68
66
  # @param install_doors [Boolean] whether to install the Ruby facade constants
69
- # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
70
67
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
71
68
  # to the booted domain
72
- def boot_described(described, install_doors: true, install_facade: nil)
73
- Loader.boot_described(described, install_doors: install_doors, install_facade: install_facade)
69
+ def boot_described(described, install_doors: true)
70
+ Loader.boot_described(described, install_doors: install_doors)
74
71
  end
75
72
 
76
73
  # Loads only the given files of a domain; otherwise like `boot`. See Loader.boot_files.
@@ -78,13 +75,11 @@ module Hecks
78
75
  # @param paths [String, Array<String>] one or more file paths within the domain
79
76
  # @param shared [String, nil] a shared-root override
80
77
  # @param install_doors [Boolean] whether to install the Ruby facade constants
81
- # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
82
78
  # @param environment [String, nil] the environment name for the selected-file loader
83
79
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the dispatcher bound
84
80
  # to the booted domain
85
- def boot_files(paths, shared: nil, install_doors: true, install_facade: nil, environment: Runtime::Loader::FROM_ENV)
86
- Loader.boot_files(paths, shared: shared, install_doors: install_doors, environment: environment,
87
- install_facade: install_facade)
81
+ def boot_files(paths, shared: nil, install_doors: true, environment: Runtime::Loader::FROM_ENV)
82
+ Loader.boot_files(paths, shared: shared, install_doors: install_doors, environment: environment)
88
83
  end
89
84
 
90
85
  # Bind the ambient registry for the duration of the block, restoring
data/lib/hecks/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Hecks
2
2
  # Read directly by the gemspec, so this file must never require the
3
3
  # rest of the gem (its dependencies aren't resolved yet at that point).
4
- VERSION = "3.3.0".freeze
4
+ VERSION = "3.4.0".freeze
5
5
  end
data/lib/hecks.rb CHANGED
@@ -13,7 +13,6 @@ require_relative "hecks/construct"
13
13
  require_relative "hecks/ir"
14
14
  require_relative "hecks/literal"
15
15
  require_relative "hecks/doors"
16
- require_relative "hecks/facade"
17
16
  require_relative "hecks/query_specification"
18
17
 
19
18
  require_relative "hecks/ports"
@@ -58,13 +57,11 @@ module Hecks
58
57
  # @param path [String] path to a domain directory, or a file inside one
59
58
  # @param shared [String, nil] a shared-root override; see `Runtime::Loader.boot`
60
59
  # @param install_doors [Boolean] install the `Widget::Item.Add`-style facade
61
- # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
62
60
  # @param environment [String, nil] env name; its `.hecksagon`/`.world` overlay,
63
61
  # if present, loads after the domain's own. Defaults to `HECKS_ENVIRONMENT`; nil loads none
64
62
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] dispatcher bound to the domain
65
- def boot(path, shared: nil, install_doors: true, install_facade: nil, environment: Runtime::Loader::FROM_ENV)
66
- Runtime.boot(path, shared: shared, install_doors: install_doors, environment: environment,
67
- install_facade: install_facade)
63
+ def boot(path, shared: nil, install_doors: true, environment: Runtime::Loader::FROM_ENV)
64
+ Runtime.boot(path, shared: shared, install_doors: install_doors, environment: environment)
68
65
  end
69
66
 
70
67
  # Loads a domain's declarations without binding any adapter or opening any store.
@@ -82,10 +79,9 @@ module Hecks
82
79
  #
83
80
  # @param described [Runtime::Loader::Described] what `describe` answered
84
81
  # @param install_doors [Boolean] install the `Widget::Item.Add`-style facade
85
- # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
86
82
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] dispatcher bound to the domain
87
- def boot_described(described, install_doors: true, install_facade: nil)
88
- Runtime.boot_described(described, install_doors: install_doors, install_facade: install_facade)
83
+ def boot_described(described, install_doors: true)
84
+ Runtime.boot_described(described, install_doors: install_doors)
89
85
  end
90
86
 
91
87
  # Boots a domain from an explicit list of files (a `.bluebook`, its
@@ -94,12 +90,10 @@ module Hecks
94
90
  # @param paths [String, Array<String>] one or more file paths within the domain
95
91
  # @param shared [String, nil] a shared-root override; see `Runtime::Loader.boot_files`
96
92
  # @param install_doors [Boolean] install the `Widget::Item.Add`-style facade
97
- # @param install_facade [Boolean, nil] the deprecated spelling of `install_doors`; warns
98
93
  # @param environment [String, nil] environment name passed to the selected-file loader
99
94
  # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] dispatcher bound to the domain
100
- def boot_files(paths, shared: nil, install_doors: true, install_facade: nil, environment: Runtime::Loader::FROM_ENV)
101
- Runtime.boot_files(paths, shared: shared, install_doors: install_doors, environment: environment,
102
- install_facade: install_facade)
95
+ def boot_files(paths, shared: nil, install_doors: true, environment: Runtime::Loader::FROM_ENV)
96
+ Runtime.boot_files(paths, shared: shared, install_doors: install_doors, environment: environment)
103
97
  end
104
98
 
105
99
  # Binds the ambient registry for the duration of the block.
@@ -1 +1 @@
1
- 3.3.0
1
+ 3.4.0
@@ -184,8 +184,6 @@ pub static KEYWORDS: &[KeywordRow] = &[
184
184
  KeywordRow { word: "hecksagon", context: "File", body: "keywords", inner: "Hecksagon", opens: "Hecksagon", fills: "", status: "admitted", was: "", resolves_via: "", disambiguator: "" },
185
185
  KeywordRow { word: "subscribe", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "subscriptions", status: "admitted", was: "", resolves_via: "", disambiguator: "" },
186
186
  KeywordRow { word: "attaches", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "attachments", status: "admitted", was: "", resolves_via: "", disambiguator: "" },
187
- KeywordRow { word: "uses_framework", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "attachments", status: "deprecated", was: "", resolves_via: "", disambiguator: "" },
188
- KeywordRow { word: "uses_embryonaut_bluebook", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "attachments", status: "deprecated", was: "", resolves_via: "", disambiguator: "" },
189
187
  KeywordRow { word: "port", context: "Hecksagon", body: "keywords", inner: "DomainPort", opens: "DomainPort", fills: "", status: "admitted", was: "", resolves_via: "", disambiguator: "" },
190
188
  KeywordRow { word: "translates", context: "Hecksagon", body: "keywords", inner: "Policy", opens: "Policy", fills: "", status: "admitted", was: "", resolves_via: "", disambiguator: "" },
191
189
  KeywordRow { word: "bounded", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "", status: "admitted", was: "", resolves_via: "", disambiguator: "" },
@@ -470,8 +468,6 @@ pub static ARGUMENTS: &[ArgumentRow] = &[
470
468
  ArgumentRow { keyword: "subscribe", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "subscriptions", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
471
469
  ArgumentRow { keyword: "attaches", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "attachments", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
472
470
  ArgumentRow { keyword: "attaches", context: "Hecksagon", at: "", named: "from", kind: "symbol", required: "false", fills: "source", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
473
- ArgumentRow { keyword: "uses_framework", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "attachments", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
474
- ArgumentRow { keyword: "uses_embryonaut_bluebook", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "attachments", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
475
471
  ArgumentRow { keyword: "port", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "name", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
476
472
  ArgumentRow { keyword: "translates", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "name", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
477
473
  ArgumentRow { keyword: "reference_to", context: "PortOperation", at: "1", named: "", kind: "constant", required: "true", fills: "type", selects: "", pair_key_fills: "", pair_value_fills: "", pairs_shape: "", status: "admitted", variadic: "", minimum: "" },
@@ -567,7 +567,7 @@ mod tests {
567
567
  #[test]
568
568
  fn does_not_strip_a_bare_lowercase_call() {
569
569
  assert_eq!(
570
- strip_aggregate_receiver("uses_framework \"Governance\""),
570
+ strip_aggregate_receiver("attaches \"Governance\""),
571
571
  None
572
572
  );
573
573
  assert_eq!(strip_aggregate_receiver("subscribe \"Deposited\""), None);
@@ -14,9 +14,8 @@ pub fn not_implemented(file: &str, line: usize, word: &str) -> Diagnostic {
14
14
  /// Applies a `.hecksagon` body onto an already-built `ir::Bluebook`, attaching
15
15
  /// aggregate-scoped ports to the aggregates the sibling `.bluebook` registered.
16
16
  ///
17
- /// `gem_chapter_names` collects each `attaches "Name"` (and the deprecated `uses_framework`) and
18
- /// `vendored_bluebook_names` each `attaches "name", from: :vendor` (and the deprecated
19
- /// `uses_embryonaut_bluebook`), in file order, for `hecks-parse resolve`; `ir.json` itself
17
+ /// `gem_chapter_names` collects each `attaches "Name"` and
18
+ /// `vendored_bluebook_names` each `attaches "name", from: :vendor`, in file order, for `hecks-parse resolve`; `ir.json` itself
20
19
  /// carries neither.
21
20
  ///
22
21
  /// `require_matching_aggregate` is `false` for resolve, which never sees a `.bluebook`, so an
@@ -65,8 +64,20 @@ pub fn apply(
65
64
  if let LineShape::Call(call) = lex::classify(file, &line)? {
66
65
  if !matches!(
67
66
  call.word.as_str(),
68
- "port" | "subscribe" | "uses_framework" | "uses_embryonaut_bluebook" | "attaches" | "translates" | "bounded" | "end"
67
+ "port" | "subscribe" | "attaches" | "translates" | "bounded" | "end"
69
68
  ) {
69
+ let instead = match call.word.as_str() {
70
+ "uses_framework" => Some("attaches \"Name\""),
71
+ "uses_embryonaut_bluebook" => Some("attaches \"name\", from: :vendor"),
72
+ _ => None,
73
+ };
74
+ if let Some(instead) = instead {
75
+ return Err(Diagnostic::new(
76
+ file,
77
+ line.number,
78
+ format!("`{}` was removed in 3.4.0; use `{instead}`", call.word),
79
+ ));
80
+ }
70
81
  *pos += 1;
71
82
  if matches!(call.opener, Opener::DoBlock { .. }) {
72
83
  skip_dropped_body(file, lines, pos)?;
@@ -98,26 +109,6 @@ pub fn apply(
98
109
  let built = policy::parse_body(file, lines, pos, &name)?;
99
110
  bluebook.policies.push(built);
100
111
  }
101
- // Deprecated spelling of `attaches "Name"`; gated, then collected.
102
- "uses_framework" => {
103
- gem_chapter_names.push(super::positional_text(
104
- file,
105
- gated.line.number,
106
- "uses_framework",
107
- &gated.args,
108
- 1,
109
- )?);
110
- }
111
- // Deprecated spelling of `attaches "name", from: :vendor`; collected the same way.
112
- "uses_embryonaut_bluebook" => {
113
- vendored_bluebook_names.push(super::positional_text(
114
- file,
115
- gated.line.number,
116
- "uses_embryonaut_bluebook",
117
- &gated.args,
118
- 1,
119
- )?);
120
- }
121
112
  "subscribe" => {}
122
113
  // One word for a chapter the gem carries and for a vendored package; a binding
123
114
  // fact collected for `resolve`, absent from `ir.json`. Only `from: :vendor`
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hecks
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Young
@@ -288,7 +288,6 @@ files:
288
288
  - lib/hecks/embryonaut_bluebook/vendor.rb
289
289
  - lib/hecks/embryonaut_bluebook/vendor_cli.rb
290
290
  - lib/hecks/engine_agreement.rb
291
- - lib/hecks/facade.rb
292
291
  - lib/hecks/forms.rb
293
292
  - lib/hecks/forms/app.rb
294
293
  - lib/hecks/forms/banking_presentation.rb
data/lib/hecks/facade.rb DELETED
@@ -1,31 +0,0 @@
1
- # The deprecated alias shim: `Hecks::Facade` is now `Hecks::Doors` and `Doors::Surface` is
2
- # `Doors::RubyDoor`. Both old constants still resolve and warn; they are removed in
3
- # `Hecks::Doors::REMOVAL`.
4
- require_relative "doors"
5
-
6
- # The root namespace; this file holds only the deprecated aliases.
7
- module Hecks
8
- # Resolves the constants that now live in `Doors` under their old names, warning on each use.
9
- #
10
- # Extended onto `Hecks` and `Hecks::Doors`, ahead of `Module#const_missing`.
11
- module DoorsAliases
12
- # Old constant name mapped to the new one, per namespace that carried it.
13
- RENAMED = { Hecks => { Facade: "Hecks::Doors" }, Hecks::Doors => { Surface: "Hecks::Doors::RubyDoor" } }.freeze
14
-
15
- # Answers a renamed constant with its replacement and a warning; anything else
16
- # goes to the next `const_missing`.
17
- #
18
- # @param name [Symbol] the missing constant
19
- # @return [Module] the replacement module
20
- def const_missing(name)
21
- target = RENAMED.fetch(self, {})[name]
22
- return super unless target
23
-
24
- warn "[hecks] #{self}::#{name} is deprecated and is removed in #{Hecks::Doors::REMOVAL}; use #{target}"
25
- Object.const_get(target)
26
- end
27
- end
28
-
29
- extend DoorsAliases
30
- Doors.extend(DoorsAliases)
31
- end