-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang-format] clang-format-ignore: Add support for double asterisk patterns #110560
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,11 +49,29 @@ bool matchFilePath(StringRef Pattern, StringRef FilePath) { | |
| return false; | ||
| break; | ||
| case '*': { | ||
| while (++I < EOP && Pattern[I] == '*') { // Skip consecutive stars. | ||
| if (I + 1 < EOP && Pattern[I + 1] == '*') { | ||
| // Handle '**' pattern | ||
| while (++I < EOP && Pattern[I] == '*') { // Skip consecutive stars. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds like a |
||
| } | ||
| if (I == EOP) | ||
| return true; // '**' at the end matches everything | ||
| if (Pattern[I] == Separator) { | ||
| // Try to match the rest of the pattern without consuming the | ||
| // separator for the case where we want to match "zero" directories | ||
| // e.g. "a/**/b" matches "a/b" | ||
| if (matchFilePath(Pattern.substr(I + 1), FilePath.substr(J))) | ||
| return true; | ||
| } | ||
| while (J < End) { | ||
| if (matchFilePath(Pattern.substr(I), FilePath.substr(J))) | ||
| return true; | ||
| ++J; | ||
| } | ||
| return false; | ||
| } | ||
| const auto K = FilePath.find(Separator, J); // Index of next `Separator`. | ||
| const bool NoMoreSeparatorsInFilePath = K == StringRef::npos; | ||
| if (I == EOP) // `Pattern` ends with a star. | ||
| if (++I == EOP) // `Pattern` ends with a star. | ||
| return NoMoreSeparatorsInFilePath; | ||
| // `Pattern` ends with a lone backslash. | ||
| if (Pattern[I] == '\\' && ++I == EOP) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -164,6 +164,40 @@ TEST_F(MatchFilePathTest, Path) { | |
| EXPECT_FALSE(match("foo\\", R"(foo*\)")); | ||
| } | ||
|
|
||
| TEST_F(MatchFilePathTest, DoubleAsterisk) { | ||
| EXPECT_TRUE(match("a/b/c/d.cpp", "**b**")); | ||
| EXPECT_TRUE(match("a/b/c/d.cpp", "**/b/**")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "**d_*")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "**/d_*")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "**d_**")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "**/d_**")); | ||
|
|
||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "**/b/c/**")); | ||
|
|
||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "a/**/b/c/d_e.cpp")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "a/**/c/d_e.cpp")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "a/**/b/**/d_e.cpp")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "**/b/**/d_e.cpp")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "a/**/**/b/**")); | ||
|
|
||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "**/d")); | ||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "**/b/d")); | ||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "**/b/d/**")); | ||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "**/b/c/")); | ||
|
|
||
| // Multiple consecutive asterisks are treated as ** | ||
| EXPECT_TRUE(match("a/b/c/d.cpp", "***b****")); | ||
| EXPECT_TRUE(match("a/b/c/d.cpp", "****/b/***")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "***d_**")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "****/d_*")); | ||
| EXPECT_TRUE(match("a/b/c/d_e.cpp", "***/b/c/*****")); | ||
|
|
||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "*****/d")); | ||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "***/b/d")); | ||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "*****/b/d/***")); | ||
| EXPECT_FALSE(match("a/b/c/d_e.cpp", "***/b/c")); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should there be some tests with repetition?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we are doing this an saying "Its like .gitignore" should we support
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand what you are asking.
I am only indicating that the I do not think the current implementation could easily support theese glob patterns the same way .gitignore does. @owenca may understand better and have an opinion.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When I added .clang-format-ignore, I chose a POSIX glob-like model and intentionally stayed clear of the .gitignore model, which is, IMO, confusing and overcomplicated. I prefer to not add
Yes, the current behavior is to check the patterns in the .clang-format-ignore file one pattern at a time until a match is found.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This came up as I have been working on adding support for clang-format within AMD's PAL repository and found clang-format-ignore to be extremely limiting. There are 2 key reasons I am adding this feature:
These two cases came up in the PAL repo in the following manner:
The current way to ignore these kinds of patterns is something like this: Which can be simplified into
How do we gauge how much of a demand there is for this feature?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
How is it extremely limited? Just because it doesn't support
We have
I was conscious of this use case, but you can do something like
See #52975 (comment). If we were to add
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
PAL has not used clang-format at all, my contributions have been an effort to support the PAL formatting style so we can start to use the tool.
I was not aware of
Like you said, this is not ideal as it relies on anyone adding/moving files that may need to be ignored to regenerate the clang-format-ignore file.
Are you seeing a gap in the unit tests I have? I think I have these cases covered but can add more specific unit tests if you have an example. |
||
| } | ||
|
|
||
| } // namespace | ||
| } // namespace format | ||
| } // namespace clang | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always end in full stop.