ccios 2.1.0 → 4.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c88ba12634db23d2c4e956b6f03b721a127dbbc49897c49cd2b9fe15a295704b
4
- data.tar.gz: eadb6778ddd52ce31071e3f3addc37c523fcfb1272a00f212bad6eb73d0e089d
3
+ metadata.gz: 53f92f6691a68ed285f5fd2a9f917c361ebf291a68177e86063804c0dd364d77
4
+ data.tar.gz: fb1dcd2a753b36379c840c22fb33cc2542e455d6c528b7bc05504dfd3df4d1b8
5
5
  SHA512:
6
- metadata.gz: 8cf76e8f0ed4b932cf9d653bc0e30fe970806025b48ae6490232b37f3cc62cd2ce756f4e1a9560603f9d06338e3ffb85c388797c975a80b3b54974f8205b6431
7
- data.tar.gz: 9753729e4574c4f30a047168590b77195cb3f51566179b1c98cadc97320b47e3b7d3dd3547d8c082b64b01419c5be2cd329a1ebd01e2dcfc45cefadf3857e5e7
6
+ metadata.gz: 9614e307beb251a22efbfa42051cb1eaf436925dbfdba7adc2e18ee26b95728a5c034d6b398d548ae3566bf33d294ec31f57cd7ca6c98c35faff074fe00a712f
7
+ data.tar.gz: 217096830d6e21a0d7b11295eace1309ff935df07443f5072760d380566f19a180de1b769d0f195b025a89ad239abd660b057ce125d4709dd67c7a201f9c9591
@@ -0,0 +1,20 @@
1
+ name: Ruby
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v1
12
+ - name: Set up Ruby 2.6
13
+ uses: actions/setup-ruby@v1
14
+ with:
15
+ ruby-version: 2.6.x
16
+ - name: Build and test with Rake
17
+ run: |
18
+ gem install bundler
19
+ bundle install --jobs 4 --retry 3
20
+ bundle exec rake
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
- ccios-*.gem
1
+ ccios-*.gem
2
+ xcuserdata
3
+ .DS_Store
@@ -0,0 +1,36 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+ `ADUtils` adheres to [Semantic Versioning](http://semver.org/).
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [4.0.0]
8
+
9
+ ### Added
10
+ - Use `ADCoordinator` dependency in coordinator files
11
+
12
+ ### Fixed
13
+ - Use `active_support` instead of `rails` dependency
14
+ - Add dev dependencies
15
+
16
+ ## [3.0.0]
17
+
18
+ ### Fixed
19
+ - Use `ApplicationDependencyProvider` in Coordinator
20
+ - Updated by [Denis Poifol](https://github.com/denisPoifol) in Pull Request [#10](https://github.com/felginep/ccios/pull/10)
21
+
22
+ ## [2.3.1]
23
+
24
+ ### Fixed
25
+ - Import `Core` in Repository implementations
26
+ - Updated by [Hervé Béranger](https://github.com/hberenger) in Pull Request [#11](https://github.com/felginep/ccios/pull/11)
27
+
28
+ ## [2.3.0]
29
+
30
+ ### Added
31
+ - Add possibilty to specify target in `.ccios.yml`
32
+
33
+ ## [2.2.0]
34
+
35
+ ### Added
36
+ - Create configuration with optional `.ccios.yml` file
@@ -1,128 +1,49 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ccios (1.0.3)
4
+ ccios (4.0.0)
5
+ activesupport (> 4)
5
6
  mustache (~> 1.0)
6
- rails
7
7
  xcodeproj (~> 1.4)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- CFPropertyList (2.3.5)
13
- actioncable (5.1.3)
14
- actionpack (= 5.1.3)
15
- nio4r (~> 2.0)
16
- websocket-driver (~> 0.6.1)
17
- actionmailer (5.1.3)
18
- actionpack (= 5.1.3)
19
- actionview (= 5.1.3)
20
- activejob (= 5.1.3)
21
- mail (~> 2.5, >= 2.5.4)
22
- rails-dom-testing (~> 2.0)
23
- actionpack (5.1.3)
24
- actionview (= 5.1.3)
25
- activesupport (= 5.1.3)
26
- rack (~> 2.0)
27
- rack-test (~> 0.6.3)
28
- rails-dom-testing (~> 2.0)
29
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
30
- actionview (5.1.3)
31
- activesupport (= 5.1.3)
32
- builder (~> 3.1)
33
- erubi (~> 1.4)
34
- rails-dom-testing (~> 2.0)
35
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
36
- activejob (5.1.3)
37
- activesupport (= 5.1.3)
38
- globalid (>= 0.3.6)
39
- activemodel (5.1.3)
40
- activesupport (= 5.1.3)
41
- activerecord (5.1.3)
42
- activemodel (= 5.1.3)
43
- activesupport (= 5.1.3)
44
- arel (~> 8.0)
45
- activesupport (5.1.3)
12
+ CFPropertyList (3.0.2)
13
+ activesupport (6.0.3.3)
46
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
47
- i18n (~> 0.7)
15
+ i18n (>= 0.7, < 2)
48
16
  minitest (~> 5.1)
49
17
  tzinfo (~> 1.1)
50
- arel (8.0.0)
51
- builder (3.2.3)
52
- claide (1.0.2)
18
+ zeitwerk (~> 2.2, >= 2.2.2)
19
+ atomos (0.1.3)
20
+ claide (1.0.3)
53
21
  colored2 (3.1.2)
54
- concurrent-ruby (1.0.5)
55
- erubi (1.6.1)
56
- globalid (0.4.0)
57
- activesupport (>= 4.2.0)
58
- i18n (0.8.6)
59
- loofah (2.0.3)
60
- nokogiri (>= 1.5.9)
61
- mail (2.6.6)
62
- mime-types (>= 1.16, < 4)
63
- method_source (0.8.2)
64
- mime-types (3.1)
65
- mime-types-data (~> 3.2015)
66
- mime-types-data (3.2016.0521)
67
- mini_portile2 (2.2.0)
68
- minitest (5.10.3)
69
- mustache (1.0.5)
70
- nanaimo (0.2.3)
71
- nio4r (2.1.0)
72
- nokogiri (1.8.0)
73
- mini_portile2 (~> 2.2.0)
74
- rack (2.0.3)
75
- rack-test (0.6.3)
76
- rack (>= 1.0)
77
- rails (5.1.3)
78
- actioncable (= 5.1.3)
79
- actionmailer (= 5.1.3)
80
- actionpack (= 5.1.3)
81
- actionview (= 5.1.3)
82
- activejob (= 5.1.3)
83
- activemodel (= 5.1.3)
84
- activerecord (= 5.1.3)
85
- activesupport (= 5.1.3)
86
- bundler (>= 1.3.0)
87
- railties (= 5.1.3)
88
- sprockets-rails (>= 2.0.0)
89
- rails-dom-testing (2.0.3)
90
- activesupport (>= 4.2.0)
91
- nokogiri (>= 1.6)
92
- rails-html-sanitizer (1.0.3)
93
- loofah (~> 2.0)
94
- railties (5.1.3)
95
- actionpack (= 5.1.3)
96
- activesupport (= 5.1.3)
97
- method_source
98
- rake (>= 0.8.7)
99
- thor (>= 0.18.1, < 2.0)
100
- rake (12.0.0)
101
- sprockets (3.7.1)
22
+ concurrent-ruby (1.1.7)
23
+ i18n (1.8.5)
102
24
  concurrent-ruby (~> 1.0)
103
- rack (> 1, < 3)
104
- sprockets-rails (3.2.0)
105
- actionpack (>= 4.0)
106
- activesupport (>= 4.0)
107
- sprockets (>= 3.0.0)
108
- thor (0.20.0)
25
+ minitest (5.14.2)
26
+ mustache (1.1.1)
27
+ nanaimo (0.3.0)
28
+ rake (12.3.3)
109
29
  thread_safe (0.3.6)
110
- tzinfo (1.2.3)
30
+ tzinfo (1.2.7)
111
31
  thread_safe (~> 0.1)
112
- websocket-driver (0.6.5)
113
- websocket-extensions (>= 0.1.0)
114
- websocket-extensions (0.1.2)
115
- xcodeproj (1.5.1)
116
- CFPropertyList (~> 2.3.3)
32
+ xcodeproj (1.18.0)
33
+ CFPropertyList (>= 2.3.3, < 4.0)
34
+ atomos (~> 0.1.3)
117
35
  claide (>= 1.0.2, < 2.0)
118
36
  colored2 (~> 3.1)
119
- nanaimo (~> 0.2.3)
37
+ nanaimo (~> 0.3.0)
38
+ zeitwerk (2.4.0)
120
39
 
121
40
  PLATFORMS
122
41
  ruby
123
42
 
124
43
  DEPENDENCIES
125
44
  ccios!
45
+ minitest (~> 5.11)
46
+ rake (~> 12.3)
126
47
 
127
48
  BUNDLED WITH
128
- 1.12.3
49
+ 1.17.3
@@ -0,0 +1,11 @@
1
+ build:
2
+ gem build ccios.gemspec
3
+
4
+ install: clean build
5
+ gem install ccios-*.gem
6
+
7
+ clean:
8
+ rm -f ccios-*.gem
9
+
10
+ tests:
11
+ bundle exec rake test
data/README.md CHANGED
@@ -14,7 +14,7 @@ gem install ./ccios-x.x.x.gem
14
14
  ```
15
15
 
16
16
  To run the tests run:
17
- ```rake test```
17
+ ```bundle exec rake test```
18
18
 
19
19
  # How to use
20
20
 
@@ -101,3 +101,61 @@ The following structure is created for you in the Xcode project:
101
101
  +-- Coordinator/
102
102
  | +-- ExampleCoordinator
103
103
  ```
104
+
105
+ ## Configuration
106
+
107
+
108
+ Each project is different. You can configure the groups to use in the xcodeproj for the new files.
109
+
110
+ Create a file `.ccios.yml` at the root of your project.
111
+
112
+ By default, if no file is present, the following configuration will be used:
113
+ ```
114
+ app:
115
+ project: MyProject.xcodeproj
116
+ presenter:
117
+ group: Classes/App
118
+ coordinator:
119
+ group: Classes/Coordinator
120
+
121
+ core:
122
+ project: MyProject.xcodeproj
123
+ interactor:
124
+ group: Classes/Core/Interactor
125
+ repository:
126
+ group: Classes/Core/Data
127
+
128
+ data:
129
+ project: MyProject.xcodeproj
130
+ repository:
131
+ group: Classes/Data
132
+ ```
133
+
134
+ But you could imagine more complex project structures with multiple xcodeproj:
135
+ ```
136
+ app:
137
+ project: MyProject/MyProject.xcodeproj
138
+ target: MyProject # optional
139
+ presenter:
140
+ group: Classes/App
141
+ coordinator:
142
+ group: Classes/Coordinator
143
+
144
+ core:
145
+ project: MyProjectCore/MyProjectCore.xcodeproj
146
+ target: MyProjectCore # optional
147
+ interactor:
148
+ group: MyProjectCore/Interactors
149
+ repository:
150
+ group: MyProjectCore/Repository
151
+
152
+ data:
153
+ project: MyProjectData/MyProjectData.xcodeproj
154
+ target: MyProjectData # optional
155
+ repository:
156
+ group: MyProjectData/Sources/Repositories
157
+
158
+ ```
159
+
160
+ *Note*: The path of the new files will be infered from the path of the group. It works with *Group with folder* and *Group without folder* in Xcode.
161
+
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ccios'
3
- s.version = '2.1.0'
3
+ s.version = '4.0.0'
4
4
  s.executables << 'ccios'
5
5
  s.date = '2016-08-03'
6
6
  s.summary = "Clean Code iOS Generator"
@@ -11,7 +11,10 @@ Gem::Specification.new do |s|
11
11
  s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
12
12
  s.homepage = 'http://rubygems.org/gems/hola'
13
13
  s.license = 'MIT'
14
+ s.add_dependency 'activesupport', '> 4'
14
15
  s.add_dependency 'xcodeproj', '~> 1.4'
15
- s.add_dependency 'rails', '~> 5.1'
16
16
  s.add_dependency "mustache", "~> 1.0"
17
+
18
+ s.add_development_dependency 'rake', '~> 12.3'
19
+ s.add_development_dependency 'minitest', '~> 5.11'
17
20
  end
@@ -1,11 +1,12 @@
1
1
  require 'date'
2
2
  require 'xcodeproj'
3
3
  require 'optparse'
4
- require 'rails' # for underscore method used in code_templater.rb
4
+ require 'active_support'
5
5
  require 'ccios/presenter_generator'
6
6
  require 'ccios/coordinator_generator'
7
7
  require 'ccios/interactor_generator'
8
8
  require 'ccios/repository_generator'
9
+ require 'ccios/config'
9
10
 
10
11
  options = {}
11
12
  OptionParser.new do |opts|
@@ -35,31 +36,32 @@ OptionParser.new do |opts|
35
36
  end.parse!
36
37
 
37
38
  source_path = Dir.pwd
38
- parser = PBXProjParser.new source_path
39
+ config = Config.parse ".ccios.yml"
40
+ parser = PBXProjParser.new(source_path, config)
39
41
 
40
42
  if options[:presenter]
41
43
  presenter_name = options[:presenter]
42
- presenter_generator = PresenterGenerator.new parser
44
+ presenter_generator = PresenterGenerator.new(parser, config)
43
45
  generator_options = {generate_delegate: options[:generate_delegate]}
44
46
  presenter_generator.generate(presenter_name, generator_options)
45
47
  end
46
48
 
47
49
  if options[:coordinator]
48
50
  coordinator_name = options[:coordinator]
49
- coordinator_generator = CoordinatorGenerator.new parser
51
+ coordinator_generator = CoordinatorGenerator.new(parser, config)
50
52
  generator_options = {generate_delegate: options[:generate_delegate]}
51
53
  coordinator_generator.generate(coordinator_name, generator_options)
52
54
  end
53
55
 
54
56
  if options[:interactor]
55
57
  interactor_name = options[:interactor]
56
- interactor_generator = InteractorGenerator.new parser
58
+ interactor_generator = InteractorGenerator.new(parser, config)
57
59
  interactor_generator.generate(interactor_name)
58
60
  end
59
61
 
60
62
  if options[:repository]
61
63
  repository_name = options[:repository]
62
- repository_generator = RepositoryGenerator.new parser
64
+ repository_generator = RepositoryGenerator.new(parser, config)
63
65
  repository_generator.generate(repository_name)
64
66
  end
65
67
 
@@ -1,5 +1,5 @@
1
1
  require 'mustache'
2
- require 'rails'
2
+ require 'active_support/core_ext/string'
3
3
 
4
4
  class CodeTemplater
5
5
  def initialize(options = {})
@@ -0,0 +1,116 @@
1
+ require 'yaml'
2
+
3
+ class Config
4
+
5
+ attr_reader :app, :core, :data
6
+
7
+ def self.parse(source_path)
8
+ if File.exist?(source_path)
9
+ config = YAML.load_file(source_path)
10
+ self.new config, source_path
11
+ else
12
+ puts "File #{source_path} does not exists. Using default config."
13
+ self.default
14
+ end
15
+ end
16
+
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
+ }
35
+ end
36
+
37
+ def self.default
38
+ self.new default_config_hash
39
+ end
40
+
41
+ def initialize(config_hash, source_path = nil)
42
+ @source_path = source_path
43
+ validate config_hash
44
+ @app = AppConfig.new config_hash["app"]
45
+ @core = CoreConfig.new config_hash["core"]
46
+ @data = DataConfig.new config_hash["data"]
47
+ end
48
+
49
+ def validate(hash)
50
+ validate_path hash, "app.project"
51
+ validate_path hash, "app.presenter.group"
52
+ validate_path hash, "app.coordinator.group"
53
+
54
+ validate_path hash, "core.project"
55
+ validate_path hash, "core.interactor.group"
56
+ validate_path hash, "core.repository.group"
57
+
58
+ validate_path hash, "data.project"
59
+ validate_path hash, "data.repository.group"
60
+ end
61
+
62
+ def validate_path(hash, path)
63
+ components = path.split(".")
64
+ keys = []
65
+ components.each do |component|
66
+ hash = hash[component]
67
+ keys << component
68
+ if hash.nil?
69
+ message = "Key \"#{keys.join(".")}\" is missing"
70
+ message += " in #{@source_path}" unless @source_path.nil?
71
+ raise message
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ class AppConfig
78
+ attr_reader :project, :target, :presenter, :coordinator
79
+
80
+ def initialize(hash)
81
+ @project = hash["project"]
82
+ @target = hash["target"]
83
+ @presenter = ObjectConfig.new hash["presenter"]
84
+ @coordinator = ObjectConfig.new hash["coordinator"]
85
+ end
86
+ end
87
+
88
+ class CoreConfig
89
+ attr_reader :project, :target, :interactor, :repository
90
+
91
+ def initialize(hash)
92
+ @project = hash["project"]
93
+ @target = hash["target"]
94
+ @interactor = ObjectConfig.new hash["interactor"]
95
+ @repository = ObjectConfig.new hash["repository"]
96
+ end
97
+ end
98
+
99
+ class DataConfig
100
+ attr_reader :project, :target, :repository
101
+
102
+ def initialize(hash)
103
+ @project = hash["project"]
104
+ @target = hash["target"]
105
+ @repository = ObjectConfig.new hash["repository"]
106
+ end
107
+ end
108
+
109
+ class ObjectConfig
110
+
111
+ attr_reader :group
112
+
113
+ def initialize(hash)
114
+ @group = hash["group"]
115
+ end
116
+ end
@@ -3,14 +3,15 @@ require_relative "pbxproj_parser"
3
3
 
4
4
  class CoordinatorGenerator
5
5
 
6
- def initialize(parser)
6
+ def initialize(parser, config)
7
7
  @parser = parser
8
+ @config = config
8
9
  end
9
10
 
10
11
  def generate(coordinator_name, options = {})
11
12
  coordinator_group = @parser.coordinator_group
12
- file_creator = FileCreator.new(@parser.source_path, options)
13
- target = @parser.main_target
13
+ file_creator = FileCreator.new(options)
14
+ target = @parser.app_target
14
15
  file_creator.create_file(coordinator_name, 'Coordinator', coordinator_group, target)
15
16
  end
16
17
  end
@@ -1,9 +1,18 @@
1
1
  require_relative 'code_templater'
2
+ require 'fileutils'
3
+ require 'logger'
2
4
 
3
5
  class FileCreator
4
- def initialize(source_path, options = {})
5
- @source_path = source_path
6
- @classes_path = source_path + '/Classes'
6
+
7
+ def self.logger
8
+ @@logger ||= create_logger
9
+ end
10
+
11
+ def logger
12
+ FileCreator.logger
13
+ end
14
+
15
+ def initialize(options = {})
7
16
  @options = options
8
17
  end
9
18
 
@@ -17,13 +26,15 @@ class FileCreator
17
26
  end
18
27
 
19
28
  def git_username
20
- `cd #{@source_path}; git config user.name`.strip
29
+ `git config user.name`.strip
21
30
  end
22
31
 
23
32
  def create_file(prefix, suffix, group, target)
24
- file_path = @classes_path + '/' + prefix + suffix + '.swift'
33
+ file_path = File.join(group.real_path, prefix + suffix + '.swift')
25
34
 
26
- raise "File #{file_path} already exists" if File.exists?(file_path)
35
+ raise "File #{file_path} already exists" if File.exist?(file_path)
36
+ dirname = File.dirname(file_path)
37
+ FileUtils.mkdir_p dirname unless File.directory?(dirname)
27
38
  file = File.new(file_path, 'w')
28
39
 
29
40
  templater_options = templater_options(target)
@@ -36,14 +47,30 @@ class FileCreator
36
47
  target.add_file_references([file_ref])
37
48
  end
38
49
 
50
+ def create_empty_directory(group)
51
+ dirname = group.real_path
52
+ FileUtils.mkdir_p dirname unless File.directory?(dirname)
53
+
54
+ git_keep_path = File.join(dirname, ".gitkeep")
55
+ FileUtils.touch(git_keep_path) if Dir.empty?(dirname)
56
+ end
57
+
39
58
  def print_file_content(prefix, suffix)
40
- file_path = @classes_path + '/' + suffix + '.swift'
59
+ file_name = suffix + '.swift'
41
60
 
42
61
  code_templater = CodeTemplater.new(@options)
43
62
  template = code_templater.content_for_suffix(prefix, suffix)
44
63
 
45
- puts "Add this snippet to #{file_path}"
46
- puts template
47
- puts "\n"
64
+ logger.info "Add this snippet to #{file_name}"
65
+ logger.info template
66
+ end
67
+
68
+ private
69
+
70
+ def self.create_logger
71
+ logger = Logger.new(STDOUT)
72
+ logger.level = Logger::DEBUG
73
+ logger.formatter = proc { |severity, datetime, progname, msg| msg + "\n" }
74
+ logger
48
75
  end
49
76
  end
@@ -3,18 +3,23 @@ require_relative "pbxproj_parser"
3
3
 
4
4
  class InteractorGenerator
5
5
 
6
- def initialize(parser)
6
+ def initialize(parser, config)
7
7
  @parser = parser
8
+ @config = config
8
9
  end
9
10
 
10
11
  def generate(interactor_name, options = {})
11
12
  interactor_group = @parser.interactor_group
12
13
  new_group_name = "#{interactor_name}Interactor"
14
+
15
+ associate_path_to_group = !interactor_group.path.nil?
16
+
13
17
  raise "[Error] Group #{new_group_name} already exists in #{app_group.display_name}" if interactor_group[new_group_name]
14
- new_group = interactor_group.new_group(new_group_name)
18
+ new_group_path = File.join(interactor_group.real_path, new_group_name)
19
+ new_group = interactor_group.new_group(new_group_name, associate_path_to_group ? new_group_path : nil)
15
20
 
16
- file_creator = FileCreator.new(@parser.source_path, options)
17
- target = @parser.main_target
21
+ file_creator = FileCreator.new(options)
22
+ target = @parser.core_target
18
23
  file_creator.create_file(interactor_name, 'Interactor', new_group, target)
19
24
  file_creator.create_file(interactor_name, 'InteractorImplementation', new_group, target)
20
25
 
@@ -1,50 +1,87 @@
1
1
  require 'xcodeproj'
2
+ require 'active_support/core_ext/object/blank'
2
3
 
3
4
  class PBXProjParser
4
5
 
5
- attr_accessor :source_path, :project
6
+ attr_accessor :source_path
6
7
 
7
- def initialize(source_path)
8
+ def initialize(source_path, config)
8
9
  @source_path = source_path
9
- if project_path.nil?
10
- raise "[Error] There is no xcodeproj at path #{@source_path}"
11
- end
12
- @project = Xcodeproj::Project.open(project_path)
13
- end
14
-
15
- def project_path
16
- Dir.glob("#{@source_path}/*.xcodeproj").first
10
+ @config = config
11
+ @projects = {}
17
12
  end
18
13
 
19
- def main_target
20
- @project.targets.first
14
+ def app_project
15
+ project_for(@config.app.project)
21
16
  end
22
17
 
23
- def classes_group
24
- @project.groups.find { |g| g.display_name === "Classes" }
18
+ def core_project
19
+ project_for(@config.core.project)
25
20
  end
26
21
 
27
- def app_group
28
- classes_group["App"]
22
+ def data_project
23
+ project_for(@config.data.project)
29
24
  end
30
25
 
31
- def core_group
32
- classes_group["Core"]
26
+ def presenter_group
27
+ path = @config.app.presenter.group
28
+ app_project[path]
33
29
  end
34
30
 
35
31
  def coordinator_group
36
- classes_group["Coordinator"]
32
+ path = @config.app.coordinator.group
33
+ app_project[path]
37
34
  end
38
35
 
39
36
  def interactor_group
40
- core_group["Interactor"]
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)
41
53
  end
42
54
 
43
- def data_group
44
- classes_group["Data"]
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)
45
61
  end
