Commit f8e64a87 authored by Marco Bubke's avatar Marco Bubke
Browse files

Clang: Add Declaration highlighting



We are adding declaration detection for function to the highligher on
user request. Other declaration will follow in separate patches.

Task-number: QTCREATORBUG-15564
Change-Id: I54e97c26425f8d6e9854547d50a9ac8fa076b4e8
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@theqtcompany.com>
parent 2349b13a
......@@ -5,6 +5,7 @@ QtcLibrary {
Depends { name: "Qt.network" }
Depends { name: "Sqlite" }
Depends { name: "Utils" }
cpp.defines: base.concat("CLANGBACKENDIPC_BUILD_LIB")
cpp.includePaths: base.concat(".")
......@@ -18,6 +19,7 @@ QtcLibrary {
Export {
Depends { name: "Sqlite" }
Depends { name: "Utils" }
Depends { name: "Qt.network" }
cpp.includePaths: [
"."
......
QTC_LIB_NAME = Clangbackendipc
QTC_LIB_DEPENDS += sqlite
QTC_LIB_DEPENDS += sqlite utils
INCLUDEPATH *= $$IDE_SOURCE_TREE/src/libs/clangbackendipc
......@@ -26,6 +26,8 @@
#ifndef CLANGBACKENDIPC_GLOBAL_H
#define CLANGBACKENDIPC_GLOBAL_H
#include <utils/sizedarray.h>
#include <QtCore/qglobal.h>
#if defined(CLANGBACKENDIPC_BUILD_LIB)
......@@ -51,7 +53,7 @@ enum class DiagnosticSeverity // one to one mapping of the clang enum numbers
Fatal = 4
};
enum class HighlightingType
enum class HighlightingType : quint8
{
Invalid,
Keyword,
......@@ -70,7 +72,8 @@ enum class HighlightingType
PreprocessorDefinition,
PreprocessorExpansion,
Label,
OutputArgument
OutputArgument,
Declaration
};
enum class CompletionCorrection
......@@ -123,5 +126,12 @@ struct MessageTrait<Message> \
static const MessageType enumeration = MessageType::Message; \
};
using MixinHighlightingTypes = Utils::SizedArray<HighlightingType, 6>;
struct HighlightingTypes {
HighlightingType mainHighlightingType;
MixinHighlightingTypes mixinHighlightingTypes;
};
}
#endif // CLANGBACKENDIPC_GLOBAL_H
......@@ -35,14 +35,25 @@ namespace ClangBackEnd {
HighlightingMarkContainer::HighlightingMarkContainer(uint line,
uint column,
uint length,
HighlightingType type)
HighlightingTypes types)
: line_(line),
column_(column),
length_(length),
type_(type)
types_(types)
{
}
HighlightingMarkContainer::HighlightingMarkContainer(uint line,
uint column,
uint length,
HighlightingType type)
: line_(line),
column_(column),
length_(length)
{
types_.mainHighlightingType = type;
}
uint HighlightingMarkContainer::line() const
{
return line_;
......@@ -58,14 +69,21 @@ uint HighlightingMarkContainer::length() const
return length_;
}
HighlightingType HighlightingMarkContainer::type() const
HighlightingTypes HighlightingMarkContainer::types() const
{
return type_;
return types_;
}
quint32 &HighlightingMarkContainer::typeAsInt()
QDataStream &operator<<(QDataStream &out, HighlightingTypes highlightingTypes)
{
return reinterpret_cast<quint32&>(type_);
out << reinterpret_cast<const quint8&>(highlightingTypes.mainHighlightingType);
out << highlightingTypes.mixinHighlightingTypes.size();
for (HighlightingType type : highlightingTypes.mixinHighlightingTypes)
out << reinterpret_cast<const quint8&>(type);
return out;
}
QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container)
......@@ -73,27 +91,55 @@ QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &conta
out << container.line_;
out << container.column_;
out << container.length_;
out << quint32(container.type_);
out << container.types_;
return out;
}
QDataStream &operator>>(QDataStream &in, HighlightingTypes &highlightingTypes)
{
in >> reinterpret_cast<quint8&>(highlightingTypes.mainHighlightingType);
quint8 size;
in >> size;
for (int counter = 0; counter < size; ++counter) {
HighlightingType type;
in >> reinterpret_cast<quint8&>(type);
highlightingTypes.mixinHighlightingTypes.push_back(type);
}
return in;
}
QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container)
{
in >> container.line_;
in >> container.column_;
in >> container.length_;
in >> container.typeAsInt();
in >> container.types_;
return in;
}
bool operator==(const MixinHighlightingTypes &first, const MixinHighlightingTypes &second)
{
return first.size() == second.size()
&& std::equal(first.begin(), first.end(), second.begin());
}
bool operator==(const HighlightingTypes &first, const HighlightingTypes &second)
{
return first.mainHighlightingType == second.mainHighlightingType
&& first.mixinHighlightingTypes == second.mixinHighlightingTypes;
}
bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second)
{
return first.line_ == second.line_
&& first.column_ == second.column_
&& first.length_ == second.length_
&& first.type_ == second.type_;
&& first.types_ == second.types_;
}
#define RETURN_TEXT_FOR_CASE(enumValue) case HighlightingType::enumValue: return #enumValue
......@@ -129,7 +175,7 @@ QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container)
<< container.line() << ", "
<< container.column() << ", "
<< container.length() << ", "
<< highlightingTypeToCStringLiteral(container.type()) << ", "
<< highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", "
<< ")";
return debug;
......@@ -140,13 +186,25 @@ void PrintTo(HighlightingType highlightingType, std::ostream *os)
*os << highlightingTypeToCStringLiteral(highlightingType);
}
void PrintTo(const HighlightingTypes &types, std::ostream *os)
{
PrintTo(types.mainHighlightingType, os);
*os << "[";
for (HighlightingType type : types.mixinHighlightingTypes)
PrintTo(type, os);
*os << "]";
}
void PrintTo(const HighlightingMarkContainer& container, ::std::ostream *os)
{
*os << "HighlightingMarkContainer("
<< container.line() << ", "
<< container.column() << ", "
<< container.length() << ", ";
PrintTo(container.type(), os);
PrintTo(container.types(), os);
*os << ")";
}
......
......@@ -36,29 +36,29 @@ class CMBIPC_EXPORT HighlightingMarkContainer
friend CMBIPC_EXPORT bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second);
public:
HighlightingMarkContainer() = default;
HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types);
HighlightingMarkContainer(uint line, uint column, uint length, HighlightingType type);
uint line() const;
uint column() const;
uint length() const;
HighlightingType type() const;
private:
quint32 &typeAsInt();
HighlightingTypes types() const;
private:
uint line_;
uint column_;
uint length_;
HighlightingType type_;
HighlightingTypes types_;
};
CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container);
CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, HighlightingMarkContainer &container);
CMBIPC_EXPORT bool operator==(const HighlightingTypes &first, const HighlightingTypes &second);
CMBIPC_EXPORT bool operator==(const HighlightingMarkContainer &first, const HighlightingMarkContainer &second);
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container);
CMBIPC_EXPORT void PrintTo(HighlightingType highlightingType, ::std::ostream *os);
CMBIPC_EXPORT void PrintTo(const HighlightingTypes &types, ::std::ostream *os);
void PrintTo(const HighlightingMarkContainer &container, ::std::ostream *os);
} // namespace ClangBackEnd
......@@ -25,57 +25,67 @@
#include "clanghighlightingmarksreporter.h"
#include <cpptools/semantichighlighter.h>
#include <texteditor/textstyles.h>
#include <QFuture>
namespace {
CppTools::SemanticHighlighter::Kind toCppToolsSemanticHighlighterKind(
ClangBackEnd::HighlightingType type)
TextEditor::TextStyle toTextStyle(ClangBackEnd::HighlightingType type)
{
using ClangBackEnd::HighlightingType;
using CppTools::SemanticHighlighter;
switch (type) {
case HighlightingType::Keyword:
return SemanticHighlighter::PseudoKeywordUse;
case HighlightingType::Function:
return SemanticHighlighter::FunctionUse;
case HighlightingType::VirtualFunction:
return SemanticHighlighter::VirtualMethodUse;
case HighlightingType::Type:
return SemanticHighlighter::TypeUse;
case HighlightingType::LocalVariable:
return SemanticHighlighter::LocalUse;
case HighlightingType::Field:
return SemanticHighlighter::FieldUse;
case HighlightingType::GlobalVariable:
return SemanticHighlighter::Unknown;
case HighlightingType::Enumeration:
return SemanticHighlighter::EnumerationUse;
case HighlightingType::Label:
return SemanticHighlighter::LabelUse;
case HighlightingType::Preprocessor:
case HighlightingType::PreprocessorDefinition:
case HighlightingType::PreprocessorExpansion:
return SemanticHighlighter::MacroUse;
default:
return SemanticHighlighter::Unknown;
case HighlightingType::Keyword:
return TextEditor::C_KEYWORD;
case HighlightingType::Function:
return TextEditor::C_FUNCTION;
case HighlightingType::VirtualFunction:
return TextEditor::C_VIRTUAL_METHOD;
case HighlightingType::Type:
return TextEditor::C_TYPE;
case HighlightingType::LocalVariable:
return TextEditor::C_LOCAL;
case HighlightingType::Field:
return TextEditor::C_FIELD;
case HighlightingType::Enumeration:
return TextEditor::C_ENUMERATION;
case HighlightingType::Label:
return TextEditor::C_LABEL;
case HighlightingType::Preprocessor:
case HighlightingType::PreprocessorDefinition:
case HighlightingType::PreprocessorExpansion:
return TextEditor::C_PREPROCESSOR;
case HighlightingType::Declaration:
return TextEditor::C_DECLARATION;
default:
return TextEditor::C_TEXT; // never called
}
Q_UNREACHABLE();
}
TextEditor::TextStyles toTextStyles(ClangBackEnd::HighlightingTypes types)
{
TextEditor::TextStyles textStyles;
textStyles.mainStyle = toTextStyle(types.mainHighlightingType);
for (ClangBackEnd::HighlightingType type : types.mixinHighlightingTypes)
textStyles.mixinStyles.push_back(toTextStyle(type));
return textStyles;
}
TextEditor::HighlightingResult toHighlightingResult(
const ClangBackEnd::HighlightingMarkContainer &highlightingMark)
{
const auto highlighterKind = toCppToolsSemanticHighlighterKind(highlightingMark.type());
const auto textStyles = toTextStyles(highlightingMark.types());
return TextEditor::HighlightingResult(highlightingMark.line(),
highlightingMark.column(),
highlightingMark.length(),
highlighterKind);
textStyles);
}
} // anonymous
......
......@@ -29,8 +29,7 @@
#include "texteditor_global.h"
#include "colorscheme.h"
#include <utils/sizedarray.h>
#include "textstyles.h"
#include <QHash>
#include <QList>
......@@ -47,13 +46,6 @@ namespace TextEditor {
class FormatDescription;
using MixinTextStyles = Utils::SizedArray<TextStyle, 6>;
struct TextStyles {
TextStyle mainStyle;
MixinTextStyles mixinStyles;
};
/**
* Font settings (default font and enumerated list of formats).
*/
......
......@@ -216,7 +216,8 @@ HEADERS += texteditorplugin.h \
codeassist/keywordscompletionassist.h \
textmarkregistry.h \
marginsettings.h \
blockrange.h
blockrange.h \
textstyles.h
FORMS += \
displaysettingspage.ui \
......
......@@ -135,6 +135,7 @@ QtcPlugin {
"textmark.cpp",
"textmark.h",
"textmarkregistry.h",
"textstyles.h",
"typingsettings.cpp",
"typingsettings.h",
]
......
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "texteditorconstants.h"
#include <utils/sizedarray.h>
namespace TextEditor {
using MixinTextStyles = Utils::SizedArray<TextStyle, 6>;
struct TextStyles {
TextStyle mainStyle;
MixinTextStyles mixinStyles;
};
} // namespace TextEditor
......@@ -50,20 +50,48 @@ HighlightingMark::HighlightingMark(const CXCursor &cxCursor,
line = start.line();
column = start.column();
length = end.offset() - start.offset();
type = kind(cxToken, originalCursor);
collectKinds(cxToken, originalCursor);
}
HighlightingMark::HighlightingMark(uint line, uint column, uint length, HighlightingTypes types)
: line(line),
column(column),
length(length),
types(types)
{
}
HighlightingMark::HighlightingMark(uint line, uint column, uint length, HighlightingType type)
: line(line),
column(column),
length(length),
type(type)
types(HighlightingTypes())
{
types.mainHighlightingType = type;
}
bool HighlightingMark::hasInvalidMainType() const
{
return types.mainHighlightingType == HighlightingType::Invalid;
}
bool HighlightingMark::hasMainType(HighlightingType type) const
{
return types.mainHighlightingType == type;
}
bool HighlightingMark::hasMixinType(HighlightingType type) const
{
auto found = std::find(types.mixinHighlightingTypes.begin(),
types.mixinHighlightingTypes.end(),
type);
return found != types.mixinHighlightingTypes.end();
}
bool HighlightingMark::hasType(HighlightingType type) const
bool HighlightingMark::hasOnlyType(HighlightingType type) const
{
return this->type == type;
return types.mixinHighlightingTypes.size() == 0 && hasMainType(type);
}
bool HighlightingMark::hasFunctionArguments() const
......@@ -80,7 +108,7 @@ QVector<HighlightingMark> HighlightingMark::outputFunctionArguments() const
HighlightingMark::operator HighlightingMarkContainer() const
{
return HighlightingMarkContainer(line, column, length, type);
return HighlightingMarkContainer(line, column, length, types);
}
namespace {
......@@ -90,8 +118,8 @@ bool isFinalFunction(const Cursor &cursor)
auto referencedCursor = cursor.referenced();
if (referencedCursor.hasFinalFunctionAttribute())
return true;
else return false;
else
return false;
}
bool isFunctionInFinalClass(const Cursor &cursor)
......@@ -104,20 +132,19 @@ bool isFunctionInFinalClass(const Cursor &cursor)
}
}
HighlightingType HighlightingMark::memberReferenceKind(const Cursor &cursor) const
void HighlightingMark::memberReferenceKind(const Cursor &cursor)
{
if (cursor.isDynamicCall()) {
if (isFinalFunction(cursor) || isFunctionInFinalClass(cursor))
return HighlightingType::Function;
types.mainHighlightingType = HighlightingType::Function;
else
return HighlightingType::VirtualFunction;
types.mainHighlightingType = HighlightingType::VirtualFunction;
} else {
identifierKind(cursor.referenced(), Recursion::RecursivePass);
}
return identifierKind(cursor.referenced());
}
HighlightingType HighlightingMark::referencedTypeKind(const Cursor &cursor) const
void HighlightingMark::referencedTypeKind(const Cursor &cursor)
{
const Cursor referencedCursor = cursor.referenced();
......@@ -128,19 +155,17 @@ HighlightingType HighlightingMark::referencedTypeKind(const Cursor &cursor) cons
case CXCursor_TypedefDecl:
case CXCursor_TemplateTypeParameter:
case CXCursor_TypeAliasDecl:
case CXCursor_EnumDecl: return HighlightingType::Type;
default: return HighlightingType::Invalid;
case CXCursor_EnumDecl: types.mainHighlightingType = HighlightingType::Type; break;
default: types.mainHighlightingType = HighlightingType::Invalid; break;
}
Q_UNREACHABLE();
}
HighlightingType HighlightingMark::variableKind(const Cursor &cursor) const
void HighlightingMark::variableKind(const Cursor &cursor)
{
if (cursor.isLocalVariable())
return HighlightingType::LocalVariable;
types.mainHighlightingType = HighlightingType::LocalVariable;
else
return HighlightingType::GlobalVariable;
types.mainHighlightingType = HighlightingType::GlobalVariable;
}
bool HighlightingMark::isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const
......@@ -157,32 +182,39 @@ bool isNotFinalFunction(const Cursor &cursor)
}
bool HighlightingMark::isRealDynamicCall(const Cursor &cursor) const
{
return originalCursor.isDynamicCall() && isNotFinalFunction(cursor);
}
HighlightingType HighlightingMark::functionKind(const Cursor &cursor) const
void HighlightingMark::addExtraTypeIfFirstPass(HighlightingType type,
Recursion recursion)
{
if (recursion == Recursion::FirstPass)
types.mixinHighlightingTypes.push_back(type);
}
void HighlightingMark::functionKind(const Cursor &cursor, Recursion recursion)
{
if (isRealDynamicCall(cursor) || isVirtualMethodDeclarationOrDefinition(cursor))
return HighlightingType::VirtualFunction;
types.mainHighlightingType = HighlightingType::VirtualFunction;
else
return HighlightingType::Function;
types.mainHighlightingType = HighlightingType::Function;
addExtraTypeIfFirstPass(HighlightingType::Declaration, recursion);
}
HighlightingType HighlightingMark::identifierKind(const Cursor &cursor) const
void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
{
switch (cursor.kind()) {
case CXCursor_Destructor:
case CXCursor_Constructor:
case CXCursor_FunctionDecl:
case CXCursor_CallExpr:
case CXCursor_CXXMethod: return functionKind(cursor);
case CXCursor_CXXMethod: functionKind(cursor, recursion); break;