From af27e8f18378769b8bb6650cb73e45df2045b50b Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Tue, 19 May 2020 11:28:40 -0700 Subject: [PATCH] [CodeCompletion] Avoid suggesting duplicated module names in global completion result. Overly modules have the same name as the shadowed modules. We should not list both names because they are identical. Maintain a set of seen module names to avoid suggesting duplicated names. rdar://problem/63370253 --- lib/IDE/CodeCompletion.cpp | 12 ++++-- .../Headers/OverlayTest.h | 2 + .../OverlayTest.framework/Headers/Overlayed.h | 13 +++++++ .../Modules/module.modulemap | 7 ++++ .../mock-sdk/OverlayTest.swiftinterface | 10 +++++ test/IDE/complete_overlaymodule.swift | 37 +++++++++++++++++++ 6 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap create mode 100644 test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface create mode 100644 test/IDE/complete_overlaymodule.swift diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 6d7e0434eb437..63d59acd325a5 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -6196,6 +6196,8 @@ void CodeCompletionCallbacksImpl::doneParsing() { break; } + llvm::SmallPtrSet seenModuleNames; + for (auto &Request: Lookup.RequestedCachedResults) { // Use the current SourceFile as the DeclContext so that we can use it to // perform qualified lookup, and to get the correct visibility for @@ -6248,7 +6250,9 @@ void CodeCompletionCallbacksImpl::doneParsing() { return; // already handled. RequestedModules.push_back({std::move(K), TheModule, Request.OnlyTypes, Request.OnlyPrecedenceGroups}); - if (Request.IncludeModuleQualifier) + + if (Request.IncludeModuleQualifier && + seenModuleNames.insert(TheModule->getName()).second) Lookup.addModuleName(TheModule); } }; @@ -6263,8 +6267,10 @@ void CodeCompletionCallbacksImpl::doneParsing() { Lookup.getToplevelCompletions(Request.OnlyTypes); // Add the qualifying module name - if (Request.IncludeModuleQualifier) - Lookup.addModuleName(CurDeclContext->getParentModule()); + auto curModule = CurDeclContext->getParentModule(); + if (Request.IncludeModuleQualifier && + seenModuleNames.insert(curModule->getName()).second) + Lookup.addModuleName(curModule); // Add results for all imported modules. ModuleDecl::ImportFilter ImportFilter; diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h new file mode 100644 index 0000000000000..b91209ef648da --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h @@ -0,0 +1,2 @@ +#include + diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h new file mode 100644 index 0000000000000..48336b32085b6 --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h @@ -0,0 +1,13 @@ + +#ifndef OVERLAYED_H +#define OVERLAYED_H + +struct __attribute__((swift_name("Overlayed"))) OVOverlayed { + double x, y, z; +}; + +double OVOverlayedInOriginalFunc(struct OVOverlayed s) __attribute__((swift_name("Overlayed.inOriginalFunc(self:)"))); + +struct OVOverlayed createOverlayed(); + +#endif diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap new file mode 100644 index 0000000000000..52db6e58085c2 --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap @@ -0,0 +1,7 @@ +framework module OverlayTest { + umbrella header "OverlayTest.h" + + export * + module * { export * } +} + diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface b/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface new file mode 100644 index 0000000000000..ad75d7f67b6ea --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface @@ -0,0 +1,10 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -module-name OverlayTest + +@_exported import OverlayTest + +public extension Overlayed { + public func inOverlayFunc() {} +} + +public func createOverlayedInOverlay() -> Overlayed diff --git a/test/IDE/complete_overlaymodule.swift b/test/IDE/complete_overlaymodule.swift new file mode 100644 index 0000000000000..b4cd14d62c226 --- /dev/null +++ b/test/IDE/complete_overlaymodule.swift @@ -0,0 +1,37 @@ +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=TYPE_GLOBAL | %FileCheck %s --check-prefix=TYPE_GLOBAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=EXPR_GLOBAL | %FileCheck %s --check-prefix=EXPR_GLOBAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=EXPR_MEMBER | %FileCheck %s --check-prefix=EXPR_MEMBER + +import OverlayTest + +func testGlobalType() { + let _: #^TYPE_GLOBAL^# +// TYPE_GLOBAL: Begin completions +// TYPE_GLOBAL-NOT: OverlayTest[#Module#] +// TYPE_GLOBAL-DAG: Decl[Module]/None: OverlayTest[#Module#]; +// TYPE_GLOBAL-NOT: OverlayTest[#Module#] +// TYPE_GLOBAL-DAG: Decl[Struct]/OtherModule[OverlayTest.Overlayed]: Overlayed[#Overlayed#]; +// TYPE_GLOBAL: End completions +} +func testGlobalExpr() { + let _ = #^EXPR_GLOBAL^# +// EPXR_GLOBAL: Begin completions +// EXPR_GLOBAL-NOT: OverlayTest[#Module#] +// EXPR_GLOBAL-DAG: Decl[Module]/None: OverlayTest[#Module#]; +// EXPR_GLOBAL-NOT: OverlayTest[#Module#] +// EXPR_GLOBAL-DAG: Decl[Struct]/OtherModule[OverlayTest.Overlayed]: Overlayed[#Overlayed#]; +// EXPR_GLOBAL-DAG: Decl[FreeFunction]/OtherModule[OverlayTest]: createOverlayedInOverlay()[#Overlayed#]; +// EXPR_GLOBAL-DAG: Decl[FreeFunction]/OtherModule[OverlayTest.Overlayed]: createOverlayed()[#Overlayed#]; +// EPXR_GLOBAL: End completions +} +func testGlobalExpr(value: Overlayed) { + value.#^EXPR_MEMBER^# +// EXPR_MEMBER: Begin completions, 6 items +// EXPR_MEMBER-DAG: Keyword[self]/CurrNominal: self[#Overlayed#]; name=self +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: x[#Double#]; name=x +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: y[#Double#]; name=y +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: z[#Double#]; name=z +// EXPR_MEMBER-DAG: Decl[InstanceMethod]/CurrNominal: inOverlayFunc()[#Void#]; name=inOverlayFunc() +// EXPR_MEMBER-DAG: Decl[InstanceMethod]/CurrNominal: inOriginalFunc()[#Double#]; name=inOriginalFunc() +// EXPR_MEMBER: End completions +}