podfileDep 2.3.6 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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