rosette-core 1.0.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.
- checksums.yaml +7 -0
- data/Gemfile +26 -0
- data/History.txt +3 -0
- data/README.md +94 -0
- data/Rakefile +18 -0
- data/lib/rosette/core.rb +110 -0
- data/lib/rosette/core/branch_utils.rb +152 -0
- data/lib/rosette/core/commands.rb +139 -0
- data/lib/rosette/core/commands/errors.rb +17 -0
- data/lib/rosette/core/commands/git/commit_command.rb +65 -0
- data/lib/rosette/core/commands/git/diff_base_command.rb +301 -0
- data/lib/rosette/core/commands/git/diff_command.rb +188 -0
- data/lib/rosette/core/commands/git/diff_entry.rb +44 -0
- data/lib/rosette/core/commands/git/fetch_command.rb +27 -0
- data/lib/rosette/core/commands/git/repo_snapshot_command.rb +40 -0
- data/lib/rosette/core/commands/git/show_command.rb +70 -0
- data/lib/rosette/core/commands/git/snapshot_command.rb +50 -0
- data/lib/rosette/core/commands/git/status_command.rb +128 -0
- data/lib/rosette/core/commands/git/with_non_merge_ref.rb +48 -0
- data/lib/rosette/core/commands/git/with_ref.rb +92 -0
- data/lib/rosette/core/commands/git/with_refs.rb +92 -0
- data/lib/rosette/core/commands/git/with_repo_name.rb +50 -0
- data/lib/rosette/core/commands/git/with_snapshots.rb +45 -0
- data/lib/rosette/core/commands/queuing/enqueue_commit_command.rb +37 -0
- data/lib/rosette/core/commands/queuing/requeue_commit_command.rb +46 -0
- data/lib/rosette/core/commands/translations/export_command.rb +257 -0
- data/lib/rosette/core/commands/translations/translation_lookup_command.rb +66 -0
- data/lib/rosette/core/commands/translations/with_locale.rb +47 -0
- data/lib/rosette/core/configurator.rb +160 -0
- data/lib/rosette/core/error_reporters/buffered_error_reporter.rb +96 -0
- data/lib/rosette/core/error_reporters/error_reporter.rb +31 -0
- data/lib/rosette/core/error_reporters/nil_error_reporter.rb +25 -0
- data/lib/rosette/core/error_reporters/printing_error_reporter.rb +58 -0
- data/lib/rosette/core/error_reporters/raising_error_reporter.rb +27 -0
- data/lib/rosette/core/errors.rb +93 -0
- data/lib/rosette/core/extractor/commit_log.rb +33 -0
- data/lib/rosette/core/extractor/commit_log_status.rb +57 -0
- data/lib/rosette/core/extractor/commit_processor.rb +109 -0
- data/lib/rosette/core/extractor/extractor.rb +72 -0
- data/lib/rosette/core/extractor/extractor_config.rb +74 -0
- data/lib/rosette/core/extractor/locale.rb +118 -0
- data/lib/rosette/core/extractor/phrase.rb +76 -0
- data/lib/rosette/core/extractor/phrase/phrase_index_policy.rb +108 -0
- data/lib/rosette/core/extractor/phrase/phrase_to_hash.rb +33 -0
- data/lib/rosette/core/extractor/repo_config.rb +339 -0
- data/lib/rosette/core/extractor/serializer_config.rb +55 -0
- data/lib/rosette/core/extractor/static_extractor.rb +44 -0
- data/lib/rosette/core/extractor/translation.rb +44 -0
- data/lib/rosette/core/extractor/translation/translation_to_hash.rb +28 -0
- data/lib/rosette/core/git/diff_finder.rb +131 -0
- data/lib/rosette/core/git/ref.rb +116 -0
- data/lib/rosette/core/git/repo.rb +378 -0
- data/lib/rosette/core/path_matcher_factory.rb +330 -0
- data/lib/rosette/core/resolvers/extractor_id.rb +37 -0
- data/lib/rosette/core/resolvers/integration_id.rb +37 -0
- data/lib/rosette/core/resolvers/preprocessor_id.rb +38 -0
- data/lib/rosette/core/resolvers/resolver.rb +115 -0
- data/lib/rosette/core/resolvers/serializer_id.rb +37 -0
- data/lib/rosette/core/snapshots/cached_head_snapshot_factory.rb +51 -0
- data/lib/rosette/core/snapshots/cached_snapshot_factory.rb +67 -0
- data/lib/rosette/core/snapshots/head_snapshot_factory.rb +58 -0
- data/lib/rosette/core/snapshots/repo_config_path_filter.rb +83 -0
- data/lib/rosette/core/snapshots/snapshot_factory.rb +184 -0
- data/lib/rosette/core/string_utils.rb +23 -0
- data/lib/rosette/core/translation_status.rb +81 -0
- data/lib/rosette/core/validators.rb +18 -0
- data/lib/rosette/core/validators/commit_validator.rb +62 -0
- data/lib/rosette/core/validators/commits_validator.rb +32 -0
- data/lib/rosette/core/validators/encoding_validator.rb +32 -0
- data/lib/rosette/core/validators/locale_validator.rb +37 -0
- data/lib/rosette/core/validators/repo_validator.rb +33 -0
- data/lib/rosette/core/validators/serializer_validator.rb +37 -0
- data/lib/rosette/core/validators/validator.rb +31 -0
- data/lib/rosette/core/version.rb +8 -0
- data/lib/rosette/data_stores.rb +11 -0
- data/lib/rosette/data_stores/errors.rb +26 -0
- data/lib/rosette/data_stores/phrase_status.rb +59 -0
- data/lib/rosette/integrations.rb +12 -0
- data/lib/rosette/integrations/errors.rb +15 -0
- data/lib/rosette/integrations/integratable.rb +58 -0
- data/lib/rosette/integrations/integration.rb +23 -0
- data/lib/rosette/preprocessors.rb +11 -0
- data/lib/rosette/preprocessors/errors.rb +14 -0
- data/lib/rosette/preprocessors/preprocessor.rb +48 -0
- data/lib/rosette/queuing.rb +14 -0
- data/lib/rosette/queuing/commits.rb +19 -0
- data/lib/rosette/queuing/commits/commit_conductor.rb +90 -0
- data/lib/rosette/queuing/commits/commit_job.rb +93 -0
- data/lib/rosette/queuing/commits/commits_queue_configurator.rb +60 -0
- data/lib/rosette/queuing/commits/extract_stage.rb +46 -0
- data/lib/rosette/queuing/commits/fetch_stage.rb +51 -0
- data/lib/rosette/queuing/commits/finalize_stage.rb +76 -0
- data/lib/rosette/queuing/commits/phrase_storage_granularity.rb +20 -0
- data/lib/rosette/queuing/commits/push_stage.rb +91 -0
- data/lib/rosette/queuing/commits/stage.rb +96 -0
- data/lib/rosette/queuing/job.rb +74 -0
- data/lib/rosette/queuing/queue.rb +28 -0
- data/lib/rosette/queuing/queue_configurator.rb +76 -0
- data/lib/rosette/queuing/worker.rb +30 -0
- data/lib/rosette/serializers.rb +10 -0
- data/lib/rosette/serializers/serializer.rb +98 -0
- data/lib/rosette/tms.rb +9 -0
- data/lib/rosette/tms/repository.rb +95 -0
- data/rosette-core.gemspec +24 -0
- data/spec/core/branch_utils_spec.rb +110 -0
- data/spec/core/commands/git/commit_command_spec.rb +60 -0
- data/spec/core/commands/git/diff_command_spec.rb +263 -0
- data/spec/core/commands/git/fetch_command_spec.rb +61 -0
- data/spec/core/commands/git/repo_snapshot_command_spec.rb +72 -0
- data/spec/core/commands/git/show_command_spec.rb +128 -0
- data/spec/core/commands/git/snapshot_command_spec.rb +86 -0
- data/spec/core/commands/git/status_command_spec.rb +154 -0
- data/spec/core/commands/queuing/enqueue_commit_command_spec.rb +34 -0
- data/spec/core/commands/queuing/requeue_commit_command_spec.rb +46 -0
- data/spec/core/commands/translations/export_command_spec.rb +113 -0
- data/spec/core/commands/translations/translation_lookup_command_spec.rb +58 -0
- data/spec/core/configurator_spec.rb +47 -0
- data/spec/core/error_reporters/buffered_error_reporter_spec.rb +61 -0
- data/spec/core/error_reporters/nil_error_reporter_spec.rb +16 -0
- data/spec/core/error_reporters/printing_error_reporter_spec.rb +60 -0
- data/spec/core/extractor/commit_log_status_spec.rb +216 -0
- data/spec/core/extractor/commit_processor_spec.rb +68 -0
- data/spec/core/extractor/extractor_config_spec.rb +47 -0
- data/spec/core/extractor/extractor_spec.rb +26 -0
- data/spec/core/extractor/locale_spec.rb +92 -0
- data/spec/core/extractor/phrase/phrase_index_policy_spec.rb +116 -0
- data/spec/core/extractor/phrase/phrase_to_hash_spec.rb +18 -0
- data/spec/core/extractor/repo_config_spec.rb +147 -0
- data/spec/core/extractor/translation/translation_to_hash_spec.rb +25 -0
- data/spec/core/git/diff_finder_spec.rb +74 -0
- data/spec/core/git/ref_spec.rb +118 -0
- data/spec/core/git/repo_spec.rb +216 -0
- data/spec/core/path_matcher_factory_spec.rb +139 -0
- data/spec/core/resolvers/extractor_id_spec.rb +47 -0
- data/spec/core/resolvers/integration_id_spec.rb +47 -0
- data/spec/core/resolvers/preprocessor_id_spec.rb +47 -0
- data/spec/core/resolvers/serializer_id_spec.rb +47 -0
- data/spec/core/snapshots/snapshot_factory_spec.rb +145 -0
- data/spec/core/string_utils_spec.rb +19 -0
- data/spec/core/translation_status_spec.rb +91 -0
- data/spec/core/validators/commit_validator_spec.rb +40 -0
- data/spec/core/validators/encoding_validator_spec.rb +30 -0
- data/spec/core/validators/locale_validator_spec.rb +31 -0
- data/spec/core/validators/repo_validator_spec.rb +30 -0
- data/spec/core/validators/serializer_validator_spec.rb +31 -0
- data/spec/integrations/integratable_spec.rb +58 -0
- data/spec/queuing/commits/commit_conductor_spec.rb +71 -0
- data/spec/queuing/commits/commit_job_spec.rb +87 -0
- data/spec/queuing/commits/extract_stage_spec.rb +68 -0
- data/spec/queuing/commits/fetch_stage_spec.rb +101 -0
- data/spec/queuing/commits/finalize_stage_spec.rb +88 -0
- data/spec/queuing/commits/push_stage_spec.rb +145 -0
- data/spec/queuing/commits/stage_spec.rb +80 -0
- data/spec/queuing/job_spec.rb +33 -0
- data/spec/queuing/queue_configurator_spec.rb +44 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/test_helpers/fake_commit_stage.rb +17 -0
- metadata +257 -0
@@ -0,0 +1,330 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
# Constructs condition trees for path matchers.
|
6
|
+
#
|
7
|
+
# @see ExtractorConfig
|
8
|
+
class PathMatcherFactory
|
9
|
+
# Creates a new empty node that can be used as the root of a
|
10
|
+
# conditions tree.
|
11
|
+
#
|
12
|
+
# @return [Node] the new empty node
|
13
|
+
def self.create_root
|
14
|
+
Node.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# Facilitates creating operator nodes that can perform binary
|
18
|
+
# operations, like "and", "or", and "not".
|
19
|
+
module NodeOperatorFactory
|
20
|
+
# Creates an {OrNode} for combining two nodes together with a
|
21
|
+
# logical "or".
|
22
|
+
#
|
23
|
+
# @param [Node] right The other node. The left node is +self+.
|
24
|
+
# @return [OrNode] a node representing the logical "or" of +self+
|
25
|
+
# and +right+.
|
26
|
+
def or(right)
|
27
|
+
OrNode.new(self, right)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates an {AndNode} for combining two nodes together with a
|
31
|
+
# logical "and".
|
32
|
+
#
|
33
|
+
# @param [Node] right The other node. The left node is +self+.
|
34
|
+
# @return [AndNode] a node representing the logical "and" of +self+
|
35
|
+
# and +right+.
|
36
|
+
def and(right)
|
37
|
+
AndNode.new(self, right)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Creates a {NotNode} for negating +self+.
|
41
|
+
#
|
42
|
+
# @return [NotNode] a node representing the negation of +self+.
|
43
|
+
def not
|
44
|
+
NotNode.new(self)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Provides common methods for creating nodes.
|
49
|
+
module NodeFactory
|
50
|
+
# Creates a {FileExtensionNode}.
|
51
|
+
#
|
52
|
+
# @param [String] extension The file extension to match.
|
53
|
+
# @return [FileExtensionNode]
|
54
|
+
def match_file_extension(extension)
|
55
|
+
FileExtensionNode.new(extension)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Creates a bunch of {FileExtensionNode}s combined using a logical "or".
|
59
|
+
#
|
60
|
+
# @param [Array<String>] extensions A list of file extensions.
|
61
|
+
# @return [FileExtensionNode, OrNode] the root node of a tree of all
|
62
|
+
# the file extensions specified in +extensions+. Each file extension
|
63
|
+
# will be wrapped in a {FileExtensionNode} and logically "or"ed
|
64
|
+
# together. If +extensions+ only contains one file extension, then this
|
65
|
+
# method just returns an instance of {FileExtensionNode}. If +extensions+
|
66
|
+
# contains more than one entry, this method returns an {OrNode}.
|
67
|
+
def match_file_extensions(extensions)
|
68
|
+
Array(extensions).inject(nil) do |node, extension|
|
69
|
+
new_node = match_file_extension(extension)
|
70
|
+
node ? node.or(new_node) : new_node
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Creates a {PathNode}.
|
75
|
+
#
|
76
|
+
# @param [String] path The path to match.
|
77
|
+
# @return [PathNode]
|
78
|
+
def match_path(path)
|
79
|
+
PathNode.new(path)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Creates a bunch of {PathNode}s combined using a logical "or".
|
83
|
+
#
|
84
|
+
# @param [Array<String>] paths A list of paths.
|
85
|
+
# @return [PathNode, OrNode] the root of a tree of all the paths specified
|
86
|
+
# in +paths+. Each path will be wrapped in a {PathNode} and logically
|
87
|
+
# "or"ed together. If +paths+ only contains one path, then this method
|
88
|
+
# just returns an instance of {PathNode}. If +paths+ contains more than
|
89
|
+
# one entry, this method returns an {OrNode}.
|
90
|
+
def match_paths(paths)
|
91
|
+
Array(paths).inject(nil) do |node, path|
|
92
|
+
new_node = match_path(path)
|
93
|
+
node ? node.or(new_node) : new_node
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Creates a {RegexNode}.
|
98
|
+
#
|
99
|
+
# @param [Regexp] regex The regex to match.
|
100
|
+
# @return [RegexNode]
|
101
|
+
def match_regex(regex)
|
102
|
+
RegexNode.new(regex)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Creates a bunch of {RegexNode}s combined using a logical "or".
|
106
|
+
#
|
107
|
+
# @param [Array<Regexp>] regexes A list of regular expressions.
|
108
|
+
# @return [RegexNode, OrNode] the root of a tree of all the regexes specified
|
109
|
+
# in +regexes+. Each regex will be wrapped in a {RegexNode} and logically
|
110
|
+
# "or"ed together. If +regexes+ only contains one entry, then this method
|
111
|
+
# just returns an instance of {RegexNode}. If +regexes+ contains more than
|
112
|
+
# one entry, this method returns an {OrNode}.
|
113
|
+
def match_regexes(regexes)
|
114
|
+
Array(regexes).inject(nil) do |node, regex|
|
115
|
+
new_node = match_regex(regex)
|
116
|
+
node ? node.or(new_node) : new_node
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
include NodeFactory
|
122
|
+
|
123
|
+
# The base class for all condition nodes.
|
124
|
+
class Node
|
125
|
+
include NodeFactory
|
126
|
+
include NodeOperatorFactory
|
127
|
+
|
128
|
+
# Determines if the given path matches the conditions defined by this node
|
129
|
+
# and it's children.
|
130
|
+
#
|
131
|
+
# @param [String] path The path to match.
|
132
|
+
# @return [Boolean] true if +path+ matches, false otherwise.
|
133
|
+
def matches?(path)
|
134
|
+
false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# The base class for all nodes that perform binary operations (i.e.
|
139
|
+
# operations that take two operands).
|
140
|
+
#
|
141
|
+
# @!attribute [r] left
|
142
|
+
# @return [Node] the left child.
|
143
|
+
# @!attribute [r] right
|
144
|
+
# @return [Node] the right child.
|
145
|
+
class BinaryNode < Node
|
146
|
+
attr_reader :left, :right
|
147
|
+
|
148
|
+
# Creates a new binary node with left and right children.
|
149
|
+
#
|
150
|
+
# @param [Node] left The left child.
|
151
|
+
# @param [Node] right The right child.
|
152
|
+
def initialize(left, right)
|
153
|
+
@left = left
|
154
|
+
@right = right
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# The base class for all nodes that perform unary operations (i.e.
|
159
|
+
# operations that take only one operand).
|
160
|
+
#
|
161
|
+
# @!attribute [r] child
|
162
|
+
# @return [Node] the child node.
|
163
|
+
class UnaryNode < Node
|
164
|
+
attr_reader :child
|
165
|
+
|
166
|
+
# Creates a new unary node.
|
167
|
+
#
|
168
|
+
# @param [Node] child The child.
|
169
|
+
def initialize(child)
|
170
|
+
@child = child
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# A logical "and".
|
175
|
+
class AndNode < BinaryNode
|
176
|
+
# Determines if the given path matches the left AND the right child's
|
177
|
+
# conditions.
|
178
|
+
#
|
179
|
+
# @param [String] path The path to match.
|
180
|
+
# @return [Boolean] true if both the left and right children match
|
181
|
+
# +path+, false otherwise.
|
182
|
+
def matches?(path)
|
183
|
+
left.matches?(path) && right.matches?(path)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Generates a string representation of this node.
|
187
|
+
#
|
188
|
+
# @return [String]
|
189
|
+
def to_s
|
190
|
+
"(#{left.to_s} AND #{right.to_s})"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# A logical "OR".
|
195
|
+
class OrNode < BinaryNode
|
196
|
+
# Determines if the given path matches the left OR the right child's
|
197
|
+
# conditions.
|
198
|
+
#
|
199
|
+
# @param [String] path The path to match.
|
200
|
+
# @return [Boolean] true if the left or the right child matches +path+,
|
201
|
+
# false otherwise.
|
202
|
+
def matches?(path)
|
203
|
+
left.matches?(path) || right.matches?(path)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Generates a string representation of this node.
|
207
|
+
#
|
208
|
+
# @return [String]
|
209
|
+
def to_s
|
210
|
+
"(#{left.to_s} OR #{right.to_s})"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# A logical "NOT".
|
215
|
+
class NotNode < UnaryNode
|
216
|
+
# Determines if the given path does NOT match the child's conditions.
|
217
|
+
#
|
218
|
+
# @param [String] path The path to match.
|
219
|
+
# @return [Boolean] true if the child does not match +path+, false
|
220
|
+
# otherwise.
|
221
|
+
def matches?(path)
|
222
|
+
!child.matches?(path)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Generates a string representation of this node.
|
226
|
+
#
|
227
|
+
# @return [String]
|
228
|
+
def to_s
|
229
|
+
"(NOT #{child.to_s})"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Matches file extensions.
|
234
|
+
#
|
235
|
+
# @!attribute [r] extension
|
236
|
+
# @return [String] the extension to match.
|
237
|
+
class FileExtensionNode < Node
|
238
|
+
attr_reader :extension
|
239
|
+
|
240
|
+
# Creates a new file extension node.
|
241
|
+
#
|
242
|
+
# @param [String] extension The extension to match.
|
243
|
+
def initialize(extension)
|
244
|
+
@extension = extension
|
245
|
+
end
|
246
|
+
|
247
|
+
# Determines if the given path's file extension matches +extension+.
|
248
|
+
#
|
249
|
+
# @param [String] path The path to match.
|
250
|
+
# @return [Boolean] true if the path matches +extension+, false otherwise.
|
251
|
+
def matches?(path)
|
252
|
+
# avoid using File.extname to allow matching against double extensions,
|
253
|
+
# eg. file.html.erb
|
254
|
+
path[-extension.size..-1] == extension
|
255
|
+
end
|
256
|
+
|
257
|
+
# Generates a string representation of this node.
|
258
|
+
#
|
259
|
+
# @return [String]
|
260
|
+
def to_s
|
261
|
+
"has_file_extension('#{extension}')"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# Matches paths.
|
266
|
+
#
|
267
|
+
# @!attribute [r] path
|
268
|
+
# @return [String] the path to match.
|
269
|
+
class PathNode < Node
|
270
|
+
attr_reader :path
|
271
|
+
|
272
|
+
# Creates a new path node.
|
273
|
+
#
|
274
|
+
# @param [String] path The path to match.
|
275
|
+
def initialize(path)
|
276
|
+
@path = path
|
277
|
+
end
|
278
|
+
|
279
|
+
# Determines if the given path matches +path+.
|
280
|
+
#
|
281
|
+
# @param [String] match_path The path to match.
|
282
|
+
# @return [Boolean] true if +match_path+ matches +path+, false otherwise.
|
283
|
+
# Matching is done by comparing the first +n+ characters of +match_path+
|
284
|
+
# to +path+, where +n+ is the number of characters in +path+. In other words,
|
285
|
+
# if +path+ is "/path/to" and +match_path+ is '/path/to/foo.rb', this method
|
286
|
+
# will return true.
|
287
|
+
def matches?(match_path)
|
288
|
+
match_path[0...path.size] == path
|
289
|
+
end
|
290
|
+
|
291
|
+
# Generates a string representation of this node.
|
292
|
+
#
|
293
|
+
# @return [String]
|
294
|
+
def to_s
|
295
|
+
"matches_path('#{path}')"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# Determines if the given path matches +regex+.
|
300
|
+
#
|
301
|
+
# @!attribute [r] regex
|
302
|
+
# @return [Regex] The regex to match with.
|
303
|
+
class RegexNode < Node
|
304
|
+
attr_reader :regex
|
305
|
+
|
306
|
+
# Creates a new regex node.
|
307
|
+
#
|
308
|
+
# @param [Regex] regex The regex to match with.
|
309
|
+
def initialize(regex)
|
310
|
+
@regex = regex
|
311
|
+
end
|
312
|
+
|
313
|
+
# Determines if +regex+ matches the given path.
|
314
|
+
#
|
315
|
+
# @param [String] path The path to match.
|
316
|
+
# @return [Boolean] true if +regex+ matches +path+, false otherwise.
|
317
|
+
def matches?(path)
|
318
|
+
!!(path =~ regex)
|
319
|
+
end
|
320
|
+
|
321
|
+
# Generates a string representation of this node.
|
322
|
+
#
|
323
|
+
# @return [String]
|
324
|
+
def to_s
|
325
|
+
"matches_regex(/#{regex.source}/)"
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Logic for handling extractor ids. Extractor ids are strings that refer to
|
7
|
+
# a particular extractor class. For example, the id 'yaml/rails' refers to
|
8
|
+
# +Rosette::Extractors::YamlExtractor::RailsExtractor+.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# ExtractorId.resolve('yaml/rails')
|
12
|
+
# # => Rosette::Extractors::YamlExtractor::RailsExtractor
|
13
|
+
class ExtractorId < Resolver
|
14
|
+
class << self
|
15
|
+
|
16
|
+
# Parses and identifies the class constant for the given extractor id.
|
17
|
+
#
|
18
|
+
# @param [Class, String] extractor_id When given a class, returns the
|
19
|
+
# class. When given a string, parses and identifies the corresponding
|
20
|
+
# class constant in +namespace+.
|
21
|
+
# @param [Class] namespace The namespace to look in.
|
22
|
+
# @return [Class] The identified class constant.
|
23
|
+
def resolve(extractor_id, namespace = Rosette::Extractors)
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def suffix
|
30
|
+
'Extractor'
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Logic for handling integration ids. Integration ids are strings that refer
|
7
|
+
# to a particular integration class. For example, the id 'smartling' refers
|
8
|
+
# to +Rosette::Integrations::SmartlingIntegration+.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# IntegrationId.resolve('smartling')
|
12
|
+
# # => Rosette::Integrations::SmartlingIntegration
|
13
|
+
class IntegrationId < Resolver
|
14
|
+
class << self
|
15
|
+
|
16
|
+
# Parses and identifies the class constant for the given integration id.
|
17
|
+
#
|
18
|
+
# @param [Class, String] integration_id When given a class, returns the
|
19
|
+
# class. When given a string, parses and identifies the corresponding
|
20
|
+
# class constant in +namespace+.
|
21
|
+
# @param [Class] namespace The namespace to look in.
|
22
|
+
# @return [Class] The identified class constant.
|
23
|
+
def resolve(integration_id, namespace = Rosette::Integrations)
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def suffix
|
30
|
+
'Integration'
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Logic for handling preprocessor ids. Preprocessor ids are strings that
|
7
|
+
# refer to a particular preprocessor class. For example, the id
|
8
|
+
# 'normalization' refers to
|
9
|
+
# +Rosette::Preprocessors::NormalizationPreprocessor+.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# PreprocessorId.resolve('normalization')
|
13
|
+
# # => Rosette::Preprocessors::NormalizationPreprocessor
|
14
|
+
class PreprocessorId < Resolver
|
15
|
+
class << self
|
16
|
+
|
17
|
+
# Parses and identifies the class constant for the given preprocessor id.
|
18
|
+
#
|
19
|
+
# @param [Class, String] preprocessor_id When given a class, returns the
|
20
|
+
# class. When given a string, parses and identifies the corresponding
|
21
|
+
# class constant in +namespace+.
|
22
|
+
# @param [Class] namespace The namespace to look in.
|
23
|
+
# @return [Class] The identified class constant.
|
24
|
+
def resolve(preprocessor_id, namespace = Rosette::Preprocessors)
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def suffix
|
31
|
+
'Preprocessor'
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Rosette
|
4
|
+
module Core
|
5
|
+
|
6
|
+
# Base class for Rosette's id resolvers that can look up a class constant
|
7
|
+
# given a namespaced id (string separated by forward slashes). For example,
|
8
|
+
# the extractor id "yaml/rails" resolves to
|
9
|
+
# +Rosette::Extractors::YamlExtractor::RailsExtractor+.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# class MyResolver < Resolver
|
13
|
+
# def resolve(id, namespace = MyNamespace::Foo)
|
14
|
+
# super
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# private
|
18
|
+
#
|
19
|
+
# # Must be defined by classes that inherit from Resolver.
|
20
|
+
# def suffix
|
21
|
+
# 'Stuff'
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# module MyNamespace
|
26
|
+
# module Foo
|
27
|
+
# module BarStuff
|
28
|
+
# class BazStuff
|
29
|
+
# ...
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# MyResolver.resolve('bar/baz') # => MyNamespace::Foo::BarStuff::BazStuff
|
36
|
+
class Resolver
|
37
|
+
class << self
|
38
|
+
|
39
|
+
# Parses and identifies the class constant for the given id.
|
40
|
+
#
|
41
|
+
# @param [Class, String] id When given a class, returns the class. When
|
42
|
+
# given a string, parses and identifies the corresponding class
|
43
|
+
# constant in +namespace+.
|
44
|
+
# @param [Class] namespace The namespace to look in.
|
45
|
+
# @return [Class] The identified class constant.
|
46
|
+
def resolve(id, namespace)
|
47
|
+
klass = case id
|
48
|
+
when Class
|
49
|
+
id
|
50
|
+
when String
|
51
|
+
lookup(id, namespace)
|
52
|
+
end
|
53
|
+
|
54
|
+
unless klass
|
55
|
+
raise ArgumentError, "#{id} could not be found - have you required it?"
|
56
|
+
end
|
57
|
+
|
58
|
+
klass
|
59
|
+
end
|
60
|
+
|
61
|
+
# Splits an id into parts.
|
62
|
+
#
|
63
|
+
# @param [String] id The id to parse.
|
64
|
+
# @return [Array<String>] A list of id parts.
|
65
|
+
def parse_id(id)
|
66
|
+
id.split('/')
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def lookup(id, namespace)
|
72
|
+
find_const(
|
73
|
+
const_candidates(
|
74
|
+
parse_id(id).map do |segment|
|
75
|
+
StringUtils.camelize(segment)
|
76
|
+
end
|
77
|
+
), namespace
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Appends the suffix to each segment one at a time and returns intermediate
|
82
|
+
# arrays of segments. For example, if given ['Json', 'KeyValue'] and a suffix
|
83
|
+
# of 'Serializer', this method would return:
|
84
|
+
# [['Json', 'KeyValue'], ['Json', 'KeyValueSerializer'], ['JsonSerializer', 'KeyValueSerializer']]
|
85
|
+
def const_candidates(segments)
|
86
|
+
[segments] + segments.map.with_index do |segment, idx|
|
87
|
+
candidate = segments[0...(segments.size - (idx + 1))]
|
88
|
+
candidate + segments[(segments.size - (idx + 1))..-1].map do |sub_seg|
|
89
|
+
"#{sub_seg}#{suffix}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def suffix
|
95
|
+
raise NotImplementedError, "#{__method__} must be defined in derived classes"
|
96
|
+
end
|
97
|
+
|
98
|
+
def find_const(candidates, namespace)
|
99
|
+
candidates.each do |segments|
|
100
|
+
found_const = segments.inject(namespace) do |const, segment|
|
101
|
+
if const && const.const_defined?(segment)
|
102
|
+
const.const_get(segment)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
return found_const if found_const
|
107
|
+
end
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|