Clang: Workaround dot detection for arrow correction

...by explicitly checking for the dot in the source.

Task-number: QTCREATORBUG-15654
Change-Id: I4172e88a7fbb3015ef391daf13ded1f0002aab9c
Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
This commit is contained in:
Nikolai Kosjar
2016-01-28 18:43:14 +01:00
parent da27ea4d42
commit 57877cc14d
7 changed files with 73 additions and 1 deletions

View File

@@ -68,7 +68,7 @@ CodeCompletions CodeCompleter::complete(uint line, uint column)
translationUnit.cxUnsavedFiles(), translationUnit.cxUnsavedFiles(),
translationUnit.unsavedFilesCount()); translationUnit.unsavedFilesCount());
if (results.hasNoResultsForDotCompletion()) if (results.hasNoResultsForDotCompletion() && hasDotAt(line, column - 1))
results = completeWithArrowInsteadOfDot(line, column); results = completeWithArrowInsteadOfDot(line, column);
return toCodeCompletions(results); return toCodeCompletions(results);
@@ -95,6 +95,14 @@ ClangCodeCompleteResults CodeCompleter::complete(uint line,
options); options);
} }
bool CodeCompleter::hasDotAt(uint line, uint column) const
{
const UnsavedFile &unsavedFile = translationUnit.unsavedFile();
const SourceLocation location = translationUnit.sourceLocationAtWithoutReparsing(line, column);
return unsavedFile.hasCharacterAt(location.offset(), '.');
}
ClangCodeCompleteResults CodeCompleter::completeWithArrowInsteadOfDot(uint line, uint column) ClangCodeCompleteResults CodeCompleter::completeWithArrowInsteadOfDot(uint line, uint column)
{ {
ClangCodeCompleteResults results; ClangCodeCompleteResults results;

View File

@@ -46,6 +46,9 @@ public:
CompletionCorrection neededCorrection() const; CompletionCorrection neededCorrection() const;
public: // for tests
bool hasDotAt(uint line, uint column) const;
private: private:
ClangCodeCompleteResults complete(uint line, ClangCodeCompleteResults complete(uint line,
uint column, uint column,

View File

@@ -65,6 +65,14 @@ const char *UnsavedFile::filePath() const
return cxUnsavedFile.Filename; return cxUnsavedFile.Filename;
} }
bool UnsavedFile::hasCharacterAt(uint position, char character) const
{
if (position < cxUnsavedFile.Length)
return cxUnsavedFile.Contents[position] == character;
return false;
}
bool UnsavedFile::replaceAt(uint position, uint length, const Utf8String &replacement) bool UnsavedFile::replaceAt(uint position, uint length, const Utf8String &replacement)
{ {
if (position < cxUnsavedFile.Length) { if (position < cxUnsavedFile.Length) {

View File

@@ -51,6 +51,7 @@ public:
const char *filePath() const; const char *filePath() const;
bool hasCharacterAt(uint position, char character) const;
bool replaceAt(uint position, uint length, const Utf8String &replacement); bool replaceAt(uint position, uint length, const Utf8String &replacement);
CXUnsavedFile *data(); CXUnsavedFile *data();

View File

@@ -148,6 +148,12 @@ protected:
readFileContent(QStringLiteral("/complete_withNoDotArrowCorrectionForOnlyDot.cpp")), readFileContent(QStringLiteral("/complete_withNoDotArrowCorrectionForOnlyDot.cpp")),
true true
}; };
ClangBackEnd::FileContainer noDotArrowCorrectionForColonColonFileContainer{
Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForColonColon.cpp"),
projectPart.projectPartId(),
readFileContent(QStringLiteral("/complete_withNoDotArrowCorrectionForColonColon.cpp")),
true
};
}; };
Utf8String CodeCompleter::readFileContent(const QString &fileName) Utf8String CodeCompleter::readFileContent(const QString &fileName)
@@ -295,6 +301,22 @@ TEST_F(CodeCompleter, ArrowCompletion)
ClangBackEnd::CompletionCorrection::NoCorrection); ClangBackEnd::CompletionCorrection::NoCorrection);
} }
TEST_F(CodeCompleter, HasDotAt)
{
auto myCompleter = setupCompleter(dotArrowCorrectionForPointerFileContainer);
ASSERT_TRUE(myCompleter.hasDotAt(5, 8));
}
TEST_F(CodeCompleter, HasNoDotAtDueToMissingUnsavedFile)
{
const ClangBackEnd::FileContainer fileContainer = dotArrowCorrectionForPointerFileContainer;
translationUnits.create({fileContainer});
ClangBackEnd::CodeCompleter myCompleter(translationUnits.translationUnit(fileContainer));
ASSERT_FALSE(myCompleter.hasDotAt(5, 8));
}
TEST_F(CodeCompleter, DotToArrowCompletionForPointer) TEST_F(CodeCompleter, DotToArrowCompletionForPointer)
{ {
auto myCompleter = setupCompleter(dotArrowCorrectionForPointerFileContainer); auto myCompleter = setupCompleter(dotArrowCorrectionForPointerFileContainer);
@@ -374,6 +396,14 @@ TEST_F(CodeCompleter, NoDotArrowCorrectionForOnlyDot)
ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection); ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection);
} }
TEST_F(CodeCompleter, NoDotArrowCorrectionForColonColon)
{
auto myCompleter = setupCompleter(noDotArrowCorrectionForColonColonFileContainer);
const ClangBackEnd::CodeCompletions completions = myCompleter.complete(1, 7);
ASSERT_THAT(myCompleter.neededCorrection(), ClangBackEnd::CompletionCorrection::NoCorrection);
}
ClangBackEnd::CodeCompleter CodeCompleter::setupCompleter( ClangBackEnd::CodeCompleter CodeCompleter::setupCompleter(
const ClangBackEnd::FileContainer &fileContainer) const ClangBackEnd::FileContainer &fileContainer)
{ {

View File

@@ -150,4 +150,25 @@ TEST_F(UnsavedFile, Replace)
ASSERT_THAT(unsavedFile, IsUnsavedFile(filePath, expectedContent, expectedContent.byteSize())); ASSERT_THAT(unsavedFile, IsUnsavedFile(filePath, expectedContent, expectedContent.byteSize()));
} }
TEST_F(UnsavedFile, HasNoCharacterForTooBigOffset)
{
::UnsavedFile unsavedFile(filePath, fileContent);
ASSERT_FALSE(unsavedFile.hasCharacterAt(100, 'x'));
}
TEST_F(UnsavedFile, HasNoCharacterForWrongOffset)
{
::UnsavedFile unsavedFile(filePath, fileContent);
ASSERT_FALSE(unsavedFile.hasCharacterAt(0, 'x'));
}
TEST_F(UnsavedFile, HasCharacterForCorrectOffset)
{
::UnsavedFile unsavedFile(filePath, fileContent);
ASSERT_TRUE(unsavedFile.hasCharacterAt(0, 'c'));
}
} // anonymous namespace } // anonymous namespace