1 // Copyright (c) 2024 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gn/ohos_components_checker.h"
6
7 #include <fstream>
8 #include <functional>
9 #include <iostream>
10 #include <sys/stat.h>
11
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/json/json_reader.h"
15 #include "base/values.h"
16 #include "gn/build_settings.h"
17 #include "gn/config.h"
18 #include "gn/filesystem_utils.h"
19 #include "gn/functions.h"
20 #include "gn/ohos_components.h"
21 #include "gn/parse_tree.h"
22 #include "gn/settings.h"
23 #include "gn/substitution_writer.h"
24 #include "gn/target.h"
25 #include "gn/value.h"
26
27 static const std::string SCAN_RESULT_PATH = "scan_out";
28 static const std::string WHITELIST_PATH = "component_compilation_whitelist.json";
29 static const int BASE_BINARY = 1;
30 static std::vector<std::string> all_deps_config_;
31 static std::map<std::string, std::vector<std::string>> public_deps_;
32 static std::map<std::string, std::vector<std::string>> lib_dirs_;
33 static std::vector<std::string> includes_over_range_;
34 static std::map<std::string, std::vector<std::string>> innerapi_public_deps_inner_;
35 static std::vector<std::string> innerapi_not_lib_;
36 static std::vector<std::string> innerapi_not_declare_;
37 static std::map<std::string, std::vector<std::string>> includes_absolute_deps_other_;
38 static std::map<std::string, std::vector<std::string>> target_absolute_deps_other_;
39 static std::map<std::string, std::vector<std::string>> import_other_;
40 static std::map<std::string, std::vector<std::string>> deps_not_lib_;
41 static std::map<std::string, std::vector<std::string>> fuzzy_match_;
42
43 OhosComponentChecker *OhosComponentChecker::instance_ = nullptr;
44
Trim(std::string & str)45 static std::string& Trim(std::string &str)
46 {
47 if (str.empty()) {
48 return str;
49 }
50 str.erase(0, str.find_first_not_of(" \t\r\n"));
51 str.erase(str.find_last_not_of(" \t\r\n") + 1);
52 return str;
53 }
54
StartWith(const std::string & str,const std::string & prefix)55 static bool StartWith(const std::string &str, const std::string &prefix)
56 {
57 return (str.rfind(prefix, 0) == 0);
58 }
59
CreateScanOutDir(const std::string & dir)60 static void CreateScanOutDir(const std::string &dir)
61 {
62 base::FilePath path(dir);
63 base::CreateDirectory(path);
64 return;
65 }
66
RemoveScanOutDir(const std::string & dir)67 static void RemoveScanOutDir(const std::string& dir)
68 {
69 if (access(dir.c_str(), F_OK) == -1) {
70 return;
71 }
72 base::FilePath path(dir);
73 base::DeleteFile(path, true);
74 return;
75 }
76
ReadBuildConfigFile(base::FilePath path,std::string & content)77 static bool ReadBuildConfigFile(base::FilePath path, std::string &content)
78 {
79 if (!base::ReadFileToString(path, &content)) {
80 return false;
81 }
82 return true;
83 }
84
LoadAllDepsConfigWhitelist(const base::Value & list)85 static void LoadAllDepsConfigWhitelist(const base::Value &list)
86 {
87 for (const base::Value &value : list.GetList()) {
88 all_deps_config_.push_back(value.GetString());
89 }
90 }
91
LoadIncludesOverRangeWhitelist(const base::Value & list)92 static void LoadIncludesOverRangeWhitelist(const base::Value &list)
93 {
94 for (const base::Value &value : list.GetList()) {
95 includes_over_range_.push_back(value.GetString());
96 }
97 }
98
LoadInnerApiPublicDepsInnerWhitelist(const base::Value & value)99 static void LoadInnerApiPublicDepsInnerWhitelist(const base::Value &value)
100 {
101 for (auto info : value.DictItems()) {
102 for (const base::Value &value_tmp : info.second.GetList()) {
103 innerapi_public_deps_inner_[info.first].push_back(value_tmp.GetString());
104 }
105 }
106 }
107
LoadPublicDepsWhitelist(const base::Value & value)108 static void LoadPublicDepsWhitelist(const base::Value &value)
109 {
110 for (auto info : value.DictItems()) {
111 for (const base::Value &value_tmp : info.second.GetList()) {
112 public_deps_[info.first].push_back(value_tmp.GetString());
113 }
114 }
115 }
116
LoadLibDirsWhitelist(const base::Value & value)117 static void LoadLibDirsWhitelist(const base::Value &value)
118 {
119 for (auto info : value.DictItems()) {
120 for (const base::Value &value_tmp : info.second.GetList()) {
121 lib_dirs_[info.first].push_back(value_tmp.GetString());
122 }
123 }
124 }
125
LoadInnerApiNotLibWhitelist(const base::Value & list)126 static void LoadInnerApiNotLibWhitelist(const base::Value &list)
127 {
128 for (const base::Value &value : list.GetList()) {
129 innerapi_not_lib_.push_back(value.GetString());
130 }
131 }
132
LoadInnerApiNotDeclareWhitelist(const base::Value & list)133 static void LoadInnerApiNotDeclareWhitelist(const base::Value &list)
134 {
135 for (const base::Value &value : list.GetList()) {
136 innerapi_not_declare_.push_back(value.GetString());
137 }
138 }
139
LoadIncludesAbsoluteDepsOtherWhitelist(const base::Value & value)140 static void LoadIncludesAbsoluteDepsOtherWhitelist(const base::Value &value)
141 {
142 for (auto info : value.DictItems()) {
143 for (const base::Value &value_tmp : info.second.GetList()) {
144 includes_absolute_deps_other_[info.first].push_back(value_tmp.GetString());
145 }
146 }
147 }
148
LoadAbsoluteDepsOtherWhitelist(const base::Value & value)149 static void LoadAbsoluteDepsOtherWhitelist(const base::Value &value)
150 {
151 for (auto info : value.DictItems()) {
152 for (const base::Value &value_tmp : info.second.GetList()) {
153 target_absolute_deps_other_[info.first].push_back(value_tmp.GetString());
154 }
155 }
156 }
157
LoadImportOtherWhitelist(const base::Value & value)158 static void LoadImportOtherWhitelist(const base::Value &value)
159 {
160 for (auto info : value.DictItems()) {
161 for (const base::Value &value_tmp : info.second.GetList()) {
162 import_other_[info.first].push_back(value_tmp.GetString());
163 }
164 }
165 }
166
LoadDepsNotLibWhitelist(const base::Value & value)167 static void LoadDepsNotLibWhitelist(const base::Value &value)
168 {
169 for (auto info : value.DictItems()) {
170 for (const base::Value &value_tmp : info.second.GetList()) {
171 deps_not_lib_[info.first].push_back(value_tmp.GetString());
172 }
173 }
174 }
175
LoadFuzzyMatchWhitelist(const base::Value & value)176 static void LoadFuzzyMatchWhitelist(const base::Value &value)
177 {
178 for (auto info : value.DictItems()) {
179 for (const base::Value &value_tmp : info.second.GetList()) {
180 fuzzy_match_[info.first].push_back(value_tmp.GetString());
181 }
182 }
183 }
184
185 static std::map<std::string, std::function<void(const base::Value &value)>> whitelist_map_ = {
186 { "all_dependent_configs", LoadAllDepsConfigWhitelist },
187 { "includes_over_range", LoadIncludesOverRangeWhitelist },
188 { "innerapi_not_lib", LoadInnerApiNotLibWhitelist },
189 { "innerapi_not_declare", LoadInnerApiNotDeclareWhitelist },
190 { "innerapi_public_deps_inner", LoadInnerApiPublicDepsInnerWhitelist },
191 { "public_deps", LoadPublicDepsWhitelist },
192 { "lib_dirs", LoadLibDirsWhitelist },
193 { "includes_absolute_deps_other", LoadIncludesAbsoluteDepsOtherWhitelist },
194 { "target_absolute_deps_other", LoadAbsoluteDepsOtherWhitelist },
195 { "import_other", LoadImportOtherWhitelist },
196 { "deps_not_lib", LoadDepsNotLibWhitelist },
197 { "fuzzy_match", LoadFuzzyMatchWhitelist }
198 };
199
LoadWhitelist(const std::string & build_dir)200 static void LoadWhitelist(const std::string &build_dir)
201 {
202 std::string whitelistContent;
203 if (!ReadBuildConfigFile(base::FilePath(build_dir + "/" + WHITELIST_PATH), whitelistContent)) {
204 if (!ReadBuildConfigFile(base::FilePath("out/products_ext/" + WHITELIST_PATH), whitelistContent)) {
205 if (!ReadBuildConfigFile(base::FilePath("build/" + WHITELIST_PATH), whitelistContent)) {
206 return;
207 }
208 }
209 }
210 const base::DictionaryValue *whitelist_dict;
211 std::unique_ptr<base::Value> whitelist = base::JSONReader::ReadAndReturnError(whitelistContent,
212 base::JSONParserOptions::JSON_PARSE_RFC, nullptr, nullptr, nullptr, nullptr);
213 if (!whitelist) {
214 return;
215 }
216 if (!whitelist->GetAsDictionary(&whitelist_dict)) {
217 return;
218 }
219
220 for (const auto kv : whitelist_dict->DictItems()) {
221 auto iter = whitelist_map_.find(kv.first);
222 if (iter != whitelist_map_.end()) {
223 iter->second(kv.second);
224 }
225 }
226 return;
227 }
228
IsIntercept(unsigned int switchValue,int shiftLeftNum)229 static bool IsIntercept(unsigned int switchValue, int shiftLeftNum)
230 {
231 if ((switchValue & (BASE_BINARY << (shiftLeftNum - 1))) != 0) {
232 return true;
233 }
234 return false;
235 }
236
InterceptAllDepsConfig(const Target * target,const std::string & label,Err * err) const237 bool OhosComponentChecker::InterceptAllDepsConfig(const Target *target, const std::string &label, Err *err) const
238 {
239 if (!IsIntercept(ruleSwitch_, ALL_DEPS_CONFIG_BINARY)) {
240 return true;
241 }
242
243 auto result = std::find(all_deps_config_.begin(), all_deps_config_.end(), label);
244 if (result != all_deps_config_.end()) {
245 return true;
246 }
247
248 *err = Err(target->defined_from(), "all_dependent_configs not allowed.",
249 "The item " + label + " does not allow all_dependent_configs.");
250 return false;
251 }
252
InterceptIncludesOverRange(const Target * target,const std::string & label,const std::string & dir,Err * err) const253 bool OhosComponentChecker::InterceptIncludesOverRange(const Target *target, const std::string &label,
254 const std::string &dir, Err *err) const
255 {
256 if (!IsIntercept(ruleSwitch_, INCLUDE_OVER_RANGE_BINARY)) {
257 return true;
258 }
259
260 auto result = std::find(includes_over_range_.begin(), includes_over_range_.end(), label);
261 if (result != includes_over_range_.end()) {
262 return true;
263 }
264 *err = Err(target->defined_from(), "Header file range is too large.",
265 "The item " + label + " header : " + dir + " range is too large.");
266 return false;
267 }
268
InterceptInnerApiPublicDepsInner(const Target * target,const std::string & label,const std::string & deps,Err * err) const269 bool OhosComponentChecker::InterceptInnerApiPublicDepsInner(const Target *target, const std::string &label,
270 const std::string &deps, Err *err) const
271 {
272 if (!IsIntercept(ruleSwitch_, INNERAPI_PUBLIC_DEPS_INNER_BINARY)) {
273 return true;
274 }
275
276 if (auto res = innerapi_public_deps_inner_.find(label); res != innerapi_public_deps_inner_.end()) {
277 std::string deps_str(deps);
278 auto res_second = std::find(res->second.begin(), res->second.end(), Trim(deps_str));
279 if (res_second != res->second.end()) {
280 return true;
281 }
282 }
283 *err = Err(target->defined_from(), "InnerApi not allow the use of public_deps dependent internal modules.",
284 "The item " + label + " not allow the use of public_deps dependent internal module : " + deps);
285 return false;
286 }
287
InterceptPublicDeps(const Target * target,const std::string & label,const std::string & deps,Err * err) const288 bool OhosComponentChecker::InterceptPublicDeps(const Target *target, const std::string &label,
289 const std::string &deps, Err *err) const
290 {
291 if (!IsIntercept(ruleSwitch_, PUBLIC_DEPS_BINARY)) {
292 return true;
293 }
294
295 if (auto res = public_deps_.find(label); res != public_deps_.end()) {
296 std::string deps_str(deps);
297 auto res_second = std::find(res->second.begin(), res->second.end(), Trim(deps_str));
298 if (res_second != res->second.end()) {
299 return true;
300 }
301 }
302 *err = Err(target->defined_from(), "public_deps/public_external_deps not allowed.",
303 "The item " + label + " not allow the use of public_deps/public_external_deps dependent module : " + deps);
304 return false;
305 }
306
InterceptLibDir(const Target * target,const std::string & label,const std::string & dir,Err * err) const307 bool OhosComponentChecker::InterceptLibDir(const Target *target, const std::string &label,
308 const std::string &dir, Err *err) const
309 {
310 if (!IsIntercept(ruleSwitch_, LIB_DIRS_BINARY)) {
311 return true;
312 }
313
314 if (auto res = fuzzy_match_.find("lib_dirs"); res != fuzzy_match_.end()) {
315 std::string lib_dirs(dir);
316 for (auto res_second : res->second) {
317 if (StartWith(Trim(lib_dirs), res_second)) {
318 return true;
319 }
320 }
321 }
322
323 if (auto res = lib_dirs_.find(label); res != lib_dirs_.end()) {
324 std::string lib_dirs(dir);
325 auto res_second = std::find(res->second.begin(), res->second.end(), Trim(lib_dirs));
326 if (res_second != res->second.end()) {
327 return true;
328 }
329 }
330
331 *err = Err(target->defined_from(), "lib_dirs not allowed.",
332 "The item" + label + " do not use lib_dirs : " + dir);
333 return false;
334 }
335
InterceptInnerApiNotLib(const Item * item,const std::string & label,Err * err) const336 bool OhosComponentChecker::InterceptInnerApiNotLib(const Item *item, const std::string &label, Err *err) const
337 {
338 if (!IsIntercept(ruleSwitch_, INNERAPI_NOT_LIB_BINARY)) {
339 return true;
340 }
341
342 auto result = std::find(innerapi_not_lib_.begin(), innerapi_not_lib_.end(), label);
343 if (result != innerapi_not_lib_.end()) {
344 return true;
345 }
346 *err =
347 Err(item->defined_from(), "InnerApi is not a library type.", "The item " + label + " is not a library type.");
348 return false;
349 }
350
InterceptDepsNotLib(const Item * item,const std::string & label,const std::string & deps,Err * err) const351 bool OhosComponentChecker::InterceptDepsNotLib(const Item *item, const std::string &label,
352 const std::string &deps, Err *err) const
353 {
354 if (!IsIntercept(ruleSwitch_, DEPS_NOT_LIB_BINARY)) {
355 return true;
356 }
357
358 if (auto res = fuzzy_match_.find("deps_not_lib"); res != fuzzy_match_.end()) {
359 std::string deps_str(deps);
360 for (auto res_second : res->second) {
361 if (StartWith(Trim(deps_str), res_second)) {
362 return true;
363 }
364 }
365 }
366
367 if (auto res = deps_not_lib_.find(label); res != deps_not_lib_.end()) {
368 std::string deps_str(deps);
369 auto res_second = std::find(res->second.begin(), res->second.end(), Trim(deps_str));
370 if (res_second != res->second.end()) {
371 return true;
372 }
373 }
374 *err = Err(item->defined_from(), "Depend a non-lib target.",
375 "The item " + label + " cannot depend on a non-lib target " + deps);
376 return false;
377 }
378
InterceptInnerApiNotDeclare(const Item * item,const std::string & label,Err * err) const379 bool OhosComponentChecker::InterceptInnerApiNotDeclare(const Item *item, const std::string &label, Err *err) const
380 {
381 if (!IsIntercept(ruleSwitch_, INNERAPI_NOT_DECLARE_BINARY)) {
382 return true;
383 }
384
385 auto result = std::find(innerapi_not_declare_.begin(), innerapi_not_declare_.end(), label);
386 if (result != innerapi_not_declare_.end()) {
387 return true;
388 }
389 *err = Err(item->defined_from(), "InnerApi is not defined in bundle.json.",
390 "The item " + label + " is not defined in bundle.json.");
391 return false;
392 }
393
InterceptIncludesAbsoluteDepsOther(const Target * target,const std::string & label,const std::string & includes,Err * err) const394 bool OhosComponentChecker::InterceptIncludesAbsoluteDepsOther(const Target *target, const std::string &label,
395 const std::string &includes, Err *err) const
396 {
397 if (!IsIntercept(ruleSwitch_, INCLUDES_ABSOLUTE_DEPS_OTHER_BINARY)) {
398 return true;
399 }
400
401 if (auto res = fuzzy_match_.find("deps_includes_absolute"); res != fuzzy_match_.end()) {
402 std::string includes_str(includes);
403 for (auto res_second : res->second) {
404 if (StartWith(Trim(includes_str), res_second)) {
405 return true;
406 }
407 }
408 }
409
410 if (auto res = includes_absolute_deps_other_.find(label); res != includes_absolute_deps_other_.end()) {
411 std::string includes_str(includes);
412 auto res_second = std::find(res->second.begin(), res->second.end(), Trim(includes_str));
413 if (res_second != res->second.end()) {
414 return true;
415 }
416 }
417 *err = Err(target->defined_from(), "Do not directly use header files of other components.",
418 "The item " + label + " do not directly use header files : " + includes + " of other components." +
419 "\n"
420 "Please use 'external_deps' dependent module.");
421 return false;
422 }
423
424
InterceptTargetAbsoluteDepsOther(const Item * item,const std::string & label,const std::string & deps,Err * err) const425 bool OhosComponentChecker::InterceptTargetAbsoluteDepsOther(const Item *item, const std::string &label,
426 const std::string &deps, Err *err) const
427 {
428 if (!IsIntercept(ruleSwitch_, TARGET_ABSOLUTE_DEPS_OTHER_BINARY)) {
429 return true;
430 }
431
432 if (auto res = fuzzy_match_.find("deps_component_absolute"); res != fuzzy_match_.end()) {
433 std::string deps_str(deps);
434 for (auto res_second : res->second) {
435 if (StartWith(Trim(deps_str), res_second)) {
436 return true;
437 }
438 }
439 }
440
441 if (auto res = target_absolute_deps_other_.find(label); res != target_absolute_deps_other_.end()) {
442 std::string deps_str(deps);
443 auto res_second = std::find(res->second.begin(), res->second.end(), Trim(deps_str));
444 if (res_second != res->second.end()) {
445 return true;
446 }
447 }
448 *err = Err(item->defined_from(), "Not allow use absolute dependent other component.",
449 "The item " + label + " not allow use absolute dependent other component : " + deps +
450 "\n"
451 "Please use 'external_deps'.");
452 return false;
453 }
454
InterceptInnerApiVisibilityDenied(const Item * item,const std::string & from_label,const std::string & to_label,Err * err) const455 bool OhosComponentChecker::InterceptInnerApiVisibilityDenied(const Item *item, const std::string &from_label,
456 const std::string &to_label, Err *err) const
457 {
458 if (!IsIntercept(ruleSwitch_, INNERAPI_VISIBILITY_DENIED)) {
459 return true;
460 }
461
462 *err = Err(item->defined_from(), "InnerApi visibility denied.",
463 "The item " + from_label + " cannot dependent " + to_label +
464 "\n"
465 "Please check 'visibility' field in 'bundle.json' of " +
466 to_label);
467 return false;
468 }
469
InterceptImportOther(const FunctionCallNode * function,const std::string & label,const std::string & deps,Err * err) const470 bool OhosComponentChecker::InterceptImportOther(const FunctionCallNode *function, const std::string &label,
471 const std::string &deps, Err *err) const
472 {
473 if (!IsIntercept(ruleSwitch_, IMPORT_OTHER_BINARY)) {
474 return true;
475 }
476
477 if (auto res = fuzzy_match_.find("deps_gni"); res != fuzzy_match_.end()) {
478 std::string deps_str(deps);
479 for (auto res_second : res->second) {
480 if (StartWith(Trim(deps_str), res_second)) {
481 return true;
482 }
483 }
484 }
485
486 if (auto res = import_other_.find(label); res != import_other_.end()) {
487 std::string deps_str(deps);
488 auto res_second = std::find(res->second.begin(), res->second.end(), Trim(deps_str));
489 if (res_second != res->second.end()) {
490 return true;
491 }
492 }
493 *err = Err(function->function(), "Not allow import other gni.",
494 label + " not allow import other gni : " + deps);
495 return false;
496 }
497
OhosComponentChecker(const std::string & build_dir,int checkType,unsigned int ruleSwitch)498 OhosComponentChecker::OhosComponentChecker(const std::string &build_dir, int checkType, unsigned int ruleSwitch)
499 {
500 checkType_ = checkType;
501 build_dir_ = build_dir;
502 ruleSwitch_ = ruleSwitch;
503 if (checkType_ == CheckType::INTERCEPT_IGNORE_TEST || checkType_ == CheckType::INTERCEPT_ALL) {
504 LoadWhitelist(build_dir_);
505 }
506 if (checkType_ == CheckType::SCAN_ALL || checkType_ == CheckType::INTERCEPT_ALL) {
507 ignoreTest_ = false;
508 }
509 RemoveScanOutDir(build_dir_ + "/" + SCAN_RESULT_PATH);
510 }
511
GenerateScanList(const std::string & path,const std::string & subsystem,const std::string & component,const std::string & label,const std::string & deps) const512 void OhosComponentChecker::GenerateScanList(const std::string &path, const std::string &subsystem,
513 const std::string &component, const std::string &label, const std::string &deps) const
514 {
515 CreateScanOutDir(build_dir_ + "/" + SCAN_RESULT_PATH);
516 std::ofstream file;
517 file.open(build_dir_ + "/" + SCAN_RESULT_PATH + "/" + path, std::ios::app);
518 file << subsystem << " " << component << " " << label << " " << deps << "\n";
519 file.close();
520 return;
521 }
522
CheckAllDepsConfigs(const Target * target,const std::string & label,Err * err) const523 bool OhosComponentChecker::CheckAllDepsConfigs(const Target *target, const std::string &label, Err *err) const
524 {
525 if (checkType_ <= CheckType::NONE || target == nullptr || (ignoreTest_ && target->testonly())) {
526 return true;
527 }
528
529 const OhosComponent *component = target->ohos_component();
530 if (component == nullptr) {
531 return true;
532 }
533 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
534 return InterceptAllDepsConfig(target, label, err);
535 }
536 GenerateScanList("all_dependent_configs.list", component->subsystem(), component->name(), label, "");
537 return true;
538 }
539
CheckInnerApiIncludesOverRange(const Target * target,const std::string & label,const std::string & dir,Err * err) const540 bool OhosComponentChecker::CheckInnerApiIncludesOverRange(const Target *target, const std::string &label,
541 const std::string &dir, Err *err) const
542 {
543 if (checkType_ <= CheckType::NONE || target == nullptr || (ignoreTest_ && target->testonly())) {
544 return true;
545 }
546
547 const OhosComponent *component = target->ohos_component();
548 if (component == nullptr || !component->isInnerApi(label) || StartWith(label, "//third_party")) {
549 return true;
550 }
551
552 bool is_part_path = false;
553 for (const auto &path : component->modulePath()) {
554 if (dir == path || dir == path + "/") {
555 is_part_path = true;
556 break;
557 }
558 }
559 if (dir != "." && dir != "./" && dir != "../" && !is_part_path) {
560 return true;
561 }
562
563 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
564 return InterceptIncludesOverRange(target, label, dir, err);
565 }
566 GenerateScanList("includes_over_range.list", component->subsystem(), component->name(), label, dir);
567 return true;
568 }
569
CheckInnerApiPublicDepsInner(const Target * target,const std::string & label,const std::string & deps,Err * err) const570 bool OhosComponentChecker::CheckInnerApiPublicDepsInner(const Target *target, const std::string &label,
571 const std::string &deps, Err *err) const
572 {
573 if (checkType_ <= CheckType::NONE || target == nullptr || (ignoreTest_ && target->testonly())) {
574 return true;
575 }
576
577 const OhosComponent *component = target->ohos_component();
578 if (component == nullptr || !component->isInnerApi(label)) {
579 return true;
580 }
581
582 bool is_same_part = false;
583 for (const auto &path : component->modulePath()) {
584 if (StartWith(deps, path)) {
585 is_same_part = true;
586 break;
587 }
588 }
589
590 if (!is_same_part && StartWith(deps, "//")) {
591 return true;
592 }
593
594 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
595 return InterceptInnerApiPublicDepsInner(target, label, deps, err);
596 }
597 GenerateScanList("innerapi_public_deps_inner.list", component->subsystem(), component->name(), label, deps);
598 return true;
599 }
600
CheckPublicDeps(const Target * target,const std::string & label,const std::string & deps,Err * err) const601 bool OhosComponentChecker::CheckPublicDeps(const Target *target, const std::string &label,
602 const std::string &deps, Err *err) const
603 {
604 if (checkType_ <= CheckType::NONE || target == nullptr || (ignoreTest_ && target->testonly())) {
605 return true;
606 }
607
608 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
609 return InterceptPublicDeps(target, label, deps, err);
610 }
611 const OhosComponent *component = target->ohos_component();
612 GenerateScanList("public_deps.list", component == nullptr ? "" : component->subsystem(),
613 component == nullptr ? "" : component->name(), label, deps);
614 return true;
615 }
616
CheckLibDir(const Target * target,const std::string & label,const std::string & dir,Err * err) const617 bool OhosComponentChecker::CheckLibDir(const Target *target, const std::string &label,
618 const std::string &dir, Err *err) const
619 {
620 if (checkType_ <= CheckType::NONE || target == nullptr || (ignoreTest_ && target->testonly())) {
621 return true;
622 }
623
624 const OhosComponent *component = target->ohos_component();
625 if (component == nullptr) {
626 return true;
627 }
628
629 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
630 return InterceptLibDir(target, label, dir, err);
631 }
632 GenerateScanList("lib_dirs.list", component->subsystem(), component->name(), label, dir);
633 return true;
634 }
635
CheckInnerApiNotLib(const Item * item,const OhosComponent * component,const std::string & label,const std::string & deps,Err * err) const636 bool OhosComponentChecker::CheckInnerApiNotLib(const Item *item, const OhosComponent *component,
637 const std::string &label, const std::string &deps, Err *err) const
638 {
639 if (checkType_ <= CheckType::NONE || item == nullptr || item->AsTarget() == nullptr ||
640 (ignoreTest_ && item->testonly()) || component == nullptr) {
641 return true;
642 }
643
644 Target::OutputType type = item->AsTarget()->output_type();
645 if (type == Target::SHARED_LIBRARY || type == Target::STATIC_LIBRARY || type == Target::RUST_LIBRARY ||
646 type == Target::EXECUTABLE || type == Target::COPY_FILES) {
647 return true;
648 }
649
650 if (type == Target::GROUP && item->checkflag() == false) {
651 return true;
652 }
653
654 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
655 return InterceptDepsNotLib(item, label, deps, err) && InterceptInnerApiNotLib(item, deps, err);
656 }
657
658 std::string type_str(Target::GetStringForOutputType(type));
659 GenerateScanList("innerapi_not_lib.list", component->subsystem(), component->name(), deps, type_str);
660 GenerateScanList("deps_not_lib.list", component->subsystem(), component->name(), label, deps);
661 return true;
662 }
663
CheckInnerApiNotDeclare(const Item * item,const OhosComponent * component,const std::string & label,Err * err) const664 bool OhosComponentChecker::CheckInnerApiNotDeclare(const Item *item, const OhosComponent *component,
665 const std::string &label, Err *err) const
666 {
667 if (checkType_ <= CheckType::NONE || component == nullptr || item == nullptr || (ignoreTest_ && item->testonly())) {
668 return true;
669 }
670
671 if (component->isInnerApi(label)) {
672 return true;
673 }
674 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
675 return InterceptInnerApiNotDeclare(item, label, err);
676 }
677 GenerateScanList("innerapi_not_declare.list", component->subsystem(), component->name(), label, "");
678 return true;
679 }
680
CheckIncludesAbsoluteDepsOther(const Target * target,const std::string & label,const std::string & includes,Err * err) const681 bool OhosComponentChecker::CheckIncludesAbsoluteDepsOther(const Target *target, const std::string &label,
682 const std::string &includes, Err *err) const
683 {
684 if (checkType_ <= CheckType::NONE || target == nullptr || (ignoreTest_ && target->testonly())) {
685 return true;
686 }
687
688 if (includes == "//" || !StartWith(includes, "//") || StartWith(includes, "//out/")
689 || StartWith(includes, "////out/") || StartWith(includes, "//prebuilts/")) {
690 return true;
691 }
692
693 const OhosComponent *component = target->ohos_component();
694 if (component == nullptr) {
695 return true;
696 }
697
698 for(const auto &path : component->modulePath()) {
699 if (StartWith(includes, path)) {
700 return true;
701 }
702 }
703
704 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
705 return InterceptIncludesAbsoluteDepsOther(target, label, includes, err);
706 }
707 GenerateScanList("includes_absolute_deps_other.list", component->subsystem(), component->name(), label, includes);
708 return true;
709 }
710
CheckInnerApiVisibilityDenied(const Item * item,const OhosComponent * component,const std::string & label,const std::string & deps,Err * err) const711 bool OhosComponentChecker::CheckInnerApiVisibilityDenied(const Item *item, const OhosComponent *component,
712 const std::string &label, const std::string &deps, Err *err) const
713 {
714 if (checkType_ <= CheckType::NONE || component == nullptr || item == nullptr || (ignoreTest_ && item->testonly())) {
715 return true;
716 }
717
718 if (!component->isInnerApi(deps)) {
719 return true;
720 }
721 std::vector<std::string> visibility = component->getInnerApiVisibility(deps);
722 if (visibility.empty()) {
723 return true;
724 }
725
726 const OhosComponent *from_component = item->ohos_component();
727 if (from_component == nullptr) {
728 return true;
729 }
730 auto result = std::find(visibility.begin(), visibility.end(), from_component->name());
731 if (result != visibility.end()) {
732 return true;
733 }
734
735 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
736 return InterceptInnerApiVisibilityDenied(item, label, deps, err);
737 }
738 GenerateScanList("innerkit_visibility_denied.list", from_component->subsystem(), from_component->name(), label,
739 deps);
740 return true;
741 }
742
CheckTargetAbsoluteDepsOther(const Item * item,const OhosComponent * component,const std::string & label,const std::string & deps,bool is_external_deps,Err * err) const743 bool OhosComponentChecker::CheckTargetAbsoluteDepsOther(const Item *item, const OhosComponent *component,
744 const std::string &label, const std::string &deps, bool is_external_deps, Err *err) const
745 {
746 if (checkType_ <= CheckType::NONE || component == nullptr || item == nullptr || (ignoreTest_ && item->testonly())) {
747 return true;
748 }
749
750 if (is_external_deps) {
751 return true;
752 }
753
754 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
755 return InterceptTargetAbsoluteDepsOther(item, label, deps, err);
756 }
757
758 const OhosComponent *from_component = item->ohos_component();
759 if (from_component == nullptr) {
760 return true;
761 }
762 GenerateScanList("target_absolute_deps_other.list",
763 from_component->subsystem(), from_component->name(), label, deps);
764 return true;
765 }
766
CheckImportOther(const FunctionCallNode * function,const BuildSettings * build_settings,const std::string & label,const std::string & deps,Err * err) const767 bool OhosComponentChecker::CheckImportOther(const FunctionCallNode *function, const BuildSettings *build_settings,
768 const std::string &label, const std::string &deps, Err *err) const
769 {
770 if (checkType_ <= CheckType::NONE || function == nullptr || build_settings == nullptr) {
771 return true;
772 }
773 const OhosComponent *component = build_settings->GetOhosComponent(label);
774 if (component == nullptr) {
775 return true;
776 }
777 if (StartWith(deps, "//build/") || StartWith(deps, "//out/")
778 || StartWith(deps, "//prebuilts/")) {
779 return true;
780 }
781
782 for (const auto &path : component->modulePath()) {
783 if (StartWith(deps, path)) {
784 return true;
785 }
786 }
787
788 if (checkType_ >= CheckType::INTERCEPT_IGNORE_TEST) {
789 return InterceptImportOther(function, label, deps, err);
790 }
791 GenerateScanList("import_other.list", component->subsystem(), component->name(), label, deps);
792 return true;
793 }
794