Commit bbdee91b authored by Nikolai Kosjar's avatar Nikolai Kosjar

CppTools: Handle erroneous statements in FindMethodDefinitionInsertPoint

...at end of file.

Change-Id: Ife8142cd9cf3c5e4be2594b7cc635e5ab7b9e946
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent 3eaf0440
......@@ -155,6 +155,7 @@ private slots:
void test_quickfix_InsertDefFromDecl_afterClass();
void test_quickfix_InsertDefFromDecl_headerSource_basic1();
void test_quickfix_InsertDefFromDecl_headerSource_basic2();
void test_quickfix_InsertDefFromDecl_headerSource_basic3();
void test_quickfix_InsertDefFromDecl_headerSource_namespace1();
void test_quickfix_InsertDefFromDecl_headerSource_namespace2();
void test_quickfix_InsertDefFromDecl_freeFunction();
......@@ -165,6 +166,9 @@ private slots:
void test_quickfix_InsertDefFromDecl_ignoreSurroundingGeneratedDeclarations();
void test_quickfix_InsertDefFromDecl_respectWsInOperatorNames1();
void test_quickfix_InsertDefFromDecl_respectWsInOperatorNames2();
void test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile1();
void test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile2();
void test_quickfix_InsertDefFromDecl_erroneousStatementAtEndOfFile();
void test_quickfix_InsertDeclFromDef();
......
......@@ -902,6 +902,7 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_afterClass()
}
/// Check from header file: If there is a source file, insert the definition in the source file.
/// Case: Source file is empty.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic1()
{
QList<TestDocumentPtr> testFiles;
......@@ -934,7 +935,8 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic1()
data.run(&factory);
}
/// Check from source file: Insert in source file, not header file.
/// Check from header file: If there is a source file, insert the definition in the source file.
/// Case: Source file is not empty.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic2()
{
QList<TestDocumentPtr> testFiles;
......@@ -942,6 +944,44 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic2()
QByteArray original;
QByteArray expected;
// Header File
original = "void f()@;\n";
expected = original + "\n";
testFiles << TestDocument::create(original, expected, QLatin1String("file.h"));
// Source File
original =
"#include \"file.h\"\n"
"\n"
"int x;\n"
;
expected =
"#include \"file.h\"\n"
"\n"
"int x;\n"
"\n"
"\n"
"void f()\n"
"{\n"
"\n"
"}\n"
"\n"
;
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
InsertDefFromDecl factory;
TestCase data(testFiles);
data.run(&factory);
}
/// Check from source file: Insert in source file, not header file.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_headerSource_basic3()
{
QList<TestDocumentPtr> testFiles;
QByteArray original;
QByteArray expected;
// Empty Header File
testFiles << TestDocument::create("", "\n", QLatin1String("file.h"));
......@@ -1270,6 +1310,131 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_respectWsInOperatorNames2(
data.run(&factory);
}
/// Check if a function like macro use is not separated by the function to insert
/// Case: Macro preceded by preproceesor directives and declaration.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile1()
{
QList<TestDocumentPtr> testFiles;
QByteArray original;
QByteArray expected;
// Header File
original = "void f()@;\n";
expected = original + "\n";
testFiles << TestDocument::create(original, expected, QLatin1String("file.h"));
// Source File
original =
"#include \"file.h\"\n"
"#define MACRO(X) X x;\n"
"int lala;\n"
"\n"
"MACRO(int)\n"
;
expected =
"#include \"file.h\"\n"
"#define MACRO(X) X x;\n"
"int lala;\n"
"\n"
"\n"
"\n"
"void f()\n"
"{\n"
"\n"
"}\n"
"\n"
"MACRO(int)\n"
"\n"
;
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
InsertDefFromDecl factory;
TestCase data(testFiles);
data.run(&factory);
}
/// Check if a function like macro use is not separated by the function to insert
/// Case: Marco preceded only by preprocessor directives.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_macroUsesAtEndOfFile2()
{
QList<TestDocumentPtr> testFiles;
QByteArray original;
QByteArray expected;
// Header File
original = "void f()@;\n";
expected = original + "\n";
testFiles << TestDocument::create(original, expected, QLatin1String("file.h"));
// Source File
original =
"#include \"file.h\"\n"
"#define MACRO(X) X x;\n"
"\n"
"MACRO(int)\n"
;
expected =
"#include \"file.h\"\n"
"#define MACRO(X) X x;\n"
"\n"
"\n"
"\n"
"void f()\n"
"{\n"
"\n"
"}\n"
"\n"
"MACRO(int)\n"
"\n"
;
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
InsertDefFromDecl factory;
TestCase data(testFiles);
data.run(&factory);
}
/// Check if insertion happens before syntactically erroneous statements at end of file.
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_erroneousStatementAtEndOfFile()
{
QList<TestDocumentPtr> testFiles;
QByteArray original;
QByteArray expected;
// Header File
original = "void f()@;\n";
expected = original + "\n";
testFiles << TestDocument::create(original, expected, QLatin1String("file.h"));
// Source File
original =
"#include \"file.h\"\n"
"\n"
"MissingSemicolon(int)\n"
;
expected =
"#include \"file.h\"\n"
"\n"
"\n"
"\n"
"void f()\n"
"{\n"
"\n"
"}\n"
"\n"
"MissingSemicolon(int)\n"
"\n"
;
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
InsertDefFromDecl factory;
TestCase data(testFiles);
data.run(&factory);
}
// Function for one of InsertDeclDef section cases
void insertToSectionDeclFromDef(const QByteArray &section, int sectionIndex)
{
......
......@@ -356,7 +356,7 @@ class FindMethodDefinitionInsertPoint : protected ASTVisitor
{
QList<const Identifier *> _namespaceNames;
int _currentDepth;
HighestValue<int, int> _bestToken;
HighestValue<int, unsigned> _bestToken;
public:
FindMethodDefinitionInsertPoint(TranslationUnit *translationUnit)
......@@ -366,10 +366,10 @@ public:
void operator()(Symbol *decl, unsigned *line, unsigned *column)
{
// default to end of file
_bestToken.maybeSet(-1, translationUnit()->ast()->lastToken());
if (translationUnit()->ast()->lastToken() >= 2) {
const unsigned lastToken = translationUnit()->ast()->lastToken();
_bestToken.maybeSet(-1, lastToken);
if (lastToken >= 2) {
QList<const Name *> names = LookupContext::fullyQualifiedName(decl);
foreach (const Name *name, names) {
const Identifier *id = name->asNameId();
......@@ -381,7 +381,11 @@ public:
accept(translationUnit()->ast());
}
translationUnit()->getTokenEndPosition(_bestToken.get(), line, column);
if (lastToken == _bestToken.get()) // No matching namespace found
translationUnit()->getTokenStartPosition(lastToken, line, column);
else // Insert at end of matching namespace
translationUnit()->getTokenEndPosition(_bestToken.get(), line, column);
}
protected:
......
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