Skip to content

Commit

Permalink
[Format] Fix detection of languages when reading from stdin (#79051)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bhamiltoncx authored Jan 23, 2024
1 parent eabddf2 commit d813af7
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
5 changes: 5 additions & 0 deletions clang/test/Format/dump-config-objc-stdin.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// RUN: clang-format -dump-config - < %s | FileCheck %s

// CHECK: Language: ObjC
@interface Foo
@end
24 changes: 13 additions & 11 deletions clang/tools/clang-format/ClangFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() : "");
Expand Down
8 changes: 8 additions & 0 deletions clang/unittests/Format/FormatTestObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ class FormatTestObjC : public FormatTestBase {
_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"
Expand Down

0 comments on commit d813af7

Please sign in to comment.