expressir 2.4.16 → 2.4.17
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/express/lazy_repository.rb +211 -0
- data/lib/expressir/express.rb +1 -0
- data/lib/expressir/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6fb8953f2f2e9d76be3693148c8951ae36f562bbaf8214a8bc510b68888700d2
|
|
4
|
+
data.tar.gz: dfbcc336cc1a580501ca69632d6e6bb348e196be470cbc712a637131ffe1993c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e5259fb143ac5419ab85b8a97e8ab50a3a809826f799b8cd74242a673599c5cac0bd21cfe1dc33af562c16a806afc95f9f43f75f8eba43e18b68377104d5406
|
|
7
|
+
data.tar.gz: 0d2520a7a817f1c8d72a6f768887e803c91a6070f3cf8d4230bde9e66dcb6a1580ff7ee39ac6e9c886106cde64db14e175db57e81be0b798ea8f45af57bfaaa7
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "liquid"
|
|
4
|
+
|
|
5
|
+
module Expressir
|
|
6
|
+
module Express
|
|
7
|
+
# Lazy read path over a compiled-set artifact (M2 slice 2,
|
|
8
|
+
# TODO.parity-ee/19): schemas hydrate individually, on first touch,
|
|
9
|
+
# instead of the whole repository at once. Metanorma schema-doc
|
|
10
|
+
# rendering touches one schema per page — the lazy repository makes
|
|
11
|
+
# that pay: one hydration per page, not one per schema in the set.
|
|
12
|
+
#
|
|
13
|
+
# Duck-types the read surface of Model::Repository used by
|
|
14
|
+
# rendering (schemas, files, each, size, children). Anything beyond
|
|
15
|
+
# the read surface should wait for eager hydration via
|
|
16
|
+
# #to_eager (returns a real Model::Repository).
|
|
17
|
+
class LazyRepository
|
|
18
|
+
attr_reader :set_path
|
|
19
|
+
|
|
20
|
+
# @param set_path [String] compiled-set artifact path
|
|
21
|
+
# @param read_paths [Hash{String => String}] wire path => source path
|
|
22
|
+
def initialize(set_path, read_paths = {})
|
|
23
|
+
@set_path = set_path
|
|
24
|
+
@set = Core.lazy_set(set_path)
|
|
25
|
+
@read_paths = read_paths
|
|
26
|
+
@wire_paths = @set.wire_paths
|
|
27
|
+
@mutex = Mutex.new
|
|
28
|
+
@file_cache = {}
|
|
29
|
+
@hydration_count = 0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Wire paths in artifact order — no hydration.
|
|
33
|
+
# @return [Array<String>]
|
|
34
|
+
def wire_paths
|
|
35
|
+
@wire_paths.dup
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Files in artifact order, each wrapped so it hydrates on first
|
|
39
|
+
# use. The file is the hydration grain: an artifact stores wire
|
|
40
|
+
# JSON per source file.
|
|
41
|
+
# @return [Array<LazyFile>]
|
|
42
|
+
def files
|
|
43
|
+
@wire_paths.map { |wire_path| file_by_wire_path(wire_path) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Hydrated (or hydrating) file for one wire path.
|
|
47
|
+
def file_by_wire_path(wire_path)
|
|
48
|
+
@mutex.synchronize do
|
|
49
|
+
@file_cache[wire_path] ||= LazyFile.new(wire_path) do
|
|
50
|
+
hydrate(wire_path)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Schemas across all files. EAGER by definition: it hydrates
|
|
56
|
+
# every file. Lazy callers iterate #files, or render through
|
|
57
|
+
# #to_liquid, which keeps per-file hydration lazy.
|
|
58
|
+
# @return [Array<Declarations::Schema>]
|
|
59
|
+
def schemas
|
|
60
|
+
files.map(&:__target__).flat_map(&:schemas).compact
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Liquid binding for metanorma (M2): returns a Drop whose
|
|
64
|
+
# `schemas` is a lazy per-file list — each entry hydrates only
|
|
65
|
+
# its own file when the template touches it. Schema count per
|
|
66
|
+
# file is unknown until hydration, so the Drop presents one
|
|
67
|
+
# entry per FILE; single-schema files (the corpus norm) render
|
|
68
|
+
# identically to the eager path.
|
|
69
|
+
def to_liquid
|
|
70
|
+
LazyRepositoryDrop.new(self)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# How many files have actually been hydrated (observability for
|
|
74
|
+
# the laziness contract).
|
|
75
|
+
def hydration_count
|
|
76
|
+
@hydration_count
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Hydrate everything and return a real Model::Repository — the
|
|
80
|
+
# escape hatch for callers needing the full read surface.
|
|
81
|
+
def to_eager
|
|
82
|
+
repo = Model::Repository.new
|
|
83
|
+
repo.files = files.map(&:__target__)
|
|
84
|
+
repo
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def each(&)
|
|
88
|
+
files.each(&)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def size
|
|
92
|
+
@wire_paths.size
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def children
|
|
96
|
+
schemas
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# The read path on disk for a wire path (may be nil when the
|
|
100
|
+
# caller did not supply source paths).
|
|
101
|
+
def read_path_for(wire_path)
|
|
102
|
+
@read_paths[wire_path]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def matches_sources?
|
|
106
|
+
@set.matches_sources(@read_paths.dup) == true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
def hydrate(wire_path)
|
|
112
|
+
@mutex.synchronize do
|
|
113
|
+
_wire, model = @set.hydrate_one(wire_path)
|
|
114
|
+
@hydration_count += 1
|
|
115
|
+
model
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Liquid::Drop over a LazyRepository: `schemas` enumerates lazy
|
|
121
|
+
# per-file entries; touching an entry hydrates that file and
|
|
122
|
+
# presents its schemas (single-schema files present the schema
|
|
123
|
+
# itself, matching the eager Drop's element contract).
|
|
124
|
+
class LazyRepositoryDrop < ::Liquid::Drop
|
|
125
|
+
def initialize(repo)
|
|
126
|
+
@repo = repo
|
|
127
|
+
super()
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def schemas
|
|
131
|
+
@repo.files.map do |file|
|
|
132
|
+
LazyFileDrop.new(file)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def size
|
|
137
|
+
@repo.size
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Per-file lazy drop: hydrates on first access, then presents the
|
|
142
|
+
# file's single schema directly (or the schema list for
|
|
143
|
+
# multi-schema files).
|
|
144
|
+
class LazyFileDrop < ::Liquid::Drop
|
|
145
|
+
def initialize(file)
|
|
146
|
+
@file = file
|
|
147
|
+
super()
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def __file__
|
|
151
|
+
@file.__target__
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def method_missing(name, *, &)
|
|
155
|
+
schemas = __file__.schemas
|
|
156
|
+
if schemas.size == 1
|
|
157
|
+
schemas.first.public_send(name, *, &)
|
|
158
|
+
else
|
|
159
|
+
__file__.public_send(name, *, &)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def respond_to_missing?(name, include_private = false)
|
|
164
|
+
__file__.respond_to?(name, include_private) ||
|
|
165
|
+
__file__.schemas.first.respond_to?(name, include_private)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Stands in for a Model::ExpFile until first method access, then
|
|
170
|
+
# hydrates through the block and forwards everything.
|
|
171
|
+
class LazyFile
|
|
172
|
+
def initialize(wire_path, &hydrator)
|
|
173
|
+
@wire_path = wire_path
|
|
174
|
+
@hydrator = hydrator
|
|
175
|
+
@mutex = Mutex.new
|
|
176
|
+
@target = nil
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
attr_reader :wire_path
|
|
180
|
+
|
|
181
|
+
# The real Schema, hydrating on first call.
|
|
182
|
+
def __target__
|
|
183
|
+
@mutex.synchronize do
|
|
184
|
+
@__target__ ||= @hydrator.call
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def method_missing(name, *, &)
|
|
189
|
+
__target__.public_send(name, *, &)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def respond_to_missing?(name, include_private = false)
|
|
193
|
+
__target__.respond_to?(name, include_private)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Identity through the wrapper: rendering compares and groups by
|
|
197
|
+
# class/is_a?, which the real file answers.
|
|
198
|
+
def is_a?(klass)
|
|
199
|
+
super || __target__.is_a?(klass)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def instance_of?(klass)
|
|
203
|
+
__target__.instance_of?(klass)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def class
|
|
207
|
+
__target__.class
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
data/lib/expressir/express.rb
CHANGED
|
@@ -44,6 +44,7 @@ module Expressir
|
|
|
44
44
|
"#{__dir__}/express/schema_plain_source_formatter"
|
|
45
45
|
autoload :SchemaSourceFormatter, "#{__dir__}/express/schema_source_formatter"
|
|
46
46
|
autoload :ScopeResolver, "#{__dir__}/express/scope_resolver"
|
|
47
|
+
autoload :LazyRepository, "#{__dir__}/express/lazy_repository"
|
|
47
48
|
autoload :SmrlXml, "#{__dir__}/express/smrl_xml"
|
|
48
49
|
autoload :Xsd, "#{__dir__}/express/xsd"
|
|
49
50
|
autoload :SourceFormatter, "#{__dir__}/express/source_formatter"
|
data/lib/expressir/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: expressir
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.4.
|
|
4
|
+
version: 2.4.17
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -506,6 +506,7 @@ files:
|
|
|
506
506
|
- lib/expressir/express/grammar/parser.rb
|
|
507
507
|
- lib/expressir/express/hyperlink_formatter.rb
|
|
508
508
|
- lib/expressir/express/interface_dot.rb
|
|
509
|
+
- lib/expressir/express/lazy_repository.rb
|
|
509
510
|
- lib/expressir/express/line_map.rb
|
|
510
511
|
- lib/expressir/express/listing.rb
|
|
511
512
|
- lib/expressir/express/model_traversal.rb
|