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.
Files changed (158) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +26 -0
  3. data/History.txt +3 -0
  4. data/README.md +94 -0
  5. data/Rakefile +18 -0
  6. data/lib/rosette/core.rb +110 -0
  7. data/lib/rosette/core/branch_utils.rb +152 -0
  8. data/lib/rosette/core/commands.rb +139 -0
  9. data/lib/rosette/core/commands/errors.rb +17 -0
  10. data/lib/rosette/core/commands/git/commit_command.rb +65 -0
  11. data/lib/rosette/core/commands/git/diff_base_command.rb +301 -0
  12. data/lib/rosette/core/commands/git/diff_command.rb +188 -0
  13. data/lib/rosette/core/commands/git/diff_entry.rb +44 -0
  14. data/lib/rosette/core/commands/git/fetch_command.rb +27 -0
  15. data/lib/rosette/core/commands/git/repo_snapshot_command.rb +40 -0
  16. data/lib/rosette/core/commands/git/show_command.rb +70 -0
  17. data/lib/rosette/core/commands/git/snapshot_command.rb +50 -0
  18. data/lib/rosette/core/commands/git/status_command.rb +128 -0
  19. data/lib/rosette/core/commands/git/with_non_merge_ref.rb +48 -0
  20. data/lib/rosette/core/commands/git/with_ref.rb +92 -0
  21. data/lib/rosette/core/commands/git/with_refs.rb +92 -0
  22. data/lib/rosette/core/commands/git/with_repo_name.rb +50 -0
  23. data/lib/rosette/core/commands/git/with_snapshots.rb +45 -0
  24. data/lib/rosette/core/commands/queuing/enqueue_commit_command.rb +37 -0
  25. data/lib/rosette/core/commands/queuing/requeue_commit_command.rb +46 -0
  26. data/lib/rosette/core/commands/translations/export_command.rb +257 -0
  27. data/lib/rosette/core/commands/translations/translation_lookup_command.rb +66 -0
  28. data/lib/rosette/core/commands/translations/with_locale.rb +47 -0
  29. data/lib/rosette/core/configurator.rb +160 -0
  30. data/lib/rosette/core/error_reporters/buffered_error_reporter.rb +96 -0
  31. data/lib/rosette/core/error_reporters/error_reporter.rb +31 -0
  32. data/lib/rosette/core/error_reporters/nil_error_reporter.rb +25 -0
  33. data/lib/rosette/core/error_reporters/printing_error_reporter.rb +58 -0
  34. data/lib/rosette/core/error_reporters/raising_error_reporter.rb +27 -0
  35. data/lib/rosette/core/errors.rb +93 -0
  36. data/lib/rosette/core/extractor/commit_log.rb +33 -0
  37. data/lib/rosette/core/extractor/commit_log_status.rb +57 -0
  38. data/lib/rosette/core/extractor/commit_processor.rb +109 -0
  39. data/lib/rosette/core/extractor/extractor.rb +72 -0
  40. data/lib/rosette/core/extractor/extractor_config.rb +74 -0
  41. data/lib/rosette/core/extractor/locale.rb +118 -0
  42. data/lib/rosette/core/extractor/phrase.rb +76 -0
  43. data/lib/rosette/core/extractor/phrase/phrase_index_policy.rb +108 -0
  44. data/lib/rosette/core/extractor/phrase/phrase_to_hash.rb +33 -0
  45. data/lib/rosette/core/extractor/repo_config.rb +339 -0
  46. data/lib/rosette/core/extractor/serializer_config.rb +55 -0
  47. data/lib/rosette/core/extractor/static_extractor.rb +44 -0
  48. data/lib/rosette/core/extractor/translation.rb +44 -0
  49. data/lib/rosette/core/extractor/translation/translation_to_hash.rb +28 -0
  50. data/lib/rosette/core/git/diff_finder.rb +131 -0
  51. data/lib/rosette/core/git/ref.rb +116 -0
  52. data/lib/rosette/core/git/repo.rb +378 -0
  53. data/lib/rosette/core/path_matcher_factory.rb +330 -0
  54. data/lib/rosette/core/resolvers/extractor_id.rb +37 -0
  55. data/lib/rosette/core/resolvers/integration_id.rb +37 -0
  56. data/lib/rosette/core/resolvers/preprocessor_id.rb +38 -0
  57. data/lib/rosette/core/resolvers/resolver.rb +115 -0
  58. data/lib/rosette/core/resolvers/serializer_id.rb +37 -0
  59. data/lib/rosette/core/snapshots/cached_head_snapshot_factory.rb +51 -0
  60. data/lib/rosette/core/snapshots/cached_snapshot_factory.rb +67 -0
  61. data/lib/rosette/core/snapshots/head_snapshot_factory.rb +58 -0
  62. data/lib/rosette/core/snapshots/repo_config_path_filter.rb +83 -0
  63. data/lib/rosette/core/snapshots/snapshot_factory.rb +184 -0
  64. data/lib/rosette/core/string_utils.rb +23 -0
  65. data/lib/rosette/core/translation_status.rb +81 -0
  66. data/lib/rosette/core/validators.rb +18 -0
  67. data/lib/rosette/core/validators/commit_validator.rb +62 -0
  68. data/lib/rosette/core/validators/commits_validator.rb +32 -0
  69. data/lib/rosette/core/validators/encoding_validator.rb +32 -0
  70. data/lib/rosette/core/validators/locale_validator.rb +37 -0
  71. data/lib/rosette/core/validators/repo_validator.rb +33 -0
  72. data/lib/rosette/core/validators/serializer_validator.rb +37 -0
  73. data/lib/rosette/core/validators/validator.rb +31 -0
  74. data/lib/rosette/core/version.rb +8 -0
  75. data/lib/rosette/data_stores.rb +11 -0
  76. data/lib/rosette/data_stores/errors.rb +26 -0
  77. data/lib/rosette/data_stores/phrase_status.rb +59 -0
  78. data/lib/rosette/integrations.rb +12 -0
  79. data/lib/rosette/integrations/errors.rb +15 -0
  80. data/lib/rosette/integrations/integratable.rb +58 -0
  81. data/lib/rosette/integrations/integration.rb +23 -0
  82. data/lib/rosette/preprocessors.rb +11 -0
  83. data/lib/rosette/preprocessors/errors.rb +14 -0
  84. data/lib/rosette/preprocessors/preprocessor.rb +48 -0
  85. data/lib/rosette/queuing.rb +14 -0
  86. data/lib/rosette/queuing/commits.rb +19 -0
  87. data/lib/rosette/queuing/commits/commit_conductor.rb +90 -0
  88. data/lib/rosette/queuing/commits/commit_job.rb +93 -0
  89. data/lib/rosette/queuing/commits/commits_queue_configurator.rb +60 -0
  90. data/lib/rosette/queuing/commits/extract_stage.rb +46 -0
  91. data/lib/rosette/queuing/commits/fetch_stage.rb +51 -0
  92. data/lib/rosette/queuing/commits/finalize_stage.rb +76 -0
  93. data/lib/rosette/queuing/commits/phrase_storage_granularity.rb +20 -0
  94. data/lib/rosette/queuing/commits/push_stage.rb +91 -0
  95. data/lib/rosette/queuing/commits/stage.rb +96 -0
  96. data/lib/rosette/queuing/job.rb +74 -0
  97. data/lib/rosette/queuing/queue.rb +28 -0
  98. data/lib/rosette/queuing/queue_configurator.rb +76 -0
  99. data/lib/rosette/queuing/worker.rb +30 -0
  100. data/lib/rosette/serializers.rb +10 -0
  101. data/lib/rosette/serializers/serializer.rb +98 -0
  102. data/lib/rosette/tms.rb +9 -0
  103. data/lib/rosette/tms/repository.rb +95 -0
  104. data/rosette-core.gemspec +24 -0
  105. data/spec/core/branch_utils_spec.rb +110 -0
  106. data/spec/core/commands/git/commit_command_spec.rb +60 -0
  107. data/spec/core/commands/git/diff_command_spec.rb +263 -0
  108. data/spec/core/commands/git/fetch_command_spec.rb +61 -0
  109. data/spec/core/commands/git/repo_snapshot_command_spec.rb +72 -0
  110. data/spec/core/commands/git/show_command_spec.rb +128 -0
  111. data/spec/core/commands/git/snapshot_command_spec.rb +86 -0
  112. data/spec/core/commands/git/status_command_spec.rb +154 -0
  113. data/spec/core/commands/queuing/enqueue_commit_command_spec.rb +34 -0
  114. data/spec/core/commands/queuing/requeue_commit_command_spec.rb +46 -0
  115. data/spec/core/commands/translations/export_command_spec.rb +113 -0
  116. data/spec/core/commands/translations/translation_lookup_command_spec.rb +58 -0
  117. data/spec/core/configurator_spec.rb +47 -0
  118. data/spec/core/error_reporters/buffered_error_reporter_spec.rb +61 -0
  119. data/spec/core/error_reporters/nil_error_reporter_spec.rb +16 -0
  120. data/spec/core/error_reporters/printing_error_reporter_spec.rb +60 -0
  121. data/spec/core/extractor/commit_log_status_spec.rb +216 -0
  122. data/spec/core/extractor/commit_processor_spec.rb +68 -0
  123. data/spec/core/extractor/extractor_config_spec.rb +47 -0
  124. data/spec/core/extractor/extractor_spec.rb +26 -0
  125. data/spec/core/extractor/locale_spec.rb +92 -0
  126. data/spec/core/extractor/phrase/phrase_index_policy_spec.rb +116 -0
  127. data/spec/core/extractor/phrase/phrase_to_hash_spec.rb +18 -0
  128. data/spec/core/extractor/repo_config_spec.rb +147 -0
  129. data/spec/core/extractor/translation/translation_to_hash_spec.rb +25 -0
  130. data/spec/core/git/diff_finder_spec.rb +74 -0
  131. data/spec/core/git/ref_spec.rb +118 -0
  132. data/spec/core/git/repo_spec.rb +216 -0
  133. data/spec/core/path_matcher_factory_spec.rb +139 -0
  134. data/spec/core/resolvers/extractor_id_spec.rb +47 -0
  135. data/spec/core/resolvers/integration_id_spec.rb +47 -0
  136. data/spec/core/resolvers/preprocessor_id_spec.rb +47 -0
  137. data/spec/core/resolvers/serializer_id_spec.rb +47 -0
  138. data/spec/core/snapshots/snapshot_factory_spec.rb +145 -0
  139. data/spec/core/string_utils_spec.rb +19 -0
  140. data/spec/core/translation_status_spec.rb +91 -0
  141. data/spec/core/validators/commit_validator_spec.rb +40 -0
  142. data/spec/core/validators/encoding_validator_spec.rb +30 -0
  143. data/spec/core/validators/locale_validator_spec.rb +31 -0
  144. data/spec/core/validators/repo_validator_spec.rb +30 -0
  145. data/spec/core/validators/serializer_validator_spec.rb +31 -0
  146. data/spec/integrations/integratable_spec.rb +58 -0
  147. data/spec/queuing/commits/commit_conductor_spec.rb +71 -0
  148. data/spec/queuing/commits/commit_job_spec.rb +87 -0
  149. data/spec/queuing/commits/extract_stage_spec.rb +68 -0
  150. data/spec/queuing/commits/fetch_stage_spec.rb +101 -0
  151. data/spec/queuing/commits/finalize_stage_spec.rb +88 -0
  152. data/spec/queuing/commits/push_stage_spec.rb +145 -0
  153. data/spec/queuing/commits/stage_spec.rb +80 -0
  154. data/spec/queuing/job_spec.rb +33 -0
  155. data/spec/queuing/queue_configurator_spec.rb +44 -0
  156. data/spec/spec_helper.rb +90 -0
  157. data/spec/test_helpers/fake_commit_stage.rb +17 -0
  158. metadata +257 -0
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Raises errors instead of printing or logging them.
7
+ class RaisingErrorReporter < ErrorReporter
8
+ # Raises an error.
9
+ #
10
+ # @param [Exception] error The error to raise.
11
+ # @param [Hash] options A hash of associated options.
12
+ # @return [void]
13
+ def report_error(error, options = {})
14
+ raise error
15
+ end
16
+
17
+ # Does nothing.
18
+ #
19
+ # @param [Exception] error An error, but nothing is done with it.
20
+ # @param [Hash] options A hash of associated options.
21
+ # @return [void]
22
+ def report_warning(error, options = {})
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Represents a generic syntax error that probably occurred when attempting
7
+ # to parse a bit of source code or other well-defined text format.
8
+ #
9
+ # @!attribute [r] message
10
+ # @return [String] the error message.
11
+ # @!attribute [r] original_exception
12
+ # @return [Exception] the original exception, probably from a parser of
13
+ # some kind.
14
+ # @!attribute [r] language
15
+ # @return [Symbol] the language that the text the parser attempted to
16
+ # parse was in when this error was generated.
17
+ class SyntaxError < StandardError
18
+ attr_reader :message, :original_exception, :language
19
+
20
+ # Creates a new syntax error object.
21
+ #
22
+ # @param [String] msg The error message text.
23
+ # @param [Exception] original_exception The original error from the
24
+ # parser or some such.
25
+ # @param [Symbol] language The source code language.
26
+ def initialize(msg, original_exception, language)
27
+ super(msg)
28
+ @message = msg
29
+ @original_exception = original_exception
30
+ @language = language
31
+ end
32
+
33
+ # A string representation of this error which combines both the original
34
+ # message as well as the language.
35
+ #
36
+ # @return [String]
37
+ def message
38
+ "#{@message} (#{language})"
39
+ end
40
+
41
+ alias :to_s :message
42
+ end
43
+
44
+ # Represents a generic syntax error generated by one of Rosette's
45
+ # extractors. Since extractors parse source code and other
46
+ # well-defined text formats, there's always the possibility that these formats
47
+ # will contain syntax errors.
48
+ #
49
+ # @!attribute [r] original_exception
50
+ # @return [Exception] the original error from the parser or some such.
51
+ # @!attribute [r] language
52
+ # @return [Symbol] the source code language.
53
+ # @!attribute [r] file
54
+ # @return [String] the file that was being parsed when the error was
55
+ # generated.
56
+ # @!attribute [r] commit_id
57
+ # @return [String] the commit id that contained the file that was being
58
+ # parsed when the error was generated.
59
+ class ExtractionSyntaxError < StandardError
60
+ attr_reader :original_exception, :language, :file, :commit_id
61
+
62
+ # Creates a new syntax error object.
63
+ #
64
+ # @param [String] msg The error message text.
65
+ # @param [Exception] original_exception The original error from the
66
+ # parser or some such.
67
+ # @param [Symbol] language The source code language.
68
+ # @param [String] file The file that was being parsed when the error
69
+ # was generated.
70
+ # @param [String] commit_id The commit id that contained the file that
71
+ # was being parsed when the error was generated.
72
+ def initialize(msg, original_exception, language, file, commit_id)
73
+ super(msg)
74
+ @message = msg
75
+ @original_exception = original_exception
76
+ @language = language
77
+ @file = file
78
+ @commit_id = commit_id
79
+ end
80
+
81
+ # A string representation of this error which includes the original
82
+ # message, the source language, the file, and the commit id.
83
+ #
84
+ # @return [String]
85
+ def message
86
+ "#{@message}: #{original_exception.message} (#{language}) in #{file} at #{commit_id}"
87
+ end
88
+
89
+ alias :to_s :message
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Represents a commit log. Commit logs track the status of individual
7
+ # commits, what time the commit occurred, and how many phrases it contains.
8
+ #
9
+ # @!attribute [rw] repo_name
10
+ # @return [String] the name of the repo the commit was found in.
11
+ # @!attribute [rw] commit_id
12
+ # @return [String] the git commit id.
13
+ # @!attribute [rw] phrase_count
14
+ # @return [Fixnum] the number of phrases found in this commit.
15
+ # @!attribute [rw] status
16
+ # @return [String] the [PhraseStatus] of this commit.
17
+ # @!attribute [rw] commit_datetime
18
+ # @return [DateTime] the time this commit was made.
19
+ # @!attribute [rw] branch_name
20
+ # @return [String] the name of the branch that contains this commit.
21
+ class CommitLog
22
+ def initialize(repo_name, commit_id, phrase_count = nil, status = nil, commit_datetime = nil, branch_name = nil)
23
+ @repo_name = repo_name
24
+ @commit_id = commit_id
25
+ @phrase_count = phrase_count
26
+ @status = status
27
+ @commit_datetime = commit_datetime
28
+ @branch_name = branch_name
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'aasm'
4
+
5
+ module Rosette
6
+ module Core
7
+
8
+ # Provides a state machine for transitioning between the possible states of
9
+ # a commit log.
10
+ module CommitLogStatus
11
+ # aasm requires all states to be symbols
12
+ Rosette::DataStores::PhraseStatus.all.each do |status|
13
+ self.const_set(status, status.to_sym)
14
+ end
15
+
16
+ def self.included(base)
17
+ base.class_eval do
18
+ include AASM
19
+
20
+ aasm do
21
+ # define states from PhraseStatus constants
22
+ Rosette::DataStores::PhraseStatus.all.each do |status|
23
+ state status.to_sym
24
+ end
25
+
26
+ attribute_name :status
27
+ initial_state NOT_SEEN
28
+
29
+ event :fetch do
30
+ transitions from: NOT_SEEN, to: FETCHED
31
+ end
32
+
33
+ event :extract do
34
+ transitions from: FETCHED, to: EXTRACTED
35
+ end
36
+
37
+ event :push do
38
+ transitions from: [EXTRACTED, PUSHED], to: PUSHED
39
+ end
40
+
41
+ event :finalize do
42
+ transitions from: [EXTRACTED, PUSHED, FINALIZED], to: FINALIZED
43
+ end
44
+
45
+ # called when jgit can't find the commit
46
+ event :missing do
47
+ transitions(
48
+ from: Rosette::DataStores::PhraseStatus.statuses,
49
+ to: MISSING
50
+ )
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: UTF-8
2
+
3
+ java_import 'org.eclipse.jgit.revwalk.RevWalk'
4
+
5
+ module Rosette
6
+ module Core
7
+
8
+ # Extracts phrases from a git commit. Should be thread-safe.
9
+ #
10
+ # @!attribute [r] config
11
+ # @return [Configurator] the Rosette config to use.
12
+ # @!attribute [r] error_reporter
13
+ # @return [ErrorReporter] the error reporter to report syntax
14
+ # errors, etc to.
15
+ #
16
+ # @example
17
+ # processor = CommitProcessor.new(configuration)
18
+ # processor.process_each_phrase('my_repo', 'master') do |phrase|
19
+ # puts phrase.key
20
+ # end
21
+ class CommitProcessor
22
+ attr_reader :config, :error_reporter
23
+
24
+ # Creates a new processor.
25
+ #
26
+ # @param [Configurator] config The Rosette config to use.
27
+ # @param [ErrorReporter] error_reporter The error reporter to report
28
+ # syntax errors, etc to.
29
+ def initialize(config, error_reporter = NilErrorReporter.instance)
30
+ @config = config
31
+ @error_reporter = error_reporter
32
+ end
33
+
34
+ # Extracts translatable phrases from the given ref and yields them
35
+ # sequentially to the given block. If no block is given, this method
36
+ # returns an +Enumerator+.
37
+ #
38
+ # @param [String] repo_name The name of the repository to extract
39
+ # translatable phrases from. Must be configured in +config+.
40
+ # @param [String] commit_ref The git ref or commit id to extract
41
+ # translatable phrases from.
42
+ # @raise [Java::OrgEclipseJgitErrors::MissingObjectException]
43
+ # @return [void, Enumerator] either nothing if a block is given or
44
+ # an instance of +Enumerator+ if no block is given.
45
+ # @yield [phrase] a single extracted phrase.
46
+ # @yieldparam phrase [Phrase]
47
+ def process_each_phrase(repo_name, commit_ref)
48
+ if block_given?
49
+ repo_config = config.get_repo(repo_name)
50
+ rev_walk = RevWalk.new(repo_config.repo.jgit_repo)
51
+ diff_finder = DiffFinder.new(repo_config.repo.jgit_repo, rev_walk)
52
+ commit = repo_config.repo.get_rev_commit(commit_ref, rev_walk)
53
+
54
+ diff_finder.diff_with_parents(commit).each_pair do |_, diff_entries|
55
+ diff_entries.each do |diff_entry|
56
+ if diff_entry.getNewPath != '/dev/null'
57
+ process_diff_entry(diff_entry, repo_config, commit) do |phrase|
58
+ yield phrase
59
+ end
60
+ end
61
+ end
62
+ end
63
+ else
64
+ to_enum(__method__, repo_name, commit_ref)
65
+ end
66
+ end
67
+
68
+ protected
69
+
70
+ def process_diff_entry(diff_entry, repo_config, commit)
71
+ repo_config.get_extractor_configs(diff_entry.getNewPath).each do |extractor_config|
72
+ source_code = read_object_from_entry(diff_entry, repo_config, extractor_config)
73
+ line_numbers_to_author = repo_config.repo.blame(diff_entry.getNewPath, commit.getId.name)
74
+
75
+ begin
76
+ extractor_config.extractor.extract_each_from(source_code) do |phrase, line_number|
77
+ phrase.file = diff_entry.getNewPath
78
+ phrase.commit_id = commit.getId.name
79
+
80
+ if extractor_config.extractor.supports_line_numbers?
81
+ if author_identity = line_numbers_to_author[line_number - 1]
82
+ phrase.author_name = author_identity.getName
83
+ phrase.author_email = author_identity.getEmailAddress
84
+ phrase.line_number = line_number
85
+ end
86
+ end
87
+
88
+ yield phrase
89
+ end
90
+ rescue SyntaxError => e
91
+ error_reporter.report_error(
92
+ ExtractionSyntaxError.new(
93
+ e.message, e.original_exception, e.language,
94
+ diff_entry.getNewPath, commit.getId.name
95
+ )
96
+ )
97
+ end
98
+ end
99
+ end
100
+
101
+ def read_object_from_entry(diff_entry, repo_config, extractor_config)
102
+ object_reader = repo_config.repo.jgit_repo.newObjectReader
103
+ bytes = object_reader.open(diff_entry.getNewId.toObjectId).getBytes
104
+ Java::JavaLang::String.new(bytes, extractor_config.encoding.to_s).to_s
105
+ end
106
+ end
107
+
108
+ end
109
+ end
@@ -0,0 +1,72 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Base class for extractors that extract phrases from source code,
7
+ # eg. Ruby, JavaScript, HAML, etc.
8
+ #
9
+ # @!attribute [r] config
10
+ # @return [Configurator] the Rosette config to use.
11
+ class Extractor
12
+ attr_reader :config
13
+
14
+ # Creates a new extractor.
15
+ #
16
+ # @param [Configurator] config The Rosette config to use.
17
+ def initialize(config = nil)
18
+ @config = config
19
+ end
20
+
21
+ # Extracts each translatable phrase from the given source code.
22
+ # Derived classes must implement the +#each_function_call+ method
23
+ # for this to work.
24
+ #
25
+ # @param [String] source_code The source code to extract phrases
26
+ # from.
27
+ # @return [void, Enumerator] If passed a block, this method yields
28
+ # each consecutive phrase found in +source_code+. If no block is
29
+ # passed, it returns an +Enumerator+.
30
+ # @yield [phrase] a single extracted phrase.
31
+ # @yieldparam phrase [Phrase]
32
+ def extract_each_from(source_code)
33
+ if block_given?
34
+ each_function_call(source_code) do |node, line_number|
35
+ if valid_name?(node) && valid_args?(node)
36
+ yield make_phrase(get_key(node), get_meta_key(node)), line_number
37
+ end
38
+ end
39
+ else
40
+ to_enum(__method__, source_code)
41
+ end
42
+ end
43
+
44
+ protected
45
+
46
+ def each_function_call(source_code)
47
+ raise NotImplementedError, "#{__method__} must be implemented by derived classes."
48
+ end
49
+
50
+ def valid_name?(node)
51
+ raise NotImplementedError, "#{__method__} must be implemented by derived classes."
52
+ end
53
+
54
+ def valid_args?(node)
55
+ raise NotImplementedError, "#{__method__} must be implemented by derived classes."
56
+ end
57
+
58
+ def get_key(node)
59
+ raise NotImplementedError, "#{__method__} must be implemented by derived classes."
60
+ end
61
+
62
+ def get_meta_key(node)
63
+ nil
64
+ end
65
+
66
+ def make_phrase(key, meta_key = nil, file = nil)
67
+ Phrase.new(key, meta_key, file)
68
+ end
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: UTF-8
2
+
3
+ module Rosette
4
+ module Core
5
+
6
+ # Configuration for an extractor.
7
+ #
8
+ # @example
9
+ # ex = ExtractorConfig.new(JsonExtractor::KeyValueExtractor)
10
+ # .set_encoding(Encoding::UTF_8)
11
+ # .set_conditions do |root|
12
+ # root.match_file_extension('.json').and(
13
+ # root.match_path('config/locales')
14
+ # )
15
+ # end
16
+ #
17
+ # @!attribute [r] extractor
18
+ # @return [Extractor] the extractor instance that will be used to
19
+ # extract phrases.
20
+ # @!attribute [r] encoding
21
+ # @return [String, Encoding] the encoding to expect the contents of
22
+ # source files to be in.
23
+ # @!attribute [r] root
24
+ # @return [PathMatcherFactory::Node] the root of the
25
+ # conditions tree. Only files that are matched by the conditions in
26
+ # this tree will have their phrases extracted.
27
+ class ExtractorConfig
28
+ attr_reader :extractor_id, :extractor, :encoding, :root
29
+
30
+ # Creates a new extractor configuration.
31
+ #
32
+ # @param [String] extractor_id The extractor id of +extractor_class+.
33
+ # @param [Class] extractor_class The extractor to use.
34
+ def initialize(extractor_id, extractor_class)
35
+ @extractor_id = extractor_id
36
+ @extractor = extractor_class.new(self)
37
+ @root = PathMatcherFactory.create_root
38
+ @encoding = Rosette::Core::DEFAULT_ENCODING
39
+ end
40
+
41
+ # Sets the encoding to expect the contents of source files to be in.
42
+ #
43
+ # @param [String, Encoding] new_encoding the encoding to use.
44
+ # @return [self]
45
+ def set_encoding(new_encoding)
46
+ @encoding = new_encoding
47
+ self
48
+ end
49
+
50
+ # Determines if the given path matches all the conditions in the
51
+ # conditions tree.
52
+ #
53
+ # @param [String] path The path to match.
54
+ # @return [Boolean] true if the path matches, false otherwise.
55
+ def matches?(path)
56
+ root.matches?(path)
57
+ end
58
+
59
+ # Creates and yields a node that represents the root of a conditions
60
+ # tree. Callers should use the yielded root to build up a set of
61
+ # conditions that will be used to match paths in the repository.
62
+ # Matching paths will be processed by the extractor (i.e. their
63
+ # translatable phrases will be identified and stored).
64
+ #
65
+ # @return [self]
66
+ # @yield [root] the root of the conditions tree
67
+ # @yieldparam root [PathMatcherFactory::Node]
68
+ def set_conditions
69
+ @root = yield PathMatcherFactory.create_root
70
+ self
71
+ end
72
+ end
73
+ end
74
+ end