From: Sam McCall Date: Fri, 12 Jan 2018 14:51:47 +0000 (+0000) Subject: [CodeComplete] Add an option to omit results from the preamble. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3ee4cc4acfa675c8cace6b05f2b41ed45a6a1033;p=clang [CodeComplete] Add an option to omit results from the preamble. Summary: Enumerating the contents of a namespace or global scope will omit any decls that aren't already loaded, instead of deserializing them from the PCH. This allows a fast hybrid code completion where symbols from headers are provided by an external index. (Sema already exposes the information needed to do a reasonabl job of filtering them). Clangd plans to implement this hybrid. This option is just a hint - callers still need to postfilter results if they want to *avoid* completing decls outside the main file. Reviewers: bkramer, ilya-biryukov Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D41989 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@322371 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index a0c4dc98ad..775b7acc94 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -5161,7 +5161,14 @@ enum CXCodeComplete_Flags { * \brief Whether to include brief documentation within the set of code * completions returned. */ - CXCodeComplete_IncludeBriefComments = 0x04 + CXCodeComplete_IncludeBriefComments = 0x04, + + /** + * \brief Whether to speed up completion by omitting some entities which are + * defined in the preamble. There's no guarantee any particular entity will + * be omitted. This may be useful if the headers are indexed externally. + */ + CXCodeComplete_SkipPreamble = 0x08 }; /** diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 5d280b5608..e8db3ec237 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -934,6 +934,12 @@ public: return CodeCompleteOpts.IncludeBriefComments; } + /// \brief Hint whether to load data from the external AST in order to provide + /// full results. If false, declarations from the preamble may be omitted. + bool loadExternal() const { + return CodeCompleteOpts.LoadExternal; + } + /// \brief Determine whether the output of this consumer is binary. bool isOutputBinary() const { return OutputIsBinary; } diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h index 091d8ca605..bfba2be3ec 100644 --- a/include/clang/Sema/CodeCompleteOptions.h +++ b/include/clang/Sema/CodeCompleteOptions.h @@ -35,9 +35,14 @@ public: /// Show brief documentation comments in code completion results. unsigned IncludeBriefComments : 1; + /// Hint whether to load data from the external AST in order to provide + /// full results. If false, declarations from the preamble may be omitted. + unsigned LoadExternal : 1; + CodeCompleteOptions() : IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1), - IncludeNamespaceLevelDecls(1), IncludeBriefComments(0) {} + IncludeNamespaceLevelDecls(1), IncludeBriefComments(0), + LoadExternal(1) {} }; } // namespace clang diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b4afd073c6..23aa3565d1 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3199,11 +3199,13 @@ public: void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, - bool IncludeGlobalScope = true); + bool IncludeGlobalScope = true, + bool LoadExternal = true); void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope = true, - bool IncludeDependentBases = false); + bool IncludeDependentBases = false, + bool LoadExternal = true); enum CorrectTypoKind { CTK_NonError, // CorrectTypo used in a non error recovery situation. diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 1160df15a9..74abbf3b72 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -2068,6 +2068,7 @@ void ASTUnit::CodeComplete( CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns; CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty(); CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments; + CodeCompleteOpts.LoadExternal = Consumer.loadExternal(); assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 2acc896d53..f7adaf4dcd 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3524,7 +3524,8 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); AddOrdinaryNameResults(CompletionContext, S, *this, Results); Results.ExitScope(); @@ -3599,7 +3600,8 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy); CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, - CodeCompleter->includeGlobals()); + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); Results.setFilter(nullptr); } } @@ -3669,8 +3671,9 @@ void Sema::CodeCompleteExpression(Scope *S, CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); - + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); + Results.EnterNewScope(); AddOrdinaryNameResults(PCC_Expression, S, *this, Results); Results.ExitScope(); @@ -3939,7 +3942,8 @@ static void AddRecordMembersCompletionResults(Sema &SemaRef, CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext); SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, SemaRef.CodeCompleter->includeGlobals(), - /*IncludeDependentBases=*/true); + /*IncludeDependentBases=*/true, + SemaRef.CodeCompleter->loadExternal()); if (SemaRef.getLangOpts().CPlusPlus) { if (!Results.empty()) { @@ -4049,8 +4053,9 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, if (Class) { CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.setFilter(&ResultBuilder::IsObjCIvar); - LookupVisibleDecls(Class, LookupMemberName, Consumer, - CodeCompleter->includeGlobals()); + LookupVisibleDecls( + Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(), + /*IncludeDependentBases=*/false, CodeCompleter->loadExternal()); } } @@ -4124,12 +4129,15 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { // First pass: look for tags. Results.setFilter(Filter); LookupVisibleDecls(S, LookupTagName, Consumer, - CodeCompleter->includeGlobals()); + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); if (CodeCompleter->includeGlobals()) { // Second pass: look for nested name specifiers. Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); } HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -4540,8 +4548,9 @@ void Sema::CodeCompleteAfterIf(Scope *S) { CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); - + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); + AddOrdinaryNameResults(PCC_Statement, S, *this, Results); // "else" block @@ -4649,7 +4658,8 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, /*IncludeGlobalScope=*/true, - /*IncludeDependentBases=*/true); + /*IncludeDependentBases=*/true, + CodeCompleter->loadExternal()); } auto CC = Results.getCompletionContext(); @@ -4677,7 +4687,8 @@ void Sema::CodeCompleteUsing(Scope *S) { // nested-name-specifier. CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, @@ -4698,7 +4709,8 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { Results.EnterNewScope(); CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, CodeCompletionContext::CCC_Namespace, @@ -4764,7 +4776,8 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { &ResultBuilder::IsNamespaceOrAlias); CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); @@ -4791,8 +4804,9 @@ void Sema::CodeCompleteOperatorName(Scope *S) { Results.allowNestedNameSpecifiers(); CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); - + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); + // Add any type specifiers AddTypeSpecifierResults(getLangOpts(), Results); Results.ExitScope(); @@ -5620,8 +5634,9 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); - + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); + if (CodeCompleter->includeMacros()) AddMacroResults(PP, Results, false); @@ -5834,8 +5849,9 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.EnterNewScope(); LookupVisibleDecls(S, LookupOrdinaryName, Consumer, - CodeCompleter->includeGlobals()); - + CodeCompleter->includeGlobals(), + CodeCompleter->loadExternal()); + // If we are in an Objective-C method inside a class that has a superclass, // add "super" as an option. if (ObjCMethodDecl *Method = getCurMethodDecl()) @@ -7942,8 +7958,9 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, if (!CodeCompleter || CodeCompleter->includeGlobals()) { CodeCompletionDeclConsumer Consumer(Builder, Context.getTranslationUnitDecl()); - LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, - Consumer); + LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, + Consumer, + !CodeCompleter || CodeCompleter->loadExternal()); } if (!CodeCompleter || CodeCompleter->includeMacros()) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index fb83c0f05e..c44a375d73 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -3498,7 +3498,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, bool InBaseClass, VisibleDeclConsumer &Consumer, VisibleDeclsRecord &Visited, - bool IncludeDependentBases = false) { + bool IncludeDependentBases, + bool LoadExternal) { if (!Ctx) return; @@ -3513,11 +3514,12 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, auto &Idents = S.Context.Idents; // Ensure all external identifiers are in the identifier table. - if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) { - std::unique_ptr Iter(External->getIdentifiers()); - for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next()) - Idents.get(Name); - } + if (LoadExternal) + if (IdentifierInfoLookup *External = Idents.getExternalIdentifierLookup()) { + std::unique_ptr Iter(External->getIdentifiers()); + for (StringRef Name = Iter->Next(); !Name.empty(); Name = Iter->Next()) + Idents.get(Name); + } // Walk all lookup results in the TU for each identifier. for (const auto &Ident : Idents) { @@ -3540,7 +3542,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, Result.getSema().ForceDeclarationOfImplicitMembers(Class); // Enumerate all of the results in this context. - for (DeclContextLookupResult R : Ctx->lookups()) { + for (DeclContextLookupResult R : + LoadExternal ? Ctx->lookups() : Ctx->noload_lookups()) { for (auto *D : R) { if (auto *ND = Result.getAcceptableDecl(D)) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); @@ -3557,7 +3560,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, continue; LookupVisibleDecls(I->getNominatedNamespace(), Result, QualifiedNameLookup, InBaseClass, Consumer, Visited, - IncludeDependentBases); + IncludeDependentBases, LoadExternal); } } @@ -3614,7 +3617,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, // Find results in this base class (and its bases). ShadowContextRAII Shadow(Visited); LookupVisibleDecls(RD, Result, QualifiedNameLookup, true, Consumer, - Visited, IncludeDependentBases); + Visited, IncludeDependentBases, LoadExternal); } } @@ -3623,22 +3626,23 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, // Traverse categories. for (auto *Cat : IFace->visible_categories()) { ShadowContextRAII Shadow(Visited); - LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false, - Consumer, Visited); + LookupVisibleDecls(Cat, Result, QualifiedNameLookup, false, Consumer, + Visited, IncludeDependentBases, LoadExternal); } // Traverse protocols. for (auto *I : IFace->all_referenced_protocols()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer, - Visited); + Visited, IncludeDependentBases, LoadExternal); } // Traverse the superclass. if (IFace->getSuperClass()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup, - true, Consumer, Visited); + true, Consumer, Visited, IncludeDependentBases, + LoadExternal); } // If there is an implementation, traverse it. We do this to find @@ -3646,26 +3650,28 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, if (IFace->getImplementation()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(IFace->getImplementation(), Result, - QualifiedNameLookup, InBaseClass, Consumer, Visited); + QualifiedNameLookup, InBaseClass, Consumer, Visited, + IncludeDependentBases, LoadExternal); } } else if (ObjCProtocolDecl *Protocol = dyn_cast(Ctx)) { for (auto *I : Protocol->protocols()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer, - Visited); + Visited, IncludeDependentBases, LoadExternal); } } else if (ObjCCategoryDecl *Category = dyn_cast(Ctx)) { for (auto *I : Category->protocols()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(I, Result, QualifiedNameLookup, false, Consumer, - Visited); + Visited, IncludeDependentBases, LoadExternal); } // If there is an implementation, traverse it. if (Category->getImplementation()) { ShadowContextRAII Shadow(Visited); LookupVisibleDecls(Category->getImplementation(), Result, - QualifiedNameLookup, true, Consumer, Visited); + QualifiedNameLookup, true, Consumer, Visited, + IncludeDependentBases, LoadExternal); } } } @@ -3673,7 +3679,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, static void LookupVisibleDecls(Scope *S, LookupResult &Result, UnqualUsingDirectiveSet &UDirs, VisibleDeclConsumer &Consumer, - VisibleDeclsRecord &Visited) { + VisibleDeclsRecord &Visited, + bool LoadExternal) { if (!S) return; @@ -3712,7 +3719,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, Result.getNameLoc(), Sema::LookupMemberName); if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) { LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); + /*InBaseClass=*/false, Consumer, Visited, + /*IncludeDependentBases=*/false, LoadExternal); } } @@ -3726,7 +3734,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, continue; LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); + /*InBaseClass=*/false, Consumer, Visited, + /*IncludeDependentBases=*/false, LoadExternal); } } else if (!S->getParent()) { // Look into the translation unit scope. We walk through the translation @@ -3740,7 +3749,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, // in DeclContexts unless we have to" optimization), we can eliminate this. Entity = Result.getSema().Context.getTranslationUnitDecl(); LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); + /*InBaseClass=*/false, Consumer, Visited, + /*IncludeDependentBases=*/false, LoadExternal); } if (Entity) { @@ -3749,17 +3759,19 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, for (const UnqualUsingEntry &UUE : UDirs.getNamespacesFor(Entity)) LookupVisibleDecls(const_cast(UUE.getNominatedNamespace()), Result, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); + /*InBaseClass=*/false, Consumer, Visited, + /*IncludeDependentBases=*/false, LoadExternal); } // Lookup names in the parent scope. ShadowContextRAII Shadow(Visited); - LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited); + LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited, + LoadExternal); } void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, - bool IncludeGlobalScope) { + bool IncludeGlobalScope, bool LoadExternal) { // Determine the set of using directives available during // unqualified name lookup. Scope *Initial = S; @@ -3780,13 +3792,13 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, if (!IncludeGlobalScope) Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); - ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited); + ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited, LoadExternal); } void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope, - bool IncludeDependentBases) { + bool IncludeDependentBases, bool LoadExternal) { LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); Result.setAllowHidden(Consumer.includeHiddenDecls()); VisibleDeclsRecord Visited; @@ -3795,7 +3807,7 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, /*InBaseClass=*/false, Consumer, Visited, - IncludeDependentBases); + IncludeDependentBases, LoadExternal); } /// LookupOrCreateLabel - Do a name lookup of a label with the specified name. diff --git a/test/Index/complete-pch-skip.cpp b/test/Index/complete-pch-skip.cpp new file mode 100644 index 0000000000..866976f990 --- /dev/null +++ b/test/Index/complete-pch-skip.cpp @@ -0,0 +1,18 @@ +namespace ns { +int bar; +} + +int main() { return ns:: } + +// RUN: echo "namespace ns { int foo; }" > %t.h +// RUN: c-index-test -write-pch %t.h.pch -x c++-header %t.h +// +// RUN: c-index-test -code-completion-at=%s:5:26 -include %t.h %s | FileCheck -check-prefix=WITH-PCH %s +// WITH-PCH: {TypedText bar} +// WITH-PCH: {TypedText foo} + +// RUN: env CINDEXTEST_COMPLETION_SKIP_PREAMBLE=1 c-index-test -code-completion-at=%s:5:26 -include %t.h %s | FileCheck -check-prefix=SKIP-PCH %s +// SKIP-PCH-NOT: foo +// SKIP-PCH: {TypedText bar} +// SKIP-PCH-NOT: foo + diff --git a/test/Index/complete-pch-skip.h b/test/Index/complete-pch-skip.h new file mode 100644 index 0000000000..f7422af773 --- /dev/null +++ b/test/Index/complete-pch-skip.h @@ -0,0 +1,3 @@ +namespace ns { +int foo; +} diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index c5e345ef6a..2094be339c 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -2326,6 +2326,8 @@ int perform_code_completion(int argc, const char **argv, int timing_only) { completionOptions |= CXCodeComplete_IncludeCodePatterns; if (getenv("CINDEXTEST_COMPLETION_BRIEF_COMMENTS")) completionOptions |= CXCodeComplete_IncludeBriefComments; + if (getenv("CINDEXTEST_COMPLETION_SKIP_PREAMBLE")) + completionOptions |= CXCodeComplete_SkipPreamble; if (timing_only) input += strlen("-code-completion-timing="); diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index d4af0870c0..ba2c818cca 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -643,6 +643,7 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, ArrayRef unsaved_files, unsigned options) { bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments; + bool SkipPreamble = options & CXCodeComplete_SkipPreamble; #ifdef UDP_CODE_COMPLETION_LOGGER #ifdef UDP_CODE_COMPLETION_LOGGER_PORT @@ -689,6 +690,7 @@ clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename, // Create a code-completion consumer to capture the results. CodeCompleteOptions Opts; Opts.IncludeBriefComments = IncludeBriefComments; + Opts.LoadExternal = !SkipPreamble; CaptureCompletionResults Capture(Opts, *Results, &TU); // Perform completion.