46
62
 
47
63
  def save
48
- @project.save
64
+ app_project.save
65
+ core_project.save
66
+ data_project.save
67
+ end
68
+
69
+ private
70
+
71
+ def project_for(path)
72
+ module_project_path = File.join(source_path, path)
73
+ resolved_module_project_path = Dir.glob(module_project_path).first
74
+ if !File.exist?(resolved_module_project_path)
75
+ raise "[Error] There is no xcodeproj at path #{module_project_path}"
76
+ end
77
+ @projects[module_project_path] ||= Xcodeproj::Project.open(resolved_module_project_path)
78
+ end
79
+
80
+ def target_for(project, target_name)
81
+ if target_name.blank?
82
+ project.targets.find { |t| t.product_type == "com.apple.product-type.application" }
83
+ else
84
+ project.targets.find { |t| t.name == target_name }
85
+ end
49
86
  end
50
87
  end
@@ -3,27 +3,43 @@ require_relative "pbxproj_parser"
3
3
 
4
4
  class PresenterGenerator
5
5
 
6
- def initialize(parser)
6
+ def initialize(parser, config)
7
7
  @parser = parser
8
+ @config = config
8
9
  end
9
10
 
10
11
  def generate(presenter_name, options = {})
11
- app_group = @parser.app_group
12
+ app_group = @parser.presenter_group
13
+
14
+ associate_path_to_group = !app_group.path.nil?
15
+
12
16
  raise "[Error] Group #{presenter_name} already exists in #{app_group.display_name}" if app_group[presenter_name]
