@@ -49,7 +49,8 @@ class ModuleDependencyScanner {
49
49
50
50
// / Scanning the single file specified by \param FilePath.
51
51
std::optional<ModuleDependencyInfo>
52
- scan (PathRef FilePath, const ProjectModules::CommandMangler &Mangler);
52
+ scan (PathRef FilePath, const ProjectModules::CommandMangler &Mangler,
53
+ ProjectModulesCache *Cache);
53
54
54
55
// / Scanning every source file in the current project to get the
55
56
// / <module-name> to <module-unit-source> map.
@@ -58,7 +59,8 @@ class ModuleDependencyScanner {
58
59
// / a global module dependency scanner to monitor every file. Or we
59
60
// / can simply require the build systems (or even the end users)
60
61
// / to provide the map.
61
- void globalScan (const ProjectModules::CommandMangler &Mangler);
62
+ void globalScan (const ProjectModules::CommandMangler &Mangler,
63
+ ProjectModulesCache &Cache);
62
64
63
65
// / Get the source file from the module name. Note that the language
64
66
// / guarantees all the module names are unique in a valid program.
@@ -68,6 +70,12 @@ class ModuleDependencyScanner {
68
70
// / declaring the same module.
69
71
PathRef getSourceForModuleName (llvm::StringRef ModuleName) const ;
70
72
73
+ // / Validate if source file \c Source declare a module with \c ModuleName.
74
+ // / If yes, return the source file path. Otherwise, return std::nullopt.
75
+ std::optional<PathRef>
76
+ validateSourceForModuleName (PathRef Source, llvm::StringRef ModuleName,
77
+ const ProjectModules::CommandMangler &Mangler);
78
+
71
79
// / Return the direct required modules. Indirect required modules are not
72
80
// / included.
73
81
std::vector<std::string>
@@ -83,15 +91,14 @@ class ModuleDependencyScanner {
83
91
84
92
clang::tooling::dependencies::DependencyScanningService Service;
85
93
86
- // TODO: Add a scanning cache.
87
-
88
94
// Map module name to source file path.
89
95
llvm::StringMap<std::string> ModuleNameToSource;
90
96
};
91
97
92
98
std::optional<ModuleDependencyScanner::ModuleDependencyInfo>
93
99
ModuleDependencyScanner::scan (PathRef FilePath,
94
- const ProjectModules::CommandMangler &Mangler) {
100
+ const ProjectModules::CommandMangler &Mangler,
101
+ ProjectModulesCache *Cache) {
95
102
auto Candidates = CDB->getCompileCommands (FilePath);
96
103
if (Candidates.empty ())
97
104
return std::nullopt;
@@ -124,6 +131,9 @@ ModuleDependencyScanner::scan(PathRef FilePath,
124
131
if (ScanningResult->Provides ) {
125
132
ModuleNameToSource[ScanningResult->Provides ->ModuleName ] = FilePath;
126
133
Result.ModuleName = ScanningResult->Provides ->ModuleName ;
134
+
135
+ if (Cache)
136
+ Cache->setEntry (FilePath, ScanningResult->Provides ->ModuleName );
127
137
}
128
138
129
139
for (auto &Required : ScanningResult->Requires )
@@ -133,9 +143,9 @@ ModuleDependencyScanner::scan(PathRef FilePath,
133
143
}
134
144
135
145
void ModuleDependencyScanner::globalScan (
136
- const ProjectModules::CommandMangler &Mangler) {
146
+ const ProjectModules::CommandMangler &Mangler, ProjectModulesCache &Cache ) {
137
147
for (auto &File : CDB->getAllFiles ())
138
- scan (File, Mangler);
148
+ scan (File, Mangler, &Cache );
139
149
140
150
GlobalScanned = true ;
141
151
}
@@ -155,12 +165,28 @@ PathRef ModuleDependencyScanner::getSourceForModuleName(
155
165
156
166
std::vector<std::string> ModuleDependencyScanner::getRequiredModules (
157
167
PathRef File, const ProjectModules::CommandMangler &Mangler) {
158
- auto ScanningResult = scan (File, Mangler);
168
+ auto ScanningResult = scan (File, Mangler, /* Cache= */ nullptr );
159
169
if (!ScanningResult)
160
170
return {};
161
171
162
172
return ScanningResult->RequiredModules ;
163
173
}
174
+
175
+ std::optional<PathRef> ModuleDependencyScanner::validateSourceForModuleName (
176
+ PathRef Source, llvm::StringRef ModuleName,
177
+ const ProjectModules::CommandMangler &Mangler) {
178
+ auto ScanningResult = scan (Source, Mangler, /* Cache=*/ nullptr );
179
+ if (!ScanningResult)
180
+ return std::nullopt;
181
+
182
+ // If the name matches, return the source file path from ModuleNameToSource
183
+ // cache instead of the input. Since the lifetime of the input may not be long
184
+ // enough.
185
+ if (ScanningResult->ModuleName == ModuleName)
186
+ return ModuleNameToSource[ModuleName];
187
+
188
+ return std::nullopt;
189
+ }
164
190
} // namespace
165
191
166
192
// / TODO: The existing `ScanningAllProjectModules` is not efficient. See the
@@ -190,9 +216,18 @@ class ScanningAllProjectModules : public ProjectModules {
190
216
// / RequiredSourceFile is not used intentionally. See the comments of
191
217
// / ModuleDependencyScanner for detail.
192
218
PathRef
193
- getSourceForModuleName (llvm::StringRef ModuleName,
219
+ getSourceForModuleName (ProjectModulesCache &Cache, llvm::StringRef ModuleName,
194
220
PathRef RequiredSourceFile = PathRef()) override {
195
- Scanner.globalScan (Mangler);
221
+ if (auto Source =
222
+ Cache.getSourceForModuleName (ModuleName, RequiredSourceFile)) {
223
+ if (std::optional<PathRef> Path =
224
+ Scanner.validateSourceForModuleName (*Source, ModuleName, Mangler))
225
+ return *Path;
226
+
227
+ Cache.clearEntry (ModuleName, RequiredSourceFile);
228
+ }
229
+
230
+ Scanner.globalScan (Mangler, Cache);
196
231
return Scanner.getSourceForModuleName (ModuleName);
197
232
}
198
233
0 commit comments