diff --git a/src/libs/clangbackendipc/clangbackendipc_global.h b/src/libs/clangbackendipc/clangbackendipc_global.h index 544a5b15ac11c56b59065af32480f0033b6f60a5..c9851069b58e43282a0ee73e312f47f3e699442a 100644 --- a/src/libs/clangbackendipc/clangbackendipc_global.h +++ b/src/libs/clangbackendipc/clangbackendipc_global.h @@ -53,5 +53,28 @@ enum class DiagnosticSeverity // one to one mapping of the clang enum numbers Error = 3, Fatal = 4 }; + +enum class HighlightingType +{ + Invalid, + Keyword, + StringLiteral, + NumberLiteral, + Comment, + Function, + VirtualFunction, + Type, + LocalVariable, + Field, + GlobalVariable, + Enumeration, + Operator, + Preprocessor, + PreprocessorDefinition, + PreprocessorExpansion, + Label, + OutputArgument +}; + } #endif // CLANGBACKENDIPC_GLOBAL_H diff --git a/src/libs/sqlite/utf8string.cpp b/src/libs/sqlite/utf8string.cpp index b4492a9d198404ad447f02c70d56649d6b2f05b8..c8cbaea22302f1b17074daa665e23247d414bf56 100644 --- a/src/libs/sqlite/utf8string.cpp +++ b/src/libs/sqlite/utf8string.cpp @@ -158,6 +158,11 @@ bool Utf8String::endsWith(const Utf8String &text) const return byteArray.endsWith(text.byteArray); } +bool Utf8String::isNull() const +{ + return byteArray.isNull(); +} + bool Utf8String::isEmpty() const { return byteArray.isEmpty(); diff --git a/src/libs/sqlite/utf8string.h b/src/libs/sqlite/utf8string.h index 52c6f46758bc89953b1bccbc3c7d9ba72e4cf775..c6adfc9371626337fd97d6e85266f673bcec889c 100644 --- a/src/libs/sqlite/utf8string.h +++ b/src/libs/sqlite/utf8string.h @@ -86,6 +86,7 @@ public: bool startsWith(const char *text) const; bool startsWith(char character) const; bool endsWith(const Utf8String &text) const; + bool isNull() const; bool isEmpty() const; bool hasContent() const; diff --git a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri index 73aa363a95908410d5754e8f165fd0487dab6c13..93131082bf9087177c135290e4a310128dfd0617 100644 --- a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri +++ b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri @@ -25,7 +25,13 @@ HEADERS += $$PWD/clangipcserver.h \ $$PWD/diagnosticsetiterator.h \ $$PWD/clangfilesystemwatcher.h \ $$PWD/translationunitalreadyexistsexception.h \ - $$PWD/commandlinearguments.h + $$PWD/commandlinearguments.h \ + $$PWD/cursor.h \ + $$PWD/type.h \ + $$PWD/highlightinginformations.h \ + $$PWD/highlightinginformation.h \ + $$PWD/highlightinginformationsiterator.h \ + $$PWD/skippedsourceranges.h SOURCES += $$PWD/clangipcserver.cpp \ $$PWD/codecompleter.cpp \ @@ -51,4 +57,9 @@ SOURCES += $$PWD/clangipcserver.cpp \ $$PWD/fixit.cpp \ $$PWD/clangfilesystemwatcher.cpp \ $$PWD/translationunitalreadyexistsexception.cpp \ - $$PWD/commandlinearguments.cpp + $$PWD/commandlinearguments.cpp \ + $$PWD/cursor.cpp \ + $$PWD/type.cpp \ + $$PWD/highlightinginformations.cpp \ + $$PWD/highlightinginformation.cpp \ + $$PWD/skippedsourceranges.cpp diff --git a/src/tools/clangbackend/ipcsource/clangstring.cpp b/src/tools/clangbackend/ipcsource/clangstring.cpp index 200e83427066d8b3c344fd0e7330509a65790d74..5decaf15490a9bc4ebbc0f705167a6ab4993d1bb 100644 --- a/src/tools/clangbackend/ipcsource/clangstring.cpp +++ b/src/tools/clangbackend/ipcsource/clangstring.cpp @@ -61,6 +61,11 @@ ClangString &ClangString::operator=(ClangString &&other) return *this; } +const char *ClangString::cString() const +{ + return clang_getCString(cxString); +} + ClangString::ClangString(ClangString &&other) : cxString(std::move(other.cxString)) { @@ -70,7 +75,7 @@ ClangString::ClangString(ClangString &&other) ClangString::operator Utf8String() const { - return Utf8String(clang_getCString(cxString), -1); + return Utf8String(cString(), -1); } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangstring.h b/src/tools/clangbackend/ipcsource/clangstring.h index f18a61228219a98167f53235281766ba40555a8b..2db7b8ade0c705dc1217b1a9200160c456abf9e9 100644 --- a/src/tools/clangbackend/ipcsource/clangstring.h +++ b/src/tools/clangbackend/ipcsource/clangstring.h @@ -51,6 +51,8 @@ public: operator Utf8String() const; + const char *cString() const; + bool isNull() const; private: diff --git a/src/tools/clangbackend/ipcsource/cursor.cpp b/src/tools/clangbackend/ipcsource/cursor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ea5009d4df78cd2d331714be1acb566e07115ce --- /dev/null +++ b/src/tools/clangbackend/ipcsource/cursor.cpp @@ -0,0 +1,351 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "cursor.h" + +#include "clangstring.h" +#include "sourcelocation.h" +#include "sourcerange.h" + +#include <ostream> + +namespace ClangBackEnd { + +Cursor::Cursor() + : cxCursor(clang_getNullCursor()) +{ +} + +Cursor::Cursor(CXCursor cxCursor) + : cxCursor(cxCursor) +{ +} + +bool Cursor::isNull() const +{ + return clang_Cursor_isNull(cxCursor); +} + +bool Cursor::isValid() const +{ + return !clang_isInvalid(kind()); +} + +bool Cursor::isTranslationUnit() const +{ + return clang_isTranslationUnit(kind()); +} + +bool Cursor::isDefinition() const +{ + return clang_isCursorDefinition(cxCursor); +} + +bool Cursor::isDynamicCall() const +{ + return clang_Cursor_isDynamicCall(cxCursor); +} + +bool Cursor::isVirtualMethod() const +{ + return clang_CXXMethod_isVirtual(cxCursor); +} + +bool Cursor::isPureVirtualMethod() const +{ + return clang_CXXMethod_isPureVirtual(cxCursor); +} + +bool Cursor::isConstantMethod() const +{ + return clang_CXXMethod_isConst(cxCursor); +} + +bool Cursor::isStaticMethod() const +{ + return clang_CXXMethod_isStatic(cxCursor); +} + +bool Cursor::isCompoundType() const +{ + switch (kind()) { + case CXCursor_ClassDecl: + case CXCursor_StructDecl: + case CXCursor_UnionDecl: return true; + default: return false; + } +} + +bool Cursor::isDeclaration() const +{ + return clang_isDeclaration(kind()); +} + +bool Cursor::isLocalVariable() const +{ + switch (semanticParent().kind()) { + case CXCursor_FunctionDecl: + case CXCursor_CXXMethod: + case CXCursor_Constructor: + case CXCursor_Destructor: + case CXCursor_ConversionFunction: + case CXCursor_FunctionTemplate: + case CXCursor_ObjCInstanceMethodDecl: return true; + default: + return false; + } +} + +bool Cursor::hasFinalFunctionAttribute() const +{ + bool hasFinal = false; + + visit([&] (Cursor cursor, Cursor /*parent*/) { + if (cursor.kind() == CXCursor_CXXFinalAttr) { + hasFinal = true; + return CXChildVisit_Break; + } else { + return CXChildVisit_Recurse; + } + }); + + return hasFinal; +} + +bool Cursor::hasFinalClassAttribute() const +{ + bool hasFinal = false; + + visit([&] (Cursor cursor, Cursor /*parent*/) { + switch (cursor.kind()) { + case CXCursor_CXXFinalAttr: + hasFinal = true; + return CXChildVisit_Break; + case CXCursor_CXXMethod: + return CXChildVisit_Break; + default: + return CXChildVisit_Recurse; + } + }); + + return hasFinal; +} + +bool Cursor::isUnexposed() const +{ + return clang_isUnexposed(kind()); +} + +Utf8String Cursor::unifiedSymbolResolution() const +{ + return ClangString(clang_getCursorUSR(cxCursor)); +} + +Utf8String Cursor::mangling() const +{ + return ClangString(clang_Cursor_getMangling(cxCursor)); +} + +ClangString Cursor::spelling() const +{ + return ClangString(clang_getCursorSpelling(cxCursor)); +} + +Utf8String Cursor::displayName() const +{ + return ClangString(clang_getCursorDisplayName(cxCursor)); +} + +Utf8String Cursor::briefComment() const +{ + return ClangString(clang_Cursor_getBriefCommentText(cxCursor)); +} + +Utf8String Cursor::rawComment() const +{ + return ClangString(clang_Cursor_getRawCommentText(cxCursor)); +} + +int Cursor::argumentCount() const +{ + return clang_Cursor_getNumArguments(cxCursor); +} + +Type Cursor::type() const +{ + return clang_getCursorType(cxCursor); +} + +Type Cursor::nonPointerTupe() const +{ + auto typeResult = type(); + + if (typeResult.isPointer()) + typeResult = typeResult.pointeeType(); + + return typeResult; +} + +SourceLocation Cursor::sourceLocation() const +{ + return clang_getCursorLocation(cxCursor); +} + +SourceRange Cursor::sourceRange() const +{ + return clang_getCursorExtent(cxCursor); +} + +SourceRange Cursor::commentRange() const +{ + return clang_Cursor_getCommentRange(cxCursor); +} + +Cursor Cursor::definition() const +{ + return clang_getCursorDefinition(cxCursor); +} + +Cursor Cursor::canonical() const +{ + return clang_getCanonicalCursor(cxCursor); +} + +Cursor Cursor::referenced() const +{ + return clang_getCursorReferenced(cxCursor); +} + +Cursor Cursor::semanticParent() const +{ + return clang_getCursorSemanticParent(cxCursor); +} + +Cursor Cursor::lexicalParent() const +{ + return clang_getCursorLexicalParent(cxCursor); +} + +Cursor Cursor::functionBaseDeclaration() const +{ + auto functionBaseCursor = functionBase(); + + if (functionBaseCursor.isValid()) + return functionBaseCursor.nonPointerTupe().canonical().declaration(); + else + return semanticParent().semanticParent(); +} + +Cursor Cursor::functionBase() const +{ + Cursor functionBaseCursor; + + visit([&] (Cursor cursor, Cursor /*parentCursor*/) { + switch (cursor.kind()) { + case CXCursor_DeclRefExpr: + functionBaseCursor = cursor; ; + return CXChildVisit_Break; + default: + return CXChildVisit_Recurse; + } + }); + + return functionBaseCursor; +} + +Cursor Cursor::argument(int index) const +{ + return clang_Cursor_getArgument(cxCursor, index); +} +namespace { +void collectOutputArguments(const Cursor &callExpression, + std::vector<Cursor> &outputArguments) +{ + auto callExpressionType = callExpression.referenced().type(); + auto argumentCount = callExpression.argumentCount(); + outputArguments.reserve(argumentCount); + + for (int argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex) { + auto argument = callExpression.argument(argumentIndex); + auto argumentType = callExpressionType.argument(argumentIndex); + + if (!argument.isUnexposed() && argumentType.isOutputParameter()) + outputArguments.push_back(callExpression.argument(argumentIndex)); + } +} +} + +std::vector<Cursor> Cursor::outputArguments() const +{ + std::vector<Cursor> outputArguments; + + if (kind() == CXCursor_CallExpr) + collectOutputArguments(*this, outputArguments); + + return outputArguments; +} + +CXCursorKind Cursor::kind() const +{ + return clang_getCursorKind(cxCursor); +} + +bool operator==(const Cursor &first, const Cursor &second) +{ + return clang_equalCursors(first.cxCursor, second.cxCursor); +} + +void PrintTo(CXCursorKind cursorKind, ::std::ostream *os) +{ + ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursorKind)); + *os << cursorKindSpelling.cString(); +} + +void PrintTo(const Cursor &cursor, ::std::ostream*os) +{ + if (cursor.isValid()) { + ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursor.kind())); + *os << cursorKindSpelling.cString() << " "; + + auto identifier = cursor.displayName(); + if (identifier.hasContent()) { + *os << "\"" + << identifier.constData() + << "\": "; + } + + PrintTo(cursor.sourceLocation(), os); + } else { + *os << "Invalid cursor!"; + } +} + +} // namespace ClangBackEnd + diff --git a/src/tools/clangbackend/ipcsource/cursor.h b/src/tools/clangbackend/ipcsource/cursor.h new file mode 100644 index 0000000000000000000000000000000000000000..d4256401e5d419f4a96c502246db0e0860366eee --- /dev/null +++ b/src/tools/clangbackend/ipcsource/cursor.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_CURSOR_H +#define CLANGBACKEND_CURSOR_H + +#include "type.h" + +#include <clang-c/Index.h> + +#include <iosfwd> + +#include <vector> + +class Utf8String; + +namespace ClangBackEnd { + +class SourceLocation; +class SourceRange; +class ClangString; + +class Cursor +{ + friend class Type; + friend bool operator==(const Cursor &first, const Cursor &second); +public: + Cursor(); + Cursor(CXCursor cxCursor); + + bool isNull() const; + bool isValid() const; + + bool isTranslationUnit() const; + bool isDefinition() const; + bool isDynamicCall() const; + bool isVirtualMethod() const; + bool isPureVirtualMethod() const; + bool isConstantMethod() const; + bool isStaticMethod() const; + bool isCompoundType() const; + bool isDeclaration() const; + bool isLocalVariable() const; + bool hasFinalFunctionAttribute() const; + bool hasFinalClassAttribute() const; + bool isUnexposed() const; + + Utf8String unifiedSymbolResolution() const; + Utf8String mangling() const; + ClangString spelling() const; + Utf8String displayName() const; + Utf8String briefComment() const; + Utf8String rawComment() const; + int argumentCount() const; + + Type type() const; + Type nonPointerTupe() const; + + SourceLocation sourceLocation() const; + SourceRange sourceRange() const; + SourceRange commentRange() const; + + Cursor definition() const; + Cursor canonical() const; + Cursor alias() const; + Cursor referenced() const; + Cursor semanticParent() const; + Cursor lexicalParent() const; + Cursor functionBaseDeclaration() const; + Cursor functionBase() const; + Cursor argument(int index) const; + std::vector<Cursor> outputArguments() const; + + CXCursorKind kind() const; + + template <class VisitorCallback> + void visit(VisitorCallback visitorCallback) const; + +private: + CXCursor cxCursor; +}; + +template <class VisitorCallback> +void Cursor::visit(VisitorCallback visitorCallback) const +{ + auto visitor = [] (CXCursor cursor, CXCursor parent, CXClientData lambda) -> CXChildVisitResult { + auto &visitorCallback = *static_cast<VisitorCallback*>(lambda); + + return visitorCallback(cursor, parent); + }; + + clang_visitChildren(cxCursor, visitor, &visitorCallback); +} + +bool operator==(const Cursor &first, const Cursor &second); + +void PrintTo(CXCursorKind cursorKind, ::std::ostream *os); +void PrintTo(const Cursor &cursor, ::std::ostream* os); +} // namespace ClangBackEnd + + +#endif // CLANGBACKEND_CURSOR_H diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..808a0407d14e930e3ee27b82d8e04f6638a9afa9 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "clangstring.h" +#include "cursor.h" +#include "highlightinginformation.h" +#include "sourcelocation.h" +#include "sourcerange.h" + +#include <cstring> +#include <ostream> + +#include <QDebug> + +namespace ClangBackEnd { + +HighlightingInformation::HighlightingInformation(const CXCursor &cxCursor, + CXToken *cxToken, + CXTranslationUnit cxTranslationUnit) +{ + 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(); + length = end.offset() - start.offset(); + type = kind(cxToken, originalCursor); +} + +HighlightingInformation::HighlightingInformation(uint line, uint column, uint length, HighlightingType type) + : line(line), + column(column), + length(length), + type(type) +{ +} + +bool HighlightingInformation::hasType(HighlightingType type) const +{ + return this->type == type; +} + +bool HighlightingInformation::hasFunctionArguments() const +{ + return originalCursor.argumentCount() > 0; +} + +QVector<HighlightingInformation> HighlightingInformation::outputFunctionArguments() const +{ + QVector<HighlightingInformation> outputFunctionArguments; + + return outputFunctionArguments; +} + +namespace { + +bool isFinalFunction(const Cursor &cursor) +{ + auto referencedCursor = cursor.referenced(); + if (referencedCursor.hasFinalFunctionAttribute()) + return true; + + else return false; +} + +bool isFunctionInFinalClass(const Cursor &cursor) +{ + auto functionBase = cursor.functionBaseDeclaration(); + if (functionBase.isValid() && functionBase.hasFinalClassAttribute()) + return true; + + return false; +} +} + +HighlightingType HighlightingInformation::memberReferenceKind(const Cursor &cursor) const +{ + if (cursor.isDynamicCall()) { + if (isFinalFunction(cursor) || isFunctionInFinalClass(cursor)) + return HighlightingType::Function; + else + return HighlightingType::VirtualFunction; + } + + return identifierKind(cursor.referenced()); + +} + +HighlightingType HighlightingInformation::referencedTypeKind(const Cursor &cursor) const +{ + const Cursor referencedCursor = cursor.referenced(); + + switch (referencedCursor.kind()) { + case CXCursor_ClassDecl: + case CXCursor_StructDecl: + case CXCursor_UnionDecl: + case CXCursor_TemplateTypeParameter: + case CXCursor_TypeAliasDecl: return HighlightingType::Type; + case CXCursor_EnumDecl: return HighlightingType::Enumeration; + default: return HighlightingType::Invalid; + } + + Q_UNREACHABLE(); +} + +HighlightingType HighlightingInformation::variableKind(const Cursor &cursor) const +{ + if (cursor.isLocalVariable()) + return HighlightingType::LocalVariable; + else + return HighlightingType::GlobalVariable; +} + +bool HighlightingInformation::isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const +{ + return cursor.isVirtualMethod() + && (originalCursor.isDeclaration() || originalCursor.isDefinition()); +} +namespace { +bool isNotFinalFunction(const Cursor &cursor) +{ + return !cursor.hasFinalFunctionAttribute(); +} + +} +bool HighlightingInformation::isRealDynamicCall(const Cursor &cursor) const +{ + + return originalCursor.isDynamicCall() && isNotFinalFunction(cursor); +} + +HighlightingType HighlightingInformation::functionKind(const Cursor &cursor) const +{ + if (isRealDynamicCall(cursor) || isVirtualMethodDeclarationOrDefinition(cursor)) + return HighlightingType::VirtualFunction; + else + return HighlightingType::Function; +} + +HighlightingType HighlightingInformation::identifierKind(const Cursor &cursor) const +{ + switch (cursor.kind()) { + case CXCursor_Destructor: + case CXCursor_Constructor: + case CXCursor_FunctionDecl: + case CXCursor_CallExpr: + case CXCursor_CXXMethod: return functionKind(cursor); + case CXCursor_NonTypeTemplateParameter: + case CXCursor_ParmDecl: return HighlightingType::LocalVariable; + case CXCursor_VarDecl: return variableKind(cursor); + case CXCursor_DeclRefExpr: return identifierKind(cursor.referenced()); + case CXCursor_MemberRefExpr: return memberReferenceKind(cursor); + case CXCursor_FieldDecl: + case CXCursor_MemberRef: + case CXCursor_ObjCIvarDecl: + case CXCursor_ObjCPropertyDecl: + case CXCursor_ObjCClassMethodDecl: + case CXCursor_ObjCInstanceMethodDecl: + case CXCursor_ObjCSynthesizeDecl: + case CXCursor_ObjCDynamicDecl: return HighlightingType::Field; + case CXCursor_TypeRef: return referencedTypeKind(cursor); + case CXCursor_ClassDecl: + case CXCursor_TemplateTypeParameter: + case CXCursor_TemplateTemplateParameter: + case CXCursor_UnionDecl: + case CXCursor_StructDecl: + case CXCursor_TemplateRef: + case CXCursor_Namespace: + case CXCursor_NamespaceRef: + case CXCursor_NamespaceAlias: + case CXCursor_TypeAliasDecl: + case CXCursor_ClassTemplate: + case CXCursor_UnexposedDecl: + case CXCursor_CXXStaticCastExpr: + case CXCursor_CXXReinterpretCastExpr: + case CXCursor_ObjCCategoryDecl: + case CXCursor_ObjCCategoryImplDecl: + case CXCursor_ObjCImplementationDecl: + case CXCursor_ObjCInterfaceDecl: + case CXCursor_ObjCProtocolDecl: + case CXCursor_ObjCProtocolRef: + case CXCursor_ObjCClassRef: + case CXCursor_ObjCSuperClassRef: return HighlightingType::Type; + case CXCursor_FunctionTemplate: return HighlightingType::Function; + case CXCursor_EnumConstantDecl: return HighlightingType::Enumeration; + case CXCursor_EnumDecl: return referencedTypeKind(cursor); + case CXCursor_PreprocessingDirective: return HighlightingType::Preprocessor; + case CXCursor_MacroExpansion: return HighlightingType::PreprocessorExpansion; + case CXCursor_MacroDefinition: return HighlightingType::PreprocessorDefinition; + case CXCursor_InclusionDirective: return HighlightingType::StringLiteral; + case CXCursor_LabelRef: + case CXCursor_LabelStmt: return HighlightingType::Label; + default: return HighlightingType::Invalid; + } + + Q_UNREACHABLE(); +} + +namespace { +HighlightingType literalKind(const Cursor &cursor) +{ + switch (cursor.kind()) { + case CXCursor_CharacterLiteral: + case CXCursor_StringLiteral: + case CXCursor_ObjCStringLiteral: return HighlightingType::StringLiteral; + case CXCursor_IntegerLiteral: + case CXCursor_ImaginaryLiteral: + case CXCursor_FloatingLiteral: return HighlightingType::NumberLiteral; + default: return HighlightingType::Invalid; + } + + Q_UNREACHABLE(); +} + + +HighlightingType punctationKind(const Cursor &cursor) +{ + switch (cursor.kind()) { + case CXCursor_DeclRefExpr: return HighlightingType::Operator; + default: return HighlightingType::Invalid; + } +} + +} +HighlightingType HighlightingInformation::kind(CXToken *cxToken, const Cursor &cursor) const +{ + auto cxTokenKind = clang_getTokenKind(*cxToken); + + switch (cxTokenKind) { + case CXToken_Keyword: return HighlightingType::Keyword; + case CXToken_Punctuation: return punctationKind(cursor); + case CXToken_Identifier: return identifierKind(cursor); + case CXToken_Comment: return HighlightingType::Comment; + case CXToken_Literal: return literalKind(cursor); + } + + Q_UNREACHABLE(); +} + +void PrintTo(const HighlightingInformation& information, ::std::ostream *os) +{ + *os << "type: "; + PrintTo(information.type, os); + *os << " line: " << information.line + << " column: " << information.column + << " length: " << information.length; +} + +void PrintTo(HighlightingType highlightingType, std::ostream *os) +{ + switch (highlightingType) { + case HighlightingType::Invalid: *os << "Invalid"; break; + case HighlightingType::Comment: *os << "Comment"; break; + case HighlightingType::Keyword: *os << "Keyword"; break; + case HighlightingType::StringLiteral: *os << "StringLiteral"; break; + case HighlightingType::NumberLiteral: *os << "NumberLiteral"; break; + case HighlightingType::Function: *os << "Function"; break; + case HighlightingType::VirtualFunction: *os << "VirtualFunction"; break; + case HighlightingType::Type: *os << "Type"; break; + case HighlightingType::LocalVariable: *os << "LocalVariable"; break; + case HighlightingType::GlobalVariable: *os << "GlobalVariable"; break; + case HighlightingType::Field: *os << "Field"; break; + case HighlightingType::Enumeration: *os << "Enumeration"; break; + case HighlightingType::Operator: *os << "Operator"; break; + case HighlightingType::Preprocessor: *os << "Preprocessor"; break; + case HighlightingType::Label: *os << "Label"; break; + case HighlightingType::OutputArgument: *os << "OutputArgument"; break; + case HighlightingType::PreprocessorDefinition: *os << "PreprocessorDefinition"; break; + case HighlightingType::PreprocessorExpansion: *os << "PreprocessorExpansion"; break; + } +} + + + +} // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.h b/src/tools/clangbackend/ipcsource/highlightinginformation.h new file mode 100644 index 0000000000000000000000000000000000000000..ee327b62135ceb1639915e4fe55b8a712ad77f31 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/highlightinginformation.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_HIGHLIGHTINGINFORMATION_H +#define CLANGBACKEND_HIGHLIGHTINGINFORMATION_H + +#include <clangbackendipc_global.h> + +#include "cursor.h" + +#include <clang-c/Index.h> + +namespace ClangBackEnd { + +class HighlightingInformation +{ + friend bool operator==(const HighlightingInformation &first, const HighlightingInformation &second); + friend void PrintTo(const HighlightingInformation& highlightingInformation, ::std::ostream *os); + +public: + HighlightingInformation(const CXCursor &cxCursor, CXToken *cxToken, CXTranslationUnit cxTranslationUnit); + HighlightingInformation(uint line, uint column, uint length, HighlightingType type); + + bool hasType(HighlightingType type) const; + bool hasFunctionArguments() const; + QVector<HighlightingInformation> outputFunctionArguments() const; + +private: + HighlightingType identifierKind(const Cursor &cursor) const; + HighlightingType referencedTypeKind(const Cursor &cursor) const; + HighlightingType variableKind(const Cursor &cursor) const; + bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const; + HighlightingType functionKind(const Cursor &cursor) const; + HighlightingType memberReferenceKind(const Cursor &cursor) const; + HighlightingType kind(CXToken *cxToken, const Cursor &cursor) const; + bool isRealDynamicCall(const Cursor &cursor) const; + +private: + Cursor originalCursor; + uint line; + uint column; + uint length; + HighlightingType type; +}; + +void PrintTo(const HighlightingInformation& highlightingInformation, ::std::ostream *os); +void PrintTo(HighlightingType highlightingType, ::std::ostream *os); + +inline bool operator==(const HighlightingInformation &first, const HighlightingInformation &second) +{ + return first.line == second.line + && first.column == second.column + && first.length == second.length + && first.type == second.type; +} + +} // namespace ClangBackEnd + +#endif // CLANGBACKEND_HIGHLIGHTINGINFORMATION_H diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.cpp b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7157768fd6868d98bc9558cb4ab6fb2f4fec651 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "highlightinginformations.h" + +namespace ClangBackEnd { + +HighlightingInformations::HighlightingInformations(CXTranslationUnit cxTranslationUnit, CXToken *tokens, uint tokensCount) + : cxTranslationUnit(cxTranslationUnit), + cxToken(tokens), + cxTokenCount(tokensCount) +{ + cxCursor.resize(tokensCount); + clang_annotateTokens(cxTranslationUnit, cxToken, cxTokenCount, cxCursor.data()); +} + +HighlightingInformations::~HighlightingInformations() +{ + clang_disposeTokens(cxTranslationUnit, cxToken, cxTokenCount); +} + +HighlightingInformations::const_iterator HighlightingInformations::begin() const +{ + return const_iterator(cxCursor.cbegin(), cxToken, cxTranslationUnit); +} + +HighlightingInformations::const_iterator HighlightingInformations::end() const +{ + return const_iterator(cxCursor.cend(), cxToken + cxTokenCount, cxTranslationUnit); +} + +bool HighlightingInformations::isEmpty() const +{ + return cxTokenCount == 0; +} + +bool ClangBackEnd::HighlightingInformations::isNull() const +{ + return cxToken == nullptr; +} + +uint HighlightingInformations::size() const +{ + return cxTokenCount; +} + +HighlightingInformation HighlightingInformations::operator[](size_t index) const +{ + return HighlightingInformation(cxCursor[index], cxToken + index, cxTranslationUnit); +} + +} // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.h b/src/tools/clangbackend/ipcsource/highlightinginformations.h new file mode 100644 index 0000000000000000000000000000000000000000..2c7b8ce9bbf12fb7e4ce300c4f2f405559bbf7b4 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/highlightinginformations.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_HIGHLIGHTINGINFORMATIONS_H +#define CLANGBACKEND_HIGHLIGHTINGINFORMATIONS_H + +#include "highlightinginformationsiterator.h" + +#include <clang-c/Index.h> + +#include <vector> + +namespace ClangBackEnd { + +using uint = unsigned int; + +class HighlightingInformations +{ +public: + using const_iterator = HighlightingInformationsIterator; + using value_type = HighlightingInformation; + +public: + HighlightingInformations() = default; + HighlightingInformations(CXTranslationUnit cxTranslationUnit, CXToken *tokens, uint tokensCount); + ~HighlightingInformations(); + + bool isEmpty() const; + bool isNull() const; + uint size() const; + + HighlightingInformation operator[](size_t index) const; + + const_iterator begin() const; + const_iterator end() const; + +private: + CXTranslationUnit cxTranslationUnit = nullptr; + CXToken *const cxToken = nullptr; + const uint cxTokenCount = 0; + + std::vector<CXCursor> cxCursor; +}; + +} // namespace ClangBackEnd + +#endif // CLANGBACKEND_HIGHLIGHTINGINFORMATIONS_H diff --git a/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h b/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h new file mode 100644 index 0000000000000000000000000000000000000000..53f540970e60347cd452b7499de503b496ef9888 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef HIGHLIGHTINGINFORMATIONSITERATOR_H +#define HIGHLIGHTINGINFORMATIONSITERATOR_H + +#include "highlightinginformation.h" + +#include <iterator> +#include <vector> + +#include <clang-c/Index.h> + +namespace ClangBackEnd { + +using uint = unsigned int; + +class DiagnosticSet; +class Diagnostic; + +class HighlightingInformationsIterator : public std::iterator<std::forward_iterator_tag, HighlightingInformation, uint> +{ +public: + HighlightingInformationsIterator(std::vector<CXCursor>::const_iterator cxCursorIterator, + CXToken *cxToken, + CXTranslationUnit cxTranslationUnit) + : cxCursorIterator(cxCursorIterator), + cxToken(cxToken), + cxTranslationUnit(cxTranslationUnit) + {} + + HighlightingInformationsIterator(const HighlightingInformationsIterator &other) + : cxCursorIterator(other.cxCursorIterator) + {} + + HighlightingInformationsIterator& operator++() + { + ++cxCursorIterator; + ++cxToken; + + return *this; + } + + HighlightingInformationsIterator operator++(int) + { + return HighlightingInformationsIterator(cxCursorIterator++, cxToken++, cxTranslationUnit); + } + + bool operator==(HighlightingInformationsIterator other) const + { + return cxCursorIterator == other.cxCursorIterator; + } + + bool operator!=(HighlightingInformationsIterator other) const + { + return cxCursorIterator != other.cxCursorIterator; + } + + HighlightingInformation operator*() + { + return HighlightingInformation(*cxCursorIterator, cxToken, cxTranslationUnit); + } + +private: + std::vector<CXCursor>::const_iterator cxCursorIterator; + CXToken *cxToken; + CXTranslationUnit cxTranslationUnit; +}; + +} // namespace ClangBackEnd + +#endif // HIGHLIGHTINGINFORMATIONSITERATOR_H diff --git a/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp b/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a39131474b72ac13e1acc88f7461815fd7864c0 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ +#include "skippedsourceranges.h" + +#include "sourcerangecontainer.h" + +#include <QVector> + +#include <algorithm> + +namespace ClangBackEnd { + +SkippedSourceRanges::SkippedSourceRanges(CXTranslationUnit cxTranslationUnit, const char *filePath) +{ + cxSkippedSourceRanges = clang_getSkippedRanges(cxTranslationUnit, + clang_getFile(cxTranslationUnit, + filePath)); +} + +SkippedSourceRanges::~SkippedSourceRanges() +{ + clang_disposeSourceRangeList(cxSkippedSourceRanges); +} + +SkippedSourceRanges &SkippedSourceRanges::operator=(SkippedSourceRanges &&other) +{ + if (this != &other) { + cxSkippedSourceRanges = other.cxSkippedSourceRanges; + other.cxSkippedSourceRanges = nullptr; + } + + return *this; +} + +std::vector<SourceRange> SkippedSourceRanges::sourceRanges() const +{ + std::vector<SourceRange> sourceRanges; + + auto sourceRangeCount = cxSkippedSourceRanges->count; + sourceRanges.reserve(sourceRangeCount); + + std::copy(cxSkippedSourceRanges->ranges, + cxSkippedSourceRanges->ranges + sourceRangeCount, + std::back_inserter(sourceRanges)); + + return sourceRanges; +} + +QVector<SourceRangeContainer> SkippedSourceRanges::toSourceRangeContainers() const +{ + QVector<SourceRangeContainer> sourceRangeContainers; + + auto sourceRanges = this->sourceRanges(); + + std::copy(sourceRanges.cbegin(), + sourceRanges.cend(), + std::back_inserter(sourceRangeContainers)); + + return sourceRangeContainers; +} + +ClangBackEnd::SkippedSourceRanges::operator QVector<SourceRangeContainer>() const +{ + return toSourceRangeContainers(); +} + +SkippedSourceRanges::SkippedSourceRanges(SkippedSourceRanges &&other) + : cxSkippedSourceRanges(other.cxSkippedSourceRanges) +{ + other.cxSkippedSourceRanges = nullptr; +} + +} // namespace ClangBackEnd + diff --git a/src/tools/clangbackend/ipcsource/skippedsourceranges.h b/src/tools/clangbackend/ipcsource/skippedsourceranges.h new file mode 100644 index 0000000000000000000000000000000000000000..8d38bc50c9eac95e301c5d5e0593cf703993ed41 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/skippedsourceranges.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ +#ifndef CLANGBACKEND_SKIPPEDSOURCERANGES_H +#define CLANGBACKEND_SKIPPEDSOURCERANGES_H + +#include "sourcerange.h" + +namespace ClangBackEnd { + +class SourceRangeContainer; + +class SkippedSourceRanges +{ +public: + SkippedSourceRanges(CXTranslationUnit TranslationUnit, const char *filePath); + ~SkippedSourceRanges(); + + SkippedSourceRanges(const SkippedSourceRanges &) = delete; + const SkippedSourceRanges &operator=(const SkippedSourceRanges &) = delete; + + SkippedSourceRanges(SkippedSourceRanges &&); + SkippedSourceRanges &operator=(SkippedSourceRanges &&); + + std::vector<SourceRange> sourceRanges() const; + + QVector<SourceRangeContainer> toSourceRangeContainers() const; + + operator QVector<SourceRangeContainer>() const; + +private: + CXSourceRangeList *cxSkippedSourceRanges; +}; + +} // namespace ClangBackEnd + +#endif // CLANGBACKEND_SKIPPEDSOURCERANGES_H diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.cpp b/src/tools/clangbackend/ipcsource/sourcelocation.cpp index 8a7cd0d8716adf4e30f249891becf74bc56df0ba..e04f44c7d88a8129c9e40ba00dbd0b13ea5c1fd5 100644 --- a/src/tools/clangbackend/ipcsource/sourcelocation.cpp +++ b/src/tools/clangbackend/ipcsource/sourcelocation.cpp @@ -31,6 +31,7 @@ #include "sourcelocation.h" #include "clangstring.h" +#include "translationunit.h" #include <utf8string.h> @@ -39,6 +40,11 @@ namespace ClangBackEnd { +SourceLocation::SourceLocation() + : cxSourceLocation(clang_getNullLocation()) +{ +} + const Utf8String &SourceLocation::filePath() const { return filePath_; @@ -65,6 +71,7 @@ SourceLocationContainer SourceLocation::toSourceLocationContainer() const } SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation) + : cxSourceLocation(cxSourceLocation) { CXFile cxFile; @@ -77,10 +84,37 @@ SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation) filePath_ = ClangString(clang_getFileName(cxFile)); } +SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit, + const Utf8String &filePath, + uint line, + uint column) + : cxSourceLocation(clang_getLocation(cxTranslationUnit, + clang_getFile(cxTranslationUnit, + filePath.constData()), + line, + column)), + filePath_(filePath), + line_(line) +{ +} + +bool operator==(const SourceLocation &first, const SourceLocation &second) +{ + return clang_equalLocations(first.cxSourceLocation, second.cxSourceLocation); +} + +SourceLocation::operator CXSourceLocation() const +{ + return cxSourceLocation; +} + void PrintTo(const SourceLocation &sourceLocation, std::ostream *os) { - *os << sourceLocation.filePath().constData() - << ", line: " << sourceLocation.line() + auto filePath = sourceLocation.filePath(); + if (filePath.hasContent()) + *os << filePath.constData() << ", "; + + *os << "line: " << sourceLocation.line() << ", column: "<< sourceLocation.column() << ", offset: "<< sourceLocation.offset(); } diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.h b/src/tools/clangbackend/ipcsource/sourcelocation.h index 3ee500623b84f4d8ace06515a1d95f3119f41cc2..83ba6c77c9c8230d5f0d9e6fccd5a9f3a2af716a 100644 --- a/src/tools/clangbackend/ipcsource/sourcelocation.h +++ b/src/tools/clangbackend/ipcsource/sourcelocation.h @@ -38,13 +38,19 @@ namespace ClangBackEnd { class SourceLocationContainer; +class TranslationUnit; class SourceLocation { friend class Diagnostic; friend class SourceRange; + friend class TranslationUnit; + friend class Cursor; + friend bool operator==(const SourceLocation &first, const SourceLocation &second); public: + SourceLocation(); + const Utf8String &filePath() const; uint line() const; uint column() const; @@ -54,14 +60,23 @@ public: private: SourceLocation(CXSourceLocation cxSourceLocation); + SourceLocation(CXTranslationUnit cxTranslationUnit, + const Utf8String &filePath, + uint line, + uint column); + + operator CXSourceLocation() const; private: + CXSourceLocation cxSourceLocation; Utf8String filePath_; - uint line_; - uint column_; - uint offset_; + uint line_ = 0; + uint column_ = 0; + uint offset_ = 0; }; +bool operator==(const SourceLocation &first, const SourceLocation &second); + void PrintTo(const SourceLocation &sourceLocation, ::std::ostream* os); } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/sourcerange.cpp b/src/tools/clangbackend/ipcsource/sourcerange.cpp index 7375988b2bd7237790ab6f3da927cb4d41540582..f069edc9cb152f39ecc2024736d82980765b7de0 100644 --- a/src/tools/clangbackend/ipcsource/sourcerange.cpp +++ b/src/tools/clangbackend/ipcsource/sourcerange.cpp @@ -32,6 +32,8 @@ #include <sourcerangecontainer.h> +#include <ostream> + namespace ClangBackEnd { SourceRange::SourceRange() @@ -39,6 +41,11 @@ SourceRange::SourceRange() { } +SourceRange::SourceRange(const SourceLocation &start, const SourceLocation &end) + : cxSourceRange(clang_getRange(start, end)) +{ +} + bool SourceRange::isNull() const { return clang_Range_isNull(cxSourceRange); @@ -65,10 +72,33 @@ SourceRangeContainer SourceRange::toSourceRangeContainer() const end().toSourceLocationContainer()); } +ClangBackEnd::SourceRange::operator SourceRangeContainer() const +{ + return toSourceRangeContainer(); +} + +ClangBackEnd::SourceRange::operator CXSourceRange() const +{ + return cxSourceRange; +} + SourceRange::SourceRange(CXSourceRange cxSourceRange) : cxSourceRange(cxSourceRange) { } +bool operator==(const SourceRange &first, const SourceRange &second) +{ + return clang_equalRanges(first.cxSourceRange, second.cxSourceRange); +} + +void PrintTo(const SourceRange &sourceRange, ::std::ostream* os) +{ + *os << "["; + PrintTo(sourceRange.start(), os); + *os << ", "; + PrintTo(sourceRange.end(), os); + *os << "]"; +} } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/sourcerange.h b/src/tools/clangbackend/ipcsource/sourcerange.h index 3c80e4e040db381747a8b5b9c2b340426b89ee0f..f9b786cf4aad2b546df11f5a9ebb5afe01f73f26 100644 --- a/src/tools/clangbackend/ipcsource/sourcerange.h +++ b/src/tools/clangbackend/ipcsource/sourcerange.h @@ -41,9 +41,14 @@ class SourceRange { friend class Diagnostic; friend class FixIt; + friend class Cursor; + friend class HighlightingInformation; + friend bool operator==(const SourceRange &first, const SourceRange &second); public: SourceRange(); + SourceRange(CXSourceRange cxSourceRange); + SourceRange(const SourceLocation &start, const SourceLocation &end); bool isNull() const; bool isValid() const; @@ -53,13 +58,15 @@ public: SourceRangeContainer toSourceRangeContainer() const; -private: - SourceRange(CXSourceRange cxSourceRange); + operator CXSourceRange() const; + operator SourceRangeContainer() const; private: CXSourceRange cxSourceRange; }; +bool operator==(const SourceRange &first, const SourceRange &second); +void PrintTo(const SourceRange &sourceRange, ::std::ostream* os); } // namespace ClangBackEnd #endif // CLANGBACKEND_SOURCERANGE_H diff --git a/src/tools/clangbackend/ipcsource/translationunit.cpp b/src/tools/clangbackend/ipcsource/translationunit.cpp index 88e917010f6df50ad5eb1cd9b5f91c26915bfcd4..8769f7caef3f9b8cceccb204f33159a0df32330b 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.cpp +++ b/src/tools/clangbackend/ipcsource/translationunit.cpp @@ -30,13 +30,17 @@ #include "translationunit.h" +#include "cursor.h" #include "clangstring.h" #include "codecompleter.h" #include "commandlinearguments.h" #include "diagnosticcontainer.h" #include "diagnosticset.h" #include "projectpart.h" +#include "skippedsourceranges.h" #include "sourcelocation.h" +#include "sourcerange.h" +#include "highlightinginformations.h" #include "translationunitfilenotexitexception.h" #include "translationunitisnullexception.h" #include "translationunitparseerrorexception.h" @@ -245,6 +249,53 @@ void TranslationUnit::setDirtyIfDependencyIsMet(const Utf8String &filePath) } } +SourceLocation TranslationUnit::sourceLocationAt(uint line, uint column) const +{ + return SourceLocation(cxTranslationUnit(), filePath(), line, column); +} + +SourceLocation TranslationUnit::sourceLocationAt(const Utf8String &filePath, uint line, uint column) const +{ + return SourceLocation(cxTranslationUnit(), filePath, line, column); +} + +SourceRange TranslationUnit::sourceRange(uint fromLine, uint fromColumn, uint toLine, uint toColumn) const +{ + return SourceRange(sourceLocationAt(fromLine, fromColumn), + sourceLocationAt(toLine, toColumn)); +} + +Cursor TranslationUnit::cursorAt(uint line, uint column) const +{ + return clang_getCursor(cxTranslationUnit(), sourceLocationAt(line, column)); +} + +Cursor TranslationUnit::cursorAt(const Utf8String &filePath, uint line, uint column) const +{ + return clang_getCursor(cxTranslationUnit(), sourceLocationAt(filePath, line, column)); +} + +Cursor TranslationUnit::cursor() const +{ + return clang_getTranslationUnitCursor(cxTranslationUnit()); +} + +HighlightingInformations TranslationUnit::highlightingInformationsInRange(const SourceRange &range) const +{ + CXToken *cxTokens = 0; + uint cxTokensCount = 0; + auto translationUnit = cxTranslationUnit(); + + clang_tokenize(translationUnit, range, &cxTokens, &cxTokensCount); + + return HighlightingInformations(translationUnit, cxTokens, cxTokensCount); +} + +SkippedSourceRanges TranslationUnit::skippedSourceRanges() const +{ + return SkippedSourceRanges(cxTranslationUnit(), d->filePath.constData()); +} + void TranslationUnit::checkIfNull() const { if (isNull()) @@ -380,7 +431,8 @@ uint TranslationUnit::defaultOptions() { return CXTranslationUnit_CacheCompletionResults | CXTranslationUnit_PrecompiledPreamble - | CXTranslationUnit_IncludeBriefCommentsInCodeCompletion; + | CXTranslationUnit_IncludeBriefCommentsInCodeCompletion + | CXTranslationUnit_DetailedPreprocessingRecord; } uint TranslationUnit::unsavedFilesCount() const diff --git a/src/tools/clangbackend/ipcsource/translationunit.h b/src/tools/clangbackend/ipcsource/translationunit.h index e44852e47394d144c73355073b7d5526d51ecba2..fd3831cb3e04148f61d4168ab4d9739d25d338fe 100644 --- a/src/tools/clangbackend/ipcsource/translationunit.h +++ b/src/tools/clangbackend/ipcsource/translationunit.h @@ -52,8 +52,13 @@ class ProjectPart; class DiagnosticContainer; class DiagnosticSet; class FileContainer; +class HighlightingInformations; class TranslationUnits; class CommandLineArguments; +class Cursor; +class SourceLocation; +class SourceRange; +class SkippedSourceRanges; using time_point = std::chrono::steady_clock::time_point; @@ -111,6 +116,19 @@ public: CommandLineArguments commandLineArguments() const; + SourceLocation sourceLocationAt(uint line, uint column) const; + SourceLocation sourceLocationAt(const Utf8String &filePath, uint line, uint column) const; + + SourceRange sourceRange(uint fromLine, uint fromColumn, uint toLine, uint toColumn) const; + + Cursor cursorAt(uint line, uint column) const; + Cursor cursorAt(const Utf8String &filePath, uint line, uint column) const; + Cursor cursor() const; + + HighlightingInformations highlightingInformationsInRange(const SourceRange &range) const; + + SkippedSourceRanges skippedSourceRanges() const; + private: void checkIfNull() const; void checkIfFileExists() const; diff --git a/src/tools/clangbackend/ipcsource/type.cpp b/src/tools/clangbackend/ipcsource/type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1f78e44eb2d6cb0651ab633d3bfbe9b547db452 --- /dev/null +++ b/src/tools/clangbackend/ipcsource/type.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "type.h" + +#include "clangstring.h" +#include "cursor.h" + +#include <utf8string.h> + +#include <ostream> + +namespace ClangBackEnd { + +bool Type::isConstant() const +{ + return clang_isConstQualifiedType(cxType); +} + +bool Type::isConstantReference() +{ + return isLValueReference() && pointeeType().isConstant(); +} + +bool Type::isPointer() const +{ + return cxType.kind == CXType_Pointer; +} + +bool Type::isPointerToConstant() const +{ + return isPointer() && pointeeType().isConstant(); +} + +bool Type::isConstantPointer() const +{ + return isPointer() && isConstant(); +} + +bool Type::isLValueReference() const +{ + return cxType.kind == CXType_LValueReference; +} + +bool Type::isReferencingConstant() const +{ + return (isPointer() || isLValueReference()) && pointeeType().isConstant(); +} + +bool Type::isOutputParameter() const +{ + return (isPointer() || isLValueReference()) && !pointeeType().isConstant(); +} + +Utf8String Type::utf8Spelling() const +{ + return ClangString(clang_getTypeSpelling(cxType)); +} + +ClangString Type::spelling() const +{ + return ClangString(clang_getTypeSpelling(cxType)); +} + +int Type::argumentCount() const +{ + return clang_getNumArgTypes(cxType); +} + +Type Type::alias() const +{ + return clang_getTypedefDeclUnderlyingType(clang_getTypeDeclaration(cxType)); +} + +Type Type::canonical() const +{ + return clang_getCanonicalType(cxType); +} + +Type Type::classType() const +{ + return clang_Type_getClassType(cxType); +} + +Type Type::pointeeType() const +{ + return clang_getPointeeType(cxType); +} + +Type Type::argument(int index) const +{ + return clang_getArgType(cxType, index); +} + +Cursor Type::declaration() const +{ + return clang_getTypeDeclaration(cxType); +} + +CXTypeKind Type::kind() const +{ + return cxType.kind; +} + +Type::Type(CXType cxType) + : cxType(cxType) +{ +} + +bool operator==(Type first, Type second) +{ + return clang_equalTypes(first.cxType, second.cxType); +} + +void PrintTo(CXTypeKind typeKind, ::std::ostream* os) +{ + ClangString typeKindSpelling(clang_getTypeKindSpelling(typeKind)); + *os << typeKindSpelling.cString(); +} + +void PrintTo(const Type &type, ::std::ostream* os) +{ + ClangString typeKindSpelling(clang_getTypeKindSpelling(type.kind())); + *os << typeKindSpelling.cString() + << ": \"" << type.spelling().cString() << "\""; +} + + +} // namespace ClangBackEnd + diff --git a/src/tools/clangbackend/ipcsource/type.h b/src/tools/clangbackend/ipcsource/type.h new file mode 100644 index 0000000000000000000000000000000000000000..099bfa4e3eeb0db3c88b87911e0b1b7afb6b092c --- /dev/null +++ b/src/tools/clangbackend/ipcsource/type.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGBACKEND_TYPE_H +#define CLANGBACKEND_TYPE_H + +#include <clang-c/Index.h> + +#include <iosfwd> + +class Utf8String; + +namespace ClangBackEnd { + +class Cursor; +class ClangString; + +class Type +{ + friend class Cursor; + friend bool operator==(Type first, Type second); + +public: + bool isConstant() const; + bool isConstantReference(); + bool isPointer() const; + bool isPointerToConstant() const; + bool isConstantPointer() const; + bool isLValueReference() const; + bool isReferencingConstant() const; + bool isOutputParameter() const; + + Utf8String utf8Spelling() const; + ClangString spelling() const; + int argumentCount() const; + + Type alias() const; + Type canonical() const; + Type classType() const; + Type pointeeType() const; + Type argument(int index) const; + + Cursor declaration() const; + + CXTypeKind kind() const; + +private: + Type(CXType cxType); + +private: + CXType cxType; +}; + +bool operator==(Type first, Type second); + +void PrintTo(CXTypeKind typeKind, ::std::ostream* os); +void PrintTo(const Type &type, ::std::ostream* os); +} // namespace ClangBackEnd + +#endif // CLANGBACKEND_TYPE_H diff --git a/tests/unit/unittest/clangstringtest.cpp b/tests/unit/unittest/clangstringtest.cpp index 0467de693dfaf0cc837ed25058a779cb91698418..b7ee1982b92fd623ebad095c0d2b6f8ccc47acf6 100644 --- a/tests/unit/unittest/clangstringtest.cpp +++ b/tests/unit/unittest/clangstringtest.cpp @@ -42,6 +42,8 @@ namespace { +using ::testing::StrEq; + using ClangBackEnd::ClangString; TEST(ClangString, ConvertToUtf8String) @@ -87,4 +89,11 @@ TEST(ClangString, MoveSelfAssigment) ASSERT_FALSE(text.isNull()); } + +TEST(ClangString, SpellingAsCString) +{ + ClangString text(CXString{"text", 0}); + + ASSERT_THAT(text.cString(), StrEq("text")); +} } diff --git a/tests/unit/unittest/cursortest.cpp b/tests/unit/unittest/cursortest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0e18c130831a26136ce2b84c5324ab9f3fe5ef9 --- /dev/null +++ b/tests/unit/unittest/cursortest.cpp @@ -0,0 +1,819 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include <clangstring.h> +#include <cursor.h> +#include <projectpart.h> +#include <projects.h> +#include <sourcelocation.h> +#include <sourcerange.h> +#include <translationunit.h> +#include <translationunits.h> +#include <unsavedfiles.h> + +#include <gmock/gmock.h> +#include <gmock/gmock-matchers.h> +#include <gtest/gtest.h> +#include "gtest-qt-printing.h" + +using ClangBackEnd::Cursor; +using ClangBackEnd::TranslationUnit; +using ClangBackEnd::UnsavedFiles; +using ClangBackEnd::ProjectPart; +using ClangBackEnd::TranslationUnits; +using ClangBackEnd::ClangString; +using ClangBackEnd::SourceRange; + +using testing::IsNull; +using testing::NotNull; +using testing::Gt; +using testing::Contains; +using testing::EndsWith; +using testing::AllOf; +using testing::Not; +using testing::IsEmpty; +using testing::StrEq; + +namespace { + +struct Data { + ClangBackEnd::ProjectParts projects; + ClangBackEnd::UnsavedFiles unsavedFiles; + ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles}; + TranslationUnit translationUnit{Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp"), + ProjectPart(Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-std=c++11")}), + {}, + translationUnits}; +}; + +class Cursor : public ::testing::Test +{ +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + +protected: + static Data *d; + const TranslationUnit &translationUnit = d->translationUnit; + + +}; + +TEST_F(Cursor, CreateNullCursor) +{ + ::Cursor cursor; + + ASSERT_TRUE(cursor.isNull()); +} + +TEST_F(Cursor, CompareNullCursors) +{ + ::Cursor cursor; + ::Cursor cursor2; + + ASSERT_THAT(cursor, cursor2); +} + +TEST_F(Cursor, IsNotValid) +{ + ::Cursor cursor; + + ASSERT_FALSE(cursor.isValid()); +} + +TEST_F(Cursor, IsValid) +{ + auto cursor = translationUnit.cursor(); + + ASSERT_TRUE(cursor.isValid()); +} + +TEST_F(Cursor, IsTranslationUnit) +{ + auto cursor = translationUnit.cursor(); + + ASSERT_TRUE(cursor.isTranslationUnit()); +} + +TEST_F(Cursor, NullCursorIsNotTranslationUnit) +{ + ::Cursor cursor; + + ASSERT_FALSE(cursor.isTranslationUnit()); +} + +TEST_F(Cursor, UnifiedSymbolResolution) +{ + ::Cursor cursor; + + ASSERT_TRUE(cursor.unifiedSymbolResolution().isEmpty()); +} + +TEST_F(Cursor, GetCursorAtLocation) +{ + auto cursor = translationUnit.cursorAt(3, 6); + + ASSERT_THAT(cursor.unifiedSymbolResolution(), Utf8StringLiteral("c:@F@function#I#")); +} + +TEST_F(Cursor, GetCursoSourceLocation) +{ + auto cursor = translationUnit.cursorAt(3, 6); + + ASSERT_THAT(cursor.sourceLocation(), translationUnit.sourceLocationAt(3, 6)); +} + +TEST_F(Cursor, GetCursoSourceRange) +{ + auto cursor = translationUnit.cursorAt(3, 6); + + ASSERT_THAT(cursor.sourceRange(), SourceRange(translationUnit.sourceLocationAt(3, 1), + translationUnit.sourceLocationAt(6, 2))); +} + +TEST_F(Cursor, Mangling) +{ + auto cursor = translationUnit.cursorAt(3, 6); + + + ASSERT_THAT(cursor.mangling(), Utf8StringLiteral("_Z8functioni")); +} + +TEST_F(Cursor, Spelling) +{ + auto cursor = translationUnit.cursorAt(3, 6); + + + ASSERT_THAT(cursor.spelling().cString(), StrEq("function")); +} + +TEST_F(Cursor, DisplayName) +{ + auto cursor = translationUnit.cursorAt(3, 6); + + + ASSERT_THAT(cursor.displayName(), Utf8StringLiteral("function(int)")); +} + +TEST_F(Cursor, BriefComment) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); + + + ASSERT_THAT(cursor.briefComment(), Utf8StringLiteral("A brief comment")); +} + +TEST_F(Cursor, RawComment) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); + + + ASSERT_THAT(cursor.rawComment(), Utf8StringLiteral("/**\n * A brief comment\n */")); +} + +TEST_F(Cursor, CommentRange) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); + + + ASSERT_THAT(cursor.commentRange(), + SourceRange(translationUnit.sourceLocationAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 7, 1), + translationUnit.sourceLocationAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 9, 4))); +} + +TEST_F(Cursor, IsDefinition) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); + + ASSERT_TRUE(cursor.isDefinition()); +} + +TEST_F(Cursor, ForwardDeclarationIsNotDefinition) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7); + + ASSERT_FALSE(cursor.isDefinition()); +} + +TEST_F(Cursor, GetDefinitionOfFowardDeclaration) +{ + auto forwardDeclarationcursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7); + auto definitionCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); + + ASSERT_THAT(forwardDeclarationcursor.definition(), definitionCursor); +} + +TEST_F(Cursor, CallToMethodeIsNotDynamic) +{ + auto cursor = translationUnit.cursorAt(18, 5); + + ASSERT_FALSE(cursor.isDynamicCall()); +} + +TEST_F(Cursor, CallToAbstractVirtualMethodeIsDynamic) +{ + auto cursor = translationUnit.cursorAt(19, 5); + + ASSERT_TRUE(cursor.isDynamicCall()); +} + +TEST_F(Cursor, CanonicalCursor) +{ + auto forwardDeclarationcursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7); + auto definitionCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); + + ASSERT_THAT(definitionCursor.canonical(), forwardDeclarationcursor); +} + +TEST_F(Cursor, ReferencedCursor) +{ + auto functionCallCursor = translationUnit.cursorAt(18, 5); + auto functionCursor = translationUnit.cursorAt(16, 17); + + ASSERT_THAT(functionCallCursor.referenced(), functionCursor); +} + +TEST_F(Cursor, IsVirtual) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17); + + ASSERT_TRUE(cursor.isVirtualMethod()); +} + +TEST_F(Cursor, IsNotPureVirtualOnlyVirtual) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17); + + ASSERT_FALSE(cursor.isPureVirtualMethod()); +} + +TEST_F(Cursor, IsPureVirtual) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 16, 17); + + ASSERT_TRUE(cursor.isPureVirtualMethod()); +} + +TEST_F(Cursor, ConstantMethod) +{ + auto cursor = translationUnit.cursorAt(31, 18); + + ASSERT_TRUE(cursor.isConstantMethod()); +} + +TEST_F(Cursor, IsStaticMethod) +{ + auto cursor = translationUnit.cursorAt(36, 18); + + ASSERT_TRUE(cursor.isStaticMethod()); +} + +TEST_F(Cursor, TypeSpelling) +{ + auto cursor = translationUnit.cursorAt(43, 5); + + ASSERT_THAT(cursor.type().utf8Spelling(), Utf8StringLiteral("lint")); +} + +TEST_F(Cursor, CanonicalTypeSpelling) +{ + auto cursor = translationUnit.cursorAt(43, 5); + + ASSERT_THAT(cursor.type().canonical().utf8Spelling(), Utf8StringLiteral("long long")); +} + +TEST_F(Cursor, CanonicalTypeCStringSpelling) +{ + auto cursor = translationUnit.cursorAt(43, 5); + + auto spelling = cursor.type().canonical().spelling(); + + ASSERT_THAT(spelling.cString(), StrEq("long long")); +} + +TEST_F(Cursor, CanonicalTypeIsNotType) +{ + auto cursor = translationUnit.cursorAt(43, 5); + + ASSERT_THAT(cursor.type().canonical(), Not(cursor.type())); +} + +TEST_F(Cursor, TypeDeclartionIsAlias) +{ + auto declarationCursor = translationUnit.cursorAt(41, 5); + auto lintCursor = translationUnit.cursorAt(39, 11); + + ASSERT_THAT(declarationCursor.type().declaration().type(), lintCursor.type()); +} + +TEST_F(Cursor, TypeIsConstantWithoutAliasLookup) +{ + auto cursor = translationUnit.cursorAt(45, 16); + + ASSERT_TRUE(cursor.type().isConstant()); +} + +TEST_F(Cursor, ClassIsCompoundType) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7); + + ASSERT_TRUE(cursor.isCompoundType()); +} + +TEST_F(Cursor, StructIsCompoundType) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8); + + ASSERT_TRUE(cursor.isCompoundType()); +} + +TEST_F(Cursor, UnionIsCompoundType) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 33, 7); + + ASSERT_TRUE(cursor.isCompoundType()); +} + +TEST_F(Cursor, IsDeclaration) +{ + auto cursor = translationUnit.cursorAt(41, 10); + + ASSERT_TRUE(cursor.isDeclaration()); +} + +TEST_F(Cursor, SemanticParent) +{ + auto cursor = translationUnit.cursorAt(43, 6); + auto expectedSemanticParent = translationUnit.cursorAt(36, 18); + + auto semanticParent = cursor.semanticParent(); + + ASSERT_THAT(semanticParent, expectedSemanticParent); +} + +TEST_F(Cursor, IsLocalVariableInMethod) +{ + auto cursor = translationUnit.cursorAt(20, 9); + + ASSERT_TRUE(cursor.isLocalVariable()); +} + +TEST_F(Cursor, IsLocalVariableInStaticFunction) +{ + auto cursor = translationUnit.cursorAt(43, 5); + + ASSERT_TRUE(cursor.isLocalVariable()); +} + +TEST_F(Cursor, IsLocalVariableInTemplateFunction) +{ + auto cursor = translationUnit.cursorAt(52, 7); + + ASSERT_TRUE(cursor.isLocalVariable()); +} + +TEST_F(Cursor, IsLocalVariableInConversionOperator) +{ + auto cursor = translationUnit.cursorAt(57, 9); + + ASSERT_TRUE(cursor.isLocalVariable()); +} + +TEST_F(Cursor, IsLocalVariableInOperator) +{ + auto cursor = translationUnit.cursorAt(62, 9); + + ASSERT_TRUE(cursor.isLocalVariable()); +} + +TEST_F(Cursor, IsLocalVariableInConstructor) +{ + auto cursor = translationUnit.cursorAt(13, 9); + + ASSERT_TRUE(cursor.isLocalVariable()); +} + +TEST_F(Cursor, IsLocalVariableInDestructor) +{ + auto cursor = translationUnit.cursorAt(69, 9); + + ASSERT_TRUE(cursor.isLocalVariable()); +} + +TEST_F(Cursor, FindFunctionCaller) +{ + auto functionCursor = translationUnit.cursorAt(92, 24); + auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8); + + ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor); +} + +TEST_F(Cursor, FindFunctionCallerPointer) +{ + auto functionCursor = translationUnit.cursorAt(79, 25); + auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8); + + ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor); +} + +TEST_F(Cursor, FindFunctionCallerThis) +{ + auto functionCursor = translationUnit.cursorAt(106, 5); + auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 38, 8); + + ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor); +} + +TEST_F(Cursor, NonPointerTypeForValue) +{ + auto variableCursor = translationUnit.cursorAt(101, 10); + auto variablePointerCursor = translationUnit.cursorAt(100, 11); + + ASSERT_THAT(variableCursor.nonPointerTupe(), variablePointerCursor.nonPointerTupe()); +} + +TEST_F(Cursor, HasFinalAttributeInFunction) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 30, 18); + + ASSERT_TRUE(cursor.hasFinalFunctionAttribute()); +} + +TEST_F(Cursor, HasNotFinalAttributeInFunction) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17); + + ASSERT_FALSE(cursor.hasFinalFunctionAttribute()); +} + +TEST_F(Cursor, HasFinalAttributeInClass) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8); + + ASSERT_TRUE(cursor.hasFinalClassAttribute()); +} + +TEST_F(Cursor, HasNotFinaAttributeInClass) +{ + auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 38, 8); + + ASSERT_FALSE(cursor.hasFinalClassAttribute()); +} + +TEST_F(Cursor, HasOutputValues) +{ + auto callExpressionCursor = translationUnit.cursorAt(117, 19); + auto outputArgumentExpectedCursor = translationUnit.cursorAt(117, 20); + + auto outputArguments = callExpressionCursor.outputArguments(); + + ASSERT_THAT(outputArguments.size(), 1); + ASSERT_THAT(outputArguments[0], outputArgumentExpectedCursor); +} + +TEST_F(Cursor, HasOnlyInputValues) +{ + auto callExpressionCursor = translationUnit.cursorAt(118, 18); + + auto outputArguments = callExpressionCursor.outputArguments(); + + ASSERT_THAT(outputArguments, IsEmpty()); +} + +TEST_F(Cursor, ArgumentCountIsZero) +{ + auto cursor = translationUnit.cursorAt(121, 23); + + auto count = cursor.type().argumentCount(); + + ASSERT_THAT(count, 0); +} + +TEST_F(Cursor, ArgumentCountIsTwo) +{ + auto cursor = translationUnit.cursorAt(122, 22); + + auto count = cursor.type().argumentCount(); + + ASSERT_THAT(count, 2); +} + +TEST_F(Cursor, ArgumentOneIsValue) +{ + auto callExpressionCursor = translationUnit.cursorAt(122, 22); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isConstant()); + ASSERT_THAT(argument.kind(), CXType_Int); +} + +TEST_F(Cursor, ArgumentTwoIsLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(122, 22); + + auto argument = callExpressionCursor.type().argument(1); + + ASSERT_THAT(argument.kind(), CXType_LValueReference); +} + +TEST_F(Cursor, ArgumentTwoIsConstantReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(122, 22); + + auto argumentPointee = callExpressionCursor.type().argument(1); + + ASSERT_TRUE(argumentPointee.isConstantReference()); +} + +TEST_F(Cursor, CursorArgumentCount) +{ + auto cursor = translationUnit.cursorAt(117, 19); + + ASSERT_THAT(cursor.kind(), CXCursor_CallExpr); + ASSERT_THAT(cursor.argumentCount(), 4); +} + +TEST_F(Cursor, CursorArgumentInputValue) +{ + auto callExpressionCursor = translationUnit.cursorAt(117, 19); + auto declarationReferenceExpressionCursor = translationUnit.cursorAt(117, 20); + + ASSERT_THAT(callExpressionCursor.argument(0), declarationReferenceExpressionCursor); +} + +TEST_F(Cursor, IsConstantLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(125, 26); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isConstantReference()); +} + +TEST_F(Cursor, LValueReferenceIsNotConstantLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(124, 21); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isConstantReference()); +} + +TEST_F(Cursor, ValueIsNotConstantLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(123, 18); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isConstantReference()); +} + +TEST_F(Cursor, PointerToConstantNotConstantLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(126, 20); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isConstantReference()); +} + +TEST_F(Cursor, IsLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(124, 21); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isLValueReference()); +} + +TEST_F(Cursor, ConstantLValueReferenceIsLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(125, 26); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isLValueReference()); +} + +TEST_F(Cursor, ValueIsNotLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(123, 18); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isLValueReference()); +} + +TEST_F(Cursor, PointerIsNotLValueReference) +{ + auto callExpressionCursor = translationUnit.cursorAt(126, 20); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isLValueReference()); +} + +TEST_F(Cursor, PointerToConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(126, 20); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isPointerToConstant()); +} + +TEST_F(Cursor, ValueIsNotPointerToConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(123, 18); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isPointerToConstant()); +} + +TEST_F(Cursor, PointerNotPointerToConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(127, 13); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isPointerToConstant()); +} + +TEST_F(Cursor, ConstantLValueReferenceIsNotPointerToConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(125, 26); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isPointerToConstant()); +} + +TEST_F(Cursor, IsConstantPointer) +{ + auto callExpressionCursor = translationUnit.cursorAt(128, 21); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isConstantPointer()); +} + +TEST_F(Cursor, PointerToConstantIsNotConstantPointer) +{ + auto callExpressionCursor = translationUnit.cursorAt(126, 20); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isConstantPointer()); +} + +TEST_F(Cursor, ConstValueIsNotConstantPointer) +{ + auto callExpressionCursor = translationUnit.cursorAt(129, 23); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isConstantPointer()); +} + +TEST_F(Cursor, PointerToConstantIsReferencingConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(126, 20); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isReferencingConstant()); +} + +TEST_F(Cursor, ConstantReferenceIsReferencingConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(125, 26); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isReferencingConstant()); +} + +TEST_F(Cursor, LValueReferenceIsNotReferencingConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(124, 21); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isReferencingConstant()); +} + +TEST_F(Cursor, ValueIsNotReferencingConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(123, 18); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isReferencingConstant()); +} + +TEST_F(Cursor, PointerIsNotRefencingConstant) +{ + auto callExpressionCursor = translationUnit.cursorAt(127, 13); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isReferencingConstant()); +} + +TEST_F(Cursor, PointerIsOutputParameter) +{ + auto callExpressionCursor = translationUnit.cursorAt(127, 13); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isOutputParameter()); +} + +TEST_F(Cursor, ConstantReferenceIsNotOutputParameter) +{ + auto callExpressionCursor = translationUnit.cursorAt(125, 26); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isOutputParameter()); +} + +TEST_F(Cursor, PointerToConstantIsNotOutputParameter) +{ + auto callExpressionCursor = translationUnit.cursorAt(126, 20); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isOutputParameter()) << argument.isConstant() << argument.pointeeType().isConstant(); +} + +TEST_F(Cursor, ConstantPointerIsNotOutputParameter) +{ + auto callExpressionCursor = translationUnit.cursorAt(128, 21); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isOutputParameter()); +} + +TEST_F(Cursor, ReferenceIsOutputParameter) +{ + auto callExpressionCursor = translationUnit.cursorAt(124, 21); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_TRUE(argument.isOutputParameter()); +} + +TEST_F(Cursor, ConstReferenceIsNotOutputParameter) +{ + auto callExpressionCursor = translationUnit.cursorAt(125, 26); + + auto argument = callExpressionCursor.type().argument(0); + + ASSERT_FALSE(argument.isOutputParameter()); +} + +Data *Cursor::d; + +void Cursor::SetUpTestCase() +{ + d = new Data; +} + +void Cursor::TearDownTestCase() +{ + delete d; + d = nullptr; +} + +} diff --git a/tests/unit/unittest/data/cursor.cpp b/tests/unit/unittest/data/cursor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a492867dd6bd51a2732db6bfd5d2b30cb42e4c83 --- /dev/null +++ b/tests/unit/unittest/data/cursor.cpp @@ -0,0 +1,129 @@ +#include "cursor.h" + +void function(int x) +{ + +} + +namespace Namespace +{ +SuperClass::SuperClass(int x) noexcept + : y(x) +{ + int LocalVariable; +} + +int SuperClass::Method() +{ + Method(); + AbstractVirtualMethod(y); + int LocalVariable; + return y; +} + +int SuperClass::VirtualMethod(int z) +{ + AbstractVirtualMethod(z); + + return y; +} + +bool SuperClass::ConstMethod() const +{ + return y; +} + +void SuperClass::StaticMethod() +{ + using longint = long long int; + using lint = longint; + + lint foo; + + foo = 30; + + const lint bar = 20; +} +} + +template <class T> +void TemplateFunction(T LocalVariableParameter) +{ + T LocalVariable; +} + +Namespace::SuperClass::operator int() const +{ + int LocalVariable; +} + +int Namespace::SuperClass::operator ++() const +{ + int LocalVariable; + + return LocalVariable; +} + +Namespace::SuperClass::~SuperClass() +{ + int LocalVariable; +} + +void Struct::FinalVirtualMethod() +{ + +} + +void f1(Struct *FindFunctionCaller) +{ + FindFunctionCaller->FinalVirtualMethod(); +} + +void f2(){ + Struct *s = new Struct; + + f1(s); +} + +void f3() +{ + auto FindFunctionCaller = Struct(); + + FindFunctionCaller.FinalVirtualMethod(); +} + + +void f4() +{ + Struct s; + + auto *sPointer = &s; + auto sValue = s; +} + +void NonFinalStruct::function() +{ + FinalVirtualMethod(); +} + +void OutputFunction(int &out, int in = 1, const int &in2=2, int *out2=nullptr); +void InputFunction(const int &value); + +void f5() +{ + int OutputValue; + int InputValue = 20; + + OutputFunction(OutputValue); + InputFunction(InputValue); +} + +void ArgumentCountZero(); +void ArgumentCountTwo(int one, const int &two); +void IntegerValue(int); +void LValueReference(int &); +void ConstLValueReference(const int &); +void PointerToConst(const int *); +void Pointer(int *); +void ConstantPointer(int *const); +void ConstIntegerValue(const int); diff --git a/tests/unit/unittest/data/cursor.h b/tests/unit/unittest/data/cursor.h new file mode 100644 index 0000000000000000000000000000000000000000..3e9e9a2bfb993b8fc1625d30a05e0ebd50ff4865 --- /dev/null +++ b/tests/unit/unittest/data/cursor.h @@ -0,0 +1,42 @@ + + + +namespace Namespace +{ +class SuperClass; +/** + * A brief comment + */ +class SuperClass +{ + SuperClass() = default; + SuperClass(int x) noexcept; + int Method(); + virtual int VirtualMethod(int z); + virtual int AbstractVirtualMethod(int z) = 0; + bool ConstMethod() const; + static void StaticMethod(); + operator int() const; + int operator ++() const; + ~SuperClass(); + +private: + int y; +}; +} + +struct Struct final +{ + virtual void FinalVirtualMethod() final; +}; + +union Union +{ + +}; + +struct NonFinalStruct +{ + virtual void FinalVirtualMethod() final; + void function(); +}; diff --git a/tests/unit/unittest/data/highlightinginformations.cpp b/tests/unit/unittest/data/highlightinginformations.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d651fd65e1c19bb48bd9a391e5fd7eb117d3fe85 --- /dev/null +++ b/tests/unit/unittest/data/highlightinginformations.cpp @@ -0,0 +1,385 @@ +auto *Variable = "Variable"; +auto *u8Variable = u8"Variable"; +auto *rawVariable = R"(Variable)"; +auto Character = 'c'; + + + + + + + + + + + + + + + + + + +auto integer = 1; +auto numFloat = 1.2f; + + + + + + + + + + + + + + + + + + + + +int function(int x) +{ + return x; +} + +struct Foo +{ + void memberFunction() {} +}; + +int functionDeclaration(int x); + +struct Foo2 +{ + void memberFunction(); +}; + +void f() +{ + function(1); +} + +struct ConversionFunction { + operator Foo(); + operator int(); +}; + +void TypeReference() +{ + Foo foo; +} + +void LocalVariableDeclaration() +{ + Foo foo; + + foo.memberFunction(); +} + +void LocalVariableFunctionArgument(Foo &foo) +{ + foo.memberFunction(); +} + +struct Foo3 { + int ClassMember; + + void ClassMemberReference() + { + ClassMember++; + } +}; + +struct Foo4 +{ + void MemberFunctionReference(); + + void function() + { + MemberFunctionReference(); + } +}; + +struct Foo5 +{ + void StaticMethod(); + + void function() + { + Foo5::StaticMethod(); + } +}; + +enum Enumeration +{ + Enumerator +}; + +void f2() +{ + Enumeration enumeration; + + enumeration = Enumerator; +} + +class ForwardReference; + +class Class +{ public: + Class(); + ~Class(); +}; + +ForwardReference *f3() +{ + Class ConstructorReference; + + return 0; +} + +union Union +{ + +}; + +Union UnionDeclarationReference; + + + + + + + + + +namespace NameSpace { +struct StructInNameSpace {}; +} + +namespace NameSpaceAlias = NameSpace; + +NameSpace::StructInNameSpace foo6; + +class BaseClass { +public: + virtual void VirtualFunction(); + virtual void FinalVirtualFunction(); +}; + + +void f8() +{ + BaseClass NonVirtualFunctionCall; + NonVirtualFunctionCall.VirtualFunction(); + + BaseClass *NonVirtualFunctionCallPointer = new BaseClass(); + NonVirtualFunctionCallPointer->VirtualFunction(); +} + +class DerivedClass : public BaseClass +{public: + void VirtualFunction() override; + void FinalVirtualFunction() final; +}; + +void f8(BaseClass *VirtualFunctionCallPointer) +{ + VirtualFunctionCallPointer->VirtualFunction(); +} + +class FinalClass final : public DerivedClass +{ + void FinalClassThisCall(); +}; + +void f8(DerivedClass *FinalVirtualFunctionCallPointer) +{ + FinalVirtualFunctionCallPointer->FinalVirtualFunction(); +} + +void f9(BaseClass *NonFinalVirtualFunctionCallPointer) +{ + NonFinalVirtualFunctionCallPointer->FinalVirtualFunction(); +} + +void f10(FinalClass *ClassFinalVirtualFunctionCallPointer) +{ + ClassFinalVirtualFunctionCallPointer->VirtualFunction(); +} + +class Operator { +public: + Operator operator+=(const Operator &first); +}; + +Operator operator+(const Operator &first, const Operator &second); + +void f10() +{ + auto PlusOperator = Operator() + Operator(); + Operator PlusAssignOperator; + PlusAssignOperator += Operator(); +} + +/* Comment */ + +#define PreprocessorDefinition Class +#define MacroDefinition(a,b) ((a)>(b)?(a):(b)) + +void f11() +{ + MacroDefinition(2, 4); +} + +#include "highlightinginformations.h" + +void f12() { +GOTO_LABEL: + + goto GOTO_LABEL; +} + +template <class T> +void TemplateFunction(T v) +{ + T XXXXX = v; +} +void TemplateReference() +{ + TemplateFunction(1); +// std::vector<int> TemplateIntance; +} + + + + +template <class T> +class TemplateFoo {}; + + +template <class TemplateTypeParameter = Foo, int NonTypeTemplateParameter = 1, template <class> class TemplateTemplateParameter = TemplateFoo> +void TemplateFunction(TemplateTypeParameter TemplateParameter) +{ + TemplateTypeParameter TemplateTypeParameterReference; + auto NonTypeTemplateParameterReference = NonTypeTemplateParameter; + TemplateTemplateParameter<TemplateTypeParameter> TemplateTemplateParameterReference; +} + + + +void FinalClass::FinalClassThisCall() +{ + VirtualFunction(); +} + + +void OutputParameter(int &one, const int &two, int *three=0); + +void f12() +{ + int One; + OutputParameter(One, 2); +} + +#include <highlightinginformations.h> + +#define FOREACH(variable, container) \ + variable; \ + auto x = container; + +#define foreach2 FOREACH + +#include <initializer_list> + +void f13() +{ + auto container = 1; + foreach2(int index, container); +} + +class SecondArgumentInMacroExpansionIsField { + int container = 1; + + void f() + { + foreach2(int index, container); + } +}; + +typedef unsigned uint32; + +enum EnumerationType : uint32 +{ + Other = 0, +}; + + +struct TypeInCast { + void function(); +}; + +void f14() +{ + static_cast<void (TypeInCast::*)()>(&TypeInCast::function); + reinterpret_cast<void (TypeInCast::*)()>(&TypeInCast::function); +} + +using IntegerAlias = int; +using SecondIntegerAlias = IntegerAlias; +using IntegerTypedef = int; +using Function = void (*)(); + + + +void f15() +{ + IntegerAlias integerAlias; + SecondIntegerAlias secondIntegerAlias; + IntegerTypedef integerTypedef; + Function(); +} + +class FriendFoo +{ +public: + friend class FooFriend; + friend bool operator==(const FriendFoo &first, const FriendFoo &second); +}; + +class FieldInitialization +{ +public: + FieldInitialization() : + member(0) + {} + + int member; +}; + +template<class Type> +void TemplateFunctionCall(Type type) +{ + type + type; +} + +void f16() +{ + TemplateFunctionCall(1); +} + + +template <typename T> +class TemplatedType +{ + T value = T(); +}; + +void f17() +{ + TemplatedType<int> TemplatedTypeDeclaration; +} diff --git a/tests/unit/unittest/data/highlightinginformations.h b/tests/unit/unittest/data/highlightinginformations.h new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/unit/unittest/data/skippedsourceranges.cpp b/tests/unit/unittest/data/skippedsourceranges.cpp new file mode 100644 index 0000000000000000000000000000000000000000..775393fcedcb2dac890cb76b9327ab8146b418dd --- /dev/null +++ b/tests/unit/unittest/data/skippedsourceranges.cpp @@ -0,0 +1,19 @@ +#if 0 + +void f(); + +#endif + +#ifndef BLAH +class Class +{ + +}; +#endif + +#ifdef BLAH +class Class +{ + +}; +#endif diff --git a/tests/unit/unittest/highlightinginformationstest.cpp b/tests/unit/unittest/highlightinginformationstest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c09f12cc1704ac381e8f6440014a428bf9fd6255 --- /dev/null +++ b/tests/unit/unittest/highlightinginformationstest.cpp @@ -0,0 +1,902 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include <cursor.h> +#include <clangbackendipc_global.h> +#include <clangstring.h> +#include <projectpart.h> +#include <projects.h> +#include <sourcelocation.h> +#include <sourcerange.h> +#include <highlightinginformation.h> +#include <highlightinginformations.h> +#include <translationunit.h> +#include <translationunits.h> +#include <unsavedfiles.h> + +#include <gmock/gmock.h> +#include <gmock/gmock-matchers.h> +#include <gtest/gtest.h> +#include "gtest-qt-printing.h" + +using ClangBackEnd::Cursor; +using ClangBackEnd::HighlightingInformation; +using ClangBackEnd::HighlightingInformations; +using ClangBackEnd::HighlightingType; +using ClangBackEnd::TranslationUnit; +using ClangBackEnd::UnsavedFiles; +using ClangBackEnd::ProjectPart; +using ClangBackEnd::TranslationUnits; +using ClangBackEnd::ClangString; +using ClangBackEnd::SourceRange; + +using testing::PrintToString; +using testing::IsNull; +using testing::NotNull; +using testing::Gt; +using testing::Contains; +using testing::EndsWith; +using testing::AllOf; +using testing::Not; +using testing::IsEmpty; +using testing::SizeIs; + +namespace { + +MATCHER_P4(IsHighlightingInformation, line, column, length, type, + std::string(negation ? "isn't " : "is ") + + PrintToString(HighlightingInformation(line, column, length, type)) + ) +{ + const HighlightingInformation expected(line, column, length, type); + + return arg == expected; +} + +MATCHER_P(HasType, type, + std::string(negation ? "isn't " : "is ") + + PrintToString(type) + ) +{ + return arg.hasType(type); +} + +struct Data { + ClangBackEnd::ProjectParts projects; + ClangBackEnd::UnsavedFiles unsavedFiles; + ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles}; + TranslationUnit translationUnit{Utf8StringLiteral(TESTDATA_DIR"/highlightinginformations.cpp"), + ProjectPart(Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-std=c++14")}), + {}, + translationUnits}; +}; + +class HighlightingInformations : public ::testing::Test +{ +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + + SourceRange sourceRange(uint line, uint columnEnd) const; + +protected: + static Data *d; + const TranslationUnit &translationUnit = d->translationUnit; +}; + +TEST_F(HighlightingInformations, CreateNullInformations) +{ + ::HighlightingInformations infos; + + ASSERT_TRUE(infos.isNull()); +} + +TEST_F(HighlightingInformations, NullInformationsAreEmpty) +{ + ::HighlightingInformations infos; + + ASSERT_TRUE(infos.isEmpty()); +} + +TEST_F(HighlightingInformations, IsNotNull) +{ + const auto aRange = translationUnit.sourceRange(3, 1, 5, 1); + + const auto infos = translationUnit.highlightingInformationsInRange(aRange); + + ASSERT_FALSE(infos.isNull()); +} + +TEST_F(HighlightingInformations, IteratorBeginEnd) +{ + const auto aRange = translationUnit.sourceRange(3, 1, 5, 1); + const auto infos = translationUnit.highlightingInformationsInRange(aRange); + + const auto endIterator = std::next(infos.begin(), infos.size()); + + ASSERT_THAT(infos.end(), endIterator); +} + +TEST_F(HighlightingInformations, Size) +{ + const auto range = translationUnit.sourceRange(5, 5, 5, 10); + + const auto infos = translationUnit.highlightingInformationsInRange(range); + + ASSERT_THAT(infos.size(), 1); +} + +TEST_F(HighlightingInformations, DISABLED_Keyword) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(5, 12)); + + ASSERT_THAT(infos[0], IsHighlightingInformation(5u, 5u, 6u, HighlightingType::Keyword)); +} + +TEST_F(HighlightingInformations, StringLiteral) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(1, 29)); + + ASSERT_THAT(infos[4], IsHighlightingInformation(1u, 24u, 10u, HighlightingType::StringLiteral)); +} + +TEST_F(HighlightingInformations, Utf8StringLiteral) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(2, 33)); + + ASSERT_THAT(infos[4], IsHighlightingInformation(2u, 24u, 12u, HighlightingType::StringLiteral)); +} + +TEST_F(HighlightingInformations, RawStringLiteral) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(3, 34)); + + ASSERT_THAT(infos[4], IsHighlightingInformation(3u, 24u, 13u, HighlightingType::StringLiteral)); +} + +TEST_F(HighlightingInformations, CharacterLiteral) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(4, 28)); + + ASSERT_THAT(infos[3], IsHighlightingInformation(4u, 24u, 3u, HighlightingType::StringLiteral)); +} + +TEST_F(HighlightingInformations, IntegerLiteral) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(23, 26)); + + ASSERT_THAT(infos[3], IsHighlightingInformation(23u, 24u, 1u, HighlightingType::NumberLiteral)); +} + +TEST_F(HighlightingInformations, FloatLiteral) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(24, 29)); + + ASSERT_THAT(infos[3], IsHighlightingInformation(24u, 24u, 4u, HighlightingType::NumberLiteral)); +} + +TEST_F(HighlightingInformations, FunctionDefinition) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(45, 20)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(45u, 5u, 8u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, MemberFunctionDefinition) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(52, 29)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(52u, 10u, 14u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, FunctionDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(55, 32)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(55u, 5u, 19u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, MemberFunctionDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(59, 27)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(59u, 10u, 14u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, MemberFunctionReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(104, 35)); + + ASSERT_THAT(infos[0], IsHighlightingInformation(104u, 9u, 23u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, FunctionCall) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(64, 16)); + + ASSERT_THAT(infos[0], IsHighlightingInformation(64u, 5u, 8u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, TypeConversionFunction) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(68, 20)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(68u, 14u, 3u, HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, InbuiltTypeConversionFunction) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(69, 20)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(69u, 14u, 3u, HighlightingType::Keyword)); +} + +TEST_F(HighlightingInformations, TypeReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(74, 13)); + + ASSERT_THAT(infos[0], IsHighlightingInformation(74u, 5u, 3u, HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, LocalVariable) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(79, 13)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(79u, 9u, 3u, HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, LocalVariableDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(79, 13)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(79u, 9u, 3u, HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, LocalVariableReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(81, 26)); + + ASSERT_THAT(infos[0], IsHighlightingInformation(81u, 5u, 3u, HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, LocalVariableFunctionArgumentDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(84, 45)); + + ASSERT_THAT(infos[5], IsHighlightingInformation(84u, 41u, 3u, HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, LocalVariableFunctionArgumentReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(86, 26)); + + ASSERT_THAT(infos[0], IsHighlightingInformation(86u, 5u, 3u, HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, ClassVariableDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(90, 21)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(90u, 9u, 11u, HighlightingType::Field)); +} + +TEST_F(HighlightingInformations, ClassVariableReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(94, 23)); + + ASSERT_THAT(infos[0], IsHighlightingInformation(94u, 9u, 11u, HighlightingType::Field)); +} + +TEST_F(HighlightingInformations, StaticMethodDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(110, 25)); + + ASSERT_THAT(infos[1], IsHighlightingInformation(110u, 10u, 12u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, StaticMethodReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(114, 30)); + + ASSERT_THAT(infos[2], IsHighlightingInformation(114u, 15u, 12u, HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, Enumeration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(118, 17)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Enumeration)); +} + +TEST_F(HighlightingInformations, Enumerator) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(120, 15)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Enumeration)); +} + +TEST_F(HighlightingInformations, EnumerationReferenceDeclarationType) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(125, 28)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Enumeration)); +} + +TEST_F(HighlightingInformations, EnumerationReferenceDeclarationVariable) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(125, 28)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, EnumerationReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(127, 30)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, EnumeratorReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(127, 30)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Enumeration)); +} + +TEST_F(HighlightingInformations, ClassForwardDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(130, 12)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, ConstructorDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(134, 13)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, DestructorDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(135, 15)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, ClassForwardDeclarationReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(138, 23)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, ClassTypeReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(140, 32)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, ConstructorReferenceVariable) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(140, 32)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, UnionDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(145, 12)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, UnionDeclarationReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(150, 33)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, GlobalVariable) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(150, 33)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::GlobalVariable)); +} + +TEST_F(HighlightingInformations, StructDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(50, 11)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, NameSpace) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(160, 22)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, NameSpaceAlias) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(164, 38)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, NameSpaceReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(166, 35)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, VirtualFunction) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(170, 35)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::VirtualFunction)); +} + +TEST_F(HighlightingInformations, DISABLED_NonVirtualFunctionCall) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(177, 46)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, DISABLED_NonVirtualFunctionCallPointer) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(180, 54)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, VirtualFunctionCallPointer) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(192, 51)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::VirtualFunction)); +} + +TEST_F(HighlightingInformations, FinalVirtualFunctionCallPointer) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(202, 61)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, NonFinalVirtualFunctionCallPointer) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(207, 61)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::VirtualFunction)); +} + +TEST_F(HighlightingInformations, PlusOperator) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(224, 49)); + + ASSERT_THAT(infos[6], HasType(HighlightingType::Operator)); +} + +TEST_F(HighlightingInformations, PlusAssignOperator) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(226, 24)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Operator)); +} + +TEST_F(HighlightingInformations, Comment) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(229, 14)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Comment)); +} + +TEST_F(HighlightingInformations, PreprocessingDirective) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(231, 37)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Preprocessor)); +} + +TEST_F(HighlightingInformations, PreprocessorMacroDefinition) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(231, 37)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::PreprocessorDefinition)); +} + +TEST_F(HighlightingInformations, PreprocessorFunctionMacroDefinition) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(232, 47)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::PreprocessorDefinition)); +} + +TEST_F(HighlightingInformations, PreprocessorMacroExpansion) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(236, 27)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::PreprocessorExpansion)); +} + +TEST_F(HighlightingInformations, PreprocessorMacroExpansionArgument) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(236, 27)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::NumberLiteral)); +} + +TEST_F(HighlightingInformations, PreprocessorInclusionDirective) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(239, 18)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::StringLiteral)); +} + +TEST_F(HighlightingInformations, GotoLabelStatement) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(242, 12)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Label)); +} + +TEST_F(HighlightingInformations, GotoLabelStatementReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(244, 21)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Label)); +} + +TEST_F(HighlightingInformations, TemplateReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(254, 25)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, TemplateTypeParameter) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135)); + + ASSERT_THAT(infos[3], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TemplateDefaultParameter) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135)); + + ASSERT_THAT(infos[5], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, NonTypeTemplateParameter) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135)); + + ASSERT_THAT(infos[8], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, NonTypeTemplateParameterDefaultArgument) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135)); + + ASSERT_THAT(infos[10], HasType(HighlightingType::NumberLiteral)); +} + +TEST_F(HighlightingInformations, TemplateTemplateParameter) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135)); + + ASSERT_THAT(infos[17], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TemplateTemplateParameterDefaultArgument) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135)); + + ASSERT_THAT(infos[19], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TemplateFunctionDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(266, 63)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, TemplateTypeParameterReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(268, 58)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TemplateTypeParameterDeclarationReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(268, 58)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, NonTypeTemplateParameterReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(269, 71)); + + ASSERT_THAT(infos[3], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, NonTypeTemplateParameterReferenceReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(269, 71)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, TemplateTemplateParameterReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(270, 89)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TemplateTemplateContainerParameterReference) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(270, 89)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TemplateTemplateParameterReferenceVariable) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(270, 89)); + + ASSERT_THAT(infos[4], HasType(HighlightingType::LocalVariable)); +} + +TEST_F(HighlightingInformations, ClassFinalVirtualFunctionCallPointer) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(212, 61)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, ClassFinalVirtualFunctionCall) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(277, 23)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, HasFunctionArguments) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(286, 29)); + + ASSERT_TRUE(infos[1].hasFunctionArguments()); +} + +TEST_F(HighlightingInformations, NoOutputFunctionArguments) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(285, 13)); + + auto outputFunctionArguments = infos[1].outputFunctionArguments(); + + ASSERT_THAT(outputFunctionArguments, IsEmpty()); +} + +TEST_F(HighlightingInformations, DISABLED_OneOutputFunctionArguments) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(285, 13)); + + auto outputFunctionArguments = infos[1].outputFunctionArguments(); + + ASSERT_THAT(outputFunctionArguments, SizeIs(1)); +} + +TEST_F(HighlightingInformations, PreprocessorInclusionDirectiveWithAngleBrackets ) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(289, 38)); + + ASSERT_THAT(infos[3], HasType(HighlightingType::StringLiteral)); +} + +TEST_F(HighlightingInformations, ArgumentInMacroExpansionIsKeyword) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(302, 36)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Keyword)); +} + +TEST_F(HighlightingInformations, DISABLED_FirstArgumentInMacroExpansionIsLocalVariable) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(302, 36)); + + ASSERT_THAT(infos[3], HasType(HighlightingType::Invalid)); +} + +TEST_F(HighlightingInformations, DISABLED_SecondArgumentInMacroExpansionIsLocalVariable) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(302, 36)); + + ASSERT_THAT(infos[5], HasType(HighlightingType::Invalid)); +} + +TEST_F(HighlightingInformations, DISABLED_SecondArgumentInMacroExpansionIsField) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(310, 40)); + + ASSERT_THAT(infos[5], HasType(HighlightingType::Invalid)); +} + + +TEST_F(HighlightingInformations, DISABLED_EnumerationType) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(316, 30)); + + ASSERT_THAT(infos[3], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TypeInStaticCast) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(328, 64)); + + ASSERT_THAT(infos[4], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, StaticCastIsKeyword) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(328, 64)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Keyword)); +} + +TEST_F(HighlightingInformations, StaticCastPunctationIsInvalid) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(328, 64)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Invalid)); + ASSERT_THAT(infos[3], HasType(HighlightingType::Invalid)); + ASSERT_THAT(infos[5], HasType(HighlightingType::Invalid)); +} + +TEST_F(HighlightingInformations, TypeInReinterpretCast) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(329, 69)); + + ASSERT_THAT(infos[4], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, IntegerAliasDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(333, 41)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, IntegerAlias) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(341, 31)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, SecondIntegerAlias) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(342, 43)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, IntegerTypedef) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(343, 35)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, FunctionAlias) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(344, 16)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, FriendTypeDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(350, 28)); + + ASSERT_THAT(infos[2], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, FriendArgumentTypeDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(351, 65)); + + ASSERT_THAT(infos[6], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, DISABLED_FriendArgumentDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(351, 65)); + + ASSERT_THAT(infos[8], HasType(HighlightingType::Invalid)); +} + +TEST_F(HighlightingInformations, FieldInitialization) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(358, 18)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Field)); +} + +TEST_F(HighlightingInformations, TemplateFunctionCall) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(372, 29)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Function)); +} + +TEST_F(HighlightingInformations, TemplatedType) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(377, 21)); + + ASSERT_THAT(infos[1], HasType(HighlightingType::Type)); +} + +TEST_F(HighlightingInformations, TemplatedTypeDeclaration) +{ + const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(384, 49)); + + ASSERT_THAT(infos[0], HasType(HighlightingType::Type)); +} + +Data *HighlightingInformations::d; + +void HighlightingInformations::SetUpTestCase() +{ + d = new Data; +} + +void HighlightingInformations::TearDownTestCase() +{ + delete d; + d = nullptr; +} + +ClangBackEnd::SourceRange HighlightingInformations::sourceRange(uint line, uint columnEnd) const +{ + return translationUnit.sourceRange(line, 1, line, columnEnd); +} + +} diff --git a/tests/unit/unittest/skippedsourcerangestest.cpp b/tests/unit/unittest/skippedsourcerangestest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b37b8726909b671de4f623a6f0bdaad3c4497f02 --- /dev/null +++ b/tests/unit/unittest/skippedsourcerangestest.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include <cursor.h> +#include <clangstring.h> +#include <projectpart.h> +#include <projects.h> +#include <skippedsourceranges.h> +#include <sourcelocation.h> +#include <sourcerange.h> +#include <translationunit.h> +#include <translationunits.h> +#include <unsavedfiles.h> + +#include <sourcerangecontainer.h> + +#include <QVector> + +#include <gmock/gmock.h> +#include <gmock/gmock-matchers.h> +#include <gtest/gtest.h> +#include "gtest-qt-printing.h" + +using ClangBackEnd::Cursor; +using ClangBackEnd::TranslationUnit; +using ClangBackEnd::UnsavedFiles; +using ClangBackEnd::ProjectPart; +using ClangBackEnd::TranslationUnits; +using ClangBackEnd::ClangString; +using ClangBackEnd::SourceRange; +using ClangBackEnd::SkippedSourceRanges; + +using testing::IsNull; +using testing::NotNull; +using testing::Gt; +using testing::Contains; +using testing::EndsWith; +using testing::AllOf; +using testing::Not; +using testing::IsEmpty; +using testing::SizeIs; +using testing::PrintToString; + +namespace { + +MATCHER_P4(IsSourceLocation, filePath, line, column, offset, + std::string(negation ? "isn't" : "is") + + " source location with file path "+ PrintToString(filePath) + + ", line " + PrintToString(line) + + ", column " + PrintToString(column) + + " and offset " + PrintToString(offset) + ) +{ + if (!arg.filePath().endsWith(filePath) + || arg.line() != line + || arg.column() != column + || arg.offset() != offset) { + return false; + } + + return true; +} + +struct Data { + ClangBackEnd::ProjectParts projects; + ClangBackEnd::UnsavedFiles unsavedFiles; + ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles}; + Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/skippedsourceranges.cpp"); + TranslationUnit translationUnit{filePath, + ProjectPart(Utf8StringLiteral("projectPartId"), + {Utf8StringLiteral("-std=c++11"),Utf8StringLiteral("-DBLAH")}), + {}, + translationUnits}; +}; + +class SkippedSourceRanges : public ::testing::Test +{ +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + +protected: + static Data *d; + const TranslationUnit &translationUnit = d->translationUnit; + const Utf8String &filePath = d->filePath; + const ::SkippedSourceRanges skippedSourceRanges{d->translationUnit.skippedSourceRanges()}; +}; + +Data *SkippedSourceRanges::d; + +TEST_F(SkippedSourceRanges, RangeWithZero) +{ + auto ranges = skippedSourceRanges.sourceRanges(); + + ASSERT_THAT(ranges, SizeIs(2)); +} + +TEST_F(SkippedSourceRanges, RangeOne) +{ + auto ranges = skippedSourceRanges.sourceRanges(); + + ASSERT_THAT(ranges[0].start(), IsSourceLocation(filePath, 1, 2, 1)); + ASSERT_THAT(ranges[0].end(), IsSourceLocation(filePath, 5, 7, 24)); +} + +TEST_F(SkippedSourceRanges, RangeTwo) +{ + auto ranges = skippedSourceRanges.sourceRanges(); + + ASSERT_THAT(ranges[1].start(), IsSourceLocation(filePath, 7, 2, 27)); + ASSERT_THAT(ranges[1].end(), IsSourceLocation(filePath, 12, 7, 63)); +} + +TEST_F(SkippedSourceRanges, RangeContainerSize) +{ + auto ranges = skippedSourceRanges.toSourceRangeContainers(); + + ASSERT_THAT(ranges, SizeIs(2)); +} + +void SkippedSourceRanges::SetUpTestCase() +{ + d = new Data; +} + +void SkippedSourceRanges::TearDownTestCase() +{ + delete d; + d = nullptr; +} + +} diff --git a/tests/unit/unittest/sourcelocationtest.cpp b/tests/unit/unittest/sourcelocationtest.cpp index 9db922c282be7b4b423c9ba7d022103fc276d63e..9213d9359c3f10ec64c7d777ebb5d4a292da13e5 100644 --- a/tests/unit/unittest/sourcelocationtest.cpp +++ b/tests/unit/unittest/sourcelocationtest.cpp @@ -50,13 +50,13 @@ using ClangBackEnd::ProjectPart; using ClangBackEnd::SourceLocation; using ClangBackEnd::TranslationUnit; using ClangBackEnd::UnsavedFiles; + using testing::EndsWith; +using testing::Not; namespace { -class SourceLocation : public ::testing::Test -{ -protected: +struct Data { ProjectPart projectPart{Utf8StringLiteral("projectPartId")}; ClangBackEnd::ProjectParts projects; ClangBackEnd::UnsavedFiles unsavedFiles; @@ -68,7 +68,18 @@ protected: DiagnosticSet diagnosticSet{translationUnit.diagnostics()}; Diagnostic diagnostic{diagnosticSet.front()}; ::SourceLocation sourceLocation{diagnostic.location()}; +}; +class SourceLocation : public ::testing::Test +{ +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + +protected: + static Data *d; + const ::SourceLocation &sourceLocation = d->sourceLocation; + const TranslationUnit &translationUnit = d->translationUnit; }; TEST_F(SourceLocation, FilePath) @@ -91,4 +102,27 @@ TEST_F(SourceLocation, Offset) ASSERT_THAT(sourceLocation.offset(), 18); } +TEST_F(SourceLocation, Create) +{ + ASSERT_THAT(translationUnit.sourceLocationAt(4, 1), sourceLocation); +} + +TEST_F(SourceLocation, NotEqual) +{ + ASSERT_THAT(translationUnit.sourceLocationAt(3, 1), Not(sourceLocation)); +} + +Data *SourceLocation::d; + +void SourceLocation::SetUpTestCase() +{ + d = new Data; +} + +void SourceLocation::TearDownTestCase() +{ + delete d; + d = nullptr; +} + } diff --git a/tests/unit/unittest/sourcerangetest.cpp b/tests/unit/unittest/sourcerangetest.cpp index 771bd49ccff1d1b806137d4b74e3e5d0356ebbf0..b517c42380434220df0d6b1bf5083f5bc550d763 100644 --- a/tests/unit/unittest/sourcerangetest.cpp +++ b/tests/unit/unittest/sourcerangetest.cpp @@ -51,7 +51,9 @@ using ClangBackEnd::UnsavedFiles; using ClangBackEnd::Diagnostic; using ClangBackEnd::SourceRange; using ClangBackEnd::TranslationUnits; + using testing::PrintToString; +using testing::IsEmpty; namespace { @@ -73,9 +75,7 @@ MATCHER_P4(IsSourceLocation, filePath, line, column, offset, return true; } -class SourceRange : public ::testing::Test -{ -protected: +struct Data { ProjectPart projectPart{Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-pedantic")}}; ClangBackEnd::ProjectParts projects; ClangBackEnd::UnsavedFiles unsavedFiles; @@ -90,6 +90,20 @@ protected: ::SourceRange sourceRange{diagnostic.ranges().front()}; }; +class SourceRange : public ::testing::Test +{ +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + +protected: + static Data *d; + const ::SourceRange &sourceRange = d->sourceRange; + const Diagnostic &diagnostic = d->diagnostic; + const Diagnostic &diagnosticWithFilteredOutInvalidRange = d->diagnosticWithFilteredOutInvalidRange; + const TranslationUnit &translationUnit = d->translationUnit; +}; + TEST_F(SourceRange, IsNull) { ::SourceRange sourceRange; @@ -125,9 +139,34 @@ TEST_F(SourceRange, End) 44u)); } +TEST_F(SourceRange, Create) +{ + ASSERT_THAT(sourceRange, ::SourceRange(sourceRange.start(), sourceRange.end())); +} + +TEST_F(SourceRange, SourceRangeFromTranslationUnit) +{ + auto sourceRangeFromTranslationUnit = translationUnit.sourceRange(8u, 5u, 8u, 6u); + + ASSERT_THAT(sourceRangeFromTranslationUnit, sourceRange); +} + TEST_F(SourceRange, InvalidRangeIsFilteredOut) { - ASSERT_TRUE(diagnosticWithFilteredOutInvalidRange.ranges().empty()); + ASSERT_THAT(diagnosticWithFilteredOutInvalidRange.ranges(), IsEmpty()); +} + +Data *SourceRange::d; + +void SourceRange::SetUpTestCase() +{ + d = new Data; +} + +void SourceRange::TearDownTestCase() +{ + delete d; + d = nullptr; } } diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 193f1caa68e0067d3ca7679b917db2d7fc84680e..6fe2d25f2e2561ef94950d28340c0c2a129fe108 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -53,7 +53,10 @@ SOURCES += \ translationunittest.cpp \ unsavedfilestest.cpp \ utf8test.cpp \ - senddocumenttrackertest.cpp + senddocumenttrackertest.cpp \ + cursortest.cpp \ + highlightinginformationstest.cpp \ + skippedsourcerangestest.cpp HEADERS += \ gtest-qt-printing.h \