13
- new_group = app_group.new_group(presenter_name)
17
+ new_group_path = File.join(app_group.real_path, presenter_name)
18
+ new_group = app_group.new_group(presenter_name, associate_path_to_group ? new_group_path : nil)
19
+
20
+ ui_group_path = File.join(new_group_path, "UI")
21
+ ui_group = new_group.new_group("UI", associate_path_to_group ? ui_group_path : nil)
22
+
23
+ view_group_path = File.join(ui_group_path, "View")
24
+ view_group = ui_group.new_group("View", associate_path_to_group ? view_group_path : nil)
25
+
26
+ view_controller_group_path = File.join(ui_group_path, "ViewController")
27
+ view_controller_group = ui_group.new_group("ViewController", associate_path_to_group ? view_controller_group_path : nil)
28
+
29
+ presenter_group_path = File.join(new_group_path, "Presenter")
30
+ presenter_group = new_group.new_group("Presenter", associate_path_to_group ? presenter_group_path : nil)
14
31
 
15
- ui_group = new_group.new_group("UI")
16
- ui_group.new_group("View")
17
- view_controller_group = ui_group.new_group("ViewController")
18
- presenter_group = new_group.new_group("Presenter")
19
- model_group = new_group.new_group("Model")
32
+ model_group_path = File.join(new_group_path, "Model")
33
+ model_group = new_group.new_group("Model", associate_path_to_group ? model_group_path : nil)
20
34
 
