forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.0' into 4.1
Conflicts: src/plugins/projectexplorer/runconfiguration.h tests/unit/unittest/unittest.pro Change-Id: I3d327b1198df2a7e9268916af9624ce5d21195df
This commit is contained in:
@@ -153,13 +153,16 @@ public:
|
|||||||
|
|
||||||
m_floatButton = new DockWidgetTitleButton(this);
|
m_floatButton = new DockWidgetTitleButton(this);
|
||||||
m_floatButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q));
|
m_floatButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q));
|
||||||
m_floatButton->setAccessibleName(QDockWidget::tr("Float"));
|
|
||||||
m_floatButton->setAccessibleDescription(QDockWidget::tr("Undocks and re-attaches the dock widget"));
|
|
||||||
|
|
||||||
m_closeButton = new DockWidgetTitleButton(this);
|
m_closeButton = new DockWidgetTitleButton(this);
|
||||||
m_closeButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q));
|
m_closeButton->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q));
|
||||||
|
|
||||||
|
#ifndef QT_NO_ACCESSIBILITY
|
||||||
|
m_floatButton->setAccessibleName(QDockWidget::tr("Float"));
|
||||||
|
m_floatButton->setAccessibleDescription(QDockWidget::tr("Undocks and re-attaches the dock widget"));
|
||||||
m_closeButton->setAccessibleName(QDockWidget::tr("Close"));
|
m_closeButton->setAccessibleName(QDockWidget::tr("Close"));
|
||||||
m_closeButton->setAccessibleDescription(QDockWidget::tr("Closes the dock widget"));
|
m_closeButton->setAccessibleDescription(QDockWidget::tr("Closes the dock widget"));
|
||||||
|
#endif
|
||||||
|
|
||||||
setActive(false);
|
setActive(false);
|
||||||
|
|
||||||
|
@@ -613,7 +613,7 @@ void ClangCompletionAssistProcessor::handleAvailableCompletions(
|
|||||||
QTC_CHECK(m_completions.isEmpty());
|
QTC_CHECK(m_completions.isEmpty());
|
||||||
|
|
||||||
m_completions = toAssistProposalItems(completions);
|
m_completions = toAssistProposalItems(completions);
|
||||||
if (m_addSnippets)
|
if (m_addSnippets && !m_completions.isEmpty())
|
||||||
addSnippets();
|
addSnippets();
|
||||||
|
|
||||||
setAsyncProposalAvailable(createProposal(neededCorrection));
|
setAsyncProposalAvailable(createProposal(neededCorrection));
|
||||||
|
@@ -932,18 +932,28 @@ void ClangCodeCompletionTest::testCompleteConstructorAndFallbackToGlobalCompleti
|
|||||||
QVERIFY(!hasSnippet(t.proposal, "class"));
|
QVERIFY(!hasSnippet(t.proposal, "class"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Explicitly Inserting The Dot
|
||||||
|
// ----------------------------
|
||||||
|
// Inserting the dot for is important since it will send the editor
|
||||||
|
// content to the backend and thus generate an unsaved file on the backend
|
||||||
|
// side. The unsaved file enables us to do the dot to arrow correction.
|
||||||
|
|
||||||
void ClangCodeCompletionTest::testCompleteWithDotToArrowCorrection()
|
void ClangCodeCompletionTest::testCompleteWithDotToArrowCorrection()
|
||||||
{
|
{
|
||||||
// Inserting the dot for this test is important since it will send the editor
|
|
||||||
// content to the backend and thus generate an unsaved file on the backend
|
|
||||||
// side. The unsaved file enables us to do the dot to arrow correction.
|
|
||||||
|
|
||||||
ProjectLessCompletionTest t("dotToArrowCorrection.cpp",
|
ProjectLessCompletionTest t("dotToArrowCorrection.cpp",
|
||||||
QStringLiteral("."));
|
QStringLiteral(".")); // See above "Explicitly Inserting The Dot"
|
||||||
|
|
||||||
QVERIFY(hasItem(t.proposal, "member"));
|
QVERIFY(hasItem(t.proposal, "member"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangCodeCompletionTest::testDontCompleteWithDotToArrowCorrectionForFloats()
|
||||||
|
{
|
||||||
|
ProjectLessCompletionTest t("noDotToArrowCorrectionForFloats.cpp",
|
||||||
|
QStringLiteral(".")); // See above "Explicitly Inserting The Dot"
|
||||||
|
|
||||||
|
QCOMPARE(t.proposal->size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
void ClangCodeCompletionTest::testCompleteProjectDependingCode()
|
void ClangCodeCompletionTest::testCompleteProjectDependingCode()
|
||||||
{
|
{
|
||||||
const TestDocument testDocument("completionWithProject.cpp");
|
const TestDocument testDocument("completionWithProject.cpp");
|
||||||
|
@@ -48,6 +48,7 @@ private slots:
|
|||||||
void testCompleteConstructorAndFallbackToGlobalCompletion();
|
void testCompleteConstructorAndFallbackToGlobalCompletion();
|
||||||
|
|
||||||
void testCompleteWithDotToArrowCorrection();
|
void testCompleteWithDotToArrowCorrection();
|
||||||
|
void testDontCompleteWithDotToArrowCorrectionForFloats();
|
||||||
|
|
||||||
void testCompleteProjectDependingCode();
|
void testCompleteProjectDependingCode();
|
||||||
void testCompleteProjectDependingCodeAfterChangingProject();
|
void testCompleteProjectDependingCodeAfterChangingProject();
|
||||||
|
@@ -22,5 +22,6 @@
|
|||||||
<file>objc_messages_3.mm</file>
|
<file>objc_messages_3.mm</file>
|
||||||
<file>preprocessorKeywordsCompletion.cpp</file>
|
<file>preprocessorKeywordsCompletion.cpp</file>
|
||||||
<file>dotToArrowCorrection.cpp</file>
|
<file>dotToArrowCorrection.cpp</file>
|
||||||
|
<file>noDotToArrowCorrectionForFloats.cpp</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
void f()
|
||||||
|
{
|
||||||
|
0 /* COMPLETE HERE */
|
||||||
|
}
|
@@ -173,6 +173,8 @@ class PROJECTEXPLORER_EXPORT Runnable
|
|||||||
|
|
||||||
bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const override
|
bool canReUseOutputPane(const std::unique_ptr<Concept> &other) const override
|
||||||
{
|
{
|
||||||
|
if (!other.get())
|
||||||
|
return false;
|
||||||
if (other->typeId() != typeId())
|
if (other->typeId() != typeId())
|
||||||
return false;
|
return false;
|
||||||
auto that = static_cast<const Model<T> *>(other.get());
|
auto that = static_cast<const Model<T> *>(other.get());
|
||||||
|
@@ -68,8 +68,7 @@ CodeCompletions CodeCompleter::complete(uint line, uint column)
|
|||||||
translationUnit.cxUnsavedFiles(),
|
translationUnit.cxUnsavedFiles(),
|
||||||
translationUnit.unsavedFilesCount());
|
translationUnit.unsavedFilesCount());
|
||||||
|
|
||||||
if (results.hasNoResultsForDotCompletion() && hasDotAt(line, column - 1))
|
tryDotArrowCorrectionIfNoResults(results, line, column);
|
||||||
results = completeWithArrowInsteadOfDot(line, column);
|
|
||||||
|
|
||||||
return toCodeCompletions(results);
|
return toCodeCompletions(results);
|
||||||
}
|
}
|
||||||
@@ -93,13 +92,6 @@ ClangCodeCompleteResults CodeCompleter::complete(uint line,
|
|||||||
defaultOptions());
|
defaultOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CodeCompleter::hasDotAt(uint line, uint column) const
|
|
||||||
{
|
|
||||||
const UnsavedFile &unsavedFile = translationUnit.unsavedFile();
|
|
||||||
|
|
||||||
return unsavedFile.hasCharacterAt(line, column, '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
uint CodeCompleter::defaultOptions() const
|
uint CodeCompleter::defaultOptions() const
|
||||||
{
|
{
|
||||||
uint options = CXCodeComplete_IncludeMacros
|
uint options = CXCodeComplete_IncludeMacros
|
||||||
@@ -111,12 +103,25 @@ uint CodeCompleter::defaultOptions() const
|
|||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangCodeCompleteResults CodeCompleter::completeWithArrowInsteadOfDot(uint line, uint column)
|
void CodeCompleter::tryDotArrowCorrectionIfNoResults(ClangCodeCompleteResults &results,
|
||||||
|
uint line,
|
||||||
|
uint column)
|
||||||
|
{
|
||||||
|
if (results.hasNoResultsForDotCompletion()) {
|
||||||
|
const UnsavedFile &unsavedFile = translationUnit.unsavedFile();
|
||||||
|
bool positionIsOk = false;
|
||||||
|
const uint dotPosition = unsavedFile.toUtf8Position(line, column - 1, &positionIsOk);
|
||||||
|
if (positionIsOk && unsavedFile.hasCharacterAt(dotPosition, '.'))
|
||||||
|
results = completeWithArrowInsteadOfDot(line, column, dotPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangCodeCompleteResults CodeCompleter::completeWithArrowInsteadOfDot(uint line,
|
||||||
|
uint column,
|
||||||
|
uint dotPosition)
|
||||||
{
|
{
|
||||||
ClangCodeCompleteResults results;
|
ClangCodeCompleteResults results;
|
||||||
|
const bool replaced = translationUnit.unsavedFile().replaceAt(dotPosition,
|
||||||
const SourceLocation location = translationUnit.sourceLocationAtWithoutReparsing(line, column - 1);
|
|
||||||
const bool replaced = translationUnit.unsavedFile().replaceAt(location.offset(),
|
|
||||||
1,
|
1,
|
||||||
Utf8StringLiteral("->"));
|
Utf8StringLiteral("->"));
|
||||||
|
|
||||||
|
@@ -45,18 +45,20 @@ public:
|
|||||||
|
|
||||||
CompletionCorrection neededCorrection() const;
|
CompletionCorrection neededCorrection() const;
|
||||||
|
|
||||||
public: // for tests
|
|
||||||
bool hasDotAt(uint line, uint column) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint defaultOptions() const;
|
uint defaultOptions() const;
|
||||||
|
|
||||||
|
void tryDotArrowCorrectionIfNoResults(ClangCodeCompleteResults &results,
|
||||||
|
uint line,
|
||||||
|
uint column);
|
||||||
|
|
||||||
ClangCodeCompleteResults complete(uint line,
|
ClangCodeCompleteResults complete(uint line,
|
||||||
uint column,
|
uint column,
|
||||||
CXUnsavedFile *unsavedFiles,
|
CXUnsavedFile *unsavedFiles,
|
||||||
unsigned unsavedFileCount);
|
unsigned unsavedFileCount);
|
||||||
|
ClangCodeCompleteResults completeWithArrowInsteadOfDot(uint line,
|
||||||
ClangCodeCompleteResults completeWithArrowInsteadOfDot(uint line, uint column);
|
uint column,
|
||||||
|
uint dotPosition);
|
||||||
|
|
||||||
Utf8String filePath() const;
|
Utf8String filePath() const;
|
||||||
static void checkCodeCompleteResult(CXCodeCompleteResults *completeResults);
|
static void checkCodeCompleteResult(CXCodeCompleteResults *completeResults);
|
||||||
|
@@ -71,15 +71,24 @@ const char *UnsavedFile::filePath() const
|
|||||||
return cxUnsavedFile.Filename;
|
return cxUnsavedFile.Filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnsavedFile::hasCharacterAt(uint line, uint column, char character) const
|
uint UnsavedFile::toUtf8Position(uint line, uint column, bool *ok) const
|
||||||
{
|
{
|
||||||
Utf8PositionFromLineColumn converter(cxUnsavedFile.Contents);
|
Utf8PositionFromLineColumn converter(cxUnsavedFile.Contents);
|
||||||
if (converter.find(line, column)) {
|
if (converter.find(line, column)) {
|
||||||
const uint utf8Position = converter.position();
|
*ok = true;
|
||||||
return hasCharacterAt(utf8Position, character);
|
return converter.position();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
*ok = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnsavedFile::hasCharacterAt(uint line, uint column, char character) const
|
||||||
|
{
|
||||||
|
bool positionIsOk = false;
|
||||||
|
const uint utf8Position = toUtf8Position(line, column, &positionIsOk);
|
||||||
|
|
||||||
|
return positionIsOk && hasCharacterAt(utf8Position, character);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnsavedFile::hasCharacterAt(uint position, char character) const
|
bool UnsavedFile::hasCharacterAt(uint position, char character) const
|
||||||
|
@@ -55,6 +55,7 @@ public:
|
|||||||
const char *filePath() const;
|
const char *filePath() const;
|
||||||
|
|
||||||
// 1-based line and column
|
// 1-based line and column
|
||||||
|
uint toUtf8Position(uint line, uint column, bool *ok) const;
|
||||||
bool hasCharacterAt(uint line, uint column, char character) const;
|
bool hasCharacterAt(uint line, uint column, char character) const;
|
||||||
bool hasCharacterAt(uint position, char character) 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);
|
||||||
|
@@ -112,6 +112,19 @@ protected:
|
|||||||
readFileContent(QStringLiteral("/complete_withDotArrowCorrectionForPointer.cpp")),
|
readFileContent(QStringLiteral("/complete_withDotArrowCorrectionForPointer.cpp")),
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerBeforeTyping{
|
||||||
|
Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
|
||||||
|
projectPart.projectPartId(),
|
||||||
|
readFileContent(QStringLiteral("/complete_withDotArrowCorrectionForPointer_beforeTyping.cpp")),
|
||||||
|
true
|
||||||
|
};
|
||||||
|
ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerAfterTyping{
|
||||||
|
Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
|
||||||
|
projectPart.projectPartId(),
|
||||||
|
readFileContent(QStringLiteral("/complete_withDotArrowCorrectionForPointer_afterTyping.cpp")),
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerInitial{
|
ClangBackEnd::FileContainer dotArrowCorrectionForPointerFileContainerInitial{
|
||||||
Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
|
Utf8StringLiteral(TESTDATA_DIR"/complete_withDotArrowCorrectionForPointer.cpp"),
|
||||||
projectPart.projectPartId(),
|
projectPart.projectPartId(),
|
||||||
@@ -313,30 +326,6 @@ 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, HasDotAtWithUpdatedUnsavedFile)
|
|
||||||
{
|
|
||||||
auto myCompleter = setupCompleter(dotArrowCorrectionForPointerFileContainerInitial);
|
|
||||||
unsavedFiles.createOrUpdate({dotArrowCorrectionForPointerFileContainerUpdated});
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -350,6 +339,24 @@ TEST_F(CodeCompleter, DotToArrowCompletionForPointer)
|
|||||||
ClangBackEnd::CompletionCorrection::DotToArrowCorrection);
|
ClangBackEnd::CompletionCorrection::DotToArrowCorrection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(CodeCompleter, DotToArrowCompletionForPointerInOutdatedTranslationUnit)
|
||||||
|
{
|
||||||
|
auto fileContainerBeforeTyping = dotArrowCorrectionForPointerFileContainerBeforeTyping;
|
||||||
|
auto myCompleter = setupCompleter(fileContainerBeforeTyping);
|
||||||
|
auto translationUnit = translationUnits.translationUnit(fileContainerBeforeTyping.filePath(),
|
||||||
|
fileContainerBeforeTyping.projectPartId());
|
||||||
|
translationUnit.cxTranslationUnit(); // Parse
|
||||||
|
unsavedFiles.createOrUpdate({dotArrowCorrectionForPointerFileContainerAfterTyping});
|
||||||
|
|
||||||
|
const ClangBackEnd::CodeCompletions completions = myCompleter.complete(5, 9);
|
||||||
|
|
||||||
|
ASSERT_THAT(completions,
|
||||||
|
Contains(IsCodeCompletion(Utf8StringLiteral("member"),
|
||||||
|
CodeCompletion::VariableCompletionKind)));
|
||||||
|
ASSERT_THAT(myCompleter.neededCorrection(),
|
||||||
|
ClangBackEnd::CompletionCorrection::DotToArrowCorrection);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(CodeCompleter, NoDotToArrowCompletionForObject)
|
TEST_F(CodeCompleter, NoDotToArrowCompletionForObject)
|
||||||
{
|
{
|
||||||
auto myCompleter = setupCompleter(noDotArrowCorrectionForObjectFileContainer);
|
auto myCompleter = setupCompleter(noDotArrowCorrectionForObjectFileContainer);
|
||||||
|
@@ -0,0 +1,6 @@
|
|||||||
|
struct Foo { int member; };
|
||||||
|
|
||||||
|
void g(Foo *foo)
|
||||||
|
{
|
||||||
|
foo.
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
struct Foo { int member; };
|
||||||
|
|
||||||
|
void g(Foo *foo)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@@ -34,6 +34,7 @@
|
|||||||
using ClangBackEnd::UnsavedFile;
|
using ClangBackEnd::UnsavedFile;
|
||||||
using ClangBackEnd::UnsavedFiles;
|
using ClangBackEnd::UnsavedFiles;
|
||||||
|
|
||||||
|
using ::testing::Eq;
|
||||||
using ::testing::PrintToString;
|
using ::testing::PrintToString;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -150,6 +151,44 @@ TEST_F(UnsavedFile, Replace)
|
|||||||
ASSERT_THAT(unsavedFile, IsUnsavedFile(filePath, expectedContent, expectedContent.byteSize()));
|
ASSERT_THAT(unsavedFile, IsUnsavedFile(filePath, expectedContent, expectedContent.byteSize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UnsavedFile, ToUtf8PositionForValidLineColumn)
|
||||||
|
{
|
||||||
|
::UnsavedFile unsavedFile(filePath, fileContent);
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
const uint position = unsavedFile.toUtf8Position(1, 1, &ok);
|
||||||
|
|
||||||
|
ASSERT_TRUE(ok);
|
||||||
|
ASSERT_THAT(position, Eq(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnsavedFile, ToUtf8PositionForInValidLineColumn)
|
||||||
|
{
|
||||||
|
::UnsavedFile unsavedFile(filePath, fileContent);
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
unsavedFile.toUtf8Position(2, 1, &ok);
|
||||||
|
|
||||||
|
ASSERT_FALSE(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnsavedFile, ToUtf8PositionForDefaultConstructedUnsavedFile)
|
||||||
|
{
|
||||||
|
::UnsavedFile unsavedFile;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
unsavedFile.toUtf8Position(1, 1, &ok);
|
||||||
|
|
||||||
|
ASSERT_FALSE(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnsavedFile, HasNoCharacterForDefaultConstructedUnsavedFile)
|
||||||
|
{
|
||||||
|
::UnsavedFile unsavedFile;
|
||||||
|
|
||||||
|
ASSERT_FALSE(unsavedFile.hasCharacterAt(0, 'x'));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(UnsavedFile, HasNoCharacterForTooBigOffset)
|
TEST_F(UnsavedFile, HasNoCharacterForTooBigOffset)
|
||||||
{
|
{
|
||||||
::UnsavedFile unsavedFile(filePath, fileContent);
|
::UnsavedFile unsavedFile(filePath, fileContent);
|
||||||
|
Reference in New Issue
Block a user