expressir 2.4.18 → 2.4.20
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 +4 -4
- data/lib/expressir/mapping/refpath.rb +89 -30
- data/lib/expressir/mapping.rb +10 -2
- data/lib/expressir/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e6cda48af3f6a3d844c896622b39a79c31631c9b164f5f727d2841d85decb1ec
|
|
4
|
+
data.tar.gz: 375c96471483ed06f43272785520d5f6c763687a03f104dd1d5049636c010948
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f64857ddcef1a8bd7896ee1c5c8ed6050ba263e2ab8aa2df2bc8a02e98f3e55c8cf2e6b186760dbda9a37e513882292fe3569eb5ded9eee471978e3ef4580a9e
|
|
7
|
+
data.tar.gz: 8e6f94bc7c441f0fd1394c7cff8d512e20247c5f07291b2d969bdfcdef1af5cadf6230b4b2512cc273ca08d9de3ef906e4762fad6cbbcaa273f3667429355dea
|
|
@@ -15,6 +15,10 @@ module Expressir
|
|
|
15
15
|
# link := "->" | "<-" | "<=" | "=>" | "=" NAME
|
|
16
16
|
# (relation to the previous node)
|
|
17
17
|
# node := NAME ["." ATTRIBUTE]
|
|
18
|
+
# | LINK (<<express:SCHEMA.ITEM,ITEM>>,
|
|
19
|
+
# #460: a link may stand
|
|
20
|
+
# wherever a declaration
|
|
21
|
+
# is referenced)
|
|
18
22
|
# index := "[" ("i" | DIGITS) "]"
|
|
19
23
|
# MARKER := "{" | "}" | "[" | "]" | "(" | ")" | ":" | "|" | "!"
|
|
20
24
|
# | "," | "/" | "*" (grouping/annotation; no
|
|
@@ -42,6 +46,8 @@ module Expressir
|
|
|
42
46
|
attribute :attribute, :string
|
|
43
47
|
attribute :index, :string
|
|
44
48
|
attribute :literal, :string
|
|
49
|
+
# annotated EXPRESS link form: <<express:SCHEMA.ITEM,ITEM>>
|
|
50
|
+
attribute :link, :string
|
|
45
51
|
|
|
46
52
|
key_value do
|
|
47
53
|
map "operator", to: :operator
|
|
@@ -49,6 +55,7 @@ module Expressir
|
|
|
49
55
|
map "attribute", to: :attribute
|
|
50
56
|
map "index", to: :index
|
|
51
57
|
map "literal", to: :literal
|
|
58
|
+
map "link", to: :link
|
|
52
59
|
end
|
|
53
60
|
end
|
|
54
61
|
|
|
@@ -62,9 +69,12 @@ module Expressir
|
|
|
62
69
|
end
|
|
63
70
|
end
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
EXPRESS_LINK_PATH = /\A<<express:([^,>]+)(?:,[^>]+)?>>\z/
|
|
73
|
+
private_constant :EXPRESS_LINK_PATH
|
|
74
|
+
|
|
75
|
+
TOKEN = /<<express:[^,>]+(?:,[^>]+)?>>|->|<-|<=|=>|[{}\[\]()=:|!,*\/]|'(?:''|[^'])*'|\w+(?:\.\w+)?/
|
|
66
76
|
MARKERS = ["{", "}", "[", "]", "(", ")", ":", "|", "!", ",", "/",
|
|
67
|
-
"*"].freeze
|
|
77
|
+
"*", "MAPPING_OF"].freeze
|
|
68
78
|
LINKS = ["->", "<-", "<=", "=>"].freeze
|
|
69
79
|
DECLARATION_COLLECTIONS = %i[types entities].freeze
|
|
70
80
|
private_constant :TOKEN, :MARKERS, :LINKS, :DECLARATION_COLLECTIONS
|
|
@@ -109,19 +119,17 @@ module Expressir
|
|
|
109
119
|
end
|
|
110
120
|
when *MARKERS
|
|
111
121
|
steps << Step.new(operator: token)
|
|
122
|
+
when /\A<<express:/
|
|
123
|
+
steps << Step.new(operator: pending_link, link: token)
|
|
124
|
+
pending_link = nil
|
|
125
|
+
pending_type_assign = false
|
|
112
126
|
else
|
|
113
127
|
name, _, attribute = token.partition(".")
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
operator = pending_link || ("=" if pending_type_assign)
|
|
120
|
-
steps << Step.new(operator: operator, name: name,
|
|
121
|
-
attribute: attribute.empty? ? nil : attribute)
|
|
122
|
-
pending_link = nil
|
|
123
|
-
pending_type_assign = false
|
|
124
|
-
end
|
|
128
|
+
operator = pending_link || ("=" if pending_type_assign)
|
|
129
|
+
steps << Step.new(operator: operator, name: name,
|
|
130
|
+
attribute: attribute.empty? ? nil : attribute)
|
|
131
|
+
pending_link = nil
|
|
132
|
+
pending_type_assign = false
|
|
125
133
|
end
|
|
126
134
|
i += 1
|
|
127
135
|
end
|
|
@@ -153,34 +161,66 @@ module Expressir
|
|
|
153
161
|
by_name = name_index(repository)
|
|
154
162
|
issues = []
|
|
155
163
|
prev = nil
|
|
164
|
+
last_qualified = nil
|
|
156
165
|
path.steps.each_with_index do |step, pos|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
next
|
|
160
|
-
end
|
|
166
|
+
# markers never break the running link, mirroring parse
|
|
167
|
+
next if MARKERS.include?(step.operator)
|
|
161
168
|
|
|
162
|
-
|
|
163
|
-
|
|
169
|
+
if step.link
|
|
170
|
+
issues.concat(check_link_step(step, pos, repository))
|
|
171
|
+
else
|
|
172
|
+
issues.concat(check_step(step, pos, prev, last_qualified, by_name))
|
|
173
|
+
end
|
|
174
|
+
prev = step if step.name || step.link
|
|
175
|
+
last_qualified = step if step.name && step.attribute
|
|
164
176
|
end
|
|
165
177
|
issues
|
|
166
178
|
end
|
|
167
179
|
|
|
180
|
+
EXPRESS_BUILTINS = %w[NUMBER INTEGER REAL STRING BOOLEAN LOGICAL
|
|
181
|
+
BINARY].freeze
|
|
182
|
+
private_constant :EXPRESS_BUILTINS
|
|
183
|
+
|
|
168
184
|
def name_index(repository)
|
|
185
|
+
index = EXPRESS_BUILTINS.to_h { |b| [b.downcase, [nil, nil]] }
|
|
169
186
|
repository.schemas.flat_map do |schema|
|
|
170
187
|
DECLARATION_COLLECTIONS.flat_map do |coll|
|
|
171
188
|
Array(schema.public_send(coll))
|
|
172
189
|
.select { |d| d.respond_to?(:id) && d.id }
|
|
173
190
|
.map { |d| [d.id.safe_downcase, [schema, d]] }
|
|
174
191
|
end
|
|
175
|
-
end.
|
|
192
|
+
end.each { |pair| index[pair[0]] = pair[1] }
|
|
193
|
+
index
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Annotated EXPRESS link node: <<express:SCHEMA.ITEM,ITEM>>
|
|
197
|
+
# (item part optional) resolves against the repository (#460).
|
|
198
|
+
def check_link_step(step, pos, repository)
|
|
199
|
+
parts = step.link.match(EXPRESS_LINK_PATH)
|
|
200
|
+
return [Issue.new(step: pos, message: "malformed link '#{step.link}'")] unless parts
|
|
201
|
+
|
|
202
|
+
schema_id, item_id = parts[1].split(".", 2).compact
|
|
203
|
+
schema = repository.schemas
|
|
204
|
+
.find { |s| s.id&.safe_downcase == schema_id&.safe_downcase }
|
|
205
|
+
unless schema
|
|
206
|
+
return [Issue.new(step: pos,
|
|
207
|
+
message: "unknown schema '#{schema_id}' in #{step.link}")]
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
return [] if item_id.nil?
|
|
211
|
+
return [] if Expressir::Mapping.item_declared?(schema, item_id)
|
|
212
|
+
|
|
213
|
+
[Issue.new(step: pos,
|
|
214
|
+
message: "schema '#{schema_id}' does not declare " \
|
|
215
|
+
"'#{item_id}' (#{step.link})")]
|
|
176
216
|
end
|
|
177
217
|
|
|
178
|
-
def check_step(step, pos, prev, by_name)
|
|
218
|
+
def check_step(step, pos, prev, last_qualified, by_name)
|
|
179
219
|
found = by_name[step.name&.safe_downcase]
|
|
180
220
|
return [Issue.new(step: pos, message: "unknown type '#{step.name}'")] unless found
|
|
181
221
|
|
|
182
222
|
issues = attribute_issues(step, pos, found[1], by_name)
|
|
183
|
-
issues.concat(link_issues(step, pos, prev, by_name))
|
|
223
|
+
issues.concat(link_issues(step, pos, prev, last_qualified, by_name))
|
|
184
224
|
issues
|
|
185
225
|
end
|
|
186
226
|
|
|
@@ -239,7 +279,7 @@ module Expressir
|
|
|
239
279
|
"aggregate but carries [#{step.index}]")]
|
|
240
280
|
end
|
|
241
281
|
|
|
242
|
-
def link_issues(step, pos, prev, by_name)
|
|
282
|
+
def link_issues(step, pos, prev, last_qualified, by_name)
|
|
243
283
|
return [] unless LINKS.include?(step.operator)
|
|
244
284
|
unless prev && step.name
|
|
245
285
|
return [Issue.new(step: pos,
|
|
@@ -247,20 +287,39 @@ module Expressir
|
|
|
247
287
|
end
|
|
248
288
|
|
|
249
289
|
case step.operator
|
|
250
|
-
when "->", "<-"
|
|
290
|
+
when "->", "<-"
|
|
291
|
+
attribute_link_issues(step, pos, prev, last_qualified)
|
|
251
292
|
when "<=" then subtype_link_issues(step, pos, prev, by_name)
|
|
252
293
|
when "=>" then supertype_link_issues(step, pos, prev, by_name)
|
|
253
294
|
end
|
|
254
295
|
end
|
|
255
296
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
297
|
+
# `->`: the attribute-qualified node precedes the operator;
|
|
298
|
+
# `<-`: it follows (the entity before <- is referenced BY the
|
|
299
|
+
# attribute after it). An aggregate dereference `[i]` keeps the
|
|
300
|
+
# running attribute owner qualified for the next link
|
|
301
|
+
# (`attr -> list_type[i] -> element_type`).
|
|
302
|
+
def attribute_link_issues(step, pos, prev, last_qualified)
|
|
303
|
+
if step.operator == "->"
|
|
304
|
+
qualified = if prev&.attribute
|
|
305
|
+
prev
|
|
306
|
+
else
|
|
307
|
+
(prev&.index ? last_qualified : nil)
|
|
308
|
+
end
|
|
309
|
+
unless qualified&.attribute
|
|
310
|
+
return [Issue.new(step: pos,
|
|
311
|
+
message: "'->' requires an attribute-qualified " \
|
|
312
|
+
"node before it, got '#{prev&.name}'")]
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
return []
|
|
261
316
|
end
|
|
262
317
|
|
|
263
|
-
[]
|
|
318
|
+
return [] if step.attribute
|
|
319
|
+
|
|
320
|
+
[Issue.new(step: pos,
|
|
321
|
+
message: "'<-' requires an attribute-qualified node " \
|
|
322
|
+
"after it, got '#{step.name}'")]
|
|
264
323
|
end
|
|
265
324
|
|
|
266
325
|
# `a <= b`: a is a subtype of b.
|
data/lib/expressir/mapping.rb
CHANGED
|
@@ -136,8 +136,16 @@ module Expressir
|
|
|
136
136
|
def values(document)
|
|
137
137
|
document.ae.to_a.flat_map do |element|
|
|
138
138
|
[element.entity, element.aimelt] +
|
|
139
|
-
element.aa.to_a.flat_map
|
|
140
|
-
|
|
139
|
+
element.aa.to_a.flat_map do |aa|
|
|
140
|
+
[aa.attribute, aa.aimelt, aa.assertion_to]
|
|
141
|
+
end
|
|
142
|
+
end.compact + subtype_constraint_values(document)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Every declaration reference in the sc entries (#460): the
|
|
146
|
+
# constraint name and the entity it constrains.
|
|
147
|
+
def subtype_constraint_values(document)
|
|
148
|
+
document.sc.to_a.flat_map { |sc| [sc.constraint, sc.entity] }.compact
|
|
141
149
|
end
|
|
142
150
|
|
|
143
151
|
# Every reference path in the document as [location, content]
|
data/lib/expressir/version.rb
CHANGED