iosappaudit 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '020928007442acd4e62981306e047324cd18bbae4639a3abfa989d2451fb68e2'
4
+ data.tar.gz: eae2e1627e5f9e20f74cb99ae865b75fb6919a660545a92313557781aafe2358
5
+ SHA512:
6
+ metadata.gz: 74575f011ea5d86e3d027901e84155d34fcd9cc1b74ffddc1d4ba0ca29bb01efa6cb6cb5e82b1afce0e1fd9e9225b90c7549837ed9c1ecd7569b016e23ddf45c
7
+ data.tar.gz: bf7062f0c587b10604320744d7b81b4ad04a5a56c2ac817b1af0999ed94f835755dc6c3e6bb2ee52ec3d4e1fd00ea4052e3f630c623859c6009ba3617764633b
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in iosappaudit.gemspec
4
+ gemspec
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "iosappaudit"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ project_url: "" # required
2
+ sources_url: "" # required
3
+ xcodeproj:
4
+ name: "" # first xcodeproj found will be used if empty
5
+ main_target_name: "" # first target will be used if empty
6
+ complexity:
7
+ file_line_count_threshold: 500
8
+ output_format:
9
+ adds_row_padding: true
10
+ size: 0
11
+ csv_output: audit.csv
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require 'iosappaudit'
@@ -0,0 +1,35 @@
1
+ section:
2
+ project:
3
+ title: Project
4
+ row:
5
+ name: Name
6
+ version: Version
7
+ deployment_target: Deployment Target
8
+ localizations: Localizations
9
+ settings:
10
+ title: Settings
11
+ row:
12
+ schemes: Schemes
13
+ targets: Targets
14
+ configurations: Configurations
15
+ complexity:
16
+ title: Code
17
+ row:
18
+ file_count: Files
19
+ file_count_threshold: !!pl
20
+ 1: Files with more than one line
21
+ n: Files with more than %1 lines
22
+ swift_file_count: Swift files
23
+ obj_c_file_count: Objective C files
24
+ code_line_count: Lines of code
25
+ ccn_line_count: Cyclomatic Complexity Number
26
+ resources:
27
+ title: Resources
28
+ row:
29
+ xib_count: Xibs
30
+ storyboards: Storyboards
31
+ tests:
32
+ title: Tests
33
+ row:
34
+ unit_tests: Unit Tests
35
+ ui_tests: UI Tests
@@ -0,0 +1,43 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "iosappaudit/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'iosappaudit'
8
+ s.version = IOSAppAudit::VERSION
9
+ s.date = '2019-01-23'
10
+ s.summary = "Audit"
11
+ s.description = "Audit"
12
+ s.authors = ["Gaétan Zanella"]
13
+ s.email = 'gaetan.zanella@gmail.com'
14
+ # use `git ls-files -coz -x *.gem` for development
15
+
16
+ s.homepage = 'http://rubygems.org/gems/hola'
17
+ s.license = 'MIT'
18
+ s.add_dependency "xcodeproj", "~> 1.4"
19
+ s.add_dependency "r18n-core", "~> 3.2"
20
+ s.add_dependency "colorize", "~> 0.8"
21
+ s.add_development_dependency "byebug", "~> 10.0"
22
+
23
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
24
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
25
+ if s.respond_to?(:metadata)
26
+ s.metadata["allowed_push_host"] = "https://rubygems.org"
27
+ s.metadata["homepage_uri"] = s.homepage
28
+ s.metadata["source_code_uri"] = "https://github.com/faberNovel/iosappaudit"
29
+ s.metadata["changelog_uri"] = "https://github.com/faberNovel/iosappaudit/blob/master/CHANGELOG.md"
30
+ else
31
+ raise "RubyGems 2.0 or newer is required to protect against " \
32
+ "public gem pushes."
33
+ end
34
+
35
+ # Specify which files should be added to the gem when it is released.
36
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
37
+ s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
38
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
39
+ end
40
+ s.bindir = "exe"
41
+ s.executables = ["iosappaudit"]
42
+ s.require_paths = ["lib"]
43
+ end
@@ -0,0 +1,37 @@
1
+ require 'optparse'
2
+ require 'xcodeproj'
3
+ require 'rexml/document'
4
+ require 'r18n-core'
5
+ require 'CSV'
6
+ require 'yaml'
7
+ require 'JSON'
8
+ require 'fileutils'
9
+ require 'colorize'
10
+
11
+ require_relative "iosappaudit/Review/complexity_report.rb"
12
+ require_relative "iosappaudit/Review/complexity_report_parser.rb"
13
+ require_relative "iosappaudit/Review/complexity_reviewer.rb"
14
+ require_relative "iosappaudit/Review/project_report.rb"
15
+ require_relative "iosappaudit/Review/project_reviewer.rb"
16
+ require_relative "iosappaudit/Helper/file_seeker.rb"
17
+ require_relative "iosappaudit/Helper/options_parser.rb"
18
+ require_relative "iosappaudit/Presenter/CSVReportPresenter.rb"
19
+
20
+ options = {}
21
+ OptionParser.new do |parser|
22
+ parser.on("-o", "--option=URL") do |url|
23
+ options[:url] = url
24
+ end
25
+ end.parse!
26
+
27
+ properties_parser = Helper::OptionsParser.new
28
+ properties = properties_parser.parse options
29
+
30
+ complexity_reviewer = Review::ComplexityReviewer.new
31
+ complexity_report = complexity_reviewer.review_folder properties
32
+
33
+ project_reviewer = Review::ProjectReviewer.new
34
+ project_report = project_reviewer.review_folder properties
35
+
36
+ presenter = Presenter::CSVReportPresenter.new properties, project_report, complexity_report
37
+ presenter.generate_review
@@ -0,0 +1,20 @@
1
+ module Helper
2
+ class FileSeeker
3
+
4
+ def initialize()
5
+ end
6
+
7
+
8
+ def find_files(url, name, extension)
9
+ Dir.glob("#{url}/**/#{name}.#{extension}")
10
+ end
11
+
12
+ def find_files_with_extension(url, extension)
13
+ Dir.glob("#{url}/**/*.#{extension}")
14
+ end
15
+
16
+ def find_file_names_with_extension(url, extension)
17
+ find_files_with_extension(url, extension).map { |url| File.basename(url) }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Helper
2
+ class OptionsParser
3
+ def parse(options)
4
+ default_properties = JSON.parse(YAML::load_file(__dir__ + "/../../../default_configuration.yaml").to_json, object_class: Hash)
5
+ properties = JSON.parse(YAML::load_file(options[:url]).to_json, object_class: Hash)
6
+ default_properties.merge! properties
7
+ symbolizeOptions default_properties
8
+ end
9
+
10
+ def symbolizeOptions(options)
11
+ options.inject({}) { |new_hash, key_value|
12
+ key, value = key_value
13
+ value = symbolizeOptions(value) if value.is_a?(Hash)
14
+ new_hash[key.to_sym] = value
15
+ new_hash
16
+ }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,94 @@
1
+ include R18n::Helpers
2
+
3
+ module Presenter
4
+ class CSVReportPresenter
5
+
6
+ def initialize(options, project_report, complexity_report)
7
+ @project_report = project_report
8
+ @complexity_report = complexity_report
9
+ @options = options
10
+ root = File.expand_path '../../..', File.dirname(__FILE__)
11
+ R18n.default_places = "#{root}/i18n/"
12
+ R18n.set('en')
13
+ end
14
+
15
+ def generate_review
16
+ puts "Generating csv review..."
17
+ url = @options[:csv_output]
18
+ CSV.open(url, "wb") do |csv|
19
+ # Project
20
+ csv << section(t.section.project.title)
21
+ csv << value_row(t.section.project.row.name, @project_report.name)
22
+ csv << value_row(t.section.project.row.version, @project_report.version)
23
+ csv << value_row(t.section.project.row.deployment_target, @project_report.deployment_target.first)
24
+ csv << array_row(t.section.project.row.localizations, @project_report.localizations)
25
+ # Settings
26
+ csv << section(t.section.settings.title)
27
+ csv << array_row(t.section.settings.row.targets, @project_report.target_names)
28
+ csv << array_row(t.section.settings.row.configurations, @project_report.configuration_names)
29
+ # Complexity
30
+ csv << section(t.section.complexity.title)
31
+ csv << array_row(t.section.complexity.row.file_count, @project_report.main_target_files)
32
+ csv << array_row(t.section.complexity.row.swift_file_count, @project_report.main_target_swift_files)
33
+ csv << array_row(t.section.complexity.row.obj_c_file_count, @project_report.main_target_obj_c_files)
34
+ csv << value_row(t.section.complexity.row.code_line_count, @complexity_report.file_measure.sum_ncss)
35
+ file_line_count_threshold = @options[:complexity][:file_line_count_threshold]
36
+ metrics_ncss = @complexity_report.file_metrics_with_more_than_count_lines @options[:complexity][:file_line_count_threshold]
37
+ csv << array_row(t.section.complexity.row.file_count_threshold(file_line_count_threshold), format_ncss(metrics_ncss))
38
+ metrics_ccn = @complexity_report.file_metrics_sorted_by_ccn
39
+ csv << value_row(t.section.complexity.row.ccn_line_count, @complexity_report.file_measure.sum_ccn, format_ccn(metrics_ccn))
40
+ # Resources
41
+ csv << section(t.section.resources.title)
42
+ csv << array_row(t.section.resources.row.xib_count, @project_report.xibs)
43
+ csv << array_row(t.section.resources.row.storyboards, @project_report.storyboards)
44
+ # Tests
45
+ csv << section(t.section.tests.title)
46
+ csv << array_row(t.section.tests.row.unit_tests, @project_report.unit_test_target_files)
47
+ csv << array_row(t.section.tests.row.ui_tests, @project_report.ui_test_target_files)
48
+ end
49
+ puts "Report #{url} created 🎉".colorize(:green)
50
+ end
51
+
52
+ def section(title)
53
+ return [title]
54
+ end
55
+
56
+ def value_row(title, value, detail=[])
57
+ if value.nil?
58
+ return format_row [title, detail]
59
+ end
60
+ format_row [title, value, format_array(detail)]
61
+ end
62
+
63
+ def array_row(title, array)
64
+ if array.nil?
65
+ return [title, 0]
66
+ end
67
+ return format_row [title, array.count, format_array(array)]
68
+ end
69
+
70
+ def format_row(array)
71
+ if @options[:output_format][:adds_row_padding]
72
+ array.unshift("")
73
+ end
74
+ array
75
+ end
76
+
77
+ def format_array(array)
78
+ size = @options[:output_format][:size]
79
+ output = array.first(size).join("\n")
80
+ if array.count > size
81
+ output += "\n..."
82
+ end
83
+ output
84
+ end
85
+
86
+ def format_ncss(metrics)
87
+ metrics.map { |metric| "(#{metric.ncss}) #{metric.file_url}" }
88
+ end
89
+
90
+ def format_ccn(metrics)
91
+ metrics.map { |metric| "(#{metric.ccn}) #{metric.file_url}" }
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,70 @@
1
+ module Review
2
+ class FunctionMetric
3
+
4
+ attr_accessor :file_url, :function_name, :line_number, :ncss, :ccn
5
+
6
+ def initialize(file_url = "", function_name = "", line_number = 0, ncss = 0, ccn = 0)
7
+ @file_url = file_url
8
+ @function_name = function_name
9
+ @line_number = line_number
10
+ @ncss = ncss
11
+ @ccn = ccn
12
+ end
13
+ end
14
+
15
+ class FileMetric
16
+
17
+ attr_accessor :file_url, :ncss, :ccn, :functions
18
+
19
+ def initialize(file_url = "", ncss = 0, ccn = 0, functions = 0)
20
+ @file_url = file_url
21
+ @ncss = ncss
22
+ @ccn = ccn
23
+ @functions = functions
24
+ end
25
+ end
26
+
27
+ class FunctionMeasure
28
+
29
+ attr_accessor :metrics, :average_ncss, :average_ccn
30
+
31
+ def initialize(metrics = [], average_ncss = 0, average_ccn = 0)
32
+ @metrics = metrics
33
+ @average_ncss = average_ncss
34
+ @average_ccn = average_ccn
35
+ end
36
+ end
37
+
38
+ class FileMeasure
39
+
40
+ attr_accessor :metrics, :average_ncss, :average_ccn, :average_functions, :sum_ncss, :sum_ccn, :sum_functions
41
+
42
+ def initialize(metrics = [], average_ncss = 0, average_ccn = 0, average_functions = 0, sum_ncss = 0, sum_ccn = 0, sum_functions = 0)
43
+ @metrics = metrics
44
+ @average_ncss = average_ncss
45
+ @average_ccn = average_ccn
46
+ @average_functions = average_functions
47
+ @sum_ncss = sum_ncss
48
+ @sum_ccn = sum_ccn
49
+ @sum_functions = sum_functions
50
+ end
51
+ end
52
+
53
+ class ComplexityReport
54
+
55
+ attr_accessor :function_measure, :file_measure
56
+
57
+ def initialize(function_measure = [], file_measure = [])
58
+ @function_measure = function_measure
59
+ @file_measure = file_measure
60
+ end
61
+
62
+ def file_metrics_with_more_than_count_lines(count)
63
+ file_measure.metrics.select { |metric| metric.ncss >= count }.sort { |lhs, rhs| (lhs.ncss <=> rhs.ncss) * -1 }
64
+ end
65
+
66
+ def file_metrics_sorted_by_ccn
67
+ file_measure.metrics.sort { |lhs, rhs| (lhs.ccn <=> rhs.ccn) * -1 }
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,50 @@
1
+ include REXML
2
+
3
+ module Review
4
+ class ComplexityReportParser
5
+
6
+ def initialize()
7
+ end
8
+
9
+ def parse_file(url)
10
+ file = File.new url
11
+ doc = Document.new file
12
+
13
+ function_measure = FunctionMeasure.new
14
+ file_measure = FileMeasure.new
15
+
16
+ function_xml = doc.root.elements["measure[@type='Function']"]
17
+ function_measure.average_ncss = function_xml.elements["average[@label='NCSS']"]["value"].to_s.to_f
18
+ function_measure.average_ccn = function_xml.elements["average[@label='CCN']"]["value"].to_s.to_f
19
+ function_xml.elements.each("item") do |item|
20
+ values = item.get_elements("value")
21
+ item_name = item.attributes["name"]
22
+ metric = FunctionMetric.new
23
+ metric.file_url = /(?<=( at )).+(?=:)/.match(item_name).to_s
24
+ metric.function_name = /.+(?=\(...\))/.match(item_name).to_s
25
+ metric.line_number = /(?<=:)\d+/.match(item_name).to_s.to_i
26
+ metric.ncss = values[1].text.to_i
27
+ metric.ccn = values[2].text.to_i
28
+ function_measure.metrics.push metric
29
+ end
30
+
31
+ file_xml = doc.root.elements["measure[@type='File']"]
32
+ file_measure.average_ncss = file_xml.elements["average[@label='NCSS']"]["value"].to_s.to_f
33
+ file_measure.average_ccn = file_xml.elements["average[@label='CCN']"]["value"].to_s.to_f
34
+ file_measure.average_functions = file_xml.elements["average[@label='Functions']"]["value"].to_s.to_f
35
+ file_measure.sum_ncss = file_xml.elements["sum[@label='NCSS']"]["value"].to_s.to_i
36
+ file_measure.sum_ccn = file_xml.elements["sum[@label='CCN']"]["value"].to_s.to_i
37
+ file_measure.sum_functions = file_xml.elements["sum[@label='Functions']"]["value"].to_s.to_i
38
+ file_xml.elements.each("item") do |item|
39
+ values = item.get_elements("value")
40
+ metric = FileMetric.new
41
+ metric.file_url = item.attributes["name"].to_s
42
+ metric.ncss = values[1].text.to_i
43
+ metric.ccn = values[2].text.to_i
44
+ metric.functions = values[3].text.to_i
45
+ file_measure.metrics.push metric
46
+ end
47
+ ComplexityReport.new function_measure, file_measure
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ module Review
2
+ class ComplexityReviewer
3
+
4
+ def initialize()
5
+ end
6
+
7
+ def review_folder(options)
8
+ puts "Reviewing source complexity... "
9
+ lizard_report = "lizard-report.xml"
10
+ source = options[:sources_url]
11
+ `lizard -m --xml #{source} > #{lizard_report}`
12
+ parser = ComplexityReportParser.new
13
+ report = parser.parse_file lizard_report
14
+ FileUtils.rm lizard_report
15
+ report
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,45 @@
1
+ module Review
2
+ class ProjectReport
3
+ attr_accessor :name, :version, :deployment_target, :target_names, :configuration_names, :main_target_name, :main_target_files, :main_target_resources, :ui_test_target_name, :unit_test_target_name, :ui_test_target_files, :unit_test_target_files, :localizations
4
+
5
+ def initialize
6
+ @name = ""
7
+ @version = ""
8
+ @deployment_target = ""
9
+ @target_names = ""
10
+ @configuration_names = ""
11
+ @main_target_name = ""
12
+ @main_target_files = []
13
+ @main_target_resources = []
14
+ @ui_test_target_name = ""
15
+ @unit_test_targe_name = ""
16
+ @ui_test_target_files = []
17
+ @unit_test_target_files = []
18
+ @localizations = []
19
+ end
20
+
21
+ def main_target_swift_files
22
+ main_target_files.select { |file| file.include?(".swift") }
23
+ end
24
+
25
+ def main_target_obj_c_files
26
+ main_target_files.select { |file| file.include?(".m") }
27
+ end
28
+
29
+ def has_swift_files?
30
+ main_target_swift_files.empty?
31
+ end
32
+
33
+ def has_obj_c_files?
34
+ main_target_obj_c_files.empty?
35
+ end
36
+
37
+ def xibs
38
+ main_target_resources.select { |file| file.include?(".xib") }
39
+ end
40
+
41
+ def storyboards
42
+ main_target_resources.select { |file| file.include?(".storyboard") }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,61 @@
1
+ module Review
2
+ class ProjectReviewer
3
+
4
+ def initialize()
5
+ end
6
+
7
+ def review_folder(options)
8
+ file_seeker = Helper::FileSeeker.new
9
+ url = options[:project_url]
10
+ project_name = options[:xcodeproj][:name]
11
+ urls = []
12
+ if project_name.empty?
13
+ urls = file_seeker.find_files_with_extension url, "xcodeproj"
14
+ else
15
+ urls = file_seeker.find_files url, project_name, "xcodeproj"
16
+ end
17
+ if urls.empty?
18
+ raise "Xcode project not found"
19
+ end
20
+ report = ProjectReport.new
21
+ project = Xcodeproj::Project.open urls.first
22
+ project_basename = File.basename(urls.first)
23
+ puts "Reviewing #{project_basename}..."
24
+ root_object = project.root_object
25
+ if root_object.targets.empty?
26
+ raise "Xcode project #{root_object.name} has no target"
27
+ end
28
+ report.name = root_object.name
29
+ report.deployment_target = root_object.targets.map { |target| target.deployment_target }.uniq
30
+ report.target_names = root_object.targets.map &:name
31
+ report.configuration_names = root_object.targets.flat_map { |target| target.build_configurations.map(&:name) }.uniq
32
+ report.localizations = findLocalizations project
33
+ main_target_name = options[:xcodeproj][:main_target_name]
34
+ main_target = nil
35
+ if main_target_name.empty?
36
+ main_target = root_object.targets[0]
37
+ else
38
+ main_target = root_object.targets.detect { |target| target.name == main_target_name }
39
+ if main_target.nil?
40
+ raise "Xcode target named #{main_target_name} not found"
41
+ end
42
+ end
43
+ report.version = project.build_configurations.map { |config| config.build_settings["CURRENT_PROJECT_VERSION"] }.uniq.first
44
+ ui_test_target = root_object.targets.detect { |target| target.build_configurations.any? { |config| !config.build_settings["TEST_TARGET_NAME"].nil? } }
45
+ unit_test_target = root_object.targets.detect { |target| target.build_configurations.any? { |config| !config.build_settings["TEST_HOST"].nil? } }
46
+ report.main_target_name = main_target&.name
47
+ report.main_target_files = main_target&.source_build_phase&.files&.map { |file| file.display_name }
48
+ report.main_target_resources = main_target&.resources_build_phase&.files&.map { |file| file.display_name }
49
+ report.ui_test_target_name = ui_test_target&.name
50
+ report.unit_test_target_name = unit_test_target&.name
51
+ report.ui_test_target_files = ui_test_target&.source_build_phase&.files&.map { |file| file.display_name }
52
+ report.unit_test_target_files = unit_test_target&.source_build_phase&.files&.map { |file| file.display_name }
53
+ return report
54
+ end
55
+
56
+ def findLocalizations(project)
57
+ files = project.files.select { |f| f.path.include?("Localizable.strings") }
58
+ files.map { |f| f.name.nil? ? "base" : f.name }.uniq
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ module IOSAppAudit
2
+ VERSION = "1.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: iosappaudit
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Gaétan Zanella
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-01-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: xcodeproj
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: r18n-core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: colorize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.8'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.8'
55
+ - !ruby/object:Gem::Dependency
56
+ name: byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ description: Audit
70
+ email: gaetan.zanella@gmail.com
71
+ executables:
72
+ - iosappaudit
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - Rakefile
79
+ - bin/console
80
+ - bin/setup
81
+ - default_configuration.yaml
82
+ - exe/iosappaudit
83
+ - i18n/en.yml
84
+ - iosappaudit.gemspec
85
+ - lib/iosappaudit.rb
86
+ - lib/iosappaudit/Helper/file_seeker.rb
87
+ - lib/iosappaudit/Helper/options_parser.rb
88
+ - lib/iosappaudit/Presenter/CSVReportPresenter.rb
89
+ - lib/iosappaudit/Review/complexity_report.rb
90
+ - lib/iosappaudit/Review/complexity_report_parser.rb
91
+ - lib/iosappaudit/Review/complexity_reviewer.rb
92
+ - lib/iosappaudit/Review/project_report.rb
93
+ - lib/iosappaudit/Review/project_reviewer.rb
94
+ - lib/iosappaudit/version.rb
95
+ homepage: http://rubygems.org/gems/hola
96
+ licenses:
97
+ - MIT
98
+ metadata:
99
+ allowed_push_host: https://rubygems.org
100
+ homepage_uri: http://rubygems.org/gems/hola
101
+ source_code_uri: https://github.com/faberNovel/iosappaudit
102
+ changelog_uri: https://github.com/faberNovel/iosappaudit/blob/master/CHANGELOG.md
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubygems_version: 3.0.3
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Audit
122
+ test_files: []