podfileDep 2.3.6 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b141be5a2d0872d97b87f3afbd0549bf6d65146f66d665432a71f82ec5da405
4
- data.tar.gz: bdd4ee72216e8929dad9c09c0bb79d487b3dfd3805026d44efbad9c2740e633b
3
+ metadata.gz: 90b91a2988e18202add645f9dfb02623d018854b09ed5b3e1c7cfe52ca463fba
4
+ data.tar.gz: 1a7f61c0e7d35282204b055e3580bf4d78894fc6525a3b1f5d59bfea7d4f95d4
5
5
  SHA512:
6
- metadata.gz: 8a0e1e6c178434c745cb3aece459458fe770ec2da2ca8e3d4efa742706f6078d5584232a94f6d22bc7d95bb8498e3eac4e97cb738767343f5be50690f89e5997
7
- data.tar.gz: 0d2cdac871d2c5ef04c13e6606bea7498a5b2d1e21662ede1ffb2abf088712d2bd2041e9eedf81a3cbab54d28976432cda1711db25dfddc88338f79ea465627c
6
+ metadata.gz: b6d370629f905be0397b4e76f2c2198b800a8e7868882d1436ed3a8a9aa19c57d3ed0a775ce1947e9e8f345cc6f2a018fc9d30c4264d966b87da80bca97f5bed
7
+ data.tar.gz: dccea04f95d9d9d06db5a22424ebf02f360a465b18f2e4a07aa05af32e3bbc2423dc34b429b360acdab81c5abdd1a878ba2578ee3b32f1c867f52dbdae9969d8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Released]
2
2
 
3
+ ### [2.4.1] - 2023-7-29
4
+ - 依赖库关系检查特殊问题修复
5
+
6
+ ### [2.4.0] - 2023-7-29
7
+ - 依赖库关系检查
8
+
3
9
  ### [2.3.6] - 2023-7-25
4
10
  - 彩色打印
5
11
 
@@ -1,11 +1,12 @@
1
1
  require 'cocoapods'
2
2
  require_relative 'podfileDep/command/quick'
3
3
  require_relative 'podfileDep/check/project'
4
- require_relative 'podfileDep/check/dep'
4
+ require_relative 'podfileDep/check/podspec'
5
5
  require_relative 'podfileDep/modify/modify_code'
6
6
  require_relative 'podfileDep/reference/project'
7
7
  require_relative 'podfileDep/indirect/indirect'
8
8
  require_relative 'podfileDep/reference/unused'
9
+ require_relative 'podfileDep/check/import'
9
10
 
10
11
  # 注册插件
11
12
  module CocoapodsPlugin
@@ -26,13 +27,16 @@ module CocoapodsPlugin
26
27
  # end
27
28
 
28
29
  Pod::HooksManager.register('podfileDep', :post_install) do |context|
29
- # 检查依赖库
30
- # Dep::DepChecker.dep_check
31
30
 
32
31
  project = Xcodeproj::XCodeProject.new
33
32
 
34
33
  # 检查import
35
- project.check_import
34
+ checker1 = Xcodeproj::ImportChecker.new(project)
35
+ checker1.check_import
36
+
37
+ # 检查podspec
38
+ checker2 = Xcodeproj::PodspecChecker.new(project)
39
+ checker2.check_podspec
36
40
 
37
41
  # 代码文件处理
38
42
  ModifyCode::Modify.modify_fb
