Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit e222597

Browse files
authored
Ignore CRLF endings when determining the names of header guards. (#50227)
Reported by @loic-sharma. The tl;dr is it should be OK to have `\r\n` (CRLF) endings if the header guard is otherwise correct. This minor refactor (and test) discounts the existence of `\r` when determining the name of a header guard, i.e.: ```h #ifndef FLUTTER_MATAN_WHY_H_ ``` ... is now (correctly) considered a value of `FLUTTER_MATAN_WHY_H_` not `FLUTTER_MATAN_WHY_H_\r`.
1 parent f2b9921 commit e222597

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

tools/header_guard_check/lib/src/header_file.dart

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,36 @@ final class HeaderFile {
3636
);
3737
}
3838

39+
static ({
40+
int start,
41+
int end,
42+
String line,
43+
}) _getLine(SourceFile sourceFile, int index) {
44+
final int start = sourceFile.getOffset(index);
45+
int end = index == sourceFile.lines - 1
46+
? sourceFile.length
47+
: sourceFile.getOffset(index + 1) - 1;
48+
String line = sourceFile.getText(start, end);
49+
50+
// On Windows, it's common for files to have CRLF line endings, and for
51+
// developers to use git's `core.autocrlf` setting to convert them to LF
52+
// line endings.
53+
//
54+
// However, our scripts expect LF line endings, so we need to remove the
55+
// CR characters from the line endings when computing the line so that
56+
// properly formatted files are not considered malformed.
57+
if (line.isNotEmpty && sourceFile.getText(end - 1, end) == '\r') {
58+
end--;
59+
line = line.substring(0, line.length - 1);
60+
}
61+
62+
return (
63+
start: start,
64+
end: end,
65+
line: line,
66+
);
67+
}
68+
3969
/// Parses the header guard of the given [sourceFile].
4070
static HeaderGuardSpans? _parseGuard(SourceFile sourceFile) {
4171
SourceSpan? ifndefSpan;
@@ -44,11 +74,7 @@ final class HeaderFile {
4474

4575
// Iterate over the lines in the file.
4676
for (int i = 0; i < sourceFile.lines; i++) {
47-
final int start = sourceFile.getOffset(i);
48-
final int end = i == sourceFile.lines - 1
49-
? sourceFile.length
50-
: sourceFile.getOffset(i + 1) - 1;
51-
final String line = sourceFile.getText(start, end);
77+
final (:int start, :int end, :String line) = _getLine(sourceFile, i);
5278

5379
// Check if the line is a header guard directive.
5480
if (line.startsWith('#ifndef')) {
@@ -70,11 +96,7 @@ final class HeaderFile {
7096

7197
// Now iterate backwards to find the (last) #endif directive.
7298
for (int i = sourceFile.lines - 1; i > 0; i--) {
73-
final int start = sourceFile.getOffset(i);
74-
final int end = i == sourceFile.lines - 1
75-
? sourceFile.length
76-
: sourceFile.getOffset(i + 1) - 1;
77-
final String line = sourceFile.getText(start, end);
99+
final (:int start, :int end, :String line) = _getLine(sourceFile, i);
78100

79101
// Check if the line is a header guard directive.
80102
if (line.startsWith('#endif')) {
@@ -94,11 +116,7 @@ final class HeaderFile {
94116
static SourceSpan? _parsePragmaOnce(SourceFile sourceFile) {
95117
// Iterate over the lines in the file.
96118
for (int i = 0; i < sourceFile.lines; i++) {
97-
final int start = sourceFile.getOffset(i);
98-
final int end = i == sourceFile.lines - 1
99-
? sourceFile.length
100-
: sourceFile.getOffset(i + 1) - 1;
101-
final String line = sourceFile.getText(start, end);
119+
final (:int start, :int end, :String line) = _getLine(sourceFile, i);
102120

103121
// Check if the line is a header guard directive.
104122
if (line.startsWith('#pragma once')) {

tools/header_guard_check/test/header_file_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,24 @@ Future<int> main(List<String> args) async {
326326
expect(headerFile.fix(engineRoot: p.dirname(file.path)), isFalse);
327327
});
328328
});
329+
330+
test('is OK with windows-style CRLF file with a valid header guard', () {
331+
final String input = <String>[
332+
'#ifndef FLUTTER_FOO_H_',
333+
'#define FLUTTER_FOO_H_',
334+
'',
335+
'// ...',
336+
'',
337+
'#endif // FLUTTER_FOO_H_',
338+
].join('\r\n');
339+
withTestFile('foo.h', input, (io.File file) {
340+
final HeaderFile headerFile = HeaderFile.parse(file.path);
341+
expect(headerFile.pragmaOnce, isNull);
342+
expect(headerFile.guard!.ifndefValue, 'FLUTTER_FOO_H_');
343+
expect(headerFile.guard!.defineValue, 'FLUTTER_FOO_H_');
344+
expect(headerFile.guard!.endifValue, 'FLUTTER_FOO_H_');
345+
});
346+
});
329347
});
330348

331349
return 0;

0 commit comments

Comments
 (0)