21
- file_creator = FileCreator.new(@parser.source_path, options)
22
- target = @parser.main_target
35
+ file_creator = FileCreator.new(options)
36
+ target = @parser.app_target
23
37
  file_creator.create_file(presenter_name, 'ViewContract', ui_group, target)
24
38
  file_creator.create_file(presenter_name, 'ViewController', view_controller_group, target)
25
39
  file_creator.create_file(presenter_name, 'Presenter', presenter_group, target)
26
40
  file_creator.create_file(presenter_name, 'PresenterImplementation', presenter_group, target)
41
+ file_creator.create_empty_directory(model_group)
42
+ file_creator.create_empty_directory(view_group)
27
43
 
28
44
  file_creator.print_file_content(presenter_name, 'DependencyProvider')
29
45
  file_creator.print_file_content(presenter_name, 'PresenterAssembly')
@@ -3,24 +3,32 @@ require_relative "pbxproj_parser"
3
3
 
4
4
  class RepositoryGenerator
5
5
 
6
- def initialize(parser)
6
+ def initialize(parser, config)
7
7
  @parser = parser
8
+ @config = config
8
9
  end
9
10
 
10
11
  def generate(repository_name, options = {})
11
- core_group = @parser.core_group
12
- core_data_group = core_group["Data"]
13
- data_group = @parser.data_group
14
- raise "[Error] Group #{repository_name} already exists in #{core_data_group.display_name}" if core_data_group[repository_name]
15
- core_data_new_group = core_data_group.new_group(repository_name)
12
+ core_group = @parser.repository_core_group
13
+ data_group = @parser.repository_data_group
14
+
15
+ raise "[Error] Group #{repository_name} already exists in #{core_group.display_name}" if core_group[repository_name]
16
+ associate_path_to_group = !core_group.path.nil?
17
+ core_data_new_group_path = File.join(core_group.real_path, repository_name)
18
+ core_data_new_group = core_group.new_group(repository_name, associate_path_to_group ? core_data_new_group_path : nil)
16
19
 
