mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Caching] Identify input type from filename correctly
When loading input from CAS, `swift-frontend` relies on the input file name to determine the type to look from CAS entry. In the case where file extension is `.private.swiftinterface`, swift mis-identify that as `.swiftinterface` file and look up the wrong input file. Add a new file type lookup function that can figure out the type from the full filename. Also add few diagnostics during the CAS lookup for the input file to error out immediately, rather than rely on the lookup failure later.
This commit is contained in:
@@ -504,6 +504,10 @@ ERROR(error_cas, none, "CAS error encountered: %0", (StringRef))
|
||||
ERROR(error_failed_cached_diag, none, "failed to serialize cached diagnostics: %0", (StringRef))
|
||||
ERROR(error_replay_cached_diag, none, "failed to replay cached diagnostics: %0", (StringRef))
|
||||
|
||||
ERROR(error_load_input_from_cas, none, "failed to load input '%0' from CAS", (StringRef))
|
||||
|
||||
ERROR(error_wrong_input_num_for_input_file_key, none, "-input-file-key only support one input file", ())
|
||||
|
||||
// Dependency Verifier Diagnostics
|
||||
ERROR(missing_member_dependency,none,
|
||||
"expected "
|
||||
|
||||
@@ -39,6 +39,11 @@ StringRef getExtension(ID Id);
|
||||
/// the invalid type \c TY_INVALID.
|
||||
ID lookupTypeForExtension(StringRef Ext);
|
||||
|
||||
/// Lookup the type to use for the file name \p Filename.
|
||||
/// If the filename is empty or type cannot be recognoized, return
|
||||
/// the invalid type \c TY_INVALID.
|
||||
ID lookupTypeFromFilename(StringRef Filename);
|
||||
|
||||
/// Lookup the type to use for the name \p Name.
|
||||
ID lookupTypeForName(StringRef Name);
|
||||
|
||||
|
||||
@@ -56,6 +56,29 @@ ID file_types::lookupTypeForExtension(StringRef Ext) {
|
||||
.Default(TY_INVALID);
|
||||
}
|
||||
|
||||
// Compute the file type from filename. This handles the lookup for extensions
|
||||
// with multiple dots, like `.private.swiftinterface` correctly.
|
||||
ID file_types::lookupTypeFromFilename(StringRef Filename) {
|
||||
StringRef MaybeExt = Filename;
|
||||
// Search from leftmost `.`, return the first match or till all dots are
|
||||
// consumed.
|
||||
size_t Pos = MaybeExt.find_first_of('.');
|
||||
while(Pos != StringRef::npos) {
|
||||
MaybeExt = MaybeExt.substr(Pos);
|
||||
// If size is 1, that means only `.` is left, return invalid.
|
||||
if (MaybeExt.size() == 1)
|
||||
return TY_INVALID;
|
||||
ID Type = lookupTypeForExtension(MaybeExt);
|
||||
if (Type != TY_INVALID)
|
||||
return Type;
|
||||
// Drop `.` and keep looking.
|
||||
MaybeExt = MaybeExt.drop_front();
|
||||
Pos = MaybeExt.find_first_of('.');
|
||||
}
|
||||
|
||||
return TY_INVALID;
|
||||
}
|
||||
|
||||
ID file_types::lookupTypeForName(StringRef Name) {
|
||||
return llvm::StringSwitch<file_types::ID>(Name)
|
||||
#define TYPE(NAME, ID, EXTENSION, FLAGS) \
|
||||
|
||||
@@ -585,15 +585,27 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
|
||||
ClangOpts.BridgingHeader))
|
||||
MemFS->addFile(Invocation.getClangImporterOptions().BridgingHeader, 0,
|
||||
std::move(loadedBuffer));
|
||||
else
|
||||
Diagnostics.diagnose(
|
||||
SourceLoc(), diag::error_load_input_from_cas,
|
||||
Invocation.getClangImporterOptions().BridgingHeader);
|
||||
}
|
||||
if (!Opts.InputFileKey.empty()) {
|
||||
auto InputPath = Opts.InputsAndOutputs.getFilenameOfFirstInput();
|
||||
auto Type = file_types::lookupTypeForExtension(
|
||||
llvm::sys::path::extension(InputPath));
|
||||
if (auto loadedBuffer = loadCachedCompileResultFromCacheKey(
|
||||
getObjectStore(), getActionCache(), Diagnostics,
|
||||
Opts.InputFileKey, Type, InputPath))
|
||||
MemFS->addFile(InputPath, 0, std::move(loadedBuffer));
|
||||
if (Opts.InputsAndOutputs.getAllInputs().size() != 1)
|
||||
Diagnostics.diagnose(SourceLoc(),
|
||||
diag::error_wrong_input_num_for_input_file_key);
|
||||
else {
|
||||
auto InputPath = Opts.InputsAndOutputs.getFilenameOfFirstInput();
|
||||
auto Type = file_types::lookupTypeFromFilename(
|
||||
llvm::sys::path::filename(InputPath));
|
||||
if (auto loadedBuffer = loadCachedCompileResultFromCacheKey(
|
||||
getObjectStore(), getActionCache(), Diagnostics,
|
||||
Opts.InputFileKey, Type, InputPath))
|
||||
MemFS->addFile(InputPath, 0, std::move(loadedBuffer));
|
||||
else
|
||||
Diagnostics.diagnose(SourceLoc(), diag::error_load_input_from_cas,
|
||||
InputPath);
|
||||
}
|
||||
}
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
|
||||
new llvm::vfs::OverlayFileSystem(SourceMgr.getFileSystem());
|
||||
|
||||
@@ -17,6 +17,7 @@ add_swift_unittest(SwiftBasicTests
|
||||
EncodedSequenceTest.cpp
|
||||
ExponentialGrowthAppendingBinaryByteStreamTests.cpp
|
||||
FileSystemTest.cpp
|
||||
FileTypes.cpp
|
||||
FixedBitSetTest.cpp
|
||||
FrozenMultiMapTest.cpp
|
||||
ImmutablePointerSetTest.cpp
|
||||
|
||||
44
unittests/Basic/FileTypes.cpp
Normal file
44
unittests/Basic/FileTypes.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
//===--- FileTypes.cpp - for swift/Basic/FileTypes.h ----------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Basic/FileTypes.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
using namespace swift;
|
||||
using namespace swift::file_types;
|
||||
|
||||
static const std::vector<std::pair<std::string, ID>> ExtIDs = {
|
||||
#define TYPE(NAME, ID, EXTENSION, FLAGS) {EXTENSION, TY_##ID},
|
||||
#include "swift/Basic/FileTypes.def"
|
||||
};
|
||||
|
||||
TEST(FileSystem, lookupTypeFromFilename) {
|
||||
for (auto &Entry: ExtIDs) {
|
||||
// no extension, skip.
|
||||
if (Entry.first.empty())
|
||||
continue;
|
||||
// raw-sil and raw-sib do not have unique extension.
|
||||
if (Entry.second == TY_RawSIL || Entry.second == TY_RawSIB)
|
||||
continue;
|
||||
|
||||
std::string Filename = "Myfile." + Entry.first;
|
||||
ID Type = lookupTypeFromFilename(Filename);
|
||||
ASSERT_EQ(getTypeName(Type), getTypeName(Entry.second));
|
||||
}
|
||||
|
||||
ASSERT_EQ(lookupTypeFromFilename(""), TY_INVALID);
|
||||
ASSERT_EQ(lookupTypeFromFilename("."), TY_INVALID);
|
||||
ASSERT_EQ(lookupTypeFromFilename(".."), TY_INVALID);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user