[Dependency Scanning] Add serialization of optional imports to the JSON output

And to the corresponding graph data structure the output gets generated from
This commit is contained in:
Artem Chikin
2025-08-15 14:49:43 -07:00
parent bc30953c15
commit b14cbbb039
5 changed files with 57 additions and 35 deletions

View File

@@ -65,6 +65,9 @@ struct swiftscan_dependency_info_s {
/// The list of source import infos.
swiftscan_import_info_set_t *imports;
/// The list of source optional import infos.
swiftscan_import_info_set_t *optional_imports;
/// Specific details of a particular kind of module.
swiftscan_module_details_t details;
};

View File

@@ -41,7 +41,7 @@ using llvm::BCVBR;
const unsigned char MODULE_DEPENDENCY_CACHE_FORMAT_SIGNATURE[] = {'I', 'M', 'D','C'};
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MAJOR = 10;
/// Increment this on every change.
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 3;
const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 4;
/// Various identifiers in this format will rely on having their strings mapped
/// using this ID.

View File

@@ -228,9 +228,13 @@ void writeLinkLibraries(llvm::raw_ostream &out,
void writeImportInfos(llvm::raw_ostream &out,
const swiftscan_import_info_set_t *imports,
unsigned indentLevel, bool trailingComma) {
bool optional, unsigned indentLevel,
bool trailingComma) {
out.indent(indentLevel * 2);
out << "\"imports\": ";
if (optional)
out << "\"optionalImports\": ";
else
out << "\"imports\": ";
out << "[\n";
for (size_t i = 0; i < imports->count; ++i) {
@@ -441,7 +445,9 @@ void writeJSON(llvm::raw_ostream &out,
/*trailingComma=*/true);
writeLinkLibraries(out, moduleInfo.link_libraries,
3, /*trailingComma=*/true);
writeImportInfos(out, moduleInfo.imports,
writeImportInfos(out, moduleInfo.imports, /*optional*/ false,
3, /*trailingComma=*/true);
writeImportInfos(out, moduleInfo.optional_imports, /*optional*/ true,
3, /*trailingComma=*/true);
}
// Swift and Clang-specific details.

View File

@@ -922,37 +922,44 @@ static swiftscan_dependency_graph_t generateFullDependencyGraph(
}
moduleInfo->link_libraries = linkLibrarySet;
// Create source import infos set for this module
auto imports = moduleDependencyInfo.getModuleImports();
swiftscan_import_info_set_t *importInfoSet =
new swiftscan_import_info_set_t;
importInfoSet->count = imports.size();
importInfoSet->imports = new swiftscan_import_info_t[importInfoSet->count];
for (size_t i = 0; i < imports.size(); ++i) {
const auto &ii = imports[i];
swiftscan_import_info_s *iInfo = new swiftscan_import_info_s;
iInfo->import_identifier = create_clone(ii.importIdentifier.c_str());
iInfo->access_level =
static_cast<swiftscan_access_level_t>(ii.accessLevel);
auto createImportSetInfo = [&](ArrayRef<ScannerImportStatementInfo> imports)
-> swiftscan_import_info_set_t * {
swiftscan_import_info_set_t *importInfoSet =
new swiftscan_import_info_set_t;
importInfoSet->count = imports.size();
importInfoSet->imports =
new swiftscan_import_info_t[importInfoSet->count];
for (size_t i = 0; i < imports.size(); ++i) {
const auto &ii = imports[i];
swiftscan_import_info_s *iInfo = new swiftscan_import_info_s;
iInfo->import_identifier = create_clone(ii.importIdentifier.c_str());
iInfo->access_level =
static_cast<swiftscan_access_level_t>(ii.accessLevel);
const auto &sourceLocations = ii.importLocations;
swiftscan_source_location_set_t *sourceLocSet =
new swiftscan_source_location_set_t;
sourceLocSet->count = sourceLocations.size();
sourceLocSet->source_locations =
new swiftscan_source_location_t[sourceLocSet->count];
for (size_t j = 0; j < sourceLocations.size(); ++j) {
const auto &sl = sourceLocations[j];
swiftscan_source_location_s *slInfo = new swiftscan_source_location_s;
slInfo->buffer_identifier = create_clone(sl.bufferIdentifier.c_str());
slInfo->line_number = sl.lineNumber;
slInfo->column_number = sl.columnNumber;
sourceLocSet->source_locations[j] = slInfo;
const auto &sourceLocations = ii.importLocations;
swiftscan_source_location_set_t *sourceLocSet =
new swiftscan_source_location_set_t;
sourceLocSet->count = sourceLocations.size();
sourceLocSet->source_locations =
new swiftscan_source_location_t[sourceLocSet->count];
for (size_t j = 0; j < sourceLocations.size(); ++j) {
const auto &sl = sourceLocations[j];
swiftscan_source_location_s *slInfo = new swiftscan_source_location_s;
slInfo->buffer_identifier = create_clone(sl.bufferIdentifier.c_str());
slInfo->line_number = sl.lineNumber;
slInfo->column_number = sl.columnNumber;
sourceLocSet->source_locations[j] = slInfo;
}
iInfo->source_locations = sourceLocSet;
importInfoSet->imports[i] = iInfo;
}
iInfo->source_locations = sourceLocSet;
importInfoSet->imports[i] = iInfo;
}
moduleInfo->imports = importInfoSet;
return importInfoSet;
};
// Create source import infos set for this module
moduleInfo->imports =
createImportSetInfo(moduleDependencyInfo.getModuleImports());
moduleInfo->optional_imports =
createImportSetInfo(moduleDependencyInfo.getOptionalModuleImports());
}
swiftscan_dependency_graph_t result = new swiftscan_dependency_graph_s;

View File

@@ -40,10 +40,16 @@
// CHECK-IMPORTS-NEXT: "importLocations": [
// CHECK-IMPORTS-NEXT: {
// CHECK-IMPORTS-NEXT: "bufferIdentifier": "{{.*}}serialized_imports.swift",
// CHECK-IMPORTS-NEXT: "linuNumber": 49,
// CHECK-IMPORTS-NEXT: "linuNumber": 54,
// CHECK-IMPORTS-NEXT: "columnNumber": 8
// CHECK-IMPORTS-NEXT: }
// CHECK-IMPORTS-NEXT: ]
// CHECK-IMPORTS: "optionalImports": [
// CHECK-IMPORTS-NEXT: {
// CHECK-IMPORTS-NEXT: "identifier": "E_Private",
// CHECK-IMPORTS-NEXT: "accessLevel": "public"
// CHECK-IMPORTS-NEXT: }
// CHECK-IMPORTS-NEXT: ],
import E
import E.Private