17
20
  raise "[Error] Group #{repository_name} already exists in #{data_group.display_name}" if data_group[repository_name]
18
- data_new_group = data_group.new_group(repository_name)
21
+ associate_path_to_group = !data_group.path.nil?
22
+ data_new_group_path = File.join(data_group.real_path, repository_name)
23
+ data_new_group = data_group.new_group(repository_name, associate_path_to_group ? data_new_group_path : nil)
24
+
25
+ file_creator = FileCreator.new(options)
26
+ core_target = @parser.core_target
27
+ file_creator.create_file(repository_name, 'Repository', core_data_new_group, core_target)
19
28
 
20
- file_creator = FileCreator.new(@parser.source_path, options)
21
- target = @parser.main_target
22
- file_creator.create_file(repository_name, 'Repository', core_data_new_group, target)
23
- file_creator.create_file(repository_name, 'RepositoryImplementation', data_new_group, target)
29
+ file_creator = FileCreator.new(options)
30
+ data_target = @parser.data_target
31
+ file_creator.create_file(repository_name, 'RepositoryImplementation', data_new_group, data_target)
24
32
 
25
33
  file_creator.print_file_content(repository_name, 'RepositoryAssembly')
26
34
  end
@@ -7,6 +7,7 @@
7
7
  //
8
8
 