@@ -1,159 +1,76 @@
1
- # require 'pathname'
2
- # require 'yaml'
3
- # require_relative '../constants'
4
- # require_relative 'module'
5
- # require_relative 'item'
6
- # require_relative 'xcodeproj'
7
- #
8
- # module Import
9
- # class ImportManager
10
- #
11
- # # 检查import规范
12
- # def self.import_check
13
- # puts "\nimport规范检查中..."
14
- # start = (Time.now.to_f * 1000).to_i
15
- #
16
- # project_manager = XCProject::XcodeprojManager.share_manager
17
- #
18
- # # 获取需要检查的模块名和路径
19
- # modules = project_manager.get_development_module
20
- #
21
- # # 获取Pods和本地依赖库的 组件名和包含的头文件列表 map类型
22
- # module_headers = project_manager.get_installed_headers_module
23
- #
24
- # # 计数
25
- # check_count = 0
26
- #
27
- # # 遍历需要被检查的模块
28
- # modules.each_value { |module_item|
29
- #
30
- # # 某个模块从代码文件里读取的双引号依赖库 #import "XX/XX.h"
31
- # import_item_map = {}
32
- #
33
- # #头文件的文件名
34
- # header_file_names = []
35
- #
36
- # module_item.source_files.each { |source_file|
37
- #
38
- # header_file_name = File.basename(source_file)
39
- # if header_file_name.end_with?(".h") or header_file_name.end_with?(".hpp") or header_file_name.end_with?(".pch")
40
- # header_file_names << header_file_name
41
- # end
42
- #
43
- # self.update_import_dot_item_map(source_file, module_item, import_item_map)
44
- #
45
- # check_count += 1
46
- # }
47
- #
48
- # if import_item_map.size == 0 and header_file_names.size == 0
49
- # next
50
- # end
51
- #
52
- # messages = []
53
- # import_item_map.each {|key, value| #key是 xxx.h value是{ImportItem:}
54
- #
55
- # # 当前仓库的文件已包含
56
- # if header_file_names.include?(key)
57
- # next
58
- # end
59
- #
60
- # # 是否是导入的系统lib
61
- # if self.check_sys_libary(key)
62
- # next
63
- # end
64
- #
65
- # search_module_name = self.get_module_name(module_headers, key)
66
- #
67
- # unless search_module_name
68
- # next
69
- # end
70
- #
71
- # messages << "#{value.file_name} 第#{value.line_index}行 #{value.import_name} => #import <#{search_module_name}/#{value.pod}>"
72
- #
73
- # }
74
- #
75
- # if messages.size >0
76
- # puts "⚠️ 组件#{module_item.module_name}存在以下情况, 请检查:"
77
- # puts messages
78
- # puts "\n"
79
- # end
80
- #
81
- # }
82
- #
83
- # duration = ((Time.now.to_f * 1000).to_i - start)*0.001
84
- # puts "import规范检查完毕! 共检查#{modules.size.to_s}个组件(#{check_count}个文件) 耗时:#{duration.round(2)}秒"
85
- # end
86
- #
87
- # # 获取某个文件内对应类型的import "XXX.h"
88
- # def self.update_import_dot_item_map(file_path, module_name, import_item_map)
89
- # if File.directory?(file_path)
90
- # return
91
- # end
92
- #
93
- # line_array = IO.readlines(file_path)
94
- # line_array.each_with_index { |line, index|
95
- # line = line.gsub(" ", "")
96
- # unless line.start_with?("#import\"")
97
- # next
98
- # end
99
- #
100
- # if line.start_with?("@implementation")
101
- # break
102
- # end
103
- #
104
- # line_split_array = line.split("\"")
105
- # if line_split_array.size <= 1
106
- # next
107
- # end
108
- #
109
- # import_name = "#{line_split_array[0]}\"#{line_split_array[1]}\"" # import"XXX.h" 或import"XXX.AAA.h" 防止后边有其他内容
110
- #
111
- # # 特殊处理
112
- # if import_name == "#import\"NBSAppAgent.h\""
113
- # next
114
- # end
115
- #
116
- # podfile = import_name
117
- # podfile = podfile.gsub("#import\"", "")
118
- # podfile = podfile.gsub("\"", "") # 变成 XX.h
119
- #
120
- # # 已经包含
121
- # if import_item_map[podfile]
122
- # next
123
- # end
124
- # pre_index = index-1 < 0 ? 0 : index-1
125
- # pre_line = line_array[pre_index]
126
- # pre_line = pre_line.gsub(" ", "").gsub("\n", "")
127
- # if pre_line.start_with?("#if") or pre_line == "#else"
128
- # next
129
- # end
130
- #
131
- # file_name = File.basename(file_path)
132
- # line_index = index+1
133
- #
134
- # import_item_map[podfile] = ImportItem.new(import_name, module_name, file_name, line_index, podfile)
135
- #
136
- # }
137
- # end
138
- #
139
- # # 根据文件名反查出属于哪个组件
140
- # def self.get_module_name(module_headers, file_name)
141
- # module_headers.each do |module_name,module_item|
142
- # module_item.source_files.each {|source_file|
143
- # if source_file.basename.to_s == file_name
144
- # return module_name
145
- # end
146
- # }
147
- # end
148
- # return nil
149
- # end
150
- #
151
- # # 获取某库是否是系统级的依赖库
152
- # def self.check_sys_libary(name)
153
- # name = name.gsub(".h", "")
154
- # libs = Constants::LIBLIBARYS
155
- # return libs.include?(name)
156
- # end
157
- #
158
- # end
159
- # end
1
+ require_relative 'project'
2
+
3
+ module Xcodeproj
4
+ class ImportChecker
5
+
6
+ # @return [XCodeProject]
7
+ attr_accessor :project
8
+
9
+ # @param project::[XCodeProject]
10
+ def initialize(project)
11
+ @project = project
12
+ end
13
+
14
+ # 检查import规范
15
+ def check_import
16
+ puts "import检查中..."
17
+ start = (Time.now.to_f * 1000).to_i
18
+ module_count = 0
19
+ file_count = 0
20
+
21
+ project.module_items.each do |module_name, module_item|
22
+ unless module_item.is_development_module
23
+ next
24
+ end
25
+ module_count += 1
26
+
27
+ messages = []
28
+
29
+ did_check_imports = {}
30
+ module_item.init_import_info
31
+
32
+ module_item.import_items.each do |import_item|
33
+ file_count += 1
34
+ did_check_import = did_check_imports[import_item.import_file_name]
35
+ if did_check_import
36
+ next
37
+ end
38
+ need_module_item = project.module_items[import_item.module_name]
39
+ real_path = need_module_item.header_files[import_item.import_file_name]
40
+ did_check_imports[import_item.import_file_name] = !!(real_path)
41
+ unless real_path
42
+ # 去查找所属模块
43
+ expect_module_name = find_module_with_header_file(import_item.import_file_name)
44
+ if expect_module_name
45
+ messages << "#{import_item.file_path.basename} 第#{import_item.line_index}行 #{import_item.import_name} => #import <#{expect_module_name}/#{import_item.import_file_name}>"
46
+ end
47
+ end
48
+ end
49
+
50
+ if messages.size >0
51
+ puts "组件#{module_item.module_name}存在以下情况, 请检查:".yellow
52
+ puts messages
53
+ puts "\n"
54
+ end
55
+
56
+ end
57
+
58
+ duration = ((Time.now.to_f * 1000).to_i - start)*0.001
59
+ puts "import检查完毕! 共检查#{module_count}个组件(#{file_count}个import) 耗时:#{duration.round(2)}秒"
60
+ end
61
+
62
+ private
63
+ # 根据头文件名查找所属组件
64
+ # @return [String, nil]
65
+ def find_module_with_header_file(header_file_name)
66
+ project.module_items.each do |module_name, module_item|
67
+ file_path = module_item.header_files[header_file_name]
68
+ if file_path
69
+ return module_item.module_name
70
+ end
71
+ end
72
+ nil
73
+ end
74
+
75
+ end
76
+ end
@@ -1,11 +1,204 @@
1
1
 
