[Parseable Output] Compute file extensions using full extension strings

Generation of valid JSON output for parseable output depends on being able to determine file types of inputs and outputs of compilation tasks. FileTypes.def defines multiple file kinds with multiple '.' extensions, such as '.abi.json' or '.features.json', but existing code attempted to compute file outputs only using the trailing suffix of the path after the last '.'. This led to some files not being recognized, which led to us not being able to generate valid JSON.

Resolves rdar://92961252
This commit is contained in:
Artem Chikin
2022-05-12 09:56:57 -07:00
parent eb8df860e8
commit b66d6cc9ec
2 changed files with 36 additions and 11 deletions

View File

@@ -588,6 +588,29 @@ mapFrontendInvocationToAction(const CompilerInvocation &Invocation) {
// StaticLinkJob, DynamicLinkJob
}
// TODO: Apply elsewhere in the compiler
static swift::file_types::ID computeFileTypeForPath(const StringRef Path) {
if (!llvm::sys::path::has_extension(Path))
return swift::file_types::ID::TY_INVALID;
auto Extension = llvm::sys::path::extension(Path).str();
auto FileType = file_types::lookupTypeForExtension(Extension);
if (FileType == swift::file_types::ID::TY_INVALID) {
auto PathStem = llvm::sys::path::stem(Path);
// If this path has a multiple '.' extension (e.g. .abi.json),
// then iterate over all preceeding possible extension variants.
while (llvm::sys::path::has_extension(PathStem)) {
auto NextExtension = llvm::sys::path::extension(PathStem);
Extension = NextExtension.str() + Extension;
FileType = file_types::lookupTypeForExtension(Extension);
if (FileType != swift::file_types::ID::TY_INVALID)
break;
}
}
return FileType;
}
static DetailedTaskDescription
constructDetailedTaskDescription(const CompilerInvocation &Invocation,
ArrayRef<InputFile> PrimaryInputs,
@@ -612,20 +635,15 @@ constructDetailedTaskDescription(const CompilerInvocation &Invocation,
for (const auto &input : PrimaryInputs) {
// Main outputs
auto OutputFile = input.outputFilename();
if (!OutputFile.empty()) {
Outputs.push_back(OutputPair(file_types::lookupTypeForExtension(
llvm::sys::path::extension(OutputFile)),
OutputFile));
}
if (!OutputFile.empty())
Outputs.push_back(OutputPair(computeFileTypeForPath(OutputFile), OutputFile));
// Supplementary outputs
const auto &primarySpecificFiles = input.getPrimarySpecificPaths();
const auto &supplementaryOutputPaths =
primarySpecificFiles.SupplementaryOutputs;
supplementaryOutputPaths.forEachSetOutput([&](const std::string &output) {
Outputs.push_back(OutputPair(file_types::lookupTypeForExtension(
llvm::sys::path::extension(output)),
output));
Outputs.push_back(OutputPair(computeFileTypeForPath(output), output));
});
}
return DetailedTaskDescription{Executable, Arguments, CommandLine, Inputs,