Commit f2631ad0 authored by Erik Verbruggen's avatar Erik Verbruggen Committed by Erik Verbruggen

C++: do not strip trailing newlines in the preprocessor output.

Doing so resulted in an incorrect position for the EOF token when the
preprocessed output would be parsed. That in turn leads to incorrect
insertion positions for refactoring actions.

This is especially true when a file contains only preprocessor
directives: the EOF token would point to line 1 column 1, which is
usually not the place where code should be inserted.

Change-Id: I7d359aa7a6c04bc52c8b873fd49ad6afc3a77319
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 271a96b1
......@@ -1332,19 +1332,6 @@ void Preprocessor::synchronizeOutputLines(const PPToken &tk, bool forceLine)
adjustForCommentOrStringNewlines(&m_env->currentLine, tk);
}
void Preprocessor::removeTrailingOutputLines()
{
QByteArray &buffer = currentOutputBuffer();
int i = buffer.size() - 1;
while (i >= 0 && buffer.at(i) == '\n')
--i;
const int mightChop = buffer.size() - i - 1;
if (mightChop > 1) {
// Keep one new line at end.
buffer.chop(mightChop - 1);
}
}
std::size_t Preprocessor::computeDistance(const Preprocessor::PPToken &tk, bool forceTillLine)
{
// Find previous non-space character or line begin.
......@@ -1450,8 +1437,6 @@ void Preprocessor::preprocess(const QString &fileName, const QByteArray &source,
} while (tk.isNot(T_EOF_SYMBOL));
removeTrailingOutputLines();
if (includeGuardMacroName) {
if (m_state.m_includeGuardState == State::IncludeGuardState_AfterDefine
|| m_state.m_includeGuardState == State::IncludeGuardState_AfterEndif)
......
......@@ -237,7 +237,6 @@ private:
void maybeStartOutputLine();
void generateOutputLineMarker(unsigned lineno);
void synchronizeOutputLines(const PPToken &tk, bool forceLine = false);
void removeTrailingOutputLines();
void enforceSpacing(const PPToken &tk, bool forceSpacing = false);
static std::size_t computeDistance(const PPToken &tk, bool forceTillLine = false);
......
......@@ -842,17 +842,17 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_namespace2()
// Source File
original =
"#include \"file.h\"\n"
"using namespace N;\n"
"\n"
;
"#include \"file.h\"\n"
"using namespace N;\n"
;
expected = original +
"\n"
"Foo::Foo()\n"
"{\n\n"
"}\n"
"\n"
;
"\n"
"\n"
"Foo::Foo()\n"
"{\n\n"
"}\n"
"\n"
;
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
InsertDefFromDecl factory;
......
......@@ -10,3 +10,8 @@ void thisFunctionIsEnabled();
void thisFunctionIsEnabled2();
# 31 "data/macro-test.cpp"
void thisFunctionIsEnabled3();
......@@ -353,6 +353,8 @@ private slots:
void skip_unknown_directives_data();
void include_guard();
void include_guard_data();
void empty_trailing_lines();
void empty_trailing_lines_data();
};
// Remove all #... lines, and 'simplify' string, to allow easily comparing the result
......@@ -1507,7 +1509,13 @@ void tst_Preprocessor::skip_unknown_directives_data()
"# 10 \"file.cpp\"\n"
"# ()\n"
"#\n";
expected = "# 1 \"<stdin>\"\n";
expected =
"# 1 \"<stdin>\"\n"
"\n"
"\n"
"\n"
"\n"
;
QTest::newRow("case 1") << original << expected;
}
......@@ -1593,6 +1601,74 @@ void tst_Preprocessor::include_guard_data()
;
}
void tst_Preprocessor::empty_trailing_lines()
{
compare_input_output();
}
void tst_Preprocessor::empty_trailing_lines_data()
{
// Test if the number of lines at the end of a file is correct. This is important to make the
// EOF token for the end up at the correct line.
QTest::addColumn<QByteArray>("input");
QTest::addColumn<QByteArray>("output");
QByteArray original;
QByteArray expected;
original =
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
;
expected = "# 1 \"<stdin>\"\n" + original;
QTest::newRow("9 empty lines") << original << expected;
original =
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
;
expected =
"# 1 \"<stdin>\"\n"
"# 11 \"<stdin>\"\n"
;
QTest::newRow("11 empty lines") << original << expected;
original =
"#include <something>\n"
;
expected =
"# 1 \"<stdin>\"\n"
"\n"
;
QTest::newRow("1 include") << original << expected;
original =
"#include <something>\n"
"\n"
;
expected =
"# 1 \"<stdin>\"\n"
"\n"
"\n"
;
QTest::newRow("1 empty line with 1 include") << original << expected;
}
void tst_Preprocessor::compare_input_output(bool keepComments)
{
QFETCH(QByteArray, input);
......@@ -1602,7 +1678,7 @@ void tst_Preprocessor::compare_input_output(bool keepComments)
Preprocessor preprocess(0, &env);
preprocess.setKeepComments(keepComments);
QByteArray prep = preprocess.run(QLatin1String("<stdin>"), input);
QCOMPARE(output, prep);
QCOMPARE(prep.constData(), output.constData());
}
QTEST_APPLESS_MAIN(tst_Preprocessor)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment