diff options
author | Marco Bubke <marco.bubke@qt.io> | 2016-10-11 18:19:12 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2016-10-12 08:01:48 +0000 |
commit | 63ae993bf2a844d8f6b25b9733827a6ccd651be3 (patch) | |
tree | b3ae122133ee5d30d7d457f792fad304b2a79c10 | |
parent | 9d55d8485cda7077d1280f3335102ffd036240b5 (diff) | |
download | qt-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>
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> ¤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; 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> ¤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; }; 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> ¤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 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 |