forked from OSchip/llvm-project
[clangd] Add C++20 concepts support to findExplicitReferences() and semantic highlighting
Summary: Fixes https://github.com/clangd/clangd/issues/259 Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73124
This commit is contained in:
parent
210f0882c9
commit
c6c5dbc824
|
@ -618,6 +618,12 @@ llvm::SmallVector<ReferenceLoc, 2> refInExpr(const Expr *E) {
|
|||
// FIXME: handle more complicated cases, e.g. ObjC, designated initializers.
|
||||
llvm::SmallVector<ReferenceLoc, 2> Refs;
|
||||
|
||||
void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E) {
|
||||
Refs.push_back(ReferenceLoc{E->getNestedNameSpecifierLoc(),
|
||||
E->getConceptNameLoc(),
|
||||
/*IsDecl=*/false,
|
||||
{E->getNamedConcept()}});
|
||||
}
|
||||
void VisitDeclRefExpr(const DeclRefExpr *E) {
|
||||
Refs.push_back(ReferenceLoc{E->getQualifierLoc(),
|
||||
E->getNameInfo().getLoc(),
|
||||
|
|
|
@ -98,6 +98,8 @@ llvm::Optional<HighlightingKind> kindForDecl(const NamedDecl *D) {
|
|||
if (isa<TemplateTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
|
||||
isa<NonTypeTemplateParmDecl>(D))
|
||||
return HighlightingKind::TemplateParameter;
|
||||
if (isa<ConceptDecl>(D))
|
||||
return HighlightingKind::Concept;
|
||||
return llvm::None;
|
||||
}
|
||||
llvm::Optional<HighlightingKind> kindForType(const Type *TP) {
|
||||
|
@ -392,6 +394,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {
|
|||
return OS << "Namespace";
|
||||
case HighlightingKind::TemplateParameter:
|
||||
return OS << "TemplateParameter";
|
||||
case HighlightingKind::Concept:
|
||||
return OS << "Concept";
|
||||
case HighlightingKind::Primitive:
|
||||
return OS << "Primitive";
|
||||
case HighlightingKind::Macro:
|
||||
|
@ -534,6 +538,8 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
|
|||
return "entity.name.namespace.cpp";
|
||||
case HighlightingKind::TemplateParameter:
|
||||
return "entity.name.type.template.cpp";
|
||||
case HighlightingKind::Concept:
|
||||
return "entity.name.type.concept.cpp";
|
||||
case HighlightingKind::Primitive:
|
||||
return "storage.type.primitive.cpp";
|
||||
case HighlightingKind::Macro:
|
||||
|
|
|
@ -41,6 +41,7 @@ enum class HighlightingKind {
|
|||
DependentName,
|
||||
Namespace,
|
||||
TemplateParameter,
|
||||
Concept,
|
||||
Primitive,
|
||||
Macro,
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@
|
|||
# CHECK-NEXT: "entity.name.type.template.cpp"
|
||||
# CHECK-NEXT: ],
|
||||
# CHECK-NEXT: [
|
||||
# CHECK-NEXT: "entity.name.type.concept.cpp"
|
||||
# CHECK-NEXT: ],
|
||||
# CHECK-NEXT: [
|
||||
# CHECK-NEXT: "storage.type.primitive.cpp"
|
||||
# CHECK-NEXT: ],
|
||||
# CHECK-NEXT: [
|
||||
|
|
|
@ -571,7 +571,7 @@ protected:
|
|||
// FIXME: Auto-completion in a template requires disabling delayed template
|
||||
// parsing.
|
||||
TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
|
||||
TU.ExtraArgs.push_back("-std=c++17");
|
||||
TU.ExtraArgs.push_back("-std=c++2a");
|
||||
|
||||
auto AST = TU.build();
|
||||
for (auto &D : AST.getDiagnostics()) {
|
||||
|
@ -1091,7 +1091,27 @@ TEST_F(FindExplicitReferencesTest, All) {
|
|||
"0: targets = {foo::T}, decl\n"
|
||||
"1: targets = {foo::V}, decl\n"
|
||||
"2: targets = {vector}\n"
|
||||
"3: targets = {foo::T}\n"}};
|
||||
"3: targets = {foo::T}\n"},
|
||||
// Concept
|
||||
{
|
||||
R"cpp(
|
||||
template <typename T>
|
||||
concept Drawable = requires (T t) { t.draw(); };
|
||||
|
||||
namespace foo {
|
||||
template <typename $0^T> requires $1^Drawable<$2^T>
|
||||
void $3^bar($4^T $5^t) {
|
||||
$6^t.draw();
|
||||
}
|
||||
}
|
||||
)cpp",
|
||||
"0: targets = {T}, decl\n"
|
||||
"1: targets = {Drawable}\n"
|
||||
"2: targets = {T}\n"
|
||||
"3: targets = {foo::bar}, decl\n"
|
||||
"4: targets = {T}\n"
|
||||
"5: targets = {t}, decl\n"
|
||||
"6: targets = {t}\n"}};
|
||||
|
||||
for (const auto &C : Cases) {
|
||||
llvm::StringRef ExpectedCode = C.first;
|
||||
|
|
|
@ -55,6 +55,7 @@ std::vector<HighlightingToken> getExpectedTokens(Annotations &Test) {
|
|||
{HighlightingKind::DependentType, "DependentType"},
|
||||
{HighlightingKind::DependentName, "DependentName"},
|
||||
{HighlightingKind::TemplateParameter, "TemplateParameter"},
|
||||
{HighlightingKind::Concept, "Concept"},
|
||||
{HighlightingKind::Primitive, "Primitive"},
|
||||
{HighlightingKind::Macro, "Macro"}};
|
||||
std::vector<HighlightingToken> ExpectedTokens;
|
||||
|
@ -108,6 +109,7 @@ void checkHighlightings(llvm::StringRef Code,
|
|||
// FIXME: Auto-completion in a template requires disabling delayed template
|
||||
// parsing.
|
||||
TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
|
||||
TU.ExtraArgs.push_back("-std=c++2a");
|
||||
|
||||
for (auto File : AdditionalFiles)
|
||||
TU.AdditionalFiles.insert({File.first, File.second});
|
||||
|
@ -649,6 +651,19 @@ sizeof...($TemplateParameter[[Elements]]);
|
|||
static const int $StaticField[[Value]] = $TemplateParameter[[T]]
|
||||
::$DependentType[[Resolver]]::$DependentName[[Value]];
|
||||
};
|
||||
)cpp",
|
||||
// Concepts
|
||||
R"cpp(
|
||||
template <typename $TemplateParameter[[T]]>
|
||||
concept $Concept[[Fooable]] =
|
||||
requires($TemplateParameter[[T]] $Parameter[[F]]) {
|
||||
$Parameter[[F]].$DependentName[[foo]]();
|
||||
};
|
||||
template <typename $TemplateParameter[[T]]>
|
||||
requires $Concept[[Fooable]]<$TemplateParameter[[T]]>
|
||||
void $Function[[bar]]($TemplateParameter[[T]] $Parameter[[F]]) {
|
||||
$Parameter[[F]].$DependentName[[foo]]();
|
||||
}
|
||||
)cpp"};
|
||||
for (const auto &TestCase : TestCases) {
|
||||
checkHighlightings(TestCase);
|
||||
|
|
Loading…
Reference in New Issue