2
- class ImportItem
3
- attr_reader :import_name, :module_item, :file_name, :line_index, :pod
4
- def initialize(import_name, module_item, file_name, line_index, pod)
5
- @import_name = import_name
6
- @module_item = module_item
7
- @file_name = file_name
8
- @line_index = line_index
9
- @pod = pod
2
+ module Xcodeproj
3
+ class ImportItem
4
+ attr_accessor :import_name
5
+ attr_accessor :module_name
6
+ attr_accessor :file_path
7
+ attr_accessor :import_file_name
8
+ attr_accessor :line_index
9
+ attr_accessor :belong_module
10
+ def initialize
11
+ @import_name = nil
12
+ @module_name = nil
13
+ @file_path = nil
14
+ @import_file_name = nil
15
+ @line_index = nil
16
+ @belong_module = nil
17
+ end
18
+
19
+ end
20
+
21
+ class ModuleItem
22
+
23
+ public
24
+ # 组名名
25
+ attr_accessor :module_name
26
+
27
+ # 组件路径
28
+ attr_accessor :module_path
29
+
30
+ # podspec路径
31
+ attr_accessor :podspec_path
32
+
33
+ # 组件目录的所有被引用的文件数组
34
+ attr_accessor :header_files
35
+
36
+ # 组件目录的所有被引用的文件数组
37
+ attr_accessor :source_files
38
+
39
+ # 是否是开发模块
40
+ attr_accessor :is_development_module
41
+
42
+ # [ImportItem]
43
+ attr_accessor :import_items
44
+
45
+ # [ImportItem]
46
+ attr_accessor :absolute_import_items
47
+
48
+ # [String]
49
+ attr_accessor :frameworks
50
+
51
+ def initialize(module_name)
52
+ @module_name = module_name
53
+ @module_path = nil
54
+ @podspec_path = nil
55
+ @header_files = {}
56
+ @source_files = {}
57
+ @import_items = []
58
+ @absolute_import_items = []
59
+ @is_development_module = false
60
+ @frameworks = []
61
+ end
62
+
63
+ # 生成 import <XX/YY.h>的信息
64
+ # 生成 include <XX/YY.h>的信息
65
+ def init_absolute_import_info
66
+ source_files.each_value do |source_file_path|
67
+ if File.directory?(source_file_path)
68
+ next
69
+ end
70
+
71
+ line_array = IO.readlines(source_file_path)
72
+ line_array.each_with_index { |line, line_index|
73
+ line = line.gsub(" ", "")
74
+
75
+ # 处理特殊情况
76
+ if line.start_with?("#import\"NBSAppAgent.h\"")
77
+ line = "#import<tingyunApp/NBSAppAgent.h>"
78
+ end
79
+
80
+ if not line.start_with?("#import<") and not line.start_with?("#include<")
81
+ next
82
+ end
83
+
84
+ if line.start_with?("@implementation")
85
+ break
86
+ end
87
+
88
+ # 前一行的内容 这里不是检测,则不需要
89
+ pre_line = ""
90
+
91
+ import_item = other_module_import(line, source_file_path, line_index, @module_name, pre_line)
92
+ if import_item
93
+ absolute_import_items << import_item
94
+ end
95
+ }
96
+ end
97
+
98
+ absolute_import_items
99
+ end
100
+
101
+ # 生成 import "XXX.h"的信息
102
+ def init_import_info
103
+ source_files.each_value do |source_file_path|
104
+ if File.directory?(source_file_path)
105
+ next
106
+ end
107
+
108
+ line_array = IO.readlines(source_file_path)
109
+ line_array.each_with_index { |line, line_index|
110
+ line = line.gsub(" ", "")
111
+
112
+ unless line.start_with?("#import")
113
+ next
114
+ end
115
+
116
+ if line.start_with?("@implementation")
117
+ break
118
+ end
119
+
120
+ # 前一行的内容
121
+ pre_index = line_index-1 < 0 ? 0 : line_index-1
122
+ pre_line = line_array[pre_index]
123
+
124
+ if line.start_with?("#import\"") #本组件
125
+ import_item = own_module_import(line, source_file_path, line_index, @module_name, pre_line)
126
+ if import_item
127
+ import_items << import_item
128
+ end
129
+ elsif line.start_with?("#import<") #其他组件
130
+
131
+ end
132
+
133
+ }
134
+ end
135
+
136
+ import_items
137
+ end
138
+
139
+ private
140
+ # 生成自己模块的import item
141
+ # @param line 以 import" 开头
142
+ def own_module_import(line, file_path, line_index, module_name, pre_line)
143
+ line_split_array = line.split("\"")
144
+ if line_split_array.size <= 1
145
+ return nil
146
+ end
147
+
148
+ import_content = "#{line_split_array[0]}\"#{line_split_array[1]}\"" # import"XXX.h" 或import"XXX.AAA.h" 防止后边有其他内容
149
+
150
+ # 特殊处理
151
+ if import_content == "#import\"NBSAppAgent.h\""
152
+ return nil
153
+ end
154
+
155
+ pre_line = pre_line.gsub(" ", "").gsub("\n", "")
156
+ if pre_line.start_with?("#if") or pre_line == "#else"
157
+ return nil
158
+ end
159
+
160
+ import_file_name = import_content
161
+ import_file_name = import_file_name.gsub("#import\"", "")
162
+ import_file_name = import_file_name.gsub("\"", "") # 变成 XX.h
163
+
164
+
165
+ import_item = ImportItem.new # (import_name, module_name, file_name, line_index, podfile)
166
+ import_item.import_name = import_content.gsub("#import\"", "#import \"")
167
+ import_item.module_name = module_name
168
+ import_item.file_path = file_path
169
+ import_item.import_file_name = import_file_name
170
+ import_item.line_index = line_index + 1
171
+
172
+ import_item
173
+ end
174
+
175
+
176
+ def other_module_import(line, file_path, line_index, module_name, pre_line)
177
+ line = line.gsub("\n","")
178
+ line_split_array = line.split("/") #import<XX/YY.h> 或 #import<XX/YY/ZZ.h>
179
+ if line_split_array.size <= 1
180
+ return nil
181
+ end
182
+
183
+ pre_line = pre_line.gsub(" ", "").gsub("\n", "")
184
+ if pre_line.start_with?("#if") or pre_line == "#else"
185
+ return nil
186
+ end
187
+
188
+ import_file_name = line_split_array[line_split_array.size-1].gsub(">", "")
189
+ belong_module = line_split_array[0].gsub("#import<", "").gsub("#include<", "")
190
+ import_name = line.gsub("#import<", "#import <").gsub("#include<", "#include <")
191
+
192
+ import_item = ImportItem.new # (import_name, module_name, file_name, line_index, podfile)
193
+ import_item.import_name = import_name
194
+ import_item.module_name = module_name
195
+ import_item.file_path = file_path
196
+ import_item.import_file_name = import_file_name
197
+ import_item.line_index = line_index + 1
198
+ import_item.belong_module = belong_module
199
+
200
+ import_item
201
+
202
+ end
10
203
  end
