diff options
author | Nikolai Kosjar <nikolai.kosjar@theqtcompany.com> | 2016-01-28 18:43:14 +0100 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@theqtcompany.com> | 2016-02-01 12:20:58 +0000 |
commit | 57877cc14de97eb5bf491c89e2c856e54859ed57 (patch) | |
tree | 0b6df9cfb0a2777689b676e486be94b4527e0aad | |
parent | da27ea4d42864472f102943e89a0cd82f9ffe230 (diff) | |
download | qt-creator-57877cc14de97eb5bf491c89e2c856e54859ed57.tar.gz |
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>
7 files changed, 73 insertions, 1 deletions
diff --git a/src/tools/clangbackend/ipcsource/codecompleter.cpp b/src/tools/clangbackend/ipcsource/codecompleter.cpp index a139e02edf..691686d047 100644 --- a/src/tools/clangbackend/ipcsource/codecompleter.cpp +++ b/src/tools/clangbackend/ipcsource/codecompleter.cpp @@ -68,7 +68,7 @@ CodeCompletions CodeCompleter::complete(uint line, uint column) translationUnit.cxUnsavedFiles(), translationUnit.unsavedFilesCount()); - if (results.hasNoResultsForDotCompletion()) + if (results.hasNoResultsForDotCompletion() && hasDotAt(line, column - 1)) results = completeWithArrowInsteadOfDot(line, column); return toCodeCompletions(results); @@ -95,6 +95,14 @@ ClangCodeCompleteResults CodeCompleter::complete(uint line, 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 results; diff --git a/src/tools/clangbackend/ipcsource/codecompleter.h b/src/tools/clangbackend/ipcsource/codecompleter.h index ceb594df63..99749414f4 100644 --- a/src/tools/clangbackend/ipcsource/codecompleter.h +++ b/src/tools/clangbackend/ipcsource/codecompleter.h @@ -46,6 +46,9 @@ public: CompletionCorrection neededCorrection() const; +public: // for tests + bool hasDotAt(uint line, uint column) const; + private: ClangCodeCompleteResults complete(uint line, uint column, diff --git a/src/tools/clangbackend/ipcsource/unsavedfile.cpp b/src/tools/clangbackend/ipcsource/unsavedfile.cpp index 1db76d22cf..b1c87e6025 100644 --- a/src/tools/clangbackend/ipcsource/unsavedfile.cpp +++ b/src/tools/clangbackend/ipcsource/unsavedfile.cpp @@ -65,6 +65,14 @@ const char *UnsavedFile::filePath() const 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) { if (position < cxUnsavedFile.Length) { diff --git a/src/tools/clangbackend/ipcsource/unsavedfile.h b/src/tools/clangbackend/ipcsource/unsavedfile.h index fe738bb262..17e09667dc 100644 --- a/src/tools/clangbackend/ipcsource/unsavedfile.h +++ b/src/tools/clangbackend/ipcsource/unsavedfile.h @@ -51,6 +51,7 @@ public: const char *filePath() const; + bool hasCharacterAt(uint position, char character) const; bool replaceAt(uint position, uint length, const Utf8String &replacement); CXUnsavedFile *data(); diff --git a/tests/unit/unittest/codecompletiontest.cpp b/tests/unit/unittest/codecompletiontest.cpp index d7a6cba623..3b2eff7d82 100644 --- a/tests/unit/unittest/codecompletiontest.cpp +++ b/tests/unit/unittest/codecompletiontest.cpp @@ -148,6 +148,12 @@ protected: readFileContent(QStringLiteral("/complete_withNoDotArrowCorrectionForOnlyDot.cpp")), true }; + ClangBackEnd::FileContainer noDotArrowCorrectionForColonColonFileContainer{ + Utf8StringLiteral(TESTDATA_DIR"/complete_withNoDotArrowCorrectionForColonColon.cpp"), + projectPart.projectPartId(), + readFileContent(QStringLiteral("/complete_withNoDotArrowCorrectionForColonColon.cpp")), + true + }; }; Utf8String CodeCompleter::readFileContent(const QString &fileName) @@ -295,6 +301,22 @@ TEST_F(CodeCompleter, ArrowCompletion) 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) { auto myCompleter = setupCompleter(dotArrowCorrectionForPointerFileContainer); @@ -374,6 +396,14 @@ TEST_F(CodeCompleter, NoDotArrowCorrectionForOnlyDot) 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( const ClangBackEnd::FileContainer &fileContainer) { diff --git a/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForColonColon.cpp b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForColonColon.cpp new file mode 100644 index 0000000000..62af4343c1 --- /dev/null +++ b/tests/unit/unittest/data/complete_withNoDotArrowCorrectionForColonColon.cpp @@ -0,0 +1 @@ +Blah:: diff --git a/tests/unit/unittest/unsavedfiletest.cpp b/tests/unit/unittest/unsavedfiletest.cpp index aa54550f2d..80f22ded35 100644 --- a/tests/unit/unittest/unsavedfiletest.cpp +++ b/tests/unit/unittest/unsavedfiletest.cpp @@ -150,4 +150,25 @@ TEST_F(UnsavedFile, Replace) 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 |