From 2c91968fdc441d0406b216713e9f7a59e37a93b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=AE=D1=80=D0=B8=D0=B8=CC=86=20=D0=A1=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=BA=D0=B8=D0=BD?= Date: Fri, 2 Aug 2019 16:53:13 +0300 Subject: [PATCH] Make config file .yml. Add OptionParser --- xcode/UnusedConfig.txt | 5 - xcode/UnusedConfig.yml | 5 + xcode/build_phases/Unused.rb | 271 +++++++++++++++++------------------ xcode/build_phases/unused.sh | 2 +- 4 files changed, 140 insertions(+), 143 deletions(-) delete mode 100644 xcode/UnusedConfig.txt create mode 100644 xcode/UnusedConfig.yml diff --git a/xcode/UnusedConfig.txt b/xcode/UnusedConfig.txt deleted file mode 100644 index 3dd1ffa..0000000 --- a/xcode/UnusedConfig.txt +++ /dev/null @@ -1,5 +0,0 @@ ---ignored-resources: -Generated/ -Resources/Localization -Carthage/ -Pods/ \ No newline at end of file diff --git a/xcode/UnusedConfig.yml b/xcode/UnusedConfig.yml new file mode 100644 index 0000000..8ac9173 --- /dev/null +++ b/xcode/UnusedConfig.yml @@ -0,0 +1,5 @@ +--ignored-resources: + - Generated/ + - Resources/Localization + - Carthage/ + - Pods/ \ No newline at end of file diff --git a/xcode/build_phases/Unused.rb b/xcode/build_phases/Unused.rb index dacf7ae..416b47e 100644 --- a/xcode/build_phases/Unused.rb +++ b/xcode/build_phases/Unused.rb @@ -1,190 +1,187 @@ #!/usr/bin/ruby #encoding: utf-8 +require 'yaml' +require 'optparse' + Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 -$config_argv_key = "--config" -$ignored_argv_key = "--ignored" -$ignored_resources_key = "--ignored-resources:" -$log_file_name = "UnusedLog.txt" - class Item - def initialize(file, line, at) - @file = file - @line = line - @at = at + 1 - if match = line.match(/(func|let|var|class|enum|struct|protocol)\s+(\w+)/) - @type = match.captures[0] - @name = match.captures[1] + def initialize(file, line, at) + @file = file + @line = line + @at = at + 1 + if match = line.match(/(func|let|var|class|enum|struct|protocol)\s+(\w+)/) + @type = match.captures[0] + @name = match.captures[1] + end end - end - def modifiers - return @modifiers if @modifiers - @modifiers = [] - if match = @line.match(/(.*?)#{@type}/) - @modifiers = match.captures[0].split(" ") + def modifiers + return @modifiers if @modifiers + @modifiers = [] + if match = @line.match(/(.*?)#{@type}/) + @modifiers = match.captures[0].split(" ") + end + return @modifiers end - return @modifiers - end - def name - @name - end + def name + @name + end - def file - @file - end + def file + @file + end - def to_s - serialize - end - def to_str - serialize - end + def to_s + serialize + end + def to_str + serialize + end - def full_file_path - Dir.pwd + '/' + @file - end + def full_file_path + Dir.pwd + '/' + @file + end - def serialize - "#{@type.to_s} #{@name.to_s} from: #{@file}:#{@at} is unused" - end + def serialize + "#{@type.to_s} #{@name.to_s} from: #{@file}:#{@at} is unused" + end - def to_xcode - "#{full_file_path}:#{@at}:0: warning: #{@type.to_s} #{@name.to_s} is unused" - end + def to_xcode + "#{full_file_path}:#{@at}:0: warning: #{@type.to_s} #{@name.to_s} is unused" + end end class Unused - def find - items = [] - unused_warnings = [] + def find + items = [] + unused_warnings = [] - regexps = parse_arguments + regexps = parse_arguments - all_files = Dir.glob("**/*.swift").reject do |path| - File.directory?(path) - end + all_files = Dir.glob("**/*.swift").reject do |path| + File.directory?(path) + end - all_files.each { |my_text_file| - file_items = grab_items(my_text_file) - file_items = filter_items(file_items) + all_files.each { |my_text_file| + file_items = grab_items(my_text_file) + file_items = filter_items(file_items) - non_private_items, private_items = file_items.partition { |f| !f.modifiers.include?("private") && !f.modifiers.include?("fileprivate") } - items += non_private_items + non_private_items, private_items = file_items.partition { |f| !f.modifiers.include?("private") && !f.modifiers.include?("fileprivate") } + items += non_private_items - # Usage within the file - if private_items.length > 0 - unused_warnings += find_usages_in_files([my_text_file], [], private_items, regexps) - end + # Usage within the file + if private_items.length > 0 + unused_warnings += find_usages_in_files([my_text_file], [], private_items, regexps) + end - } + } - xibs = Dir.glob("**/*.xib") - storyboards = Dir.glob("**/*.storyboard") + xibs = Dir.glob("**/*.xib") + storyboards = Dir.glob("**/*.storyboard") - unused_warnings += find_usages_in_files(all_files, xibs + storyboards, items, regexps) + unused_warnings += find_usages_in_files(all_files, xibs + storyboards, items, regexps) - if unused_warnings.length > 0 - # show warning - puts "#{unused_warnings.map { |e| e.to_xcode }.join("\n")}" - # write log - File.open($log_file_name, "w") do |file| - file.write("Unused code warnings count: #{unused_warnings.length}\n\n") - file.write("#{unused_warnings.map { |e| e.serialize }.join("\n")}") + if unused_warnings.length > 0 + # show warning + puts "#{unused_warnings.map { |e| e.to_xcode }.join("\n")}" + # write log + File.open("UnusedLog.txt", "w") do |file| + file.write("Unused code warnings count: #{unused_warnings.length}\n\n") + file.write("#{unused_warnings.map { |e| e.serialize }.join("\n")}") + end end end - end - def parse_arguments() - resources = [] + def parse_arguments() + resources = [] - arguments = ARGV.clone + options = {} + OptionParser.new do |opts| + options[:ignore] = [] - until arguments.empty? - item = arguments.shift + opts.on("-c", "--config=FileName") { |c| options[:config] = c } + opts.on("-i", "--ignore=a, b, c", Array) { |i| options[:ignore] += i } - # find --config file - if item == $config_argv_key - fileName = arguments.shift + end.parse! - # add --ignored-resources to array - File.readlines(fileName).each do |line| - if !line.include? $ignored_resources_key - resources += [line.chomp] - end - end - end + # find --config file + if !options[:config].nil? + fileName = options[:config] + resources += YAML.load_file(fileName).fetch("--ignored-resources") + elsif + puts "---------\n Warning: Config file is now provided \n---------" + end - # add --ignored files to array - if item == $ignored_argv_key - resources += [arguments.shift] - end - end + # find --ignored files + if !options[:ignore].nil? + resources += options[:ignore] + end - # create and return Regexp - resources.map { |r| Regexp.new(r) } - end + # create and return Regexp + resources.map { |r| Regexp.new(r) } + end - # remove files, that maches ignored Regexps array - def ignore_files_with_regexps(files, regexps) - files.select { |f| regexps.all? { |r| r.match(f.file).nil? } } - end + # remove files, that maches ignored Regexps array + def ignore_files_with_regexps(files, regexps) + files.select { |f| regexps.all? { |r| r.match(f.file).nil? } } + end - def find_usages_in_files(files, xibs, items_in, regexps) - items = items_in - usages = items.map { |f| 0 } - files.each { |file| - lines = File.readlines(file).map {|line| line.gsub(/^[^\/]*\/\/.*/, "") } - words = lines.join("\n").split(/\W+/) - words_arrray = words.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten + def find_usages_in_files(files, xibs, items_in, regexps) + items = items_in + usages = items.map { |f| 0 } + files.each { |file| + lines = File.readlines(file).map {|line| line.gsub(/^[^\/]*\/\/.*/, "") } + words = lines.join("\n").split(/\W+/) + words_arrray = words.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten - wf = Hash[*words_arrray] + wf = Hash[*words_arrray] - items.each_with_index { |f, i| - usages[i] += (wf[f.name] || 0) - } - # Remove all items which has usage 2+ - indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i } + items.each_with_index { |f, i| + usages[i] += (wf[f.name] || 0) + } + # Remove all items which has usage 2+ + indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i } - # reduce usage array if we found some functions already - indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) } - } + # reduce usage array if we found some functions already + indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) } + } - xibs.each { |xib| - lines = File.readlines(xib).map {|line| line.gsub(/^\s*\/\/.*/, "") } - full_xml = lines.join(" ") - classes = full_xml.scan(/(class|customClass)="([^"]+)"/).map { |cd| cd[1] } - classes_array = classes.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten + xibs.each { |xib| + lines = File.readlines(xib).map {|line| line.gsub(/^\s*\/\/.*/, "") } + full_xml = lines.join(" ") + classes = full_xml.scan(/(class|customClass)="([^"]+)"/).map { |cd| cd[1] } + classes_array = classes.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten - wf = Hash[*classes_array] + wf = Hash[*classes_array] - items.each_with_index { |f, i| - usages[i] += (wf[f.name] || 0) - } - # Remove all items which has usage 2+ - indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i } + items.each_with_index { |f, i| + usages[i] += (wf[f.name] || 0) + } + # Remove all items which has usage 2+ + indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i } - # reduce usage array if we found some functions already - indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) } + # reduce usage array if we found some functions already + indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) } - } + } - items = ignore_files_with_regexps(items, regexps) - end + items = ignore_files_with_regexps(items, regexps) + end - def grab_items(file) - lines = File.readlines(file).map {|line| line.gsub(/^\s*\/\/.*/, "") } - items = lines.each_with_index.select { |line, i| line[/(func|let|var|class|enum|struct|protocol)\s+\w+/] }.map { |line, i| Item.new(file, line, i)} - end + def grab_items(file) + lines = File.readlines(file).map {|line| line.gsub(/^\s*\/\/.*/, "") } + items = lines.each_with_index.select { |line, i| line[/(func|let|var|class|enum|struct|protocol)\s+\w+/] }.map { |line, i| Item.new(file, line, i)} + end - def filter_items(items) - items.select { |f| - !f.name.start_with?("test") && !f.modifiers.include?("@IBAction") && !f.modifiers.include?("override") && !f.modifiers.include?("@objc") && !f.modifiers.include?("@IBInspectable") - } - end + def filter_items(items) + items.select { |f| + !f.name.start_with?("test") && !f.modifiers.include?("@IBAction") && !f.modifiers.include?("override") && !f.modifiers.include?("@objc") && !f.modifiers.include?("@IBInspectable") + } + end end diff --git a/xcode/build_phases/unused.sh b/xcode/build_phases/unused.sh index 3301156..01fe69d 100644 --- a/xcode/build_phases/unused.sh +++ b/xcode/build_phases/unused.sh @@ -1 +1 @@ -ruby ${PROJECT_DIR}/build-scripts/xcode/build_phases/Unused.rb --config ${PROJECT_DIR}/build-scripts/xcode/UnusedConfig.txt +ruby ${PROJECT_DIR}/build-scripts/xcode/build_phases/Unused.rb --config ${PROJECT_DIR}/build-scripts/xcode/UnusedConfig.yml