[Format] Fix detection of languages when reading from stdin (#79051)

The code cleanup in #74794 accidentally broke detection of languages by
reading file content from stdin, e.g. via `clang-format -dump-config - <
/path/to/filename`.

This PR adds unit and integration tests to reproduce the issue and adds
a fix.

Fixes: #79023
This commit is contained in:
Ben Hamilton (Ben Gertzfield)
2024-01-23 13:32:41 -07:00
committed by GitHub
parent eabddf22e2
commit d813af73f7
3 changed files with 26 additions and 11 deletions

View File

@@ -0,0 +1,5 @@
// RUN: clang-format -dump-config - < %s | FileCheck %s
// CHECK: Language: ObjC
@interface Foo
@end

View File

@@ -547,18 +547,20 @@ static void PrintVersion(raw_ostream &OS) {
// Dump the configuration.
static int dumpConfig(bool IsSTDIN) {
std::unique_ptr<llvm::MemoryBuffer> Code;
// We can't read the code to detect the language if there's no file name.
if (!IsSTDIN) {
// Read in the code in case the filename alone isn't enough to detect the
// language.
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
MemoryBuffer::getFileOrSTDIN(FileNames[0]);
if (std::error_code EC = CodeOrErr.getError()) {
llvm::errs() << EC.message() << "\n";
return 1;
}
Code = std::move(CodeOrErr.get());
// `FileNames` must have at least "-" in it even if no file was specified.
assert(!FileNames.empty());
// Read in the code in case the filename alone isn't enough to detect the
// language.
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
MemoryBuffer::getFileOrSTDIN(FileNames[0]);
if (std::error_code EC = CodeOrErr.getError()) {
llvm::errs() << EC.message() << "\n";
return 1;
}
Code = std::move(CodeOrErr.get());
llvm::Expected<clang::format::FormatStyle> FormatStyle =
clang::format::getStyle(Style, IsSTDIN ? AssumeFileName : FileNames[0],
FallbackStyle, Code ? Code->getBuffer() : "");

View File

@@ -31,6 +31,14 @@ protected:
_verifyIncompleteFormat(__FILE__, __LINE__, __VA_ARGS__)
#define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__)
TEST(FormatTestObjCStyle, DetectsObjCInStdin) {
auto Style = getStyle("LLVM", "<stdin>", "none",
"@interface\n"
"- (id)init;");
ASSERT_TRUE((bool)Style);
EXPECT_EQ(FormatStyle::LK_ObjC, Style->Language);
}
TEST(FormatTestObjCStyle, DetectsObjCInHeaders) {
auto Style = getStyle("LLVM", "a.h", "none",
"@interface\n"