C++ code completion after the "operator" keyword. Provide overloaded
operators, type specifiers, type names, and nested-name-specifiers. llvm-svn: 82264
This commit is contained in:
parent
722b1eefdb
commit
c811ede9b7
|
@ -2270,6 +2270,14 @@ public:
|
|||
///
|
||||
/// \param S the scope in which the namespace alias declaration occurs.
|
||||
virtual void CodeCompleteNamespaceAliasDecl(Scope *S) { }
|
||||
|
||||
/// \brief Code completion for an operator name.
|
||||
///
|
||||
/// This code completion action is invoked when the code-completion token is
|
||||
/// found after the keyword "operator".
|
||||
///
|
||||
/// \param S the scope in which the operator keyword occurs.
|
||||
virtual void CodeCompleteOperatorName(Scope *S) { }
|
||||
//@}
|
||||
};
|
||||
|
||||
|
|
|
@ -220,6 +220,14 @@ public:
|
|||
///
|
||||
/// \param S the scope in which the namespace alias declaration occurs.
|
||||
virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
|
||||
|
||||
/// \brief Code completion for an operator name.
|
||||
///
|
||||
/// This code completion action is invoked when the code-completion token is
|
||||
/// found after the keyword "operator".
|
||||
///
|
||||
/// \param S the scope in which the operator keyword occurs.
|
||||
virtual void CodeCompleteOperatorName(Scope *S);
|
||||
//@}
|
||||
|
||||
/// \name Name lookup functions
|
||||
|
@ -248,14 +256,14 @@ public:
|
|||
bool IsUnion(NamedDecl *ND) const;
|
||||
bool IsNamespace(NamedDecl *ND) const;
|
||||
bool IsNamespaceOrAlias(NamedDecl *ND) const;
|
||||
bool IsType(NamedDecl *ND) const;
|
||||
//@}
|
||||
|
||||
/// \name Utility functions
|
||||
///
|
||||
//@{
|
||||
|
||||
bool canHiddenResultBeFound(NamedDecl *Hidden, NamedDecl *Visible);
|
||||
|
||||
void AddTypeSpecifierResults(unsigned Rank, ResultSet &Results);
|
||||
//@}
|
||||
};
|
||||
|
||||
|
|
|
@ -835,6 +835,18 @@ Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
|
|||
*EndLoc = Loc;
|
||||
return OO_Subscript;
|
||||
|
||||
case tok::code_completion: {
|
||||
// Code completion for the operator name.
|
||||
Actions.CodeCompleteOperatorName(CurScope);
|
||||
|
||||
// Consume the 'operator' token, then replace the code-completion token
|
||||
// with an 'operator' token and try again.
|
||||
SourceLocation OperatorLoc = ConsumeToken();
|
||||
Tok.setLocation(OperatorLoc);
|
||||
Tok.setKind(tok::kw_operator);
|
||||
return TryParseOperatorFunctionId(EndLoc);
|
||||
}
|
||||
|
||||
default:
|
||||
return OO_None;
|
||||
}
|
||||
|
|
|
@ -175,6 +175,28 @@ void CodeCompleteConsumer::CodeCompleteNamespaceAliasDecl(Scope *S) {
|
|||
ProcessCodeCompleteResults(Results.data(), Results.size());
|
||||
}
|
||||
|
||||
void CodeCompleteConsumer::CodeCompleteOperatorName(Scope *S) {
|
||||
ResultSet Results(*this, &CodeCompleteConsumer::IsType);
|
||||
|
||||
// Add the names of overloadable operators.
|
||||
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
|
||||
if (strcmp(Spelling, "?")) \
|
||||
Results.MaybeAddResult(Result(Spelling, 0));
|
||||
#include "clang/Basic/OperatorKinds.def"
|
||||
|
||||
// Add any type names visible from the current scope
|
||||
unsigned NextRank = CollectLookupResults(S, 0, Results);
|
||||
|
||||
// Add any type specifiers
|
||||
AddTypeSpecifierResults(0, Results);
|
||||
|
||||
// Add any nested-name-specifiers
|
||||
Results.setFilter(&CodeCompleteConsumer::IsNestedNameSpecifier);
|
||||
CollectLookupResults(S, NextRank + 1, Results);
|
||||
|
||||
ProcessCodeCompleteResults(Results.data(), Results.size());
|
||||
}
|
||||
|
||||
void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
|
||||
if (R.Kind != Result::RK_Declaration) {
|
||||
// For non-declaration results, just add the result.
|
||||
|
@ -208,7 +230,7 @@ void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
|
|||
|
||||
if (const IdentifierInfo *Id = R.Declaration->getIdentifier()) {
|
||||
// __va_list_tag is a freak of nature. Find it and skip it.
|
||||
if (Id->isStr("__va_list_tag"))
|
||||
if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
|
||||
return;
|
||||
|
||||
// FIXME: Should we filter out other names in the implementation's
|
||||
|
@ -522,6 +544,12 @@ bool CodeCompleteConsumer::IsNamespaceOrAlias(NamedDecl *ND) const {
|
|||
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
|
||||
}
|
||||
|
||||
/// \brief Brief determines whether the given declaration is a namespace or
|
||||
/// namespace alias.
|
||||
bool CodeCompleteConsumer::IsType(NamedDecl *ND) const {
|
||||
return isa<TypeDecl>(ND);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct VISIBILITY_HIDDEN SortCodeCompleteResult {
|
||||
typedef CodeCompleteConsumer::Result Result;
|
||||
|
@ -588,6 +616,53 @@ bool CodeCompleteConsumer::canHiddenResultBeFound(NamedDecl *Hidden,
|
|||
return HiddenCtx != Visible->getDeclContext()->getLookupContext();
|
||||
}
|
||||
|
||||
/// \brief Add type specifiers for the current language as keyword results.
|
||||
void CodeCompleteConsumer::AddTypeSpecifierResults(unsigned Rank,
|
||||
ResultSet &Results) {
|
||||
Results.MaybeAddResult(Result("short", Rank));
|
||||
Results.MaybeAddResult(Result("long", Rank));
|
||||
Results.MaybeAddResult(Result("signed", Rank));
|
||||
Results.MaybeAddResult(Result("unsigned", Rank));
|
||||
Results.MaybeAddResult(Result("void", Rank));
|
||||
Results.MaybeAddResult(Result("char", Rank));
|
||||
Results.MaybeAddResult(Result("int", Rank));
|
||||
Results.MaybeAddResult(Result("float", Rank));
|
||||
Results.MaybeAddResult(Result("double", Rank));
|
||||
Results.MaybeAddResult(Result("enum", Rank));
|
||||
Results.MaybeAddResult(Result("struct", Rank));
|
||||
Results.MaybeAddResult(Result("union", Rank));
|
||||
|
||||
if (getSema().getLangOptions().C99) {
|
||||
// C99-specific
|
||||
Results.MaybeAddResult(Result("_Complex", Rank));
|
||||
Results.MaybeAddResult(Result("_Imaginary", Rank));
|
||||
Results.MaybeAddResult(Result("_Bool", Rank));
|
||||
}
|
||||
|
||||
if (getSema().getLangOptions().CPlusPlus) {
|
||||
// C++-specific
|
||||
Results.MaybeAddResult(Result("bool", Rank));
|
||||
Results.MaybeAddResult(Result("class", Rank));
|
||||
Results.MaybeAddResult(Result("typename", Rank));
|
||||
Results.MaybeAddResult(Result("wchar_t", Rank));
|
||||
|
||||
if (getSema().getLangOptions().CPlusPlus0x) {
|
||||
Results.MaybeAddResult(Result("char16_t", Rank));
|
||||
Results.MaybeAddResult(Result("char32_t", Rank));
|
||||
Results.MaybeAddResult(Result("decltype", Rank));
|
||||
}
|
||||
}
|
||||
|
||||
// GNU extensions
|
||||
if (getSema().getLangOptions().GNUMode) {
|
||||
// FIXME: Enable when we actually support decimal floating point.
|
||||
// Results.MaybeAddResult(Result("_Decimal32", Rank));
|
||||
// Results.MaybeAddResult(Result("_Decimal64", Rank));
|
||||
// Results.MaybeAddResult(Result("_Decimal128", Rank));
|
||||
Results.MaybeAddResult(Result("typeof", Rank));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results,
|
||||
unsigned NumResults) {
|
||||
|
|
|
@ -3642,6 +3642,7 @@ public:
|
|||
virtual void CodeCompleteUsingDirective(Scope *S);
|
||||
virtual void CodeCompleteNamespaceDecl(Scope *S);
|
||||
virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
|
||||
virtual void CodeCompleteOperatorName(Scope *S);
|
||||
//@}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -101,4 +101,10 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
|
|||
CodeCompleter->CodeCompleteNamespaceAliasDecl(S);
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteOperatorName(Scope *S) {
|
||||
if (!CodeCompleter)
|
||||
return;
|
||||
|
||||
CodeCompleter->CodeCompleteOperatorName(S);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// RUN: clang-cc -fsyntax-only -code-completion-dump=1 %s -o - | FileCheck -check-prefix=CC1 %s &&
|
||||
// RUN: true
|
||||
|
||||
class T { };
|
||||
|
||||
typedef int Integer;
|
||||
|
||||
namespace N { }
|
||||
|
||||
void f() {
|
||||
typedef float Float;
|
||||
|
||||
// CHECK-CC1: Float : 0
|
||||
// CHECK-CC1: + : 0
|
||||
// CHECK-CC1: short : 0
|
||||
// CHECK-CC1: Integer : 2
|
||||
// CHECK-CC1: T : 2
|
||||
// CHECK-CC1: N : 5
|
||||
operator
|
Loading…
Reference in New Issue