11
204
  end
@@ -0,0 +1,175 @@
1
+ require_relative 'project'
2
+ require_relative 'util'
3
+ require_relative '../my_constants'
4
+
5
+ module Xcodeproj
6
+ class PodspecChecker
7
+
8
+ # @return [XCodeProject]
9
+ attr_accessor :project
10
+
11
+ # @param project::[XCodeProject]
12
+ def initialize(project)
13
+ @project = project
14
+ end
15
+
16
+ # 检查podspec文件
17
+ def check_podspec
18
+ puts "podspec文件检查中..."
19
+ start = (Time.now.to_f * 1000).to_i
20
+ module_count = 0
21
+
22
+ project.module_items.each do |module_name, module_item|
23
+ unless module_item.is_development_module
24
+ next
25
+ end
26
+ module_count += 1
27
+
28
+ module_item.init_absolute_import_info
29
+
30
+ # 代码里需要的模块
31
+ need_modules = get_code_need_modules(module_item)
32
+
33
+ # podspec直接依赖
34
+ podspec_modules = get_podspec_modules(module_item)
35
+
36
+ loss = loss_modules(need_modules, podspec_modules)
37
+ unused = unused_modules(need_modules, podspec_modules)
38
+
39
+ if loss.size >0
40
+ puts "组件#{module_item.module_name}可能缺少以下依赖, 请检查:".yellow
41
+ loss.each do |name|
42
+ puts " s.dependency '#{name}'"
43
+ end
44
+ end
45
+
46
+ if unused.size >0
47
+ puts "组件#{module_item.module_name}可能未使用以下依赖, 请检查:".yellow
48
+ puts unused
49
+ end
50
+
51
+ end
52
+
53
+ duration = ((Time.now.to_f * 1000).to_i - start)*0.001
54
+ puts "podspec检查完毕! 共检查#{module_count}个组件 耗时:#{duration.round(2)}秒"
55
+ end
56
+
57
+ private
58
+
59
+ # 获取缺失的模块
60
+ # @param need_modules::[String]
61
+ # @param podspec_modules::[Hash{String => [String]}]
62
+ def loss_modules(need_modules, podspec_modules)
63
+ # 展开
64
+ temp_array = []
65
+ podspec_modules.each do |podspec_module|
66
+ podspec_modules.values.each do |array|
67
+ temp_array = temp_array | array
68
+ end
69
+ end
70
+
71
+ res = []
72
+ need_modules.each do |name|
73
+ unless temp_array.include?(name)
74
+ res << name
75
+ end
76
+ end
77
+ res
78
+ end
79
+
80
+ # 获取多余的模块
81
+ # @param need_modules::[String]
82
+ # @param podspec_modules::[Hash{String => [String]}]
83
+ def unused_modules(need_modules, podspec_modules)
84
+ res = []
85
+ podspec_modules.each do |dep_name, array|
86
+ contain = false
87
+ array.each do |vendor|
88
+ if need_modules.include?(vendor)
89
+ contain = true
90
+ end
91
+ end
92
+
93
+ unless contain
94
+ res << dep_name
95
+ end
96
+ end
97
+ res
98
+ end
99
+
100
+ # @note 获取代码里需要的模块
101
+ def get_code_need_modules(module_item)
102
+ import_items = module_item.absolute_import_items
103
+ result_dic = {}
104
+ import_items.each do |import_item|
105
+ # 过滤系统库
106
+ if system_modules.include?(import_item.belong_module)
107
+ next
108
+ end
109
+
110
+ # 过滤当前库
111
+ if module_item.module_name == import_item.belong_module
112
+ next
113
+ end
114
+
115
+ # 过滤未被安装的依赖库
116
+ unless module_is_installed(import_item.belong_module)
117
+ next
118
+ end
119
+
120
+ result_dic[import_item.belong_module] = import_item
121
+ end
122
+ result_dic.keys
123
+ end
124
+
125
+ # 获取podspec文件里写的模块 直接依赖
126
+ # @return [Hash{String => [String]}]
127
+ def get_podspec_modules(module_item)
128
+
129
+ podspec_content = Util.get_podspec_content(module_item.podspec_path)
130
+
131
+ podspec_dependencies = podspec_content["dependencies"] ? podspec_content["dependencies"].keys : []
132
+
133
+ # 子模块
134
+ subspecs = podspec_content["subspecs"]
135
+ if subspecs and subspecs.class == Array
136
+ subspecs.each do |subspec|
137
+ subspec_deps = subspec["dependencies"] ? subspec["dependencies"].keys : []
138
+ podspec_dependencies = podspec_dependencies + subspec_deps
139
+ end
140
+ end
141
+
142
+ # 转成map
143
+ result = {}
144
+ podspec_dependencies.each do |podspec_dependency|
145
+ podspec_dependency = podspec_dependency.split("/")[0] #如果podspec里写的依赖是带/的,取/前第一个, 例如:s.dependency 'UMCShare/Social/ReducedQQ'
146
+ dependency_item = project.module_items[podspec_dependency]
147
+ if dependency_item
148
+ result[podspec_dependency] = dependency_item.frameworks
149
+ else #如果/都处理了,还是取不到,那就整个默认值,自身
150
+ frameworks = [podspec_dependency]
151
+ if podspec_dependency.include?("/") #处理依赖 s.dependency 'UMCShare/Social/ReducedQQ'
152
+ frameworks << podspec_dependency.split("/")[0]
153
+ end
154
+ result[podspec_dependency] = frameworks
155
+ end
156
+ end
157
+
158
+ result
159
+ end
160
+
161
+ # 判断某个库是否被安装
162
+ def module_is_installed(module_name)
163
+ all = project.lock_content["SPEC CHECKSUMS"]
164
+ unless all
165
+ return false
166
+ end
167
+ !!all[module_name]
168
+ end
169
+ # 系统级的依赖库
170
+ # @return [String]
171
+ def system_modules
172
+ MyConstants::LIBLIBARYS + MyConstants::FRAMEWORKS
173
+ end
174
+ end
175
+ end