ccios 2.1.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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