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>
This commit is contained in:
Marco Bubke
2016-10-11 18:19:12 +02:00
committed by Nikolai Kosjar
parent 9d55d8485c
commit 63ae993bf2
18 changed files with 447 additions and 57 deletions

View File

@@ -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
}

View File

@@ -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";
}

View File

@@ -100,6 +100,7 @@ enum TextStyle : quint8 {
C_ERROR_CONTEXT,
C_DECLARATION,
C_OUTPUT_ARGUMENT,
C_LAST_STYLE_SENTINEL
};

View File

@@ -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,

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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)
{
auto callExpressionType = callExpression.referenced().type();
auto argumentCount = callExpression.argumentCount();
outputArguments.reserve(argumentCount);
return !(argument.isUnexposed() && argumentType.isLValueReference());
}
}
void Cursor::collectOutputArgumentRangesTo(std::vector<CXSourceRange> &outputArgumentRanges) const
{
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));

View File

@@ -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);

View File

@@ -30,6 +30,7 @@
#include "highlightingmark.h"
#include "sourcelocation.h"
#include "sourcerange.h"
#include "sourcerangecontainer.h"
#include <cstring>
#include <ostream>
@@ -40,15 +41,18 @@ namespace ClangBackEnd {
HighlightingMark::HighlightingMark(const CXCursor &cxCursor,
CXToken *cxToken,
CXTranslationUnit cxTranslationUnit)
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;

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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;

View File

@@ -44,10 +44,12 @@ class HighlightingMarksIterator : public std::iterator<std::forward_iterator_tag
public:
HighlightingMarksIterator(std::vector<CXCursor>::const_iterator cxCursorIterator,
CXToken *cxToken,
CXTranslationUnit cxTranslationUnit)
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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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));

View File

@@ -118,6 +118,7 @@ HEADERS += \
chunksreportedmonitor.h \
clangasyncjob-base.h \
diagnosticcontainer-matcher.h \
clangcompareoperators.h \
dummyclangipcclient.h \
mockclangcodemodelclient.h \
mockclangcodemodelserver.h