From 4ebcbadea299f5cd5bcc627684e9a1e02bbc27da Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Mon, 15 Jun 2020 14:38:44 +0300 Subject: [PATCH 01/43] multiple swiftlint rules script --- xcode/build_phases/multiple_swiftlint.sh | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 xcode/build_phases/multiple_swiftlint.sh diff --git a/xcode/build_phases/multiple_swiftlint.sh b/xcode/build_phases/multiple_swiftlint.sh new file mode 100644 index 0000000..2fe8633 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +sourceDirectiry=${1:-${TARGET_NAME}}/.. # first argument or TARGET_NAME +sourceTimestamp=$(date -j -f "%Y:%m:%d %H:%M:%S" '2020:05:20 00:00:00' +%s) +touchInstinctYml="$sourceDirectiry/build-scripts/xcode/.swiftlint.yml" +swiftlint=${PODS_ROOT}/SwiftLint/swiftlint +oldYml="$sourceDirectiry/.swiftlint.yml" +excludeDirectories=("vendor" "Tests" "Mock" "Pods" "build-scripts" "nmir-loyaltyTests" "common" ".gem" "node_modules" "Framework" "fastlane") +availableExtensions=(".swift") + +function runSwiftlint() { + config="" + if [[ $2 = "true" ]]; then + config=$touchInstinctYml + else + config=$oldYml + fi + + $swiftlint autocorrect --path $1 --config $config && $swiftlint --path $1 --config $config +} + +function compareTimestamp() { + currentFileTimestamp=$(stat -f%B "$1") + diff=$(($sourceTimestamp - $currentFileTimestamp)) + if [[ $diff -lt 0 ]]; then + runSwiftlint "$filePath" true + else + runSwiftlint "$filePath" false + fi +} + +function isExcludedDirectory() { + for excludeFile in ${excludeDirectories[*]} ; do + if [[ $1 == *$excludeFile* ]]; then + return 1 + fi + done + + return 0 +} + +function isValidExtensions() { + for extension in ${availableExtensions[*]} ; do + if [[ $1 == *$extension* ]]; then + return 1 + fi + done + + return 0 +} + +function findFiles() { + for filePath in "$1"/* ; do + if [[ -d "$filePath" ]]; then + isExcludedDirectory "$filePath" + isExcludedDirectory=$? + if [[ ($isExcludedDirectory == 0) ]]; then + findFiles "$filePath" + fi + else + isValidExtensions "$filePath" + isValidExtensions=$? + if [[ $isValidExtensions == 1 ]]; then + compareTimestamp "$filePath" + fi + fi + done +} + +findFiles "$sourceDirectiry" From 2e64ab92d47bb0e85fbe6652f50914bd04284b1a Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Mon, 29 Jun 2020 16:55:56 +0300 Subject: [PATCH 02/43] multiple swiftlint rules script --- xcode/build_phases/swiftlint.rb | 392 ++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 xcode/build_phases/swiftlint.rb diff --git a/xcode/build_phases/swiftlint.rb b/xcode/build_phases/swiftlint.rb new file mode 100644 index 0000000..55ea565 --- /dev/null +++ b/xcode/build_phases/swiftlint.rb @@ -0,0 +1,392 @@ +require 'yaml' +require 'optparse' +require 'ostruct' +require 'date' +require 'fileutils' + +Encoding.default_external = Encoding::UTF_8 +Encoding.default_internal = Encoding::UTF_8 + +class String + def with_wrapped_whitespace + self.gsub(/\s+/, '\ ') + end + + def filter_allowed_symbol_into_path + self.gsub!(/[^0-9A-Za-z \-+.\/]/, '') + end + + def true? + self.to_s.downcase == "true" + end + + def add_back_to_path(count) + string = self + count.to_i.times { |i| + string = '../' + string + } + return string + end + + def nilOrEmpty? + self.nil? or self.empty? + end +end + +class Array + def nilOrEmpty? + self.nil? or self.empty? + end +end + +class YamlManager + def initialize(swiftlint_yaml_path) + @swiftlint_yaml_path = swiftlint_yaml_path + @configuration ||= YAML.load(File.read(@swiftlint_yaml_path)) + end + + def get_configuration(key) + @configuration[key] + end + + def update(key, new_configuration_values) + @configuration[key] = new_configuration_values + save_settings(@configuration) + end + + private + + def save_settings(settings) + File.write(@swiftlint_yaml_path, settings.to_yaml) + end +end + +class SettingOption + def initialize + @options = OpenStruct.new + OptionParser.new do |opt| + opt.on('-s', '--source_directory STRING', 'The directory of start') { |option| @options.source_directory = option } + opt.on('-p', '--pods_directory STRING', 'The directory of pods') { |option| @options.pods_directory = option } + opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } + opt.on('-u', '--use_multiple BOOL', 'the flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } + opt.on('-d', '--source_date DATE', 'The date of grouping files according new and old swiftlint rules') { |option| @options.source_date = option } + opt.on('-y', '--touchin_swiftlint_yaml_path STRING', 'The path to the touchin swiftlint yaml relative to the source directory') { |option| @options.touchin_swiftlint_yaml_path = option } + opt.on('-g', '--depth_git_count Int', 'The depth between the git directory and sources directory') { |option| @options.depth_git_count = option } + end.parse! + + if @options.check_mode.to_s.nilOrEmpty? + @options.check_mode = 'fully' + end + + if @options.use_multiple.to_s.nilOrEmpty? + @options.use_multiple = 'false' + end + + if @options.depth_git_count.to_s.nilOrEmpty? + @options.depth_git_count = 0 + end + + if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty? + @options.touchin_swiftlint_yaml_path = '/build-scripts/xcode/.swiftlint.yml' + end + end + + def source_directory + @options.source_directory + end + + def source_date + @options.source_date + end + + def pods_directory + @options.pods_directory + end + + def check_mode + @options.check_mode + end + + def use_multiple + @options.use_multiple + end + + def depth_git_count + @options.depth_git_count + end + + def touchin_swiftlint_yaml_path + @options.touchin_swiftlint_yaml_path + end +end + +class CommandUtils + def self.make_command(command) + command = command.to_s + return `#{command}` + end +end + +class GitСaretaker < CommandUtils + def self.get_modified_files + non_indexed_files = get_files_from('git diff --name-only | sed s/.*/"&,"/ ') + indexed_files = get_files_from('git diff --cached --name-only | sed s/.*/"&,"/ ') + + modified_files = non_indexed_files + indexed_files + unique_modified_files = modified_files.uniq + + unique_modified_swift_files = [] + if not unique_modified_files.nilOrEmpty? + unique_modified_swift_files = unique_modified_files.select { |file_path| + file_path.to_s.filter_allowed_symbol_into_path + file_path.to_s.include? '.swift' + } + end + + return unique_modified_swift_files + end + + def self.get_creation_date(file_path) + git_command = 'git log --follow --format=%cD --reverse -- ' + file_path + ' | head -1' + return make_command(git_command) + end + + private + + def self.get_files_from(command) + files_as_string = make_command(command) + return files_as_string.split(',') + end +end + +class SwiftFileManager + def initialize(excluded_files, source_date) + if not source_date.nilOrEmpty? + @source_date = Date.parse(source_date) + end + @excluded_files = excluded_files + @new_files = [] + @old_files = [] + end + + def old_files + @old_files + end + + def new_files + @new_files + end + + def find_list_file_paths(start_folder) + swift_files = File.join('**', '*.swift') + Dir.glob(swift_files, base: start_folder) { |file_path| + if not is_excluded_file(file_path) + compare_timestamp(file_path) + end + } + end + + def find_list_file_paths_from(files_path) + files_path.each { |file_path| + if not is_excluded_file(file_path) + compare_timestamp(file_path) + end + } + end + + def is_excluded_file(file_path) + @excluded_files.each do |exclude_file_path| + if file_path.include? exclude_file_path + return true + end + end + return false + end + + private + + def compare_timestamp(file_path) + wrapped_whitespace_file_path = file_path.with_wrapped_whitespace + creation_date_string = GitСaretaker.get_creation_date(wrapped_whitespace_file_path) + puts file_path + if creation_date_string.nilOrEmpty? + @old_files.push(file_path) + puts 'Not found the creation date' + else + creation_date = Date.parse(creation_date_string) + puts creation_date + if @source_date < creation_date + @new_files.push(file_path) + else + @old_files.push(file_path) + end + end + end +end + +class StrategyMaker + def initialize(source_directory, pods_directory, touchin_swiftlint_yaml_path) + @source_directory = source_directory + @pods_directory = pods_directory + @swiftlint = pods_directory + '/SwiftLint/swiftlint' + + @touchin_swiftlint_yaml_path = source_directory + touchin_swiftlint_yaml_path + @old_swiftlint_yaml_path = source_directory + '/.swiftlint.yml' + + @temporary_swiftlint_folder_name = source_directory + '/temporary_swiftlint' + @touchin_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.touchin_swiftlint.yml' + @old_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.old_swiftlint.yml' + + @swiftlint_autocorrect_command = @swiftlint + ' autocorrect --path ' + @source_directory + ' --config ' + @swiftlint_lint_command = @swiftlint + ' --path ' + @source_directory + ' --config ' + end + + def make_fully_multiple_strategy(source_date) + create_copy_temporary_files + + touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) + old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) + + touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') + old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded') + common_exclude_files = touchin_excluded_files + old_excluded_files + unique_exclude_files = common_exclude_files.uniq + + swift_files = SwiftFileManager.new(unique_exclude_files, source_date) + swift_files.find_list_file_paths(@source_directory) + + total_touchin_excluded_files = unique_exclude_files + swift_files.old_files + total_old_excluded_files = unique_exclude_files + swift_files.new_files + + touchin_swiftlint_yaml_manager.update('excluded', total_touchin_excluded_files) + old_swiftlint_yaml_manager.update('excluded', total_old_excluded_files) + + make_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) + end + + def make_simplified_multiple_strategy(source_date, depth_git_count) + included_files = GitСaretaker.get_modified_files + + if included_files.nilOrEmpty? + puts 'Git did not found swift files to check' + return + end + + create_copy_temporary_files + + touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) + old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) + + touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') + old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded') + common_exclude_files = touchin_excluded_files + old_excluded_files + unique_exclude_files = common_exclude_files.uniq + + included_files = included_files.map { |file_path| file_path.add_back_to_path(depth_git_count) } + + swift_file_manager = SwiftFileManager.new(unique_exclude_files, source_date) + swift_file_manager.find_list_file_paths_from(included_files) + + total_touchin_included_files = swift_file_manager.new_files + total_old_included_files = swift_file_manager.old_files + + touchin_swiftlint_yaml_manager.update('excluded', []) + old_swiftlint_yaml_manager.update('excluded', []) + + touchin_swiftlint_yaml_manager.update('included', total_touchin_included_files) + old_swiftlint_yaml_manager.update('included', total_old_included_files) + + is_exist_total_touchin_included_files = (not total_touchin_included_files.nilOrEmpty?) + is_exist_total_old_included_files = (not total_old_included_files.nilOrEmpty?) + + if is_exist_total_touchin_included_files and is_exist_total_old_included_files + make_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) + elsif is_exist_total_touchin_included_files and not is_exist_total_old_included_files + make_single_strategy(@touchin_swiftlint_yaml_temporary_path) + elsif not is_exist_total_touchin_included_files and is_exist_total_old_included_files + make_single_strategy(@old_swiftlint_yaml_temporary_path) + else + puts 'Git did not found swift files to check' + end + end + + def make_fully_single_strategy + make_single_strategy(@touchin_swiftlint_yaml_path) + end + + def make_simplified_single_strategy(depth_git_count) + included_files = GitСaretaker.get_modified_files + + if included_files.nilOrEmpty? + puts 'Git did not found swift files to check' + return + end + + create_copy_temporary_touchin_files + + touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) + touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') + swift_files = SwiftFileManager.new(touchin_excluded_files, '') + + included_files = included_files.select { |file_name| not swift_files.is_excluded_file(file_name) } + included_files = included_files.map { |file_path| file_path.add_back_to_path(depth_git_count) } + + touchin_swiftlint_yaml_manager.update('excluded', []) + touchin_swiftlint_yaml_manager.update('included', included_files) + + if not included_files.nilOrEmpty? + make_single_strategy(@touchin_swiftlint_yaml_temporary_path) + else + puts 'Git found the swift files to check, but they are excluded in yaml' + end + end + + private + + def make_single_strategy(swiftlint_yaml_path) + result_swiftlint_command = get_swiftlint_command(swiftlint_yaml_path) + puts result_swiftlint_command + make_bash_command(result_swiftlint_command) + end + + def make_multiple_strategy(touchin_swiftlint_yaml_temporary_path, old_swiftlint_yaml_temporary_path) + touchin_swiftlint_command = get_swiftlint_command(touchin_swiftlint_yaml_temporary_path) + old_swiftlint_command = get_swiftlint_command(old_swiftlint_yaml_temporary_path) + result_swiftlint_command = touchin_swiftlint_command + ' && ' + old_swiftlint_command + puts result_swiftlint_command + make_bash_command(result_swiftlint_command) + end + + def get_swiftlint_command(swiftlint_yaml_path) + autocorrect_command = @swiftlint_autocorrect_command + swiftlint_yaml_path + lint_command = @swiftlint_lint_command + swiftlint_yaml_path + return autocorrect_command + ' && ' + lint_command + end + + def make_bash_command(bash_command) + exit (exec bash_command) + end + + def create_copy_temporary_files + create_copy_temporary_touchin_files + FileUtils.cp @old_swiftlint_yaml_path, @old_swiftlint_yaml_temporary_path + end + + def create_copy_temporary_touchin_files + Dir.mkdir(@temporary_swiftlint_folder_name) unless Dir.exist?(@temporary_swiftlint_folder_name) + FileUtils.cp @touchin_swiftlint_yaml_path, @touchin_swiftlint_yaml_temporary_path + end +end + +setting = SettingOption.new +maker = StrategyMaker.new(setting.source_directory, setting.pods_directory, setting.touchin_swiftlint_yaml_path) + +if setting.check_mode.eql? 'fully' and setting.use_multiple.true? + maker.make_fully_multiple_strategy(setting.source_date) +elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true? + maker.make_fully_single_strategy +elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true? + maker.make_simplified_multiple_strategy(setting.source_date, setting.depth_git_count) +elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true? + maker.make_simplified_single_strategy(setting.depth_git_count) +end From 6b299828f04ef03b8535f63c2c523d82f0450c4b Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Tue, 30 Jun 2020 16:22:47 +0300 Subject: [PATCH 03/43] remove multiple_swiftlint.sh --- xcode/build_phases/multiple_swiftlint.sh | 70 ------------------------ 1 file changed, 70 deletions(-) delete mode 100644 xcode/build_phases/multiple_swiftlint.sh diff --git a/xcode/build_phases/multiple_swiftlint.sh b/xcode/build_phases/multiple_swiftlint.sh deleted file mode 100644 index 2fe8633..0000000 --- a/xcode/build_phases/multiple_swiftlint.sh +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/bash - -sourceDirectiry=${1:-${TARGET_NAME}}/.. # first argument or TARGET_NAME -sourceTimestamp=$(date -j -f "%Y:%m:%d %H:%M:%S" '2020:05:20 00:00:00' +%s) -touchInstinctYml="$sourceDirectiry/build-scripts/xcode/.swiftlint.yml" -swiftlint=${PODS_ROOT}/SwiftLint/swiftlint -oldYml="$sourceDirectiry/.swiftlint.yml" -excludeDirectories=("vendor" "Tests" "Mock" "Pods" "build-scripts" "nmir-loyaltyTests" "common" ".gem" "node_modules" "Framework" "fastlane") -availableExtensions=(".swift") - -function runSwiftlint() { - config="" - if [[ $2 = "true" ]]; then - config=$touchInstinctYml - else - config=$oldYml - fi - - $swiftlint autocorrect --path $1 --config $config && $swiftlint --path $1 --config $config -} - -function compareTimestamp() { - currentFileTimestamp=$(stat -f%B "$1") - diff=$(($sourceTimestamp - $currentFileTimestamp)) - if [[ $diff -lt 0 ]]; then - runSwiftlint "$filePath" true - else - runSwiftlint "$filePath" false - fi -} - -function isExcludedDirectory() { - for excludeFile in ${excludeDirectories[*]} ; do - if [[ $1 == *$excludeFile* ]]; then - return 1 - fi - done - - return 0 -} - -function isValidExtensions() { - for extension in ${availableExtensions[*]} ; do - if [[ $1 == *$extension* ]]; then - return 1 - fi - done - - return 0 -} - -function findFiles() { - for filePath in "$1"/* ; do - if [[ -d "$filePath" ]]; then - isExcludedDirectory "$filePath" - isExcludedDirectory=$? - if [[ ($isExcludedDirectory == 0) ]]; then - findFiles "$filePath" - fi - else - isValidExtensions "$filePath" - isValidExtensions=$? - if [[ $isValidExtensions == 1 ]]; then - compareTimestamp "$filePath" - fi - fi - done -} - -findFiles "$sourceDirectiry" From 77d5642b7aea83bebc182d958d0a2f788beff681 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Tue, 30 Jun 2020 16:48:38 +0300 Subject: [PATCH 04/43] fix indent --- xcode/build_phases/swiftlint.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xcode/build_phases/swiftlint.rb b/xcode/build_phases/swiftlint.rb index 55ea565..3fd404a 100644 --- a/xcode/build_phases/swiftlint.rb +++ b/xcode/build_phases/swiftlint.rb @@ -46,18 +46,18 @@ class YamlManager end def get_configuration(key) - @configuration[key] + @configuration[key] end def update(key, new_configuration_values) - @configuration[key] = new_configuration_values - save_settings(@configuration) + @configuration[key] = new_configuration_values + save_settings(@configuration) end private def save_settings(settings) - File.write(@swiftlint_yaml_path, settings.to_yaml) + File.write(@swiftlint_yaml_path, settings.to_yaml) end end From 635fa8dc98ed370331fd3c5c948f5b9b50d2584d Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Tue, 30 Jun 2020 16:55:06 +0300 Subject: [PATCH 05/43] added style guide and fixed naming --- xcode/build_phases/swiftlint.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xcode/build_phases/swiftlint.rb b/xcode/build_phases/swiftlint.rb index 3fd404a..c954d4a 100644 --- a/xcode/build_phases/swiftlint.rb +++ b/xcode/build_phases/swiftlint.rb @@ -1,3 +1,4 @@ +#https://github.com/TouchInstinct/Styleguide/blob/multiple_swiftlint/IOS/Guides/BuildScripts/Multiple_Swiftlint_Guide.md require 'yaml' require 'optparse' require 'ostruct' @@ -65,11 +66,11 @@ class SettingOption def initialize @options = OpenStruct.new OptionParser.new do |opt| - opt.on('-s', '--source_directory STRING', 'The directory of start') { |option| @options.source_directory = option } + opt.on('-s', '--source_directory STRING', 'The directory of source') { |option| @options.source_directory = option } opt.on('-p', '--pods_directory STRING', 'The directory of pods') { |option| @options.pods_directory = option } opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } - opt.on('-u', '--use_multiple BOOL', 'the flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } - opt.on('-d', '--source_date DATE', 'The date of grouping files according new and old swiftlint rules') { |option| @options.source_date = option } + opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } + opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option } opt.on('-y', '--touchin_swiftlint_yaml_path STRING', 'The path to the touchin swiftlint yaml relative to the source directory') { |option| @options.touchin_swiftlint_yaml_path = option } opt.on('-g', '--depth_git_count Int', 'The depth between the git directory and sources directory') { |option| @options.depth_git_count = option } end.parse! From 08d11652abd4319fd3d6f48fa422c17284bb5c28 Mon Sep 17 00:00:00 2001 From: Ivan Smolin Date: Tue, 21 Jul 2020 14:44:30 +0300 Subject: [PATCH 06/43] fix CreatePushCertificate lane --- xcode/commonFastfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xcode/commonFastfile b/xcode/commonFastfile index d903469..171fc0e 100644 --- a/xcode/commonFastfile +++ b/xcode/commonFastfile @@ -91,7 +91,7 @@ private_lane :addShield do |options| .split(/(?=[A-Z])/) # -> ["Enterprise", "Customer", "Dev1", "Without", "S", "S", "L", "Pinning", "Release"] .map { |v| v.gsub(/[[:lower:]]+/, "") }[1..2] # -> ["E", "C", "D1", "W", "S", "S", "L", "P", "R"] -> ["C", "D1"] .join # -> "CD1" - + begin add_badge( shield: "#{buildDescription}-#{buildNumber}-green", @@ -186,7 +186,10 @@ private_lane :buildArchive do |options| ) end -lane :createPushCertificate do |options| +lane :CreatePushCertificate do |options| + configuration = get_configuration_for_type(options[:type] || "development") + options = configuration.to_options.merge(options) + certificates_path = File.expand_path "../Certificates" Dir.mkdir(certificates_path) unless File.directory?(certificates_path) From 2265a153a288f24740b92e85d048a7afc943d24c Mon Sep 17 00:00:00 2001 From: Boyko Mihail Date: Wed, 22 Jul 2020 16:14:18 +0300 Subject: [PATCH 07/43] Fix documentation_generator --- xcode/build_phases/documentation_generator.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xcode/build_phases/documentation_generator.sh b/xcode/build_phases/documentation_generator.sh index a5449b7..ffd4828 100644 --- a/xcode/build_phases/documentation_generator.sh +++ b/xcode/build_phases/documentation_generator.sh @@ -1 +1,2 @@ -. build-scripts/xcode/aux_scripts/certificates_readme_generator.sh > $PROJECT_DIR/Certificates/README.md \ No newline at end of file +readonly BUILD_SCRIPTS_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR +. $BUILD_SCRIPTS_DIR/build-scripts/xcode/aux_scripts/certificates_readme_generator.sh > $PROJECT_DIR/Certificates/README.md From cc33a01bd0b8a0d92f3e50429f52db24134afd6c Mon Sep 17 00:00:00 2001 From: Ivan Smolin Date: Thu, 23 Jul 2020 13:34:09 +0300 Subject: [PATCH 08/43] don't change xcconfig for AppStore configuration --- xcode/commonFastfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xcode/commonFastfile b/xcode/commonFastfile index 171fc0e..8564ade 100644 --- a/xcode/commonFastfile +++ b/xcode/commonFastfile @@ -168,7 +168,9 @@ private_lane :buildArchive do |options| configuration = options[:configuration] xcodeproj_path = options[:xcodeproj_path] - set_xcconfig_for_configuration_of_project(xcconfig_name, configuration, xcodeproj_path) + if configuration != "AppStore" # AppStore uses xcconfig choosen in Xcode + set_xcconfig_for_configuration_of_project(xcconfig_name, configuration, xcodeproj_path) + end gym( clean: true, From 85a994bdf5c9b1a6b6feaaf7e4727bedbd10a4e7 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 28 Jul 2020 17:35:17 +0300 Subject: [PATCH 09/43] Fix bool check --- xcode/.swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index d502145..76c5915 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -241,7 +241,7 @@ custom_rules: redundant_type_annotation_bool: name: "Redundant type annotation for Bool" - regex: '((var|let)) *\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay\( *value *:)) *((true)|(false))' + regex: '\s((var|let)) *\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay\( *value *:)) *((true)|(false))' message: "Using a type annotation for Bool is redundant." severity: error From f45357752a2e19007e871b45ceb73ccf672e835e Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 28 Jul 2020 17:43:38 +0300 Subject: [PATCH 10/43] Fix bool check --- xcode/.swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index 76c5915..8e71145 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -241,7 +241,7 @@ custom_rules: redundant_type_annotation_bool: name: "Redundant type annotation for Bool" - regex: '\s((var|let)) *\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay\( *value *:)) *((true)|(false))' + regex: '\s((var|let))\s{1,}\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay\( *value *:)) *((true)|(false))' message: "Using a type annotation for Bool is redundant." severity: error From ce8f6746bf65c169fc52282dcceadc2e1fe82f12 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Tue, 28 Jul 2020 21:02:37 +0300 Subject: [PATCH 11/43] some refactoring, and remove copy paste --- xcode/build_phases/swiftlint.rb | 62 +++++++++++++++++---------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/xcode/build_phases/swiftlint.rb b/xcode/build_phases/swiftlint.rb index c954d4a..a940bcf 100644 --- a/xcode/build_phases/swiftlint.rb +++ b/xcode/build_phases/swiftlint.rb @@ -243,24 +243,18 @@ class StrategyMaker end def make_fully_multiple_strategy(source_date) - create_copy_temporary_files + create_yaml_managers_and_copy_temporary_files - touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) - old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) + exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) - touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') - old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded') - common_exclude_files = touchin_excluded_files + old_excluded_files - unique_exclude_files = common_exclude_files.uniq - - swift_files = SwiftFileManager.new(unique_exclude_files, source_date) + swift_files = SwiftFileManager.new(exclude_files, source_date) swift_files.find_list_file_paths(@source_directory) - total_touchin_excluded_files = unique_exclude_files + swift_files.old_files - total_old_excluded_files = unique_exclude_files + swift_files.new_files + total_touchin_excluded_files = exclude_files + swift_files.old_files + total_old_excluded_files = exclude_files + swift_files.new_files - touchin_swiftlint_yaml_manager.update('excluded', total_touchin_excluded_files) - old_swiftlint_yaml_manager.update('excluded', total_old_excluded_files) + @touchin_swiftlint_yaml_manager.update('excluded', total_touchin_excluded_files) + @old_swiftlint_yaml_manager.update('excluded', total_old_excluded_files) make_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) end @@ -273,29 +267,22 @@ class StrategyMaker return end - create_copy_temporary_files - - touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) - old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) + create_yaml_managers_and_copy_temporary_files - touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') - old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded') - common_exclude_files = touchin_excluded_files + old_excluded_files - unique_exclude_files = common_exclude_files.uniq - + exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) included_files = included_files.map { |file_path| file_path.add_back_to_path(depth_git_count) } - swift_file_manager = SwiftFileManager.new(unique_exclude_files, source_date) + swift_file_manager = SwiftFileManager.new(exclude_files, source_date) swift_file_manager.find_list_file_paths_from(included_files) total_touchin_included_files = swift_file_manager.new_files total_old_included_files = swift_file_manager.old_files - touchin_swiftlint_yaml_manager.update('excluded', []) - old_swiftlint_yaml_manager.update('excluded', []) + @touchin_swiftlint_yaml_manager.update('excluded', []) + @old_swiftlint_yaml_manager.update('excluded', []) - touchin_swiftlint_yaml_manager.update('included', total_touchin_included_files) - old_swiftlint_yaml_manager.update('included', total_old_included_files) + @touchin_swiftlint_yaml_manager.update('included', total_touchin_included_files) + @old_swiftlint_yaml_manager.update('included', total_old_included_files) is_exist_total_touchin_included_files = (not total_touchin_included_files.nilOrEmpty?) is_exist_total_old_included_files = (not total_old_included_files.nilOrEmpty?) @@ -347,7 +334,7 @@ class StrategyMaker def make_single_strategy(swiftlint_yaml_path) result_swiftlint_command = get_swiftlint_command(swiftlint_yaml_path) puts result_swiftlint_command - make_bash_command(result_swiftlint_command) + run_bash_command(result_swiftlint_command) end def make_multiple_strategy(touchin_swiftlint_yaml_temporary_path, old_swiftlint_yaml_temporary_path) @@ -355,7 +342,7 @@ class StrategyMaker old_swiftlint_command = get_swiftlint_command(old_swiftlint_yaml_temporary_path) result_swiftlint_command = touchin_swiftlint_command + ' && ' + old_swiftlint_command puts result_swiftlint_command - make_bash_command(result_swiftlint_command) + run_bash_command(result_swiftlint_command) end def get_swiftlint_command(swiftlint_yaml_path) @@ -364,7 +351,7 @@ class StrategyMaker return autocorrect_command + ' && ' + lint_command end - def make_bash_command(bash_command) + def run_bash_command(bash_command) exit (exec bash_command) end @@ -377,6 +364,21 @@ class StrategyMaker Dir.mkdir(@temporary_swiftlint_folder_name) unless Dir.exist?(@temporary_swiftlint_folder_name) FileUtils.cp @touchin_swiftlint_yaml_path, @touchin_swiftlint_yaml_temporary_path end + + def create_yaml_managers_and_copy_temporary_files + create_copy_temporary_files + + @touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) + @old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) + end + + def unique_exclude_files(touchin_swiftlint_yaml_manager, old_swiftlint_yaml_manager) + touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') + old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded') + common_exclude_files = touchin_excluded_files + old_excluded_files + unique_exclude_files = common_exclude_files.uniq + return unique_exclude_files + end end setting = SettingOption.new From 2285e1d18ef98bb61adfd3dac9d211c4ade8a3e4 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Wed, 29 Jul 2020 11:41:36 +0300 Subject: [PATCH 12/43] split swiftlint.rb file to some files --- .../multiple_swiftlint/array_extension.rb | 5 + .../multiple_swiftlint/command_utils.rb | 6 + .../multiple_swiftlint/git_caretaker.rb | 35 +++ .../multiple_swiftlint/setting_option.rb | 63 +++++ .../strategy_maker.rb} | 258 +----------------- .../multiple_swiftlint/string_extension.rb | 25 ++ .../multiple_swiftlint/swift_file_manager.rb | 69 +++++ .../multiple_swiftlint/swiftlint.rb | 19 ++ .../multiple_swiftlint/yaml_manager.rb | 24 ++ 9 files changed, 259 insertions(+), 245 deletions(-) create mode 100644 xcode/build_phases/multiple_swiftlint/array_extension.rb create mode 100644 xcode/build_phases/multiple_swiftlint/command_utils.rb create mode 100644 xcode/build_phases/multiple_swiftlint/git_caretaker.rb create mode 100644 xcode/build_phases/multiple_swiftlint/setting_option.rb rename xcode/build_phases/{swiftlint.rb => multiple_swiftlint/strategy_maker.rb} (50%) create mode 100644 xcode/build_phases/multiple_swiftlint/string_extension.rb create mode 100644 xcode/build_phases/multiple_swiftlint/swift_file_manager.rb create mode 100644 xcode/build_phases/multiple_swiftlint/swiftlint.rb create mode 100644 xcode/build_phases/multiple_swiftlint/yaml_manager.rb diff --git a/xcode/build_phases/multiple_swiftlint/array_extension.rb b/xcode/build_phases/multiple_swiftlint/array_extension.rb new file mode 100644 index 0000000..e5bebf6 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/array_extension.rb @@ -0,0 +1,5 @@ +class Array + def nilOrEmpty? + self.nil? or self.empty? + end +end diff --git a/xcode/build_phases/multiple_swiftlint/command_utils.rb b/xcode/build_phases/multiple_swiftlint/command_utils.rb new file mode 100644 index 0000000..cf12d07 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/command_utils.rb @@ -0,0 +1,6 @@ +class CommandUtils + def self.make_command(command) + command = command.to_s + return `#{command}` + end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/git_caretaker.rb b/xcode/build_phases/multiple_swiftlint/git_caretaker.rb new file mode 100644 index 0000000..323464a --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/git_caretaker.rb @@ -0,0 +1,35 @@ +require_relative 'array_extension.rb' +require_relative 'command_utils.rb' +require_relative 'string_extension.rb' + +class GitСaretaker < CommandUtils + def self.get_modified_files + non_indexed_files = get_files_from('git diff --name-only | sed s/.*/"&,"/ ') + indexed_files = get_files_from('git diff --cached --name-only | sed s/.*/"&,"/ ') + + modified_files = non_indexed_files + indexed_files + unique_modified_files = modified_files.uniq + + unique_modified_swift_files = [] + if not unique_modified_files.nilOrEmpty? + unique_modified_swift_files = unique_modified_files.select { |file_path| + file_path.to_s.filter_allowed_symbol_into_path + file_path.to_s.include? '.swift' + } + end + + return unique_modified_swift_files + end + + def self.get_creation_date(file_path) + git_command = 'git log --follow --format=%cD --reverse -- ' + file_path + ' | head -1' + return make_command(git_command) + end + + private + + def self.get_files_from(command) + files_as_string = make_command(command) + return files_as_string.split(',') + end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/setting_option.rb b/xcode/build_phases/multiple_swiftlint/setting_option.rb new file mode 100644 index 0000000..338d56e --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/setting_option.rb @@ -0,0 +1,63 @@ +require 'optparse' +require 'ostruct' + +require_relative 'array_extension.rb' + +class SettingOption + def initialize + @options = OpenStruct.new + OptionParser.new do |opt| + opt.on('-s', '--source_directory STRING', 'The directory of source') { |option| @options.source_directory = option } + opt.on('-p', '--pods_directory STRING', 'The directory of pods') { |option| @options.pods_directory = option } + opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } + opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } + opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option } + opt.on('-y', '--touchin_swiftlint_yaml_path STRING', 'The path to the touchin swiftlint yaml relative to the source directory') { |option| @options.touchin_swiftlint_yaml_path = option } + opt.on('-g', '--depth_git_count Int', 'The depth between the git directory and sources directory') { |option| @options.depth_git_count = option } + end.parse! + + if @options.check_mode.to_s.nilOrEmpty? + @options.check_mode = 'fully' + end + + if @options.use_multiple.to_s.nilOrEmpty? + @options.use_multiple = 'false' + end + + if @options.depth_git_count.to_s.nilOrEmpty? + @options.depth_git_count = 0 + end + + if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty? + @options.touchin_swiftlint_yaml_path = '/build-scripts/xcode/.swiftlint.yml' + end + end + + def source_directory + @options.source_directory + end + + def source_date + @options.source_date + end + + def pods_directory + @options.pods_directory + end + + def check_mode + @options.check_mode + end + + def use_multiple + @options.use_multiple + end + + def depth_git_count + @options.depth_git_count + end + + def touchin_swiftlint_yaml_path + @options.touchin_swiftlint_yaml_path + end +end \ No newline at end of file diff --git a/xcode/build_phases/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb similarity index 50% rename from xcode/build_phases/swiftlint.rb rename to xcode/build_phases/multiple_swiftlint/strategy_maker.rb index a940bcf..74419b7 100644 --- a/xcode/build_phases/swiftlint.rb +++ b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb @@ -1,229 +1,10 @@ -#https://github.com/TouchInstinct/Styleguide/blob/multiple_swiftlint/IOS/Guides/BuildScripts/Multiple_Swiftlint_Guide.md -require 'yaml' -require 'optparse' -require 'ostruct' -require 'date' require 'fileutils' -Encoding.default_external = Encoding::UTF_8 -Encoding.default_internal = Encoding::UTF_8 - -class String - def with_wrapped_whitespace - self.gsub(/\s+/, '\ ') - end - - def filter_allowed_symbol_into_path - self.gsub!(/[^0-9A-Za-z \-+.\/]/, '') - end - - def true? - self.to_s.downcase == "true" - end - - def add_back_to_path(count) - string = self - count.to_i.times { |i| - string = '../' + string - } - return string - end - - def nilOrEmpty? - self.nil? or self.empty? - end -end - -class Array - def nilOrEmpty? - self.nil? or self.empty? - end -end - -class YamlManager - def initialize(swiftlint_yaml_path) - @swiftlint_yaml_path = swiftlint_yaml_path - @configuration ||= YAML.load(File.read(@swiftlint_yaml_path)) - end - - def get_configuration(key) - @configuration[key] - end - - def update(key, new_configuration_values) - @configuration[key] = new_configuration_values - save_settings(@configuration) - end - - private - - def save_settings(settings) - File.write(@swiftlint_yaml_path, settings.to_yaml) - end -end - -class SettingOption - def initialize - @options = OpenStruct.new - OptionParser.new do |opt| - opt.on('-s', '--source_directory STRING', 'The directory of source') { |option| @options.source_directory = option } - opt.on('-p', '--pods_directory STRING', 'The directory of pods') { |option| @options.pods_directory = option } - opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } - opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } - opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option } - opt.on('-y', '--touchin_swiftlint_yaml_path STRING', 'The path to the touchin swiftlint yaml relative to the source directory') { |option| @options.touchin_swiftlint_yaml_path = option } - opt.on('-g', '--depth_git_count Int', 'The depth between the git directory and sources directory') { |option| @options.depth_git_count = option } - end.parse! - - if @options.check_mode.to_s.nilOrEmpty? - @options.check_mode = 'fully' - end - - if @options.use_multiple.to_s.nilOrEmpty? - @options.use_multiple = 'false' - end - - if @options.depth_git_count.to_s.nilOrEmpty? - @options.depth_git_count = 0 - end - - if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty? - @options.touchin_swiftlint_yaml_path = '/build-scripts/xcode/.swiftlint.yml' - end - end - - def source_directory - @options.source_directory - end - - def source_date - @options.source_date - end - - def pods_directory - @options.pods_directory - end - - def check_mode - @options.check_mode - end - - def use_multiple - @options.use_multiple - end - - def depth_git_count - @options.depth_git_count - end - - def touchin_swiftlint_yaml_path - @options.touchin_swiftlint_yaml_path - end -end - -class CommandUtils - def self.make_command(command) - command = command.to_s - return `#{command}` - end -end - -class GitСaretaker < CommandUtils - def self.get_modified_files - non_indexed_files = get_files_from('git diff --name-only | sed s/.*/"&,"/ ') - indexed_files = get_files_from('git diff --cached --name-only | sed s/.*/"&,"/ ') - - modified_files = non_indexed_files + indexed_files - unique_modified_files = modified_files.uniq - - unique_modified_swift_files = [] - if not unique_modified_files.nilOrEmpty? - unique_modified_swift_files = unique_modified_files.select { |file_path| - file_path.to_s.filter_allowed_symbol_into_path - file_path.to_s.include? '.swift' - } - end - - return unique_modified_swift_files - end - - def self.get_creation_date(file_path) - git_command = 'git log --follow --format=%cD --reverse -- ' + file_path + ' | head -1' - return make_command(git_command) - end - - private - - def self.get_files_from(command) - files_as_string = make_command(command) - return files_as_string.split(',') - end -end - -class SwiftFileManager - def initialize(excluded_files, source_date) - if not source_date.nilOrEmpty? - @source_date = Date.parse(source_date) - end - @excluded_files = excluded_files - @new_files = [] - @old_files = [] - end - - def old_files - @old_files - end - - def new_files - @new_files - end - - def find_list_file_paths(start_folder) - swift_files = File.join('**', '*.swift') - Dir.glob(swift_files, base: start_folder) { |file_path| - if not is_excluded_file(file_path) - compare_timestamp(file_path) - end - } - end - - def find_list_file_paths_from(files_path) - files_path.each { |file_path| - if not is_excluded_file(file_path) - compare_timestamp(file_path) - end - } - end - - def is_excluded_file(file_path) - @excluded_files.each do |exclude_file_path| - if file_path.include? exclude_file_path - return true - end - end - return false - end - - private - - def compare_timestamp(file_path) - wrapped_whitespace_file_path = file_path.with_wrapped_whitespace - creation_date_string = GitСaretaker.get_creation_date(wrapped_whitespace_file_path) - puts file_path - if creation_date_string.nilOrEmpty? - @old_files.push(file_path) - puts 'Not found the creation date' - else - creation_date = Date.parse(creation_date_string) - puts creation_date - if @source_date < creation_date - @new_files.push(file_path) - else - @old_files.push(file_path) - end - end - end -end +require_relative 'array_extension.rb' +require_relative 'git_caretaker.rb' +require_relative 'string_extension.rb' +require_relative 'swift_file_manager.rb' +require_relative 'yaml_manager.rb' class StrategyMaker def initialize(source_directory, pods_directory, touchin_swiftlint_yaml_path) @@ -354,6 +135,13 @@ class StrategyMaker def run_bash_command(bash_command) exit (exec bash_command) end + + def create_yaml_managers_and_copy_temporary_files + create_copy_temporary_files + + @touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) + @old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) + end def create_copy_temporary_files create_copy_temporary_touchin_files @@ -365,13 +153,6 @@ class StrategyMaker FileUtils.cp @touchin_swiftlint_yaml_path, @touchin_swiftlint_yaml_temporary_path end - def create_yaml_managers_and_copy_temporary_files - create_copy_temporary_files - - @touchin_swiftlint_yaml_manager = YamlManager.new(@touchin_swiftlint_yaml_temporary_path) - @old_swiftlint_yaml_manager = YamlManager.new(@old_swiftlint_yaml_temporary_path) - end - def unique_exclude_files(touchin_swiftlint_yaml_manager, old_swiftlint_yaml_manager) touchin_excluded_files = touchin_swiftlint_yaml_manager.get_configuration('excluded') old_excluded_files = old_swiftlint_yaml_manager.get_configuration('excluded') @@ -379,17 +160,4 @@ class StrategyMaker unique_exclude_files = common_exclude_files.uniq return unique_exclude_files end -end - -setting = SettingOption.new -maker = StrategyMaker.new(setting.source_directory, setting.pods_directory, setting.touchin_swiftlint_yaml_path) - -if setting.check_mode.eql? 'fully' and setting.use_multiple.true? - maker.make_fully_multiple_strategy(setting.source_date) -elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true? - maker.make_fully_single_strategy -elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true? - maker.make_simplified_multiple_strategy(setting.source_date, setting.depth_git_count) -elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true? - maker.make_simplified_single_strategy(setting.depth_git_count) -end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/string_extension.rb b/xcode/build_phases/multiple_swiftlint/string_extension.rb new file mode 100644 index 0000000..5b409e1 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/string_extension.rb @@ -0,0 +1,25 @@ +class String + def with_wrapped_whitespace + self.gsub(/\s+/, '\ ') + end + + def filter_allowed_symbol_into_path + self.gsub!(/[^0-9A-Za-z \-+.\/]/, '') + end + + def true? + self.to_s.downcase == "true" + end + + def add_back_to_path(count) + string = self + count.to_i.times { |i| + string = '../' + string + } + return string + end + + def nilOrEmpty? + self.nil? or self.empty? + end +end diff --git a/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb b/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb new file mode 100644 index 0000000..dd0d0f7 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb @@ -0,0 +1,69 @@ +require 'fileutils' +require 'date' + +require_relative 'git_caretaker.rb' + +class SwiftFileManager + def initialize(excluded_files, source_date) + if not source_date.nilOrEmpty? + @source_date = Date.parse(source_date) + end + @excluded_files = excluded_files + @new_files = [] + @old_files = [] + end + + def old_files + @old_files + end + + def new_files + @new_files + end + + def find_list_file_paths(start_folder) + swift_files = File.join('**', '*.swift') + Dir.glob(swift_files, base: start_folder) { |file_path| + if not is_excluded_file(file_path) + compare_timestamp(file_path) + end + } + end + + def find_list_file_paths_from(files_path) + files_path.each { |file_path| + if not is_excluded_file(file_path) + compare_timestamp(file_path) + end + } + end + + def is_excluded_file(file_path) + @excluded_files.each do |exclude_file_path| + if file_path.include? exclude_file_path + return true + end + end + return false + end + + private + + def compare_timestamp(file_path) + wrapped_whitespace_file_path = file_path.with_wrapped_whitespace + creation_date_string = GitСaretaker.get_creation_date(wrapped_whitespace_file_path) + puts file_path + if creation_date_string.nilOrEmpty? + @old_files.push(file_path) + puts 'Not found the creation date' + else + creation_date = Date.parse(creation_date_string) + puts creation_date + if @source_date < creation_date + @new_files.push(file_path) + else + @old_files.push(file_path) + end + end + end +end \ No newline at end of file diff --git a/xcode/build_phases/multiple_swiftlint/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/swiftlint.rb new file mode 100644 index 0000000..a499be7 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/swiftlint.rb @@ -0,0 +1,19 @@ +#https://github.com/TouchInstinct/Styleguide/blob/multiple_swiftlint/IOS/Guides/BuildScripts/Multiple_Swiftlint_Guide.md +require_relative 'setting_option.rb' +require_relative 'strategy_maker.rb' + +Encoding.default_external = Encoding::UTF_8 +Encoding.default_internal = Encoding::UTF_8 + +setting = SettingOption.new +maker = StrategyMaker.new(setting.source_directory, setting.pods_directory, setting.touchin_swiftlint_yaml_path) + +if setting.check_mode.eql? 'fully' and setting.use_multiple.true? + maker.make_fully_multiple_strategy(setting.source_date) +elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true? + maker.make_fully_single_strategy +elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true? + maker.make_simplified_multiple_strategy(setting.source_date, setting.depth_git_count) +elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true? + maker.make_simplified_single_strategy(setting.depth_git_count) +end diff --git a/xcode/build_phases/multiple_swiftlint/yaml_manager.rb b/xcode/build_phases/multiple_swiftlint/yaml_manager.rb new file mode 100644 index 0000000..cb3bbd8 --- /dev/null +++ b/xcode/build_phases/multiple_swiftlint/yaml_manager.rb @@ -0,0 +1,24 @@ +require 'yaml' +require 'fileutils' + +class YamlManager + def initialize(swiftlint_yaml_path) + @swiftlint_yaml_path = swiftlint_yaml_path + @configuration ||= YAML.load(File.read(@swiftlint_yaml_path)) + end + + def get_configuration(key) + @configuration[key] + end + + def update(key, new_configuration_values) + @configuration[key] = new_configuration_values + save_settings(@configuration) + end + + private + + def save_settings(settings) + File.write(@swiftlint_yaml_path, settings.to_yaml) + end +end From e819248df2bcb59f6ed16457e2f9537b468e2608 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Wed, 29 Jul 2020 12:30:58 +0300 Subject: [PATCH 13/43] =?UTF-8?q?rename=20make=5F=20=E2=80=93>=20run=5F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../multiple_swiftlint/strategy_maker.rb | 24 +++++++++---------- .../multiple_swiftlint/swiftlint.rb | 10 ++++---- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb index 74419b7..14fcdf0 100644 --- a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb +++ b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb @@ -23,7 +23,7 @@ class StrategyMaker @swiftlint_lint_command = @swiftlint + ' --path ' + @source_directory + ' --config ' end - def make_fully_multiple_strategy(source_date) + def run_fully_multiple_strategy(source_date) create_yaml_managers_and_copy_temporary_files exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) @@ -37,10 +37,10 @@ class StrategyMaker @touchin_swiftlint_yaml_manager.update('excluded', total_touchin_excluded_files) @old_swiftlint_yaml_manager.update('excluded', total_old_excluded_files) - make_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) + run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) end - def make_simplified_multiple_strategy(source_date, depth_git_count) + def run_simplified_multiple_strategy(source_date, depth_git_count) included_files = GitСaretaker.get_modified_files if included_files.nilOrEmpty? @@ -69,21 +69,21 @@ class StrategyMaker is_exist_total_old_included_files = (not total_old_included_files.nilOrEmpty?) if is_exist_total_touchin_included_files and is_exist_total_old_included_files - make_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) + run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) elsif is_exist_total_touchin_included_files and not is_exist_total_old_included_files - make_single_strategy(@touchin_swiftlint_yaml_temporary_path) + run_single_strategy(@touchin_swiftlint_yaml_temporary_path) elsif not is_exist_total_touchin_included_files and is_exist_total_old_included_files - make_single_strategy(@old_swiftlint_yaml_temporary_path) + run_single_strategy(@old_swiftlint_yaml_temporary_path) else puts 'Git did not found swift files to check' end end - def make_fully_single_strategy - make_single_strategy(@touchin_swiftlint_yaml_path) + def run_fully_single_strategy + run_single_strategy(@touchin_swiftlint_yaml_path) end - def make_simplified_single_strategy(depth_git_count) + def run_simplified_single_strategy(depth_git_count) included_files = GitСaretaker.get_modified_files if included_files.nilOrEmpty? @@ -104,7 +104,7 @@ class StrategyMaker touchin_swiftlint_yaml_manager.update('included', included_files) if not included_files.nilOrEmpty? - make_single_strategy(@touchin_swiftlint_yaml_temporary_path) + run_single_strategy(@touchin_swiftlint_yaml_temporary_path) else puts 'Git found the swift files to check, but they are excluded in yaml' end @@ -112,13 +112,13 @@ class StrategyMaker private - def make_single_strategy(swiftlint_yaml_path) + def run_single_strategy(swiftlint_yaml_path) result_swiftlint_command = get_swiftlint_command(swiftlint_yaml_path) puts result_swiftlint_command run_bash_command(result_swiftlint_command) end - def make_multiple_strategy(touchin_swiftlint_yaml_temporary_path, old_swiftlint_yaml_temporary_path) + def run_multiple_strategy(touchin_swiftlint_yaml_temporary_path, old_swiftlint_yaml_temporary_path) touchin_swiftlint_command = get_swiftlint_command(touchin_swiftlint_yaml_temporary_path) old_swiftlint_command = get_swiftlint_command(old_swiftlint_yaml_temporary_path) result_swiftlint_command = touchin_swiftlint_command + ' && ' + old_swiftlint_command diff --git a/xcode/build_phases/multiple_swiftlint/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/swiftlint.rb index a499be7..cf8852c 100644 --- a/xcode/build_phases/multiple_swiftlint/swiftlint.rb +++ b/xcode/build_phases/multiple_swiftlint/swiftlint.rb @@ -6,14 +6,14 @@ Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 setting = SettingOption.new -maker = StrategyMaker.new(setting.source_directory, setting.pods_directory, setting.touchin_swiftlint_yaml_path) +strategy_maker = StrategyMaker.new(setting.source_directory, setting.pods_directory, setting.touchin_swiftlint_yaml_path) if setting.check_mode.eql? 'fully' and setting.use_multiple.true? - maker.make_fully_multiple_strategy(setting.source_date) + strategy_maker.run_fully_multiple_strategy(setting.source_date) elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true? - maker.make_fully_single_strategy + strategy_maker.run_fully_single_strategy elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true? - maker.make_simplified_multiple_strategy(setting.source_date, setting.depth_git_count) + strategy_maker.run_simplified_multiple_strategy(setting.source_date, setting.depth_git_count) elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true? - maker.make_simplified_single_strategy(setting.depth_git_count) + strategy_maker.run_simplified_single_strategy(setting.depth_git_count) end From c5cde472dd48c0f4550037813f251fd10f5cf1d4 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Wed, 29 Jul 2020 12:40:54 +0300 Subject: [PATCH 14/43] =?UTF-8?q?changed=20pods=5Fdirectory=20=E2=80=93>?= =?UTF-8?q?=20swiftlint=5Fexecutable=5Fpath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../build_phases/multiple_swiftlint/setting_option.rb | 6 +++--- .../build_phases/multiple_swiftlint/strategy_maker.rb | 11 ++++------- xcode/build_phases/multiple_swiftlint/swiftlint.rb | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/xcode/build_phases/multiple_swiftlint/setting_option.rb b/xcode/build_phases/multiple_swiftlint/setting_option.rb index 338d56e..923acab 100644 --- a/xcode/build_phases/multiple_swiftlint/setting_option.rb +++ b/xcode/build_phases/multiple_swiftlint/setting_option.rb @@ -8,7 +8,7 @@ class SettingOption @options = OpenStruct.new OptionParser.new do |opt| opt.on('-s', '--source_directory STRING', 'The directory of source') { |option| @options.source_directory = option } - opt.on('-p', '--pods_directory STRING', 'The directory of pods') { |option| @options.pods_directory = option } + opt.on('-l', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option } opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option } @@ -41,8 +41,8 @@ class SettingOption @options.source_date end - def pods_directory - @options.pods_directory + def swiftlint_executable_path + @options.swiftlint_executable_path end def check_mode diff --git a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb index 14fcdf0..28e4ee3 100644 --- a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb +++ b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb @@ -7,11 +7,8 @@ require_relative 'swift_file_manager.rb' require_relative 'yaml_manager.rb' class StrategyMaker - def initialize(source_directory, pods_directory, touchin_swiftlint_yaml_path) - @source_directory = source_directory - @pods_directory = pods_directory - @swiftlint = pods_directory + '/SwiftLint/swiftlint' - + def initialize(source_directory, swiftlint_executable_path, touchin_swiftlint_yaml_path) + @source_directory = source_directory @touchin_swiftlint_yaml_path = source_directory + touchin_swiftlint_yaml_path @old_swiftlint_yaml_path = source_directory + '/.swiftlint.yml' @@ -19,8 +16,8 @@ class StrategyMaker @touchin_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.touchin_swiftlint.yml' @old_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.old_swiftlint.yml' - @swiftlint_autocorrect_command = @swiftlint + ' autocorrect --path ' + @source_directory + ' --config ' - @swiftlint_lint_command = @swiftlint + ' --path ' + @source_directory + ' --config ' + @swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @source_directory + ' --config ' + @swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @source_directory + ' --config ' end def run_fully_multiple_strategy(source_date) diff --git a/xcode/build_phases/multiple_swiftlint/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/swiftlint.rb index cf8852c..533c927 100644 --- a/xcode/build_phases/multiple_swiftlint/swiftlint.rb +++ b/xcode/build_phases/multiple_swiftlint/swiftlint.rb @@ -6,7 +6,7 @@ Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 setting = SettingOption.new -strategy_maker = StrategyMaker.new(setting.source_directory, setting.pods_directory, setting.touchin_swiftlint_yaml_path) +strategy_maker = StrategyMaker.new(setting.source_directory, setting.swiftlint_executable_path, setting.touchin_swiftlint_yaml_path) if setting.check_mode.eql? 'fully' and setting.use_multiple.true? strategy_maker.run_fully_multiple_strategy(setting.source_date) From dcf88a7be578c576bb42b0d60da051978b14fa64 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Wed, 29 Jul 2020 13:54:17 +0300 Subject: [PATCH 15/43] =?UTF-8?q?replace=20depth=5Fgit=5Fcount=20=E2=80=93?= =?UTF-8?q?>=20git=5Fdirectory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../build_phases/multiple_swiftlint/setting_option.rb | 10 +++++----- .../build_phases/multiple_swiftlint/strategy_maker.rb | 8 ++++---- .../multiple_swiftlint/string_extension.rb | 8 -------- xcode/build_phases/multiple_swiftlint/swiftlint.rb | 4 ++-- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/xcode/build_phases/multiple_swiftlint/setting_option.rb b/xcode/build_phases/multiple_swiftlint/setting_option.rb index 923acab..998cd83 100644 --- a/xcode/build_phases/multiple_swiftlint/setting_option.rb +++ b/xcode/build_phases/multiple_swiftlint/setting_option.rb @@ -9,11 +9,11 @@ class SettingOption OptionParser.new do |opt| opt.on('-s', '--source_directory STRING', 'The directory of source') { |option| @options.source_directory = option } opt.on('-l', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option } + opt.on('-g', '--git_directory STRING', 'The directory of git') { |option| @options.git_directory = option } opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option } opt.on('-y', '--touchin_swiftlint_yaml_path STRING', 'The path to the touchin swiftlint yaml relative to the source directory') { |option| @options.touchin_swiftlint_yaml_path = option } - opt.on('-g', '--depth_git_count Int', 'The depth between the git directory and sources directory') { |option| @options.depth_git_count = option } end.parse! if @options.check_mode.to_s.nilOrEmpty? @@ -24,8 +24,8 @@ class SettingOption @options.use_multiple = 'false' end - if @options.depth_git_count.to_s.nilOrEmpty? - @options.depth_git_count = 0 + if @options.git_directory.to_s.nilOrEmpty? + @options.git_directory = @options.source_directory end if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty? @@ -53,8 +53,8 @@ class SettingOption @options.use_multiple end - def depth_git_count - @options.depth_git_count + def git_directory + @options.git_directory end def touchin_swiftlint_yaml_path diff --git a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb index 28e4ee3..e92c0bb 100644 --- a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb +++ b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb @@ -37,7 +37,7 @@ class StrategyMaker run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) end - def run_simplified_multiple_strategy(source_date, depth_git_count) + def run_simplified_multiple_strategy(source_date, git_directory) included_files = GitСaretaker.get_modified_files if included_files.nilOrEmpty? @@ -48,7 +48,7 @@ class StrategyMaker create_yaml_managers_and_copy_temporary_files exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) - included_files = included_files.map { |file_path| file_path.add_back_to_path(depth_git_count) } + included_files = included_files.map { |file_path| git_directory + file_path } swift_file_manager = SwiftFileManager.new(exclude_files, source_date) swift_file_manager.find_list_file_paths_from(included_files) @@ -80,7 +80,7 @@ class StrategyMaker run_single_strategy(@touchin_swiftlint_yaml_path) end - def run_simplified_single_strategy(depth_git_count) + def run_simplified_single_strategy(git_directory) included_files = GitСaretaker.get_modified_files if included_files.nilOrEmpty? @@ -95,7 +95,7 @@ class StrategyMaker swift_files = SwiftFileManager.new(touchin_excluded_files, '') included_files = included_files.select { |file_name| not swift_files.is_excluded_file(file_name) } - included_files = included_files.map { |file_path| file_path.add_back_to_path(depth_git_count) } + included_files = included_files.map { |file_path| git_directory + file_path } touchin_swiftlint_yaml_manager.update('excluded', []) touchin_swiftlint_yaml_manager.update('included', included_files) diff --git a/xcode/build_phases/multiple_swiftlint/string_extension.rb b/xcode/build_phases/multiple_swiftlint/string_extension.rb index 5b409e1..33a6357 100644 --- a/xcode/build_phases/multiple_swiftlint/string_extension.rb +++ b/xcode/build_phases/multiple_swiftlint/string_extension.rb @@ -11,14 +11,6 @@ class String self.to_s.downcase == "true" end - def add_back_to_path(count) - string = self - count.to_i.times { |i| - string = '../' + string - } - return string - end - def nilOrEmpty? self.nil? or self.empty? end diff --git a/xcode/build_phases/multiple_swiftlint/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/swiftlint.rb index 533c927..74d1f6c 100644 --- a/xcode/build_phases/multiple_swiftlint/swiftlint.rb +++ b/xcode/build_phases/multiple_swiftlint/swiftlint.rb @@ -13,7 +13,7 @@ if setting.check_mode.eql? 'fully' and setting.use_multiple.true? elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true? strategy_maker.run_fully_single_strategy elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true? - strategy_maker.run_simplified_multiple_strategy(setting.source_date, setting.depth_git_count) + strategy_maker.run_simplified_multiple_strategy(setting.source_date, setting.git_directory) elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true? - strategy_maker.run_simplified_single_strategy(setting.depth_git_count) + strategy_maker.run_simplified_single_strategy(setting.git_directory) end From 04c863cc14679bb6088672723d40a1c47e32b5c5 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Wed, 29 Jul 2020 17:36:14 +0300 Subject: [PATCH 16/43] fix naming and remove unnecessary code --- .../multiple_swiftlint/setting_option.rb | 12 ++++++------ .../multiple_swiftlint/strategy_maker.rb | 16 ++++++++-------- .../multiple_swiftlint/swift_file_manager.rb | 5 ++--- .../build_phases/multiple_swiftlint/swiftlint.rb | 5 +---- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/xcode/build_phases/multiple_swiftlint/setting_option.rb b/xcode/build_phases/multiple_swiftlint/setting_option.rb index 998cd83..0941e28 100644 --- a/xcode/build_phases/multiple_swiftlint/setting_option.rb +++ b/xcode/build_phases/multiple_swiftlint/setting_option.rb @@ -7,8 +7,8 @@ class SettingOption def initialize @options = OpenStruct.new OptionParser.new do |opt| - opt.on('-s', '--source_directory STRING', 'The directory of source') { |option| @options.source_directory = option } - opt.on('-l', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option } + opt.on('-p', '--project_directory STRING', 'The directory of project') { |option| @options.project_directory = option } + opt.on('-s', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option } opt.on('-g', '--git_directory STRING', 'The directory of git') { |option| @options.git_directory = option } opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } @@ -25,7 +25,7 @@ class SettingOption end if @options.git_directory.to_s.nilOrEmpty? - @options.git_directory = @options.source_directory + @options.git_directory = @options.project_directory end if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty? @@ -33,8 +33,8 @@ class SettingOption end end - def source_directory - @options.source_directory + def project_directory + @options.project_directory end def source_date @@ -60,4 +60,4 @@ class SettingOption def touchin_swiftlint_yaml_path @options.touchin_swiftlint_yaml_path end -end \ No newline at end of file +end diff --git a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb index e92c0bb..a289f5f 100644 --- a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb +++ b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb @@ -7,17 +7,17 @@ require_relative 'swift_file_manager.rb' require_relative 'yaml_manager.rb' class StrategyMaker - def initialize(source_directory, swiftlint_executable_path, touchin_swiftlint_yaml_path) - @source_directory = source_directory - @touchin_swiftlint_yaml_path = source_directory + touchin_swiftlint_yaml_path - @old_swiftlint_yaml_path = source_directory + '/.swiftlint.yml' + def initialize(project_directory, swiftlint_executable_path, touchin_swiftlint_yaml_path) + @project_directory = project_directory + @touchin_swiftlint_yaml_path = project_directory + touchin_swiftlint_yaml_path + @old_swiftlint_yaml_path = project_directory + '/.swiftlint.yml' - @temporary_swiftlint_folder_name = source_directory + '/temporary_swiftlint' + @temporary_swiftlint_folder_name = project_directory + '/temporary_swiftlint' @touchin_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.touchin_swiftlint.yml' @old_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.old_swiftlint.yml' - @swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @source_directory + ' --config ' - @swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @source_directory + ' --config ' + @swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @project_directory + ' --config ' + @swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @project_directory + ' --config ' end def run_fully_multiple_strategy(source_date) @@ -26,7 +26,7 @@ class StrategyMaker exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) swift_files = SwiftFileManager.new(exclude_files, source_date) - swift_files.find_list_file_paths(@source_directory) + swift_files.find_list_file_paths(@project_directory) total_touchin_excluded_files = exclude_files + swift_files.old_files total_old_excluded_files = exclude_files + swift_files.new_files diff --git a/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb b/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb index dd0d0f7..b8edf6c 100644 --- a/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb +++ b/xcode/build_phases/multiple_swiftlint/swift_file_manager.rb @@ -52,13 +52,12 @@ class SwiftFileManager def compare_timestamp(file_path) wrapped_whitespace_file_path = file_path.with_wrapped_whitespace creation_date_string = GitСaretaker.get_creation_date(wrapped_whitespace_file_path) - puts file_path if creation_date_string.nilOrEmpty? @old_files.push(file_path) - puts 'Not found the creation date' + puts ('Creation date of ' + file_path + ' was not found') else creation_date = Date.parse(creation_date_string) - puts creation_date + puts ('Creation date of ' + file_path + ' is ' + creation_date.to_s) if @source_date < creation_date @new_files.push(file_path) else diff --git a/xcode/build_phases/multiple_swiftlint/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/swiftlint.rb index 74d1f6c..e9cc0d2 100644 --- a/xcode/build_phases/multiple_swiftlint/swiftlint.rb +++ b/xcode/build_phases/multiple_swiftlint/swiftlint.rb @@ -2,11 +2,8 @@ require_relative 'setting_option.rb' require_relative 'strategy_maker.rb' -Encoding.default_external = Encoding::UTF_8 -Encoding.default_internal = Encoding::UTF_8 - setting = SettingOption.new -strategy_maker = StrategyMaker.new(setting.source_directory, setting.swiftlint_executable_path, setting.touchin_swiftlint_yaml_path) +strategy_maker = StrategyMaker.new(setting.project_directory, setting.swiftlint_executable_path, setting.touchin_swiftlint_yaml_path) if setting.check_mode.eql? 'fully' and setting.use_multiple.true? strategy_maker.run_fully_multiple_strategy(setting.source_date) From 0eb6a299d77ae1ee561dadc058ec880e7fa51aa5 Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Thu, 30 Jul 2020 11:51:58 +0300 Subject: [PATCH 17/43] =?UTF-8?q?rename=20project=5Fdirectory=20=E2=80=93>?= =?UTF-8?q?=20project=5Froot=5Fpath,=20git=5Fdirectory=20=E2=80=93>=20sour?= =?UTF-8?q?ce=5Froot=5Fpath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../multiple_swiftlint/setting_option.rb | 16 ++++++------- .../multiple_swiftlint/strategy_maker.rb | 24 +++++++++---------- .../multiple_swiftlint/swiftlint.rb | 6 ++--- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/xcode/build_phases/multiple_swiftlint/setting_option.rb b/xcode/build_phases/multiple_swiftlint/setting_option.rb index 0941e28..e3d0ccf 100644 --- a/xcode/build_phases/multiple_swiftlint/setting_option.rb +++ b/xcode/build_phases/multiple_swiftlint/setting_option.rb @@ -7,9 +7,9 @@ class SettingOption def initialize @options = OpenStruct.new OptionParser.new do |opt| - opt.on('-p', '--project_directory STRING', 'The directory of project') { |option| @options.project_directory = option } + opt.on('-p', '--project_root_path STRING', 'The path of project directory') { |option| @options.project_root_path = option } + opt.on('-r', '--source_root_path STRING', 'The path of source directory ') { |option| @options.source_root_path = option } opt.on('-s', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option } - opt.on('-g', '--git_directory STRING', 'The directory of git') { |option| @options.git_directory = option } opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } opt.on('-d', '--source_date DATE', 'The date of grouping files according touchin and old swiftlint rules') { |option| @options.source_date = option } @@ -24,8 +24,8 @@ class SettingOption @options.use_multiple = 'false' end - if @options.git_directory.to_s.nilOrEmpty? - @options.git_directory = @options.project_directory + if @options.source_root_path.to_s.nilOrEmpty? + @options.source_root_path = @options.project_root_path end if @options.touchin_swiftlint_yaml_path.to_s.nilOrEmpty? @@ -33,8 +33,8 @@ class SettingOption end end - def project_directory - @options.project_directory + def project_root_path + @options.project_root_path end def source_date @@ -53,8 +53,8 @@ class SettingOption @options.use_multiple end - def git_directory - @options.git_directory + def source_root_path + @options.source_root_path end def touchin_swiftlint_yaml_path diff --git a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb index a289f5f..a677892 100644 --- a/xcode/build_phases/multiple_swiftlint/strategy_maker.rb +++ b/xcode/build_phases/multiple_swiftlint/strategy_maker.rb @@ -7,17 +7,17 @@ require_relative 'swift_file_manager.rb' require_relative 'yaml_manager.rb' class StrategyMaker - def initialize(project_directory, swiftlint_executable_path, touchin_swiftlint_yaml_path) - @project_directory = project_directory - @touchin_swiftlint_yaml_path = project_directory + touchin_swiftlint_yaml_path - @old_swiftlint_yaml_path = project_directory + '/.swiftlint.yml' + def initialize(project_root_path, swiftlint_executable_path, touchin_swiftlint_yaml_path) + @project_root_path = project_root_path + @touchin_swiftlint_yaml_path = project_root_path + touchin_swiftlint_yaml_path + @old_swiftlint_yaml_path = project_root_path + '/.swiftlint.yml' - @temporary_swiftlint_folder_name = project_directory + '/temporary_swiftlint' + @temporary_swiftlint_folder_name = project_root_path + '/temporary_swiftlint' @touchin_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.touchin_swiftlint.yml' @old_swiftlint_yaml_temporary_path = @temporary_swiftlint_folder_name + '/.old_swiftlint.yml' - @swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @project_directory + ' --config ' - @swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @project_directory + ' --config ' + @swiftlint_autocorrect_command = swiftlint_executable_path + ' autocorrect --path ' + @project_root_path + ' --config ' + @swiftlint_lint_command = swiftlint_executable_path + ' --path ' + @project_root_path + ' --config ' end def run_fully_multiple_strategy(source_date) @@ -26,7 +26,7 @@ class StrategyMaker exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) swift_files = SwiftFileManager.new(exclude_files, source_date) - swift_files.find_list_file_paths(@project_directory) + swift_files.find_list_file_paths(@project_root_path) total_touchin_excluded_files = exclude_files + swift_files.old_files total_old_excluded_files = exclude_files + swift_files.new_files @@ -37,7 +37,7 @@ class StrategyMaker run_multiple_strategy(@touchin_swiftlint_yaml_temporary_path, @old_swiftlint_yaml_temporary_path) end - def run_simplified_multiple_strategy(source_date, git_directory) + def run_simplified_multiple_strategy(source_date, source_root_path) included_files = GitСaretaker.get_modified_files if included_files.nilOrEmpty? @@ -48,7 +48,7 @@ class StrategyMaker create_yaml_managers_and_copy_temporary_files exclude_files = unique_exclude_files(@touchin_swiftlint_yaml_manager, @old_swiftlint_yaml_manager) - included_files = included_files.map { |file_path| git_directory + file_path } + included_files = included_files.map { |file_path| source_root_path + file_path } swift_file_manager = SwiftFileManager.new(exclude_files, source_date) swift_file_manager.find_list_file_paths_from(included_files) @@ -80,7 +80,7 @@ class StrategyMaker run_single_strategy(@touchin_swiftlint_yaml_path) end - def run_simplified_single_strategy(git_directory) + def run_simplified_single_strategy(source_root_path) included_files = GitСaretaker.get_modified_files if included_files.nilOrEmpty? @@ -95,7 +95,7 @@ class StrategyMaker swift_files = SwiftFileManager.new(touchin_excluded_files, '') included_files = included_files.select { |file_name| not swift_files.is_excluded_file(file_name) } - included_files = included_files.map { |file_path| git_directory + file_path } + included_files = included_files.map { |file_path| source_root_path + file_path } touchin_swiftlint_yaml_manager.update('excluded', []) touchin_swiftlint_yaml_manager.update('included', included_files) diff --git a/xcode/build_phases/multiple_swiftlint/swiftlint.rb b/xcode/build_phases/multiple_swiftlint/swiftlint.rb index e9cc0d2..17f8383 100644 --- a/xcode/build_phases/multiple_swiftlint/swiftlint.rb +++ b/xcode/build_phases/multiple_swiftlint/swiftlint.rb @@ -3,14 +3,14 @@ require_relative 'setting_option.rb' require_relative 'strategy_maker.rb' setting = SettingOption.new -strategy_maker = StrategyMaker.new(setting.project_directory, setting.swiftlint_executable_path, setting.touchin_swiftlint_yaml_path) +strategy_maker = StrategyMaker.new(setting.project_root_path, setting.swiftlint_executable_path, setting.touchin_swiftlint_yaml_path) if setting.check_mode.eql? 'fully' and setting.use_multiple.true? strategy_maker.run_fully_multiple_strategy(setting.source_date) elsif setting.check_mode.eql? 'fully' and not setting.use_multiple.true? strategy_maker.run_fully_single_strategy elsif setting.check_mode.eql? 'simplified' and setting.use_multiple.true? - strategy_maker.run_simplified_multiple_strategy(setting.source_date, setting.git_directory) + strategy_maker.run_simplified_multiple_strategy(setting.source_date, setting.source_root_path) elsif setting.check_mode.eql? 'simplified' and not setting.use_multiple.true? - strategy_maker.run_simplified_single_strategy(setting.git_directory) + strategy_maker.run_simplified_single_strategy(setting.source_root_path) end From d70fc7f34dc47d7b454fb90fb1caf9696505607a Mon Sep 17 00:00:00 2001 From: Maxim Sorokin Date: Thu, 30 Jul 2020 12:19:38 +0300 Subject: [PATCH 18/43] changed description for project_root_path and source_root_path --- xcode/build_phases/multiple_swiftlint/setting_option.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xcode/build_phases/multiple_swiftlint/setting_option.rb b/xcode/build_phases/multiple_swiftlint/setting_option.rb index e3d0ccf..44b8d7e 100644 --- a/xcode/build_phases/multiple_swiftlint/setting_option.rb +++ b/xcode/build_phases/multiple_swiftlint/setting_option.rb @@ -7,8 +7,10 @@ class SettingOption def initialize @options = OpenStruct.new OptionParser.new do |opt| - opt.on('-p', '--project_root_path STRING', 'The path of project directory') { |option| @options.project_root_path = option } - opt.on('-r', '--source_root_path STRING', 'The path of source directory ') { |option| @options.source_root_path = option } + opt.on('-p', '--project_root_path STRING', 'The path of project directory and contains *.xcodeproj file always. ' + + 'Example: project_root_path=~/Projects/MyProject/Source/..') { |option| @options.project_root_path = option } + opt.on('-r', '--source_root_path STRING', 'The path of source directory and may not contains *.xcodeproj file in some cases. ' + + 'Example: source_root_path=~/Projects/MyProject/') { |option| @options.source_root_path = option } opt.on('-s', '--swiftlint_executable_path STRING', 'The executable path of swiftlint') { |option| @options.swiftlint_executable_path = option } opt.on('-c', '--check_mode MODE', 'The mode of check is "fully" or "simplified"') { |option| @options.check_mode = option } opt.on('-u', '--use_multiple BOOL', 'The flag indicates the use of multiple yaml swiftlint configurations') { |option| @options.use_multiple = option } From e1d0747fc3656b02c9db7b0b8f7a74d27770ff58 Mon Sep 17 00:00:00 2001 From: Vitaliy Salnikov Date: Fri, 7 Aug 2020 15:26:52 +0300 Subject: [PATCH 19/43] Add output path option for xcconfig rendering --- xcode/config_generator/render_xcconfigs.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/xcode/config_generator/render_xcconfigs.rb b/xcode/config_generator/render_xcconfigs.rb index 64d6b8e..e08f18a 100755 --- a/xcode/config_generator/render_xcconfigs.rb +++ b/xcode/config_generator/render_xcconfigs.rb @@ -2,15 +2,13 @@ require 'json' require 'mustache' require 'yaml' -# Usage: render_xcconfigs.rb # -# Result: Adds .xcconfig files to $configs_folder_name directory. +# Usage: render_xcconfigs.rb [] +# +# Result: Adds .xcconfig files to ouptut folder. # Files are only being added and changed, not removed! # It is recommended to remove old .xcconfig files before running this script. - - -# Constants -$configs_folder_name = "TargetConfigurations" +# class String def in_current_dir @@ -23,10 +21,11 @@ configurations_file_path = ARGV[0] temp_configs_data_file_path = "configs_data.json".in_current_dir generator_path = "build_options_helper/helper.py".in_current_dir template_path = "target_xcconfig.mustache".in_current_dir -build_parameters_path = ARGV[1] || "build_parameters.yaml".in_current_dir +build_parameters_path = ARGV[1] +configs_folder_name = ARGV[2] || "TargetConfigurations" # Create config directory if needed -Dir.mkdir($configs_folder_name) unless Dir.exist?($configs_folder_name) +Dir.mkdir(configs_folder_name) unless Dir.exist?(configs_folder_name) # Call python script and generate configs to config file system("python #{generator_path} -bp #{build_parameters_path} -o #{__dir__} -r ios_build_settings -p ios") @@ -147,7 +146,7 @@ targets.each do |target_name, target| } # Create file for every setting in loop - File.open($configs_folder_name + "/" + target_name + config["name"] + ".xcconfig", 'w') { |file| + File.open(configs_folder_name + "/" + target_name + config["name"] + ".xcconfig", 'w') { |file| file.puts(Mustache.render(target_xcconfig_tempate, config_data)) } end From 1b444a458208831921b3b5bd90361f225569881d Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Wed, 19 Aug 2020 17:06:08 +0300 Subject: [PATCH 20/43] move apigen and static analysis scripts to plugins. removed extra files --- checkstyle/configuration/google_checks.xml | 210 ----------- .../configuration/touchin_checkstyle.xml | 339 ------------------ findbugs/filters/findbugs-filter.xml | 23 -- gradle/apiGenerator.gradle | 44 --- gradle/apiGeneratorKotlinServer.gradle | 38 -- gradle/commonStaticAnalysis.gradle | 233 ------------ gradle/plugins/.gitignore | 19 + gradle/plugins/build.gradle.kts | 52 +++ gradle/plugins/settings.gradle.kts | 0 .../java/apigen/ApiGeneratorAndroidPlugin.kt | 37 ++ .../java/apigen/ApiGeneratorBackendPlugin.kt | 19 + .../main/java/apigen/ApiGeneratorExtension.kt | 22 ++ .../main/java/apigen/ApiGeneratorPlugin.kt | 76 ++++ .../errors/AndroidLintError.kt | 12 + .../java/static_analysis/errors/CpdError.kt | 12 + .../static_analysis/errors/DetektError.kt | 12 + .../errors/StaticAnalysisError.kt | 5 + .../static_analysis/linters/AndroidLinter.kt | 65 ++++ .../java/static_analysis/linters/CpdLinter.kt | 57 +++ .../static_analysis/linters/DetektLinter.kt | 62 ++++ .../java/static_analysis/linters/Linter.kt | 12 + .../plugins/StaticAnalysisAndroidPlugin.kt | 43 +++ .../plugins/StaticAnalysisBackendPlugin.kt | 21 ++ .../plugins/StaticAnalysisExtension.kt | 6 + .../plugins/StaticAnalysisPlugin.kt | 47 +++ .../java/static_analysis/utils/Extensions.kt | 33 ++ .../static_analysis/utils/ReportGenerator.kt | 52 +++ .../applicationFileNaming.gradle | 0 gradle/{ => scripts}/stringGenerator.gradle | 0 gradle/staticAnalysis.gradle | 166 --------- lint/lint.xml | 272 -------------- pmd/rulesets/java/android.xml | 131 ------- export_src.sh => scripts/export_src.sh | 0 .../detekt-config.yml | 2 +- static_analysis_configs/lint.xml | 273 ++++++++++++++ 35 files changed, 938 insertions(+), 1457 deletions(-) delete mode 100755 checkstyle/configuration/google_checks.xml delete mode 100755 checkstyle/configuration/touchin_checkstyle.xml delete mode 100644 findbugs/filters/findbugs-filter.xml delete mode 100644 gradle/apiGenerator.gradle delete mode 100644 gradle/apiGeneratorKotlinServer.gradle delete mode 100644 gradle/commonStaticAnalysis.gradle create mode 100644 gradle/plugins/.gitignore create mode 100644 gradle/plugins/build.gradle.kts create mode 100644 gradle/plugins/settings.gradle.kts create mode 100644 gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt create mode 100644 gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt create mode 100644 gradle/plugins/src/main/java/apigen/ApiGeneratorExtension.kt create mode 100644 gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/errors/CpdError.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/errors/DetektError.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/errors/StaticAnalysisError.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/linters/Linter.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisAndroidPlugin.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisBackendPlugin.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisExtension.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisPlugin.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/utils/Extensions.kt create mode 100644 gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt rename gradle/{ => scripts}/applicationFileNaming.gradle (100%) rename gradle/{ => scripts}/stringGenerator.gradle (100%) delete mode 100644 gradle/staticAnalysis.gradle delete mode 100644 lint/lint.xml delete mode 100644 pmd/rulesets/java/android.xml rename export_src.sh => scripts/export_src.sh (100%) rename {kotlin => static_analysis_configs}/detekt-config.yml (99%) create mode 100644 static_analysis_configs/lint.xml diff --git a/checkstyle/configuration/google_checks.xml b/checkstyle/configuration/google_checks.xml deleted file mode 100755 index 441f1af..0000000 --- a/checkstyle/configuration/google_checks.xml +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/checkstyle/configuration/touchin_checkstyle.xml b/checkstyle/configuration/touchin_checkstyle.xml deleted file mode 100755 index b36d47f..0000000 --- a/checkstyle/configuration/touchin_checkstyle.xml +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/findbugs/filters/findbugs-filter.xml b/findbugs/filters/findbugs-filter.xml deleted file mode 100644 index bb462be..0000000 --- a/findbugs/filters/findbugs-filter.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gradle/apiGenerator.gradle b/gradle/apiGenerator.gradle deleted file mode 100644 index fc9dae3..0000000 --- a/gradle/apiGenerator.gradle +++ /dev/null @@ -1,44 +0,0 @@ -repositories { - maven { - url 'https://dl.bintray.com/touchin/touchin-tools' - metadataSources { - artifact() - } - } -} - -configurations { - apigenerator -} - -dependencies { - apigenerator 'ru.touchin:api-generator:1.4.0-beta3' -} - -android.libraryVariants.all { variant -> - final File generatedModelsDirectory = new File("${project.buildDir}/generated/source/models/${variant.dirName}") - - def generateJsonModelsTask = tasks.create("apiGenerator${variant.name}") doLast { - javaexec { - main = "-jar" - workingDir = file("${rootDir}") - args = [ - configurations.apigenerator.asPath, - "generate-client-code", - "--output-language", - "KOTLIN", - "--specification-path", - rootProject.extensions.findByName("pathToApiSchemes"), - "--kotlin-methods-generation-mode", - "COROUTINE", - "--output-path", - "${generatedModelsDirectory.path}", - "--package-name", - "${rootProject.extensions.findByName("applicationId") ?: applicationId}" - ] - } - } - - generateJsonModelsTask.description = 'Generates Java classes for JSON models' - variant.registerJavaGeneratingTask generateJsonModelsTask, generatedModelsDirectory -} diff --git a/gradle/apiGeneratorKotlinServer.gradle b/gradle/apiGeneratorKotlinServer.gradle deleted file mode 100644 index 66676b5..0000000 --- a/gradle/apiGeneratorKotlinServer.gradle +++ /dev/null @@ -1,38 +0,0 @@ -repositories { - maven { - url "https://dl.bintray.com/touchin/touchin-tools" - metadataSources { - artifact() - } - } -} - -configurations { - apigeneratorKotlinServer -} - -dependencies { - apigeneratorKotlinServer 'ru.touchin:api-generator:1.4.0-beta1' -} - -task generateApiModelsKotlinServer doLast { - javaexec { - main = "-jar" - workingDir = file("${rootDir}") - args = [ - configurations.apigeneratorKotlinServer.asPath, - "generate-client-code", - "--output-language", - "KOTLIN_SERVER", - "--specification-path", - rootProject.extensions.findByName("pathToApiSchemes"), - "--output-path", - "${rootDir}/src/main/kotlin", - "--package-name", - rootProject.extensions.findByName("apiPackageName"), - "--recreate_output_dirs", - false - ] - } -} - diff --git a/gradle/commonStaticAnalysis.gradle b/gradle/commonStaticAnalysis.gradle deleted file mode 100644 index b929257..0000000 --- a/gradle/commonStaticAnalysis.gradle +++ /dev/null @@ -1,233 +0,0 @@ -apply plugin: 'cpd' -apply plugin: 'io.gitlab.arturbosch.detekt' - -def getCpdTask -def getLintTask -def getKotlinDetektTasks - -def appendError -def appendCpdErrors -def appendKotlinErrors -def appendLintErrors - -repositories { - maven { url "http://dl.bintray.com/touchin/touchin-tools" } -} - -configurations { - pngtastic -} - -cpd { - skipLexicalErrors = true -} - -import org.apache.tools.ant.taskdefs.condition.Os - -ext.getIdeaFormatTask = { isAndroidProject, sources -> - def ideaPath = System.getenv("IDEA_HOME") - if (ideaPath == null) { - return tasks.create((isAndroidProject ? "android" : "server") + "donothing") - } - return tasks.create((isAndroidProject ? "android" : "server") + "IdeaFormat_$project.name", Exec) { - def inspectionPath - def params = ["-r", "-mask", "*.java,*.kt,*.xml"] - for (String source : sources) { - params.add(source) - } - - if (Os.isFamily(Os.FAMILY_WINDOWS)) { - inspectionPath = ['cmd', '/c', "\"${ideaPath}\\bin\\format.bat\" ${params.join(" ")}"] - } else { - inspectionPath = ["$ideaPath/bin/format.sh"] - } - commandLine inspectionPath - if (!Os.isFamily(Os.FAMILY_WINDOWS)) { - args = params - } - } -} - -ext.getStaticAnalysisTaskNames = { isAndroidProject, sources, buildVariant -> - def tasksNames = new ArrayList() - try { - tasksNames.add(getCpdTask(isAndroidProject, sources)) - tasksNames.addAll(getKotlinDetektTasks()) - if (isAndroidProject) { - tasksNames.add(getLintTask(buildVariant)) - } - } catch (Exception exception) { - println(exception.toString()) - } - return tasksNames -} - -ext.generateReport = { isAndroidProject -> - StringBuilder consoleReport = new StringBuilder() - consoleReport.append("STATIC ANALYSIS RESULTS:") - def count = 0 - - def previousCount = count - count = appendCpdErrors(count, new File("${project.buildDir}/reports/cpd.xml")) - if (count - previousCount > 0) { - consoleReport.append("\nCPD: FAILED (" + (count - previousCount) + " errors)") - } else { - consoleReport.append("\nCPD: PASSED") - } - - previousCount = count - subprojects.forEach { subproject -> - def reportFile = new File("${rootProject.buildDir}/reports/kotlin-detekt-${subproject.name}.xml") - if (reportFile.exists()) { - count = appendKotlinErrors(count, reportFile).toInteger() - } - } - if (count - previousCount > 0) { - consoleReport.append("\nKotlin-detekt: FAILED (" + (count - previousCount) + " errors)") - } else { - consoleReport.append("\nKotlin-detekt: PASSED") - } - - if (isAndroidProject) { - previousCount = count - count = appendLintErrors(count, new File("${rootProject.buildDir}/reports/lint_report.xml")) - if (count - previousCount > 0) { - consoleReport.append("\nLint: FAILED (" + (count - previousCount) + " errors)") - } else { - consoleReport.append("\nLint: PASSED") - } - } - - if (count > 0) { - consoleReport.append("\nOverall: FAILED (" + count + " errors)") - throw new Exception(consoleReport.toString()) - } else { - consoleReport.append("\nOverall: PASSED") - println(consoleReport.toString()) - } -} - -appendError = { number, analyzer, file, line, errorId, errorLink, description -> - println("$number. $analyzer : $description ($errorId)\n\tat $file: $line") -} - -appendKotlinErrors = { count, checkstyleFile -> - def rootNode = new XmlParser().parse(checkstyleFile) - for (def fileNode : rootNode.children()) { - if (!fileNode.name().equals("file")) { - continue - } - - for (def errorNode : fileNode.children()) { - if (!errorNode.name().equals("error")) { - continue - } - count++ - - appendError(count, "Detekt", fileNode.attribute("name"), errorNode.attribute("line"), errorNode.attribute("source"), "", errorNode.attribute("message")) - } - } - return count -} - -appendCpdErrors = { count, cpdFile -> - def rootNode = new XmlParser().parse(cpdFile) - for (def duplicationNode : rootNode.children()) { - if (!duplicationNode.name().equals("duplication")) { - continue - } - count++ - - def duplicationIndex = 0 - - String duplicationPoints = "" - for (def filePointNode : duplicationNode.children()) { - if (filePointNode.name().equals("file")) { - def file = filePointNode.attribute("path") - def line = filePointNode.attribute("line") - duplicationPoints += "\n " + file + ":" + line - duplicationIndex++ - } - } - println("$count CPD: code duplication $duplicationPoints") - } - return count -} - -appendLintErrors = { count, lintFile -> - def rootNode = new XmlParser().parse(lintFile) - for (def issueNode : rootNode.children()) { - if (!issueNode.name().equals("issue") - || !issueNode.attribute("severity").equals("Error")) { - continue - } - for (def locationNode : issueNode.children()) { - if (!locationNode.name().equals("location")) { - continue - } - count++ - appendError(count, "Lint", locationNode.attribute("file"), locationNode.attribute("line"), - issueNode.attribute("id"), issueNode.attribute("explanation"), issueNode.attribute("message")) - } - } - return count -} - -getCpdTask = { isAndroidProject, sources -> - def taskName = (isAndroidProject ? "android" : "server") + "cpd_${rootProject.name}" - def task = tasks.findByName(taskName) - if (task == null) { - task = tasks.create(taskName, tasks.findByName('cpdCheck').getClass().getSuperclass()) { - minimumTokenCount = 60 - source = files(sources) - ignoreFailures = true - reports { - xml { - enabled = true - destination = file("${rootProject.buildDir}/reports/cpd.xml") - } - } - } - } - return task.path -} - -getLintTask = { buildVariant -> - def appProject = subprojects.find { it.plugins.hasPlugin("com.android.application") } - def lintTaskPath - if (buildVariant != null) { - lintTaskPath = ":${appProject.name}:lint${buildVariant.name.capitalize()}" - } else { - def lintDebugTasks = appProject.tasks.matching { it.getName().contains("lint") && it.getName().contains("Debug") } - lintTaskPath = lintDebugTasks.first().path - } - if (lintTaskPath == null) { - throw IllegalStateException("Unable to find lint debug task for build variant: ${buildVariant}") - } - return lintTaskPath -} - -getKotlinDetektTasks = { - subprojects - .findResults { it.tasks.findByName("detekt")?.path } - .findAll { !it.contains(":libs") } -} - -task optimizePng { - doFirst { - def jarArgs = new ArrayList() - jarArgs.add(configurations.pngtastic.asPath) - def relatedPathIndex = "${rootDir}".length() + 1 - for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/drawable**/*.png')) { - jarArgs.add(file.absolutePath.substring(relatedPathIndex)) - } - for (def file : fileTree(dir: "${rootDir}", include: '**/src/**/res/mipmap**/*.png')) { - jarArgs.add(file.absolutePath.substring(relatedPathIndex)) - } - javaexec { main = "-jar"; args = jarArgs; workingDir = file("${rootDir}") } - } -} - -dependencies { - pngtastic 'com.github.depsypher:pngtastic:1.2' -} diff --git a/gradle/plugins/.gitignore b/gradle/plugins/.gitignore new file mode 100644 index 0000000..d7e7478 --- /dev/null +++ b/gradle/plugins/.gitignore @@ -0,0 +1,19 @@ +# Generated files +bin/ +gen/ + +# Gradle files +.gradle/ +build/ +/*/build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Log Files +*.log +.gradle +.idea +.DS_Store +/captures +*.iml diff --git a/gradle/plugins/build.gradle.kts b/gradle/plugins/build.gradle.kts new file mode 100644 index 0000000..3611bcb --- /dev/null +++ b/gradle/plugins/build.gradle.kts @@ -0,0 +1,52 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + `java-gradle-plugin` + `kotlin-dsl` +} + +// The kotlin-dsl plugin requires a repository to be declared +repositories { + jcenter() + google() +} + +dependencies { + // android gradle plugin, required by custom plugin + implementation("com.android.tools.build:gradle:4.0.1") + + implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.10.0") + implementation("de.aaschmid:gradle-cpd-plugin:3.1") + + // kotlin plugin, required by custom plugin + implementation(kotlin("gradle-plugin", embeddedKotlinVersion)) + + gradleKotlinDsl() + implementation(kotlin("stdlib-jdk8")) +} + +val compileKotlin: KotlinCompile by tasks +compileKotlin.kotlinOptions { + jvmTarget = "1.8" +} + +gradlePlugin { + plugins { + create("api-generator-android") { + id = "api-generator-android" + implementationClass = "apigen.ApiGeneratorAndroidPlugin" + } + create("api-generator-backend") { + id = "api-generator-backend" + implementationClass = "apigen.ApiGeneratorBackendPlugin" + } + create("static-analysis-android") { + id = "static-analysis-android" + implementationClass = "static_analysis.plugins.StaticAnalysisAndroidPlugin" + } + create("static-analysis-backend") { + id = "static-analysis-backend" + implementationClass = "static_analysis.plugins.StaticAnalysisBackendPlugin" + } + } +} diff --git a/gradle/plugins/settings.gradle.kts b/gradle/plugins/settings.gradle.kts new file mode 100644 index 0000000..e69de29 diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt new file mode 100644 index 0000000..fa417b0 --- /dev/null +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt @@ -0,0 +1,37 @@ +package apigen + +import com.android.build.gradle.LibraryExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() { + + override fun apply(target: Project) { + super.apply(target) + + with(target) { + val extension = getExtension() + val outputDir = getDirectoryForGeneration() + + extension.outputDirPath = outputDir.path + extension.recreateOutputDir = true + + afterEvaluate { + extensions.getByType().apply { + sourceSets.getByName("main") + .java + .srcDir(outputDir) + } + tasks + .filterIsInstance(KotlinCompile::class.java) + .forEach { + it.source(outputDir) + } + } + } + } + + private fun Project.getDirectoryForGeneration() = file("$buildDir/generated/api") + +} diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt new file mode 100644 index 0000000..b68eccf --- /dev/null +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt @@ -0,0 +1,19 @@ +package apigen + +import org.gradle.api.Project + +class ApiGeneratorBackendPlugin : ApiGeneratorPlugin() { + + override fun apply(target: Project) { + super.apply(target) + + with(target) { + val extension = getExtension() + + extension.outputDirPath = file("src/main/kotlin").path + extension.recreateOutputDir = false + extension.outputLanguage = OutputLanguage.KotlinServer + + } + } +} diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorExtension.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorExtension.kt new file mode 100644 index 0000000..76e0ed9 --- /dev/null +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorExtension.kt @@ -0,0 +1,22 @@ +package apigen + +open class ApiGeneratorExtension( + var pathToApiSchemes: String? = null, + var outputPackageName: String = "", + var outputDirPath: String = "", + var recreateOutputDir: Boolean = false, + var outputLanguage: OutputLanguage? = null +) + +sealed class OutputLanguage(val argName: String, val methodOutputType: MethodOutputType? = null) { + object KotlinServer : OutputLanguage("KOTLIN_SERVER") + class KotlinAndroid(methodOutputType: MethodOutputType = MethodOutputType.Rx) : OutputLanguage("KOTLIN", methodOutputType) + object Java : OutputLanguage("JAVA") + object Swift : OutputLanguage("SWIFT") +} + +sealed class MethodOutputType(val argName: String) { + object Rx : MethodOutputType("REACTIVE") + object RetrofitCall : MethodOutputType("CALL") + object Coroutine : MethodOutputType("COROUTINE") +} diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt new file mode 100644 index 0000000..ff272ce --- /dev/null +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt @@ -0,0 +1,76 @@ +package apigen + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.repositories + +abstract class ApiGeneratorPlugin : Plugin { + + companion object { + const val API_GENERATOR_CONFIG = "apiGenerator" + const val API_GENERATOR_EXT_NAME = "apiGenerator" + const val API_GENERATOR_VERSION = "1.4.0-beta4" + } + + override fun apply(target: Project) { + with(target) { + repositories { + maven { + url = uri("https://dl.bintray.com/touchin/touchin-tools") + metadataSources { + artifact() + } + } + } + + configurations.create(API_GENERATOR_CONFIG) + + dependencies { + add(API_GENERATOR_CONFIG, "ru.touchin:api-generator:$API_GENERATOR_VERSION") + } + + extensions.create(API_GENERATOR_EXT_NAME) + + val apiGenTask = createApiGeneratorTask() + + gradle.projectsEvaluated { + tasks.getByName("preBuild").dependsOn(apiGenTask) + } + } + } + + protected fun Project.getExtension(): ApiGeneratorExtension = extensions.getByName(API_GENERATOR_EXT_NAME) as ApiGeneratorExtension + + private fun Project.createApiGeneratorTask(): Task = tasks.create(API_GENERATOR_CONFIG).doLast { + + val extension = getExtension() + + val pathToApiSchemes = extension.pathToApiSchemes ?: throw IllegalStateException("Configure path to api schemes for api generator plugin") + val outputLanguage = extension.outputLanguage ?: throw IllegalStateException("Configure output language code for api generator plugin") + + javaexec { + main = "-jar" + workingDir = rootDir + args = listOfNotNull( + configurations.getByName("apiGenerator").asPath, + "generate-client-code", + "--output-language", + outputLanguage.argName, + "--specification-path", + pathToApiSchemes, + "--kotlin-methods-generation-mode".takeIf { outputLanguage.methodOutputType != null }, + outputLanguage.methodOutputType?.argName, + "--output-path", + extension.outputDirPath, + "--package-name", + extension.outputPackageName, + "--recreate_output_dirs", + extension.recreateOutputDir.toString() + ) + } + } + +} diff --git a/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt b/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt new file mode 100644 index 0000000..aee4a44 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt @@ -0,0 +1,12 @@ +package static_analysis.errors + +class AndroidLintError( + private val filePath: String, + private val fileLine: String, + private val errorId: String, + private val description: String +) : StaticAnalysisError { + + override fun print(count: Int): String = "\n$count. Android Lint. $description ($errorId)\n\tat [$filePath:$fileLine]" + +} diff --git a/gradle/plugins/src/main/java/static_analysis/errors/CpdError.kt b/gradle/plugins/src/main/java/static_analysis/errors/CpdError.kt new file mode 100644 index 0000000..cca1c8a --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/errors/CpdError.kt @@ -0,0 +1,12 @@ +package static_analysis.errors + +class CpdError( + private val duplications: List>, + private val codeFragment: String +) : StaticAnalysisError { + + override fun print(count: Int): String = "\n$count. CPD. Code duplication in files: " + + duplications.joinToString(separator = "") { (file, line) -> "\n\t[$file:$line]" } + + "\n\n Duplicated code:\n\n$codeFragment\n" + +} diff --git a/gradle/plugins/src/main/java/static_analysis/errors/DetektError.kt b/gradle/plugins/src/main/java/static_analysis/errors/DetektError.kt new file mode 100644 index 0000000..3aa9c09 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/errors/DetektError.kt @@ -0,0 +1,12 @@ +package static_analysis.errors + +class DetektError( + private val filePath: String, + private val fileLine: String, + private val errorId: String, + private val description: String +) : StaticAnalysisError { + + override fun print(count: Int): String = "\n$count. Detekt. $description ($errorId)\n\tat [$filePath:$fileLine]" + +} diff --git a/gradle/plugins/src/main/java/static_analysis/errors/StaticAnalysisError.kt b/gradle/plugins/src/main/java/static_analysis/errors/StaticAnalysisError.kt new file mode 100644 index 0000000..f932aca --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/errors/StaticAnalysisError.kt @@ -0,0 +1,5 @@ +package static_analysis.errors + +interface StaticAnalysisError { + fun print(count: Int): String +} diff --git a/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt new file mode 100644 index 0000000..f299d22 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt @@ -0,0 +1,65 @@ +package static_analysis.linters + +import com.android.build.gradle.AppExtension +import com.android.build.gradle.AppPlugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.findByType +import static_analysis.errors.AndroidLintError +import static_analysis.errors.StaticAnalysisError +import static_analysis.plugins.StaticAnalysisExtension +import static_analysis.utils.typedChildren +import static_analysis.utils.xmlParser + +class AndroidLinter : Linter { + + override val name: String = "Android lint" + + override fun getErrors(project: Project): List = xmlParser(project.getLintReportFile()) + .typedChildren() + .filter { it.name() == "issue" && (it.attribute("severity") as String) == "Error" } + .map { errorNode -> + errorNode + .typedChildren() + .filter { it.name() == "location" } + .map { locationNode -> + AndroidLintError( + filePath = locationNode.attribute("file") as String, + fileLine = locationNode.attribute("line") as String, + errorId = errorNode.attribute("id") as String, + description = errorNode.attribute("message") as String + ) + } + } + .flatten() + + override fun setupForProject(project: Project, extension: StaticAnalysisExtension) { + project.gradle.projectsEvaluated { + project.subprojects + .mapNotNull { it.extensions.findByType() } + .first() + .lintOptions.apply { + isAbortOnError = false + isCheckAllWarnings = true + isWarningsAsErrors = false + xmlReport = true + htmlReport = false + isCheckDependencies = true + disable("MissingConstraints", "VectorRaster") + xmlOutput = project.getLintReportFile() + lintConfig = project.file("${extension.buildScriptDir}/static_analysis_configs/lint.xml") + } + } + } + + override fun getTaskNames(project: Project, buildType: String?): List = project + .subprojects + .filter { it.plugins.hasPlugin(AppPlugin::class.java) } + .mapNotNull { subproject: Project -> + subproject.tasks.find { task -> + task.name.contains(buildType!!, ignoreCase = true) && task.name.contains("lint") + }?.path + } + + private fun Project.getLintReportFile() = file("${rootProject.buildDir}/reports/lint-report.xml") + +} diff --git a/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt new file mode 100644 index 0000000..ca3ff7e --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt @@ -0,0 +1,57 @@ +package static_analysis.linters + +import de.aaschmid.gradle.plugins.cpd.Cpd +import de.aaschmid.gradle.plugins.cpd.CpdExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.findByType +import org.gradle.kotlin.dsl.withType +import static_analysis.errors.CpdError +import static_analysis.errors.StaticAnalysisError +import static_analysis.plugins.StaticAnalysisExtension +import static_analysis.utils.getSources +import static_analysis.utils.typedChildren +import static_analysis.utils.xmlParser + +class CpdLinter : Linter { + + override val name: String = "CPD" + + override fun getErrors(project: Project): List = xmlParser(project.getCpdReportFile()) + .typedChildren() + .filter { it.name() == "duplication" } + .map { duplicationNode -> + + val children = duplicationNode + .typedChildren() + + CpdError( + duplications = children + .filter { it.name() == "file" } + .map { fileNode -> fileNode.attribute("path") as String to fileNode.attribute("line") as String }, + codeFragment = children.findLast { it.name() == "codefragment" }!!.text() + ) + + } + + override fun setupForProject(project: Project, extension: StaticAnalysisExtension) { + project.extensions.findByType()!!.apply { + isSkipLexicalErrors = true + language = "kotlin" + minimumTokenCount = 60 + } + project.tasks.withType { + reports.xml.destination = project.getCpdReportFile() + ignoreFailures = true + source = project.getSources(extension.excludes) + } + } + + override fun getTaskNames(project: Project, buildType: String?): List = project + .rootProject + .tasks + .withType() + .map { it.path } + + private fun Project.getCpdReportFile() = file("${rootProject.buildDir}/reports/cpd.xml") + +} diff --git a/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt new file mode 100644 index 0000000..0aafb22 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt @@ -0,0 +1,62 @@ +package static_analysis.linters + +import io.gitlab.arturbosch.detekt.Detekt +import org.gradle.api.Project +import static_analysis.errors.DetektError +import static_analysis.errors.StaticAnalysisError +import static_analysis.plugins.StaticAnalysisExtension +import static_analysis.utils.getSources +import static_analysis.utils.typedChildren +import static_analysis.utils.xmlParser + +class DetektLinter : Linter { + + override val name: String = "Detekt" + + override fun getErrors(project: Project): List = xmlParser(project.getDetektReportFile()) + .typedChildren() + .filter { fileNode -> fileNode.name() == "file" } + .map { fileNode -> + fileNode + .typedChildren() + .filter { it.name() == "error" } + .map { errorNode -> + DetektError( + filePath = fileNode.attribute("name") as String, + fileLine = errorNode.attribute("line") as String, + errorId = errorNode.attribute("source") as String, + description = errorNode.attribute("message") as String + ) + } + } + .flatten() + + override fun setupForProject(project: Project, extension: StaticAnalysisExtension) { + project + .tasks + .withType(Detekt::class.java) { + exclude("**/test/**") + exclude("resources/") + exclude("build/") + exclude("tmp/") + jvmTarget = "1.8" + + config.setFrom(project.files("${extension.buildScriptDir!!}/static_analysis_configs/detekt-config.yml")) + reports { + txt.enabled = false + html.enabled = false + xml { + enabled = true + destination = project.getDetektReportFile() + } + } + + source = project.getSources(extension.excludes) + } + } + + override fun getTaskNames(project: Project, buildType: String?): List = listOf(":detekt") + + private fun Project.getDetektReportFile() = file("${rootProject.buildDir}/reports/detekt.xml") + +} diff --git a/gradle/plugins/src/main/java/static_analysis/linters/Linter.kt b/gradle/plugins/src/main/java/static_analysis/linters/Linter.kt new file mode 100644 index 0000000..65421a1 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/linters/Linter.kt @@ -0,0 +1,12 @@ +package static_analysis.linters + +import org.gradle.api.Project +import static_analysis.errors.StaticAnalysisError +import static_analysis.plugins.StaticAnalysisExtension + +interface Linter { + val name: String + fun getErrors(project: Project): List + fun setupForProject(project: Project, extension: StaticAnalysisExtension) + fun getTaskNames(project: Project, buildType: String? = null): List +} diff --git a/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisAndroidPlugin.kt b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisAndroidPlugin.kt new file mode 100644 index 0000000..c433e81 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisAndroidPlugin.kt @@ -0,0 +1,43 @@ +package static_analysis.plugins + +import com.android.build.gradle.AppExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType +import static_analysis.linters.AndroidLinter +import static_analysis.linters.CpdLinter +import static_analysis.linters.DetektLinter +import static_analysis.linters.Linter + +class StaticAnalysisAndroidPlugin : StaticAnalysisPlugin() { + + override fun createStaticAnalysisTasks(project: Project, linters: List) { + project.subprojects { + if (plugins.hasPlugin("com.android.application")) { + + extensions.getByType().apply { + applicationVariants.forEach { variant -> + project.tasks.register("staticAnalysis${variant.name.capitalize()}") { + setupStaticAnalysisTask(linters, variant.name) + } + } + + project.tasks.register("staticAnalysis") { + setupStaticAnalysisTask( + linters = linters, + buildVariant = applicationVariants.first { it.name.contains("Debug") }.name + ) + } + } + + + } + } + } + + override fun createLinters(): List = listOf( + DetektLinter(), + CpdLinter(), + AndroidLinter() + ) + +} diff --git a/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisBackendPlugin.kt b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisBackendPlugin.kt new file mode 100644 index 0000000..fa35f1d --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisBackendPlugin.kt @@ -0,0 +1,21 @@ +package static_analysis.plugins + +import org.gradle.api.Project +import static_analysis.linters.CpdLinter +import static_analysis.linters.DetektLinter +import static_analysis.linters.Linter + +class StaticAnalysisBackendPlugin : StaticAnalysisPlugin() { + + override fun createStaticAnalysisTasks(project: Project, linters: List) { + project.tasks.register("staticAnalysis") { + setupStaticAnalysisTask(linters) + } + } + + override fun createLinters(): List = listOf( + CpdLinter(), + DetektLinter() + ) + +} diff --git a/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisExtension.kt b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisExtension.kt new file mode 100644 index 0000000..dfa698d --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisExtension.kt @@ -0,0 +1,6 @@ +package static_analysis.plugins + +open class StaticAnalysisExtension( + var excludes: String = "", + var buildScriptDir: String? = null +) diff --git a/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisPlugin.kt b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisPlugin.kt new file mode 100644 index 0000000..38ded00 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/plugins/StaticAnalysisPlugin.kt @@ -0,0 +1,47 @@ +package static_analysis.plugins + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.getByType +import static_analysis.linters.Linter +import static_analysis.utils.ReportGenerator + +abstract class StaticAnalysisPlugin : Plugin { + + companion object { + const val DETEKT_ID = "io.gitlab.arturbosch.detekt" + const val CPD_ID = "de.aaschmid.cpd" + const val STATIC_ANALYSIS_EXT_NAME = "staticAnalysis" + } + + override fun apply(target: Project) { + + with(target) { + pluginManager.apply(CPD_ID) + pluginManager.apply(DETEKT_ID) + + extensions.create(STATIC_ANALYSIS_EXT_NAME) + + val linters = createLinters() + + afterEvaluate { + linters.forEach { it.setupForProject(target, extensions.getByType()) } + } + + gradle.projectsEvaluated { + createStaticAnalysisTasks(target, linters) + } + } + } + + fun Task.setupStaticAnalysisTask(linters: List, buildVariant: String? = null) { + doFirst { ReportGenerator.generate(linters, project) } + dependsOn(*(linters.map { it.getTaskNames(project, buildVariant) }.flatten().toTypedArray())) + } + + abstract fun createLinters(): List + abstract fun createStaticAnalysisTasks(project: Project, linters: List) + +} diff --git a/gradle/plugins/src/main/java/static_analysis/utils/Extensions.kt b/gradle/plugins/src/main/java/static_analysis/utils/Extensions.kt new file mode 100644 index 0000000..c53ce16 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/utils/Extensions.kt @@ -0,0 +1,33 @@ +package static_analysis.utils + +import groovy.util.Node +import groovy.util.XmlParser +import org.gradle.api.Project +import org.gradle.api.file.FileTree +import java.io.File + +fun Node.typedChildren() = children() as List + +fun xmlParser(file: File) = XmlParser().parse(file) + +fun Project.getSources(excludes: String): FileTree = files( + project + .rootProject + .subprojects + .filter { subproject -> subproject.subprojects.isEmpty() && !excludes.contains(subproject.path) } + .map { subproject -> subproject.file("${subproject.projectDir.path}/src/main") } + .filter { it.exists() && it.isDirectory } + .flatMap { srcDir -> + srcDir + .listFiles() + .orEmpty() + .flatMap { + listOf( + File(srcDir.path, "java"), + File(srcDir.path, "kotlin") + ) + } + } + .filter { it.exists() && it.isDirectory } + .map { it.path } +).asFileTree diff --git a/gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt b/gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt new file mode 100644 index 0000000..caf543e --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt @@ -0,0 +1,52 @@ +package static_analysis.utils + +import org.gradle.api.Project +import static_analysis.errors.StaticAnalysisError +import static_analysis.linters.Linter + +object ReportGenerator { + + fun generate(linters: List, project: Project) { + + val groupedErrors = linters + .map { linter -> linter to linter.getErrors(project) } + + val lintersResults = groupedErrors + .map { it.first.name to it.second.size } + + val allErrors = groupedErrors + .map { it.second } + .flatten() + + val consoleReport = StringBuilder("\nSTATIC ANALYSIS ERRORS:").apply { + appendAllErrors(allErrors) + append("\nREPORT:\n") + appendReportsSummary(lintersResults) + appendOverallSummary(allErrors) + } + + if (allErrors.isEmpty()) { + println(consoleReport) + } else { + throw Exception(consoleReport.toString()) + } + + } + + private fun StringBuilder.appendAllErrors(errors: List) = errors + .mapIndexed { index, staticAnalysisError -> staticAnalysisError.print(index + 1) } + .forEach { error -> append(error) } + + private fun StringBuilder.appendReportsSummary(lintersResults: List>) = lintersResults + .forEach { this.appendSummary(it.first, it.second) } + + private fun StringBuilder.appendOverallSummary(errors: List) = appendSummary("Overall", errors.size) + + private fun StringBuilder.appendSummary(header: String, quantityOfErrors: Int) { + assert(quantityOfErrors < 0) + + append("\n$header: ") + append(if (quantityOfErrors == 0) "PASSED" else "FAILED ($quantityOfErrors errors)") + } + +} diff --git a/gradle/applicationFileNaming.gradle b/gradle/scripts/applicationFileNaming.gradle similarity index 100% rename from gradle/applicationFileNaming.gradle rename to gradle/scripts/applicationFileNaming.gradle diff --git a/gradle/stringGenerator.gradle b/gradle/scripts/stringGenerator.gradle similarity index 100% rename from gradle/stringGenerator.gradle rename to gradle/scripts/stringGenerator.gradle diff --git a/gradle/staticAnalysis.gradle b/gradle/staticAnalysis.gradle deleted file mode 100644 index b952ec9..0000000 --- a/gradle/staticAnalysis.gradle +++ /dev/null @@ -1,166 +0,0 @@ -buildscript { - repositories { - maven { url "https://plugins.gradle.org/m2" } - } - dependencies { - classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.5.1" - } -} - -def getServerProjectSources -def getAndroidProjectSources - -apply from: "$buildScriptsDir/gradle/commonStaticAnalysis.gradle" - -gradle.projectsEvaluated { - - tasks.withType(JavaCompile) { - options.compilerArgs << - "-Xlint:cast" << - "-Xlint:divzero" << - "-Xlint:empty" << - "-Xlint:deprecation" << - "-Xlint:finally" << - "-Xlint:overrides" << - "-Xlint:path" << - "-Werror" - } - - def excludes = rootProject.extensions.findByName("staticAnalysisExcludes") - - def androidSources = getAndroidProjectSources(excludes) - def androidStaticAnalysisTasks = getStaticAnalysisTaskNames(true, androidSources, null) - def androidIdeaFormatTask = getIdeaFormatTask(true, androidSources) - - task staticAnalysisWithFormatting { - androidStaticAnalysisTasks.each { task -> - tasks.findByName(task)?.mustRunAfter(androidIdeaFormatTask) - } - dependsOn androidIdeaFormatTask - dependsOn androidStaticAnalysisTasks - doFirst { - generateReport(true) - } - } - - task staticAnalysis { - dependsOn androidStaticAnalysisTasks - doFirst { - generateReport(true) - } - } - - def serverStaticAnalysisTasks = getStaticAnalysisTaskNames(false, getServerProjectSources(excludes), null) - def serverIdeaFormatTask = getIdeaFormatTask(false, getServerProjectSources(excludes)) - - task serverStaticAnalysisWithFormatting { - serverStaticAnalysisTasks.each { task -> - tasks.findByName(task)?.mustRunAfter(serverIdeaFormatTask) - } - dependsOn serverIdeaFormatTask - dependsOn serverStaticAnalysisTasks - doFirst { - generateReport(false) - } - } - - task serverStaticAnalysis { - dependsOn serverStaticAnalysisTasks - doFirst { - generateReport(false) - } - } - - subprojects { subproject -> - if (subproject.plugins.hasPlugin("com.android.application")) { - subproject.android { - lintOptions.abortOnError = false - lintOptions.checkAllWarnings = true - lintOptions.warningsAsErrors = false - lintOptions.xmlReport = true - lintOptions.xmlOutput = file "$rootProject.buildDir/reports/lint_report.xml" - lintOptions.htmlReport = false - lintOptions.lintConfig = file "$buildScriptsDir/lint/lint.xml" - lintOptions.checkDependencies true - lintOptions.disable 'MissingConstraints', 'VectorRaster' - - applicationVariants.all { variant -> - task("staticAnalysis${variant.name.capitalize()}") { - dependsOn getStaticAnalysisTaskNames(true, androidSources, variant) - doFirst { generateReport(true) } - } - } - } - } - - def regex = ~':detekt$' - tasks.forEach { task -> - if (!task.name.contains(":libs") && task.path =~ regex) { - task.exclude '**/test/**' - task.exclude 'resources/' - task.exclude 'build/' - task.exclude 'tmp/' - - task.jvmTarget = "1.8" - } - } - - detekt { - config = files("$buildScriptsDir/kotlin/detekt-config.yml") - - reports { - txt.enabled = false - html.enabled = false - xml { - enabled = true - destination = file("${rootProject.buildDir}/reports/kotlin-detekt-${subproject.name}.xml") - } - } - } - } -} - -getServerProjectSources = { excludes -> - def sources = new ArrayList() - def sourcesDirectory = new File(project.projectDir.path, 'src') - - for (def sourceFlavorDirectory : sourcesDirectory.listFiles()) { - def javaSourceDirectory = new File(sourceFlavorDirectory.path, 'java') - def kotlinSourceDirectory = new File(sourceFlavorDirectory.path, 'kotlin') - - if (javaSourceDirectory.exists() && javaSourceDirectory.isDirectory()) { - sources.add(javaSourceDirectory.absolutePath) - } - if (kotlinSourceDirectory.exists() && kotlinSourceDirectory.isDirectory()) { - sources.add(kotlinSourceDirectory.absolutePath) - } - } - return sources -} - -getAndroidProjectSources = { excludes -> - def sources = new ArrayList() - for (def project : rootProject.subprojects) { - if (!project.subprojects.isEmpty() || (excludes != null && excludes.contains(project.path))) { - continue - } - - def sourcesDirectory = new File(project.projectDir.path, 'src') - if (!sourcesDirectory.exists() || !sourcesDirectory.isDirectory()) { - continue - } - - for (def sourceFlavorDirectory : sourcesDirectory.listFiles()) { - def javaSourceDirectory = new File(sourceFlavorDirectory.path, 'java') - def kotlinSourceDirectory = new File(sourceFlavorDirectory.path, 'kotlin') - - if (javaSourceDirectory.exists() && javaSourceDirectory.isDirectory()) { - sources.add(javaSourceDirectory.absolutePath) - } - if (kotlinSourceDirectory.exists() && kotlinSourceDirectory.isDirectory()) { - sources.add(kotlinSourceDirectory.absolutePath) - } - } - } - return sources -} diff --git a/lint/lint.xml b/lint/lint.xml deleted file mode 100644 index 57a80e9..0000000 --- a/lint/lint.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pmd/rulesets/java/android.xml b/pmd/rulesets/java/android.xml deleted file mode 100644 index debe6f4..0000000 --- a/pmd/rulesets/java/android.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - Every Java Rule in PMD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/export_src.sh b/scripts/export_src.sh similarity index 100% rename from export_src.sh rename to scripts/export_src.sh diff --git a/kotlin/detekt-config.yml b/static_analysis_configs/detekt-config.yml similarity index 99% rename from kotlin/detekt-config.yml rename to static_analysis_configs/detekt-config.yml index 3afb6fa..5ea4cce 100644 --- a/kotlin/detekt-config.yml +++ b/static_analysis_configs/detekt-config.yml @@ -23,7 +23,7 @@ formatting: active: true console-reports: - active: true + active: false exclude: # - 'ProjectStatisticsReport' # - 'ComplexityReport' diff --git a/static_analysis_configs/lint.xml b/static_analysis_configs/lint.xml new file mode 100644 index 0000000..98227d4 --- /dev/null +++ b/static_analysis_configs/lint.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 0f53df4bb45903a2d748bb0d087a99fec3bcfd90 Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Wed, 19 Aug 2020 17:56:02 +0300 Subject: [PATCH 21/43] update api gen version --- gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt index ff272ce..e0fc6ec 100644 --- a/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt @@ -12,7 +12,7 @@ abstract class ApiGeneratorPlugin : Plugin { companion object { const val API_GENERATOR_CONFIG = "apiGenerator" const val API_GENERATOR_EXT_NAME = "apiGenerator" - const val API_GENERATOR_VERSION = "1.4.0-beta4" + const val API_GENERATOR_VERSION = "1.4.0-beta5" } override fun apply(target: Project) { From 7b54155ae1bd769dec94bd79edd43ead4dc2cfc0 Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Thu, 20 Aug 2020 13:33:57 +0300 Subject: [PATCH 22/43] fixed android api gen and string generator for old projects --- .../main/java/apigen/ApiGeneratorAndroidPlugin.kt | 10 ++++++++-- gradle/scripts/stringGenerator.gradle | 14 +++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt index fa417b0..0442f43 100644 --- a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt @@ -1,8 +1,9 @@ package apigen +import com.android.build.gradle.AppExtension import com.android.build.gradle.LibraryExtension import org.gradle.api.Project -import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.findByType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() { @@ -18,7 +19,12 @@ class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() { extension.recreateOutputDir = true afterEvaluate { - extensions.getByType().apply { + extensions.findByType()?.apply { + sourceSets.getByName("main") + .java + .srcDir(outputDir) + } + extensions.findByType()?.apply { sourceSets.getByName("main") .java .srcDir(outputDir) diff --git a/gradle/scripts/stringGenerator.gradle b/gradle/scripts/stringGenerator.gradle index 374ab12..9c47e90 100644 --- a/gradle/scripts/stringGenerator.gradle +++ b/gradle/scripts/stringGenerator.gradle @@ -2,11 +2,11 @@ import groovy.json.JsonSlurper import groovy.xml.MarkupBuilder task stringGenerator { - generate(android.languageMap, android.rootPath ?: "app") + generate(android.languageMap, project) println("Strings generated!") } -private def generate(Map sources, String rootPath) { +private def generate(Map sources, Project project) { if (sources == null || sources.isEmpty()) { throw new IOException("languageMap can't be null or empty") } @@ -31,7 +31,7 @@ private def generate(Map sources, String rootPath) { } } - def stringsFile = getFile(key, key == defaultLang, rootPath) + def stringsFile = getFile(key, key == defaultLang, project) stringsFile.write(sw.toString(), "UTF-8") } } @@ -69,15 +69,15 @@ private static Map getJsonsMap(Map sources) { } } -private static File getFile(String key, boolean defaultLang, String rootPath) { +private static File getFile(String key, boolean defaultLang, Project project) { if (defaultLang) { - return new File("${rootPath}/src/main/res/values/strings.xml") + return project.file("src/main/res/values/strings.xml") } else { - def directory = new File("${rootPath}/src/main/res/values-$key") + def directory = project.file("src/main/res/values-$key") if (!directory.exists()) { directory.mkdir() } - return new File("${rootPath}/src/main/res/values-$key/strings.xml") + return project.file("src/main/res/values-$key/strings.xml") } } From b3bff241398f0545fe1870b62371594c495e5825 Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Thu, 20 Aug 2020 15:22:41 +0300 Subject: [PATCH 23/43] fixed problem with source sets for java code --- .../src/main/java/apigen/ApiGeneratorAndroidPlugin.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt index 0442f43..d30c4f5 100644 --- a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt @@ -3,6 +3,7 @@ package apigen import com.android.build.gradle.AppExtension import com.android.build.gradle.LibraryExtension import org.gradle.api.Project +import org.gradle.api.tasks.compile.JavaCompile import org.gradle.kotlin.dsl.findByType import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -34,6 +35,12 @@ class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() { .forEach { it.source(outputDir) } + + tasks + .filterIsInstance() + .forEach { + it.source(outputDir) + } } } } From 3d73b2473f5d85af83f4a7392215a29d0f733221 Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Thu, 20 Aug 2020 15:24:04 +0300 Subject: [PATCH 24/43] little change of code's style --- .../plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt index d30c4f5..83295d3 100644 --- a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt @@ -31,7 +31,7 @@ class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() { .srcDir(outputDir) } tasks - .filterIsInstance(KotlinCompile::class.java) + .filterIsInstance() .forEach { it.source(outputDir) } From 21e21aca1d4ad49355cb51b549d1454cb97741a7 Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Thu, 20 Aug 2020 17:55:14 +0300 Subject: [PATCH 25/43] fix android lint bug with no file column errors --- .../src/main/java/static_analysis/errors/AndroidLintError.kt | 4 ++-- .../src/main/java/static_analysis/linters/AndroidLinter.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt b/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt index aee4a44..b7b850b 100644 --- a/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt +++ b/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt @@ -2,11 +2,11 @@ package static_analysis.errors class AndroidLintError( private val filePath: String, - private val fileLine: String, + private val fileLine: String?, private val errorId: String, private val description: String ) : StaticAnalysisError { - override fun print(count: Int): String = "\n$count. Android Lint. $description ($errorId)\n\tat [$filePath:$fileLine]" + override fun print(count: Int): String = "\n$count. Android Lint. $description ($errorId)\n\tat [$filePath${fileLine?.let { ":$it" }.orEmpty()}]" } diff --git a/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt index f299d22..3e19265 100644 --- a/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt +++ b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt @@ -24,7 +24,7 @@ class AndroidLinter : Linter { .map { locationNode -> AndroidLintError( filePath = locationNode.attribute("file") as String, - fileLine = locationNode.attribute("line") as String, + fileLine = locationNode.attribute("line") as String?, errorId = errorNode.attribute("id") as String, description = errorNode.attribute("message") as String ) From a8e55fc0e856425fc81428197ab704694c90a4d7 Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Wed, 2 Sep 2020 17:48:46 +0300 Subject: [PATCH 26/43] fix proguard cut annotation which used in custom json adapter --- proguard/rules/moshi.pro | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 proguard/rules/moshi.pro diff --git a/proguard/rules/moshi.pro b/proguard/rules/moshi.pro new file mode 100644 index 0000000..fe81601 --- /dev/null +++ b/proguard/rules/moshi.pro @@ -0,0 +1,23 @@ +# JSR 305 annotations are for embedding nullability information. +-dontwarn javax.annotation.** + +-keepclasseswithmembers class * { + @com.squareup.moshi.* ; +} + +-keep @com.squareup.moshi.JsonQualifier interface * +-keep @com.squareup.moshi.JsonQualifier class * + +# Enum field names are used by the integrated EnumJsonAdapter. +# values() is synthesized by the Kotlin compiler and is used by EnumJsonAdapter indirectly +# Annotate enums with @JsonClass(generateAdapter = false) to use them with Moshi. +-keepclassmembers @com.squareup.moshi.JsonClass class * extends java.lang.Enum { + ; + **[] values(); +} + +-keep class kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoaderImpl + +-keepclassmembers class kotlin.Metadata { + public ; +} From 487291a54fd5fdb0d3b028d0b3e57adb28fe280b Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Tue, 8 Sep 2020 15:42:47 +0300 Subject: [PATCH 27/43] fix code review --- gradle/plugins/.gitignore | 1 + .../java/apigen/ApiGeneratorAndroidPlugin.kt | 8 ++----- .../java/apigen/ApiGeneratorBackendPlugin.kt | 10 ++++----- .../main/java/apigen/ApiGeneratorPlugin.kt | 4 ++-- .../errors/AndroidLintError.kt | 5 ++++- .../static_analysis/linters/AndroidLinter.kt | 22 +++++++++++-------- .../java/static_analysis/linters/CpdLinter.kt | 4 ++-- .../static_analysis/linters/DetektLinter.kt | 2 +- .../main/java/static_analysis/utils/Node.kt | 5 +++++ .../utils/{Extensions.kt => Project.kt} | 6 ----- .../static_analysis/utils/ReportGenerator.kt | 4 ++-- .../java/static_analysis/utils/XmlUtils.kt | 4 ++++ proguard/common.pro | 2 +- 13 files changed, 41 insertions(+), 36 deletions(-) create mode 100644 gradle/plugins/src/main/java/static_analysis/utils/Node.kt rename gradle/plugins/src/main/java/static_analysis/utils/{Extensions.kt => Project.kt} (87%) create mode 100644 gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt diff --git a/gradle/plugins/.gitignore b/gradle/plugins/.gitignore index d7e7478..39d12d8 100644 --- a/gradle/plugins/.gitignore +++ b/gradle/plugins/.gitignore @@ -12,6 +12,7 @@ local.properties # Log Files *.log + .gradle .idea .DS_Store diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt index 83295d3..ea06f40 100644 --- a/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorAndroidPlugin.kt @@ -32,15 +32,11 @@ class ApiGeneratorAndroidPlugin : ApiGeneratorPlugin() { } tasks .filterIsInstance() - .forEach { - it.source(outputDir) - } + .forEach { it.source(outputDir) } tasks .filterIsInstance() - .forEach { - it.source(outputDir) - } + .forEach { it.source(outputDir) } } } } diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt index b68eccf..b4a8723 100644 --- a/gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorBackendPlugin.kt @@ -7,13 +7,11 @@ class ApiGeneratorBackendPlugin : ApiGeneratorPlugin() { override fun apply(target: Project) { super.apply(target) - with(target) { - val extension = getExtension() + val extension = target.getExtension() - extension.outputDirPath = file("src/main/kotlin").path - extension.recreateOutputDir = false - extension.outputLanguage = OutputLanguage.KotlinServer + extension.outputDirPath = target.file("src/main/kotlin").path + extension.recreateOutputDir = false + extension.outputLanguage = OutputLanguage.KotlinServer - } } } diff --git a/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt b/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt index e0fc6ec..7e9b607 100644 --- a/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt +++ b/gradle/plugins/src/main/java/apigen/ApiGeneratorPlugin.kt @@ -12,7 +12,7 @@ abstract class ApiGeneratorPlugin : Plugin { companion object { const val API_GENERATOR_CONFIG = "apiGenerator" const val API_GENERATOR_EXT_NAME = "apiGenerator" - const val API_GENERATOR_VERSION = "1.4.0-beta5" + const val API_GENERATOR_DEFAULT_VERSION = "1.4.0-beta5" } override fun apply(target: Project) { @@ -29,7 +29,7 @@ abstract class ApiGeneratorPlugin : Plugin { configurations.create(API_GENERATOR_CONFIG) dependencies { - add(API_GENERATOR_CONFIG, "ru.touchin:api-generator:$API_GENERATOR_VERSION") + add(API_GENERATOR_CONFIG, "ru.touchin:api-generator:$API_GENERATOR_DEFAULT_VERSION") } extensions.create(API_GENERATOR_EXT_NAME) diff --git a/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt b/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt index b7b850b..6b87d81 100644 --- a/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt +++ b/gradle/plugins/src/main/java/static_analysis/errors/AndroidLintError.kt @@ -7,6 +7,9 @@ class AndroidLintError( private val description: String ) : StaticAnalysisError { - override fun print(count: Int): String = "\n$count. Android Lint. $description ($errorId)\n\tat [$filePath${fileLine?.let { ":$it" }.orEmpty()}]" + override fun print(count: Int): String = "\n$count. Android Lint. $description ($errorId)\n\tat [$filePath$fileLinePrefix]" + + private val fileLinePrefix: String + get() = fileLine?.let { ":$it" }.orEmpty() } diff --git a/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt index 3e19265..3853959 100644 --- a/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt +++ b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt @@ -8,7 +8,7 @@ import static_analysis.errors.AndroidLintError import static_analysis.errors.StaticAnalysisError import static_analysis.plugins.StaticAnalysisExtension import static_analysis.utils.typedChildren -import static_analysis.utils.xmlParser +import xmlParser class AndroidLinter : Linter { @@ -51,14 +51,18 @@ class AndroidLinter : Linter { } } - override fun getTaskNames(project: Project, buildType: String?): List = project - .subprojects - .filter { it.plugins.hasPlugin(AppPlugin::class.java) } - .mapNotNull { subproject: Project -> - subproject.tasks.find { task -> - task.name.contains(buildType!!, ignoreCase = true) && task.name.contains("lint") - }?.path - } + override fun getTaskNames(project: Project, buildType: String?): List { + if (buildType == null) throw IllegalStateException("build type must not be null in android linter") + + return project + .subprojects + .filter { it.plugins.hasPlugin(AppPlugin::class.java) } + .mapNotNull { subproject: Project -> + subproject.tasks.find { task -> + task.name.contains(buildType, ignoreCase = true) && task.name.contains("lint") + }?.path + } + } private fun Project.getLintReportFile() = file("${rootProject.buildDir}/reports/lint-report.xml") diff --git a/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt index ca3ff7e..313d250 100644 --- a/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt +++ b/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt @@ -10,7 +10,7 @@ import static_analysis.errors.StaticAnalysisError import static_analysis.plugins.StaticAnalysisExtension import static_analysis.utils.getSources import static_analysis.utils.typedChildren -import static_analysis.utils.xmlParser +import xmlParser class CpdLinter : Linter { @@ -50,7 +50,7 @@ class CpdLinter : Linter { .rootProject .tasks .withType() - .map { it.path } + .map(Cpd::getPath) private fun Project.getCpdReportFile() = file("${rootProject.buildDir}/reports/cpd.xml") diff --git a/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt index 0aafb22..3905ce8 100644 --- a/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt +++ b/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt @@ -7,7 +7,7 @@ import static_analysis.errors.StaticAnalysisError import static_analysis.plugins.StaticAnalysisExtension import static_analysis.utils.getSources import static_analysis.utils.typedChildren -import static_analysis.utils.xmlParser +import xmlParser class DetektLinter : Linter { diff --git a/gradle/plugins/src/main/java/static_analysis/utils/Node.kt b/gradle/plugins/src/main/java/static_analysis/utils/Node.kt new file mode 100644 index 0000000..e8618e2 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/utils/Node.kt @@ -0,0 +1,5 @@ +package static_analysis.utils + +import groovy.util.Node + +fun Node.typedChildren() = children() as List diff --git a/gradle/plugins/src/main/java/static_analysis/utils/Extensions.kt b/gradle/plugins/src/main/java/static_analysis/utils/Project.kt similarity index 87% rename from gradle/plugins/src/main/java/static_analysis/utils/Extensions.kt rename to gradle/plugins/src/main/java/static_analysis/utils/Project.kt index c53ce16..f1c46cf 100644 --- a/gradle/plugins/src/main/java/static_analysis/utils/Extensions.kt +++ b/gradle/plugins/src/main/java/static_analysis/utils/Project.kt @@ -1,15 +1,9 @@ package static_analysis.utils -import groovy.util.Node -import groovy.util.XmlParser import org.gradle.api.Project import org.gradle.api.file.FileTree import java.io.File -fun Node.typedChildren() = children() as List - -fun xmlParser(file: File) = XmlParser().parse(file) - fun Project.getSources(excludes: String): FileTree = files( project .rootProject diff --git a/gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt b/gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt index caf543e..b18f8f4 100644 --- a/gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt +++ b/gradle/plugins/src/main/java/static_analysis/utils/ReportGenerator.kt @@ -12,10 +12,10 @@ object ReportGenerator { .map { linter -> linter to linter.getErrors(project) } val lintersResults = groupedErrors - .map { it.first.name to it.second.size } + .map { (linter, linterErrors) -> linter.name to linterErrors.size } val allErrors = groupedErrors - .map { it.second } + .map(Pair>::second) .flatten() val consoleReport = StringBuilder("\nSTATIC ANALYSIS ERRORS:").apply { diff --git a/gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt b/gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt new file mode 100644 index 0000000..f335b29 --- /dev/null +++ b/gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt @@ -0,0 +1,4 @@ +import groovy.util.XmlParser +import java.io.File + +fun xmlParser(file: File) = XmlParser().parse(file) diff --git a/proguard/common.pro b/proguard/common.pro index 52715c2..d7f2023 100644 --- a/proguard/common.pro +++ b/proguard/common.pro @@ -1,5 +1,4 @@ -include rules/components.pro - -include rules/okhttp.pro -include rules/retrofit.pro -include rules/logansquare.pro @@ -7,3 +6,4 @@ -include rules/glide.pro -include rules/kaspersky.pro -include rules/appsflyer.pro +-include rules/moshi.pro From adf2946881bf0490ad41418bf76e9c14cb925260 Mon Sep 17 00:00:00 2001 From: Maxim Bachinsky Date: Tue, 8 Sep 2020 19:04:43 +0300 Subject: [PATCH 28/43] fixed code review --- .../java/static_analysis/linters/AndroidLinter.kt | 13 ++++++++----- .../main/java/static_analysis/linters/CpdLinter.kt | 2 +- .../java/static_analysis/linters/DetektLinter.kt | 2 +- .../src/main/java/static_analysis/utils/XmlUtils.kt | 2 ++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt index 3853959..8550e04 100644 --- a/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt +++ b/gradle/plugins/src/main/java/static_analysis/linters/AndroidLinter.kt @@ -8,7 +8,7 @@ import static_analysis.errors.AndroidLintError import static_analysis.errors.StaticAnalysisError import static_analysis.plugins.StaticAnalysisExtension import static_analysis.utils.typedChildren -import xmlParser +import static_analysis.utils.xmlParser class AndroidLinter : Linter { @@ -52,15 +52,18 @@ class AndroidLinter : Linter { } override fun getTaskNames(project: Project, buildType: String?): List { - if (buildType == null) throw IllegalStateException("build type must not be null in android linter") + if (buildType == null) { + throw IllegalStateException("Build type must not be null in android linter") + } return project .subprojects .filter { it.plugins.hasPlugin(AppPlugin::class.java) } .mapNotNull { subproject: Project -> - subproject.tasks.find { task -> - task.name.contains(buildType, ignoreCase = true) && task.name.contains("lint") - }?.path + subproject + .tasks + .find { task -> task.name.contains(buildType, ignoreCase = true) && task.name.contains("lint") } + ?.path } } diff --git a/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt index 313d250..1e7395a 100644 --- a/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt +++ b/gradle/plugins/src/main/java/static_analysis/linters/CpdLinter.kt @@ -10,7 +10,7 @@ import static_analysis.errors.StaticAnalysisError import static_analysis.plugins.StaticAnalysisExtension import static_analysis.utils.getSources import static_analysis.utils.typedChildren -import xmlParser +import static_analysis.utils.xmlParser class CpdLinter : Linter { diff --git a/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt b/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt index 3905ce8..0aafb22 100644 --- a/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt +++ b/gradle/plugins/src/main/java/static_analysis/linters/DetektLinter.kt @@ -7,7 +7,7 @@ import static_analysis.errors.StaticAnalysisError import static_analysis.plugins.StaticAnalysisExtension import static_analysis.utils.getSources import static_analysis.utils.typedChildren -import xmlParser +import static_analysis.utils.xmlParser class DetektLinter : Linter { diff --git a/gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt b/gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt index f335b29..1754f4c 100644 --- a/gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt +++ b/gradle/plugins/src/main/java/static_analysis/utils/XmlUtils.kt @@ -1,3 +1,5 @@ +package static_analysis.utils + import groovy.util.XmlParser import java.io.File From 3546f980fdf97ae29e467c40b9d975c800880612 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 14 Sep 2020 22:07:30 +0300 Subject: [PATCH 29/43] Add localization files check --- xcode/build_phases/common/localization_check | Bin 0 -> 72656 bytes xcode/build_phases/localization_check.sh | 9 +++++++++ 2 files changed, 9 insertions(+) create mode 100755 xcode/build_phases/common/localization_check create mode 100755 xcode/build_phases/localization_check.sh diff --git a/xcode/build_phases/common/localization_check b/xcode/build_phases/common/localization_check new file mode 100755 index 0000000000000000000000000000000000000000..3ca068bbc5677ff06e90da59a2f916dc4d8dce82 GIT binary patch literal 72656 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 literal 0 HcmV?d00001 diff --git a/xcode/build_phases/localization_check.sh b/xcode/build_phases/localization_check.sh new file mode 100755 index 0000000..6cd5c61 --- /dev/null +++ b/xcode/build_phases/localization_check.sh @@ -0,0 +1,9 @@ +# source: https://github.com/iKenndac/verify-string-files + +SOURCES_DIR=${1:-${TARGET_NAME}} # first argument or TARGET_NAME + +if [ "${CONFIGURATION}" = "DEBUG" ]; then + ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Base.lproj/Localizable.strings -warning-level warning +else + ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Base.lproj/Localizable.strings +fi From 94f1d45c7f59ff435e9f55adb3839376e6c886ae Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 14 Sep 2020 22:11:59 +0300 Subject: [PATCH 30/43] Code correction --- xcode/build_phases/localization_check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcode/build_phases/localization_check.sh b/xcode/build_phases/localization_check.sh index 6cd5c61..9a4407d 100755 --- a/xcode/build_phases/localization_check.sh +++ b/xcode/build_phases/localization_check.sh @@ -1,6 +1,6 @@ # source: https://github.com/iKenndac/verify-string-files -SOURCES_DIR=${1:-${TARGET_NAME}} # first argument or TARGET_NAME +readonly SOURCES_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR if [ "${CONFIGURATION}" = "DEBUG" ]; then ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Base.lproj/Localizable.strings -warning-level warning From 80cc86b4f817d971744356572c015b426fb5e731 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 14 Sep 2020 22:14:01 +0300 Subject: [PATCH 31/43] Code correction --- xcode/build_phases/localization_check.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xcode/build_phases/localization_check.sh b/xcode/build_phases/localization_check.sh index 9a4407d..ede7c9b 100755 --- a/xcode/build_phases/localization_check.sh +++ b/xcode/build_phases/localization_check.sh @@ -3,7 +3,7 @@ readonly SOURCES_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR if [ "${CONFIGURATION}" = "DEBUG" ]; then - ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Base.lproj/Localizable.strings -warning-level warning + ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Localization/Base.lproj/Localizable.strings -warning-level warning else - ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Base.lproj/Localizable.strings + ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Localization/Base.lproj/Localizable.strings fi From 2f65d801ec37dab309e8fb52445f35c8a0acb43e Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 14 Sep 2020 22:19:01 +0300 Subject: [PATCH 32/43] Code correction --- xcode/build_phases/localization_check.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/xcode/build_phases/localization_check.sh b/xcode/build_phases/localization_check.sh index ede7c9b..0b15d78 100755 --- a/xcode/build_phases/localization_check.sh +++ b/xcode/build_phases/localization_check.sh @@ -1,9 +1,11 @@ # source: https://github.com/iKenndac/verify-string-files readonly SOURCES_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR +readonly LOCALIZATION_PATH="${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings" +readonly CHECK_SCRIPT="${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check" if [ "${CONFIGURATION}" = "DEBUG" ]; then - ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Localization/Base.lproj/Localizable.strings -warning-level warning + ${SOURCES_DIR} -master ${LOCALIZATION_PATH} -warning-level warning else - ${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check -master ${SOURCES_DIR}/Resources/Localization/Base.lproj/Localizable.strings + ${CHECK_SCRIPT} -master ${LOCALIZATION_PATH} fi From b73abe782cc6eba22801b3a7fe39d900ed4b9b30 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 14 Sep 2020 22:27:42 +0300 Subject: [PATCH 33/43] Update binary --- xcode/build_phases/common/localization_check | Bin 72656 -> 72656 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/xcode/build_phases/common/localization_check b/xcode/build_phases/common/localization_check index 3ca068bbc5677ff06e90da59a2f916dc4d8dce82..201ca8c1697110251fcb64a7eb5240bcec5a033e 100755 GIT binary patch delta 14056 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 MlwbMTHywxmFLf1t5C8xG delta 13831 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 NAH25v;OP!I{|^IH9*F<| From 2f4628e5a72480b2613591cfa4265eb652febd89 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 14 Sep 2020 22:29:19 +0300 Subject: [PATCH 34/43] Update binary --- xcode/build_phases/common/localization_check | Bin 72656 -> 72656 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/xcode/build_phases/common/localization_check b/xcode/build_phases/common/localization_check index 201ca8c1697110251fcb64a7eb5240bcec5a033e..e1d10789411a9af4cd44a4f7d30a01832c1263c2 100755 GIT binary patch delta 318 zcmcbxo#n!ImJJ4+0zYf_&HWK%wR_bY)BCKy4=>y7z*(Zo*s^)6-t8d9jLj1p1N`JH z%~O(6EmP7gOpS~aladk>Q7f(~^>n6DR*apJp>{pMUT?Ru(PgMe{sg-7`q) zxu9OlZT61ea@M227G4_`SH?`7m6f)}%<+@F<+UQwZil}!9+q=v9-PA+*E4zHg%pv6 zZzHD9I`=R5Sx6RFM{8K{;e8dA9ifgKO6{Ru@m6ds#u@XRcqF%5$F&H=}g6E?B`U5OA+D&e!Iv?IBi~vd<=b y|0dtPyg(t=v6Gjx$uuA|a`vp|6-srDuJ_`KQ y`9AsX Date: Mon, 14 Sep 2020 22:30:38 +0300 Subject: [PATCH 35/43] Update script --- xcode/build_phases/localization_check.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/xcode/build_phases/localization_check.sh b/xcode/build_phases/localization_check.sh index 0b15d78..72b3733 100755 --- a/xcode/build_phases/localization_check.sh +++ b/xcode/build_phases/localization_check.sh @@ -4,8 +4,4 @@ readonly SOURCES_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR readonly LOCALIZATION_PATH="${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings" readonly CHECK_SCRIPT="${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check" -if [ "${CONFIGURATION}" = "DEBUG" ]; then - ${SOURCES_DIR} -master ${LOCALIZATION_PATH} -warning-level warning -else - ${CHECK_SCRIPT} -master ${LOCALIZATION_PATH} -fi +${CHECK_SCRIPT} -master ${LOCALIZATION_PATH} From 427adefbc6118dd6b72983198ec5894120671fa7 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 15 Sep 2020 10:54:46 +0300 Subject: [PATCH 36/43] Fix PR --- xcode/build_phases/localization_check.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xcode/build_phases/localization_check.sh b/xcode/build_phases/localization_check.sh index 72b3733..cf514c5 100755 --- a/xcode/build_phases/localization_check.sh +++ b/xcode/build_phases/localization_check.sh @@ -1,7 +1,9 @@ # source: https://github.com/iKenndac/verify-string-files -readonly SOURCES_DIR=${1:-${PROJECT_DIR}} # first argument or PROJECT_DIR -readonly LOCALIZATION_PATH="${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings" -readonly CHECK_SCRIPT="${SOURCES_DIR}/build-scripts/xcode/build_phases/common/localization_check" +# first argument set base localization strings path +readonly LOCALIZATION_PATH=${2:-${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings} + +# second argument set check script path +readonly CHECK_SCRIPT=${3:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/localization_check} ${CHECK_SCRIPT} -master ${LOCALIZATION_PATH} From 1e2e8518a44536fcb69380717ce26d653be311ac Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 15 Sep 2020 11:01:49 +0300 Subject: [PATCH 37/43] Fix typo --- xcode/build_phases/localization_check.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xcode/build_phases/localization_check.sh b/xcode/build_phases/localization_check.sh index cf514c5..afb80eb 100755 --- a/xcode/build_phases/localization_check.sh +++ b/xcode/build_phases/localization_check.sh @@ -1,9 +1,9 @@ # source: https://github.com/iKenndac/verify-string-files # first argument set base localization strings path -readonly LOCALIZATION_PATH=${2:-${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings} +readonly LOCALIZATION_PATH=${1:-${PRODUCT_NAME}/Resources/Localization/Base.lproj/Localizable.strings} # second argument set check script path -readonly CHECK_SCRIPT=${3:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/localization_check} +readonly CHECK_SCRIPT=${2:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/localization_check} ${CHECK_SCRIPT} -master ${LOCALIZATION_PATH} From ab03600b0ddd25cb6aea4b2806a1e19895020e84 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 15 Sep 2020 11:33:05 +0300 Subject: [PATCH 38/43] Add disposable_nil rule --- xcode/.swiftlint.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index 8e71145..cbda066 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -251,6 +251,12 @@ custom_rules: message: "The parameter name is actually used in the function name. Use _ instead." severity: error + disposable_nil: + name: "Disposable nil" + regex: ' *\S*(d|D)isposable *= *nil' + message: "Use `dispose()` instead of nil." + severity: error + # Rx unused_map_parameter: From 697805638cbd188565b7a54ab373a884baa94b05 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 15 Sep 2020 11:51:29 +0300 Subject: [PATCH 39/43] Code correction --- xcode/.swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index cbda066..2f1053a 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -253,7 +253,7 @@ custom_rules: disposable_nil: name: "Disposable nil" - regex: ' *\S*(d|D)isposable *= *nil' + regex: ' *\S*(d|D)isposable\?? *= *nil' message: "Use `dispose()` instead of nil." severity: error From c9ced95bce60c8658051896ab118bbf53ca14fe1 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 15 Sep 2020 12:05:24 +0300 Subject: [PATCH 40/43] Code correction --- xcode/.swiftlint.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index 2f1053a..7ba943a 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -251,12 +251,6 @@ custom_rules: message: "The parameter name is actually used in the function name. Use _ instead." severity: error - disposable_nil: - name: "Disposable nil" - regex: ' *\S*(d|D)isposable\?? *= *nil' - message: "Use `dispose()` instead of nil." - severity: error - # Rx unused_map_parameter: @@ -265,6 +259,12 @@ custom_rules: message: "Replace Rx.map operator with replace(with:) or asVoid(). For Sequence.map consider using forEach." severity: warning + disposable_nil: + name: "Disposable nil" + regex: ' *\S*(d|D)isposable\?? *= *nil' + message: "Use `dispose()` instead of nil." + severity: error + # LeadKit multiple_add_subview: From 7b92842a4beccfe7bd9487e2683b0d39ee357b89 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 15 Sep 2020 12:14:59 +0300 Subject: [PATCH 41/43] Update message --- xcode/.swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index 7ba943a..40a41b4 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -262,7 +262,7 @@ custom_rules: disposable_nil: name: "Disposable nil" regex: ' *\S*(d|D)isposable\?? *= *nil' - message: "Use `dispose()` instead of nil." + message: "nil assigning doesn't dispose subscription. Call `dispose()` instead." severity: error # LeadKit From 55e29f68a6a857db1556430cb59774f9ee8db0bb Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 18 Sep 2020 12:57:28 +0300 Subject: [PATCH 42/43] Add parameter_closure rule --- xcode/.swiftlint.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index 40a41b4..1b7f74b 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -251,6 +251,12 @@ custom_rules: message: "The parameter name is actually used in the function name. Use _ instead." severity: error + parameter_closure: + name: "Parameter closure" + regex: '\w*<\S*, Void\S*>' + message: "Use `ParameterClosure` instead of declaring an explicit return value of `Void`." + severity: error + # Rx unused_map_parameter: From b022bfce9539312e5c120f1bfced5dbc4e11ee80 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 18 Sep 2020 13:07:21 +0300 Subject: [PATCH 43/43] Code correction --- xcode/.swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcode/.swiftlint.yml b/xcode/.swiftlint.yml index 1b7f74b..a8c88c7 100644 --- a/xcode/.swiftlint.yml +++ b/xcode/.swiftlint.yml @@ -253,7 +253,7 @@ custom_rules: parameter_closure: name: "Parameter closure" - regex: '\w*<\S*, Void\S*>' + regex: '\w*Closure<[^\r\n\t\f\v]*, Void[^\r\n\t\f\v]*>' message: "Use `ParameterClosure` instead of declaring an explicit return value of `Void`." severity: error