diff options
-rw-r--r-- | include/clang/Frontend/ASTUnit.h | 3 | ||||
-rw-r--r-- | include/clang/Sema/CodeCompleteConsumer.h | 59 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 45 | ||||
-rw-r--r-- | test/Index/complete-exprs.c | 2 | ||||
-rw-r--r-- | test/Index/complete-macros.c | 2 |
6 files changed, 98 insertions, 37 deletions
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 76a86871de..f18e70e750 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -232,6 +232,9 @@ public: /// \brief The libclang cursor kind corresponding to this code-completion /// result. CXCursorKind Kind; + + /// \brief The simplified type class for a non-macro completion result. + SimplifiedTypeClass TypeClass; }; private: diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 16dd69d401..82ea46c290 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H #include "clang/AST/Type.h" +#include "clang/AST/CanonicalType.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "clang-c/Index.h" @@ -72,7 +73,38 @@ enum { /// Objective-C object pointer types). CCF_SimilarTypeMatch = 2 }; + +/// \brief A simplified classification of types used when determining +/// "similar" types for code completion. +enum SimplifiedTypeClass { + STC_Arithmetic, + STC_Array, + STC_Block, + STC_Function, + STC_ObjectiveC, + STC_Other, + STC_Pointer, + STC_Record, + STC_Void +}; + +/// \brief Determine the simplified type class of the given canonical type. +SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T); +/// \brief Determine the type that this declaration will have if it is used +/// as a type or in an expression. +QualType getDeclUsageType(ASTContext &C, NamedDecl *ND); + +/// \brief Determine the priority to be given to a macro code completion result +/// with the given name. +/// +/// \param MacroName The name of the macro. +/// +/// \param PreferredTypeIsPointer Whether the preferred type for the context +/// of this macro is a pointer type. +unsigned getMacroUsagePriority(llvm::StringRef MacroName, + bool PreferredTypeIsPointer = false); + class FunctionDecl; class FunctionType; class FunctionTemplateDecl; @@ -138,29 +170,36 @@ public: private: enum Kind Kind; + /// \brief The type that would prefer to see at this point (e.g., the type + /// of an initializer or function parameter). + QualType PreferredType; + /// \brief The type of the base object in a member access expression. - QualType Type; + QualType BaseType; public: /// \brief Construct a new code-completion context of the given kind. - CodeCompletionContext(enum Kind Kind) : Kind(Kind) { - assert(Kind != CCC_MemberAccess && "Member access requires a type"); - } + CodeCompletionContext(enum Kind Kind) : Kind(Kind) { } /// \brief Construct a new code-completion context of the given kind. - CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind), Type(T) { - assert(Kind == CCC_MemberAccess && "Only member access has a type"); + CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) { + if (Kind == CCC_MemberAccess) + BaseType = T; + else + PreferredType = T; } /// \brief Retrieve the kind of code-completion context. enum Kind getKind() const { return Kind; } + /// \brief Retrieve the type that this expression would prefer to have, e.g., + /// if the expression is a variable initializer or a function argument, the + /// type of the corresponding variable or function parameter. + QualType getPreferredType() const { return PreferredType; } + /// \brief Retrieve the type of the base object in a member-access /// expression. - QualType getType() const { - assert(Kind == CCC_MemberAccess && "Only member access has a type"); - return Type; - } + QualType getBaseType() const { return BaseType; } }; diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 8ac5b681a6..a573fb41ab 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -191,6 +191,10 @@ void ASTUnit::CacheCodeCompletionResults() { Ctx->getLangOptions()); CachedResult.Priority = Results[I].Priority; CachedResult.Kind = Results[I].CursorKind; + CachedResult.TypeClass + = getSimplifiedTypeClass( + Ctx->getCanonicalType(getDeclUsageType(*Ctx, + Results[I].Declaration))); CachedCompletionResults.push_back(CachedResult); break; } @@ -215,6 +219,7 @@ void ASTUnit::CacheCodeCompletionResults() { | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); CachedResult.Priority = Results[I].Priority; CachedResult.Kind = Results[I].CursorKind; + CachedResult.TypeClass = STC_Void; CachedCompletionResults.push_back(CachedResult); break; } @@ -1417,7 +1422,24 @@ namespace { AddedResult = true; } - AllResults.push_back(Result(C->Completion, C->Priority, C->Kind)); + // Adjust priority based on similar type classes. + unsigned Priority = C->Priority; + if (!Context.getPreferredType().isNull()) { + if (C->Kind == CXCursor_MacroDefinition) { + Priority = getMacroUsagePriority(C->Completion->getTypedText(), + Context.getPreferredType()->isAnyPointerType()); + } else { + CanQualType Expected + = S.Context.getCanonicalType(Context.getPreferredType()); + SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected); + if (ExpectedSTC == C->TypeClass) { + // FIXME: How can we check for an exact match? + Priority /= CCF_SimilarTypeMatch; + } + } + } + + AllResults.push_back(Result(C->Completion, Priority, C->Kind)); } // If we did not add any cached completion results, just forward the diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 599a10fd90..332f8c8029 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -476,21 +476,9 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, return false; } -enum SimplifiedTypeClass { - STC_Arithmetic, - STC_Array, - STC_Block, - STC_Function, - STC_ObjectiveC, - STC_Other, - STC_Pointer, - STC_Record, - STC_Void -}; - /// \brief A simplified classification of types used to determine whether two /// types are "similar enough" when adjusting priorities. -static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) { +SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { switch (T->getTypeClass()) { case Type::Builtin: switch (cast<BuiltinType>(T)->getKind()) { @@ -561,7 +549,7 @@ static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) { /// \brief Get the type that a given expression will have if this declaration /// is used as an expression in its "typical" code-completion form. -static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) { +QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) @@ -2202,6 +2190,20 @@ namespace { }; } +unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName, + bool PreferredTypeIsPointer) { + unsigned Priority = CCP_Macro; + + // Treat the "nil" and "NULL" macros as null pointer constants. + if (MacroName.equals("nil") || MacroName.equals("NULL")) { + Priority = CCP_Constant; + if (PreferredTypeIsPointer) + Priority = Priority / CCF_SimilarTypeMatch; + } + + return Priority; +} + static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, bool TargetTypeIsPointer = false) { typedef CodeCompleteConsumer::Result Result; @@ -2210,16 +2212,9 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); M != MEnd; ++M) { - unsigned Priority = CCP_Macro; - - // Treat the "nil" and "NULL" macros as null pointer constants. - if (M->first->isStr("nil") || M->first->isStr("NULL")) { - Priority = CCP_Constant; - if (TargetTypeIsPointer) - Priority = Priority / CCF_SimilarTypeMatch; - } - - Results.AddResult(Result(M->first, Priority)); + Results.AddResult(Result(M->first, + getMacroUsagePriority(M->first->getName(), + TargetTypeIsPointer))); } Results.ExitScope(); } @@ -2356,7 +2351,7 @@ void Sema::CodeCompleteExpression(Scope *S, QualType T, if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, PreferredTypeIsPointer); HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Expression, + CodeCompletionContext(CodeCompletionContext::CCC_Expression, T), Results.data(),Results.size()); } diff --git a/test/Index/complete-exprs.c b/test/Index/complete-exprs.c index 7dfe280d9e..3605420956 100644 --- a/test/Index/complete-exprs.c +++ b/test/Index/complete-exprs.c @@ -23,7 +23,7 @@ const char *str = "Hello, \nWorld"; // FIXME: Priorities aren't right // CHECK-CC1a: ParmDecl:{ResultType int}{TypedText j} (2) // CHECK-CC1a: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) -// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50) +// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (25) // CHECK-CC1a: macro definition:{TypedText __VERSION__} (70) // RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s // RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s diff --git a/test/Index/complete-macros.c b/test/Index/complete-macros.c index d0974db31f..26a63b151b 100644 --- a/test/Index/complete-macros.c +++ b/test/Index/complete-macros.c @@ -20,6 +20,8 @@ void f2() { // CHECK-CC1: macro definition:{TypedText FOO}{LeftParen (}{Placeholder Arg1}{Comma , }{Placeholder Arg2}{RightParen )} // RUN: c-index-test -code-completion-at=%s:13:13 %s | FileCheck -check-prefix=CHECK-CC2 %s // RUN: c-index-test -code-completion-at=%s:14:8 %s | FileCheck -check-prefix=CHECK-CC2 %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:14:8 %s | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2: macro definition:{TypedText nil} (30) // RUN: c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC3 %s +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:15:5 %s | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: macro definition:{TypedText nil} (60) |