9
9
  import Foundation
10
+ import ADCoordinator
10
11
 
11
12
  {{#generate_delegate}}
12
13
  protocol {{name}}CoordinatorDelegate: AnyObject {
@@ -19,15 +20,20 @@ class {{name}}Coordinator: Coordinator {
19
20
  {{#generate_delegate}}
20
21
  weak var delegate: {{name}}CoordinatorDelegate?
21
22
  {{/generate_delegate}}
22
- private let navigationController: UINavigationController
23
+ private let dependencyProvider: ApplicationDependencyProvider
24
+ private unowned var navigationController: UINavigationController
23
25
 
24
- init(navigationController: UINavigationController) {
26
+ init(navigationController: UINavigationController,
27
+ dependencyProvider: ApplicationDependencyProvider) {
25
28
  self.navigationController = navigationController
29
+ self.dependencyProvider = dependencyProvider
26
30
  }
27
31
 
28
32
  // MARK: - Public
29
33
 
30
34
  func start() {
31
-
35
+ let viewController = UIViewController()
36
+ navigationController.pushViewController(viewController, animated: false)
37
+ bindToLifecycle(of: viewController)
32
38
  }
33
39
  }
@@ -8,6 +8,6 @@
8
8
 
9
9
  import Foundation
10
10
 
11
- protocol {{name}}Interactor {
11
+ public protocol {{name}}Interactor {
12
12
  func execute()
13
13
  }
@@ -1,4 +1,4 @@
1
- container.register({{name}}Interactor.self) { r in
1
+ container.register({{name}}Interactor.self) { _ in
2
2
  {{name}}InteractorImplementation(
3
3
 
4
4
  )
@@ -8,11 +8,15 @@
8
8
 
9
9
  import Foundation
10
10
 
11
- class {{name}}InteractorImplementation: {{name}}Interactor {
11
+ public class {{name}}InteractorImplementation: {{name}}Interactor {
12
+
13
+ public init() {
14
+
15
+ }
12
16
 
13
17
  // MARK: - {{name}}Interactor
14
18
 
15
- func execute() {
19
+ public func execute() {
16
20
 
17
21
  }
18
22
  }
@@ -8,6 +8,6 @@
8
8
 
9
9
  import Foundation
10
10
 
11
- protocol {{name}}Repository {
11
+ public protocol {{name}}Repository {
12
12
 
13
13
  }
@@ -1,5 +1,6 @@
1
- container.register({{name}}Repository.self) { r in
1
+ container.register({{name}}Repository.self) { _ in
2
2
  {{name}}RepositoryImplementation(
3
3
 
4
4
  )
5
- }.inObjectScope(.container)
5
+ }
6
+ .inObjectScope(.container)
@@ -8,10 +8,11 @@
8
8
  //
9
9
 
10
10
  import Foundation
11
+ import Core
11
12
 
12
- class {{name}}RepositoryImplementation: {{name}}Repository {
13
+ public class {{name}}RepositoryImplementation: {{name}}Repository {
13
14
 
14
- init() {
15
+ public init() {
15
16
 
16
17
  }
17
18
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ccios
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pierre Felgines
@@ -10,6 +10,20 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2016-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: xcodeproj
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -25,33 +39,47 @@ dependencies:
25
39
  - !ruby/object:Gem::Version
26
40
  version: '1.4'
27
41
  - !ruby/object:Gem::Dependency
28
- name: rails
42
+ name: mustache
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '5.1'
47
+ version: '1.0'
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '5.1'
54
+ version: '1.0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: mustache
56
+ name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '1.0'
48
- type: :runtime
61
+ version: '12.3'
62
+ type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '1.0'
68
+ version: '12.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.11'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.11'
55
83
  description: Clean Code iOS Generator
56
84
  email: pierre.felgines@gmail.com
57
85
  executables:
@@ -59,15 +87,19 @@ executables:
59
87
  extensions: []
60
88
  extra_rdoc_files: []
61
89
  files:
90
+ - ".github/workflows/ruby.yml"
62
91
  - ".gitignore"
92
+ - CHANGELOG.md
63
93
  - Gemfile
64
94
  - Gemfile.lock
95
+ - Makefile
65
96
  - README.md
66
97
  - Rakefile
67
98
  - bin/ccios
68
99
  - ccios.gemspec
69
100
  - lib/ccios.rb
70
101
  - lib/ccios/code_templater.rb
102
+ - lib/ccios/config.rb
71
103
  - lib/ccios/coordinator_generator.rb
72
104
  - lib/ccios/file_creator.rb
73
105
  - lib/ccios/interactor_generator.rb
@@ -106,8 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
138
  - !ruby/object:Gem::Version
107
139
  version: '0'
108
140
  requirements: []
109
- rubyforge_project:
110
- rubygems_version: 2.7.6
141
+ rubygems_version: 3.0.3
111
142
  signing_key:
112
143
  specification_version: 4
113
144
  summary: Clean Code iOS Generator