forked from qt-creator/qt-creator
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:
committed by
Nikolai Kosjar
parent
9d55d8485c
commit
63ae993bf2
@@ -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
|
||||
}
|
||||
|
@@ -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";
|
||||
}
|
||||
|
@@ -100,6 +100,7 @@ enum TextStyle : quint8 {
|
||||
C_ERROR_CONTEXT,
|
||||
|
||||
C_DECLARATION,
|
||||
C_OUTPUT_ARGUMENT,
|
||||
|
||||
C_LAST_STYLE_SENTINEL
|
||||
};
|
||||
|
@@ -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,
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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));
|
||||
|
@@ -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);
|
||||
|
@@ -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> ¤tOutputArgumentRanges)
|
||||
: currentOutputArgumentRanges(¤tOutputArgumentRanges),
|
||||
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 ¤tSourceRange) {
|
||||
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;
|
||||
|
@@ -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> ¤tOutputArgumentRanges);
|
||||
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;
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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> ¤tOutputArgumentRanges)
|
||||
: 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> ¤tOutputArgumentRanges;
|
||||
};
|
||||
|
||||
} // namespace ClangBackEnd
|
||||
|
40
tests/unit/unittest/clangcompareoperators.h
Normal file
40
tests/unit/unittest/clangcompareoperators.h
Normal 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);
|
||||
}
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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));
|
||||
|
@@ -118,6 +118,7 @@ HEADERS += \
|
||||
chunksreportedmonitor.h \
|
||||
clangasyncjob-base.h \
|
||||
diagnosticcontainer-matcher.h \
|
||||
clangcompareoperators.h \
|
||||
dummyclangipcclient.h \
|
||||
mockclangcodemodelclient.h \
|
||||
mockclangcodemodelserver.h
|
||||
|
Reference in New Issue
Block a user