1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "parser/module_parser.h"
10 #include <queue>
11 #include "parser/parser.h"
12 #include "util/logger.h"
13
14 namespace OHOS {
15 namespace HDI {
16 const char* ModuleParser::TAG = "ModuleParser";
17
Parse()18 AutoPtr<ASTModule> ModuleParser::Parse()
19 {
20 if (!ParserDependencies()) {
21 return nullptr;
22 }
23
24 if (!CompileFiles()) {
25 return nullptr;
26 }
27
28 return module_;
29 }
30
ParserDependencies()31 bool ModuleParser::ParserDependencies()
32 {
33 if (option_.GetSourceFiles().size() == 1) {
34 if (!ParserAllImports(option_.GetSourceFiles()[0])) {
35 Logger::E(TAG, "Parsing all idl file failed.");
36 return false;
37 }
38 } else {
39 if (!ParserAllidlFile(option_.GetSourceFiles())) {
40 Logger::E(TAG, "Parsing all given idl file failed.");
41 return false;
42 }
43 }
44
45 if (!CheckCircularReference()) {
46 Logger::E(TAG, "has circle reference.");
47 return false;
48 }
49
50 return true;
51 }
52
CompileFiles()53 bool ModuleParser::CompileFiles()
54 {
55 std::unique_ptr<Parser> parserPtr = std::make_unique<Parser>(option_, module_);
56
57 for (const auto& filePath : compileFiles_) {
58 if (!parserPtr->Parse(filePath)) {
59 Logger::E(TAG, "parse %s failed", filePath.string());
60 return false;
61 }
62 }
63
64 return true;
65 }
66
ParserAllImports(const String & rootFilePath)67 bool ModuleParser::ParserAllImports(const String& rootFilePath)
68 {
69 std::unique_ptr<Parser> parserPtr = std::make_unique<Parser>(option_);
70 std::shared_ptr<FileDetail> fileInfo = nullptr;
71
72 if (!parserPtr->Parse(rootFilePath, fileInfo)) {
73 return false;
74 }
75
76 if (fileInfo == nullptr) {
77 return false;
78 }
79
80 sourceFiles_[fileInfo->GetFullName()] = fileInfo;
81 return ParserAllImportsRecursion(fileInfo);
82 }
83
ParserAllImportsRecursion(const std::shared_ptr<FileDetail> & fileInfo)84 bool ModuleParser::ParserAllImportsRecursion(const std::shared_ptr<FileDetail>& fileInfo)
85 {
86 for (const auto& importName : fileInfo->GetImports()) {
87 if (sourceFiles_.find(importName) != sourceFiles_.end()) {
88 continue;
89 }
90
91 String filePath = FileDetail::ImportsToPath(importName);
92
93 std::unique_ptr<Parser> parserPtr = std::make_unique<Parser>(option_);
94 std::shared_ptr<FileDetail> file = nullptr;
95 if (!parserPtr->Parse(filePath, file)) {
96 Logger::E(TAG, "Parsing %s failed.", filePath.string());
97 return false;
98 }
99
100 if (file == nullptr) {
101 Logger::E(TAG, "Parsing %s failed, generator filedetail is nullptr.", filePath.string());
102 return false;
103 }
104
105 sourceFiles_[file->GetFullName()] = file;
106
107 if (!ParserAllImportsRecursion(file)) {
108 Logger::E(TAG, "Parsing %s file's import failed.", file->GetFilePath().string());
109 return false;
110 }
111 }
112
113 return true;
114 }
115
ParserAllidlFile(const std::vector<String> & idlSourceFile)116 bool ModuleParser::ParserAllidlFile(const std::vector<String>& idlSourceFile)
117 {
118 std::unique_ptr<Parser> parserPtr = std::make_unique<Parser>(option_);
119
120 for (const auto& idlSourceFile : idlSourceFile) {
121 std::shared_ptr<FileDetail> fileInfo = nullptr;
122 if (!parserPtr->Parse(idlSourceFile, fileInfo)) {
123 return false;
124 }
125
126 if (fileInfo == nullptr) {
127 return false;
128 }
129
130 sourceFiles_[fileInfo->GetFullName()] = fileInfo;
131 }
132
133 return true;
134 }
135
CheckCircularReference()136 bool ModuleParser::CheckCircularReference()
137 {
138 std::queue<std::shared_ptr<FileDetail>> fileQueue;
139 for (const auto& filePair : sourceFiles_) {
140 std::shared_ptr<FileDetail> fileNode = filePair.second;
141 if (fileNode->GetImportSize() == 0) {
142 fileQueue.push(fileNode);
143 }
144 }
145
146 compileFiles_.clear();
147 while (!fileQueue.empty()) {
148 std::shared_ptr<FileDetail> importFile = fileQueue.front();
149 fileQueue.pop();
150 compileFiles_.push_back(importFile->GetFilePath());
151
152 for (const auto& filePair : sourceFiles_) {
153 std::shared_ptr<FileDetail> fileNode = filePair.second;
154 if (fileNode->GetImportSize() > 0) {
155 fileNode->DelImport(importFile->GetFullName());
156 if (fileNode->GetImportSize() == 0) {
157 fileQueue.push(fileNode);
158 }
159 }
160 }
161 }
162
163 if (compileFiles_.size() < sourceFiles_.size()) {
164 return false;
165 }
166
167 return true;
168 }
169 } // namespace HDI
170 } // namespace OHOS