diff --git a/language/backgroundparser/parsejob.cpp b/language/backgroundparser/parsejob.cpp --- a/language/backgroundparser/parsejob.cpp +++ b/language/backgroundparser/parsejob.cpp @@ -42,6 +42,7 @@ #include "duchain/parsingenvironment.h" #include +#include #include #include #include @@ -314,6 +315,9 @@ } d->contents.contents = file.readAll(); ///@todo Convert from local encoding to utf-8 if they don't match + + // This is consistent with KTextEditor::Document::text() as used for already-open files. + normalizeLineEndings(d->contents.contents); d->contents.modification = KDevelop::ModificationRevision(lastModified); file.close(); diff --git a/util/kdevstringhandler.h b/util/kdevstringhandler.h --- a/util/kdevstringhandler.h +++ b/util/kdevstringhandler.h @@ -23,6 +23,7 @@ #include "utilexport.h" class QString; +class QByteArray; class QChar; class QStringList; class QVariant; @@ -66,6 +67,10 @@ */ KDEVPLATFORMUTIL_EXPORT QString stripAnsiSequences(const QString& str); + /** + * Replace all occurrences of '\r' or '\r\n' in @p text with '\n'. + */ + KDEVPLATFORMUTIL_EXPORT void normalizeLineEndings(QByteArray& text); } #endif // KDEVPLATFORM_KDEVSTRINGHANDLER_H diff --git a/util/kdevstringhandler.cpp b/util/kdevstringhandler.cpp --- a/util/kdevstringhandler.cpp +++ b/util/kdevstringhandler.cpp @@ -66,6 +66,7 @@ #include #include +#include #include #include #include @@ -229,3 +230,16 @@ } return result; } + +void KDevelop::normalizeLineEndings(QByteArray& text) +{ + for (int i = 0, s = text.size(); i < s; ++i) { + if (text[i] != '\r') { + continue; + } else if (i + 1 < s && text[i + 1] == '\n') { + text.remove(i, 1); + } else { + text[i] = '\n'; + } + } +} diff --git a/util/tests/test_stringhandler.h b/util/tests/test_stringhandler.h --- a/util/tests/test_stringhandler.h +++ b/util/tests/test_stringhandler.h @@ -34,6 +34,9 @@ void testStripAnsiSequences(); void testStripAnsiSequences_data(); + + void testNormalizeLineEndings(); + void testNormalizeLineEndings_data(); }; #endif // TESTSTRINGHANDLER_H diff --git a/util/tests/test_stringhandler.cpp b/util/tests/test_stringhandler.cpp --- a/util/tests/test_stringhandler.cpp +++ b/util/tests/test_stringhandler.cpp @@ -72,4 +72,32 @@ QTest::newRow("simple") << QStringLiteral("foo bar:") << "foo bar:"; -} \ No newline at end of file +} + +void TestStringHandler::testNormalizeLineEndings() +{ + QFETCH(QByteArray, text); + QFETCH(QByteArray, expectedOutput); + + normalizeLineEndings(text); + QCOMPARE(text, expectedOutput); +} + +void TestStringHandler::testNormalizeLineEndings_data() +{ + QTest::addColumn("text"); + QTest::addColumn("expectedOutput"); + + QTest::newRow("trivial") + << QByteArray("foo\nbar\n") + << QByteArray("foo\nbar\n"); + QTest::newRow("dos") + << QByteArray("foo\r\nbar\r\n") + << QByteArray("foo\nbar\n"); + QTest::newRow("macos_classic") + << QByteArray("foo\rbar\r") + << QByteArray("foo\nbar\n"); + QTest::newRow("mess") + << QByteArray("\r\n\n\r\r\r\n\r") + << QByteArray("\n\n\n\n\n\n"); +}