ccios 4.1.0 → 5.1.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 +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +35 -0
- data/Gemfile.lock +34 -15
- data/MAINTAINER.md +8 -0
- data/README.md +188 -56
- data/ccios.gemspec +2 -2
- data/lib/ccios/argument_template_parameter.rb +33 -0
- data/lib/ccios/code_templater.rb +24 -8
- data/lib/ccios/config.rb +41 -91
- data/lib/ccios/file_creator.rb +37 -24
- data/lib/ccios/file_template_definition.rb +95 -0
- data/lib/ccios/flag_template_parameter.rb +17 -0
- data/lib/ccios/group_template_definition.rb +54 -0
- data/lib/ccios/pbxproj_parser.rb +4 -55
- data/lib/ccios/snippet_template_definition.rb +27 -0
- data/lib/ccios/template_definition.rb +116 -0
- data/lib/ccios/templates/{coordinator.mustache → Coordinator/coordinator.mustache} +5 -2
- data/lib/ccios/templates/Coordinator/template.yml +19 -0
- data/lib/ccios/templates/{interactor_implementation.mustache → Interactor/interactor_implementation.mustache} +2 -2
- data/lib/ccios/templates/Interactor/template.yml +24 -0
- data/{templates_library/async → lib/ccios/templates/Presenter}/dependency_provider.mustache +6 -2
- data/lib/ccios/templates/{presenter_implementation.mustache → Presenter/presenter_implementation.mustache} +4 -1
- data/lib/ccios/templates/Presenter/template.yml +55 -0
- data/lib/ccios/templates/{view_contract.mustache → Presenter/view_contract.mustache} +2 -1
- data/lib/ccios/templates/{view_controller.mustache → Presenter/view_controller.mustache} +4 -0
- data/{templates_library/async/repository.mustache → lib/ccios/templates/Presenter/view_model.mustache} +2 -3
- data/lib/ccios/templates/Presenter/view_model_mapper.mustache +16 -0
- data/lib/ccios/templates/Repository/template.yml +25 -0
- data/lib/ccios/templates_loader.rb +31 -0
- data/lib/ccios.rb +65 -43
- data/templates_library/async/Coordinator/template.yml +20 -0
- data/{lib/ccios/templates → templates_library/async/Presenter}/presenter.mustache +2 -0
- data/templates_library/async/Presenter/template.yml +49 -0
- metadata +40 -34
- data/lib/ccios/coordinator_generator.rb +0 -18
- data/lib/ccios/interactor_generator.rb +0 -33
- data/lib/ccios/presenter_generator.rb +0 -71
- data/lib/ccios/repository_generator.rb +0 -44
- data/templates_library/async/interactor.mustache +0 -13
- data/templates_library/async/interactor_assembly.mustache +0 -5
- data/templates_library/async/interactor_implementation.mustache +0 -22
- data/templates_library/async/repository_assembly.mustache +0 -6
- data/templates_library/async/repository_implementation.mustache +0 -20
- /data/lib/ccios/templates/{interactor.mustache → Interactor/interactor.mustache} +0 -0
- /data/lib/ccios/templates/{interactor_assembly.mustache → Interactor/interactor_assembly.mustache} +0 -0
- /data/{templates_library/async → lib/ccios/templates/Presenter}/presenter.mustache +0 -0
- /data/lib/ccios/templates/{presenter_assembly.mustache → Presenter/presenter_assembly.mustache} +0 -0
- /data/lib/ccios/templates/{repository.mustache → Repository/repository.mustache} +0 -0
- /data/lib/ccios/templates/{repository_assembly.mustache → Repository/repository_assembly.mustache} +0 -0
- /data/lib/ccios/templates/{repository_implementation.mustache → Repository/repository_implementation.mustache} +0 -0
- /data/templates_library/async/{coordinator.mustache → Coordinator/coordinator.mustache} +0 -0
- /data/{lib/ccios/templates → templates_library/async/Presenter}/dependency_provider.mustache +0 -0
- /data/templates_library/async/{presenter_assembly.mustache → Presenter/presenter_assembly.mustache} +0 -0
- /data/templates_library/async/{presenter_implementation.mustache → Presenter/presenter_implementation.mustache} +0 -0
- /data/templates_library/async/{view_contract.mustache → Presenter/view_contract.mustache} +0 -0
- /data/templates_library/async/{view_controller.mustache → Presenter/view_controller.mustache} +0 -0
data/lib/ccios/config.rb
CHANGED
@@ -2,11 +2,12 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
class Config
|
4
4
|
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :variables, :templates_collection
|
6
6
|
|
7
7
|
def self.parse(source_path)
|
8
8
|
if File.exist?(source_path)
|
9
9
|
config = YAML.load_file(source_path)
|
10
|
+
raise "Invalid config file" unless config.is_a?(Hash)
|
10
11
|
self.new config, source_path
|
11
12
|
else
|
12
13
|
puts "File #{source_path} does not exist. Using default config."
|
@@ -14,120 +15,69 @@ class Config
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
|
-
def self.default_config_hash
|
18
|
-
project = "*.xcodeproj"
|
19
|
-
{
|
20
|
-
"app" => {
|
21
|
-
"project" => project,
|
22
|
-
"presenter" => {"group" => "Classes/App"},
|
23
|
-
"coordinator" => {"group" => "Classes/Coordinator"}
|
24
|
-
},
|
25
|
-
"core" => {
|
26
|
-
"project" => project,
|
27
|
-
"interactor" => {"group" => "Classes/Core/Interactor"},
|
28
|
-
"repository" => {"group" => "Classes/Core/Data"}
|
29
|
-
},
|
30
|
-
"data" => {
|
31
|
-
"project" => project,
|
32
|
-
"repository" => {"group" => "Classes/Data"}
|
33
|
-
},
|
34
|
-
"templates" => self.default_templates_hash
|
35
|
-
}
|
36
|
-
end
|
37
|
-
|
38
18
|
def self.default
|
39
19
|
self.new default_config_hash
|
40
20
|
end
|
41
21
|
|
42
|
-
def self.
|
43
|
-
{
|
22
|
+
def self.default_config_hash
|
23
|
+
{}
|
44
24
|
end
|
45
25
|
|
46
26
|
def initialize(config_hash, source_path = nil)
|
47
|
-
@
|
48
|
-
|
49
|
-
@
|
50
|
-
|
51
|
-
@
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
27
|
+
@variables = config_hash["variables"] || {}
|
28
|
+
@templates_collection = config_hash["templates_collection"] || nil
|
29
|
+
@templates_config = {}
|
30
|
+
|
31
|
+
raise "Invalid \"templates_collection\" in config, should be a string" unless @templates_collection.is_a?(String) || @templates_collection.nil?
|
32
|
+
|
33
|
+
templates_config = config_hash["templates_config"] || {}
|
34
|
+
raise "Invalid \"templates_config\" in configuration, it should be a dictionary" unless templates_config.is_a?(Hash)
|
35
|
+
templates_config.each do |key, hash|
|
36
|
+
raise "Invalid template configuration for \"#{key}\"" unless hash.is_a?(Hash)
|
37
|
+
template_config = TemplateConfig.new(hash)
|
38
|
+
@templates_config[key] = template_config
|
56
39
|
end
|
57
40
|
end
|
58
41
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
validate_path hash, "app.coordinator.group"
|
63
|
-
|
64
|
-
validate_path hash, "core.project"
|
65
|
-
validate_path hash, "core.interactor.group"
|
66
|
-
validate_path hash, "core.repository.group"
|
67
|
-
|
68
|
-
validate_path hash, "data.project"
|
69
|
-
validate_path hash, "data.repository.group"
|
42
|
+
def variables_for_template(template)
|
43
|
+
template_config = @templates_config[template.name] || TemplateConfig.new({})
|
44
|
+
@variables.merge(template.variables).merge(template_config.variables)
|
70
45
|
end
|
71
46
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
keys << component
|
78
|
-
if hash.nil?
|
79
|
-
message = "Key \"#{keys.join(".")}\" is missing"
|
80
|
-
message += " in #{@source_path}" unless @source_path.nil?
|
81
|
-
raise message
|
82
|
-
end
|
83
|
-
end
|
47
|
+
def variables_for_template_element(template, element_name, element_default_variables = {})
|
48
|
+
template_config = @templates_config[template.name] || TemplateConfig.new({})
|
49
|
+
element_config = template_config.element_configuration_for(element_name)
|
50
|
+
template_variables = @variables.merge(template.variables).merge(template_config.variables)
|
51
|
+
template_variables.merge(element_default_variables).merge(element_config.variables)
|
84
52
|
end
|
85
53
|
end
|
86
54
|
|
87
|
-
class
|
88
|
-
attr_reader :project, :target, :presenter, :coordinator
|
55
|
+
class TemplateConfig
|
89
56
|
|
90
|
-
|
91
|
-
@project = hash["project"]
|
92
|
-
@target = hash["target"]
|
93
|
-
@presenter = ObjectConfig.new hash["presenter"]
|
94
|
-
@coordinator = ObjectConfig.new hash["coordinator"]
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
class CoreConfig
|
99
|
-
attr_reader :project, :target, :interactor, :repository
|
57
|
+
attr_reader :variables
|
100
58
|
|
101
59
|
def initialize(hash)
|
102
|
-
@
|
103
|
-
@
|
104
|
-
|
105
|
-
|
60
|
+
@variables = hash["variables"] || {}
|
61
|
+
@template_element_config = {}
|
62
|
+
|
63
|
+
elements_variables = hash["elements_variables"] || {}
|
64
|
+
raise "Invalid configuration, \"elements_variables\" should be a dictionary" unless elements_variables.is_a?(Hash)
|
65
|
+
elements_variables.each do |key, hash|
|
66
|
+
raise "Invalid element variable configuration for \"#{key}\"" unless hash.is_a?(Hash)
|
67
|
+
@template_element_config[key] = TemplateElementConfig.new(hash)
|
68
|
+
end
|
106
69
|
end
|
107
|
-
end
|
108
70
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
def initialize(hash)
|
113
|
-
@project = hash["project"]
|
114
|
-
@target = hash["target"]
|
115
|
-
@repository = ObjectConfig.new hash["repository"]
|
71
|
+
def element_configuration_for(element)
|
72
|
+
@template_element_config[element] || TemplateConfig.new({})
|
116
73
|
end
|
117
74
|
end
|
118
75
|
|
119
|
-
class
|
120
|
-
attr_reader :group
|
76
|
+
class TemplateElementConfig
|
121
77
|
|
122
|
-
|
123
|
-
@group = hash["group"]
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class TemplatesConfig
|
128
|
-
attr_reader :path
|
78
|
+
attr_reader :variables
|
129
79
|
|
130
80
|
def initialize(hash)
|
131
|
-
@
|
81
|
+
@variables = hash
|
132
82
|
end
|
133
|
-
end
|
83
|
+
end
|
data/lib/ccios/file_creator.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative 'code_templater'
|
2
2
|
require 'fileutils'
|
3
3
|
require 'logger'
|
4
|
+
require 'xcodeproj'
|
4
5
|
|
5
6
|
class Xcodeproj::Project::Object::PBXGroup
|
6
7
|
|
@@ -14,6 +15,13 @@ class Xcodeproj::Project::Object::PBXGroup
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
18
|
+
class Xcodeproj::Project
|
19
|
+
|
20
|
+
def project_name_from_path
|
21
|
+
File.basename(@path, File.extname(@path))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
17
25
|
class FileCreator
|
18
26
|
|
19
27
|
def self.logger
|
@@ -24,40 +32,55 @@ class FileCreator
|
|
24
32
|
FileCreator.logger
|
25
33
|
end
|
26
34
|
|
27
|
-
def
|
28
|
-
@options = options
|
29
|
-
@config = config
|
30
|
-
end
|
31
|
-
|
32
|
-
def templater_options(target)
|
35
|
+
def templater_options(targets, project)
|
33
36
|
defaults = {
|
34
|
-
project_name: target.display_name,
|
35
37
|
full_username: git_username,
|
36
38
|
date: DateTime.now.strftime("%d/%m/%Y"),
|
37
39
|
}
|
38
|
-
|
40
|
+
if targets.count == 1
|
41
|
+
defaults["project_name"] = targets[0].display_name
|
42
|
+
else
|
43
|
+
defaults["project_name"] = project.project_name_from_path
|
44
|
+
end
|
45
|
+
defaults
|
39
46
|
end
|
40
47
|
|
41
48
|
def git_username
|
42
49
|
`git config user.name`.strip
|
43
50
|
end
|
44
51
|
|
45
|
-
def
|
46
|
-
|
52
|
+
def get_unknown_template_tags_for(template_path)
|
53
|
+
tags = CodeTemplater.new.get_unknown_context_keys_for_template(template_path)
|
54
|
+
tags.subtract(Set["project_name", "full_username", "date"])
|
55
|
+
tags
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_file_using_template_path(template_path, generated_filename, group, targets, project, context)
|
59
|
+
file_path = File.join(group.real_path, generated_filename)
|
47
60
|
|
48
61
|
raise "File #{file_path} already exists" if File.exist?(file_path)
|
49
62
|
dirname = File.dirname(file_path)
|
50
63
|
FileUtils.mkdir_p dirname unless File.directory?(dirname)
|
51
64
|
file = File.new(file_path, 'w')
|
52
65
|
|
53
|
-
|
54
|
-
|
55
|
-
|
66
|
+
context = context.merge(templater_options(targets, project))
|
67
|
+
file_content = CodeTemplater.new.render_file_content_from_template(template_path, generated_filename, context)
|
68
|
+
|
56
69
|
file.puts(file_content)
|
57
70
|
|
58
71
|
file.close
|
59
72
|
file_ref = group.new_reference(file_path)
|
60
|
-
target
|
73
|
+
targets.each do |target|
|
74
|
+
target.add_file_references([file_ref])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def print_file_content_using_template(filename, template_path, context)
|
79
|
+
file_content = CodeTemplater.new.render_file_content_from_template(template_path, filename, context)
|
80
|
+
Mustache.render(File.read(template_path), context)
|
81
|
+
|
82
|
+
logger.info "Add this snippet to #{filename}"
|
83
|
+
logger.info file_content
|
61
84
|
end
|
62
85
|
|
63
86
|
def create_empty_directory(group)
|
@@ -68,16 +91,6 @@ class FileCreator
|
|
68
91
|
FileUtils.touch(git_keep_path) if Dir.empty?(dirname)
|
69
92
|
end
|
70
93
|
|
71
|
-
def print_file_content(prefix, suffix)
|
72
|
-
file_name = suffix + '.swift'
|
73
|
-
|
74
|
-
code_templater = CodeTemplater.new(@options, @config.templates.path)
|
75
|
-
template = code_templater.content_for_suffix(prefix, suffix)
|
76
|
-
|
77
|
-
logger.info "Add this snippet to #{file_name}"
|
78
|
-
logger.info template
|
79
|
-
end
|
80
|
-
|
81
94
|
private
|
82
95
|
|
83
96
|
def self.create_logger
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require_relative 'code_templater'
|
2
|
+
require_relative 'file_creator'
|
3
|
+
require_relative 'pbxproj_parser'
|
4
|
+
|
5
|
+
class FileTemplateDefinition
|
6
|
+
def initialize(file_template_definition_hash)
|
7
|
+
@name = file_template_definition_hash["name"]
|
8
|
+
@path = file_template_definition_hash["file"]
|
9
|
+
@template = file_template_definition_hash["template"]
|
10
|
+
@variables = file_template_definition_hash["variables"] || {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate(parser, project, context, template_definition, config)
|
14
|
+
|
15
|
+
merged_variables = config.variables_for_template_element(template_definition, @name, @variables)
|
16
|
+
|
17
|
+
code_templater = CodeTemplater.new
|
18
|
+
expected_context_keys = template_definition.provided_context_keys
|
19
|
+
pathTags = code_templater.get_unknown_context_keys_for_string(@path)
|
20
|
+
pathTags.each do |tag|
|
21
|
+
raise "Unknown parameter \"#{tag}\" in path \"#{@path}\"" unless expected_context_keys.include?(tag)
|
22
|
+
end
|
23
|
+
|
24
|
+
file_path = code_templater.render_string(@path, context)
|
25
|
+
raise "File #{file_path} already exists" if File.exist?(file_path)
|
26
|
+
|
27
|
+
file_creator = FileCreator.new
|
28
|
+
contentTags = file_creator.get_unknown_template_tags_for(template_definition.template_source_file(@template))
|
29
|
+
contentTags.each do |tag|
|
30
|
+
raise "Unknown parameter \"#{tag}\" in template \"#{@template}\"" unless expected_context_keys.include?(tag)
|
31
|
+
end
|
32
|
+
|
33
|
+
base_path = merged_variables["base_path"]
|
34
|
+
raise "Missing base_path variable" if base_path.nil?
|
35
|
+
|
36
|
+
base_group = project[base_path]
|
37
|
+
raise "Base path \"#{base_path}\" is missing" if base_group.nil?
|
38
|
+
|
39
|
+
target_name = merged_variables["target"]
|
40
|
+
if target_name.is_a?(String) || target_name.nil?
|
41
|
+
target = parser.target_for(project, target_name)
|
42
|
+
raise "Unable to find target \"#{target_name}\"" if target.nil?
|
43
|
+
elsif target_name.is_a?(Array)
|
44
|
+
target_name.each do |target_name|
|
45
|
+
target = parser.target_for(project, target_name)
|
46
|
+
raise "Unable to find target \"#{target_name}\"" if target.nil?
|
47
|
+
end
|
48
|
+
else
|
49
|
+
raise "Invalid target in template #{@name}"
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def generate(parser, project, context, template_definition, config)
|
55
|
+
merged_variables = config.variables_for_template_element(template_definition, @name, @variables)
|
56
|
+
|
57
|
+
base_path = merged_variables["base_path"]
|
58
|
+
base_group = project[base_path]
|
59
|
+
file_path = CodeTemplater.new.render_string(@path, context)
|
60
|
+
|
61
|
+
intermediates_groups = file_path.split("/")[0...-1]
|
62
|
+
generated_filename = file_path.split("/")[-1]
|
63
|
+
|
64
|
+
group = base_group
|
65
|
+
associate_path_to_group = !base_group.path.nil?
|
66
|
+
|
67
|
+
intermediates_groups.each do |group_name|
|
68
|
+
new_group_path = File.join(group.real_path, group_name)
|
69
|
+
existing_group = group.groups.find { |g| g.display_name == group_name }
|
70
|
+
group = existing_group || group.pf_new_group(
|
71
|
+
associate_path_to_group: associate_path_to_group,
|
72
|
+
name: group_name,
|
73
|
+
path: new_group_path
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
target_name = merged_variables["target"]
|
78
|
+
|
79
|
+
targets = []
|
80
|
+
if target_name.is_a?(String) || target_name.nil?
|
81
|
+
targets = [parser.target_for(project, target_name)]
|
82
|
+
elsif target_name.is_a?(Array)
|
83
|
+
targets = target_name.map { |name| parser.target_for(project, name) }
|
84
|
+
end
|
85
|
+
|
86
|
+
FileCreator.new.create_file_using_template_path(
|
87
|
+
template_definition.template_source_file(@template),
|
88
|
+
generated_filename,
|
89
|
+
group,
|
90
|
+
targets,
|
91
|
+
project,
|
92
|
+
context
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class FlagTemplateParameter
|
2
|
+
attr_reader :name, :short_name, :description, :template_variable_name
|
3
|
+
|
4
|
+
def initialize(parameter_template_definition_hash)
|
5
|
+
@name = parameter_template_definition_hash["flag"]
|
6
|
+
@short_name = parameter_template_definition_hash["short_name"]
|
7
|
+
@description = parameter_template_definition_hash["description"] || ""
|
8
|
+
@template_variable_name = parameter_template_definition_hash["template_variable_name"] || @name
|
9
|
+
|
10
|
+
raise "Missing flag name" if @name.nil? || @name.empty?
|
11
|
+
raise "Invalid flag template_variable_name for #{@name}" if @template_variable_name.nil? || template_variable_name.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def provided_context_keys
|
15
|
+
[@template_variable_name]
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative 'code_templater'
|
2
|
+
require_relative 'file_creator'
|
3
|
+
require_relative 'pbxproj_parser'
|
4
|
+
|
5
|
+
class GroupTemplateDefinition
|
6
|
+
def initialize(group_template_definition_hash)
|
7
|
+
@name = group_template_definition_hash["name"]
|
8
|
+
@path = group_template_definition_hash["group"]
|
9
|
+
@template = group_template_definition_hash["path"]
|
10
|
+
@variables = group_template_definition_hash["variables"] || {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def validate(parser, project, context, template_definition, config)
|
14
|
+
merged_variables = config.variables_for_template_element(template_definition, @name, @variables)
|
15
|
+
|
16
|
+
code_templater = CodeTemplater.new
|
17
|
+
pathTags = code_templater.get_unknown_context_keys_for_string(@path)
|
18
|
+
pathTags.each do |tag|
|
19
|
+
raise "Unknown parameter \"#{tag}\" in path \"#{@path}\"" if context[tag].nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
base_path = merged_variables["base_path"]
|
23
|
+
raise "Missing base_path variable" if base_path.nil?
|
24
|
+
|
25
|
+
base_group = project[base_path]
|
26
|
+
raise "Base path \"#{base_path}\" is missing" if base_group.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate(parser, project, context, template_definition, config)
|
30
|
+
merged_variables = config.variables_for_template_element(template_definition, @name, @variables)
|
31
|
+
|
32
|
+
base_path = merged_variables["base_path"]
|
33
|
+
base_group = project[base_path]
|
34
|
+
group_path = CodeTemplater.new.render_string(@path, context)
|
35
|
+
|
36
|
+
group_path = group_path.split("/")
|
37
|
+
|
38
|
+
group = base_group
|
39
|
+
associate_path_to_group = !base_group.path.nil?
|
40
|
+
|
41
|
+
group_path.each do |group_name|
|
42
|
+
new_group_path = File.join(group.real_path, group_name)
|
43
|
+
existing_group = group.groups.find { |g| g.display_name == group_name }
|
44
|
+
group = existing_group || group.pf_new_group(
|
45
|
+
associate_path_to_group: associate_path_to_group,
|
46
|
+
name: group_name,
|
47
|
+
path: new_group_path
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
file_creator = FileCreator.new
|
52
|
+
file_creator.create_empty_directory(group)
|
53
|
+
end
|
54
|
+
end
|
data/lib/ccios/pbxproj_parser.rb
CHANGED
@@ -11,63 +11,12 @@ class PBXProjParser
|
|
11
11
|
@projects = {}
|
12
12
|
end
|
13
13
|
|
14
|
-
def app_project
|
15
|
-
project_for(@config.app.project)
|
16
|
-
end
|
17
|
-
|
18
|
-
def core_project
|
19
|
-
project_for(@config.core.project)
|
20
|
-
end
|
21
|
-
|
22
|
-
def data_project
|
23
|
-
project_for(@config.data.project)
|
24
|
-
end
|
25
|
-
|
26
|
-
def presenter_group
|
27
|
-
path = @config.app.presenter.group
|
28
|
-
app_project[path]
|
29
|
-
end
|
30
|
-
|
31
|
-
def coordinator_group
|
32
|
-
path = @config.app.coordinator.group
|
33
|
-
app_project[path]
|
34
|
-
end
|
35
|
-
|
36
|
-
def interactor_group
|
37
|
-
path = @config.core.interactor.group
|
38
|
-
core_project[path]
|
39
|
-
end
|
40
|
-
|
41
|
-
def repository_core_group
|
42
|
-
path = @config.core.repository.group
|
43
|
-
core_project[path]
|
44
|
-
end
|
45
|
-
|
46
|
-
def repository_data_group
|
47
|
-
path = @config.data.repository.group
|
48
|
-
data_project[path]
|
49
|
-
end
|
50
|
-
|
51
|
-
def app_target
|
52
|
-
target_for(app_project, @config.app.target)
|
53
|
-
end
|
54
|
-
|
55
|
-
def core_target
|
56
|
-
target_for(core_project, @config.core.target)
|
57
|
-
end
|
58
|
-
|
59
|
-
def data_target
|
60
|
-
target_for(data_project, @config.data.target)
|
61
|
-
end
|
62
|
-
|
63
14
|
def save
|
64
|
-
|
65
|
-
|
66
|
-
|
15
|
+
@projects.each do |path, value|
|
16
|
+
value.save
|
17
|
+
end
|
67
18
|
end
|
68
19
|
|
69
|
-
private
|
70
|
-
|
71
20
|
def project_for(path)
|
72
21
|
module_project_path = File.join(source_path, path)
|
73
22
|
resolved_module_project_path = Dir.glob(module_project_path).first
|
@@ -78,7 +27,7 @@ class PBXProjParser
|
|
78
27
|
end
|
79
28
|
|
80
29
|
def target_for(project, target_name)
|
81
|
-
if target_name.blank?
|
30
|
+
if target_name.blank? || target_name.nil?
|
82
31
|
project.targets.find { |t| t.product_type == "com.apple.product-type.application" }
|
83
32
|
else
|
84
33
|
project.targets.find { |t| t.name == target_name }
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'file_creator'
|
2
|
+
|
3
|
+
class SnippetTemplateDefinition
|
4
|
+
def initialize(snippet_template_definition_hash)
|
5
|
+
@name = snippet_template_definition_hash["name"]
|
6
|
+
@template = snippet_template_definition_hash["template"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def validate(template_definition)
|
10
|
+
expected_context_keys = template_definition.provided_context_keys
|
11
|
+
file_creator = FileCreator.new
|
12
|
+
contentTags = file_creator.get_unknown_template_tags_for(template_definition.template_source_file(@template))
|
13
|
+
contentTags.each do |tag|
|
14
|
+
raise "Unknown parameter \"#{tag}\" in template \"#{@template}\"" unless expected_context_keys.include?(tag)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate(context, template_definition)
|
19
|
+
|
20
|
+
file_creator = FileCreator.new
|
21
|
+
file_creator.print_file_content_using_template(
|
22
|
+
@name,
|
23
|
+
template_definition.template_source_file(@template),
|
24
|
+
context
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require_relative 'file_creator'
|
4
|
+
require_relative 'pbxproj_parser'
|
5
|
+
require_relative 'argument_template_parameter'
|
6
|
+
require_relative 'flag_template_parameter'
|
7
|
+
require_relative 'file_template_definition'
|
8
|
+
require_relative 'group_template_definition'
|
9
|
+
require_relative 'snippet_template_definition'
|
10
|
+
|
11
|
+
class TemplateDefinition
|
12
|
+
|
13
|
+
attr_reader :name, :description, :template_path, :template_file_source, :parameters, :variables
|
14
|
+
|
15
|
+
def self.parse(template_path)
|
16
|
+
template_definition = File.join(template_path, 'template.yml')
|
17
|
+
if File.exist?(template_definition)
|
18
|
+
template_definition = YAML.load_file(template_definition)
|
19
|
+
self.new template_definition, template_path
|
20
|
+
else
|
21
|
+
puts "Template #{template_path} is invalid: file #{template_definition} not found."
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(template_definition_hash, template_path)
|
27
|
+
@template_definition_hash = template_definition_hash
|
28
|
+
@template_path = template_path
|
29
|
+
|
30
|
+
@name = template_definition_hash["name"]
|
31
|
+
@description = template_definition_hash["description"] || ""
|
32
|
+
@variables = template_definition_hash["variables"] || {}
|
33
|
+
|
34
|
+
@parameters = template_definition_hash["parameters"].map { |hash|
|
35
|
+
next ArgumentTemplateParameter.new(hash) unless hash["argument"].nil?
|
36
|
+
next FlagTemplateParameter.new(hash) unless hash["flag"].nil?
|
37
|
+
}.compact
|
38
|
+
|
39
|
+
@generated_elements = template_definition_hash["generated_elements"].map { |hash|
|
40
|
+
next FileTemplateDefinition.new(hash) unless hash["file"].nil?
|
41
|
+
next GroupTemplateDefinition.new(hash) unless hash["group"].nil?
|
42
|
+
next nil
|
43
|
+
}.compact
|
44
|
+
|
45
|
+
if template_definition_hash["code_snippets"].nil?
|
46
|
+
@snippets = []
|
47
|
+
else
|
48
|
+
@snippets = template_definition_hash["code_snippets"].map { |hash|
|
49
|
+
SnippetTemplateDefinition.new(hash)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
@template_file_source = template_definition_hash["template_file_source"] || {}
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate(parser, options, config)
|
57
|
+
|
58
|
+
raise "Error: missing name in template" if @name.nil?
|
59
|
+
raise "Error: invalid template name" unless @name.is_a? String
|
60
|
+
|
61
|
+
merged_variables = config.variables_for_template(self)
|
62
|
+
project_path = merged_variables["project"]
|
63
|
+
|
64
|
+
project = parser.project_for(project_path)
|
65
|
+
raise "Error: Unable to find project \"#{project_path}\"" if project.nil?
|
66
|
+
|
67
|
+
@template_file_source.each do |file_template_name, path|
|
68
|
+
raise "Missing template source file for \"#{file_template_name}\"" unless File.exist?(self.template_source_file(file_template_name))
|
69
|
+
end
|
70
|
+
|
71
|
+
options = agrument_transformed_options(options)
|
72
|
+
|
73
|
+
@generated_elements.each do |generated_element|
|
74
|
+
generated_element.validate(parser, project, options, self, config)
|
75
|
+
end
|
76
|
+
|
77
|
+
@snippets.each do |snippet|
|
78
|
+
snippet.validate(self)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def template_source_file(name)
|
83
|
+
raise "Unknown template file #{name}" if @template_file_source[name].nil?
|
84
|
+
File.join(@template_path, @template_file_source[name])
|
85
|
+
end
|
86
|
+
|
87
|
+
def provided_context_keys
|
88
|
+
@parameters.flat_map { |p| p.provided_context_keys }.to_set
|
89
|
+
end
|
90
|
+
|
91
|
+
def generate(parser, options, config)
|
92
|
+
|
93
|
+
options = agrument_transformed_options(options)
|
94
|
+
|
95
|
+
merged_variables = config.variables_for_template(self)
|
96
|
+
project_path = merged_variables["project"]
|
97
|
+
|
98
|
+
project = parser.project_for project_path
|
99
|
+
|
100
|
+
@generated_elements.each do |element|
|
101
|
+
element.generate(parser, project, options, self, config)
|
102
|
+
end
|
103
|
+
|
104
|
+
@snippets.each do |snippet|
|
105
|
+
snippet.generate(options, self)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def agrument_transformed_options(options)
|
110
|
+
@parameters.select { |p| p.is_a? ArgumentTemplateParameter }.each do |argument|
|
111
|
+
options = argument.update_context(options)
|
112
|
+
end
|
113
|
+
options
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -10,6 +10,7 @@ import Foundation
|
|
10
10
|
import ADCoordinator
|
11
11
|
|
12
12
|
{{#generate_delegate}}
|
13
|
+
@MainActor
|
13
14
|
protocol {{name}}CoordinatorDelegate: AnyObject {
|
14
15
|
|
15
16
|
}
|
@@ -23,8 +24,10 @@ class {{name}}Coordinator: Coordinator {
|
|
23
24
|
private let dependencyProvider: ApplicationDependencyProvider
|
24
25
|
private unowned var navigationController: UINavigationController
|
25
26
|
|
26
|
-
init(
|
27
|
-
|
27
|
+
init(
|
28
|
+
navigationController: UINavigationController,
|
29
|
+
dependencyProvider: ApplicationDependencyProvider
|
30
|
+
) {
|
28
31
|
self.navigationController = navigationController
|
29
32
|
self.dependencyProvider = dependencyProvider
|
30
33
|
}
|