From 8a9ba2c473b3e8aceeb113e20fb92a0a8ba06067 Mon Sep 17 00:00:00 2001 From: Matan Lurey Date: Wed, 31 Jan 2024 17:31:45 -0800 Subject: [PATCH] Ignore CRLF endings when determining the names of header guards. --- .../lib/src/header_file.dart | 48 +++++++++++++------ .../test/header_file_test.dart | 18 +++++++ 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/tools/header_guard_check/lib/src/header_file.dart b/tools/header_guard_check/lib/src/header_file.dart index 9ab0b6318b015..494d6421f9b14 100644 --- a/tools/header_guard_check/lib/src/header_file.dart +++ b/tools/header_guard_check/lib/src/header_file.dart @@ -36,6 +36,36 @@ final class HeaderFile { ); } + static ({ + int start, + int end, + String line, + }) _getLine(SourceFile sourceFile, int index) { + final int start = sourceFile.getOffset(index); + int end = index == sourceFile.lines - 1 + ? sourceFile.length + : sourceFile.getOffset(index + 1) - 1; + String line = sourceFile.getText(start, end); + + // On Windows, it's common for files to have CRLF line endings, and for + // developers to use git's `core.autocrlf` setting to convert them to LF + // line endings. + // + // However, our scripts expect LF line endings, so we need to remove the + // CR characters from the line endings when computing the line so that + // properly formatted files are not considered malformed. + if (line.isNotEmpty && sourceFile.getText(end - 1, end) == '\r') { + end--; + line = line.substring(0, line.length - 1); + } + + return ( + start: start, + end: end, + line: line, + ); + } + /// Parses the header guard of the given [sourceFile]. static HeaderGuardSpans? _parseGuard(SourceFile sourceFile) { SourceSpan? ifndefSpan; @@ -44,11 +74,7 @@ final class HeaderFile { // Iterate over the lines in the file. for (int i = 0; i < sourceFile.lines; i++) { - final int start = sourceFile.getOffset(i); - final int end = i == sourceFile.lines - 1 - ? sourceFile.length - : sourceFile.getOffset(i + 1) - 1; - final String line = sourceFile.getText(start, end); + final (:int start, :int end, :String line) = _getLine(sourceFile, i); // Check if the line is a header guard directive. if (line.startsWith('#ifndef')) { @@ -70,11 +96,7 @@ final class HeaderFile { // Now iterate backwards to find the (last) #endif directive. for (int i = sourceFile.lines - 1; i > 0; i--) { - final int start = sourceFile.getOffset(i); - final int end = i == sourceFile.lines - 1 - ? sourceFile.length - : sourceFile.getOffset(i + 1) - 1; - final String line = sourceFile.getText(start, end); + final (:int start, :int end, :String line) = _getLine(sourceFile, i); // Check if the line is a header guard directive. if (line.startsWith('#endif')) { @@ -94,11 +116,7 @@ final class HeaderFile { static SourceSpan? _parsePragmaOnce(SourceFile sourceFile) { // Iterate over the lines in the file. for (int i = 0; i < sourceFile.lines; i++) { - final int start = sourceFile.getOffset(i); - final int end = i == sourceFile.lines - 1 - ? sourceFile.length - : sourceFile.getOffset(i + 1) - 1; - final String line = sourceFile.getText(start, end); + final (:int start, :int end, :String line) = _getLine(sourceFile, i); // Check if the line is a header guard directive. if (line.startsWith('#pragma once')) { diff --git a/tools/header_guard_check/test/header_file_test.dart b/tools/header_guard_check/test/header_file_test.dart index 4342ba3ed40b5..a61d0edaca0d7 100644 --- a/tools/header_guard_check/test/header_file_test.dart +++ b/tools/header_guard_check/test/header_file_test.dart @@ -326,6 +326,24 @@ Future main(List args) async { expect(headerFile.fix(engineRoot: p.dirname(file.path)), isFalse); }); }); + + test('is OK with windows-style CRLF file with a valid header guard', () { + final String input = [ + '#ifndef FLUTTER_FOO_H_', + '#define FLUTTER_FOO_H_', + '', + '// ...', + '', + '#endif // FLUTTER_FOO_H_', + ].join('\r\n'); + withTestFile('foo.h', input, (io.File file) { + final HeaderFile headerFile = HeaderFile.parse(file.path); + expect(headerFile.pragmaOnce, isNull); + expect(headerFile.guard!.ifndefValue, 'FLUTTER_FOO_H_'); + expect(headerFile.guard!.defineValue, 'FLUTTER_FOO_H_'); + expect(headerFile.guard!.endifValue, 'FLUTTER_FOO_H_'); + }); + }); }); return 0;