Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ccios improvements #25

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.2
3.3.0
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Changed

- Target variable is now optional, an empty string or an unset value will use the first target of the project. This change allows templates to not overrides global target settings in `.ccios.yml`
- When multiple targets are provided for a file, `{{project_name}}` will now be replaced by the name of the project instead of the name of the first target
- `@MainActor` has been added to relevent files in Coordinator and Presenter templates to improve Swift 6 support
- dependency provider snippets has been updated to handle Swift 6 issue (see [this issue](https://github.com/Swinject/Swinject/issues/571) for why this is required)

## [5.0.0]

This release is an entire rewrite of the templating system, allowing customization of template and settings.
Expand Down
47 changes: 33 additions & 14 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,60 @@ PATH
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.6)
CFPropertyList (3.0.7)
base64
nkf
rexml
activesupport (7.0.8)
concurrent-ruby (~> 1.0, >= 1.0.2)
activesupport (8.0.1)
base64
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
tzinfo (~> 2.0)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1)
atomos (0.1.3)
base64 (0.2.0)
benchmark (0.4.0)
bigdecimal (3.1.9)
claide (1.1.0)
colored2 (3.1.2)
concurrent-ruby (1.2.2)
i18n (1.14.1)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
drb (2.2.1)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
minitest (5.20.0)
logger (1.6.6)
minitest (5.25.4)
mustache (1.1.1)
nanaimo (0.3.0)
rake (12.3.3)
rexml (3.2.6)
nanaimo (0.4.0)
nkf (0.2.0)
rake (13.2.1)
rexml (3.4.1)
securerandom (0.4.1)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
xcodeproj (1.23.0)
uri (1.0.3)
xcodeproj (1.27.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (~> 3.2.4)
nanaimo (~> 0.4.0)
rexml (>= 3.3.6, < 4.0)

PLATFORMS
ruby

DEPENDENCIES
ccios!
minitest (~> 5.11)
rake (~> 12.3)
rake (~> 13.2)

BUNDLED WITH
2.4.10
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ templates_collection: ccios/templates
# Global overrides of variables [Optional]
variables:
project: Project.xcodeproj
target: SomeDefaultTarget

# Per template variables override
templates_config:
Expand Down Expand Up @@ -224,8 +225,8 @@ variables:
project: "*.xcodeproj"
# The base path used to generate an element. This variable must be defined once here, or on each elements below.
base_path: "path/to/base_group"
# The target in which files are added. Can be a string, a list of strings, or an empty string. This variable must be defined once here, or on each elements below. If an empty string is provided, it will use the first target found in the Xcode project.
target: ""
# The target in which files are added. Can be a string, a list of strings, or an empty string. This variable must be defined once here, or on each elements below. If this variable is not set or if an empty string is provided, it will use the first target found in the Xcode project. If present it will override the global default target. [Optional]
target: "SomeTarget"
# List of generated elements. [Required]
# Each element can be a file (using `file`), or an empty folder (using `group`)
generated_elements:
Expand Down
2 changes: 1 addition & 1 deletion ccios.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ Gem::Specification.new do |s|
s.add_dependency 'xcodeproj', '~> 1.4'
s.add_dependency "mustache", "~> 1.0"

s.add_development_dependency 'rake', '~> 12.3'
s.add_development_dependency 'rake', '~> 13.2'
s.add_development_dependency 'minitest', '~> 5.11'
end
19 changes: 15 additions & 4 deletions lib/ccios/file_creator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ def pf_new_group(associate_path_to_group:, name:, path:)
end
end

class Xcodeproj::Project

def project_name_from_path
File.basename(@path, File.extname(@path))
end
end

class FileCreator

def self.logger
Expand All @@ -25,12 +32,16 @@ def logger
FileCreator.logger
end

def templater_options(target)
def templater_options(targets, project)
defaults = {
project_name: target.display_name,
full_username: git_username,
date: DateTime.now.strftime("%d/%m/%Y"),
}
if targets.count == 1
defaults["project_name"] = targets[0].display_name
else
defaults["project_name"] = project.project_name_from_path
end
defaults
end

Expand All @@ -44,15 +55,15 @@ def get_unknown_template_tags_for(template_path)
tags
end

def create_file_using_template_path(template_path, generated_filename, group, targets, context)
def create_file_using_template_path(template_path, generated_filename, group, targets, project, context)
file_path = File.join(group.real_path, generated_filename)

raise "File #{file_path} already exists" if File.exist?(file_path)
dirname = File.dirname(file_path)
FileUtils.mkdir_p dirname unless File.directory?(dirname)
file = File.new(file_path, 'w')

context = context.merge(templater_options(targets[0]))
context = context.merge(templater_options(targets, project))
file_content = CodeTemplater.new.render_file_content_from_template(template_path, generated_filename, context)

file.puts(file_content)
Expand Down
5 changes: 3 additions & 2 deletions lib/ccios/file_template_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def validate(parser, project, context, template_definition, config)
raise "Base path \"#{base_path}\" is missing" if base_group.nil?

target_name = merged_variables["target"]
if target_name.is_a?(String)
if target_name.is_a?(String) || target_name.nil?
target = parser.target_for(project, target_name)
raise "Unable to find target \"#{target_name}\"" if target.nil?
elsif target_name.is_a?(Array)
Expand Down Expand Up @@ -77,7 +77,7 @@ def generate(parser, project, context, template_definition, config)
target_name = merged_variables["target"]

targets = []
if target_name.is_a?(String)
if target_name.is_a?(String) || target_name.nil?
targets = [parser.target_for(project, target_name)]
elsif target_name.is_a?(Array)
targets = target_name.map { |name| parser.target_for(project, name) }
Expand All @@ -88,6 +88,7 @@ def generate(parser, project, context, template_definition, config)
generated_filename,
group,
targets,
project,
context
)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/ccios/pbxproj_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def project_for(path)
end

