summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2016-10-11 18:19:12 +0200
committerNikolai Kosjar <nikolai.kosjar@qt.io>2016-10-12 08:01:48 +0000
commit63ae993bf2a844d8f6b25b9733827a6ccd651be3 (patch)
treeb3ae122133ee5d30d7d457f792fad304b2a79c10
parent9d55d8485cda7077d1280f3335102ffd036240b5 (diff)
downloadqt-creator-63ae993bf2a844d8f6b25b9733827a6ccd651be3.tar.gz
Clang: Add output argument highlighting
This adds a mix-in for writable functions arguments. Change-Id: I758f7fef77d992ea25395db550571ccb081fd5fd Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
-rw-r--r--src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp2
-rw-r--r--src/plugins/texteditor/texteditorconstants.cpp1
-rw-r--r--src/plugins/texteditor/texteditorconstants.h1
-rw-r--r--src/plugins/texteditor/texteditorsettings.cpp4
-rw-r--r--src/tools/clangbackend/ipcsource/clangtype.cpp2
-rw-r--r--src/tools/clangbackend/ipcsource/clangtype.h2
-rw-r--r--src/tools/clangbackend/ipcsource/cursor.cpp61
-rw-r--r--src/tools/clangbackend/ipcsource/cursor.h8
-rw-r--r--src/tools/clangbackend/ipcsource/highlightingmark.cpp96
-rw-r--r--src/tools/clangbackend/ipcsource/highlightingmark.h13
-rw-r--r--src/tools/clangbackend/ipcsource/highlightingmarks.cpp25
-rw-r--r--src/tools/clangbackend/ipcsource/highlightingmarks.h3
-rw-r--r--src/tools/clangbackend/ipcsource/highlightingmarksiterator.h19
-rw-r--r--tests/unit/unittest/clangcompareoperators.h40
-rw-r--r--tests/unit/unittest/cursor-test.cpp40
-rw-r--r--tests/unit/unittest/data/highlightingmarks.cpp86
-rw-r--r--tests/unit/unittest/highlightingmarks-test.cpp100
-rw-r--r--tests/unit/unittest/unittest.pro1
18 files changed, 447 insertions, 57 deletions
diff --git a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp
index 2e85c49c3c..07d5741918 100644
--- a/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp
+++ b/src/plugins/clangcodemodel/clanghighlightingmarksreporter.cpp
@@ -60,6 +60,8 @@ TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type)
return TextEditor::C_PREPROCESSOR;
case HighlightingType::Declaration:
return TextEditor::C_DECLARATION;
+ case HighlightingType::OutputArgument:
+ return TextEditor::C_OUTPUT_ARGUMENT;
default:
return TextEditor::C_TEXT; // never called
}
diff --git a/src/plugins/texteditor/texteditorconstants.cpp b/src/plugins/texteditor/texteditorconstants.cpp
index d670895512..48681e5cd0 100644
--- a/src/plugins/texteditor/texteditorconstants.cpp
+++ b/src/plugins/texteditor/texteditorconstants.cpp
@@ -102,6 +102,7 @@ const char *nameForStyle(TextStyle style)
case C_WARNING_CONTEXT: return "WarningContext";
case C_DECLARATION: return "Declaration";
+ case C_OUTPUT_ARGUMENT: return "C_OUTPUT_ARGUMENT";
case C_LAST_STYLE_SENTINEL: return "LastStyleSentinel";
}
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index f68b41cc0d..8dbaf93de4 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -100,6 +100,7 @@ enum TextStyle : quint8 {
C_ERROR_CONTEXT,
C_DECLARATION,
+ C_OUTPUT_ARGUMENT,
C_LAST_STYLE_SENTINEL
};
diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp
index 67270d81bb..0660f929f8 100644
--- a/src/plugins/texteditor/texteditorsettings.cpp
+++ b/src/plugins/texteditor/texteditorsettings.cpp
@@ -313,6 +313,10 @@ TextEditorSettings::TextEditorSettings(QObject *parent)
tr("Declaration"),
tr("Declaration of a function, variable, and so on."),
FormatDescription::ShowFontUnderlineAndRelativeControls);
+ formatDescr.emplace_back(C_OUTPUT_ARGUMENT,
+ tr("Output Argument"),
+ tr("Writable arguments of a function call."),
+ FormatDescription::ShowFontUnderlineAndRelativeControls);
d->m_fontSettingsPage = new FontSettingsPage(formatDescr,
Constants::TEXT_EDITOR_FONT_SETTINGS,
diff --git a/src/tools/clangbackend/ipcsource/clangtype.cpp b/src/tools/clangbackend/ipcsource/clangtype.cpp
index 54fe1aba2d..13ab8c9c6c 100644
--- a/src/tools/clangbackend/ipcsource/clangtype.cpp
+++ b/src/tools/clangbackend/ipcsource/clangtype.cpp
@@ -69,7 +69,7 @@ bool Type::isReferencingConstant() const
return (isPointer() || isLValueReference()) && pointeeType().isConstant();
}
-bool Type::isOutputParameter() const
+bool Type::isOutputArgument() const
{
return (isPointer() || isLValueReference()) && !pointeeType().isConstant();
}
diff --git a/src/tools/clangbackend/ipcsource/clangtype.h b/src/tools/clangbackend/ipcsource/clangtype.h
index e9a19e92db..6a51245ce6 100644
--- a/src/tools/clangbackend/ipcsource/clangtype.h
+++ b/src/tools/clangbackend/ipcsource/clangtype.h
@@ -49,7 +49,7 @@ public:
bool isConstantPointer() const;
bool isLValueReference() const;
bool isReferencingConstant() const;
- bool isOutputParameter() const;
+ bool isOutputArgument() const;
Utf8String utf8Spelling() const;
ClangString spelling() const;
diff --git a/src/tools/clangbackend/ipcsource/cursor.cpp b/src/tools/clangbackend/ipcsource/cursor.cpp
index f88ef02bcd..56dfd9e610 100644
--- a/src/tools/clangbackend/ipcsource/cursor.cpp
+++ b/src/tools/clangbackend/ipcsource/cursor.cpp
@@ -213,16 +213,32 @@ SourceLocation Cursor::sourceLocation() const
return clang_getCursorLocation(cxCursor);
}
+CXSourceLocation Cursor::cxSourceLocation() const
+{
+ return clang_getCursorLocation(cxCursor);
+}
+
SourceRange Cursor::sourceRange() const
{
return clang_getCursorExtent(cxCursor);
}
+CXSourceRange Cursor::cxSourceRange() const
+{
+ return clang_getCursorExtent(cxCursor);
+}
+
SourceRange Cursor::commentRange() const
{
return clang_Cursor_getCommentRange(cxCursor);
}
+bool Cursor::hasSameSourceLocationAs(const Cursor &other) const
+{
+ return clang_equalLocations(clang_getCursorLocation(cxCursor),
+ clang_getCursorLocation(other.cxCursor));
+}
+
Cursor Cursor::definition() const
{
return clang_getCursorDefinition(cxCursor);
@@ -279,32 +295,42 @@ Cursor Cursor::argument(int index) const
{
return clang_Cursor_getArgument(cxCursor, index);
}
+
namespace {
-void collectOutputArguments(const Cursor &callExpression,
- std::vector<Cursor> &outputArguments)
+
+bool isNotUnexposedLValueReference(const Cursor &argument, const Type &argumentType)
+{
+ return !(argument.isUnexposed() && argumentType.isLValueReference());
+}
+
+}
+
+void Cursor::collectOutputArgumentRangesTo(std::vector<CXSourceRange> &outputArgumentRanges) const
{
- auto callExpressionType = callExpression.referenced().type();
- auto argumentCount = callExpression.argumentCount();
- outputArguments.reserve(argumentCount);
+ const Type callExpressionType = referenced().type();
+ const int argumentCount = this->argumentCount();
+ const std::size_t maxSize = std::size_t(std::max(0, argumentCount))
+ + outputArgumentRanges.size();
+ outputArgumentRanges.reserve(maxSize);
for (int argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex) {
- auto argument = callExpression.argument(argumentIndex);
- auto argumentType = callExpressionType.argument(argumentIndex);
+ const Cursor argument = this->argument(argumentIndex);
+ const Type argumentType = callExpressionType.argument(argumentIndex);
- if (!argument.isUnexposed() && argumentType.isOutputParameter())
- outputArguments.push_back(callExpression.argument(argumentIndex));
+ if (isNotUnexposedLValueReference(argument, argumentType)
+ && argumentType.isOutputArgument()) {
+ outputArgumentRanges.push_back(argument.cxSourceRange());
+ }
}
}
-}
-std::vector<Cursor> Cursor::outputArguments() const
+std::vector<CXSourceRange> Cursor::outputArgumentRanges() const
{
- std::vector<Cursor> outputArguments;
+ std::vector<CXSourceRange> outputArgumentRanges;
- if (kind() == CXCursor_CallExpr)
- collectOutputArguments(*this, outputArguments);
+ collectOutputArgumentRangesTo(outputArgumentRanges);
- return outputArguments;
+ return outputArgumentRanges;
}
CXCursorKind Cursor::kind() const
@@ -317,6 +343,11 @@ bool operator==(const Cursor &first, const Cursor &second)
return clang_equalCursors(first.cxCursor, second.cxCursor);
}
+bool operator!=(const Cursor &first, const Cursor &second)
+{
+ return !(first == second);
+}
+
void PrintTo(CXCursorKind cursorKind, ::std::ostream *os)
{
ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursorKind));
diff --git a/src/tools/clangbackend/ipcsource/cursor.h b/src/tools/clangbackend/ipcsource/cursor.h
index 6711ab98d5..8f294c7e26 100644
--- a/src/tools/clangbackend/ipcsource/cursor.h
+++ b/src/tools/clangbackend/ipcsource/cursor.h
@@ -78,8 +78,11 @@ public:
Type nonPointerTupe() const;
SourceLocation sourceLocation() const;
+ CXSourceLocation cxSourceLocation() const;
SourceRange sourceRange() const;
+ CXSourceRange cxSourceRange() const;
SourceRange commentRange() const;
+ bool hasSameSourceLocationAs(const Cursor &other) const;
Cursor definition() const;
Cursor canonical() const;
@@ -90,7 +93,9 @@ public:
Cursor functionBaseDeclaration() const;
Cursor functionBase() const;
Cursor argument(int index) const;
- std::vector<Cursor> outputArguments() const;
+ void collectOutputArgumentRangesTo(
+ std::vector<CXSourceRange> &outputArgumentRanges) const;
+ std::vector<CXSourceRange> outputArgumentRanges() const;
CXCursorKind kind() const;
@@ -114,6 +119,7 @@ void Cursor::visit(VisitorCallback visitorCallback) const
}
bool operator==(const Cursor &first, const Cursor &second);
+bool operator!=(const Cursor &first, const Cursor &second);
void PrintTo(CXCursorKind cursorKind, ::std::ostream *os);
void PrintTo(const Cursor &cursor, ::std::ostream* os);
diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.cpp b/src/tools/clangbackend/ipcsource/highlightingmark.cpp
index 18ceca9157..d4744f7853 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmark.cpp
+++ b/src/tools/clangbackend/ipcsource/highlightingmark.cpp
@@ -30,6 +30,7 @@
#include "highlightingmark.h"
#include "sourcelocation.h"
#include "sourcerange.h"
+#include "sourcerangecontainer.h"
#include <cstring>
#include <ostream>
@@ -39,16 +40,19 @@
namespace ClangBackEnd {
HighlightingMark::HighlightingMark(const CXCursor &cxCursor,
- CXToken *cxToken,
- CXTranslationUnit cxTranslationUnit)
+ CXToken *cxToken,
+ CXTranslationUnit cxTranslationUnit,
+ std::vector<CXSourceRange> &currentOutputArgumentRanges)
+ : currentOutputArgumentRanges(&currentOutputArgumentRanges),
+ originalCursor(cxCursor)
{
const SourceRange sourceRange = clang_getTokenExtent(cxTranslationUnit, *cxToken);
const auto start = sourceRange.start();
const auto end = sourceRange.end();
- originalCursor = cxCursor;
line = start.line();
column = start.column();
+ offset = start.offset();
length = end.offset() - start.offset();
collectKinds(cxToken, originalCursor);
}
@@ -159,6 +163,17 @@ void HighlightingMark::variableKind(const Cursor &cursor)
types.mainHighlightingType = HighlightingType::LocalVariable;
else
types.mainHighlightingType = HighlightingType::GlobalVariable;
+
+ if (isOutputArgument())
+ types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
+}
+
+void HighlightingMark::fieldKind(const Cursor &)
+{
+ types.mainHighlightingType = HighlightingType::Field;
+
+ if (isOutputArgument())
+ types.mixinHighlightingTypes.push_back(HighlightingType::OutputArgument);
}
bool HighlightingMark::isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const
@@ -185,6 +200,68 @@ void HighlightingMark::addExtraTypeIfFirstPass(HighlightingType type,
types.mixinHighlightingTypes.push_back(type);
}
+bool HighlightingMark::isArgumentInCurrentOutputArgumentLocations() const
+{
+ auto originalSourceLocation = originalCursor.cxSourceLocation();
+
+ const auto isNotSameOutputArgument = [&] (const CXSourceRange &currentSourceRange) {
+ return !(originalSourceLocation.int_data >= currentSourceRange.begin_int_data
+ && originalSourceLocation.int_data <= currentSourceRange.end_int_data);
+ };
+
+ auto partitionPoint = std::partition(currentOutputArgumentRanges->begin(),
+ currentOutputArgumentRanges->end(),
+ isNotSameOutputArgument);
+
+ bool isOutputArgument = partitionPoint != currentOutputArgumentRanges->end();
+
+ if (isOutputArgument)
+ currentOutputArgumentRanges->erase(partitionPoint, currentOutputArgumentRanges->end());
+
+ return isOutputArgument;
+}
+
+bool HighlightingMark::isOutputArgument() const
+{
+ if (currentOutputArgumentRanges->empty())
+ return false;
+
+ return isArgumentInCurrentOutputArgumentLocations();
+}
+
+void HighlightingMark::collectOutputArguments(const Cursor &cursor)
+{
+ cursor.collectOutputArgumentRangesTo(*currentOutputArgumentRanges);
+ filterOutPreviousOutputArguments();
+}
+
+namespace {
+
+uint getStart(CXSourceRange cxSourceRange)
+{
+ CXSourceLocation startSourceLocation = clang_getRangeStart(cxSourceRange);
+
+ uint startOffset;
+
+ clang_getFileLocation(startSourceLocation, nullptr, nullptr, nullptr, &startOffset);
+
+ return startOffset;
+}
+}
+
+void HighlightingMark::filterOutPreviousOutputArguments()
+{
+ auto isAfterLocation = [this] (CXSourceRange outputRange) {
+ return getStart(outputRange) > offset;
+ };
+
+ auto precedingBegin = std::partition(currentOutputArgumentRanges->begin(),
+ currentOutputArgumentRanges->end(),
+ isAfterLocation);
+
+ currentOutputArgumentRanges->erase(precedingBegin, currentOutputArgumentRanges->end());
+}
+
void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion)
{
if (isRealDynamicCall(cursor) || isVirtualMethodDeclarationOrDefinition(cursor))
@@ -204,12 +281,13 @@ void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
case CXCursor_CallExpr:
case CXCursor_CXXMethod: functionKind(cursor, recursion); break;
case CXCursor_NonTypeTemplateParameter:
- case CXCursor_ParmDecl: types.mainHighlightingType = HighlightingType::LocalVariable; break;
+ case CXCursor_CompoundStmt: types.mainHighlightingType = HighlightingType::LocalVariable; break;
+ case CXCursor_ParmDecl:
case CXCursor_VarDecl: variableKind(cursor); break;
case CXCursor_DeclRefExpr: identifierKind(cursor.referenced(), Recursion::RecursivePass); break;
case CXCursor_MemberRefExpr: memberReferenceKind(cursor); break;
case CXCursor_FieldDecl:
- case CXCursor_MemberRef:
+ case CXCursor_MemberRef: fieldKind(cursor); break;
case CXCursor_ObjCIvarDecl:
case CXCursor_ObjCPropertyDecl:
case CXCursor_ObjCClassMethodDecl:
@@ -282,15 +360,17 @@ HighlightingType operatorKind(const Cursor &cursor)
return HighlightingType::Invalid;
}
-HighlightingType punctationKind(const Cursor &cursor)
+}
+
+HighlightingType HighlightingMark::punctuationKind(const Cursor &cursor)
{
switch (cursor.kind()) {
case CXCursor_DeclRefExpr: return operatorKind(cursor);
+ case CXCursor_CallExpr: collectOutputArguments(cursor);
default: return HighlightingType::Invalid;
}
}
-}
void HighlightingMark::collectKinds(CXToken *cxToken, const Cursor &cursor)
{
auto cxTokenKind = clang_getTokenKind(*cxToken);
@@ -299,7 +379,7 @@ void HighlightingMark::collectKinds(CXToken *cxToken, const Cursor &cursor)
switch (cxTokenKind) {
case CXToken_Keyword: types.mainHighlightingType = HighlightingType::Keyword; break;
- case CXToken_Punctuation: types.mainHighlightingType = punctationKind(cursor); break;
+ case CXToken_Punctuation: types.mainHighlightingType = punctuationKind(cursor); break;
case CXToken_Identifier: identifierKind(cursor, Recursion::FirstPass); break;
case CXToken_Comment: types.mainHighlightingType = HighlightingType::Comment; break;
case CXToken_Literal: types.mainHighlightingType = literalKind(cursor); break;
diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.h b/src/tools/clangbackend/ipcsource/highlightingmark.h
index 7f2009810b..1740852730 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmark.h
+++ b/src/tools/clangbackend/ipcsource/highlightingmark.h
@@ -45,7 +45,10 @@ class HighlightingMark
};
public:
- HighlightingMark(const CXCursor &cxCursor, CXToken *cxToken, CXTranslationUnit cxTranslationUnit);
+ HighlightingMark(const CXCursor &cxCursor,
+ CXToken *cxToken,
+ CXTranslationUnit cxTranslationUnit,
+ std::vector<CXSourceRange> &currentOutputArgumentRanges);
HighlightingMark(uint line, uint column, uint length, HighlightingTypes types);
HighlightingMark(uint line, uint column, uint length, HighlightingType type);
@@ -61,18 +64,26 @@ private:
void identifierKind(const Cursor &cursor, Recursion recursion);
void referencedTypeKind(const Cursor &cursor);
void variableKind(const Cursor &cursor);
+ void fieldKind(const Cursor &cursor);
bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const;
void functionKind(const Cursor &cursor, Recursion recursion);
void memberReferenceKind(const Cursor &cursor);
+ HighlightingType punctuationKind(const Cursor &cursor);
void collectKinds(CXToken *cxToken, const Cursor &cursor);
bool isRealDynamicCall(const Cursor &cursor) const;
void addExtraTypeIfFirstPass(HighlightingType type, Recursion recursion);
+ bool isOutputArgument() const;
+ void collectOutputArguments(const Cursor &cursor);
+ void filterOutPreviousOutputArguments();
+ bool isArgumentInCurrentOutputArgumentLocations() const;
private:
+ std::vector<CXSourceRange> *currentOutputArgumentRanges = nullptr;
Cursor originalCursor;
uint line;
uint column;
uint length;
+ uint offset = 0;
HighlightingTypes types;
};
diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp
index 10cb2b5e82..725e6eb316 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmarks.cpp
+++ b/src/tools/clangbackend/ipcsource/highlightingmarks.cpp
@@ -47,12 +47,18 @@ HighlightingMarks::~HighlightingMarks()
HighlightingMarks::const_iterator HighlightingMarks::begin() const
{
- return const_iterator(cxCursor.cbegin(), cxToken, cxTranslationUnit);
+ return const_iterator(cxCursor.cbegin(),
+ cxToken,
+ cxTranslationUnit,
+ currentOutputArgumentRanges);
}
HighlightingMarks::const_iterator HighlightingMarks::end() const
{
- return const_iterator(cxCursor.cend(), cxToken + cxTokenCount, cxTranslationUnit);
+ return const_iterator(cxCursor.cend(),
+ cxToken + cxTokenCount,
+ cxTranslationUnit,
+ currentOutputArgumentRanges);
}
QVector<HighlightingMarkContainer> HighlightingMarks::toHighlightingMarksContainers() const
@@ -67,11 +73,19 @@ QVector<HighlightingMarkContainer> HighlightingMarks::toHighlightingMarksContain
&& !highlightMark.hasMainType(HighlightingType::Comment);
};
- std::copy_if(begin(), end(), std::back_inserter(containers), isValidHighlightMark);
+ for (const HighlightingMark &highlightMark : *this) {
+ if (isValidHighlightMark(highlightMark))
+ containers.push_back(highlightMark);
+ }
return containers;
}
+bool HighlightingMarks::currentOutputArgumentRangesAreEmpty() const
+{
+ return currentOutputArgumentRanges.empty();
+}
+
bool HighlightingMarks::isEmpty() const
{
return cxTokenCount == 0;
@@ -89,7 +103,10 @@ uint HighlightingMarks::size() const
HighlightingMark HighlightingMarks::operator[](size_t index) const
{
- return HighlightingMark(cxCursor[index], cxToken + index, cxTranslationUnit);
+ return HighlightingMark(cxCursor[index],
+ cxToken + index,
+ cxTranslationUnit,
+ currentOutputArgumentRanges);
}
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/highlightingmarks.h b/src/tools/clangbackend/ipcsource/highlightingmarks.h
index 2d77bb86c5..6904bb3184 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmarks.h
+++ b/src/tools/clangbackend/ipcsource/highlightingmarks.h
@@ -58,7 +58,10 @@ public:
QVector<HighlightingMarkContainer> toHighlightingMarksContainers() const;
+ bool currentOutputArgumentRangesAreEmpty() const;
+
private:
+ mutable std::vector<CXSourceRange> currentOutputArgumentRanges;
CXTranslationUnit cxTranslationUnit = nullptr;
CXToken *const cxToken = nullptr;
const uint cxTokenCount = 0;
diff --git a/src/tools/clangbackend/ipcsource/highlightingmarksiterator.h b/src/tools/clangbackend/ipcsource/highlightingmarksiterator.h
index 9cbfcabaad..daeada47a7 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmarksiterator.h
+++ b/src/tools/clangbackend/ipcsource/highlightingmarksiterator.h
@@ -43,11 +43,13 @@ class HighlightingMarksIterator : public std::iterator<std::forward_iterator_tag
{
public:
HighlightingMarksIterator(std::vector<CXCursor>::const_iterator cxCursorIterator,
- CXToken *cxToken,
- CXTranslationUnit cxTranslationUnit)
+ CXToken *cxToken,
+ CXTranslationUnit cxTranslationUnit,
+ std::vector<CXSourceRange> &currentOutputArgumentRanges)
: cxCursorIterator(cxCursorIterator),
cxToken(cxToken),
- cxTranslationUnit(cxTranslationUnit)
+ cxTranslationUnit(cxTranslationUnit),
+ currentOutputArgumentRanges(currentOutputArgumentRanges)
{}
HighlightingMarksIterator& operator++()
@@ -60,7 +62,10 @@ public:
HighlightingMarksIterator operator++(int)
{
- return HighlightingMarksIterator(cxCursorIterator++, cxToken++, cxTranslationUnit);
+ return HighlightingMarksIterator(cxCursorIterator++,
+ cxToken++,
+ cxTranslationUnit,
+ currentOutputArgumentRanges);
}
bool operator==(HighlightingMarksIterator other) const
@@ -75,13 +80,17 @@ public:
HighlightingMark operator*()
{
- return HighlightingMark(*cxCursorIterator, cxToken, cxTranslationUnit);
+ return HighlightingMark(*cxCursorIterator,
+ cxToken,
+ cxTranslationUnit,
+ currentOutputArgumentRanges);
}
private:
std::vector<CXCursor>::const_iterator cxCursorIterator;
CXToken *cxToken;
CXTranslationUnit cxTranslationUnit;
+ std::vector<CXSourceRange> &currentOutputArgumentRanges;
};
} // namespace ClangBackEnd
diff --git a/tests/unit/unittest/clangcompareoperators.h b/tests/unit/unittest/clangcompareoperators.h
new file mode 100644
index 0000000000..39351946be
--- /dev/null
+++ b/tests/unit/unittest/clangcompareoperators.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <clang-c/Index.h>
+
+inline
+bool operator==(const CXSourceLocation &first, const CXSourceLocation &second)
+{
+ return clang_equalLocations(first, second);
+}
+
+inline
+bool operator==(const CXSourceRange &first, const CXSourceRange &second)
+{
+ return clang_equalRanges(first, second);
+}
diff --git a/tests/unit/unittest/cursor-test.cpp b/tests/unit/unittest/cursor-test.cpp
index bba963be86..77df29a17a 100644
--- a/tests/unit/unittest/cursor-test.cpp
+++ b/tests/unit/unittest/cursor-test.cpp
@@ -25,6 +25,8 @@
#include "googletest.h"
+#include "clangcompareoperators.h"
+
#include <clangdocument.h>
#include <clangdocuments.h>
#include <clangstring.h>
@@ -85,6 +87,8 @@ protected:
const TranslationUnit &translationUnit = d->translationUnit;
};
+
+
TEST_F(Cursor, CreateNullCursor)
{
::Cursor cursor;
@@ -489,21 +493,21 @@ TEST_F(Cursor, HasNotFinaAttributeInClass)
TEST_F(Cursor, HasOutputValues)
{
auto callExpressionCursor = translationUnit.cursorAt(117, 19);
- auto outputArgumentExpectedCursor = translationUnit.cursorAt(117, 20);
+ auto outputArgumentExpectedSourceLocation = translationUnit.cursorAt(117, 20).cxSourceRange();
- auto outputArguments = callExpressionCursor.outputArguments();
+ auto outputArgumentLocations = callExpressionCursor.outputArgumentRanges();
- ASSERT_THAT(outputArguments.size(), 1);
- ASSERT_THAT(outputArguments[0], outputArgumentExpectedCursor);
+ ASSERT_THAT(outputArgumentLocations.size(), 2);
+ ASSERT_THAT(outputArgumentLocations[0], outputArgumentExpectedSourceLocation);
}
TEST_F(Cursor, HasOnlyInputValues)
{
auto callExpressionCursor = translationUnit.cursorAt(118, 18);
- auto outputArguments = callExpressionCursor.outputArguments();
+ auto outputArgumentLocations = callExpressionCursor.outputArgumentRanges();
- ASSERT_THAT(outputArguments, IsEmpty());
+ ASSERT_THAT(outputArgumentLocations, IsEmpty());
}
TEST_F(Cursor, ArgumentCountIsZero)
@@ -748,58 +752,58 @@ TEST_F(Cursor, PointerIsNotRefencingConstant)
ASSERT_FALSE(argument.isReferencingConstant());
}
-TEST_F(Cursor, PointerIsOutputParameter)
+TEST_F(Cursor, PointerIsOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(127, 13);
auto argument = callExpressionCursor.type().argument(0);
- ASSERT_TRUE(argument.isOutputParameter());
+ ASSERT_TRUE(argument.isOutputArgument());
}
-TEST_F(Cursor, ConstantReferenceIsNotOutputParameter)
+TEST_F(Cursor, ConstantReferenceIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(125, 26);
auto argument = callExpressionCursor.type().argument(0);
- ASSERT_FALSE(argument.isOutputParameter());
+ ASSERT_FALSE(argument.isOutputArgument());
}
-TEST_F(Cursor, PointerToConstantIsNotOutputParameter)
+TEST_F(Cursor, PointerToConstantIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(126, 20);
auto argument = callExpressionCursor.type().argument(0);
- ASSERT_FALSE(argument.isOutputParameter()) << argument.isConstant() << argument.pointeeType().isConstant();
+ ASSERT_FALSE(argument.isOutputArgument()) << argument.isConstant() << argument.pointeeType().isConstant();
}
-TEST_F(Cursor, ConstantPointerIsNotOutputParameter)
+TEST_F(Cursor, ConstantPointerIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(128, 21);
auto argument = callExpressionCursor.type().argument(0);
- ASSERT_TRUE(argument.isOutputParameter());
+ ASSERT_TRUE(argument.isOutputArgument());
}
-TEST_F(Cursor, ReferenceIsOutputParameter)
+TEST_F(Cursor, ReferenceIsOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(124, 21);
auto argument = callExpressionCursor.type().argument(0);
- ASSERT_TRUE(argument.isOutputParameter());
+ ASSERT_TRUE(argument.isOutputArgument());
}
-TEST_F(Cursor, ConstReferenceIsNotOutputParameter)
+TEST_F(Cursor, ConstReferenceIsNotOutputArgument)
{
auto callExpressionCursor = translationUnit.cursorAt(125, 26);
auto argument = callExpressionCursor.type().argument(0);
- ASSERT_FALSE(argument.isOutputParameter());
+ ASSERT_FALSE(argument.isOutputArgument());
}
Data *Cursor::d;
diff --git a/tests/unit/unittest/data/highlightingmarks.cpp b/tests/unit/unittest/data/highlightingmarks.cpp
index 0fb2ea3beb..d37f3e297a 100644
--- a/tests/unit/unittest/data/highlightingmarks.cpp
+++ b/tests/unit/unittest/data/highlightingmarks.cpp
@@ -278,12 +278,12 @@ void FinalClass::FinalClassThisCall()
}
-void OutputParameter(int &one, const int &two, int *three=0);
+void OutputArgument(int &one, const int &two, int *three=0);
-void f12()
+void f12b()
{
int One;
- OutputParameter(One, 2);
+ OutputArgument(One, 2);
}
#include <highlightingmarks.h>
@@ -445,3 +445,83 @@ struct LambdaTester
lambda(var2);
}
};
+
+void NonConstReferenceArgument(int &argument);
+
+void f22()
+{
+ int x = 1;
+
+ NonConstReferenceArgument(x);
+}
+
+void ConstReferenceArgument(const int &argument);
+
+void f23()
+{
+ int x = 1;
+
+ ConstReferenceArgument(x);
+}
+
+void RValueReferenceArgument(int &&argument);
+
+void f24()
+{
+ int x = 1;
+
+ RValueReferenceArgument(static_cast<int&&>(x));
+}
+
+void NonConstPointerArgument(int *argument);
+
+void f25()
+{
+ int *x;
+
+ NonConstPointerArgument(x);
+}
+
+void ConstPointerArgument(const int *argument);
+
+void f26()
+{
+ int *x;
+
+ ConstPointerArgument(x);
+}
+
+void NonConstReferenceArgumentCallInsideCall(int x, int &argument);
+int GetArgument(int x);
+
+void f27()
+{
+ int x = 1;
+
+ NonConstReferenceArgumentCallInsideCall(GetArgument(x), x);
+}
+
+void f28(int &Reference)
+{
+ NonConstReferenceArgument(Reference);
+}
+
+void f29()
+{
+ int x;
+
+ NonConstPointerArgument(&x);
+}
+
+struct NonConstPointerArgumentAsMemberOfClass
+{
+ int member;
+};
+
+void f30()
+{
+ NonConstPointerArgumentAsMemberOfClass instance;
+
+ NonConstReferenceArgument(instance.member);
+}
+
diff --git a/tests/unit/unittest/highlightingmarks-test.cpp b/tests/unit/unittest/highlightingmarks-test.cpp
index 1d3ba1a05e..9433bf9249 100644
--- a/tests/unit/unittest/highlightingmarks-test.cpp
+++ b/tests/unit/unittest/highlightingmarks-test.cpp
@@ -959,6 +959,106 @@ TEST_F(HighlightingMarks, TypeDefDeclarationUsage)
ASSERT_THAT(infos[0], HasOnlyType(HighlightingType::Type));
}
+TEST_F(HighlightingMarks, NonConstReferenceArgument)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(455, 35));
+
+ infos[1];
+
+ ASSERT_THAT(infos[2],
+ HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
+}
+
+TEST_F(HighlightingMarks, ConstReferenceArgument)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(464, 32));
+
+ infos[1];
+
+ ASSERT_THAT(infos[2],
+ HasOnlyType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingMarks, RValueReferenceArgument)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(473, 52));
+
+ infos[1];
+
+ ASSERT_THAT(infos[8],
+ HasOnlyType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingMarks, NonConstPointerArgument)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(482, 33));
+
+ infos[1];
+
+ ASSERT_THAT(infos[2],
+ HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
+}
+
+TEST_F(HighlightingMarks, ConstPointerArgument)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(491, 30));
+
+ infos[1];
+
+ ASSERT_THAT(infos[2],
+ HasOnlyType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingMarks, NonConstReferenceArgumentCallInsideCall)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(501, 64));
+ infos[1];
+
+ infos[3];
+
+ ASSERT_THAT(infos[7],
+ HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
+}
+
+TEST_F(HighlightingMarks, OutputArgumentsAreEmptyAfterIteration)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(501, 63));
+
+ for (const auto &info : infos ) {}
+
+ ASSERT_TRUE(infos.currentOutputArgumentRangesAreEmpty());
+}
+
+TEST_F(HighlightingMarks, NonConstReferenceArgumentFromFunctionParameter)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(506, 42));
+
+ infos[1];
+
+ ASSERT_THAT(infos[2],
+ HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
+}
+
+TEST_F(HighlightingMarks, NonConstPointerArgumentAsExpression)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(513, 33));
+
+ infos[1];
+
+ ASSERT_THAT(infos[3],
+ HasTwoTypes(HighlightingType::LocalVariable, HighlightingType::OutputArgument));
+}
+
+TEST_F(HighlightingMarks, NonConstPointerArgumentAsMemberOfClass)
+{
+ const auto infos = translationUnit.highlightingMarksInRange(sourceRange(525, 46));
+
+ infos[1];
+
+ ASSERT_THAT(infos[4],
+ HasTwoTypes(HighlightingType::Field, HighlightingType::OutputArgument));
+}
+
TEST_F(HighlightingMarks, DISABLED_EnumerationTypeDef)
{
const auto infos = translationUnit.highlightingMarksInRange(sourceRange(424, 41));
diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro
index ce81a41a99..aa4b560fb6 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -118,6 +118,7 @@ HEADERS += \
chunksreportedmonitor.h \
clangasyncjob-base.h \
diagnosticcontainer-matcher.h \
+ clangcompareoperators.h \
dummyclangipcclient.h \
mockclangcodemodelclient.h \
mockclangcodemodelserver.h