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:
Douglas Gregor 2009-09-18 20:05:18 +00:00
parent 722b1eefdb
commit c811ede9b7
7 changed files with 134 additions and 5 deletions

View File

@ -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) { }
//@}
};

View File

@ -219,7 +219,15 @@ public:
/// found after "namespace identifier = ".
///
/// \param S the scope in which the namespace alias declaration occurs.
virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
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);
//@}
};

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);
//@}
//===--------------------------------------------------------------------===//

View File

@ -101,4 +101,10 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
CodeCompleter->CodeCompleteNamespaceAliasDecl(S);
}
void Sema::CodeCompleteOperatorName(Scope *S) {
if (!CodeCompleter)
return;
CodeCompleter->CodeCompleteOperatorName(S);
}

View File

@ -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