def target_for(project, target_name)
if target_name.blank?
if target_name.blank? || target_name.nil?
project.targets.find { |t| t.product_type == "com.apple.product-type.application" }
else
project.targets.find { |t| t.name == target_name }
Expand Down
7 changes: 5 additions & 2 deletions lib/ccios/templates/Coordinator/coordinator.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Foundation
import ADCoordinator

{{#generate_delegate}}
@MainActor
protocol {{name}}CoordinatorDelegate: AnyObject {

}
Expand All @@ -23,8 +24,10 @@ class {{name}}Coordinator: Coordinator {
private let dependencyProvider: ApplicationDependencyProvider
private unowned var navigationController: UINavigationController

init(navigationController: UINavigationController,
dependencyProvider: ApplicationDependencyProvider) {
init(
navigationController: UINavigationController,
dependencyProvider: ApplicationDependencyProvider
) {
self.navigationController = navigationController
self.dependencyProvider = dependencyProvider
}
Expand Down
1 change: 0 additions & 1 deletion lib/ccios/templates/Coordinator/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ description: "Generate NameCoordinator"
variables:
project: "*.xcodeproj"
base_path: "Coordinator"
target: ""
parameters:
- argument: "name"
removeSuffix: "Coordinator"
Expand Down
1 change: 0 additions & 1 deletion lib/ccios/templates/Interactor/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ parameters:
variables:
project: "*.xcodeproj"
base_path: "Core/Interactor"
target: ""
generated_elements:
- name: "interactor"
file: "{{ name }}Interactor/{{ name }}Interactor.swift"
Expand Down
8 changes: 6 additions & 2 deletions lib/ccios/templates/Presenter/dependency_provider.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
func {{lowercased_name}}Presenter(viewContract: {{name}}ViewContract, presenterDelegate: {{name}}PresenterDelegate) -> {{name}}Presenter? {
return presenterAssembler
.resolver
.resolve({{name}}Presenter.self, arguments: viewContract, presenterDelegate)
.resolve(
{{name}}Presenter.self,
arguments: viewContract as {{name}}ViewContract,
presenterDelegate as {{name}}PresenterDelegate
)
}
{{/generate_delegate}}
{{^generate_delegate}}
func {{lowercased_name}}Presenter(viewContract: {{name}}ViewContract) -> {{name}}Presenter? {
return presenterAssembler
.resolver
.resolve({{name}}Presenter.self, argument: viewContract)
.resolve({{name}}Presenter.self, argument: viewContract as {{name}}ViewContract)
}
{{/generate_delegate}}
2 changes: 2 additions & 0 deletions lib/ccios/templates/Presenter/presenter.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@

import Foundation

@MainActor
protocol {{name}}Presenter {
func start()
}
{{#generate_delegate}}

@MainActor
protocol {{name}}PresenterDelegate: AnyObject {

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class {{name}}PresenterImplementation: {{name}}Presenter {
// MARK: - {{name}}Presenter

func start() {

let viewModel = {{name}}ViewModelMapper().map()
viewContract?.configure(with: viewModel)
}
}
12 changes: 9 additions & 3 deletions lib/ccios/templates/Presenter/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ parameters:
variables:
project: "*.xcodeproj"
base_path: "App"
target: ""
generated_elements:
- name: "ui_view_group"
group: "{{ name }}/UI/View"
Expand All @@ -32,8 +31,13 @@ generated_elements:
file: "{{ name }}/Presenter/{{ name }}PresenterImplementation.swift"
template: "presenter_implementation"
variables: {}
- name: "model_group"
group: "{{ name }}/Model"
- name: "view_model"
file: "{{ name }}/Model/{{ name }}ViewModel.swift"
template: "view_model"
variables: {}
- name: "view_model_mapper"
file: "{{ name }}/Model/Mapper/{{ name }}ViewModelMapper.swift"
template: "view_model_mapper"
variables: {}
code_snippets:
- name: DependencyProvider
Expand All @@ -45,5 +49,7 @@ template_file_source:
view_contract: "view_contract.mustache"
presenter: "presenter.mustache"
presenter_implementation: "presenter_implementation.mustache"
view_model: "view_model.mustache"
view_model_mapper: "view_model_mapper.mustache"
dependency_provider: "dependency_provider.mustache"
presenter_assembly: "presenter_assembly.mustache"
3 changes: 2 additions & 1 deletion lib/ccios/templates/Presenter/view_contract.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Foundation

@MainActor
protocol {{name}}ViewContract: AnyObject {

func configure(with viewModel: {{name}}ViewModel)
}
3 changes: 3 additions & 0 deletions lib/ccios/templates/Presenter/view_controller.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ class {{name}}ViewController: SharedViewController, {{name}}ViewContract {

// MARK: - {{name}}ViewContract

func configure(with viewModel: {{name}}ViewModel) {
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

en soit optionnel, mais dans les autres on n'a pas de ligne en rab après la dernière fonction, on pourrait l'enlever

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d'ailleurs autre question

  • est-ce qu'on passerait pas {{name}}ViewContract dans une extension ?
  • je sais pas si ca vaut le coup de rajouter ou non le mark UIViewController avant le viewDidload

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Je vais enlever le retour à la ligne en trop, il ne sert pas en effet.
  • Pour le ViewContract, je ne suis pas fan de le mettre dans une extension car ce view controller a comme principale fonction de conformer a ce protocole. Après c'est bien qu'on soit tous d'accord sur ce point.
  • C'est vrai qu'un MARK UIViewController ou alors un simple Lifecycle serait bien

}
12 changes: 12 additions & 0 deletions lib/ccios/templates/Presenter/view_model.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// {{name}}ViewModel.swift
// {{project_name}}
//
// Created by {{full_username}} on {{date}}.
//
//

import Foundation

struct {{name}}ViewModel {
}
16 changes: 16 additions & 0 deletions lib/ccios/templates/Presenter/view_model_mapper.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// {{name}}ViewModelMapper.swift
// {{project_name}}
//
// Created by {{full_username}} on {{date}}.
//
//

import Foundation

struct {{name}}ViewModelMapper {

func map() -> {{name}}ViewModel {
{{name}}ViewModel()
}
}
1 change: 0 additions & 1 deletion lib/ccios/templates/Repository/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ parameters:
removeSuffix: "Repository"
variables:
project: "*.xcodeproj"
target: ""
generated_elements:
- name: "repository"
file: "{{ name }}/{{ name }}Repository.swift"
Expand Down