From 4742146da9ce64f632933c86f160c93eb990ae30 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Thu, 3 Jul 2025 22:04:12 +0300 Subject: [PATCH 01/58] [Demangle] Implement Swift USR to Decl conversion --- include/swift/AST/ASTDemangler.h | 9 ++ lib/AST/ASTDemangler.cpp | 252 +++++++++++++++++++++++++++++++ 2 files changed, 261 insertions(+) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 702072ddb3c83..521632e08f709 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -33,7 +33,9 @@ namespace swift { +class Decl; class TypeDecl; +class DeclName; namespace Demangle { SWIFT_BEGIN_INLINE_NAMESPACE @@ -50,6 +52,11 @@ TypeDecl *getTypeDeclForUSR(ASTContext &ctx, llvm::StringRef usr, GenericSignature genericSig=GenericSignature()); +Decl *getDeclFromUSR(ASTContext &ctx, + llvm::StringRef usr, + const DeclContext *lookupDC, + GenericSignature genericSig=GenericSignature()); + /// An implementation of MetadataReader's BuilderType concept that /// just finds and builds things in the AST. class ASTBuilder { @@ -121,6 +128,8 @@ class ASTBuilder { DeclContext *getNotionalDC(); Demangle::NodeFactory &getNodeFactory() { return Factory; } + + Decl *findDecl(NodePointer node, StringRef usr, const DeclContext *lookupDC); Type decodeMangledType(NodePointer node, bool forRequirement = true); Type createBuiltinType(StringRef builtinName, StringRef mangledName); diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 7983d8d9831a0..7c512840046cb 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -27,6 +27,9 @@ #include "swift/AST/GenericSignature.h" #include "swift/AST/Module.h" #include "swift/AST/NameLookup.h" +#include "swift/AST/ModuleNameLookup.h" +#include "swift/AST/NameLookupRequests.h" +#include "swift/AST/USRGeneration.h" #include "swift/AST/SILLayout.h" #include "swift/AST/Type.h" #include "swift/AST/TypeCheckRequests.h" @@ -39,6 +42,177 @@ using namespace swift; +class DeclNameExtractor { + ASTContext &Ctx; + +public: + DeclNameExtractor(ASTContext &ctx) : Ctx(ctx) {} + + /// Extract a DeclName from a demangling node + DeclName extractDeclName(Node *node) { + if (node == nullptr) + return DeclName(); + + switch (node->getKind()) { + case Node::Kind::Class: + case Node::Kind::Structure: + case Node::Kind::Enum: + case Node::Kind::Protocol: + case Node::Kind::TypeAlias: + case Node::Kind::OtherNominalType: + case Node::Kind::AssociatedType: + case Node::Kind::AssociatedTypeRef: + case Node::Kind::GenericTypeParamDecl: + case Node::Kind::Variable: + case Node::Kind::Macro: + return extractIdentifierName(node); + + case Node::Kind::Constructor: + case Node::Kind::Allocator: + return DeclName(DeclBaseName::createConstructor()); + + case Node::Kind::Destructor: + case Node::Kind::Deallocator: + case Node::Kind::IsolatedDeallocator: + return DeclName(DeclBaseName::createDestructor()); + + case Node::Kind::Module: + return extractTextName(node); + + case Node::Kind::Function: + return extractFunctionLikeName(node); + + case Node::Kind::Subscript: + return extractFunctionLikeName(node); + + default: + // For any other node types, we can't extract a meaningful name + return DeclName(); + } + + } + +private: + DeclName extractIdentifierName(Node *node) { + auto Identifier = node->getChild(1); + if (Identifier == nullptr || + Identifier->getKind() != Node::Kind::Identifier) + return DeclName(); + + return extractTextName(Identifier); + } + + DeclName extractTextName(Node *node) { + if (!node->hasText()) + return DeclName(); + + auto identifier = Ctx.getIdentifier(node->getText()); + return DeclName(identifier); + } + + DeclName extractFunctionLikeName(Node *node) { + assert(node->getKind() == Node::Kind::Function || + node->getKind() == Node::Kind::Subscript); + + DeclBaseName BaseName; + if (node->getKind() == Node::Kind::Function) + BaseName = extractIdentifierName(node).getBaseName(); + else + BaseName = DeclBaseName::createSubscript(); + + if (BaseName.empty()) + return DeclName(); + + // Location of LabelList node if present, otherwise a Type node. + unsigned LabelListIdx; + if (node->getKind() == Node::Kind::Function) + LabelListIdx = 2; + else + LabelListIdx = 1; + + auto *LabelsOrType = node->getChild(LabelListIdx); + assert(LabelsOrType != nullptr && (LabelsOrType->getKind() == Node::Kind::LabelList || + LabelsOrType->getKind() == Node::Kind::Type)); + + SmallVector ArgLabels; + if (LabelsOrType->getKind() == Node::Kind::LabelList) + extractArgLabelsFromLabelList(LabelsOrType, ArgLabels); + else + extractArgLabelsFromType(LabelsOrType, ArgLabels); + + if (ArgLabels.empty()) + return DeclName(BaseName); + + return DeclName(Ctx, BaseName, ArgLabels); + } + + void extractArgLabelsFromLabelList(Node *LabelList, + SmallVectorImpl &ArgLabels) { + assert(LabelList->getKind() == Node::Kind::LabelList); + + for (unsigned i = 0; i < LabelList->getNumChildren(); ++i) { + auto *Label = LabelList->getChild(i); + + assert(Label && (Label->getKind() == Node::Kind::Identifier || + Label->getKind() == Node::Kind::FirstElementMarker)); + + if (Label->getKind() == Node::Kind::Identifier) { + ArgLabels.push_back(Ctx.getIdentifier(Label->getText())); + } else { + ArgLabels.push_back(Identifier()); + } + } + } + + void extractArgLabelsFromType(Node *Type, SmallVectorImpl &ArgLabels) { + auto ArgTuple = Type->findByKind(Demangle::Node::Kind::ArgumentTuple, + /*maxDepth=*/5); + if (ArgTuple == nullptr) + return; + + auto Params = ArgTuple->getFirstChild(); + auto ParamsType = Params->getFirstChild(); + if (ParamsType == nullptr) + return; + + if (ParamsType->getKind() != Demangle::Node::Kind::Tuple) { + // A single, unnamed parameter + ArgLabels.push_back(Identifier()); + return; + } + + // More than one parameter are present + while (Params && Params->getFirstChild() && + Params->getFirstChild()->getKind() != Node::Kind::TupleElement) { + Params = Params->getFirstChild(); + } + + if (Params) { + for (size_t i = 0; i < Params->getNumChildren(); ++i) { + ArgLabels.push_back(Identifier()); + } + } + } +}; + + +Decl *swift::Demangle::getDeclFromUSR(ASTContext &ctx, + StringRef usr, + const DeclContext *lookupDC, + GenericSignature genericSig) { + if (!usr.starts_with("s:")) + return nullptr; + + std::string mangling(usr); + mangling.replace(0, 2, MANGLING_PREFIX_STR); + + Demangle::Context Dem; + auto node = Dem.demangleSymbolAsNode(mangling); + + ASTBuilder builder(ctx, genericSig); + return builder.findDecl(node, usr, lookupDC); +} + Type swift::Demangle::getTypeForMangling(ASTContext &ctx, StringRef mangling, GenericSignature genericSig) { @@ -75,6 +249,84 @@ TypeDecl *swift::Demangle::getTypeDeclForUSR(ASTContext &ctx, return getTypeDeclForMangling(ctx, mangling, genericSig); } +Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, + const DeclContext *lookupDC) { + if (node == nullptr) + return nullptr; + + if (auto *TD = createTypeDecl(node)) + return TD; + + switch (node->getKind()) { + default: + // We should have probably arrived at a probable declaration node by now + break; + case Node::Kind::Global: + case Node::Kind::Static: + case Node::Kind::BoundGenericEnum: + case Node::Kind::BoundGenericClass: + case Node::Kind::BoundGenericFunction: + case Node::Kind::BoundGenericProtocol: + case Node::Kind::BoundGenericStructure: + case Node::Kind::BoundGenericTypeAlias: + case Node::Kind::BoundGenericOtherNominalType: + case Node::Kind::Extension: + return findDecl(node->getFirstChild(), usr, lookupDC); + } + + DeclNameExtractor NameExtractor(Ctx); + auto name = NameExtractor.extractDeclName(node); + + auto DeclContextNode = node->getFirstChild(); + if (DeclContextNode == nullptr) + return nullptr; + + SmallVector candidates; + if (DeclContextNode->getKind() == Node::Kind::Module) { + auto PotentialModules = findPotentialModules(DeclContextNode); + + for (auto *Module : PotentialModules) { + auto *moduleScopeContext = Module->getModuleScopeContext(); + namelookup::lookupInModule(Module, name, candidates, + NLKind::QualifiedLookup, namelookup::ResolutionKind::Overloadable, + moduleScopeContext, SourceLoc(), NL_QualifiedDefault); + } + } else { + auto *ownerDC = findDeclContext(DeclContextNode); + if (!ownerDC) + return nullptr; + + if (auto *nominal = ownerDC->getSelfNominalTypeDecl()) { + auto result = nominal->lookupDirect(name); + candidates.append(result.begin(), result.end()); + } else { + UnqualifiedLookupDescriptor desc(DeclNameRef(name), ownerDC); + + auto result = evaluateOrDefault(Ctx.evaluator, + UnqualifiedLookupRequest(desc), + LookupResult()); + + for (const auto& entry : result) { + if (auto *VD = entry.getValueDecl()) + candidates.push_back(VD); + } + } + } + + for (auto *candidate : candidates) { + SmallString<128> candidateUSR; + llvm::raw_svector_ostream OS(candidateUSR); + + if (ide::printDeclUSR(candidate, OS)) + continue; + + if (usr == candidateUSR) + return candidate; + } + + return nullptr; +} + Type ASTBuilder::decodeMangledType(NodePointer node, bool forRequirement) { return swift::Demangle::decodeMangledType(*this, node, forRequirement) .getType(); From edcc3908491f8fd4b1e89af06e13e3648af7c12e Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 4 Jul 2025 15:02:41 +0300 Subject: [PATCH 02/58] [Demangle] Separate DeclNameExtractor & Clang USR to Decl --- include/swift/AST/DeclNameExtractor.h | 47 +++++++ lib/AST/ASTDemangler.cpp | 177 +++----------------------- lib/AST/CMakeLists.txt | 1 + lib/AST/DeclNameExtractor.cpp | 165 ++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 156 deletions(-) create mode 100644 include/swift/AST/DeclNameExtractor.h create mode 100644 lib/AST/DeclNameExtractor.cpp diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h new file mode 100644 index 0000000000000..0b162d89c60d2 --- /dev/null +++ b/include/swift/AST/DeclNameExtractor.h @@ -0,0 +1,47 @@ +//===--- DeclNameExtractor.h - Swift Language Type Locations --------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines the DeclNameExtractor utility. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/ASTContext.h" +#include "swift/AST/Identifier.h" + +namespace swift { +namespace Demangle { + +class Node; + +class DeclNameExtractor { +private: + ASTContext &Ctx; + +public: + DeclNameExtractor(ASTContext &ctx) : Ctx(ctx) {} + + /// Extract a DeclName from a demangling node + DeclName extractDeclName(Node *node); + +private: + DeclName extractIdentifierName(Node *node); + DeclName extractTextName(Node *node); + DeclName extractFunctionLikeName(Node *node); + void extractArgLabelsFromLabelList(Node *LabelList, + SmallVectorImpl &ArgLabels); + void extractArgLabelsFromType(Node *Type, + SmallVectorImpl &ArgLabels); +}; + + +} // end namespace swift +} // end namespace Demangle diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 7c512840046cb..4600be9cf0e79 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -24,6 +24,7 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/ClangModuleLoader.h" #include "swift/AST/Decl.h" +#include "swift/AST/DeclNameExtractor.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/Module.h" #include "swift/AST/NameLookup.h" @@ -39,167 +40,21 @@ #include "swift/Demangling/Demangler.h" #include "swift/Demangling/ManglingMacros.h" #include "llvm/ADT/StringSwitch.h" +#include "clang/Tooling/Refactor/USRFinder.h" using namespace swift; -class DeclNameExtractor { - ASTContext &Ctx; - -public: - DeclNameExtractor(ASTContext &ctx) : Ctx(ctx) {} - - /// Extract a DeclName from a demangling node - DeclName extractDeclName(Node *node) { - if (node == nullptr) - return DeclName(); - - switch (node->getKind()) { - case Node::Kind::Class: - case Node::Kind::Structure: - case Node::Kind::Enum: - case Node::Kind::Protocol: - case Node::Kind::TypeAlias: - case Node::Kind::OtherNominalType: - case Node::Kind::AssociatedType: - case Node::Kind::AssociatedTypeRef: - case Node::Kind::GenericTypeParamDecl: - case Node::Kind::Variable: - case Node::Kind::Macro: - return extractIdentifierName(node); - - case Node::Kind::Constructor: - case Node::Kind::Allocator: - return DeclName(DeclBaseName::createConstructor()); - - case Node::Kind::Destructor: - case Node::Kind::Deallocator: - case Node::Kind::IsolatedDeallocator: - return DeclName(DeclBaseName::createDestructor()); - - case Node::Kind::Module: - return extractTextName(node); - - case Node::Kind::Function: - return extractFunctionLikeName(node); - - case Node::Kind::Subscript: - return extractFunctionLikeName(node); - - default: - // For any other node types, we can't extract a meaningful name - return DeclName(); - } - - } - -private: - DeclName extractIdentifierName(Node *node) { - auto Identifier = node->getChild(1); - if (Identifier == nullptr || - Identifier->getKind() != Node::Kind::Identifier) - return DeclName(); - - return extractTextName(Identifier); - } - - DeclName extractTextName(Node *node) { - if (!node->hasText()) - return DeclName(); - - auto identifier = Ctx.getIdentifier(node->getText()); - return DeclName(identifier); - } - - DeclName extractFunctionLikeName(Node *node) { - assert(node->getKind() == Node::Kind::Function || - node->getKind() == Node::Kind::Subscript); - - DeclBaseName BaseName; - if (node->getKind() == Node::Kind::Function) - BaseName = extractIdentifierName(node).getBaseName(); - else - BaseName = DeclBaseName::createSubscript(); - - if (BaseName.empty()) - return DeclName(); - - // Location of LabelList node if present, otherwise a Type node. - unsigned LabelListIdx; - if (node->getKind() == Node::Kind::Function) - LabelListIdx = 2; - else - LabelListIdx = 1; - - auto *LabelsOrType = node->getChild(LabelListIdx); - assert(LabelsOrType != nullptr && (LabelsOrType->getKind() == Node::Kind::LabelList || - LabelsOrType->getKind() == Node::Kind::Type)); - - SmallVector ArgLabels; - if (LabelsOrType->getKind() == Node::Kind::LabelList) - extractArgLabelsFromLabelList(LabelsOrType, ArgLabels); - else - extractArgLabelsFromType(LabelsOrType, ArgLabels); - - if (ArgLabels.empty()) - return DeclName(BaseName); - - return DeclName(Ctx, BaseName, ArgLabels); - } - - void extractArgLabelsFromLabelList(Node *LabelList, - SmallVectorImpl &ArgLabels) { - assert(LabelList->getKind() == Node::Kind::LabelList); - - for (unsigned i = 0; i < LabelList->getNumChildren(); ++i) { - auto *Label = LabelList->getChild(i); - - assert(Label && (Label->getKind() == Node::Kind::Identifier || - Label->getKind() == Node::Kind::FirstElementMarker)); - - if (Label->getKind() == Node::Kind::Identifier) { - ArgLabels.push_back(Ctx.getIdentifier(Label->getText())); - } else { - ArgLabels.push_back(Identifier()); - } - } - } - - void extractArgLabelsFromType(Node *Type, SmallVectorImpl &ArgLabels) { - auto ArgTuple = Type->findByKind(Demangle::Node::Kind::ArgumentTuple, - /*maxDepth=*/5); - if (ArgTuple == nullptr) - return; - - auto Params = ArgTuple->getFirstChild(); - auto ParamsType = Params->getFirstChild(); - if (ParamsType == nullptr) - return; - - if (ParamsType->getKind() != Demangle::Node::Kind::Tuple) { - // A single, unnamed parameter - ArgLabels.push_back(Identifier()); - return; - } - - // More than one parameter are present - while (Params && Params->getFirstChild() && - Params->getFirstChild()->getKind() != Node::Kind::TupleElement) { - Params = Params->getFirstChild(); - } - - if (Params) { - for (size_t i = 0; i < Params->getNumChildren(); ++i) { - ArgLabels.push_back(Identifier()); - } - } - } -}; +static Decl *getClangDeclFromUSR(ASTContext &ctx, StringRef usr) { + auto *clangLoader = ctx.getClangModuleLoader(); + auto &clangCtx = clangLoader->getClangASTContext(); + auto *clangDecl = clang::tooling::rename::getNamedDeclWithUSR(clangCtx, usr); + return clangLoader->importDeclDirectly(clangDecl); +} -Decl *swift::Demangle::getDeclFromUSR(ASTContext &ctx, - StringRef usr, - const DeclContext *lookupDC, - GenericSignature genericSig) { +static Decl *getSwiftDeclFromUSR(ASTContext &ctx, StringRef usr, + const DeclContext *lookupDC, + GenericSignature genericSig) { if (!usr.starts_with("s:")) return nullptr; @@ -213,6 +68,16 @@ Decl *swift::Demangle::getDeclFromUSR(ASTContext &ctx, return builder.findDecl(node, usr, lookupDC); } +Decl *swift::Demangle::getDeclFromUSR(ASTContext &ctx, + StringRef usr, + const DeclContext *lookupDC, + GenericSignature genericSig) { + if (usr.starts_with("c:")) + return getClangDeclFromUSR(ctx, usr); + + return getSwiftDeclFromUSR(ctx, usr, lookupDC, genericSig); +} + Type swift::Demangle::getTypeForMangling(ASTContext &ctx, StringRef mangling, GenericSignature genericSig) { diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 3b820c1aa7258..586182c6cc9ce 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -45,6 +45,7 @@ add_swift_host_library(swiftAST STATIC Decl.cpp DeclContext.cpp DeclContextDumper.cpp + DeclNameExtractor.cpp DeclNameLoc.cpp DiagnosticArgument.cpp DiagnosticBridge.cpp diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp new file mode 100644 index 0000000000000..d6a86822a3aed --- /dev/null +++ b/lib/AST/DeclNameExtractor.cpp @@ -0,0 +1,165 @@ +//===--- DeclNameExtractor.cpp ----------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file implements the DeclNameExtractor utility. +// +//===----------------------------------------------------------------------===// + +#include "swift/AST/ASTContext.h" +#include "swift/AST/DeclNameExtractor.h" + +using namespace swift; +using namespace Demangle; + +DeclName DeclNameExtractor::extractDeclName(Node *node) { + if (node == nullptr) + return DeclName(); + + switch (node->getKind()) { + case Node::Kind::Class: + case Node::Kind::Structure: + case Node::Kind::Enum: + case Node::Kind::Protocol: + case Node::Kind::TypeAlias: + case Node::Kind::OtherNominalType: + case Node::Kind::AssociatedType: + case Node::Kind::AssociatedTypeRef: + case Node::Kind::GenericTypeParamDecl: + case Node::Kind::Variable: + case Node::Kind::Macro: + return extractIdentifierName(node); + + case Node::Kind::Constructor: + case Node::Kind::Allocator: + return DeclName(DeclBaseName::createConstructor()); + + case Node::Kind::Destructor: + case Node::Kind::Deallocator: + case Node::Kind::IsolatedDeallocator: + return DeclName(DeclBaseName::createDestructor()); + + case Node::Kind::Module: + return extractTextName(node); + + case Node::Kind::Function: + return extractFunctionLikeName(node); + + case Node::Kind::Subscript: + return extractFunctionLikeName(node); + + default: + // For any other node types, we can't extract a meaningful name + return DeclName(); + } + +} + +DeclName DeclNameExtractor::extractIdentifierName(Node *node) { + auto Identifier = node->getChild(1); + if (Identifier == nullptr || + Identifier->getKind() != Node::Kind::Identifier) + return DeclName(); + + return extractTextName(Identifier); +} + +DeclName DeclNameExtractor::extractTextName(Node *node) { + if (!node->hasText()) + return DeclName(); + + auto identifier = Ctx.getIdentifier(node->getText()); + return DeclName(identifier); +} + +DeclName DeclNameExtractor::extractFunctionLikeName(Node *node) { + assert(node->getKind() == Node::Kind::Function || + node->getKind() == Node::Kind::Subscript); + + DeclBaseName BaseName; + if (node->getKind() == Node::Kind::Function) + BaseName = extractIdentifierName(node).getBaseName(); + else + BaseName = DeclBaseName::createSubscript(); + + if (BaseName.empty()) + return DeclName(); + + // Location of LabelList node if present, otherwise a Type node. + unsigned LabelListIdx; + if (node->getKind() == Node::Kind::Function) + LabelListIdx = 2; + else + LabelListIdx = 1; + + auto *LabelsOrType = node->getChild(LabelListIdx); + assert(LabelsOrType != nullptr && (LabelsOrType->getKind() == Node::Kind::LabelList || + LabelsOrType->getKind() == Node::Kind::Type)); + + SmallVector ArgLabels; + if (LabelsOrType->getKind() == Node::Kind::LabelList) + extractArgLabelsFromLabelList(LabelsOrType, ArgLabels); + else + extractArgLabelsFromType(LabelsOrType, ArgLabels); + + if (ArgLabels.empty()) + return DeclName(BaseName); + + return DeclName(Ctx, BaseName, ArgLabels); +} + +void DeclNameExtractor::extractArgLabelsFromLabelList(Node *LabelList, + SmallVectorImpl &ArgLabels) { + assert(LabelList->getKind() == Node::Kind::LabelList); + + for (unsigned i = 0; i < LabelList->getNumChildren(); ++i) { + auto *Label = LabelList->getChild(i); + + assert(Label && (Label->getKind() == Node::Kind::Identifier || + Label->getKind() == Node::Kind::FirstElementMarker)); + + if (Label->getKind() == Node::Kind::Identifier) { + ArgLabels.push_back(Ctx.getIdentifier(Label->getText())); + } else { + ArgLabels.push_back(Identifier()); + } + } +} + +void DeclNameExtractor::extractArgLabelsFromType(Node *Type, SmallVectorImpl &ArgLabels) { + auto ArgTuple = Type->findByKind(Demangle::Node::Kind::ArgumentTuple, + /*maxDepth=*/5); + if (ArgTuple == nullptr) + return; + + auto Params = ArgTuple->getFirstChild(); + auto ParamsType = Params->getFirstChild(); + if (ParamsType == nullptr) + return; + + if (ParamsType->getKind() != Demangle::Node::Kind::Tuple) { + // A single, unnamed parameter + ArgLabels.push_back(Identifier()); + return; + } + + // More than one parameter are present + while (Params && Params->getFirstChild() && + Params->getFirstChild()->getKind() != Node::Kind::TupleElement) { + Params = Params->getFirstChild(); + } + + if (Params) { + for (size_t i = 0; i < Params->getNumChildren(); ++i) { + ArgLabels.push_back(Identifier()); + } + } +} From 74db73b104594792ebd21a9af6049c765d407150 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 5 Jul 2025 13:58:04 +0300 Subject: [PATCH 03/58] [USR] Allow generating Swift USR for any Clang decl --- include/swift/AST/TypeCheckRequests.h | 7 +++- include/swift/AST/USRGeneration.h | 11 ++++++- lib/AST/USRGeneration.cpp | 47 +++++++++++++++++---------- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 5cc78b9cf7168..67b5dce5d7ba6 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -764,13 +764,18 @@ struct USRGenerationOptions { /// wants the USR of the Swift declaration. bool distinguishSynthesizedDecls; + /// @brief Whether to emit USRs using the Swift declaration for all declarations + /// specifically, emits a Swift USR for all Clang-based declarations. + bool useSwiftUSR; + friend llvm::hash_code hash_value(const USRGenerationOptions &options) { return llvm::hash_value(options.distinguishSynthesizedDecls); } friend bool operator==(const USRGenerationOptions &lhs, const USRGenerationOptions &rhs) { - return lhs.distinguishSynthesizedDecls == rhs.distinguishSynthesizedDecls; + return lhs.distinguishSynthesizedDecls == rhs.distinguishSynthesizedDecls && + lhs.useSwiftUSR == rhs.useSwiftUSR; } friend bool operator!=(const USRGenerationOptions &lhs, diff --git a/include/swift/AST/USRGeneration.h b/include/swift/AST/USRGeneration.h index 07e069b70aa38..5171fc4ab9f98 100644 --- a/include/swift/AST/USRGeneration.h +++ b/include/swift/AST/USRGeneration.h @@ -45,9 +45,18 @@ bool printDeclTypeUSR(const ValueDecl *D, raw_ostream &OS); /// Prints out the USR for the given ValueDecl. /// @param distinguishSynthesizedDecls Whether to use the USR of the /// synthesized declaration instead of the USR of the underlying Clang USR. +/// @param useSwiftUSR Whether to generate a Swift USR for all Clang declarations as well. /// \returns true if it failed, false on success. bool printValueDeclUSR(const ValueDecl *D, raw_ostream &OS, - bool distinguishSynthesizedDecls = false); + bool distinguishSynthesizedDecls = false, + bool useSwiftUSR = false); + +/// Prints out the Swift USR for the given ValueDecl regardless of its source (Swift or Clang). +/// Equivalent to `printValueDeclUSR(D, OS, false, /*useSwiftUSR=*/true)` +inline bool printValueDeclSwiftUSR(const ValueDecl *D, raw_ostream &OS) { + return printValueDeclUSR(D, OS, /*distinguishSynthesizedDecls=*/false, + /*useSwiftUSR=*/true); +} /// Prints out the USR for the given ModuleEntity. /// In case module aliasing is used, it prints the real module name. For example, diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 077dd13e767af..54c85d66b9efd 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -173,23 +173,12 @@ static bool shouldUseObjCUSR(const Decl *D) { void swift::simple_display(llvm::raw_ostream &out, const USRGenerationOptions &options) { out << "USRGenerationOptions (distinguishSynthesizedDecls: " - << options.distinguishSynthesizedDecls << ")"; + << options.distinguishSynthesizedDecls + << ", useSwiftUSR: " << options.useSwiftUSR << ")"; } -std::string -swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, - USRGenerationOptions options) const { - if (auto *VD = dyn_cast(D)) - D = VD->getCanonicalVarDecl(); - - if (!D->hasName() && !isa(D) && !isa(D)) - return std::string(); // Ignore. - if (D->getModuleContext()->isBuiltinModule() && - !isa(D)) - return std::string(); // Ignore. - if (isa(D)) - return std::string(); // Ignore. - +static std::optional +generateClangUSR(const ValueDecl *D, USRGenerationOptions options) { auto interpretAsClangNode = [&options](const ValueDecl *D) -> ClangNode { auto *importer = D->getASTContext().getClangModuleLoader(); ClangNode ClangN = importer->getEffectiveClangNode(D); @@ -260,6 +249,28 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, return std::string(OS.str()); } } + + return std::nullopt; +} + +std::string +swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, + USRGenerationOptions options) const { + if (auto *VD = dyn_cast(D)) + D = VD->getCanonicalVarDecl(); + + if (!D->hasName() && !isa(D) && !isa(D)) + return std::string(); // Ignore. + if (D->getModuleContext()->isBuiltinModule() && + !isa(D)) + return std::string(); // Ignore. + if (isa(D)) + return std::string(); // Ignore. + + if (!options.useSwiftUSR) { + if (auto USR = generateClangUSR(D, options)) + return USR.value(); + } auto declIFaceTy = D->getInterfaceType(); @@ -307,10 +318,12 @@ bool ide::printModuleUSR(ModuleEntity Mod, raw_ostream &OS) { } bool ide::printValueDeclUSR(const ValueDecl *D, raw_ostream &OS, - bool distinguishSynthesizedDecls) { + bool distinguishSynthesizedDecls, + bool useSwiftUSR) { auto result = evaluateOrDefault( D->getASTContext().evaluator, - USRGenerationRequest{D, {distinguishSynthesizedDecls}}, std::string()); + USRGenerationRequest{D, {distinguishSynthesizedDecls, useSwiftUSR}}, + std::string()); if (result.empty()) return true; OS << result; From 970a4557aa7b5e92fd60c8edb473502e94afd74d Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 5 Jul 2025 16:17:21 +0300 Subject: [PATCH 04/58] [Demangle] Optimize USR to Clang Decl performance --- lib/AST/ASTDemangler.cpp | 96 ++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 39 deletions(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 4600be9cf0e79..a8d1292a88112 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -44,17 +44,9 @@ using namespace swift; -static Decl *getClangDeclFromUSR(ASTContext &ctx, StringRef usr) { - auto *clangLoader = ctx.getClangModuleLoader(); - auto &clangCtx = clangLoader->getClangASTContext(); - auto *clangDecl = clang::tooling::rename::getNamedDeclWithUSR(clangCtx, usr); - - return clangLoader->importDeclDirectly(clangDecl); -} - -static Decl *getSwiftDeclFromUSR(ASTContext &ctx, StringRef usr, - const DeclContext *lookupDC, - GenericSignature genericSig) { +Decl *swift::Demangle::getDeclFromUSR(ASTContext &ctx, StringRef usr, + const DeclContext *lookupDC, + GenericSignature genericSig) { if (!usr.starts_with("s:")) return nullptr; @@ -68,16 +60,6 @@ static Decl *getSwiftDeclFromUSR(ASTContext &ctx, StringRef usr, return builder.findDecl(node, usr, lookupDC); } -Decl *swift::Demangle::getDeclFromUSR(ASTContext &ctx, - StringRef usr, - const DeclContext *lookupDC, - GenericSignature genericSig) { - if (usr.starts_with("c:")) - return getClangDeclFromUSR(ctx, usr); - - return getSwiftDeclFromUSR(ctx, usr, lookupDC, genericSig); -} - Type swift::Demangle::getTypeForMangling(ASTContext &ctx, StringRef mangling, GenericSignature genericSig) { @@ -114,6 +96,32 @@ TypeDecl *swift::Demangle::getTypeDeclForUSR(ASTContext &ctx, return getTypeDeclForMangling(ctx, mangling, genericSig); } +using ValueDeclPredicate = llvm::function_ref; + +static Decl * +findTopLevelClangDecl(ClangModuleLoader *importer, DeclName name, + ValueDeclPredicate predicate) { + struct Consumer : VisibleDeclConsumer { + ValueDecl *Result = nullptr; + ValueDeclPredicate Predicate; + + explicit Consumer(ValueDeclPredicate Predicate) : Predicate(Predicate) {} + + void foundDecl(ValueDecl *decl, DeclVisibilityKind reason, + DynamicLookupInfo dynamicLookupInfo = {}) override { + if (Result != nullptr) + return; + + if (Predicate(decl)) + Result = decl; + } + } consumer(predicate); + + importer->lookupValue(name, consumer); + + return consumer.Result; +} + Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, const DeclContext *lookupDC) { if (node == nullptr) @@ -142,22 +150,38 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, DeclNameExtractor NameExtractor(Ctx); auto name = NameExtractor.extractDeclName(node); - auto DeclContextNode = node->getFirstChild(); - if (DeclContextNode == nullptr) + auto contextNode = node->getFirstChild(); + if (!contextNode) return nullptr; + auto hasMatchingUSR = [usr](const ValueDecl *VD) { + SmallString<128> candidateUSR; + llvm::raw_svector_ostream OS(candidateUSR); + + if (ide::printValueDeclSwiftUSR(VD, OS)) + return false; + + return usr == candidateUSR; + }; + SmallVector candidates; - if (DeclContextNode->getKind() == Node::Kind::Module) { - auto PotentialModules = findPotentialModules(DeclContextNode); - - for (auto *Module : PotentialModules) { - auto *moduleScopeContext = Module->getModuleScopeContext(); - namelookup::lookupInModule(Module, name, candidates, - NLKind::QualifiedLookup, namelookup::ResolutionKind::Overloadable, - moduleScopeContext, SourceLoc(), NL_QualifiedDefault); + if (contextNode->getKind() == Node::Kind::Module) { + // If a foreign Clang module, perform lookup in Clang importer + if (auto kind = getForeignModuleKind(contextNode)) { + auto *importer = Ctx.getClangModuleLoader(); + return findTopLevelClangDecl(importer, name, hasMatchingUSR); + } + + auto potentialModules = findPotentialModules(contextNode); + + for (auto *module : potentialModules) { + auto *moduleScopeContext = module->getModuleScopeContext(); + namelookup::lookupInModule(module, name, candidates, + NLKind::QualifiedLookup, namelookup::ResolutionKind::Overloadable, + moduleScopeContext, SourceLoc(), NL_QualifiedDefault); } } else { - auto *ownerDC = findDeclContext(DeclContextNode); + auto *ownerDC = findDeclContext(contextNode); if (!ownerDC) return nullptr; @@ -179,13 +203,7 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, } for (auto *candidate : candidates) { - SmallString<128> candidateUSR; - llvm::raw_svector_ostream OS(candidateUSR); - - if (ide::printDeclUSR(candidate, OS)) - continue; - - if (usr == candidateUSR) + if (hasMatchingUSR(candidate)) return candidate; } From 302b36350feb0ced85aa5acebdc4b170e9ebcedd Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 5 Jul 2025 23:48:03 +0300 Subject: [PATCH 05/58] [Demangle] Find extension by underlying module for Clang decls --- lib/AST/ASTDemangler.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index a8d1292a88112..0cd09b4cf391b 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -1567,7 +1567,10 @@ ASTBuilder::findDeclContext(NodePointer node) { for (auto *ext : nominalDecl->getExtensions()) { bool found = false; for (ModuleDecl *module : moduleDecls) { - if (ext->getParentModule() == module) { + auto *extensionModule = ext->getParentModule(); + + if (extensionModule == module || + extensionModule == module->getUnderlyingModuleIfOverlay()) { found = true; break; } From 6e526f9343da71ffa1ee9400d19b11af69278a49 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Tue, 8 Jul 2025 22:18:48 +0300 Subject: [PATCH 06/58] [Demangle] Rename getDeclFromUSR to getDeclForUSR for consistency --- include/swift/AST/ASTDemangler.h | 8 ++++---- lib/AST/ASTDemangler.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 521632e08f709..bef6e6894bc1b 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -52,10 +52,10 @@ TypeDecl *getTypeDeclForUSR(ASTContext &ctx, llvm::StringRef usr, GenericSignature genericSig=GenericSignature()); -Decl *getDeclFromUSR(ASTContext &ctx, - llvm::StringRef usr, - const DeclContext *lookupDC, - GenericSignature genericSig=GenericSignature()); +Decl *getDeclForUSR(ASTContext &ctx, + llvm::StringRef usr, + const DeclContext *lookupDC, + GenericSignature genericSig=GenericSignature()); /// An implementation of MetadataReader's BuilderType concept that /// just finds and builds things in the AST. diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 0cd09b4cf391b..7e37e9d70dd58 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -44,9 +44,9 @@ using namespace swift; -Decl *swift::Demangle::getDeclFromUSR(ASTContext &ctx, StringRef usr, - const DeclContext *lookupDC, - GenericSignature genericSig) { +Decl *swift::Demangle::getDeclForUSR(ASTContext &ctx, StringRef usr, + const DeclContext *lookupDC, + GenericSignature genericSig) { if (!usr.starts_with("s:")) return nullptr; From 9b7e8170bc5724fbb0934f1c522f6ca8f2f67444 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Tue, 8 Jul 2025 22:29:19 +0300 Subject: [PATCH 07/58] [Demangle] Fix issues with Clang USR to Decl reconstruction --- include/swift/AST/ASTDemangler.h | 3 ++- lib/AST/ASTDemangler.cpp | 32 +++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index bef6e6894bc1b..c837e144f07e6 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -295,7 +295,8 @@ class ASTBuilder { /// The module name encoded in the node is either the module's real or ABI /// name. Multiple modules can share the same name. This function returns /// all modules that contain that name. - llvm::ArrayRef findPotentialModules(NodePointer node); + llvm::ArrayRef findPotentialModules(NodePointer node, + ModuleDecl *&scratch); Demangle::NodePointer findModuleNode(NodePointer node); diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 7e37e9d70dd58..7056e8910d283 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -172,7 +172,8 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, return findTopLevelClangDecl(importer, name, hasMatchingUSR); } - auto potentialModules = findPotentialModules(contextNode); + ModuleDecl *scratch; + auto potentialModules = findPotentialModules(contextNode, scratch); for (auto *module : potentialModules) { auto *moduleScopeContext = module->getModuleScopeContext(); @@ -398,7 +399,9 @@ Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor, auto moduleNode = findModuleNode(definingDecl); if (!moduleNode) return Type(); - auto potentialParentModules = findPotentialModules(moduleNode); + + ModuleDecl *scratch; + auto potentialParentModules = findPotentialModules(moduleNode, scratch); if (potentialParentModules.empty()) return Type(); @@ -1332,9 +1335,17 @@ ASTBuilder::createTypeDecl(NodePointer node, } llvm::ArrayRef -ASTBuilder::findPotentialModules(NodePointer node) { +ASTBuilder::findPotentialModules(NodePointer node, ModuleDecl *&scratch) { assert(node->getKind() == Demangle::Node::Kind::Module); + const auto moduleName = node->getText(); + + if (moduleName == CLANG_HEADER_MODULE_NAME) { + auto *importer = Ctx.getClangModuleLoader(); + scratch = importer->getImportedHeaderModule(); + return ArrayRef(&scratch, 1); + } + return Ctx.getModulesByRealOrABIName(moduleName); } @@ -1442,7 +1453,8 @@ ASTBuilder::findDeclContext(NodePointer node) { // debugger or USR together with the OriginallyDefinedIn attribute for // example. assert(false && "Looked up module as decl context directly!"); - auto modules = findPotentialModules(node); + ModuleDecl *scratch; + auto modules = findPotentialModules(node, scratch); return modules.empty() ? nullptr : modules[0]; } @@ -1460,7 +1472,8 @@ ASTBuilder::findDeclContext(NodePointer node) { if (!moduleNode) return nullptr; - auto potentialModules = findPotentialModules(moduleNode); + ModuleDecl *scratch; + auto potentialModules = findPotentialModules(moduleNode, scratch); if (potentialModules.empty()) return nullptr; @@ -1510,7 +1523,8 @@ ASTBuilder::findDeclContext(NodePointer node) { auto child = node->getFirstChild(); if (child->getKind() == Node::Kind::Module) { - auto potentialModules = findPotentialModules(child); + ModuleDecl *scratch; + auto potentialModules = findPotentialModules(child, scratch); if (potentialModules.empty()) return nullptr; @@ -1533,7 +1547,8 @@ ASTBuilder::findDeclContext(NodePointer node) { return findDeclContext(node->getChild(0)); case Demangle::Node::Kind::Extension: { - auto moduleDecls = findPotentialModules(node->getFirstChild()); + ModuleDecl *scratch; + auto moduleDecls = findPotentialModules(node->getFirstChild(), scratch); if (moduleDecls.empty()) return nullptr; @@ -1569,8 +1584,7 @@ ASTBuilder::findDeclContext(NodePointer node) { for (ModuleDecl *module : moduleDecls) { auto *extensionModule = ext->getParentModule(); - if (extensionModule == module || - extensionModule == module->getUnderlyingModuleIfOverlay()) { + if (extensionModule == module) { found = true; break; } From 7b376cd53efd3e9b0eb516188586ff0de5a49d5b Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 11 Jul 2025 19:35:28 +0300 Subject: [PATCH 08/58] [Demangle] Remove unused lookup DC param to getDeclForUSR --- include/swift/AST/ASTDemangler.h | 3 +-- lib/AST/ASTDemangler.cpp | 16 +++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index c837e144f07e6..3240bf9f7e087 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -54,7 +54,6 @@ TypeDecl *getTypeDeclForUSR(ASTContext &ctx, Decl *getDeclForUSR(ASTContext &ctx, llvm::StringRef usr, - const DeclContext *lookupDC, GenericSignature genericSig=GenericSignature()); /// An implementation of MetadataReader's BuilderType concept that @@ -129,7 +128,7 @@ class ASTBuilder { Demangle::NodeFactory &getNodeFactory() { return Factory; } - Decl *findDecl(NodePointer node, StringRef usr, const DeclContext *lookupDC); + Decl *findDecl(NodePointer node, StringRef usr); Type decodeMangledType(NodePointer node, bool forRequirement = true); Type createBuiltinType(StringRef builtinName, StringRef mangledName); diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 7056e8910d283..13d607cf37ef7 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -45,7 +45,6 @@ using namespace swift; Decl *swift::Demangle::getDeclForUSR(ASTContext &ctx, StringRef usr, - const DeclContext *lookupDC, GenericSignature genericSig) { if (!usr.starts_with("s:")) return nullptr; @@ -57,7 +56,7 @@ Decl *swift::Demangle::getDeclForUSR(ASTContext &ctx, StringRef usr, auto node = Dem.demangleSymbolAsNode(mangling); ASTBuilder builder(ctx, genericSig); - return builder.findDecl(node, usr, lookupDC); + return builder.findDecl(node, usr); } Type swift::Demangle::getTypeForMangling(ASTContext &ctx, @@ -122,8 +121,7 @@ findTopLevelClangDecl(ClangModuleLoader *importer, DeclName name, return consumer.Result; } -Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, - const DeclContext *lookupDC) { +Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { if (node == nullptr) return nullptr; @@ -144,7 +142,7 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, case Node::Kind::BoundGenericTypeAlias: case Node::Kind::BoundGenericOtherNominalType: case Node::Kind::Extension: - return findDecl(node->getFirstChild(), usr, lookupDC); + return findDecl(node->getFirstChild(), usr); } DeclNameExtractor NameExtractor(Ctx); @@ -182,15 +180,15 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr, moduleScopeContext, SourceLoc(), NL_QualifiedDefault); } } else { - auto *ownerDC = findDeclContext(contextNode); - if (!ownerDC) + auto *DC = findDeclContext(contextNode); + if (!DC) return nullptr; - if (auto *nominal = ownerDC->getSelfNominalTypeDecl()) { + if (auto *nominal = DC->getSelfNominalTypeDecl()) { auto result = nominal->lookupDirect(name); candidates.append(result.begin(), result.end()); } else { - UnqualifiedLookupDescriptor desc(DeclNameRef(name), ownerDC); + UnqualifiedLookupDescriptor desc(DeclNameRef(name), DC); auto result = evaluateOrDefault(Ctx.evaluator, UnqualifiedLookupRequest(desc), From 37ae9bad48ef4291e0e016e657a485553cd4ddad Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 11 Jul 2025 19:40:27 +0300 Subject: [PATCH 09/58] [Demangle] Move move switch' default at the bottom --- lib/AST/ASTDemangler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 13d607cf37ef7..d83e2669378ab 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -129,9 +129,6 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { return TD; switch (node->getKind()) { - default: - // We should have probably arrived at a probable declaration node by now - break; case Node::Kind::Global: case Node::Kind::Static: case Node::Kind::BoundGenericEnum: @@ -143,6 +140,9 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { case Node::Kind::BoundGenericOtherNominalType: case Node::Kind::Extension: return findDecl(node->getFirstChild(), usr); + default: + // We should have arrived at a declaration node by now + break; } DeclNameExtractor NameExtractor(Ctx); From d58d343a16c2a2d184e1e83c371b6b6229f22d46 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 11 Jul 2025 20:24:51 +0300 Subject: [PATCH 10/58] [IDE] Verify USR to Decl on code completion --- lib/IDE/CodeCompletionResultBuilder.cpp | 50 +++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index f0a027f2d1d9f..1cc681f39d346 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -13,6 +13,7 @@ #include "CodeCompletionResultBuilder.h" #include "CodeCompletionDiagnostics.h" #include "swift/AST/ASTContext.h" +#include "swift/AST/ASTDemangler.h" #include "swift/AST/USRGeneration.h" #include "swift/Basic/Assertions.h" #include "swift/Basic/LLVM.h" @@ -80,6 +81,48 @@ copyAssociatedUSRs(llvm::BumpPtrAllocator &Allocator, const Decl *D) { return {}; } +/// Tries to reconstruct the provided \p D declaration using \c Demangle::getDeclForUSR and verifies +/// that the declarations match. +/// This only works if \p D is a \c ValueDecl and \c shouldCopyAssociatedUSRForDecl is true. +/// +/// This is intended for testing only. +static void verifyUSRToDeclReconstruction(ASTContext &Ctx, const Decl *D) { + auto *VD = dyn_cast_or_null(D); + if (!VD) + return; + + if (!shouldCopyAssociatedUSRForDecl(VD)) + return; + + SmallString<128> SwiftUSR; + + llvm::raw_svector_ostream OS(SwiftUSR); + if (ide::printValueDeclSwiftUSR(VD, OS)) { + llvm::errs() << "Declaration is:\n"; + VD->dump(llvm::errs()); + assert(false && "Declaration should have a Swift USR"); + } + + auto *Reconstructed = Demangle::getDeclForUSR(Ctx, SwiftUSR); + + if (!Reconstructed) { + llvm::errs() << "Swift USR is " << SwiftUSR << ", declaration is:\n"; + VD->dump(llvm::errs()); + + assert(false && "Reconstructed declaration shouldn't be null"); + } + + if (Reconstructed != VD) { + llvm::errs() << "Declaration is:\n"; + VD->dump(llvm::errs()); + llvm::errs() << "Instead, found declaration:\n"; + Reconstructed->dump(llvm::errs()); + + assert(false && "Reconstructed declaraton doesn't equal the" + "provided declaration"); + } +} + void CodeCompletionResultBuilder::addChunkWithText( CodeCompletionString::Chunk::ChunkKind Kind, StringRef Text) { addChunkWithTextNoCopy(Kind, Text.copy(*Sink.Allocator)); @@ -186,6 +229,13 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { ContextFreeResult->calculateContextualNotRecommendedReason( ContextualNotRecReason, CanCurrDeclContextHandleAsync); + // TODO(a7medev): Move to completion options. + bool verifyUSRToDecl = true; + if (verifyUSRToDecl) { + auto &Ctx = DC->getASTContext(); + verifyUSRToDeclReconstruction(Ctx, AssociatedDecl); + } + return new (Allocator) CodeCompletionResult( *ContextFreeResult, SemanticContext, Flair, NumBytesToErase, typeRelation, notRecommendedReason); From 7f23a99861452815e9c9adeb2effa9e4184736c3 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 11 Jul 2025 22:47:31 +0300 Subject: [PATCH 11/58] [IDE] Add verify USR to Decl completion option --- include/swift/IDE/CodeCompletionContext.h | 7 +++++++ include/swift/IDE/CodeCompletionResultSink.h | 3 +++ lib/IDE/CodeCompletionContext.cpp | 1 + lib/IDE/CodeCompletionResultBuilder.cpp | 5 +++++ tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h | 1 + tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp | 3 +++ tools/SourceKit/tools/complete-test/complete-test.cpp | 9 +++++++++ .../sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp | 2 ++ 8 files changed, 31 insertions(+) diff --git a/include/swift/IDE/CodeCompletionContext.h b/include/swift/IDE/CodeCompletionContext.h index b7625f1408d57..52f63ce83787f 100644 --- a/include/swift/IDE/CodeCompletionContext.h +++ b/include/swift/IDE/CodeCompletionContext.h @@ -86,6 +86,13 @@ class CodeCompletionContext { return CurrentResults.addCallWithNoDefaultArgs; } + void setVerifyUSRToDecl(bool flag) { + CurrentResults.verifyUSRToDecl = flag; + } + bool verifyUSRToDecl() const { + return CurrentResults.verifyUSRToDecl; + } + /// Allocate a string owned by the code completion context. StringRef copyString(StringRef Str) { return Str.copy(*CurrentResults.Allocator); diff --git a/include/swift/IDE/CodeCompletionResultSink.h b/include/swift/IDE/CodeCompletionResultSink.h index 4554698915d52..e1e29d01cdc4f 100644 --- a/include/swift/IDE/CodeCompletionResultSink.h +++ b/include/swift/IDE/CodeCompletionResultSink.h @@ -40,6 +40,9 @@ struct CodeCompletionResultSink { /// Whether to include an item without any default arguments. bool addCallWithNoDefaultArgs = true; + + /// Whether to verify USR to \c Decl reconstruction during completion. + bool verifyUSRToDecl = false; private: /// Whether the code completion results computed for this sink are intended to diff --git a/lib/IDE/CodeCompletionContext.cpp b/lib/IDE/CodeCompletionContext.cpp index 78320962ed98d..2da14b033c445 100644 --- a/lib/IDE/CodeCompletionContext.cpp +++ b/lib/IDE/CodeCompletionContext.cpp @@ -145,6 +145,7 @@ void CodeCompletionContext::addResultsFromModules( Sink.addInitsToTopLevel = getAddInitsToTopLevel(); Sink.includeObjectLiterals = includeObjectLiterals(); Sink.addCallWithNoDefaultArgs = addCallWithNoDefaultArgs(); + Sink.verifyUSRToDecl = verifyUSRToDecl(); Sink.setProduceContextFreeResults((*V)->USRTypeArena); lookupCodeCompletionResultsFromModule(Sink, R.TheModule, R.Key.AccessPath, R.Key.ResultsHaveLeadingDot, SF); diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 1cc681f39d346..65446ca9e65ba 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -132,6 +132,11 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { auto &Allocator = *Sink.Allocator; auto *CCS = CodeCompletionString::create(Allocator, Chunks); + if (Sink.verifyUSRToDecl && AssociatedDecl) { + auto &Ctx = DC->getASTContext(); + verifyUSRToDeclReconstruction(Ctx, AssociatedDecl); + } + CodeCompletionDiagnosticSeverity ContextFreeDiagnosticSeverity = CodeCompletionDiagnosticSeverity::None; NullTerminatedStringRef ContextFreeDiagnosticMessage; diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h index c87aa81efd06c..c83d60e4e662f 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h @@ -46,6 +46,7 @@ struct Options { bool annotatedDescription = false; bool includeObjectLiterals = true; bool addCallWithNoDefaultArgs = true; + bool verifyUSRToDecl = false; unsigned minFuzzyLength = 2; unsigned showTopNonLiteralResults = 3; diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index 778d1bac70a1a..b133af77eb5d8 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -102,6 +102,7 @@ static void swiftCodeCompleteImpl( CompletionContext.setIncludeObjectLiterals(opts.includeObjectLiterals); CompletionContext.setAddInitsToTopLevel(opts.addInitsToTopLevel); CompletionContext.setAddCallWithNoDefaultArgs(opts.addCallWithNoDefaultArgs); + CompletionContext.setVerifyUSRToDecl(opts.verifyUSRToDecl); Lang.performWithParamsToCompletionLikeOperation( UnresolvedInputFile, Offset, /*InsertCodeCompletionToken=*/true, Args, @@ -728,6 +729,7 @@ static void translateCodeCompletionOptions(OptionsDictionary &from, static UIdent KeyPopularityBonus("key.codecomplete.sort.popularitybonus"); static UIdent KeyAnnotatedDescription("key.codecomplete.annotateddescription"); static UIdent KeyIncludeObjectLiterals("key.codecomplete.includeobjectliterals"); + static UIdent KeyVerifyUSRToDecl("key.codecomplete.verifyusrtodecl"); from.valueForOption(KeySortByName, to.sortByName); from.valueForOption(KeyUseImportDepth, to.useImportDepth); @@ -753,6 +755,7 @@ static void translateCodeCompletionOptions(OptionsDictionary &from, from.valueForOption(KeyTopNonLiteral, to.showTopNonLiteralResults); from.valueForOption(KeyAnnotatedDescription, to.annotatedDescription); from.valueForOption(KeyIncludeObjectLiterals, to.includeObjectLiterals); + from.valueForOption(KeyVerifyUSRToDecl, to.verifyUSRToDecl); } /// Canonicalize a name that is in the format of a reference to a function into diff --git a/tools/SourceKit/tools/complete-test/complete-test.cpp b/tools/SourceKit/tools/complete-test/complete-test.cpp index bb225cafa1a14..1e8d289e41784 100644 --- a/tools/SourceKit/tools/complete-test/complete-test.cpp +++ b/tools/SourceKit/tools/complete-test/complete-test.cpp @@ -64,6 +64,7 @@ struct TestOptions { std::optional fuzzyMatching; std::optional fuzzyWeight; std::optional popularityBonus; + std::optional verifyUSRToDecl; StringRef filterRulesJSON; std::string moduleCachePath; bool rawOutput = false; @@ -115,6 +116,7 @@ static sourcekitd_uid_t KeyResults; static sourcekitd_uid_t KeyPopular; static sourcekitd_uid_t KeyUnpopular; static sourcekitd_uid_t KeySubStructure; +static sourcekitd_uid_t KeyVerifyUSRToDecl; // Returns false and sets 'error' on failure. static bool parseOptions(ArrayRef args, TestOptions &options, @@ -260,6 +262,10 @@ static bool parseOptions(ArrayRef args, TestOptions &options, options.disableImplicitConcurrencyModuleImport = true; } else if (opt == "disable-implicit-string-processing-module-import") { options.disableImplicitStringProcessingModuleImport = true; + } else if (opt == "verify-usr-to-decl") { + options.verifyUSRToDecl = true; + } else if (opt == "no-verify-usr-to-decl") { + options.verifyUSRToDecl = false; } } @@ -342,6 +348,8 @@ static int skt_main(int argc, const char **argv) { sourcekitd_uid_get_from_cstr("key.codecomplete.sort.popularitybonus"); KeyTopNonLiteral = sourcekitd_uid_get_from_cstr("key.codecomplete.showtopnonliteralresults"); + KeyVerifyUSRToDecl = + sourcekitd_uid_get_from_cstr("key.codecomplete.verifyusrtodecl"); KeySourceFile = sourcekitd_uid_get_from_cstr("key.sourcefile"); KeySourceText = sourcekitd_uid_get_from_cstr("key.sourcetext"); KeyName = sourcekitd_uid_get_from_cstr("key.name"); @@ -640,6 +648,7 @@ static bool codeCompleteRequest(sourcekitd_uid_t requestUID, const char *name, addBoolOption(KeyFuzzyMatching, options.fuzzyMatching); addBoolOption(KeyHideLowPriority, options.hideLowPriority); addBoolOption(KeyHideByName, options.hideByName); + addBoolOption(KeyVerifyUSRToDecl, options.verifyUSRToDecl); auto addIntOption = [&](sourcekitd_uid_t key, std::optional option) { diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp index 01067871cf73f..bc55276e0d8a4 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -212,6 +212,7 @@ struct CompletionRequest { bool includeObjectLiterals = true; bool addInitsToTopLevel = false; bool addCallWithNoDefaultArgs = true; + bool verifyUSRToDecl = false; CompletionRequest(const char *path, unsigned offset, ArrayRef args) { @@ -294,6 +295,7 @@ swiftide_complete_cancellable(swiftide_connection_t _conn, result->context.setIncludeObjectLiterals(req.includeObjectLiterals); result->context.setAddInitsToTopLevel(req.addInitsToTopLevel); result->context.setAddCallWithNoDefaultArgs(req.addCallWithNoDefaultArgs); + result->context.setVerifyUSRToDecl(req.verifyUSRToDecl); conn->codeComplete( req.path, req.offset, req.compilerArguments, fileSystem, result->context, From 8a087e47baad8cdeb3474f3dc5b50e192fe16e23 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 12:39:35 +0300 Subject: [PATCH 12/58] [IDE] Don't pass ASTContext directly to verifyUSRToDeclReconstruction --- lib/IDE/CodeCompletionResultBuilder.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 65446ca9e65ba..1aaf9e184728d 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -86,8 +86,8 @@ copyAssociatedUSRs(llvm::BumpPtrAllocator &Allocator, const Decl *D) { /// This only works if \p D is a \c ValueDecl and \c shouldCopyAssociatedUSRForDecl is true. /// /// This is intended for testing only. -static void verifyUSRToDeclReconstruction(ASTContext &Ctx, const Decl *D) { - auto *VD = dyn_cast_or_null(D); +static void verifyUSRToDeclReconstruction(const Decl *D) { + auto *VD = dyn_cast(D); if (!VD) return; @@ -103,6 +103,7 @@ static void verifyUSRToDeclReconstruction(ASTContext &Ctx, const Decl *D) { assert(false && "Declaration should have a Swift USR"); } + auto &Ctx = VD->getASTContext(); auto *Reconstructed = Demangle::getDeclForUSR(Ctx, SwiftUSR); if (!Reconstructed) { @@ -118,7 +119,7 @@ static void verifyUSRToDeclReconstruction(ASTContext &Ctx, const Decl *D) { llvm::errs() << "Instead, found declaration:\n"; Reconstructed->dump(llvm::errs()); - assert(false && "Reconstructed declaraton doesn't equal the" + assert(false && "Reconstructed declaraton doesn't equal the " "provided declaration"); } } @@ -133,8 +134,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { auto *CCS = CodeCompletionString::create(Allocator, Chunks); if (Sink.verifyUSRToDecl && AssociatedDecl) { - auto &Ctx = DC->getASTContext(); - verifyUSRToDeclReconstruction(Ctx, AssociatedDecl); + verifyUSRToDeclReconstruction(AssociatedDecl); } CodeCompletionDiagnosticSeverity ContextFreeDiagnosticSeverity = From 7617b216193d2a9bea3339555207341ff799130c Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 12:40:25 +0300 Subject: [PATCH 13/58] [Demangle] Compare extension module against underlying module in findDeclContext --- lib/AST/ASTDemangler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index d83e2669378ab..71f6bd8b5b9f7 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -1582,7 +1582,8 @@ ASTBuilder::findDeclContext(NodePointer node) { for (ModuleDecl *module : moduleDecls) { auto *extensionModule = ext->getParentModule(); - if (extensionModule == module) { + if (extensionModule == module || + extensionModule == module->getUnderlyingModuleIfOverlay()) { found = true; break; } From 327f09e4bd08aa9ee988296e08be44819902adfe Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 13:26:41 +0300 Subject: [PATCH 14/58] [Test] Default to verify USR to Decl in tests --- .../tools/complete-test/complete-test.cpp | 2 ++ .../tools/sourcekitd-test/sourcekitd-test.cpp | 2 ++ tools/swift-ide-test/swift-ide-test.cpp | 20 +++++++++++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tools/SourceKit/tools/complete-test/complete-test.cpp b/tools/SourceKit/tools/complete-test/complete-test.cpp index 1e8d289e41784..1df3880b051a1 100644 --- a/tools/SourceKit/tools/complete-test/complete-test.cpp +++ b/tools/SourceKit/tools/complete-test/complete-test.cpp @@ -368,6 +368,8 @@ static int skt_main(int argc, const char **argv) { auto Args = llvm::ArrayRef(argv + 1, argc - 1); TestOptions options; + // Default to verifying USR to Decl reconstruction. + options.verifyUSRToDecl = true; std::string error; if (!parseOptions(Args, options, error)) { llvm::errs() << "usage: complete-test -tok=A file\n" << error << "\n"; diff --git a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp index c79a8f297c03e..ec36a87f92671 100644 --- a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp +++ b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp @@ -734,6 +734,8 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) { sourcekitd_request_dictionary_set_string(Req, KeyName, SemaName.c_str()); // Default to sort by name. Opts.RequestOptions.insert(Opts.RequestOptions.begin(), "sort.byname=1"); + // Default to verifying USR to Decl conversion to cover many use cases + Opts.RequestOptions.insert(Opts.RequestOptions.begin(), "verifyusrtodecl=1"); addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete."); break; diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 8ea7ceaf6bc3a..dd8fbf5d09342 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -510,6 +510,12 @@ CodeCompletionAnnotateResults("code-completion-annotate-results", llvm::cl::cat(Category), llvm::cl::init(false)); +static llvm::cl::opt +CodeCompletionVerifyUSRToDecl("code-completion-verify-usr-to-decl", + llvm::cl::desc("Verify USR to Decl reconstruction"), + llvm::cl::cat(Category), + llvm::cl::init(true)); + static llvm::cl::opt DebugClientDiscriminator("debug-client-discriminator", llvm::cl::desc("A discriminator to prefer in lookups"), @@ -1430,7 +1436,8 @@ doCodeCompletion(const CompilerInvocation &InitInvok, StringRef SourceFilename, bool CodeCompletionAnnotateResults, bool CodeCompletionAddInitsToTopLevel, bool CodeCompletionAddCallWithNoDefaultArgs, - bool CodeCompletionSourceText) { + bool CodeCompletionSourceText, + bool CodeCompletionVerifyUSRToDecl) { std::unique_ptr OnDiskCache; if (!options::CompletionCachePath.empty()) { OnDiskCache = std::make_unique( @@ -1442,6 +1449,7 @@ doCodeCompletion(const CompilerInvocation &InitInvok, StringRef SourceFilename, CompletionContext.setAddInitsToTopLevel(CodeCompletionAddInitsToTopLevel); CompletionContext.setAddCallWithNoDefaultArgs( CodeCompletionAddCallWithNoDefaultArgs); + CompletionContext.setVerifyUSRToDecl(CodeCompletionVerifyUSRToDecl); return performWithCompletionLikeOperationParams( InitInvok, SourceFilename, SecondSourceFileName, CodeCompletionToken, @@ -1471,7 +1479,8 @@ static int doBatchCodeCompletion(const CompilerInvocation &InitInvok, bool CodeCompletionAnnotateResults, bool CodeCompletionAddInitsToTopLevel, bool CodeCompletionAddCallWithNoDefaultArgs, - bool CodeCompletionSourceText) { + bool CodeCompletionSourceText, + bool CodeCompletionVerifyUSRToDecl) { auto FileBufOrErr = llvm::MemoryBuffer::getFile(SourceFilename); if (!FileBufOrErr) { llvm::errs() << "error opening input file: " @@ -1621,6 +1630,7 @@ static int doBatchCodeCompletion(const CompilerInvocation &InitInvok, CompletionContext.setAddInitsToTopLevel(CodeCompletionAddInitsToTopLevel); CompletionContext.setAddCallWithNoDefaultArgs( CodeCompletionAddCallWithNoDefaultArgs); + CompletionContext.setVerifyUSRToDecl(CodeCompletionVerifyUSRToDecl); PrintingDiagnosticConsumer PrintDiags; auto completionStart = std::chrono::high_resolution_clock::now(); @@ -4731,7 +4741,8 @@ int main(int argc, char *argv[]) { options::CodeCompletionAnnotateResults, options::CodeCompleteInitsInPostfixExpr, options::CodeCompletionAddCallWithNoDefaultArgs, - options::CodeCompletionSourceText); + options::CodeCompletionSourceText, + options::CodeCompletionVerifyUSRToDecl); break; case ActionType::CodeCompletion: @@ -4746,7 +4757,8 @@ int main(int argc, char *argv[]) { options::CodeCompletionAnnotateResults, options::CodeCompleteInitsInPostfixExpr, options::CodeCompletionAddCallWithNoDefaultArgs, - options::CodeCompletionSourceText); + options::CodeCompletionSourceText, + options::CodeCompletionVerifyUSRToDecl); break; case ActionType::REPLCodeCompletion: From 5fc0510e0e7c4ee0b37fdc7483e7ff61b84e55e3 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 13:33:02 +0300 Subject: [PATCH 15/58] [Test] Don't check equality of decls in verifyUSRToDeclReconstruction The declarations may not be identical (have the same pointer) but if the reconstructed declaration is not null, it's guaranteed to have the same USR as the original declaration so they refer to the same logical declaration. --- lib/IDE/CodeCompletionResultBuilder.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 1aaf9e184728d..f31381f59fd0e 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -112,16 +112,6 @@ static void verifyUSRToDeclReconstruction(const Decl *D) { assert(false && "Reconstructed declaration shouldn't be null"); } - - if (Reconstructed != VD) { - llvm::errs() << "Declaration is:\n"; - VD->dump(llvm::errs()); - llvm::errs() << "Instead, found declaration:\n"; - Reconstructed->dump(llvm::errs()); - - assert(false && "Reconstructed declaraton doesn't equal the " - "provided declaration"); - } } void CodeCompletionResultBuilder::addChunkWithText( From 03dc3b99df2ed747c9166915b44cd594e556d4ff Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 14:48:47 +0300 Subject: [PATCH 16/58] [Demangle] Fix DeclName extraction for raw identifiers --- include/swift/AST/ASTDemangler.h | 4 --- include/swift/AST/DeclNameExtractor.h | 3 ++ lib/AST/ASTDemangler.cpp | 47 +++++++-------------------- lib/AST/DeclNameExtractor.cpp | 29 +++++++++++++++-- 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 3240bf9f7e087..e8a2b5d9e9b6e 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -317,10 +317,6 @@ class ASTBuilder { static GenericTypeDecl *getAcceptableTypeDeclCandidate(ValueDecl *decl, Demangle::Node::Kind kind); - - /// Returns an identifier with the given name, automatically removing any - /// surrounding backticks that are present for raw identifiers. - Identifier getIdentifier(StringRef name); }; SWIFT_END_INLINE_NAMESPACE diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h index 0b162d89c60d2..52412ae1df45a 100644 --- a/include/swift/AST/DeclNameExtractor.h +++ b/include/swift/AST/DeclNameExtractor.h @@ -42,6 +42,9 @@ class DeclNameExtractor { SmallVectorImpl &ArgLabels); }; +/// Returns an identifier with the given name, automatically removing any +/// surrounding backticks that are present for raw identifiers. +Identifier getIdentifier(ASTContext &Ctx, StringRef name); } // end namespace swift } // end namespace Demangle diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 71f6bd8b5b9f7..adc0eb2d22aa8 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -228,7 +228,7 @@ TypeDecl *ASTBuilder::createTypeDecl(NodePointer node) { if (proto == nullptr) return nullptr; - auto name = getIdentifier(node->getChild(1)->getText()); + auto name = getIdentifier(Ctx, node->getChild(1)->getText()); return proto->getAssociatedType(name); } @@ -244,7 +244,7 @@ ASTBuilder::createBuiltinType(StringRef builtinName, StringRef strippedName = builtinName.drop_front(BUILTIN_TYPE_NAME_PREFIX.size()); - Ctx.TheBuiltinModule->lookupValue(getIdentifier(strippedName), + Ctx.TheBuiltinModule->lookupValue(getIdentifier(Ctx, strippedName), NLKind::QualifiedLookup, decls); if (decls.size() == 1 && isa(decls[0])) @@ -483,7 +483,7 @@ Type ASTBuilder::createTupleType(ArrayRef eltTypes, ArrayRef la for (unsigned i : indices(eltTypes)) { Identifier label; if (!labels[i].empty()) - label = getIdentifier(labels[i]); + label = getIdentifier(Ctx, labels[i]); elements.emplace_back(eltTypes[i], label); } @@ -543,7 +543,7 @@ Type ASTBuilder::createFunctionType( if (!type->isMaterializable()) return Type(); - auto label = getIdentifier(param.getLabel()); + auto label = getIdentifier(Ctx, param.getLabel()); auto flags = param.getFlags(); auto ownership = ParamDecl::getParameterSpecifierForValueOwnership(asValueOwnership(flags.getOwnership())); @@ -1054,7 +1054,7 @@ Type ASTBuilder::createGenericTypeParameterType(unsigned depth, Type ASTBuilder::createDependentMemberType(StringRef member, Type base) { - auto identifier = getIdentifier(member); + auto identifier = getIdentifier(Ctx, member); if (auto *archetype = base->getAs()) { if (Type memberType = archetype->getNestedTypeByName(identifier)) @@ -1071,7 +1071,7 @@ Type ASTBuilder::createDependentMemberType(StringRef member, Type ASTBuilder::createDependentMemberType(StringRef member, Type base, ProtocolDecl *protocol) { - auto identifier = getIdentifier(member); + auto identifier = getIdentifier(Ctx, member); if (auto *archetype = base->getAs()) { if (auto assocType = protocol->getAssociatedType(identifier)) @@ -1315,7 +1315,7 @@ ASTBuilder::getAcceptableTypeDeclCandidate(ValueDecl *decl, DeclContext *ASTBuilder::getNotionalDC() { if (!NotionalDC) { - NotionalDC = ModuleDecl::createEmpty(getIdentifier(".RemoteAST"), Ctx); + NotionalDC = ModuleDecl::createEmpty(getIdentifier(Ctx, ".RemoteAST"), Ctx); NotionalDC = new (Ctx) TopLevelCodeDecl(NotionalDC); } return NotionalDC; @@ -1498,7 +1498,7 @@ ASTBuilder::findDeclContext(NodePointer node) { Demangle::Node::Kind::PrivateDeclName) { name = declNameNode->getChild(1)->getText(); privateDiscriminator = - getIdentifier(declNameNode->getChild(0)->getText()); + getIdentifier(Ctx, declNameNode->getChild(0)->getText()); } else if (declNameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName) { @@ -1527,14 +1527,14 @@ ASTBuilder::findDeclContext(NodePointer node) { return nullptr; for (auto *module : potentialModules) - if (auto typeDecl = findTypeDecl(module, getIdentifier(name), + if (auto typeDecl = findTypeDecl(module, getIdentifier(Ctx, name), privateDiscriminator, node->getKind())) return typeDecl; return nullptr; } if (auto *dc = findDeclContext(child)) - if (auto typeDecl = findTypeDecl(dc, getIdentifier(name), + if (auto typeDecl = findTypeDecl(dc, getIdentifier(Ctx, name), privateDiscriminator, node->getKind())) return typeDecl; @@ -1737,7 +1737,7 @@ GenericTypeDecl *ASTBuilder::findForeignTypeDecl(StringRef name, found); break; } - importer->lookupValue(getIdentifier(name), consumer); + importer->lookupValue(getIdentifier(Ctx, name), consumer); if (consumer.Result) consumer.Result = getAcceptableTypeDeclCandidate(consumer.Result, kind); break; @@ -1747,28 +1747,3 @@ GenericTypeDecl *ASTBuilder::findForeignTypeDecl(StringRef name, return consumer.Result; } - -Identifier ASTBuilder::getIdentifier(StringRef name) { - if (name.size() > 1 && name.front() == '`' && name.back() == '`') { - // Raw identifiers have backticks affixed before mangling. We need to - // remove those before creating the Identifier for the AST, which doesn't - // encode the backticks. - std::string fixedName; - for (size_t i = 1; i < name.size() - 1; ++i) { - unsigned char ch = name[i]; - // Raw identifiers have the space (U+0020) replaced with a non-breaking - // space (U+00A0, UTF-8: 0xC2 0xA0) in their mangling so that parts of - // the runtime that use space as a delimiter remain compatible with - // these identifiers. Flip it back. - if (ch == 0xc2 && i < name.size() - 2 && - (unsigned char)name[i + 1] == 0xa0) { - fixedName.push_back(' '); - ++i; - } else { - fixedName.push_back(ch); - } - } - return Ctx.getIdentifier(fixedName); - } - return Ctx.getIdentifier(name); -} diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index d6a86822a3aed..222bec94db2a4 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -76,7 +76,7 @@ DeclName DeclNameExtractor::extractTextName(Node *node) { if (!node->hasText()) return DeclName(); - auto identifier = Ctx.getIdentifier(node->getText()); + auto identifier = getIdentifier(Ctx, node->getText()); return DeclName(identifier); } @@ -127,7 +127,7 @@ void DeclNameExtractor::extractArgLabelsFromLabelList(Node *LabelList, Label->getKind() == Node::Kind::FirstElementMarker)); if (Label->getKind() == Node::Kind::Identifier) { - ArgLabels.push_back(Ctx.getIdentifier(Label->getText())); + ArgLabels.push_back(getIdentifier(Ctx, Label->getText())); } else { ArgLabels.push_back(Identifier()); } @@ -163,3 +163,28 @@ void DeclNameExtractor::extractArgLabelsFromType(Node *Type, SmallVectorImpl 1 && name.front() == '`' && name.back() == '`') { + // Raw identifiers have backticks affixed before mangling. We need to + // remove those before creating the Identifier for the AST, which doesn't + // encode the backticks. + std::string fixedName; + for (size_t i = 1; i < name.size() - 1; ++i) { + unsigned char ch = name[i]; + // Raw identifiers have the space (U+0020) replaced with a non-breaking + // space (U+00A0, UTF-8: 0xC2 0xA0) in their mangling so that parts of + // the runtime that use space as a delimiter remain compatible with + // these identifiers. Flip it back. + if (ch == 0xc2 && i < name.size() - 2 && + (unsigned char)name[i + 1] == 0xa0) { + fixedName.push_back(' '); + ++i; + } else { + fixedName.push_back(ch); + } + } + return Ctx.getIdentifier(fixedName); + } + return Ctx.getIdentifier(name); +} From 1394721a67aa1f9cbe5e30f8bdd131b01d3cf258 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 23:08:29 +0300 Subject: [PATCH 17/58] [Demangle] Extract identifier from PrivateDeclName & RelatedEntityDeclName nodes in DeclNameExtractor --- include/swift/AST/DeclNameExtractor.h | 4 +++ lib/AST/ASTDemangler.cpp | 18 ++--------- lib/AST/DeclNameExtractor.cpp | 43 +++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h index 52412ae1df45a..a5cebf81f1eee 100644 --- a/include/swift/AST/DeclNameExtractor.h +++ b/include/swift/AST/DeclNameExtractor.h @@ -46,5 +46,9 @@ class DeclNameExtractor { /// surrounding backticks that are present for raw identifiers. Identifier getIdentifier(ASTContext &Ctx, StringRef name); +bool extractNameNodeInfo(ASTContext &Ctx, Node *node, StringRef &name, + StringRef &relatedEntityKind, + Identifier &privateDiscriminator); + } // end namespace swift } // end namespace Demangle diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index adc0eb2d22aa8..f0debce0f89db 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -1491,22 +1491,8 @@ ASTBuilder::findDeclContext(NodePointer node) { StringRef name; StringRef relatedEntityKind; Identifier privateDiscriminator; - if (declNameNode->getKind() == Demangle::Node::Kind::Identifier) { - name = declNameNode->getText(); - - } else if (declNameNode->getKind() == - Demangle::Node::Kind::PrivateDeclName) { - name = declNameNode->getChild(1)->getText(); - privateDiscriminator = - getIdentifier(Ctx, declNameNode->getChild(0)->getText()); - - } else if (declNameNode->getKind() == - Demangle::Node::Kind::RelatedEntityDeclName) { - name = declNameNode->getChild(1)->getText(); - relatedEntityKind = declNameNode->getFirstChild()->getText(); - - // Ignore any other decl-name productions for now. - } else { + if (!extractNameNodeInfo(Ctx, declNameNode, name, relatedEntityKind, + privateDiscriminator)) { return nullptr; } diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index 222bec94db2a4..112c568f830ac 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -21,7 +21,7 @@ using namespace swift; using namespace Demangle; DeclName DeclNameExtractor::extractDeclName(Node *node) { - if (node == nullptr) + if (!node) return DeclName(); switch (node->getKind()) { @@ -64,12 +64,19 @@ DeclName DeclNameExtractor::extractDeclName(Node *node) { } DeclName DeclNameExtractor::extractIdentifierName(Node *node) { - auto Identifier = node->getChild(1); - if (Identifier == nullptr || - Identifier->getKind() != Node::Kind::Identifier) + auto identifierNode = node->getChild(1); + if (!identifierNode) return DeclName(); - - return extractTextName(Identifier); + + StringRef name; + StringRef relatedEntityKind; + Identifier privateDiscriminator; + if (!extractNameNodeInfo(Ctx, identifierNode, name, relatedEntityKind, + privateDiscriminator)) { + return DeclName(); + } + + return getIdentifier(Ctx, name); } DeclName DeclNameExtractor::extractTextName(Node *node) { @@ -188,3 +195,27 @@ Identifier swift::Demangle::getIdentifier(ASTContext &Ctx, StringRef name) { } return Ctx.getIdentifier(name); } + +bool swift::Demangle::extractNameNodeInfo(ASTContext &Ctx, Node *node, + StringRef &name, + StringRef &relatedEntityKind, + Identifier &privateDiscriminator) { + switch (node->getKind()) { + case Demangle::Node::Kind::Identifier: + name = node->getText(); + return true; + + case Demangle::Node::Kind::PrivateDeclName: + name = node->getChild(1)->getText(); + privateDiscriminator = getIdentifier(Ctx, node->getChild(0)->getText()); + return true; + + case Demangle::Node::Kind::RelatedEntityDeclName: + name = node->getChild(1)->getText(); + relatedEntityKind = node->getFirstChild()->getText(); + return true; + + default: + return false; + } +} From 14cbe80ebd985da7e064a880f75115f42eba5287 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 23:16:35 +0300 Subject: [PATCH 18/58] [ASTContext] Remove module from NameToModules on load module with same name --- lib/AST/ASTContext.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index ee20b87f48c6a..483fa730dc205 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2380,16 +2380,35 @@ void ASTContext::addLoadedModule(ModuleDecl *M) { // For example, if '-module-alias Foo=Bar' is passed in to the frontend, // and a source file has 'import Foo', a module called Bar (real name) // will be loaded and added to the map. - getImpl().LoadedModules[M->getRealName()] = M; + + auto RealName = M->getRealName(); + auto ABIName = M->getABIName(); + + auto &LoadedModules = getImpl().LoadedModules; + auto &NameToModules = getImpl().NameToModules; + + // If a module with the same name has been loaded before, remove it from the + // list of modules that share the same name. + if (auto *current = LoadedModules.lookup(RealName)) { + auto isCurrentModule = [&](ModuleDecl *module) { + return module == current; + }; + llvm::erase_if(NameToModules[RealName], isCurrentModule); + + if (RealName != ABIName) + llvm::erase_if(NameToModules[ABIName], isCurrentModule); + } + + LoadedModules[RealName] = M; // Add the module to the mapping from module name to list of modules that // share that name. - getImpl().NameToModules[M->getRealName()].push_back(M); + NameToModules[RealName].push_back(M); // If the ABI name differs from the real name, also add the module to the list // that share that ABI name. - if (M->getRealName() != M->getABIName()) - getImpl().NameToModules[M->getABIName()].push_back(M); + if (RealName != ABIName) + NameToModules[ABIName].push_back(M); } void ASTContext::removeLoadedModule(Identifier RealName) { From 62f680bd06a548d80170efa95f617398feeeddad Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 12 Jul 2025 23:17:24 +0300 Subject: [PATCH 19/58] [Demangle] Remove unqualified lookup in ASTBuilder::findDecl --- lib/AST/ASTDemangler.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index f0debce0f89db..8e20ae6b381bd 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -187,17 +187,6 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { if (auto *nominal = DC->getSelfNominalTypeDecl()) { auto result = nominal->lookupDirect(name); candidates.append(result.begin(), result.end()); - } else { - UnqualifiedLookupDescriptor desc(DeclNameRef(name), DC); - - auto result = evaluateOrDefault(Ctx.evaluator, - UnqualifiedLookupRequest(desc), - LookupResult()); - - for (const auto& entry : result) { - if (auto *VD = entry.getValueDecl()) - candidates.push_back(VD); - } } } From abfa8f6c0aeaf6dfbbf613546f09de2c19f4331c Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sun, 13 Jul 2025 20:58:21 +0300 Subject: [PATCH 20/58] [Demangle] Lookup Decl with privateDiscriminator in ASTBuilder::findDecl --- include/swift/AST/DeclNameExtractor.h | 12 +++-- lib/AST/ASTDemangler.cpp | 23 +++++---- lib/AST/DeclNameExtractor.cpp | 69 +++++++++++++++++---------- 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h index a5cebf81f1eee..edaf986496222 100644 --- a/include/swift/AST/DeclNameExtractor.h +++ b/include/swift/AST/DeclNameExtractor.h @@ -25,17 +25,21 @@ class Node; class DeclNameExtractor { private: ASTContext &Ctx; - + public: DeclNameExtractor(ASTContext &ctx) : Ctx(ctx) {} /// Extract a DeclName from a demangling node - DeclName extractDeclName(Node *node); + /// \returns true if a \c DeclName is found, false otherwise. + bool extractDeclName(Node *node, DeclName &name, + Identifier &privateDiscriminator); private: - DeclName extractIdentifierName(Node *node); + bool extractIdentifierName(Node *node, DeclName &declName, + Identifier &privateDiscriminator); DeclName extractTextName(Node *node); - DeclName extractFunctionLikeName(Node *node); + bool extractFunctionLikeName(Node *node, DeclName &declName, + Identifier &privateDiscriminator); void extractArgLabelsFromLabelList(Node *LabelList, SmallVectorImpl &ArgLabels); void extractArgLabelsFromType(Node *Type, diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 8e20ae6b381bd..aaf1e32593f4c 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -146,8 +146,12 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { } DeclNameExtractor NameExtractor(Ctx); - auto name = NameExtractor.extractDeclName(node); - + + DeclName name; + Identifier privateDiscriminator; + if (!NameExtractor.extractDeclName(node, name, privateDiscriminator)) + return nullptr; + auto contextNode = node->getFirstChild(); if (!contextNode) return nullptr; @@ -174,20 +178,19 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { auto potentialModules = findPotentialModules(contextNode, scratch); for (auto *module : potentialModules) { - auto *moduleScopeContext = module->getModuleScopeContext(); - namelookup::lookupInModule(module, name, candidates, - NLKind::QualifiedLookup, namelookup::ResolutionKind::Overloadable, - moduleScopeContext, SourceLoc(), NL_QualifiedDefault); + module->lookupMember(candidates, module, name, privateDiscriminator); } } else { auto *DC = findDeclContext(contextNode); if (!DC) return nullptr; - if (auto *nominal = DC->getSelfNominalTypeDecl()) { - auto result = nominal->lookupDirect(name); - candidates.append(result.begin(), result.end()); - } + auto *module = DC->getParentModule(); + + if (isa(DC)) + DC = DC->getSelfNominalTypeDecl(); + + module->lookupMember(candidates, DC, name, privateDiscriminator); } for (auto *candidate : candidates) { diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index 112c568f830ac..df64f7eaba701 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -20,9 +20,10 @@ using namespace swift; using namespace Demangle; -DeclName DeclNameExtractor::extractDeclName(Node *node) { +bool DeclNameExtractor::extractDeclName(Node *node, DeclName &name, + Identifier &privateDiscriminator) { if (!node) - return DeclName(); + return false; switch (node->getKind()) { case Node::Kind::Class: @@ -36,47 +37,53 @@ DeclName DeclNameExtractor::extractDeclName(Node *node) { case Node::Kind::GenericTypeParamDecl: case Node::Kind::Variable: case Node::Kind::Macro: - return extractIdentifierName(node); + return extractIdentifierName(node, name, privateDiscriminator); case Node::Kind::Constructor: case Node::Kind::Allocator: - return DeclName(DeclBaseName::createConstructor()); + name = DeclName(DeclBaseName::createConstructor()); + return true; case Node::Kind::Destructor: case Node::Kind::Deallocator: case Node::Kind::IsolatedDeallocator: - return DeclName(DeclBaseName::createDestructor()); + name = DeclName(DeclBaseName::createDestructor()); + return true; case Node::Kind::Module: - return extractTextName(node); + name = extractTextName(node); + return true; case Node::Kind::Function: - return extractFunctionLikeName(node); + return extractFunctionLikeName(node, name, privateDiscriminator); case Node::Kind::Subscript: - return extractFunctionLikeName(node); + return extractFunctionLikeName(node, name, privateDiscriminator); default: // For any other node types, we can't extract a meaningful name - return DeclName(); + return false; } } -DeclName DeclNameExtractor::extractIdentifierName(Node *node) { - auto identifierNode = node->getChild(1); - if (!identifierNode) - return DeclName(); +bool +DeclNameExtractor::extractIdentifierName(Node *node, DeclName &declName, + Identifier &privateDiscriminator) { + auto Identifier = node->getChild(1); + if (!Identifier) + return false; StringRef name; StringRef relatedEntityKind; - Identifier privateDiscriminator; - if (!extractNameNodeInfo(Ctx, identifierNode, name, relatedEntityKind, + if (!extractNameNodeInfo(Ctx, Identifier, name, relatedEntityKind, privateDiscriminator)) { - return DeclName(); + return false; } - return getIdentifier(Ctx, name); + declName = getIdentifier(Ctx, name); + + return true; } DeclName DeclNameExtractor::extractTextName(Node *node) { @@ -87,19 +94,26 @@ DeclName DeclNameExtractor::extractTextName(Node *node) { return DeclName(identifier); } -DeclName DeclNameExtractor::extractFunctionLikeName(Node *node) { +bool +DeclNameExtractor::extractFunctionLikeName(Node *node, DeclName &declName, + Identifier &privateDiscriminator) { assert(node->getKind() == Node::Kind::Function || node->getKind() == Node::Kind::Subscript); DeclBaseName BaseName; - if (node->getKind() == Node::Kind::Function) - BaseName = extractIdentifierName(node).getBaseName(); - else + if (node->getKind() == Node::Kind::Function) { + DeclName name; + if (!extractIdentifierName(node, name, privateDiscriminator)) + return false; + + BaseName = name.getBaseName(); + } else { BaseName = DeclBaseName::createSubscript(); + } if (BaseName.empty()) - return DeclName(); - + return false; + // Location of LabelList node if present, otherwise a Type node. unsigned LabelListIdx; if (node->getKind() == Node::Kind::Function) @@ -117,10 +131,13 @@ DeclName DeclNameExtractor::extractFunctionLikeName(Node *node) { else extractArgLabelsFromType(LabelsOrType, ArgLabels); - if (ArgLabels.empty()) - return DeclName(BaseName); + if (ArgLabels.empty()) { + declName = DeclName(BaseName); + return true; + } - return DeclName(Ctx, BaseName, ArgLabels); + declName = DeclName(Ctx, BaseName, ArgLabels); + return true; } void DeclNameExtractor::extractArgLabelsFromLabelList(Node *LabelList, From dd55e32ac34fd2e49c77679e4df0aa53fd462d73 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sun, 13 Jul 2025 21:48:22 +0300 Subject: [PATCH 21/58] [Test] Fix invalid redeclarations in completion tests & disable verify USR to Decl for protocol where --- test/IDE/complete_ambiguous.swift | 6 +-- test/IDE/complete_at_top_level.swift | 4 +- test/IDE/complete_crashes.swift | 14 +++++-- test/IDE/complete_flair_cache.swift | 4 +- test/IDE/complete_if_switch_expr.swift | 2 +- test/IDE/complete_keywords.swift | 4 +- .../complete_multiple_trailingclosure.swift | 4 +- test/IDE/complete_pound_keypath.swift | 8 ++-- test/IDE/complete_shadowing.swift | 2 +- test/IDE/complete_sself.swift | 40 +++++++++---------- test/IDE/complete_stmt_controlling_expr.swift | 8 ++-- test/IDE/complete_type.swift | 2 +- test/IDE/complete_where_clause.swift | 11 ++++- .../CodeComplete/complete_filter_rules.swift | 2 +- .../CodeComplete/complete_fuzzy.swift | 2 +- .../CodeComplete/complete_sort_order.swift | 2 +- 16 files changed, 64 insertions(+), 51 deletions(-) diff --git a/test/IDE/complete_ambiguous.swift b/test/IDE/complete_ambiguous.swift index 425c262ca4116..39e3bf8502112 100644 --- a/test/IDE/complete_ambiguous.swift +++ b/test/IDE/complete_ambiguous.swift @@ -34,7 +34,7 @@ arrayWrapper(overloadedReturn()).#^SKIP_DUPLICATES^# // SKIP_DUPLICATES-NOT: count[#Int#] // SKIP_DUPLICATES-NOT: formIndex({#(i): &Int#}, {#offsetBy: Int#})[#Void#] -let x: (inout Int, Int) -> () = arrayWrapper(overloadedReturn()).#^SKIP_COMPOUND_DUPLICATES^# +let x1: (inout Int, Int) -> () = arrayWrapper(overloadedReturn()).#^SKIP_COMPOUND_DUPLICATES^# // SKIP_COMPOUND_DUPLICATES: Decl[InstanceMethod]/Super/IsSystem/TypeRelation[Convertible]: formIndex(_:offsetBy:)[#(inout Int, Int) -> ()#]{{; name=.+$}} // SKIP_COMPOUND_DUPLICATES-NOT: formIndex(_:offsetBy:)[#(inout Int, Int) -> ()#] @@ -62,8 +62,8 @@ givenErrorExpr(undefined).#^ERROR_IN_BASE?check=SIMPLE^# // SIMPLE-DAG: Keyword[self]/CurrNominal: self[#B#]{{; name=.+$}} // SIMPLE-DAG: Decl[InstanceMethod]/CurrNominal: doBThings()[#Void#]{{; name=.+$}} -let x: A = overloadedReturn().#^RELATED^# -let x: A = overloadedReturn(1).#^RELATED_EXTRAARG?check=RELATED^# +let x2: A = overloadedReturn().#^RELATED^# +let x3: A = overloadedReturn(1).#^RELATED_EXTRAARG?check=RELATED^# // RELATED: Begin completions, 4 items // RELATED-DAG: Keyword[self]/CurrNominal: self[#A#]{{; name=.+$}} diff --git a/test/IDE/complete_at_top_level.swift b/test/IDE/complete_at_top_level.swift index 565931fab7476..dce4025b986bc 100644 --- a/test/IDE/complete_at_top_level.swift +++ b/test/IDE/complete_at_top_level.swift @@ -79,7 +79,7 @@ func resyncParser6() {} fooObject.instanceFunc(#^TYPE_CHECKED_EXPR_6?check=PLAIN_TOP_LEVEL^# -func resyncParser6() {} +func resyncParser6b() {} fooObject.is#^TYPE_CHECKED_EXPR_KW_1?check=NORESULT^# @@ -104,7 +104,7 @@ var topLevelVar1 = #^TOP_LEVEL_VAR_INIT_1?check=TOP_LEVEL_VAR_INIT_1;check=TOP_L // Check that the variable itself does not show up. // TOP_LEVEL_VAR_INIT_1_NEGATIVE-NOT: topLevelVar1 -func resyncParser7() {} +func resyncParser7a() {} var topLevelVar2 = FooStruct#^TOP_LEVEL_VAR_INIT_2^# // TOP_LEVEL_VAR_INIT_2-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc({#(self): FooStruct#})[#(Int) -> Void#]{{; name=.+$}} diff --git a/test/IDE/complete_crashes.swift b/test/IDE/complete_crashes.swift index 509f50121dbe2..4d30d5adb4483 100644 --- a/test/IDE/complete_crashes.swift +++ b/test/IDE/complete_crashes.swift @@ -38,7 +38,7 @@ func globalFunc() {} func globalFuncInt() -> Int { return 0 } // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LET_COMPUTED | %FileCheck %s -check-prefix=WITH_GLOBAL -class C { +class C1 { let x : Int { #^LET_COMPUTED^# } } @@ -84,8 +84,8 @@ private protocol RoundRobin : Sendable, Receivable { #endif // rdar://problem/21435993 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_21435993 -class C { +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_21435993 -code-completion-verify-usr-to-decl=false +class C2 { func test() { do {} catch { #^RDAR_21435993^# } } @@ -194,8 +194,14 @@ struct S_RDAR_28991372 { S_RDAR_28991372(x: #^RDAR_28991372^#, y: <#T##Int#>) // RDAR_28991372: Begin completions +// FIXME: We disable USR to Decl verification in the following test as it +// fails to lookup the ProtocolDecl for P due to extension binding +// triggering module lookup during the first pass of IDE inspection +// (when not all decls have been parsed yet) and caching the top-level +// decls in the module's SourceCacheLookup ignoring decls added later +// through SourceFile::addTopLevelDecl. // rdar://problem/31981486 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_31981486 | %FileCheck %s -check-prefix=RDAR_31981486 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_31981486 -code-completion-verify-usr-to-decl=false | %FileCheck %s -check-prefix=RDAR_31981486 protocol P where #^RDAR_31981486^# // RDAR_31981486: Begin completions diff --git a/test/IDE/complete_flair_cache.swift b/test/IDE/complete_flair_cache.swift index 335c97a8e8690..2124c2e0e8124 100644 --- a/test/IDE/complete_flair_cache.swift +++ b/test/IDE/complete_flair_cache.swift @@ -8,7 +8,7 @@ struct MyStruct {} protocol MyProtocol {} -func testType() { +func testType1() { let a: #^TYPE^# // TYPE-NOT: Keyword[import] // TYPE-NOT: Keyword[struct] @@ -19,7 +19,7 @@ func testType() { // TYPE-DAG: Decl[Struct]/OtherModule[Swift]/IsSystem: Int[#Int#]; name=Int } -func testType() { +func testType2() { #^EXPR^# // EXPR-DAG: Keyword[import]/None/Flair[RareKeyword]: import; name=import // EXPR-DAG: Keyword[struct]/None/Flair[RareKeyword]: struct; name=struct diff --git a/test/IDE/complete_if_switch_expr.swift b/test/IDE/complete_if_switch_expr.swift index 97b6c145a39e2..50e58285638fa 100644 --- a/test/IDE/complete_if_switch_expr.swift +++ b/test/IDE/complete_if_switch_expr.swift @@ -225,7 +225,7 @@ func testSkipTypeChecking8() throws -> E { return e } -func testSkipTypeChecking8() throws -> E { +func testSkipTypeChecking8a() throws -> E { // Only need to type-check the inner function in this case. let e: E = if Bool.random() { func localFunc() { diff --git a/test/IDE/complete_keywords.swift b/test/IDE/complete_keywords.swift index b3b85ac7a1409..1043045b4d5b8 100644 --- a/test/IDE/complete_keywords.swift +++ b/test/IDE/complete_keywords.swift @@ -343,13 +343,13 @@ enum InEnumFunc { } } -class InClassFunc { +class InClassFunc1 { func testInFuncBody4() { #^IN_FUNC_BODY_4?check=KW_DECL_STMT;check=KW_RETURN;check=KW_NO_IN^# } } -class InClassFunc { +class InClassFunc2 { class Nested { func testInFuncBody5() { #^IN_FUNC_BODY_5?check=KW_DECL_STMT;check=KW_RETURN;check=KW_NO_IN^# diff --git a/test/IDE/complete_multiple_trailingclosure.swift b/test/IDE/complete_multiple_trailingclosure.swift index 3f7de84d2b297..555ea76b3a755 100644 --- a/test/IDE/complete_multiple_trailingclosure.swift +++ b/test/IDE/complete_multiple_trailingclosure.swift @@ -113,7 +113,7 @@ struct TestStruct2 { init(fn1: () -> Int, fn2: () -> String = {}, fn3: () -> String = {}) {} func testStructMethod() {} } -func testOptionalInit() { +func testOptionalInit2() { TestStruct2 { 2 } #^INIT_OPTIONAL_SAMELINE^# @@ -148,7 +148,7 @@ struct TestStruct3 { init(fn1: () -> Int, fn2: () -> String, fn3: () -> String) {} func testStructMethod() {} } -func testOptionalInit() { +func testOptionalInit1() { // missing 'fn2' and 'fn3'. TestStruct3 { 2 diff --git a/test/IDE/complete_pound_keypath.swift b/test/IDE/complete_pound_keypath.swift index 7480b76fe2278..aabbae91ae67e 100644 --- a/test/IDE/complete_pound_keypath.swift +++ b/test/IDE/complete_pound_keypath.swift @@ -49,19 +49,19 @@ func completeInKeyPath2() { func completeInKeyPath3() { _ = #keyPath(ObjCClass.prop1.#^IN_KEYPATH_3^# } -func completeInKeyPath3() { +func completeInKeyPath4() { _ = #keyPath(String.#^IN_KEYPATH_4^# } -func completeInKeyPath4() { +func completeInKeyPath5() { _ = #keyPath(ObjCClass.prop2.#^IN_KEYPATH_5^# } -func completeInKeyPath5() { +func completeInKeyPath6() { _ = #keyPath(ObjCClass.prop3.#^IN_KEYPATH_6^# } -func completeInKeyPath6() { +func completeInKeyPath7() { _ = #keyPath(ObjCClass.prop4.anythingHere.#^IN_KEYPATH_7^# } diff --git a/test/IDE/complete_shadowing.swift b/test/IDE/complete_shadowing.swift index 2070b15f98856..2cc67d72e8982 100644 --- a/test/IDE/complete_shadowing.swift +++ b/test/IDE/complete_shadowing.swift @@ -180,7 +180,7 @@ func test_Local_GenericParamType() { } } -func test_Local_GenericParamType() { +func test_Local_GenericParam() { var testValue: String = "" func test(_: testValue) { #^Local_GenericParam?check=GENERICPARAM_TESTVALUE^# diff --git a/test/IDE/complete_sself.swift b/test/IDE/complete_sself.swift index 9aa982639035b..7ed9542884468 100644 --- a/test/IDE/complete_sself.swift +++ b/test/IDE/complete_sself.swift @@ -8,16 +8,16 @@ // DYNAMICSELF: Keyword[Self]/CurrNominal{{(/TypeRelation\[Convertible\])?}}: Self[#Self#]; -func freeFunc() { +func freeFunc1() { #^GLOBAL_BODY_EXPR?check=NOSELF^# let _: #^GLOBAL_BODY_TYPE?check=NOSELF^# } var freeVar: String { "\(#^GLOBAL_VARBODY_EXPR?check=NOSELF^#)" } -func freeFunc(x: #^GLOBAL_FUNC_PARAMTYPE?check=NOSELF^#) {} -func freeFunc(x: Int = #^GLOBAL_FUNC_DEFAULTEXPR?check=NOSELF^#) {} -func freeFunc(x: Int) -> #^GLOBAL_FUNC_RESULTTYPE?check=NOSELF^# {} +func freeFunc2(x: #^GLOBAL_FUNC_PARAMTYPE?check=NOSELF^#) {} +func freeFunc3(x: Int = #^GLOBAL_FUNC_DEFAULTEXPR?check=NOSELF^#) {} +func freeFunc4(x: Int) -> #^GLOBAL_FUNC_RESULTTYPE?check=NOSELF^# {} var x: ^#GLOBAL_VAR_TYPE^# @@ -52,38 +52,38 @@ extension P { } struct S { - func method(x: #^STRUCT_FUNC_PARAMTYPE?check=STATICSELF^#) - func method(x: Int = #^STRUCT_FUNC_DEFAULTEXPR?check=STATICSELF^#) { } - func method(x: Int) -> #^STRUCT_FUNC_RESULTTYPE?check=STATICSELF^# + func method1(x: #^STRUCT_FUNC_PARAMTYPE?check=STATICSELF^#) + func method1(x: Int = #^STRUCT_FUNC_DEFAULTEXPR?check=STATICSELF^#) { } + func method1(x: Int) -> #^STRUCT_FUNC_RESULTTYPE?check=STATICSELF^# - subscript(x: #^STRUCT_SUBSCRIPT_PARAMTYPE?check=STATICSELF^#) -> Int { get } - subscript(y: Int) -> #^STRUCT_SUBSCRIPT_RESULTTYPE?check=STATICSELF^# { get } + subscript(x1: #^STRUCT_SUBSCRIPT_PARAMTYPE?check=STATICSELF^#) -> Int { get } + subscript(y1: Int) -> #^STRUCT_SUBSCRIPT_RESULTTYPE?check=STATICSELF^# { get } - var x: #^STRUCT_VAR_TYPE?check=STATICSELF^# + var x1: #^STRUCT_VAR_TYPE?check=STATICSELF^# - func bodyTest() { + func bodyTest1() { #^STRUCT_BODY_EXPR?check=STATICSELF^# let _: #^STRUCT_BODY_TYPE?check=STATICSELF^# } - var varTest: String { + var varTest1: String { "\(#^STRUCT_VARBODY_EXPR?check=STATICSELF^#)" } } extension S { - func method(x: #^STRUCTEXT_FUNC_PARAMTYPE?check=STATICSELF^#) - func method(x: Int = #^STRUCTEXT_FUNC_DEFAULTEXPR?check=STATICSELF^#) { } - func method(x: Int) -> #^STRUCTEXT_FUNC_RESULTTYPE?check=STATICSELF^# + func method2(x: #^STRUCTEXT_FUNC_PARAMTYPE?check=STATICSELF^#) + func method2(x: Int = #^STRUCTEXT_FUNC_DEFAULTEXPR?check=STATICSELF^#) { } + func method2(x: Int) -> #^STRUCTEXT_FUNC_RESULTTYPE?check=STATICSELF^# - subscript(x: #^STRUCTEXT_SUBSCRIPT_PARAMTYPE?check=STATICSELF^#) -> Int { get } - subscript(y: Int) -> #^STRUCTEXT_SUBSCRIPT_RESULTTYPE?check=STATICSELF^# { get } + subscript(x2: #^STRUCTEXT_SUBSCRIPT_PARAMTYPE?check=STATICSELF^#) -> Int { get } + subscript(y2: Int) -> #^STRUCTEXT_SUBSCRIPT_RESULTTYPE?check=STATICSELF^# { get } - var x: #^STRUCTEXT_VAR_TYPE?check=STATICSELF^# + var x2: #^STRUCTEXT_VAR_TYPE?check=STATICSELF^# - func bodyTest() { + func bodyTest2() { #^STRUCTEXT_BODY_EXPR?check=STATICSELF^# let _: #^STRUCTEXT_BODY_TYPE?check=STATICSELF^# } - var varTest: String { + var varTest2: String { "\(#^STRUCTEXT_VARBODY_EXPR?check=STATICSELF^#)" } } diff --git a/test/IDE/complete_stmt_controlling_expr.swift b/test/IDE/complete_stmt_controlling_expr.swift index 49570276204e1..29d8e5fe43476 100644 --- a/test/IDE/complete_stmt_controlling_expr.swift +++ b/test/IDE/complete_stmt_controlling_expr.swift @@ -486,7 +486,7 @@ func testIfLetBinding2(x: FooStruct?) { func testIfLetBinding3(x: FooStruct?) { if let y = x, let z = y.#^IF_LET_BIND_3?check=FOOSTRUCT_DOT^# {} } -func testIfLetBinding3(x: FooStruct?) { +func testIfLetBinding4(x: FooStruct?) { if let y = x, let z = y#^IF_LET_BIND_4?check=FOOSTRUCT_NODOT^# {} } func testGuardLetBinding1(x: FooStruct?) { @@ -504,7 +504,7 @@ func testGuardLetBinding4(x: FooStruct?) { func testGuardLetBinding5(x: FooStruct?) { guard let y = x, let z = y.#^GUARD_LET_BIND_5?check=FOOSTRUCT_DOT^# else {} } -func testGuardLetBinding5(x: FooStruct?) { +func testGuardLetBinding6(x: FooStruct?) { guard let y = x, z = y#^GUARD_LET_BIND_6?check=FOOSTRUCT_NODOT^# else {} } func testGuardLetBinding7(x: FooStruct?) { @@ -513,10 +513,10 @@ func testGuardLetBinding7(x: FooStruct?) { func testGuardLetBinding8(_ x: FooStruct?) { guard let boundVal = x, let other = testGuardLetBinding8(#^GUARD_LET_BIND_8?check=FOOSTRUCT_LOCALVAL^#) else {} } -func testGuardCase(x:FooStruct?) { +func testGuardCase1(x:FooStruct?) { guard case .#^GUARD_CASE_PATTERN_1?check=OPTIONAL_FOOSTRUCT^# = x {} } -func testGuardCase(x:FooStruct?) { +func testGuardCase2(x:FooStruct?) { guard case .#^GUARD_CASE_PATTERN_2?check=OPTIONAL_FOOSTRUCT^#some() = x {} } diff --git a/test/IDE/complete_type.swift b/test/IDE/complete_type.swift index cac06526c5428..df39e92df3af2 100644 --- a/test/IDE/complete_type.swift +++ b/test/IDE/complete_type.swift @@ -281,7 +281,7 @@ protocol AssocType1 { //===--- Test that we can complete types in inheritance clause of associated type declarations. //===--- -protocol AssocType1 { +protocol AssocType2 { associatedtype AssocType : #^TYPE_IN_ASSOC_TYPE_INHERITANCE_1?check=WITH_GLOBAL_TYPES;check=GLOBAL_NEGATIVE^# } diff --git a/test/IDE/complete_where_clause.swift b/test/IDE/complete_where_clause.swift index 42cffcd9fc06c..7512159944216 100644 --- a/test/IDE/complete_where_clause.swift +++ b/test/IDE/complete_where_clause.swift @@ -29,9 +29,7 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ENUM_2 | %FileCheck %s -check-prefix=GEN_T_DOT // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ASSOC_1 | %FileCheck %s -check-prefix=P2 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ASSOC_2 | %FileCheck %s -check-prefix=U_DOT -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL | %FileCheck %s -check-prefix=PROTOCOL // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_EXT | %FileCheck %s -check-prefix=PROTOCOL -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SELF | %FileCheck %s -check-prefix=PROTOCOL_SELF // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NOMINAL_TYPEALIAS | %FileCheck %s -check-prefix=NOMINAL_TYPEALIAS // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NOMINAL_TYPEALIAS_EXT | %FileCheck %s -check-prefix=NOMINAL_TYPEALIAS_EXT // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=NOMINAL_TYPEALIAS_NESTED1 | %FileCheck %s -check-prefix=NOMINAL_TYPEALIAS_NESTED1 @@ -43,6 +41,15 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=EXT_SECONDTYPE | %FileCheck %s -check-prefix=EXT_SECONDTYPE // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=WHERE_CLAUSE_WITH_EQUAL | %FileCheck %s -check-prefix=WHERE_CLAUSE_WITH_EQUAL +// FIXME: We disable USR to Decl verification in the following 2 tests as it +// fails to lookup the ProtocolDecl for P3 and P4 due to extension +// binding triggering module lookup during the first pass of IDE +// inspection (when not all decls have been parsed yet) and caching the +// top-level decls in the module's SourceCacheLookup ignoring decls added +// later through SourceFile::addTopLevelDecl. +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL -code-completion-verify-usr-to-decl=false | %FileCheck %s -check-prefix=PROTOCOL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SELF -code-completion-verify-usr-to-decl=false | %FileCheck %s -check-prefix=PROTOCOL_SELF + class A1 {} class A2 {} diff --git a/test/SourceKit/CodeComplete/complete_filter_rules.swift b/test/SourceKit/CodeComplete/complete_filter_rules.swift index 437ac7079b195..beb965ba5343d 100644 --- a/test/SourceKit/CodeComplete/complete_filter_rules.swift +++ b/test/SourceKit/CodeComplete/complete_filter_rules.swift @@ -216,7 +216,7 @@ func testHideDesc2() { // RUN: %complete-test -filter-rules=%S/Inputs/filter-rules/showDesc.json -tok=SHOW_DESC_2 %s -- -F %S/../Inputs/libIDE-mock-sdk | %FileCheck %s -check-prefix=SHOW_DESC_2 // RUN: %complete-test -filter-rules=%S/Inputs/filter-rules/showDesc.json -tok=SHOW_DESC_3 %s -- -F %S/../Inputs/libIDE-mock-sdk | %FileCheck %s -check-prefix=SHOW_DESC_2 -func testHideDesc2() { +func testShowDesc2() { struct Local { subscript(_: Int) -> Int { return 0 } subscript(_: Float) -> Float { return 0.0 } diff --git a/test/SourceKit/CodeComplete/complete_fuzzy.swift b/test/SourceKit/CodeComplete/complete_fuzzy.swift index 6f9c03f84f615..5b9dc8ad83c63 100644 --- a/test/SourceKit/CodeComplete/complete_fuzzy.swift +++ b/test/SourceKit/CodeComplete/complete_fuzzy.swift @@ -48,7 +48,7 @@ func test3() { // RUN: %complete-test %s -group=stems -no-fuzz -tok=S1_QUAL_1 | %FileCheck %s -check-prefix=S1_QUAL_1_PREFIX // RUN: %complete-test %s -group=stems -fuzz -tok=S1_QUAL_1 | %FileCheck %s -check-prefix=S1_QUAL_1_FUZZ -func test3() { +func test4() { #^S1_QUAL_1,foo,bar,tast,footast^# // S1_QUAL_1_PREFIX-LABEL: Results for filterText: foo [ // S1_QUAL_1_PREFIX-NEXT: fooBar: diff --git a/test/SourceKit/CodeComplete/complete_sort_order.swift b/test/SourceKit/CodeComplete/complete_sort_order.swift index 90adec76d01ef..0c79938cb7e31 100644 --- a/test/SourceKit/CodeComplete/complete_sort_order.swift +++ b/test/SourceKit/CodeComplete/complete_sort_order.swift @@ -156,7 +156,7 @@ func test4(x: Int) { // Top 3 with type matching // RUN: %complete-test -top=3 -tok=EXPR_3 %s | %FileCheck %s -check-prefix=EXPR_TOP_3_TYPE_MATCH -func test4(x: Int) { +func test4b(x: Int) { let y: String = "" let z: String = y let zzz = x From 22750b371a5141ba35fea8ba5eaa268fd53b7e67 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 19 Jul 2025 12:17:21 +0300 Subject: [PATCH 22/58] [IDE] Verify decls match in verify USR to Decl reconstruction --- lib/IDE/CodeCompletionResultBuilder.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index f31381f59fd0e..0918fef2aff08 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -112,6 +112,15 @@ static void verifyUSRToDeclReconstruction(const Decl *D) { assert(false && "Reconstructed declaration shouldn't be null"); } + + if (Reconstructed != VD) { + llvm::errs() << "Swift USR is " << SwiftUSR << ", reconstructed declaration is:\n"; + Reconstructed->dump(llvm::errs()); + llvm::errs() << "Original declaration is:\n"; + VD->dump(llvm::errs()); + + assert(false && "Reconstructed declaration should match the original one"); + } } void CodeCompletionResultBuilder::addChunkWithText( @@ -224,13 +233,6 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { ContextFreeResult->calculateContextualNotRecommendedReason( ContextualNotRecReason, CanCurrDeclContextHandleAsync); - // TODO(a7medev): Move to completion options. - bool verifyUSRToDecl = true; - if (verifyUSRToDecl) { - auto &Ctx = DC->getASTContext(); - verifyUSRToDeclReconstruction(Ctx, AssociatedDecl); - } - return new (Allocator) CodeCompletionResult( *ContextFreeResult, SemanticContext, Flair, NumBytesToErase, typeRelation, notRecommendedReason); From a7c0a20e66c1b8e1777e6260d4c465065ad64fbe Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 19 Jul 2025 14:08:05 +0300 Subject: [PATCH 23/58] [Demangle] Enhance coding style in ASTDemangler & DeclNameExtractor --- include/swift/AST/ASTDemangler.h | 4 ++++ include/swift/AST/DeclNameExtractor.h | 6 +++--- lib/AST/ASTDemangler.cpp | 24 ++++++++++++++---------- lib/AST/DeclNameExtractor.cpp | 12 ++++++------ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index e8a2b5d9e9b6e..3240bf9f7e087 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -317,6 +317,10 @@ class ASTBuilder { static GenericTypeDecl *getAcceptableTypeDeclCandidate(ValueDecl *decl, Demangle::Node::Kind kind); + + /// Returns an identifier with the given name, automatically removing any + /// surrounding backticks that are present for raw identifiers. + Identifier getIdentifier(StringRef name); }; SWIFT_END_INLINE_NAMESPACE diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h index edaf986496222..ce940b500bf1e 100644 --- a/include/swift/AST/DeclNameExtractor.h +++ b/include/swift/AST/DeclNameExtractor.h @@ -1,4 +1,4 @@ -//===--- DeclNameExtractor.h - Swift Language Type Locations --------------*- C++ -*-===// +//===--- DeclNameExtractor.h - Decl Name Demangling --------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // @@ -54,5 +54,5 @@ bool extractNameNodeInfo(ASTContext &Ctx, Node *node, StringRef &name, StringRef &relatedEntityKind, Identifier &privateDiscriminator); -} // end namespace swift -} // end namespace Demangle +} // namespace Demangle +} // namespace swift diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index aaf1e32593f4c..a4ea2a5e60c7d 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -220,7 +220,7 @@ TypeDecl *ASTBuilder::createTypeDecl(NodePointer node) { if (proto == nullptr) return nullptr; - auto name = getIdentifier(Ctx, node->getChild(1)->getText()); + auto name = getIdentifier(node->getChild(1)->getText()); return proto->getAssociatedType(name); } @@ -236,7 +236,7 @@ ASTBuilder::createBuiltinType(StringRef builtinName, StringRef strippedName = builtinName.drop_front(BUILTIN_TYPE_NAME_PREFIX.size()); - Ctx.TheBuiltinModule->lookupValue(getIdentifier(Ctx, strippedName), + Ctx.TheBuiltinModule->lookupValue(getIdentifier(strippedName), NLKind::QualifiedLookup, decls); if (decls.size() == 1 && isa(decls[0])) @@ -475,7 +475,7 @@ Type ASTBuilder::createTupleType(ArrayRef eltTypes, ArrayRef la for (unsigned i : indices(eltTypes)) { Identifier label; if (!labels[i].empty()) - label = getIdentifier(Ctx, labels[i]); + label = getIdentifier(labels[i]); elements.emplace_back(eltTypes[i], label); } @@ -535,7 +535,7 @@ Type ASTBuilder::createFunctionType( if (!type->isMaterializable()) return Type(); - auto label = getIdentifier(Ctx, param.getLabel()); + auto label = getIdentifier(param.getLabel()); auto flags = param.getFlags(); auto ownership = ParamDecl::getParameterSpecifierForValueOwnership(asValueOwnership(flags.getOwnership())); @@ -1046,7 +1046,7 @@ Type ASTBuilder::createGenericTypeParameterType(unsigned depth, Type ASTBuilder::createDependentMemberType(StringRef member, Type base) { - auto identifier = getIdentifier(Ctx, member); + auto identifier = getIdentifier(member); if (auto *archetype = base->getAs()) { if (Type memberType = archetype->getNestedTypeByName(identifier)) @@ -1063,7 +1063,7 @@ Type ASTBuilder::createDependentMemberType(StringRef member, Type ASTBuilder::createDependentMemberType(StringRef member, Type base, ProtocolDecl *protocol) { - auto identifier = getIdentifier(Ctx, member); + auto identifier = getIdentifier(member); if (auto *archetype = base->getAs()) { if (auto assocType = protocol->getAssociatedType(identifier)) @@ -1307,7 +1307,7 @@ ASTBuilder::getAcceptableTypeDeclCandidate(ValueDecl *decl, DeclContext *ASTBuilder::getNotionalDC() { if (!NotionalDC) { - NotionalDC = ModuleDecl::createEmpty(getIdentifier(Ctx, ".RemoteAST"), Ctx); + NotionalDC = ModuleDecl::createEmpty(getIdentifier(".RemoteAST"), Ctx); NotionalDC = new (Ctx) TopLevelCodeDecl(NotionalDC); } return NotionalDC; @@ -1505,14 +1505,14 @@ ASTBuilder::findDeclContext(NodePointer node) { return nullptr; for (auto *module : potentialModules) - if (auto typeDecl = findTypeDecl(module, getIdentifier(Ctx, name), + if (auto typeDecl = findTypeDecl(module, getIdentifier(name), privateDiscriminator, node->getKind())) return typeDecl; return nullptr; } if (auto *dc = findDeclContext(child)) - if (auto typeDecl = findTypeDecl(dc, getIdentifier(Ctx, name), + if (auto typeDecl = findTypeDecl(dc, getIdentifier(name), privateDiscriminator, node->getKind())) return typeDecl; @@ -1715,7 +1715,7 @@ GenericTypeDecl *ASTBuilder::findForeignTypeDecl(StringRef name, found); break; } - importer->lookupValue(getIdentifier(Ctx, name), consumer); + importer->lookupValue(getIdentifier(name), consumer); if (consumer.Result) consumer.Result = getAcceptableTypeDeclCandidate(consumer.Result, kind); break; @@ -1725,3 +1725,7 @@ GenericTypeDecl *ASTBuilder::findForeignTypeDecl(StringRef name, return consumer.Result; } + +Identifier ASTBuilder::getIdentifier(StringRef name) { + return Demangle::getIdentifier(Ctx, name); +} diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index df64f7eaba701..c50e7fb9bfe90 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -55,8 +55,6 @@ bool DeclNameExtractor::extractDeclName(Node *node, DeclName &name, return true; case Node::Kind::Function: - return extractFunctionLikeName(node, name, privateDiscriminator); - case Node::Kind::Subscript: return extractFunctionLikeName(node, name, privateDiscriminator); @@ -116,20 +114,22 @@ DeclNameExtractor::extractFunctionLikeName(Node *node, DeclName &declName, // Location of LabelList node if present, otherwise a Type node. unsigned LabelListIdx; - if (node->getKind() == Node::Kind::Function) + if (node->getKind() == Node::Kind::Function) { LabelListIdx = 2; - else + } else { LabelListIdx = 1; + } auto *LabelsOrType = node->getChild(LabelListIdx); assert(LabelsOrType != nullptr && (LabelsOrType->getKind() == Node::Kind::LabelList || LabelsOrType->getKind() == Node::Kind::Type)); SmallVector ArgLabels; - if (LabelsOrType->getKind() == Node::Kind::LabelList) + if (LabelsOrType->getKind() == Node::Kind::LabelList) { extractArgLabelsFromLabelList(LabelsOrType, ArgLabels); - else + } else { extractArgLabelsFromType(LabelsOrType, ArgLabels); + } if (ArgLabels.empty()) { declName = DeclName(BaseName); From 72e87e56d25b5e2f0f2f8da4720ef324901cc8c7 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 19 Jul 2025 14:18:15 +0300 Subject: [PATCH 24/58] [Demangle] Generalize ASTDemangler::findDecl to take a predicate function instead of fixed USR matching --- include/swift/AST/ASTDemangler.h | 10 +++++++++- lib/AST/ASTDemangler.cpp | 33 +++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 3240bf9f7e087..19755a3d400fb 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -128,7 +128,15 @@ class ASTBuilder { Demangle::NodeFactory &getNodeFactory() { return Factory; } - Decl *findDecl(NodePointer node, StringRef usr); + /// Finds the \c Decl associated with the provided \p node. + /// Attempts to find a type declaration using \c createTypeDecl, if not found, it performs a lookup + /// for the declaration and returns the first declaration for which \c isMatchingValueDecl returns true. + /// + /// \note \p isMatchingValueDecl is not evaluated for type declarations, it's only used to choose + /// among lookup results when \c createTypeDecl fails. + Decl *findDecl( + NodePointer node, + llvm::function_ref isMatchingValueDecl); Type decodeMangledType(NodePointer node, bool forRequirement = true); Type createBuiltinType(StringRef builtinName, StringRef mangledName); diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index a4ea2a5e60c7d..872953b0dfbea 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -56,7 +56,18 @@ Decl *swift::Demangle::getDeclForUSR(ASTContext &ctx, StringRef usr, auto node = Dem.demangleSymbolAsNode(mangling); ASTBuilder builder(ctx, genericSig); - return builder.findDecl(node, usr); + + auto hasMatchingUSR = [usr](const ValueDecl *VD) { + SmallString<128> candidateUSR; + llvm::raw_svector_ostream OS(candidateUSR); + + if (ide::printValueDeclSwiftUSR(VD, OS)) + return false; + + return usr == candidateUSR; + }; + + return builder.findDecl(node, /*isMatchingValueDecl=*/hasMatchingUSR); } Type swift::Demangle::getTypeForMangling(ASTContext &ctx, @@ -121,7 +132,9 @@ findTopLevelClangDecl(ClangModuleLoader *importer, DeclName name, return consumer.Result; } -Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { +Decl *ASTBuilder::findDecl( + NodePointer node, + llvm::function_ref isMatchingValueDecl) { if (node == nullptr) return nullptr; @@ -139,7 +152,7 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { case Node::Kind::BoundGenericTypeAlias: case Node::Kind::BoundGenericOtherNominalType: case Node::Kind::Extension: - return findDecl(node->getFirstChild(), usr); + return findDecl(node->getFirstChild(), isMatchingValueDecl); default: // We should have arrived at a declaration node by now break; @@ -156,22 +169,12 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { if (!contextNode) return nullptr; - auto hasMatchingUSR = [usr](const ValueDecl *VD) { - SmallString<128> candidateUSR; - llvm::raw_svector_ostream OS(candidateUSR); - - if (ide::printValueDeclSwiftUSR(VD, OS)) - return false; - - return usr == candidateUSR; - }; - SmallVector candidates; if (contextNode->getKind() == Node::Kind::Module) { // If a foreign Clang module, perform lookup in Clang importer if (auto kind = getForeignModuleKind(contextNode)) { auto *importer = Ctx.getClangModuleLoader(); - return findTopLevelClangDecl(importer, name, hasMatchingUSR); + return findTopLevelClangDecl(importer, name, isMatchingValueDecl); } ModuleDecl *scratch; @@ -194,7 +197,7 @@ Decl *ASTBuilder::findDecl(NodePointer node, StringRef usr) { } for (auto *candidate : candidates) { - if (hasMatchingUSR(candidate)) + if (isMatchingValueDecl(candidate)) return candidate; } From 08c03c10c3ed02fc98ba816a4cb77a78357487e0 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Tue, 25 Mar 2025 02:37:16 +0200 Subject: [PATCH 25/58] [IDE] Add full documentation to code completion result --- include/swift/IDE/CodeCompletionResult.h | 23 ++++++++++++++----- lib/IDE/CodeCompletionCache.cpp | 7 ++++-- lib/IDE/CodeCompletionResult.cpp | 15 ++++++++---- lib/IDE/CodeCompletionResultBuilder.cpp | 14 +++++++++-- lib/IDE/CodeCompletionResultBuilder.h | 5 ++++ lib/IDE/CompletionOverrideLookup.cpp | 1 + .../include/SourceKit/Core/LangSupport.h | 1 + .../SourceKit/lib/SwiftLang/CodeCompletion.h | 4 ++++ .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 4 +++- .../lib/SwiftLang/SwiftCompletion.cpp | 4 +++- .../bin/InProc/CodeCompletionSwiftInterop.cpp | 11 +++++++++ .../bin/InProc/CodeCompletionSwiftInterop.h | 5 ++++ .../sourcekitd/CodeCompletionResultsArray.h | 1 + .../lib/API/CodeCompletionResultsArray.cpp | 18 +++++++++++---- .../tools/sourcekitd/lib/Service/Requests.cpp | 6 +++++ tools/swift-ide-test/swift-ide-test.cpp | 13 +++++++---- 16 files changed, 106 insertions(+), 26 deletions(-) diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index 9e247d1552191..c34329894ac05 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -378,6 +378,7 @@ class ContextFreeCodeCompletionResult { CodeCompletionString *CompletionString; NullTerminatedStringRef ModuleName; NullTerminatedStringRef BriefDocComment; + NullTerminatedStringRef FullDocComment; ArrayRef AssociatedUSRs; CodeCompletionResultType ResultType; @@ -410,6 +411,7 @@ class ContextFreeCodeCompletionResult { bool HasAsyncAlternative, CodeCompletionString *CompletionString, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, + NullTerminatedStringRef FullDocComment, ArrayRef AssociatedUSRs, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, @@ -421,9 +423,9 @@ class ContextFreeCodeCompletionResult { MacroRoles(MacroRoles), IsSystem(IsSystem), HasAsyncAlternative(HasAsyncAlternative), CompletionString(CompletionString), ModuleName(ModuleName), - BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs), - ResultType(ResultType), NotRecommended(NotRecommended), - DiagnosticSeverity(DiagnosticSeverity), + BriefDocComment(BriefDocComment), FullDocComment(FullDocComment), + AssociatedUSRs(AssociatedUSRs), ResultType(ResultType), + NotRecommended(NotRecommended), DiagnosticSeverity(DiagnosticSeverity), DiagnosticMessage(DiagnosticMessage), FilterName(FilterName), NameForDiagnostics(NameForDiagnostics) { this->AssociatedKind.Opaque = AssociatedKind; @@ -453,6 +455,7 @@ class ContextFreeCodeCompletionResult { CodeCompletionString *CompletionString, CodeCompletionOperatorKind KnownOperatorKin, NullTerminatedStringRef BriefDocComment, + NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, @@ -460,14 +463,15 @@ class ContextFreeCodeCompletionResult { /// Constructs a \c Keyword result. /// - /// \note The caller must ensure that the \p CompletionString and - /// \p BriefDocComment outlive this result, typically by storing them in - /// the same \c CodeCompletionResultSink as the result itself. + /// \note The caller must ensure that the \p CompletionString, \p BriefDocComment, + /// and \p FullDocComment outlive this result, typically by storing them in the same + /// \c CodeCompletionResultSink as the result itself. static ContextFreeCodeCompletionResult * createKeywordResult(CodeCompletionResultSink &Sink, CodeCompletionKeywordKind Kind, CodeCompletionString *CompletionString, NullTerminatedStringRef BriefDocComment, + NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType); /// Constructs a \c Literal result. @@ -492,6 +496,7 @@ class ContextFreeCodeCompletionResult { const Decl *AssociatedDecl, bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, + NullTerminatedStringRef FullDocComment, ArrayRef AssociatedUSRs, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, @@ -536,6 +541,8 @@ class ContextFreeCodeCompletionResult { NullTerminatedStringRef getBriefDocComment() const { return BriefDocComment; } + NullTerminatedStringRef getFullDocComment() const { return FullDocComment; } + ArrayRef getAssociatedUSRs() const { return AssociatedUSRs; } @@ -741,6 +748,10 @@ class CodeCompletionResult { return getContextFreeResult().getBriefDocComment(); } + NullTerminatedStringRef getFullDocComment() const { + return getContextFreeResult().getFullDocComment(); + } + ArrayRef getAssociatedUSRs() const { return getContextFreeResult().getAssociatedUSRs(); } diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp index d8a4e4e84ebe8..7b874025cc833 100644 --- a/lib/IDE/CodeCompletionCache.cpp +++ b/lib/IDE/CodeCompletionCache.cpp @@ -241,6 +241,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in, auto chunkIndex = read32le(cursor); auto moduleIndex = read32le(cursor); auto briefDocIndex = read32le(cursor); + auto fullDocIndex = read32le(cursor); auto diagMessageIndex = read32le(cursor); auto filterNameIndex = read32le(cursor); auto nameForDiagnosticsIndex = read32le(cursor); @@ -261,6 +262,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in, CodeCompletionString *string = getCompletionString(chunkIndex); auto moduleName = getString(moduleIndex); auto briefDocComment = getString(briefDocIndex); + auto fullDocComment = getString(fullDocIndex); auto diagMessage = getString(diagMessageIndex); auto filterName = getString(filterNameIndex); auto nameForDiagnostics = getString(nameForDiagnosticsIndex); @@ -268,8 +270,8 @@ static bool readCachedModule(llvm::MemoryBuffer *in, ContextFreeCodeCompletionResult *result = new (*V.Allocator) ContextFreeCodeCompletionResult( kind, associatedKind, opKind, roles, isSystem, - hasAsyncAlternative, string, moduleName, briefDocComment, - llvm::ArrayRef(assocUSRs).copy(*V.Allocator), + hasAsyncAlternative, string, moduleName, briefDocComment, + fullDocComment, llvm::ArrayRef(assocUSRs).copy(*V.Allocator), CodeCompletionResultType(resultTypes), notRecommended, diagSeverity, diagMessage, filterName, nameForDiagnostics); @@ -432,6 +434,7 @@ static void writeCachedModule(llvm::raw_ostream &out, static_cast(addCompletionString(R->getCompletionString()))); LE.write(addString(R->getModuleName())); // index into strings LE.write(addString(R->getBriefDocComment())); // index into strings + LE.write(addString(R->getFullDocComment())); // index into strings LE.write(addString(R->getDiagnosticMessage())); // index into strings LE.write(addString(R->getFilterName())); // index into strings LE.write(addString(R->getNameForDiagnostics())); // index into strings diff --git a/lib/IDE/CodeCompletionResult.cpp b/lib/IDE/CodeCompletionResult.cpp index e5490285c5d7d..20cb8fb7b725c 100644 --- a/lib/IDE/CodeCompletionResult.cpp +++ b/lib/IDE/CodeCompletionResult.cpp @@ -135,7 +135,9 @@ ContextFreeCodeCompletionResult * ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( CodeCompletionResultSink &Sink, CodeCompletionResultKind Kind, CodeCompletionString *CompletionString, - CodeCompletionOperatorKind KnownOperatorKind, NullTerminatedStringRef BriefDocComment, + CodeCompletionOperatorKind KnownOperatorKind, + NullTerminatedStringRef BriefDocComment, + NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, @@ -153,7 +155,7 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( Kind, /*AssociatedKind=*/0, KnownOperatorKind, /*MacroRoles=*/{}, /*IsSystem=*/false, /*HasAsyncAlternative=*/false, CompletionString, - /*ModuleName=*/"", BriefDocComment, + /*ModuleName=*/"", BriefDocComment, FullDocComment, /*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), @@ -165,6 +167,7 @@ ContextFreeCodeCompletionResult::createKeywordResult( CodeCompletionResultSink &Sink, CodeCompletionKeywordKind Kind, CodeCompletionString *CompletionString, NullTerminatedStringRef BriefDocComment, + NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType) { if (Sink.shouldProduceContextFreeResults()) { ResultType = ResultType.usrBasedType(Sink.getUSRTypeArena()); @@ -173,7 +176,7 @@ ContextFreeCodeCompletionResult::createKeywordResult( CodeCompletionResultKind::Keyword, static_cast(Kind), CodeCompletionOperatorKind::None, /*MacroRoles=*/{}, /*IsSystem=*/false, /*HasAsyncAlternative=*/false, CompletionString, - /*ModuleName=*/"", BriefDocComment, + /*ModuleName=*/"", BriefDocComment, FullDocComment, /*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"", getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), @@ -195,6 +198,7 @@ ContextFreeCodeCompletionResult::createLiteralResult( CompletionString, /*ModuleName=*/"", /*BriefDocComment=*/"", + /*FullDocComment=*/"", /*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"", getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), @@ -221,6 +225,7 @@ ContextFreeCodeCompletionResult::createDeclResult( CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString, const Decl *AssociatedDecl, bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, + NullTerminatedStringRef FullDocComment, ArrayRef AssociatedUSRs, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, @@ -234,8 +239,8 @@ ContextFreeCodeCompletionResult::createDeclResult( CodeCompletionResultKind::Declaration, static_cast(getCodeCompletionDeclKind(AssociatedDecl)), CodeCompletionOperatorKind::None, getCompletionMacroRoles(AssociatedDecl), - getDeclIsSystem(AssociatedDecl), HasAsyncAlternative, - CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType, + getDeclIsSystem(AssociatedDecl), HasAsyncAlternative, CompletionString, + ModuleName, BriefDocComment, FullDocComment, AssociatedUSRs, ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), /*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink)); diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 0918fef2aff08..76111daecb154 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -19,6 +19,7 @@ #include "swift/Basic/LLVM.h" #include "swift/IDE/CodeCompletionStringPrinter.h" #include "swift/IDE/Utils.h" +#include "swift/IDE/CommentConversion.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Comment.h" #include "clang/Basic/Module.h" @@ -183,6 +184,7 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { ContextFreeResult = ContextFreeCodeCompletionResult::createDeclResult( Sink, CCS, AssociatedDecl, HasAsyncAlternative, ModuleName, NullTerminatedStringRef(BriefDocComment, Allocator), + NullTerminatedStringRef(FullDocComment, Allocator), copyAssociatedUSRs(Allocator, AssociatedDecl), ResultType, ContextFreeNotRecReason, ContextFreeDiagnosticSeverity, ContextFreeDiagnosticMessage); @@ -192,14 +194,16 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { case CodeCompletionResultKind::Keyword: ContextFreeResult = ContextFreeCodeCompletionResult::createKeywordResult( Sink, KeywordKind, CCS, - NullTerminatedStringRef(BriefDocComment, Allocator), ResultType); + NullTerminatedStringRef(BriefDocComment, Allocator), + NullTerminatedStringRef(FullDocComment, Allocator), ResultType); break; case CodeCompletionResultKind::BuiltinOperator: case CodeCompletionResultKind::Pattern: ContextFreeResult = ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( Sink, Kind, CCS, CodeCompletionOperatorKind::None, - NullTerminatedStringRef(BriefDocComment, Allocator), ResultType, + NullTerminatedStringRef(BriefDocComment, Allocator), + NullTerminatedStringRef(FullDocComment, Allocator), ResultType, ContextFreeNotRecReason, ContextFreeDiagnosticSeverity, ContextFreeDiagnosticMessage); break; @@ -271,6 +275,12 @@ void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) { setContextFreeNotRecommended( ContextFreeNotRecommendedReason::SoftDeprecated); + SmallString<256> Buffer; + llvm::raw_svector_ostream OS(Buffer); + ide::getDocumentationCommentAsXML(D, OS, /*IncludeParameters=*/true); + + setFullDocComment(StringRef(Buffer).copy(Sink.getAllocator())); + if (D->getClangNode()) { if (auto *ClangD = D->getClangDecl()) { const auto &ClangContext = ClangD->getASTContext(); diff --git a/lib/IDE/CodeCompletionResultBuilder.h b/lib/IDE/CodeCompletionResultBuilder.h index 43138edee57b9..6739b2e8144d0 100644 --- a/lib/IDE/CodeCompletionResultBuilder.h +++ b/lib/IDE/CodeCompletionResultBuilder.h @@ -57,6 +57,7 @@ class CodeCompletionResultBuilder { ContextualNotRecommendedReason ContextualNotRecReason = ContextualNotRecommendedReason::None; StringRef BriefDocComment; + StringRef FullDocComment; /// The result type that this completion item produces. CodeCompletionResultType ResultType = CodeCompletionResultType::unknown(); @@ -491,6 +492,10 @@ class CodeCompletionResultBuilder { void setBriefDocComment(StringRef comment) { BriefDocComment = comment; } + + void setFullDocComment(StringRef comment) { + FullDocComment = comment; + } }; } // namespace ide diff --git a/lib/IDE/CompletionOverrideLookup.cpp b/lib/IDE/CompletionOverrideLookup.cpp index 09778c67cc63e..91d2d71fd07f0 100644 --- a/lib/IDE/CompletionOverrideLookup.cpp +++ b/lib/IDE/CompletionOverrideLookup.cpp @@ -462,6 +462,7 @@ void CompletionOverrideLookup::addResultBuilderBuildCompletion( Builder.addTextChunk(declStringWithoutFunc); Builder.addBraceStmtWithCursor(); Builder.setBriefDocComment(getResultBuilderDocComment(function)); + Builder.setFullDocComment(getResultBuilderDocComment(function)); } void CompletionOverrideLookup::addResultBuilderBuildCompletions( diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h index 4aa616c391394..2213d0d1f8cba 100644 --- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h +++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h @@ -90,6 +90,7 @@ struct CodeCompletionInfo { StringRef TypeName; StringRef ModuleName; StringRef DocBrief; + StringRef DocFull; StringRef AssocUSRs; UIdent SemanticContext; UIdent TypeRelation; diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h index e6d159b99cce8..f926b042628d5 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h @@ -166,6 +166,10 @@ class Completion { return getSwiftResult().getBriefDocComment(); } + StringRef getFullDocComment() const { + return getSwiftResult().getFullDocComment(); + } + ArrayRef getAssociatedUSRs() const { return getSwiftResult().getAssociatedUSRs(); } diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index bbbabb2f6d499..bd6c0899db81d 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -135,7 +135,8 @@ bool SourceKit::CodeCompletion::addCustomCompletions( ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( sink.swiftSink, CodeCompletionResultKind::Pattern, completionString, CodeCompletionOperatorKind::None, - /*BriefDocComment=*/"", CodeCompletionResultType::unknown(), + /*BriefDocComment=*/"", /*FullDocComment=*/"", + CodeCompletionResultType::unknown(), ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); auto *swiftResult = new (sink.allocator) CodeCompletion::SwiftResult( @@ -1160,6 +1161,7 @@ Completion *CompletionBuilder::finish() { contextFreeBase.hasAsyncAlternative(), newCompletionString, contextFreeBase.getModuleName(), contextFreeBase.getBriefDocComment(), + contextFreeBase.getFullDocComment(), contextFreeBase.getAssociatedUSRs(), contextFreeBase.getResultType(), contextFreeBase.getNotRecommendedReason(), diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index b133af77eb5d8..a1b168c48df55 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -536,6 +536,7 @@ bool SwiftToSourceKitCompletionAdapter::handleResult( Info.ModuleName = Result->getModuleName(); Info.DocBrief = Result->getBriefDocComment(); + Info.DocFull = Result->getFullDocComment(); Info.NotRecommended = Result->isNotRecommended(); Info.IsSystem = Result->isSystem(); @@ -912,7 +913,8 @@ static void transformAndForwardResults( ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( innerSink.swiftSink, CodeCompletionResultKind::BuiltinOperator, completionString, CodeCompletionOperatorKind::None, - /*BriefDocComment=*/"", CodeCompletionResultType::notApplicable(), + /*BriefDocComment=*/"", /*FullDocComment=*/"", + CodeCompletionResultType::notApplicable(), ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp index bc55276e0d8a4..9645ec7abad11 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -663,6 +663,17 @@ void swiftide_completion_item_get_doc_brief( handler(item.getBriefDocComment().data()); } +// TODO(a7medev): Is this function required? +void swiftide_completion_item_get_doc_full( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(const char *)) { + auto &item = *static_cast(_item); + if (item.getFullDocComment().empty()) { + return handler(nullptr); + } + handler(item.getFullDocComment().data()); +} + void swiftide_completion_item_get_associated_usrs( swiftide_completion_response_t _response, swiftide_completion_item_t _item, void (^handler)(const char **, uint64_t)) { diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h index 2df944d74f4ed..d8abbed279f50 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h @@ -347,6 +347,11 @@ swiftide_completion_item_get_doc_brief(swiftide_completion_response_t, swiftide_completion_item_t, void (^handler)(const char *)); +SWIFTIDE_PUBLIC void +swiftide_completion_item_get_doc_full(swiftide_completion_response_t, + swiftide_completion_item_t, + void (^handler)(const char *)); + SWIFTIDE_PUBLIC void swiftide_completion_item_get_associated_usrs( swiftide_completion_response_t, swiftide_completion_item_t, void (^handler)(const char **, uint64_t)); diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h index 518b5db8f139f..a182e65359a38 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h @@ -28,6 +28,7 @@ class CodeCompletionResultsArrayBuilder { llvm::StringRef Description, llvm::StringRef SourceText, llvm::StringRef TypeName, std::optional ModuleName, std::optional DocBrief, + std::optional DocFull, std::optional AssocUSRs, SourceKit::UIdent SemanticContext, SourceKit::UIdent TypeRelation, bool NotRecommended, bool IsSystem, unsigned NumBytesToErase); diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp index a6e16f70dc25f..211df5e3e7182 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp @@ -24,8 +24,8 @@ using namespace sourcekitd; struct CodeCompletionResultsArrayBuilder::Implementation { CompactArrayBuilder, std::optional, - std::optional, UIdent, UIdent, uint8_t, - uint8_t> + std::optional, std::optional, + UIdent, UIdent, uint8_t, uint8_t> Builder; }; @@ -41,9 +41,10 @@ CodeCompletionResultsArrayBuilder::~CodeCompletionResultsArrayBuilder() { void CodeCompletionResultsArrayBuilder::add( UIdent Kind, StringRef Name, StringRef Description, StringRef SourceText, StringRef TypeName, std::optional ModuleName, - std::optional DocBrief, std::optional AssocUSRs, - UIdent SemanticContext, UIdent TypeRelation, bool NotRecommended, - bool IsSystem, unsigned NumBytesToErase) { + std::optional DocBrief, std::optional DocFull, + std::optional AssocUSRs, UIdent SemanticContext, + UIdent TypeRelation, bool NotRecommended, bool IsSystem, + unsigned NumBytesToErase) { uint8_t Flags = 0; Flags |= NotRecommended << 1; @@ -58,6 +59,7 @@ void CodeCompletionResultsArrayBuilder::add( TypeName, ModuleName, DocBrief, + DocFull, AssocUSRs, SemanticContext, TypeRelation, @@ -83,6 +85,7 @@ class CodeCompletionResultsArray { const char *, const char *, const char *, + const char *, sourcekitd_uid_t, sourcekitd_uid_t, uint8_t, @@ -101,6 +104,7 @@ class CodeCompletionResultsArray { const char *TypeName; const char *ModuleName; const char *DocBrief; + const char *DocFull; const char *AssocUSRs; sourcekitd_uid_t SemanticContext; sourcekitd_uid_t TypeRelation; @@ -115,6 +119,7 @@ class CodeCompletionResultsArray { TypeName, ModuleName, DocBrief, + DocFull, AssocUSRs, SemanticContext, TypeRelation, @@ -143,6 +148,9 @@ class CodeCompletionResultsArray { if (DocBrief) { APPLY(KeyDocBrief, String, DocBrief); } + if (DocFull) { + APPLY(KeyDocFullAsXML, String, DocFull); + } if (AssocUSRs) { APPLY(KeyAssociatedUSRs, String, AssocUSRs); } diff --git a/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp index fca57f07de4da..f08d8c89b41b8 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp @@ -3189,6 +3189,9 @@ bool SKCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) { std::optional DocBriefOpt; if (!R.DocBrief.empty()) DocBriefOpt = R.DocBrief; + std::optional DocFullOpt; + if (!R.DocFull.empty()) + DocFullOpt = R.DocFull; std::optional AssocUSRsOpt; if (!R.AssocUSRs.empty()) AssocUSRsOpt = R.AssocUSRs; @@ -3202,6 +3205,7 @@ bool SKCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) { R.TypeName, ModuleNameOpt, DocBriefOpt, + DocFullOpt, AssocUSRsOpt, R.SemanticContext, R.TypeRelation, @@ -3377,6 +3381,8 @@ bool SKGroupedCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) result.set(KeyModuleName, R.ModuleName); if (!R.DocBrief.empty()) result.set(KeyDocBrief, R.DocBrief); + if (!R.DocFull.empty()) + result.set(KeyDocFullAsXML, R.DocFull); if (!R.AssocUSRs.empty()) result.set(KeyAssociatedUSRs, R.AssocUSRs); if (R.ModuleImportDepth) diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index dd8fbf5d09342..583a5c8810d66 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -1351,9 +1351,14 @@ static void printCodeCompletionResultsImpl( OS.write_escaped(buf); } - StringRef comment = Result->getBriefDocComment(); - if (IncludeComments && !comment.empty()) { - OS << "; comment=" << comment; + StringRef BriefComment = Result->getBriefDocComment(); + if (IncludeComments && !BriefComment.empty()) { + OS << "; briefComment=" << BriefComment; + } + + StringRef FullComment = Result->getFullDocComment(); + if (IncludeComments && !FullComment.empty()) { + OS << "; fullComment=" << FullComment; } if (Ctx) { @@ -1363,7 +1368,7 @@ static void printCodeCompletionResultsImpl( Result->getDiagnosticSeverityAndMessage(Scratch, *Ctx); if (DiagSeverityAndMessage.first != CodeCompletionDiagnosticSeverity::None) { - OS << "; diagnostics=" << comment; + OS << "; diagnostics=" << BriefComment; switch (DiagSeverityAndMessage.first) { case CodeCompletionDiagnosticSeverity::Error: OS << "error"; From e8036eb972ecb40c7307a2ab9677b430465d2f4a Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 21 Jul 2025 00:42:46 +0300 Subject: [PATCH 26/58] [IDE] Update code complete and documentation tests --- lib/IDE/CodeCompletionResultBuilder.cpp | 12 +++--- .../complete_with_clang_comments.swift | 8 ++-- test/IDE/complete_result_builder.swift | 42 +++++++++---------- .../CodeComplete/complete_docbrief_1.swift | 2 + .../CodeComplete/complete_docbrief_2.swift | 1 + .../CodeComplete/complete_docbrief_3.swift | 1 + .../complete_docbrief_package.swift | 1 + .../CodeComplete/complete_docbrief_spi.swift | 1 + .../complete_from_clang_module.swift | 1 + .../CodeComplete/complete_member.swift | 2 +- .../complete_member.swift.response | 1 + .../complete_moduleimportdepth.swift | 1 + .../bin/InProc/CodeCompletionSwiftInterop.cpp | 1 - tools/swift-ide-test/swift-ide-test.cpp | 4 +- 14 files changed, 43 insertions(+), 35 deletions(-) diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 76111daecb154..99904c028d6a6 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -274,12 +274,6 @@ void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) { else if (D->getSoftDeprecatedAttr()) setContextFreeNotRecommended( ContextFreeNotRecommendedReason::SoftDeprecated); - - SmallString<256> Buffer; - llvm::raw_svector_ostream OS(Buffer); - ide::getDocumentationCommentAsXML(D, OS, /*IncludeParameters=*/true); - - setFullDocComment(StringRef(Buffer).copy(Sink.getAllocator())); if (D->getClangNode()) { if (auto *ClangD = D->getClangDecl()) { @@ -292,6 +286,12 @@ void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) { } else { setBriefDocComment(AssociatedDecl->getSemanticBriefComment()); } + + SmallString<256> Buffer; + llvm::raw_svector_ostream OS(Buffer); + ide::getDocumentationCommentAsXML(D, OS); + + setFullDocComment(StringRef(Buffer).copy(Sink.getAllocator())); } void CodeCompletionResultBuilder::addCallArgument( diff --git a/test/IDE/clang-importing/complete_with_clang_comments.swift b/test/IDE/clang-importing/complete_with_clang_comments.swift index b3816c05052b1..a4262b164f919 100644 --- a/test/IDE/clang-importing/complete_with_clang_comments.swift +++ b/test/IDE/clang-importing/complete_with_clang_comments.swift @@ -8,7 +8,7 @@ import somemod2 #^TOP^# -// CHECK-TOP: name=some_func11(); comment=some_func11 is cool function. -// CHECK-TOP: name=some_func12(); comment=some_func12 is cool function. -// CHECK-TOP: name=some_func21(); comment=some_func21 is cool function. -// CHECK-TOP: name=some_func22(); comment=some_func22 is cool function. +// CHECK-TOP: name=some_func11(); briefcomment=some_func11 is cool function.; fullcomment=some_func11c:@F@some_func11func some_func11() some_func11 is cool function. +// CHECK-TOP: name=some_func12(); briefcomment=some_func12 is cool function.; fullcomment=some_func12c:@F@some_func12func some_func12() some_func12 is cool function. +// CHECK-TOP: name=some_func21(); briefcomment=some_func21 is cool function.; fullcomment=some_func21c:@F@some_func21func some_func21() some_func21 is cool function. +// CHECK-TOP: name=some_func22(); briefcomment=some_func22 is cool function.; fullcomment=some_func22c:@F@some_func22func some_func22() some_func22 is cool function. diff --git a/test/IDE/complete_result_builder.swift b/test/IDE/complete_result_builder.swift index 96bcde48cd8e1..25029c0cf7acd 100644 --- a/test/IDE/complete_result_builder.swift +++ b/test/IDE/complete_result_builder.swift @@ -102,24 +102,24 @@ struct AnyBuilder { } // IN_RESULT_BUILDER_DECL: Begin completions, 10 items -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildBlock(_ components: Any...) -> Any {|}; name=buildBlock(_ components: Any...) -> Any; comment=Required by every -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildExpression(_ expression: <#Expression#>) -> Any {|}; name=buildExpression(_ expression: <#Expression#>) -> Any; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildOptional(_ component: Any?) -> Any {|}; name=buildOptional(_ component: Any?) -> Any; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildEither(first component: Any) -> Any {|}; name=buildEither(first component: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildEither(second component: Any) -> Any {|}; name=buildEither(second component: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildArray(_ components: [Any]) -> Any {|}; name=buildArray(_ components: [Any]) -> Any; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildLimitedAvailability(_ component: Any) -> Any {|}; name=buildLimitedAvailability(_ component: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildFinalResult(_ component: Any) -> <#Result#> {|}; name=buildFinalResult(_ component: Any) -> <#Result#>; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildPartialBlock(first: Any) -> Any {|}; name=buildPartialBlock(first: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildPartialBlock(accumulated: Any, next: Any) -> Any {|}; name=buildPartialBlock(accumulated: Any, next: Any) -> Any; comment= - -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildBlock(_ components: Any...) -> Any {|}; name=static func buildBlock(_ components: Any...) -> Any; comment=Required by every -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildExpression(_ expression: <#Expression#>) -> Any {|}; name=static func buildExpression(_ expression: <#Expression#>) -> Any; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildOptional(_ component: Any?) -> Any {|}; name=static func buildOptional(_ component: Any?) -> Any; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildEither(first component: Any) -> Any {|}; name=static func buildEither(first component: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildEither(second component: Any) -> Any {|}; name=static func buildEither(second component: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildArray(_ components: [Any]) -> Any {|}; name=static func buildArray(_ components: [Any]) -> Any; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildLimitedAvailability(_ component: Any) -> Any {|}; name=static func buildLimitedAvailability(_ component: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildFinalResult(_ component: Any) -> <#Result#> {|}; name=static func buildFinalResult(_ component: Any) -> <#Result#>; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildPartialBlock(first: Any) -> Any {|}; name=static func buildPartialBlock(first: Any) -> Any; comment= -// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildPartialBlock(accumulated: Any, next: Any) -> Any {|}; name=static func buildPartialBlock(accumulated: Any, next: Any) -> Any; comment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildBlock(_ components: Any...) -> Any {|}; name=buildBlock(_ components: Any...) -> Any; briefcomment=Required by every +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildExpression(_ expression: <#Expression#>) -> Any {|}; name=buildExpression(_ expression: <#Expression#>) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildOptional(_ component: Any?) -> Any {|}; name=buildOptional(_ component: Any?) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildEither(first component: Any) -> Any {|}; name=buildEither(first component: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildEither(second component: Any) -> Any {|}; name=buildEither(second component: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildArray(_ components: [Any]) -> Any {|}; name=buildArray(_ components: [Any]) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildLimitedAvailability(_ component: Any) -> Any {|}; name=buildLimitedAvailability(_ component: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildFinalResult(_ component: Any) -> <#Result#> {|}; name=buildFinalResult(_ component: Any) -> <#Result#>; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildPartialBlock(first: Any) -> Any {|}; name=buildPartialBlock(first: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL: Pattern/CurrNominal: buildPartialBlock(accumulated: Any, next: Any) -> Any {|}; name=buildPartialBlock(accumulated: Any, next: Any) -> Any; briefcomment= + +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildBlock(_ components: Any...) -> Any {|}; name=static func buildBlock(_ components: Any...) -> Any; briefcomment=Required by every +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildExpression(_ expression: <#Expression#>) -> Any {|}; name=static func buildExpression(_ expression: <#Expression#>) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildOptional(_ component: Any?) -> Any {|}; name=static func buildOptional(_ component: Any?) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildEither(first component: Any) -> Any {|}; name=static func buildEither(first component: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildEither(second component: Any) -> Any {|}; name=static func buildEither(second component: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildArray(_ components: [Any]) -> Any {|}; name=static func buildArray(_ components: [Any]) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildLimitedAvailability(_ component: Any) -> Any {|}; name=static func buildLimitedAvailability(_ component: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildFinalResult(_ component: Any) -> <#Result#> {|}; name=static func buildFinalResult(_ component: Any) -> <#Result#>; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildPartialBlock(first: Any) -> Any {|}; name=static func buildPartialBlock(first: Any) -> Any; briefcomment= +// IN_RESULT_BUILDER_DECL_PREFIX: Pattern/CurrNominal: static func buildPartialBlock(accumulated: Any, next: Any) -> Any {|}; name=static func buildPartialBlock(accumulated: Any, next: Any) -> Any; briefcomment= diff --git a/test/SourceKit/CodeComplete/complete_docbrief_1.swift b/test/SourceKit/CodeComplete/complete_docbrief_1.swift index 3a37e12a9f3d6..03dd351e12ad7 100644 --- a/test/SourceKit/CodeComplete/complete_docbrief_1.swift +++ b/test/SourceKit/CodeComplete/complete_docbrief_1.swift @@ -30,6 +30,7 @@ func test() { // CHECK-NEXT: { // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, // CHECK-NEXT: key.name: "bar()", +// CHECK-NEXT: key.doc.full_as_xml: "bar()s:12DocBriefTest1PP3baryyFfunc bar()This is a doc comment of P.barMay have default information.This documentation comment was inherited from P.", // CHECK-NEXT: key.description: "bar()", // CHECK-NEXT: key.typename: "Void", // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.bar", @@ -43,6 +44,7 @@ func test() { // CHECK-NEXT: { // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, // CHECK-NEXT: key.name: "foo()", +// CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", // CHECK-NEXT: key.description: "foo()", // CHECK-NEXT: key.typename: "Void", // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", diff --git a/test/SourceKit/CodeComplete/complete_docbrief_2.swift b/test/SourceKit/CodeComplete/complete_docbrief_2.swift index 2551e84fa9c12..a9cf6a6b8ff08 100644 --- a/test/SourceKit/CodeComplete/complete_docbrief_2.swift +++ b/test/SourceKit/CodeComplete/complete_docbrief_2.swift @@ -32,6 +32,7 @@ func test() { // CHECK-NEXT: { // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", // CHECK-NEXT: key.description: "foo()", // CHECK-NEXT: key.typename: "Void", // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", diff --git a/test/SourceKit/CodeComplete/complete_docbrief_3.swift b/test/SourceKit/CodeComplete/complete_docbrief_3.swift index 90d38e18c7ff1..bd41a468e9b10 100644 --- a/test/SourceKit/CodeComplete/complete_docbrief_3.swift +++ b/test/SourceKit/CodeComplete/complete_docbrief_3.swift @@ -33,6 +33,7 @@ func test() { // CHECK-NEXT: { // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", // CHECK-NEXT: key.description: "foo()", // CHECK-NEXT: key.typename: "Void", // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", diff --git a/test/SourceKit/CodeComplete/complete_docbrief_package.swift b/test/SourceKit/CodeComplete/complete_docbrief_package.swift index 4a6dda2a2f5c8..d69351be15b1f 100644 --- a/test/SourceKit/CodeComplete/complete_docbrief_package.swift +++ b/test/SourceKit/CodeComplete/complete_docbrief_package.swift @@ -35,6 +35,7 @@ func test() { // CHECK-NEXT: { // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", // CHECK-NEXT: key.description: "foo()", // CHECK-NEXT: key.typename: "Void", // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", diff --git a/test/SourceKit/CodeComplete/complete_docbrief_spi.swift b/test/SourceKit/CodeComplete/complete_docbrief_spi.swift index ee2ed69123a12..fbbb5755389b9 100644 --- a/test/SourceKit/CodeComplete/complete_docbrief_spi.swift +++ b/test/SourceKit/CodeComplete/complete_docbrief_spi.swift @@ -36,6 +36,7 @@ func test() { // CHECK-NEXT: { // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", // CHECK-NEXT: key.description: "foo()", // CHECK-NEXT: key.typename: "Void", // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", diff --git a/test/SourceKit/CodeComplete/complete_from_clang_module.swift b/test/SourceKit/CodeComplete/complete_from_clang_module.swift index e297de9d50bdb..bb66d6b0742bf 100644 --- a/test/SourceKit/CodeComplete/complete_from_clang_module.swift +++ b/test/SourceKit/CodeComplete/complete_from_clang_module.swift @@ -4,6 +4,7 @@ import Foo // RUN: %sourcekitd-test -req=complete -pos=2:1 %s -- -F %S/../Inputs/libIDE-mock-sdk %s | %FileCheck %s // CHECK-LABEL: key.name: "fooIntVar", +// CHECK-NEXT: key.doc.full_as_xml: "fooIntVarc:@fooIntVarvar fooIntVar: Int32 Aaa. fooIntVar. Bbb.", // CHECK-NEXT: key.description: "fooIntVar", // CHECK-NEXT: key.typename: "Int32", // CHECK-NEXT: key.doc.brief: "Aaa. fooIntVar. Bbb.", diff --git a/test/SourceKit/CodeComplete/complete_member.swift b/test/SourceKit/CodeComplete/complete_member.swift index e266560fbd064..0222d564edadf 100644 --- a/test/SourceKit/CodeComplete/complete_member.swift +++ b/test/SourceKit/CodeComplete/complete_member.swift @@ -39,7 +39,7 @@ func testOverrideUSR() { Derived(). } -// RUN: %sourcekitd-test -req=complete -pos=15:5 %s -- %s > %t.response +// RUN: %sourcekitd-test -req=complete -pos=15:5 %s -- %s | %sed_clean > %t.response // RUN: %diff -u %s.response %t.response // // RUN: %sourcekitd-test -req=complete -pos=19:5 %s -- %s | %FileCheck %s -check-prefix=CHECK-OPTIONAL diff --git a/test/SourceKit/CodeComplete/complete_member.swift.response b/test/SourceKit/CodeComplete/complete_member.swift.response index 489995d707b70..3471835c5b27c 100644 --- a/test/SourceKit/CodeComplete/complete_member.swift.response +++ b/test/SourceKit/CodeComplete/complete_member.swift.response @@ -27,6 +27,7 @@ { key.kind: source.lang.swift.decl.var.instance, key.name: "fooInstanceVar", + key.doc.full_as_xml: "fooInstanceVars:15complete_member11FooProtocolP14fooInstanceVarSivpvar fooInstanceVar: Int { get }fooInstanceVar Aaa. Bbb.Ccc.", key.description: "fooInstanceVar", key.typename: "Int", key.doc.brief: "fooInstanceVar Aaa. Bbb.", diff --git a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift index cc29a4563d2f8..95b05efbea202 100644 --- a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift +++ b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift @@ -11,6 +11,7 @@ func test() { // Swift == 1 // CHECK-LABEL: key.name: "abs(:)", +// CHECK-NEXT: key.doc.full_as_xml: "abs(_:)s:s3absyxxSLRzs13SignedNumericRzlF@inlinable func abs<T>(_ x: T) -> T where T : Comparable, T : SignedNumericReturns the absolute value of the given number.xinA signed number.The absolute value of x.The absolute value of x must be representable in the same type. In particular, the absolute value of a signed, fixed-width integer type’s minimum cannot be represented.", // CHECK-NEXT: key.description: "abs(x: Comparable & SignedNumeric)", // CHECK-NEXT: key.typename: "Comparable & SignedNumeric", // CHECK-NEXT: key.doc.brief: "Returns the absolute value of the given number.", diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp index 9645ec7abad11..4b209a82d3d78 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -663,7 +663,6 @@ void swiftide_completion_item_get_doc_brief( handler(item.getBriefDocComment().data()); } -// TODO(a7medev): Is this function required? void swiftide_completion_item_get_doc_full( swiftide_completion_response_t _response, swiftide_completion_item_t _item, void (^handler)(const char *)) { diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 583a5c8810d66..017e8b8f14299 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -1353,12 +1353,12 @@ static void printCodeCompletionResultsImpl( StringRef BriefComment = Result->getBriefDocComment(); if (IncludeComments && !BriefComment.empty()) { - OS << "; briefComment=" << BriefComment; + OS << "; briefcomment=" << BriefComment; } StringRef FullComment = Result->getFullDocComment(); if (IncludeComments && !FullComment.empty()) { - OS << "; fullComment=" << FullComment; + OS << "; fullcomment=" << FullComment; } if (Ctx) { From c1d6f7e84051bd5fff20b72a89a6f85750243ef3 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Thu, 26 Jun 2025 11:56:36 +0300 Subject: [PATCH 27/58] [IDE] Rename complete_docbrief to complete_doc --- .../{complete_docbrief_1.swift => complete_doc_1.swift} | 0 .../{complete_docbrief_2.swift => complete_doc_2.swift} | 0 .../{complete_docbrief_3.swift => complete_doc_3.swift} | 0 ...complete_docbrief_package.swift => complete_doc_package.swift} | 0 .../{complete_docbrief_spi.swift => complete_doc_spi.swift} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename test/SourceKit/CodeComplete/{complete_docbrief_1.swift => complete_doc_1.swift} (100%) rename test/SourceKit/CodeComplete/{complete_docbrief_2.swift => complete_doc_2.swift} (100%) rename test/SourceKit/CodeComplete/{complete_docbrief_3.swift => complete_doc_3.swift} (100%) rename test/SourceKit/CodeComplete/{complete_docbrief_package.swift => complete_doc_package.swift} (100%) rename test/SourceKit/CodeComplete/{complete_docbrief_spi.swift => complete_doc_spi.swift} (100%) diff --git a/test/SourceKit/CodeComplete/complete_docbrief_1.swift b/test/SourceKit/CodeComplete/complete_doc_1.swift similarity index 100% rename from test/SourceKit/CodeComplete/complete_docbrief_1.swift rename to test/SourceKit/CodeComplete/complete_doc_1.swift diff --git a/test/SourceKit/CodeComplete/complete_docbrief_2.swift b/test/SourceKit/CodeComplete/complete_doc_2.swift similarity index 100% rename from test/SourceKit/CodeComplete/complete_docbrief_2.swift rename to test/SourceKit/CodeComplete/complete_doc_2.swift diff --git a/test/SourceKit/CodeComplete/complete_docbrief_3.swift b/test/SourceKit/CodeComplete/complete_doc_3.swift similarity index 100% rename from test/SourceKit/CodeComplete/complete_docbrief_3.swift rename to test/SourceKit/CodeComplete/complete_doc_3.swift diff --git a/test/SourceKit/CodeComplete/complete_docbrief_package.swift b/test/SourceKit/CodeComplete/complete_doc_package.swift similarity index 100% rename from test/SourceKit/CodeComplete/complete_docbrief_package.swift rename to test/SourceKit/CodeComplete/complete_doc_package.swift diff --git a/test/SourceKit/CodeComplete/complete_docbrief_spi.swift b/test/SourceKit/CodeComplete/complete_doc_spi.swift similarity index 100% rename from test/SourceKit/CodeComplete/complete_docbrief_spi.swift rename to test/SourceKit/CodeComplete/complete_doc_spi.swift From 2f6b2e526b46d6d81daad6ec1e22126911c9eba2 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 4 Jul 2025 15:03:12 +0300 Subject: [PATCH 28/58] [IDE] Export swiftide_completion_item_get_doc_full --- .../tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports | 1 + .../tools/sourcekitd/bin/InProc/sourcekitdInProc.exports | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports index 9c07d75032d75..ddad2c46cafdf 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports @@ -149,6 +149,7 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief +swiftide_completion_item_get_doc_full swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports index d4f811ed11db4..928e08b49afd0 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports @@ -149,6 +149,7 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief +swiftide_completion_item_get_doc_full swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label From 8ba8fa4fee8367c4b4b50cfb7b4f94176c21e05f Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Tue, 8 Jul 2025 23:13:42 +0300 Subject: [PATCH 29/58] [IDE] Add AssociatedDecl to CodeCompletionResult --- include/swift/IDE/CodeCompletionResult.h | 30 +++++++++++++++++++++--- lib/IDE/CodeCompletionResult.cpp | 28 ++++++++++++++++++---- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index c34329894ac05..be1dc21c146b7 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -601,6 +601,8 @@ class ContextFreeCodeCompletionResult { /// the completion's usage context. class CodeCompletionResult { const ContextFreeCodeCompletionResult &ContextFree; + const Decl *AssociatedDecl = nullptr; + bool HasValidAssociatedDecl : 1; SemanticContextKind SemanticContext : 3; static_assert(int(SemanticContextKind::MAX_VALUE) < 1 << 3, ""); @@ -629,13 +631,26 @@ class CodeCompletionResult { /// done by allocating the two in the same sink or adopting the context free /// sink in the sink that allocates this result. CodeCompletionResult(const ContextFreeCodeCompletionResult &ContextFree, + const Decl *AssociatedDecl, bool HasValidAssociatedDecl, SemanticContextKind SemanticContext, CodeCompletionFlair Flair, uint8_t NumBytesToErase, CodeCompletionResultTypeRelation TypeDistance, ContextualNotRecommendedReason NotRecommended) - : ContextFree(ContextFree), SemanticContext(SemanticContext), - Flair(Flair.toRaw()), NotRecommended(NotRecommended), - NumBytesToErase(NumBytesToErase), TypeDistance(TypeDistance) {} + : ContextFree(ContextFree), AssociatedDecl(AssociatedDecl), + HasValidAssociatedDecl(HasValidAssociatedDecl), + SemanticContext(SemanticContext), Flair(Flair.toRaw()), + NotRecommended(NotRecommended), NumBytesToErase(NumBytesToErase), + TypeDistance(TypeDistance) {} + + CodeCompletionResult(const ContextFreeCodeCompletionResult &ContextFree, + SemanticContextKind SemanticContext, + CodeCompletionFlair Flair, uint8_t NumBytesToErase, + CodeCompletionResultTypeRelation TypeDistance, + ContextualNotRecommendedReason NotRecommended) + : ContextFree(ContextFree), HasValidAssociatedDecl(false), + SemanticContext(SemanticContext), Flair(Flair.toRaw()), + NotRecommended(NotRecommended), NumBytesToErase(NumBytesToErase), + TypeDistance(TypeDistance) {} const ContextFreeCodeCompletionResult &getContextFreeResult() const { return ContextFree; @@ -722,6 +737,15 @@ class CodeCompletionResult { return NotRecommendedReason::VariableUsedInOwnDefinition; } } + + bool getHasValidAssociatedDecl() const { return HasValidAssociatedDecl; } + + const Decl *getAssociatedDecl() const { + assert(HasValidAssociatedDecl && "AssociatedDecl hasn't been loaded yet"); + return AssociatedDecl; + } + + const Decl *findAssociatedDecl(DeclContext *DC); SemanticContextKind getSemanticContext() const { return SemanticContext; } diff --git a/lib/IDE/CodeCompletionResult.cpp b/lib/IDE/CodeCompletionResult.cpp index 20cb8fb7b725c..f5be5d0216dad 100644 --- a/lib/IDE/CodeCompletionResult.cpp +++ b/lib/IDE/CodeCompletionResult.cpp @@ -12,6 +12,7 @@ #include "swift/IDE/CodeCompletionResult.h" #include "CodeCompletionDiagnostics.h" +#include "swift/AST/ASTDemangler.h" #include "swift/AST/Decl.h" #include "swift/AST/Module.h" #include "swift/Basic/Assertions.h" @@ -441,12 +442,30 @@ ContextFreeCodeCompletionResult::calculateContextualTypeRelation( // MARK: - CodeCompletionResult +const Decl *CodeCompletionResult::findAssociatedDecl(DeclContext *DC) { + if (HasValidAssociatedDecl) + return AssociatedDecl; + + HasValidAssociatedDecl = true; + + auto USRs = getAssociatedUSRs(); + if (USRs.empty()) + return nullptr; + + StringRef PrimaryUSR = USRs.front(); + auto &Ctx = DC->getASTContext(); + AssociatedDecl = swift::Demangle::getDeclForUSR(Ctx, PrimaryUSR); + + return AssociatedDecl; +} + CodeCompletionResult * CodeCompletionResult::withFlair(CodeCompletionFlair NewFlair, CodeCompletionResultSink &Sink) const { return new (*Sink.Allocator) - CodeCompletionResult(ContextFree, SemanticContext, NewFlair, - NumBytesToErase, TypeDistance, NotRecommended); + CodeCompletionResult(ContextFree, AssociatedDecl, HasValidAssociatedDecl, + SemanticContext, NewFlair, NumBytesToErase, + TypeDistance, NotRecommended); } CodeCompletionResult * @@ -455,8 +474,9 @@ CodeCompletionResult::withContextFreeResultSemanticContextAndFlair( SemanticContextKind NewSemanticContext, CodeCompletionFlair NewFlair, CodeCompletionResultSink &Sink) const { return new (*Sink.Allocator) - CodeCompletionResult(NewContextFree, NewSemanticContext, NewFlair, - NumBytesToErase, TypeDistance, NotRecommended); + CodeCompletionResult(NewContextFree, AssociatedDecl, HasValidAssociatedDecl, + NewSemanticContext, NewFlair, NumBytesToErase, + TypeDistance, NotRecommended); } std::pair From 36a027827c565904c72d81d80d0fbfd478406084 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Tue, 8 Jul 2025 23:20:01 +0300 Subject: [PATCH 30/58] [IDE] Pass AssociatedDecl to CodeCompletionResult on creation --- lib/IDE/CodeCompletionResultBuilder.cpp | 10 ++++++---- .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 7 ++++--- tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp | 3 ++- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 99904c028d6a6..9db45cb312995 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -218,8 +218,9 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { // If the sink only intends to store the context free results in the cache, // we don't need to compute any contextual properties. return new (Allocator) CodeCompletionResult( - *ContextFreeResult, SemanticContextKind::None, CodeCompletionFlair(), - /*NumBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated, + *ContextFreeResult, AssociatedDecl, /*HasValidAssociatedDecl=*/true, + SemanticContextKind::None, CodeCompletionFlair(), /*NumBytesToErase=*/0, + CodeCompletionResultTypeRelation::Unrelated, ContextualNotRecommendedReason::None); } else { assert( @@ -238,8 +239,9 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { ContextualNotRecReason, CanCurrDeclContextHandleAsync); return new (Allocator) CodeCompletionResult( - *ContextFreeResult, SemanticContext, Flair, NumBytesToErase, - typeRelation, notRecommendedReason); + *ContextFreeResult, AssociatedDecl, /*HasValidAssociatedDecl=*/true, + SemanticContext, Flair, NumBytesToErase, typeRelation, + notRecommendedReason); } } diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index bd6c0899db81d..a37540f2ee75e 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -140,9 +140,10 @@ bool SourceKit::CodeCompletion::addCustomCompletions( ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); auto *swiftResult = new (sink.allocator) CodeCompletion::SwiftResult( - *contextFreeResult, SemanticContextKind::Local, - CodeCompletionFlairBit::ExpressionSpecific, - /*NumBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated, + *contextFreeResult, /*AssociatedDecl=*/nullptr, + /*HasValidAssociatedDecl=*/true, SemanticContextKind::Local, + CodeCompletionFlairBit::ExpressionSpecific, /*NumBytesToErase=*/0, + CodeCompletionResultTypeRelation::Unrelated, ContextualNotRecommendedReason::None); CompletionBuilder builder(sink, *swiftResult); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index a1b168c48df55..6cd4cc395c652 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -919,7 +919,8 @@ static void transformAndForwardResults( CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); auto *paren = new (innerSink.allocator) CodeCompletion::SwiftResult( - *contextFreeResult, SemanticContextKind::CurrentNominal, + *contextFreeResult, /*AssociatedDecl=*/nullptr, + /*HasValidAssociatedDecl=*/true, SemanticContextKind::CurrentNominal, CodeCompletionFlairBit::ExpressionSpecific, exactMatch ? exactMatch->getNumBytesToErase() : 0, CodeCompletionResultTypeRelation::Unrelated, From 57d34bab027fca62ac25bacc9ed71a29c0c850f9 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 11 Jul 2025 12:44:04 +0300 Subject: [PATCH 31/58] [IDE] Fetch declaration full documentation on-demand --- include/swift/IDE/CodeCompletionResult.h | 37 ++++++++++--------- lib/IDE/CodeCompletionCache.cpp | 5 +-- lib/IDE/CodeCompletionContext.cpp | 3 ++ lib/IDE/CodeCompletionResult.cpp | 14 +++---- lib/IDE/CodeCompletionResultBuilder.cpp | 13 +------ lib/IDE/CodeCompletionResultBuilder.h | 5 --- lib/IDE/CompletionOverrideLookup.cpp | 1 - .../SourceKit/lib/SwiftLang/CodeCompletion.h | 4 +- .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 4 +- .../lib/SwiftLang/CodeCompletionOrganizer.h | 1 + .../lib/SwiftLang/SwiftCompletion.cpp | 34 ++++++++++++----- .../bin/InProc/CodeCompletionSwiftInterop.cpp | 13 +++++-- .../bin/InProc/CodeCompletionSwiftInterop.h | 6 +-- .../InProc/sourcekitdInProc-darwin.exports | 2 +- .../bin/InProc/sourcekitdInProc.exports | 2 +- tools/swift-ide-test/swift-ide-test.cpp | 17 +++++---- 16 files changed, 85 insertions(+), 76 deletions(-) diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index be1dc21c146b7..ae74dbb11e991 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -16,6 +16,7 @@ #include "swift/Basic/StringExtras.h" #include "swift/IDE/CodeCompletionResultType.h" #include "swift/IDE/CodeCompletionString.h" +#include "swift/IDE/CommentConversion.h" namespace swift { namespace ide { @@ -378,7 +379,6 @@ class ContextFreeCodeCompletionResult { CodeCompletionString *CompletionString; NullTerminatedStringRef ModuleName; NullTerminatedStringRef BriefDocComment; - NullTerminatedStringRef FullDocComment; ArrayRef AssociatedUSRs; CodeCompletionResultType ResultType; @@ -411,7 +411,6 @@ class ContextFreeCodeCompletionResult { bool HasAsyncAlternative, CodeCompletionString *CompletionString, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, - NullTerminatedStringRef FullDocComment, ArrayRef AssociatedUSRs, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, @@ -423,9 +422,9 @@ class ContextFreeCodeCompletionResult { MacroRoles(MacroRoles), IsSystem(IsSystem), HasAsyncAlternative(HasAsyncAlternative), CompletionString(CompletionString), ModuleName(ModuleName), - BriefDocComment(BriefDocComment), FullDocComment(FullDocComment), - AssociatedUSRs(AssociatedUSRs), ResultType(ResultType), - NotRecommended(NotRecommended), DiagnosticSeverity(DiagnosticSeverity), + BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs), + ResultType(ResultType), NotRecommended(NotRecommended), + DiagnosticSeverity(DiagnosticSeverity), DiagnosticMessage(DiagnosticMessage), FilterName(FilterName), NameForDiagnostics(NameForDiagnostics) { this->AssociatedKind.Opaque = AssociatedKind; @@ -455,7 +454,6 @@ class ContextFreeCodeCompletionResult { CodeCompletionString *CompletionString, CodeCompletionOperatorKind KnownOperatorKin, NullTerminatedStringRef BriefDocComment, - NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, @@ -463,15 +461,14 @@ class ContextFreeCodeCompletionResult { /// Constructs a \c Keyword result. /// - /// \note The caller must ensure that the \p CompletionString, \p BriefDocComment, - /// and \p FullDocComment outlive this result, typically by storing them in the same - /// \c CodeCompletionResultSink as the result itself. + /// \note The caller must ensure that the \p CompletionString and + /// \p BriefDocComment outlive this result, typically by storing them in + /// the same \c CodeCompletionResultSink as the result itself. static ContextFreeCodeCompletionResult * createKeywordResult(CodeCompletionResultSink &Sink, CodeCompletionKeywordKind Kind, CodeCompletionString *CompletionString, NullTerminatedStringRef BriefDocComment, - NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType); /// Constructs a \c Literal result. @@ -496,7 +493,6 @@ class ContextFreeCodeCompletionResult { const Decl *AssociatedDecl, bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, - NullTerminatedStringRef FullDocComment, ArrayRef AssociatedUSRs, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, @@ -541,8 +537,6 @@ class ContextFreeCodeCompletionResult { NullTerminatedStringRef getBriefDocComment() const { return BriefDocComment; } - NullTerminatedStringRef getFullDocComment() const { return FullDocComment; } - ArrayRef getAssociatedUSRs() const { return AssociatedUSRs; } @@ -617,6 +611,8 @@ class CodeCompletionResult { /// should be erased first if this completion string is inserted in the /// editor buffer. unsigned NumBytesToErase : 7; + +// std::optional FullDocComment; public: static const unsigned MaxNumBytesToErase = 127; @@ -738,14 +734,14 @@ class CodeCompletionResult { } } - bool getHasValidAssociatedDecl() const { return HasValidAssociatedDecl; } + bool hasValidAssociatedDecl() const { return HasValidAssociatedDecl; } const Decl *getAssociatedDecl() const { assert(HasValidAssociatedDecl && "AssociatedDecl hasn't been loaded yet"); return AssociatedDecl; } - const Decl *findAssociatedDecl(DeclContext *DC); + const Decl *findAssociatedDecl(const DeclContext *DC); SemanticContextKind getSemanticContext() const { return SemanticContext; } @@ -772,8 +768,15 @@ class CodeCompletionResult { return getContextFreeResult().getBriefDocComment(); } - NullTerminatedStringRef getFullDocComment() const { - return getContextFreeResult().getFullDocComment(); + /// Prints the full documentation comment as XML to the provided \c OS stream. + /// + /// \returns true if the result has a full documentation comment, false otherwise. + bool printFullDocComment(raw_ostream &OS) const { + assert(HasValidAssociatedDecl && "Associated declaration hasn't been fetched"); + if (AssociatedDecl) + return ide::getDocumentationCommentAsXML(AssociatedDecl, OS); + + return false; } ArrayRef getAssociatedUSRs() const { diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp index 7b874025cc833..0628372737556 100644 --- a/lib/IDE/CodeCompletionCache.cpp +++ b/lib/IDE/CodeCompletionCache.cpp @@ -241,7 +241,6 @@ static bool readCachedModule(llvm::MemoryBuffer *in, auto chunkIndex = read32le(cursor); auto moduleIndex = read32le(cursor); auto briefDocIndex = read32le(cursor); - auto fullDocIndex = read32le(cursor); auto diagMessageIndex = read32le(cursor); auto filterNameIndex = read32le(cursor); auto nameForDiagnosticsIndex = read32le(cursor); @@ -262,7 +261,6 @@ static bool readCachedModule(llvm::MemoryBuffer *in, CodeCompletionString *string = getCompletionString(chunkIndex); auto moduleName = getString(moduleIndex); auto briefDocComment = getString(briefDocIndex); - auto fullDocComment = getString(fullDocIndex); auto diagMessage = getString(diagMessageIndex); auto filterName = getString(filterNameIndex); auto nameForDiagnostics = getString(nameForDiagnosticsIndex); @@ -271,7 +269,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in, new (*V.Allocator) ContextFreeCodeCompletionResult( kind, associatedKind, opKind, roles, isSystem, hasAsyncAlternative, string, moduleName, briefDocComment, - fullDocComment, llvm::ArrayRef(assocUSRs).copy(*V.Allocator), + llvm::ArrayRef(assocUSRs).copy(*V.Allocator), CodeCompletionResultType(resultTypes), notRecommended, diagSeverity, diagMessage, filterName, nameForDiagnostics); @@ -434,7 +432,6 @@ static void writeCachedModule(llvm::raw_ostream &out, static_cast(addCompletionString(R->getCompletionString()))); LE.write(addString(R->getModuleName())); // index into strings LE.write(addString(R->getBriefDocComment())); // index into strings - LE.write(addString(R->getFullDocComment())); // index into strings LE.write(addString(R->getDiagnosticMessage())); // index into strings LE.write(addString(R->getFilterName())); // index into strings LE.write(addString(R->getNameForDiagnostics())); // index into strings diff --git a/lib/IDE/CodeCompletionContext.cpp b/lib/IDE/CodeCompletionContext.cpp index 2da14b033c445..35c05aafa5f6f 100644 --- a/lib/IDE/CodeCompletionContext.cpp +++ b/lib/IDE/CodeCompletionContext.cpp @@ -114,6 +114,9 @@ static MutableArrayRef copyCodeCompletionResults( *contextFreeResult, SemanticContextKind::OtherModule, CodeCompletionFlair(), /*numBytesToErase=*/0, typeRelation, notRecommendedReason); + + contextualResult->findAssociatedDecl(DC); + targetSink.Results.push_back(contextualResult); } diff --git a/lib/IDE/CodeCompletionResult.cpp b/lib/IDE/CodeCompletionResult.cpp index f5be5d0216dad..e5b367d3021cf 100644 --- a/lib/IDE/CodeCompletionResult.cpp +++ b/lib/IDE/CodeCompletionResult.cpp @@ -138,7 +138,6 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( CodeCompletionString *CompletionString, CodeCompletionOperatorKind KnownOperatorKind, NullTerminatedStringRef BriefDocComment, - NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, @@ -156,7 +155,7 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( Kind, /*AssociatedKind=*/0, KnownOperatorKind, /*MacroRoles=*/{}, /*IsSystem=*/false, /*HasAsyncAlternative=*/false, CompletionString, - /*ModuleName=*/"", BriefDocComment, FullDocComment, + /*ModuleName=*/"", BriefDocComment, /*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), @@ -168,7 +167,6 @@ ContextFreeCodeCompletionResult::createKeywordResult( CodeCompletionResultSink &Sink, CodeCompletionKeywordKind Kind, CodeCompletionString *CompletionString, NullTerminatedStringRef BriefDocComment, - NullTerminatedStringRef FullDocComment, CodeCompletionResultType ResultType) { if (Sink.shouldProduceContextFreeResults()) { ResultType = ResultType.usrBasedType(Sink.getUSRTypeArena()); @@ -177,7 +175,7 @@ ContextFreeCodeCompletionResult::createKeywordResult( CodeCompletionResultKind::Keyword, static_cast(Kind), CodeCompletionOperatorKind::None, /*MacroRoles=*/{}, /*IsSystem=*/false, /*HasAsyncAlternative=*/false, CompletionString, - /*ModuleName=*/"", BriefDocComment, FullDocComment, + /*ModuleName=*/"", BriefDocComment, /*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"", getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), @@ -199,7 +197,6 @@ ContextFreeCodeCompletionResult::createLiteralResult( CompletionString, /*ModuleName=*/"", /*BriefDocComment=*/"", - /*FullDocComment=*/"", /*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"", getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), @@ -226,7 +223,6 @@ ContextFreeCodeCompletionResult::createDeclResult( CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString, const Decl *AssociatedDecl, bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, - NullTerminatedStringRef FullDocComment, ArrayRef AssociatedUSRs, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, @@ -240,8 +236,8 @@ ContextFreeCodeCompletionResult::createDeclResult( CodeCompletionResultKind::Declaration, static_cast(getCodeCompletionDeclKind(AssociatedDecl)), CodeCompletionOperatorKind::None, getCompletionMacroRoles(AssociatedDecl), - getDeclIsSystem(AssociatedDecl), HasAsyncAlternative, CompletionString, - ModuleName, BriefDocComment, FullDocComment, AssociatedUSRs, ResultType, + getDeclIsSystem(AssociatedDecl), HasAsyncAlternative, + CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), /*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink)); @@ -442,7 +438,7 @@ ContextFreeCodeCompletionResult::calculateContextualTypeRelation( // MARK: - CodeCompletionResult -const Decl *CodeCompletionResult::findAssociatedDecl(DeclContext *DC) { +const Decl *CodeCompletionResult::findAssociatedDecl(const DeclContext *DC) { if (HasValidAssociatedDecl) return AssociatedDecl; diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 9db45cb312995..65255072d400a 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -184,7 +184,6 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { ContextFreeResult = ContextFreeCodeCompletionResult::createDeclResult( Sink, CCS, AssociatedDecl, HasAsyncAlternative, ModuleName, NullTerminatedStringRef(BriefDocComment, Allocator), - NullTerminatedStringRef(FullDocComment, Allocator), copyAssociatedUSRs(Allocator, AssociatedDecl), ResultType, ContextFreeNotRecReason, ContextFreeDiagnosticSeverity, ContextFreeDiagnosticMessage); @@ -194,16 +193,14 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { case CodeCompletionResultKind::Keyword: ContextFreeResult = ContextFreeCodeCompletionResult::createKeywordResult( Sink, KeywordKind, CCS, - NullTerminatedStringRef(BriefDocComment, Allocator), - NullTerminatedStringRef(FullDocComment, Allocator), ResultType); + NullTerminatedStringRef(BriefDocComment, Allocator), ResultType); break; case CodeCompletionResultKind::BuiltinOperator: case CodeCompletionResultKind::Pattern: ContextFreeResult = ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( Sink, Kind, CCS, CodeCompletionOperatorKind::None, - NullTerminatedStringRef(BriefDocComment, Allocator), - NullTerminatedStringRef(FullDocComment, Allocator), ResultType, + NullTerminatedStringRef(BriefDocComment, Allocator), ResultType, ContextFreeNotRecReason, ContextFreeDiagnosticSeverity, ContextFreeDiagnosticMessage); break; @@ -288,12 +285,6 @@ void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) { } else { setBriefDocComment(AssociatedDecl->getSemanticBriefComment()); } - - SmallString<256> Buffer; - llvm::raw_svector_ostream OS(Buffer); - ide::getDocumentationCommentAsXML(D, OS); - - setFullDocComment(StringRef(Buffer).copy(Sink.getAllocator())); } void CodeCompletionResultBuilder::addCallArgument( diff --git a/lib/IDE/CodeCompletionResultBuilder.h b/lib/IDE/CodeCompletionResultBuilder.h index 6739b2e8144d0..43138edee57b9 100644 --- a/lib/IDE/CodeCompletionResultBuilder.h +++ b/lib/IDE/CodeCompletionResultBuilder.h @@ -57,7 +57,6 @@ class CodeCompletionResultBuilder { ContextualNotRecommendedReason ContextualNotRecReason = ContextualNotRecommendedReason::None; StringRef BriefDocComment; - StringRef FullDocComment; /// The result type that this completion item produces. CodeCompletionResultType ResultType = CodeCompletionResultType::unknown(); @@ -492,10 +491,6 @@ class CodeCompletionResultBuilder { void setBriefDocComment(StringRef comment) { BriefDocComment = comment; } - - void setFullDocComment(StringRef comment) { - FullDocComment = comment; - } }; } // namespace ide diff --git a/lib/IDE/CompletionOverrideLookup.cpp b/lib/IDE/CompletionOverrideLookup.cpp index 91d2d71fd07f0..09778c67cc63e 100644 --- a/lib/IDE/CompletionOverrideLookup.cpp +++ b/lib/IDE/CompletionOverrideLookup.cpp @@ -462,7 +462,6 @@ void CompletionOverrideLookup::addResultBuilderBuildCompletion( Builder.addTextChunk(declStringWithoutFunc); Builder.addBraceStmtWithCursor(); Builder.setBriefDocComment(getResultBuilderDocComment(function)); - Builder.setFullDocComment(getResultBuilderDocComment(function)); } void CompletionOverrideLookup::addResultBuilderBuildCompletions( diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h index f926b042628d5..26aeea5ed4f0b 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h @@ -166,8 +166,8 @@ class Completion { return getSwiftResult().getBriefDocComment(); } - StringRef getFullDocComment() const { - return getSwiftResult().getFullDocComment(); + bool printFullDocComment(llvm::raw_ostream &OS) const { + return getSwiftResult().printFullDocComment(OS); } ArrayRef getAssociatedUSRs() const { diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index a37540f2ee75e..69e0d34b90768 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -135,8 +135,7 @@ bool SourceKit::CodeCompletion::addCustomCompletions( ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( sink.swiftSink, CodeCompletionResultKind::Pattern, completionString, CodeCompletionOperatorKind::None, - /*BriefDocComment=*/"", /*FullDocComment=*/"", - CodeCompletionResultType::unknown(), + /*BriefDocComment=*/"", CodeCompletionResultType::unknown(), ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); auto *swiftResult = new (sink.allocator) CodeCompletion::SwiftResult( @@ -1162,7 +1161,6 @@ Completion *CompletionBuilder::finish() { contextFreeBase.hasAsyncAlternative(), newCompletionString, contextFreeBase.getModuleName(), contextFreeBase.getBriefDocComment(), - contextFreeBase.getFullDocComment(), contextFreeBase.getAssociatedUSRs(), contextFreeBase.getResultType(), contextFreeBase.getNotRecommendedReason(), diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h index c83d60e4e662f..5357c49337b4e 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h @@ -47,6 +47,7 @@ struct Options { bool includeObjectLiterals = true; bool addCallWithNoDefaultArgs = true; bool verifyUSRToDecl = false; + bool includeFullDocumentation = false; unsigned minFuzzyLength = 2; unsigned showTopNonLiteralResults = 3; diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index 6cd4cc395c652..1077f99db6654 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -45,7 +45,8 @@ namespace { struct SwiftToSourceKitCompletionAdapter { static bool handleResult(SourceKit::CodeCompletionConsumer &consumer, CodeCompletionResult *result, - bool annotatedDescription) { + bool annotatedDescription, + bool includeFullDocumentation) { llvm::SmallString<64> description; { llvm::raw_svector_ostream OSS(description); @@ -60,13 +61,14 @@ struct SwiftToSourceKitCompletionAdapter { Completion extended(*result, description); return handleResult(consumer, &extended, /*leadingPunctuation=*/false, - /*legacyLiteralToKeyword=*/true, annotatedDescription); + /*legacyLiteralToKeyword=*/true, annotatedDescription, + includeFullDocumentation); } static bool handleResult(SourceKit::CodeCompletionConsumer &consumer, Completion *result, bool leadingPunctuation, bool legacyLiteralToKeyword, - bool annotatedDescription); + bool annotatedDescription, bool includeFullDocumentation); static void getResultAssociatedUSRs(ArrayRef AssocUSRs, @@ -168,8 +170,8 @@ deliverCodeCompleteResults(SourceKit::CodeCompletionConsumer &SKConsumer, continue; } } - if (!SwiftToSourceKitCompletionAdapter::handleResult( - SKConsumer, Result, CCOpts.annotatedDescription)) + if (!SwiftToSourceKitCompletionAdapter::handleResult(SKConsumer, Result, + CCOpts.annotatedDescription, CCOpts.includeFullDocumentation)) break; } @@ -390,7 +392,7 @@ static UIdent KeywordFuncUID("source.lang.swift.keyword.func"); bool SwiftToSourceKitCompletionAdapter::handleResult( SourceKit::CodeCompletionConsumer &Consumer, Completion *Result, bool leadingPunctuation, bool legacyLiteralToKeyword, - bool annotatedDescription) { + bool annotatedDescription, bool includeFullDocumentation) { static UIdent KeywordUID("source.lang.swift.keyword"); static UIdent PatternUID("source.lang.swift.pattern"); @@ -481,6 +483,18 @@ bool SwiftToSourceKitCompletionAdapter::handleResult( Info.TypeName = StringRef(SS.begin() + TypeBegin, TypeEnd - TypeBegin); Info.AssocUSRs = StringRef(SS.begin() + USRsBegin, USRsEnd - USRsBegin); + if (includeFullDocumentation) { + unsigned DocFullBegin = SS.size(); + { + llvm::raw_svector_ostream ccOS(SS); + Result->printFullDocComment(ccOS); + } + unsigned DocFullEnd = SS.size(); + Info.DocFull = StringRef(SS.begin() + DocFullBegin, DocFullEnd - DocFullBegin); + } else { + Info.DocFull = StringRef(); + } + static UIdent CCCtxNone("source.codecompletion.context.none"); static UIdent CCCtxExpressionSpecific( "source.codecompletion.context.exprspecific"); @@ -536,7 +550,6 @@ bool SwiftToSourceKitCompletionAdapter::handleResult( Info.ModuleName = Result->getModuleName(); Info.DocBrief = Result->getBriefDocComment(); - Info.DocFull = Result->getFullDocComment(); Info.NotRecommended = Result->isNotRecommended(); Info.IsSystem = Result->isSystem(); @@ -693,7 +706,8 @@ class SwiftGroupedCodeCompletionConsumer : public CodeCompletionView::Walker { bool handleResult(Completion *result) override { return SwiftToSourceKitCompletionAdapter::handleResult( consumer, result, /*leadingPunctuation=*/true, - /*legacyLiteralToKeyword=*/false, /*annotatedDescription=*/false); + /*legacyLiteralToKeyword=*/false, /*annotatedDescription=*/false, + /*includeFullDocumentation=*/false); } void startGroup(StringRef name) override { static UIdent GroupUID("source.lang.swift.codecomplete.group"); @@ -724,6 +738,7 @@ static void translateCodeCompletionOptions(OptionsDictionary &from, static UIdent KeyAddInnerOperators("key.codecomplete.addinneroperators"); static UIdent KeyAddInitsToTopLevel("key.codecomplete.addinitstotoplevel"); static UIdent KeyFuzzyMatching("key.codecomplete.fuzzymatching"); + static UIdent KeyIncludeFullDocumentation("key.codecomplete.includefulldocumentation"); static UIdent KeyTopNonLiteral("key.codecomplete.showtopnonliteralresults"); static UIdent KeyContextWeight("key.codecomplete.sort.contextweight"); static UIdent KeyFuzzyWeight("key.codecomplete.sort.fuzzyweight"); @@ -749,6 +764,7 @@ static void translateCodeCompletionOptions(OptionsDictionary &from, from.valueForOption(KeyAddInnerOperators, to.addInnerOperators); from.valueForOption(KeyAddInitsToTopLevel, to.addInitsToTopLevel); from.valueForOption(KeyFuzzyMatching, to.fuzzyMatching); + from.valueForOption(KeyIncludeFullDocumentation, to.includeFullDocumentation); from.valueForOption(KeyContextWeight, to.semanticContextWeight); from.valueForOption(KeyFuzzyWeight, to.fuzzyMatchWeight); from.valueForOption(KeyPopularityBonus, to.popularityBonus); @@ -913,7 +929,7 @@ static void transformAndForwardResults( ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( innerSink.swiftSink, CodeCompletionResultKind::BuiltinOperator, completionString, CodeCompletionOperatorKind::None, - /*BriefDocComment=*/"", /*FullDocComment=*/"", + /*BriefDocComment=*/"", CodeCompletionResultType::notApplicable(), ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp index 4b209a82d3d78..8fa5fe7209bd3 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -663,14 +663,21 @@ void swiftide_completion_item_get_doc_brief( handler(item.getBriefDocComment().data()); } -void swiftide_completion_item_get_doc_full( +void swiftide_completion_item_get_doc_full_copy( swiftide_completion_response_t _response, swiftide_completion_item_t _item, void (^handler)(const char *)) { auto &item = *static_cast(_item); - if (item.getFullDocComment().empty()) { + + llvm::SmallString<128> buffer; + { + llvm::raw_svector_ostream OS(buffer); + item.printFullDocComment(OS); + } + + if (buffer.empty()) { return handler(nullptr); } - handler(item.getFullDocComment().data()); + handler(strdup(buffer.c_str())); } void swiftide_completion_item_get_associated_usrs( diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h index d8abbed279f50..a1305bd749a17 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h @@ -348,9 +348,9 @@ swiftide_completion_item_get_doc_brief(swiftide_completion_response_t, void (^handler)(const char *)); SWIFTIDE_PUBLIC void -swiftide_completion_item_get_doc_full(swiftide_completion_response_t, - swiftide_completion_item_t, - void (^handler)(const char *)); +swiftide_completion_item_get_doc_full_copy(swiftide_completion_response_t, + swiftide_completion_item_t, + void (^handler)(const char *)); SWIFTIDE_PUBLIC void swiftide_completion_item_get_associated_usrs( swiftide_completion_response_t, swiftide_completion_item_t, diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports index ddad2c46cafdf..22ffcbcd1901c 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports @@ -149,7 +149,7 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief -swiftide_completion_item_get_doc_full +swiftide_completion_item_get_doc_full_copy swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports index 928e08b49afd0..05d562cf5bcfa 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports @@ -149,7 +149,7 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief -swiftide_completion_item_get_doc_full +swiftide_completion_item_get_doc_full_copy swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 017e8b8f14299..8cec232efe024 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -1352,13 +1352,16 @@ static void printCodeCompletionResultsImpl( } StringRef BriefComment = Result->getBriefDocComment(); - if (IncludeComments && !BriefComment.empty()) { - OS << "; briefcomment=" << BriefComment; - } - - StringRef FullComment = Result->getFullDocComment(); - if (IncludeComments && !FullComment.empty()) { - OS << "; fullcomment=" << FullComment; + if (IncludeComments) { + if (!BriefComment.empty()) { + OS << "; briefcomment=" << BriefComment; + } + + SmallString<256> FullComment; + llvm::raw_svector_ostream CommentOS(FullComment); + + if (Result->printFullDocComment(CommentOS) && !FullComment.empty()) + OS << "; fullcomment=" << FullComment; } if (Ctx) { From b5104a1a88f960bdafac5ececec705883c69dc13 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 11 Jul 2025 19:26:46 +0300 Subject: [PATCH 32/58] [IDE] Store Swift USR in ContextFreeCodeCompletionResult to find AssociatedDecl --- include/swift/IDE/CodeCompletionResult.h | 11 +++++-- lib/IDE/CodeCompletionCache.cpp | 13 ++++---- lib/IDE/CodeCompletionResult.cpp | 30 +++++++++---------- lib/IDE/CodeCompletionResultBuilder.cpp | 27 +++++++++++++---- .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 1 + 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index ae74dbb11e991..6131cf829edda 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -380,6 +380,9 @@ class ContextFreeCodeCompletionResult { NullTerminatedStringRef ModuleName; NullTerminatedStringRef BriefDocComment; ArrayRef AssociatedUSRs; + /// The Swift USR for a declaration (including for Clang declarations) used for looking up the \c Decl + /// instance for cached results. + NullTerminatedStringRef SwiftUSR; CodeCompletionResultType ResultType; ContextFreeNotRecommendedReason NotRecommended : 3; @@ -412,6 +415,7 @@ class ContextFreeCodeCompletionResult { NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, ArrayRef AssociatedUSRs, + NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, @@ -423,8 +427,8 @@ class ContextFreeCodeCompletionResult { HasAsyncAlternative(HasAsyncAlternative), CompletionString(CompletionString), ModuleName(ModuleName), BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs), - ResultType(ResultType), NotRecommended(NotRecommended), - DiagnosticSeverity(DiagnosticSeverity), + SwiftUSR(SwiftUSR), ResultType(ResultType), + NotRecommended(NotRecommended), DiagnosticSeverity(DiagnosticSeverity), DiagnosticMessage(DiagnosticMessage), FilterName(FilterName), NameForDiagnostics(NameForDiagnostics) { this->AssociatedKind.Opaque = AssociatedKind; @@ -494,6 +498,7 @@ class ContextFreeCodeCompletionResult { bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, ArrayRef AssociatedUSRs, + NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, @@ -540,6 +545,8 @@ class ContextFreeCodeCompletionResult { ArrayRef getAssociatedUSRs() const { return AssociatedUSRs; } + + NullTerminatedStringRef getSwiftUSR() const { return SwiftUSR; } const CodeCompletionResultType &getResultType() const { return ResultType; } diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp index 0628372737556..8c260bd8ace31 100644 --- a/lib/IDE/CodeCompletionCache.cpp +++ b/lib/IDE/CodeCompletionCache.cpp @@ -244,6 +244,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in, auto diagMessageIndex = read32le(cursor); auto filterNameIndex = read32le(cursor); auto nameForDiagnosticsIndex = read32le(cursor); + auto swiftUSRIndex = read32le(cursor); auto assocUSRCount = read32le(cursor); SmallVector assocUSRs; @@ -264,12 +265,13 @@ static bool readCachedModule(llvm::MemoryBuffer *in, auto diagMessage = getString(diagMessageIndex); auto filterName = getString(filterNameIndex); auto nameForDiagnostics = getString(nameForDiagnosticsIndex); + auto swiftUSR = getString(swiftUSRIndex); ContextFreeCodeCompletionResult *result = new (*V.Allocator) ContextFreeCodeCompletionResult( kind, associatedKind, opKind, roles, isSystem, hasAsyncAlternative, string, moduleName, briefDocComment, - llvm::ArrayRef(assocUSRs).copy(*V.Allocator), + llvm::ArrayRef(assocUSRs).copy(*V.Allocator), swiftUSR, CodeCompletionResultType(resultTypes), notRecommended, diagSeverity, diagMessage, filterName, nameForDiagnostics); @@ -430,11 +432,12 @@ static void writeCachedModule(llvm::raw_ostream &out, LE.write(static_cast(R->hasAsyncAlternative())); LE.write( static_cast(addCompletionString(R->getCompletionString()))); - LE.write(addString(R->getModuleName())); // index into strings - LE.write(addString(R->getBriefDocComment())); // index into strings - LE.write(addString(R->getDiagnosticMessage())); // index into strings - LE.write(addString(R->getFilterName())); // index into strings + LE.write(addString(R->getModuleName())); // index into strings + LE.write(addString(R->getBriefDocComment())); // index into strings + LE.write(addString(R->getDiagnosticMessage())); // index into strings + LE.write(addString(R->getFilterName())); // index into strings LE.write(addString(R->getNameForDiagnostics())); // index into strings + LE.write(addString(R->getSwiftUSR())); // index into strings LE.write(static_cast(R->getAssociatedUSRs().size())); for (unsigned i = 0; i < R->getAssociatedUSRs().size(); ++i) { diff --git a/lib/IDE/CodeCompletionResult.cpp b/lib/IDE/CodeCompletionResult.cpp index e5b367d3021cf..f6775aee8eaf8 100644 --- a/lib/IDE/CodeCompletionResult.cpp +++ b/lib/IDE/CodeCompletionResult.cpp @@ -154,10 +154,9 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( return new (Sink.getAllocator()) ContextFreeCodeCompletionResult( Kind, /*AssociatedKind=*/0, KnownOperatorKind, /*MacroRoles=*/{}, /*IsSystem=*/false, /*HasAsyncAlternative=*/false, - CompletionString, - /*ModuleName=*/"", BriefDocComment, - /*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity, - DiagnosticMessage, + CompletionString, /*ModuleName=*/"", BriefDocComment, + /*AssociatedUSRs=*/{}, /*SwiftUSR=*/"", ResultType, NotRecommended, + DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), NameForDiagnostics); } @@ -175,8 +174,8 @@ ContextFreeCodeCompletionResult::createKeywordResult( CodeCompletionResultKind::Keyword, static_cast(Kind), CodeCompletionOperatorKind::None, /*MacroRoles=*/{}, /*IsSystem=*/false, /*HasAsyncAlternative=*/false, CompletionString, - /*ModuleName=*/"", BriefDocComment, - /*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None, + /*ModuleName=*/"", BriefDocComment, /*AssociatedUSRs=*/{}, + /*SwiftUSR=*/"", ResultType, ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"", getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), /*NameForDiagnostics=*/""); @@ -194,10 +193,9 @@ ContextFreeCodeCompletionResult::createLiteralResult( CodeCompletionResultKind::Literal, static_cast(LiteralKind), CodeCompletionOperatorKind::None, /*MacroRoles=*/{}, /*IsSystem=*/false, /*HasAsyncAlternative=*/false, - CompletionString, - /*ModuleName=*/"", - /*BriefDocComment=*/"", - /*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None, + CompletionString, /*ModuleName=*/"", /*BriefDocComment=*/"", + /*AssociatedUSRs=*/{}, /*SwiftUSR=*/"", ResultType, + ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"", getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), /*NameForDiagnostics=*/""); @@ -224,6 +222,7 @@ ContextFreeCodeCompletionResult::createDeclResult( const Decl *AssociatedDecl, bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, ArrayRef AssociatedUSRs, + NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, @@ -237,8 +236,8 @@ ContextFreeCodeCompletionResult::createDeclResult( static_cast(getCodeCompletionDeclKind(AssociatedDecl)), CodeCompletionOperatorKind::None, getCompletionMacroRoles(AssociatedDecl), getDeclIsSystem(AssociatedDecl), HasAsyncAlternative, - CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType, - NotRecommended, DiagnosticSeverity, DiagnosticMessage, + CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, SwiftUSR, + ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), /*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink)); } @@ -444,13 +443,12 @@ const Decl *CodeCompletionResult::findAssociatedDecl(const DeclContext *DC) { HasValidAssociatedDecl = true; - auto USRs = getAssociatedUSRs(); - if (USRs.empty()) + auto SwiftUSR = ContextFree.getSwiftUSR(); + if (SwiftUSR.empty()) return nullptr; - StringRef PrimaryUSR = USRs.front(); auto &Ctx = DC->getASTContext(); - AssociatedDecl = swift::Demangle::getDeclForUSR(Ctx, PrimaryUSR); + AssociatedDecl = swift::Demangle::getDeclForUSR(Ctx, SwiftUSR); return AssociatedDecl; } diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 65255072d400a..16a00725e51f4 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -82,6 +82,25 @@ copyAssociatedUSRs(llvm::BumpPtrAllocator &Allocator, const Decl *D) { return {}; } +static NullTerminatedStringRef +copySwiftUSR(llvm::BumpPtrAllocator &Allocator, const Decl *D) { + auto *VD = dyn_cast(D); + if (!VD || !shouldCopyAssociatedUSRForDecl(VD)) + return NullTerminatedStringRef(); + + SmallString<128> SS; + llvm::raw_svector_ostream OS(SS); + if (!ide::printValueDeclSwiftUSR(VD, OS)) + return NullTerminatedStringRef(SS, Allocator); + + return NullTerminatedStringRef(); +} + +void CodeCompletionResultBuilder::addChunkWithText( + CodeCompletionString::Chunk::ChunkKind Kind, StringRef Text) { + addChunkWithTextNoCopy(Kind, Text.copy(*Sink.Allocator)); +} + /// Tries to reconstruct the provided \p D declaration using \c Demangle::getDeclForUSR and verifies /// that the declarations match. /// This only works if \p D is a \c ValueDecl and \c shouldCopyAssociatedUSRForDecl is true. @@ -124,11 +143,6 @@ static void verifyUSRToDeclReconstruction(const Decl *D) { } } -void CodeCompletionResultBuilder::addChunkWithText( - CodeCompletionString::Chunk::ChunkKind Kind, StringRef Text) { - addChunkWithTextNoCopy(Kind, Text.copy(*Sink.Allocator)); -} - CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { auto &Allocator = *Sink.Allocator; auto *CCS = CodeCompletionString::create(Allocator, Chunks); @@ -184,7 +198,8 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { ContextFreeResult = ContextFreeCodeCompletionResult::createDeclResult( Sink, CCS, AssociatedDecl, HasAsyncAlternative, ModuleName, NullTerminatedStringRef(BriefDocComment, Allocator), - copyAssociatedUSRs(Allocator, AssociatedDecl), ResultType, + copyAssociatedUSRs(Allocator, AssociatedDecl), + copySwiftUSR(Allocator, AssociatedDecl), ResultType, ContextFreeNotRecReason, ContextFreeDiagnosticSeverity, ContextFreeDiagnosticMessage); break; diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index 69e0d34b90768..50a5e0880f758 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -1162,6 +1162,7 @@ Completion *CompletionBuilder::finish() { newCompletionString, contextFreeBase.getModuleName(), contextFreeBase.getBriefDocComment(), contextFreeBase.getAssociatedUSRs(), + contextFreeBase.getSwiftUSR(), contextFreeBase.getResultType(), contextFreeBase.getNotRecommendedReason(), contextFreeBase.getDiagnosticSeverity(), From a3a5facc47d3657e06efe73656f78c7a285fdd9c Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 11 Jul 2025 19:28:06 +0300 Subject: [PATCH 33/58] [IDE] Enable full doc option in complete tests that assert on doc --- test/SourceKit/CodeComplete/complete_doc_1.swift | 2 +- test/SourceKit/CodeComplete/complete_doc_2.swift | 2 +- test/SourceKit/CodeComplete/complete_doc_3.swift | 2 +- test/SourceKit/CodeComplete/complete_doc_package.swift | 2 +- test/SourceKit/CodeComplete/complete_doc_spi.swift | 2 +- test/SourceKit/CodeComplete/complete_from_clang_module.swift | 2 +- test/SourceKit/CodeComplete/complete_moduleimportdepth.swift | 1 - 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/SourceKit/CodeComplete/complete_doc_1.swift b/test/SourceKit/CodeComplete/complete_doc_1.swift index 03dd351e12ad7..aa6610ece1435 100644 --- a/test/SourceKit/CodeComplete/complete_doc_1.swift +++ b/test/SourceKit/CodeComplete/complete_doc_1.swift @@ -23,7 +23,7 @@ func test() { } // All in main module. -// RUN: %sourcekitd-test -req=complete -pos=22:7 %s -- %s -module-name DocBriefTest | %FileCheck %s -check-prefix=CHECK +// RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=22:7 %s -- %s -module-name DocBriefTest | %FileCheck %s -check-prefix=CHECK // CHECK: { // CHECK: key.results: [ diff --git a/test/SourceKit/CodeComplete/complete_doc_2.swift b/test/SourceKit/CodeComplete/complete_doc_2.swift index a9cf6a6b8ff08..e355af29f4b10 100644 --- a/test/SourceKit/CodeComplete/complete_doc_2.swift +++ b/test/SourceKit/CodeComplete/complete_doc_2.swift @@ -24,7 +24,7 @@ struct S: P { } func test() { - // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK + // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK S(). // CHECK: { diff --git a/test/SourceKit/CodeComplete/complete_doc_3.swift b/test/SourceKit/CodeComplete/complete_doc_3.swift index bd41a468e9b10..3b9d718be4f39 100644 --- a/test/SourceKit/CodeComplete/complete_doc_3.swift +++ b/test/SourceKit/CodeComplete/complete_doc_3.swift @@ -25,7 +25,7 @@ public struct S: P { //--- User.swift import DocBriefTest func test() { - // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK + // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK S().foo() // CHECK: { diff --git a/test/SourceKit/CodeComplete/complete_doc_package.swift b/test/SourceKit/CodeComplete/complete_doc_package.swift index d69351be15b1f..71c643b06812f 100644 --- a/test/SourceKit/CodeComplete/complete_doc_package.swift +++ b/test/SourceKit/CodeComplete/complete_doc_package.swift @@ -27,7 +27,7 @@ package struct S: P { package import DocBriefTest func test() { - // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -package-name DocPackage | %FileCheck %s -check-prefix=CHECK + // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -package-name DocPackage | %FileCheck %s -check-prefix=CHECK S().foo() // CHECK: { diff --git a/test/SourceKit/CodeComplete/complete_doc_spi.swift b/test/SourceKit/CodeComplete/complete_doc_spi.swift index fbbb5755389b9..f07f252a2e8b1 100644 --- a/test/SourceKit/CodeComplete/complete_doc_spi.swift +++ b/test/SourceKit/CodeComplete/complete_doc_spi.swift @@ -28,7 +28,7 @@ public struct S: P { @_spi(SomeSPI) import DocBriefTest func test() { - // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK + // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK S().foo() // CHECK: { diff --git a/test/SourceKit/CodeComplete/complete_from_clang_module.swift b/test/SourceKit/CodeComplete/complete_from_clang_module.swift index bb66d6b0742bf..a2b5d844673c8 100644 --- a/test/SourceKit/CodeComplete/complete_from_clang_module.swift +++ b/test/SourceKit/CodeComplete/complete_from_clang_module.swift @@ -1,7 +1,7 @@ import Foo // REQUIRES: objc_interop -// RUN: %sourcekitd-test -req=complete -pos=2:1 %s -- -F %S/../Inputs/libIDE-mock-sdk %s | %FileCheck %s +// RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=2:1 %s -- -F %S/../Inputs/libIDE-mock-sdk %s | %FileCheck %s // CHECK-LABEL: key.name: "fooIntVar", // CHECK-NEXT: key.doc.full_as_xml: "fooIntVarc:@fooIntVarvar fooIntVar: Int32 Aaa. fooIntVar. Bbb.", diff --git a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift index 95b05efbea202..cc29a4563d2f8 100644 --- a/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift +++ b/test/SourceKit/CodeComplete/complete_moduleimportdepth.swift @@ -11,7 +11,6 @@ func test() { // Swift == 1 // CHECK-LABEL: key.name: "abs(:)", -// CHECK-NEXT: key.doc.full_as_xml: "abs(_:)s:s3absyxxSLRzs13SignedNumericRzlF@inlinable func abs<T>(_ x: T) -> T where T : Comparable, T : SignedNumericReturns the absolute value of the given number.xinA signed number.The absolute value of x.The absolute value of x must be representable in the same type. In particular, the absolute value of a signed, fixed-width integer type’s minimum cannot be represented.", // CHECK-NEXT: key.description: "abs(x: Comparable & SignedNumeric)", // CHECK-NEXT: key.typename: "Comparable & SignedNumeric", // CHECK-NEXT: key.doc.brief: "Returns the absolute value of the given number.", From f596929cdd86529bffa85a44d34a67b990d6bc42 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 14 Jul 2025 00:45:48 +0300 Subject: [PATCH 34/58] [IDE] Fetch completion result associated decl on-demand on printFullDocComment --- include/swift/IDE/CodeCompletionResult.h | 38 +++++-------------- lib/IDE/CodeCompletionContext.cpp | 9 ++--- lib/IDE/CodeCompletionResult.cpp | 34 ++++++++--------- lib/IDE/CodeCompletionResultBuilder.cpp | 9 ++--- .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 3 +- .../lib/SwiftLang/SwiftCompletion.cpp | 4 +- tools/swift-ide-test/swift-ide-test.cpp | 4 +- 7 files changed, 37 insertions(+), 64 deletions(-) diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index 6131cf829edda..0052442f953f9 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -602,8 +602,9 @@ class ContextFreeCodeCompletionResult { /// the completion's usage context. class CodeCompletionResult { const ContextFreeCodeCompletionResult &ContextFree; - const Decl *AssociatedDecl = nullptr; - bool HasValidAssociatedDecl : 1; + /// Contains the associated declaration if fetched; if not, stores the ASTContext to use for finding the + /// associated declaration through the Swift USR. + mutable llvm::PointerUnion DeclOrCtx; SemanticContextKind SemanticContext : 3; static_assert(int(SemanticContextKind::MAX_VALUE) < 1 << 3, ""); @@ -618,8 +619,6 @@ class CodeCompletionResult { /// should be erased first if this completion string is inserted in the /// editor buffer. unsigned NumBytesToErase : 7; - -// std::optional FullDocComment; public: static const unsigned MaxNumBytesToErase = 127; @@ -634,23 +633,12 @@ class CodeCompletionResult { /// done by allocating the two in the same sink or adopting the context free /// sink in the sink that allocates this result. CodeCompletionResult(const ContextFreeCodeCompletionResult &ContextFree, - const Decl *AssociatedDecl, bool HasValidAssociatedDecl, + llvm::PointerUnion DeclOrCtx, SemanticContextKind SemanticContext, CodeCompletionFlair Flair, uint8_t NumBytesToErase, CodeCompletionResultTypeRelation TypeDistance, ContextualNotRecommendedReason NotRecommended) - : ContextFree(ContextFree), AssociatedDecl(AssociatedDecl), - HasValidAssociatedDecl(HasValidAssociatedDecl), - SemanticContext(SemanticContext), Flair(Flair.toRaw()), - NotRecommended(NotRecommended), NumBytesToErase(NumBytesToErase), - TypeDistance(TypeDistance) {} - - CodeCompletionResult(const ContextFreeCodeCompletionResult &ContextFree, - SemanticContextKind SemanticContext, - CodeCompletionFlair Flair, uint8_t NumBytesToErase, - CodeCompletionResultTypeRelation TypeDistance, - ContextualNotRecommendedReason NotRecommended) - : ContextFree(ContextFree), HasValidAssociatedDecl(false), + : ContextFree(ContextFree), DeclOrCtx(DeclOrCtx), SemanticContext(SemanticContext), Flair(Flair.toRaw()), NotRecommended(NotRecommended), NumBytesToErase(NumBytesToErase), TypeDistance(TypeDistance) {} @@ -740,15 +728,8 @@ class CodeCompletionResult { return NotRecommendedReason::VariableUsedInOwnDefinition; } } - - bool hasValidAssociatedDecl() const { return HasValidAssociatedDecl; } - - const Decl *getAssociatedDecl() const { - assert(HasValidAssociatedDecl && "AssociatedDecl hasn't been loaded yet"); - return AssociatedDecl; - } - - const Decl *findAssociatedDecl(const DeclContext *DC); + + const Decl *getAssociatedDecl() const; SemanticContextKind getSemanticContext() const { return SemanticContext; } @@ -779,9 +760,8 @@ class CodeCompletionResult { /// /// \returns true if the result has a full documentation comment, false otherwise. bool printFullDocComment(raw_ostream &OS) const { - assert(HasValidAssociatedDecl && "Associated declaration hasn't been fetched"); - if (AssociatedDecl) - return ide::getDocumentationCommentAsXML(AssociatedDecl, OS); + if (auto *D = getAssociatedDecl()) + return ide::getDocumentationCommentAsXML(D, OS); return false; } diff --git a/lib/IDE/CodeCompletionContext.cpp b/lib/IDE/CodeCompletionContext.cpp index 35c05aafa5f6f..f08536368eddb 100644 --- a/lib/IDE/CodeCompletionContext.cpp +++ b/lib/IDE/CodeCompletionContext.cpp @@ -110,12 +110,11 @@ static MutableArrayRef copyCodeCompletionResults( ContextualNotRecommendedReason::None, CanCurrDeclContextHandleAsync); + ASTContext *Ctx = DC ? &DC->getASTContext() : nullptr; auto contextualResult = new (*targetSink.Allocator) CodeCompletionResult( - *contextFreeResult, SemanticContextKind::OtherModule, - CodeCompletionFlair(), - /*numBytesToErase=*/0, typeRelation, notRecommendedReason); - - contextualResult->findAssociatedDecl(DC); + *contextFreeResult, Ctx, SemanticContextKind::OtherModule, + CodeCompletionFlair(), /*numBytesToErase=*/0, typeRelation, + notRecommendedReason); targetSink.Results.push_back(contextualResult); } diff --git a/lib/IDE/CodeCompletionResult.cpp b/lib/IDE/CodeCompletionResult.cpp index f6775aee8eaf8..e775a698f00cb 100644 --- a/lib/IDE/CodeCompletionResult.cpp +++ b/lib/IDE/CodeCompletionResult.cpp @@ -437,29 +437,25 @@ ContextFreeCodeCompletionResult::calculateContextualTypeRelation( // MARK: - CodeCompletionResult -const Decl *CodeCompletionResult::findAssociatedDecl(const DeclContext *DC) { - if (HasValidAssociatedDecl) - return AssociatedDecl; +const Decl *CodeCompletionResult::getAssociatedDecl() const { + if (auto *Ctx = DeclOrCtx.dyn_cast()) { + auto SwiftUSR = ContextFree.getSwiftUSR(); + if (SwiftUSR.empty()) + return nullptr; - HasValidAssociatedDecl = true; - - auto SwiftUSR = ContextFree.getSwiftUSR(); - if (SwiftUSR.empty()) - return nullptr; - - auto &Ctx = DC->getASTContext(); - AssociatedDecl = swift::Demangle::getDeclForUSR(Ctx, SwiftUSR); - - return AssociatedDecl; + DeclOrCtx = Demangle::getDeclForUSR(*Ctx, SwiftUSR); + } + + return DeclOrCtx.dyn_cast(); } CodeCompletionResult * CodeCompletionResult::withFlair(CodeCompletionFlair NewFlair, CodeCompletionResultSink &Sink) const { return new (*Sink.Allocator) - CodeCompletionResult(ContextFree, AssociatedDecl, HasValidAssociatedDecl, - SemanticContext, NewFlair, NumBytesToErase, - TypeDistance, NotRecommended); + CodeCompletionResult(ContextFree, DeclOrCtx, SemanticContext, + NewFlair, NumBytesToErase, TypeDistance, + NotRecommended); } CodeCompletionResult * @@ -468,9 +464,9 @@ CodeCompletionResult::withContextFreeResultSemanticContextAndFlair( SemanticContextKind NewSemanticContext, CodeCompletionFlair NewFlair, CodeCompletionResultSink &Sink) const { return new (*Sink.Allocator) - CodeCompletionResult(NewContextFree, AssociatedDecl, HasValidAssociatedDecl, - NewSemanticContext, NewFlair, NumBytesToErase, - TypeDistance, NotRecommended); + CodeCompletionResult(NewContextFree, DeclOrCtx, NewSemanticContext, + NewFlair, NumBytesToErase, TypeDistance, + NotRecommended); } std::pair diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 16a00725e51f4..eb96b321c1c50 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -230,8 +230,8 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { // If the sink only intends to store the context free results in the cache, // we don't need to compute any contextual properties. return new (Allocator) CodeCompletionResult( - *ContextFreeResult, AssociatedDecl, /*HasValidAssociatedDecl=*/true, - SemanticContextKind::None, CodeCompletionFlair(), /*NumBytesToErase=*/0, + *ContextFreeResult, AssociatedDecl, SemanticContextKind::None, + CodeCompletionFlair(), /*NumBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated, ContextualNotRecommendedReason::None); } else { @@ -251,9 +251,8 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() { ContextualNotRecReason, CanCurrDeclContextHandleAsync); return new (Allocator) CodeCompletionResult( - *ContextFreeResult, AssociatedDecl, /*HasValidAssociatedDecl=*/true, - SemanticContext, Flair, NumBytesToErase, typeRelation, - notRecommendedReason); + *ContextFreeResult, AssociatedDecl, SemanticContext, Flair, + NumBytesToErase, typeRelation, notRecommendedReason); } } diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index 50a5e0880f758..3a62106c6ffac 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -139,8 +139,7 @@ bool SourceKit::CodeCompletion::addCustomCompletions( ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); auto *swiftResult = new (sink.allocator) CodeCompletion::SwiftResult( - *contextFreeResult, /*AssociatedDecl=*/nullptr, - /*HasValidAssociatedDecl=*/true, SemanticContextKind::Local, + *contextFreeResult, /*DeclOrCtx=*/nullptr, SemanticContextKind::Local, CodeCompletionFlairBit::ExpressionSpecific, /*NumBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated, ContextualNotRecommendedReason::None); diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index 1077f99db6654..b0e5e92cf9d4c 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -935,8 +935,8 @@ static void transformAndForwardResults( CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); auto *paren = new (innerSink.allocator) CodeCompletion::SwiftResult( - *contextFreeResult, /*AssociatedDecl=*/nullptr, - /*HasValidAssociatedDecl=*/true, SemanticContextKind::CurrentNominal, + *contextFreeResult, /*DeclOrCtx=*/nullptr, + SemanticContextKind::CurrentNominal, CodeCompletionFlairBit::ExpressionSpecific, exactMatch ? exactMatch->getNumBytesToErase() : 0, CodeCompletionResultTypeRelation::Unrelated, diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 8cec232efe024..a9263ee048701 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -4387,8 +4387,8 @@ int main(int argc, char *argv[]) { // We are leaking these results but it doesn't matter since the process // just terminates afterwards anyway. auto contextualResult = new CodeCompletionResult( - *contextFreeResult, SemanticContextKind::OtherModule, - CodeCompletionFlair(), + *contextFreeResult, /*DeclOrCtx=*/nullptr, + SemanticContextKind::OtherModule, CodeCompletionFlair(), /*numBytesToErase=*/0, CodeCompletionResultTypeRelation::Unrelated, ContextualNotRecommendedReason::None); contextualResults.push_back(contextualResult); From 7487c6df469778707f19e617744f697c6f15b0e1 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 14 Jul 2025 23:28:00 +0300 Subject: [PATCH 35/58] [IDE] Pass mutable C-string to handler in swiftide_completion_item_get_doc_full_copy --- .../tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp | 2 +- .../tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp index 8fa5fe7209bd3..8c3f9a7ce3e29 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -665,7 +665,7 @@ void swiftide_completion_item_get_doc_brief( void swiftide_completion_item_get_doc_full_copy( swiftide_completion_response_t _response, swiftide_completion_item_t _item, - void (^handler)(const char *)) { + void (^handler)(char *)) { auto &item = *static_cast(_item); llvm::SmallString<128> buffer; diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h index a1305bd749a17..fd3477d7f0c55 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h @@ -350,7 +350,7 @@ swiftide_completion_item_get_doc_brief(swiftide_completion_response_t, SWIFTIDE_PUBLIC void swiftide_completion_item_get_doc_full_copy(swiftide_completion_response_t, swiftide_completion_item_t, - void (^handler)(const char *)); + void (^handler)(char *)); SWIFTIDE_PUBLIC void swiftide_completion_item_get_associated_usrs( swiftide_completion_response_t, swiftide_completion_item_t, From 58f0a30a51b109a094fea6540882b0f70b2599f7 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sun, 20 Jul 2025 23:49:02 +0300 Subject: [PATCH 36/58] [USR] Split USRGenerationRequest into SwiftUSRGenerationRequest & ClangUSRGenerationRequest With the introduction of useSwiftUSR option to USRGenerationRequest, Swift declaration USRs could now get cached twice even though the useSwiftUSR option doesn't affect Swift declarations. We turned USRGenerationRequest into an uncached request that forwards requests to SwiftUSRGenerationRequest and ClangUSRGenerationRequest which cache results. ClangUSRGenerationRequest uses split caching to avoid filling the cache with a lot of null results. --- include/swift/AST/Decl.h | 5 ++ include/swift/AST/TypeCheckRequests.h | 82 +++++++++++++++++++-- include/swift/AST/TypeCheckerTypeIDZone.def | 10 ++- lib/AST/USRGeneration.cpp | 67 +++++++++++++---- lib/PrintAsClang/ClangSyntaxPrinter.cpp | 5 +- 5 files changed, 143 insertions(+), 26 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 3f90673450792..465e296a308cd 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -2909,6 +2909,10 @@ class ValueDecl : public Decl { /// a null pointer. unsigned noOpaqueResultType : 1; + /// Whether the ClangUSRGenerationRequest request was evaluated and produced + /// a std::nullopt. + unsigned noClangUSR : 1; + /// Whether the "isFinal" bit has been computed yet. unsigned isFinalComputed : 1; @@ -2943,6 +2947,7 @@ class ValueDecl : public Decl { friend class OpaqueResultTypeRequest; friend class ApplyAccessNoteRequest; friend class AvailabilityDomainForDeclRequest; + friend class ClangUSRGenerationRequest; friend class Decl; SourceLoc getLocFromSource() const { return NameLoc; } diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 67b5dce5d7ba6..2b1ed36b7c6d5 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -769,7 +769,9 @@ struct USRGenerationOptions { bool useSwiftUSR; friend llvm::hash_code hash_value(const USRGenerationOptions &options) { - return llvm::hash_value(options.distinguishSynthesizedDecls); + return llvm::hash_combine( + llvm::hash_value(options.distinguishSynthesizedDecls), + llvm::hash_value(options.useSwiftUSR)); } friend bool operator==(const USRGenerationOptions &lhs, @@ -787,11 +789,79 @@ struct USRGenerationOptions { void simple_display(llvm::raw_ostream &out, const USRGenerationOptions &options); +struct ClangUSRGenerationOptions { + /// @brief Whether to emit USRs using the Swift declaration when it is + /// synthesized from a Clang based declaration. Useful in cases where Swift + /// declarations are synthesized from Clang nodes but the caller actually + /// wants the USR of the Swift declaration. + bool distinguishSynthesizedDecls; + + friend llvm::hash_code hash_value(const ClangUSRGenerationOptions &options) { + return llvm::hash_value(options.distinguishSynthesizedDecls); + } + + friend bool operator==(const ClangUSRGenerationOptions &lhs, + const ClangUSRGenerationOptions &rhs) { + return lhs.distinguishSynthesizedDecls == rhs.distinguishSynthesizedDecls; + } + + friend bool operator!=(const ClangUSRGenerationOptions &lhs, + const ClangUSRGenerationOptions &rhs) { + return !(lhs == rhs); + } +}; + +void simple_display(llvm::raw_ostream &out, + const ClangUSRGenerationOptions &options); + +/// Generate the Clang USR for the given declaration. +class ClangUSRGenerationRequest + : public SimpleRequest< + ClangUSRGenerationRequest, + std::optional(ValueDecl *, ClangUSRGenerationOptions), + RequestFlags::SeparatelyCached | RequestFlags::SplitCached> { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + std::optional evaluate(Evaluator &eval, ValueDecl *d, + ClangUSRGenerationOptions options) const; + +public: + // Split caching. + bool isCached() const { return true; } + std::optional> getCachedResult() const; + void cacheResult(std::optional result) const; +}; + +/// Generate the Swift USR for the given declaration. +class SwiftUSRGenerationRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + std::string evaluate(Evaluator &eval, ValueDecl *d) const; + +public: + // Caching + bool isCached() const { return true; } +}; + /// Generate the USR for the given declaration. +/// This is an umbrella request that forwards to ClangUSRGenerationRequest or +/// SwiftUSRGenerationRequest. class USRGenerationRequest : public SimpleRequest { + std::string(ValueDecl *, USRGenerationOptions), + RequestFlags::Uncached> { public: using SimpleRequest::SimpleRequest; @@ -799,12 +869,12 @@ class USRGenerationRequest friend SimpleRequest; // Evaluation. - std::string evaluate(Evaluator &eval, const ValueDecl *d, + std::string evaluate(Evaluator &eval, ValueDecl *d, USRGenerationOptions options) const; public: - // Caching - bool isCached() const { return true; } + // No caching - this forwards to other requests + bool isCached() const { return false; } }; /// Generate the mangling for the given local type declaration. diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index 3870fc714a092..e2464b60aff7a 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -364,9 +364,15 @@ SWIFT_REQUEST(TypeChecker, TypeCheckASTNodeAtLocRequest, Uncached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *), SeparatelyCached, NoLocationInfo) -SWIFT_REQUEST(TypeChecker, USRGenerationRequest, - std::string(const ValueDecl *, USRGenerationOptions), +SWIFT_REQUEST(TypeChecker, ClangUSRGenerationRequest, + std::optional(ValueDecl *, ClangUSRGenerationOptions), + SeparatelyCached | SplitCached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, SwiftUSRGenerationRequest, + std::string(ValueDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, USRGenerationRequest, + std::string(ValueDecl *, USRGenerationOptions), + Uncached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, IsABICompatibleOverrideRequest, bool(ValueDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, IsStaticRequest, diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 54c85d66b9efd..5a80a3458b632 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -177,8 +177,15 @@ void swift::simple_display(llvm::raw_ostream &out, << ", useSwiftUSR: " << options.useSwiftUSR << ")"; } -static std::optional -generateClangUSR(const ValueDecl *D, USRGenerationOptions options) { +void swift::simple_display(llvm::raw_ostream &out, + const ClangUSRGenerationOptions &options) { + out << "ClangUSRGenerationOptions (distinguishSynthesizedDecls: " + << options.distinguishSynthesizedDecls << ")"; +} + +std::optional swift::ClangUSRGenerationRequest::evaluate( + Evaluator &evaluator, ValueDecl *D, + ClangUSRGenerationOptions options) const { auto interpretAsClangNode = [&options](const ValueDecl *D) -> ClangNode { auto *importer = D->getASTContext().getClangModuleLoader(); ClangNode ClangN = importer->getEffectiveClangNode(D); @@ -253,8 +260,39 @@ generateClangUSR(const ValueDecl *D, USRGenerationOptions options) { return std::nullopt; } +std::optional> +swift::ClangUSRGenerationRequest::getCachedResult() const { + auto *decl = std::get<0>(getStorage()); + if (decl->LazySemanticInfo.noClangUSR) + return std::optional(std::optional()); + + return decl->getASTContext().evaluator.getCachedNonEmptyOutput(*this); +} + +void swift::ClangUSRGenerationRequest::cacheResult( + std::optional result) const { + auto *decl = std::get<0>(getStorage()); + if (!result) { + decl->LazySemanticInfo.noClangUSR = 1; + return; + } + decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result)); +} + +std::string swift::SwiftUSRGenerationRequest::evaluate(Evaluator &evaluator, + ValueDecl *D) const { + auto declIFaceTy = D->getInterfaceType(); + + // Invalid code. + if (declIFaceTy.findIf([](Type t) -> bool { return t->is(); })) + return std::string(); + + Mangle::ASTMangler NewMangler(D->getASTContext()); + return NewMangler.mangleDeclAsUSR(D, getUSRSpacePrefix()); +} + std::string -swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, +swift::USRGenerationRequest::evaluate(Evaluator &evaluator, ValueDecl *D, USRGenerationOptions options) const { if (auto *VD = dyn_cast(D)) D = VD->getCanonicalVarDecl(); @@ -268,20 +306,16 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, return std::string(); // Ignore. if (!options.useSwiftUSR) { - if (auto USR = generateClangUSR(D, options)) - return USR.value(); + if (auto clangUSR = evaluateOrDefault( + evaluator, + ClangUSRGenerationRequest{D, {options.distinguishSynthesizedDecls}}, + std::nullopt)) { + return clangUSR.value(); + } } - auto declIFaceTy = D->getInterfaceType(); - - // Invalid code. - if (declIFaceTy.findIf([](Type t) -> bool { - return t->is(); - })) - return std::string(); - - Mangle::ASTMangler NewMangler(D->getASTContext()); - return NewMangler.mangleDeclAsUSR(D, getUSRSpacePrefix()); + return evaluateOrDefault(evaluator, SwiftUSRGenerationRequest{D}, + std::string()); } std::string ide::demangleUSR(StringRef mangled) { @@ -322,7 +356,8 @@ bool ide::printValueDeclUSR(const ValueDecl *D, raw_ostream &OS, bool useSwiftUSR) { auto result = evaluateOrDefault( D->getASTContext().evaluator, - USRGenerationRequest{D, {distinguishSynthesizedDecls, useSwiftUSR}}, + USRGenerationRequest{const_cast(D), + {distinguishSynthesizedDecls, useSwiftUSR}}, std::string()); if (result.empty()) return true; diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.cpp b/lib/PrintAsClang/ClangSyntaxPrinter.cpp index 21078f534907e..17820ea03cba8 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.cpp +++ b/lib/PrintAsClang/ClangSyntaxPrinter.cpp @@ -488,8 +488,9 @@ void ClangSyntaxPrinter::printSymbolUSRAttribute(const ValueDecl *D) const { os << "\")"; return; } - auto result = evaluateOrDefault(D->getASTContext().evaluator, - USRGenerationRequest{D, {}}, std::string()); + auto result = evaluateOrDefault( + D->getASTContext().evaluator, + USRGenerationRequest{const_cast(D), {}}, std::string()); if (result.empty()) return; os << " SWIFT_SYMBOL(\"" << result << "\")"; From f4926fe76d566329399e57174f13e18ef987f8f8 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 21 Jul 2025 00:06:26 +0300 Subject: [PATCH 37/58] [IDE] Switch assert false to ABORT in verifyUSRToDeclReconstruction --- lib/IDE/CodeCompletionResultBuilder.cpp | 30 ++++++++++++++----------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index eb96b321c1c50..4eea55e379e70 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -118,28 +118,32 @@ static void verifyUSRToDeclReconstruction(const Decl *D) { llvm::raw_svector_ostream OS(SwiftUSR); if (ide::printValueDeclSwiftUSR(VD, OS)) { - llvm::errs() << "Declaration is:\n"; - VD->dump(llvm::errs()); - assert(false && "Declaration should have a Swift USR"); + ABORT([&](auto &out) { + out << "Declaration should have a Swift USR:\n"; + VD->dump(out); + }); } auto &Ctx = VD->getASTContext(); auto *Reconstructed = Demangle::getDeclForUSR(Ctx, SwiftUSR); if (!Reconstructed) { - llvm::errs() << "Swift USR is " << SwiftUSR << ", declaration is:\n"; - VD->dump(llvm::errs()); - - assert(false && "Reconstructed declaration shouldn't be null"); + ABORT([&](auto &out) { + out << "Reconstructed declaration shouldn't be null\n" + << "Swift USR: " << SwiftUSR << ", original declaration:\n"; + VD->dump(out); + }); } if (Reconstructed != VD) { - llvm::errs() << "Swift USR is " << SwiftUSR << ", reconstructed declaration is:\n"; - Reconstructed->dump(llvm::errs()); - llvm::errs() << "Original declaration is:\n"; - VD->dump(llvm::errs()); - - assert(false && "Reconstructed declaration should match the original one"); + ABORT([&](auto &out) { + out << "Reconstructed declaration should match the original one\n" + << "Swift USR: " << SwiftUSR << "\n" + << "Original declaration:\n"; + VD->dump(out); + out << "Reconstructed declaration:\n"; + Reconstructed->dump(out); + }); } } From b93a8f692b128fc6726ec8b0387784c2302fcc05 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 21 Jul 2025 00:15:12 +0300 Subject: [PATCH 38/58] [IDE] Apply clang-format to full documentation changes --- include/swift/AST/ASTDemangler.h | 23 +++--- include/swift/AST/DeclNameExtractor.h | 2 +- include/swift/AST/TypeCheckRequests.h | 5 +- include/swift/AST/USRGeneration.h | 8 ++- include/swift/IDE/CodeCompletionContext.h | 8 +-- include/swift/IDE/CodeCompletionResult.h | 39 +++++----- include/swift/IDE/CodeCompletionResultSink.h | 2 +- lib/AST/ASTContext.cpp | 2 +- lib/AST/ASTDemangler.cpp | 39 +++++----- lib/AST/DeclNameExtractor.cpp | 72 +++++++++---------- lib/AST/USRGeneration.cpp | 5 +- lib/IDE/CodeCompletionCache.cpp | 4 +- lib/IDE/CodeCompletionResult.cpp | 31 ++++---- lib/IDE/CodeCompletionResultBuilder.cpp | 17 ++--- .../lib/SwiftLang/CodeCompletionOrganizer.cpp | 7 +- .../lib/SwiftLang/SwiftCompletion.cpp | 17 +++-- .../tools/sourcekitd-test/sourcekitd-test.cpp | 3 +- tools/swift-ide-test/swift-ide-test.cpp | 4 +- 18 files changed, 143 insertions(+), 145 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index 19755a3d400fb..d319a48b7ea1b 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -32,7 +32,7 @@ #include namespace swift { - + class Decl; class TypeDecl; class DeclName; @@ -52,9 +52,8 @@ TypeDecl *getTypeDeclForUSR(ASTContext &ctx, llvm::StringRef usr, GenericSignature genericSig=GenericSignature()); -Decl *getDeclForUSR(ASTContext &ctx, - llvm::StringRef usr, - GenericSignature genericSig=GenericSignature()); +Decl *getDeclForUSR(ASTContext &ctx, llvm::StringRef usr, + GenericSignature genericSig = GenericSignature()); /// An implementation of MetadataReader's BuilderType concept that /// just finds and builds things in the AST. @@ -127,16 +126,18 @@ class ASTBuilder { DeclContext *getNotionalDC(); Demangle::NodeFactory &getNodeFactory() { return Factory; } - + /// Finds the \c Decl associated with the provided \p node. - /// Attempts to find a type declaration using \c createTypeDecl, if not found, it performs a lookup - /// for the declaration and returns the first declaration for which \c isMatchingValueDecl returns true. + /// Attempts to find a type declaration using \c createTypeDecl, if not found, + /// it performs a lookup for the declaration and returns the first declaration + /// for which \c isMatchingValueDecl returns true. /// - /// \note \p isMatchingValueDecl is not evaluated for type declarations, it's only used to choose + /// \note \p isMatchingValueDecl is not evaluated for type declarations, it's + /// only used to choose /// among lookup results when \c createTypeDecl fails. - Decl *findDecl( - NodePointer node, - llvm::function_ref isMatchingValueDecl); + Decl * + findDecl(NodePointer node, + llvm::function_ref isMatchingValueDecl); Type decodeMangledType(NodePointer node, bool forRequirement = true); Type createBuiltinType(StringRef builtinName, StringRef mangledName); diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h index ce940b500bf1e..d5cba781b9416 100644 --- a/include/swift/AST/DeclNameExtractor.h +++ b/include/swift/AST/DeclNameExtractor.h @@ -1,4 +1,4 @@ -//===--- DeclNameExtractor.h - Decl Name Demangling --------------*- C++ -*-===// +//===--- DeclNameExtractor.h - Decl Name Demangling -------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 2b1ed36b7c6d5..4e4ec9c69f87a 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -764,8 +764,9 @@ struct USRGenerationOptions { /// wants the USR of the Swift declaration. bool distinguishSynthesizedDecls; - /// @brief Whether to emit USRs using the Swift declaration for all declarations - /// specifically, emits a Swift USR for all Clang-based declarations. + /// @brief Whether to emit USRs using the Swift declaration for all + /// declarations specifically, emits a Swift USR for all Clang-based + /// declarations. bool useSwiftUSR; friend llvm::hash_code hash_value(const USRGenerationOptions &options) { diff --git a/include/swift/AST/USRGeneration.h b/include/swift/AST/USRGeneration.h index 5171fc4ab9f98..61095c43e2a10 100644 --- a/include/swift/AST/USRGeneration.h +++ b/include/swift/AST/USRGeneration.h @@ -45,14 +45,16 @@ bool printDeclTypeUSR(const ValueDecl *D, raw_ostream &OS); /// Prints out the USR for the given ValueDecl. /// @param distinguishSynthesizedDecls Whether to use the USR of the /// synthesized declaration instead of the USR of the underlying Clang USR. -/// @param useSwiftUSR Whether to generate a Swift USR for all Clang declarations as well. +/// @param useSwiftUSR Whether to generate a Swift USR for all Clang +/// declarations as well. /// \returns true if it failed, false on success. bool printValueDeclUSR(const ValueDecl *D, raw_ostream &OS, bool distinguishSynthesizedDecls = false, bool useSwiftUSR = false); -/// Prints out the Swift USR for the given ValueDecl regardless of its source (Swift or Clang). -/// Equivalent to `printValueDeclUSR(D, OS, false, /*useSwiftUSR=*/true)` +/// Prints out the Swift USR for the given ValueDecl regardless of its source +/// (Swift or Clang). Equivalent to `printValueDeclUSR(D, OS, false, +/// /*useSwiftUSR=*/true)` inline bool printValueDeclSwiftUSR(const ValueDecl *D, raw_ostream &OS) { return printValueDeclUSR(D, OS, /*distinguishSynthesizedDecls=*/false, /*useSwiftUSR=*/true); diff --git a/include/swift/IDE/CodeCompletionContext.h b/include/swift/IDE/CodeCompletionContext.h index 52f63ce83787f..00c448ab02a37 100644 --- a/include/swift/IDE/CodeCompletionContext.h +++ b/include/swift/IDE/CodeCompletionContext.h @@ -86,12 +86,8 @@ class CodeCompletionContext { return CurrentResults.addCallWithNoDefaultArgs; } - void setVerifyUSRToDecl(bool flag) { - CurrentResults.verifyUSRToDecl = flag; - } - bool verifyUSRToDecl() const { - return CurrentResults.verifyUSRToDecl; - } + void setVerifyUSRToDecl(bool flag) { CurrentResults.verifyUSRToDecl = flag; } + bool verifyUSRToDecl() const { return CurrentResults.verifyUSRToDecl; } /// Allocate a string owned by the code completion context. StringRef copyString(StringRef Str) { diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index 0052442f953f9..57c90b9a5cca0 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -380,8 +380,8 @@ class ContextFreeCodeCompletionResult { NullTerminatedStringRef ModuleName; NullTerminatedStringRef BriefDocComment; ArrayRef AssociatedUSRs; - /// The Swift USR for a declaration (including for Clang declarations) used for looking up the \c Decl - /// instance for cached results. + /// The Swift USR for a declaration (including for Clang declarations) used + /// for looking up the \c Decl instance for cached results. NullTerminatedStringRef SwiftUSR; CodeCompletionResultType ResultType; @@ -415,8 +415,7 @@ class ContextFreeCodeCompletionResult { NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, ArrayRef AssociatedUSRs, - NullTerminatedStringRef SwiftUSR, - CodeCompletionResultType ResultType, + NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, NullTerminatedStringRef DiagnosticMessage, @@ -491,18 +490,16 @@ class ContextFreeCodeCompletionResult { /// \note The caller must ensure that the \p CompletionString and all /// \c StringRefs outlive this result, typically by storing them in the same /// \c CodeCompletionResultSink as the result itself. - static ContextFreeCodeCompletionResult * - createDeclResult(CodeCompletionResultSink &Sink, - CodeCompletionString *CompletionString, - const Decl *AssociatedDecl, - bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, - NullTerminatedStringRef BriefDocComment, - ArrayRef AssociatedUSRs, - NullTerminatedStringRef SwiftUSR, - CodeCompletionResultType ResultType, - ContextFreeNotRecommendedReason NotRecommended, - CodeCompletionDiagnosticSeverity DiagnosticSeverity, - NullTerminatedStringRef DiagnosticMessage); + static ContextFreeCodeCompletionResult *createDeclResult( + CodeCompletionResultSink &Sink, CodeCompletionString *CompletionString, + const Decl *AssociatedDecl, bool HasAsyncAlternative, + NullTerminatedStringRef ModuleName, + NullTerminatedStringRef BriefDocComment, + ArrayRef AssociatedUSRs, + NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, + ContextFreeNotRecommendedReason NotRecommended, + CodeCompletionDiagnosticSeverity DiagnosticSeverity, + NullTerminatedStringRef DiagnosticMessage); CodeCompletionResultKind getKind() const { return Kind; } @@ -545,7 +542,7 @@ class ContextFreeCodeCompletionResult { ArrayRef getAssociatedUSRs() const { return AssociatedUSRs; } - + NullTerminatedStringRef getSwiftUSR() const { return SwiftUSR; } const CodeCompletionResultType &getResultType() const { return ResultType; } @@ -602,8 +599,9 @@ class ContextFreeCodeCompletionResult { /// the completion's usage context. class CodeCompletionResult { const ContextFreeCodeCompletionResult &ContextFree; - /// Contains the associated declaration if fetched; if not, stores the ASTContext to use for finding the - /// associated declaration through the Swift USR. + /// Contains the associated declaration if fetched; if not, stores the + /// ASTContext to use for finding the associated declaration through the Swift + /// USR. mutable llvm::PointerUnion DeclOrCtx; SemanticContextKind SemanticContext : 3; static_assert(int(SemanticContextKind::MAX_VALUE) < 1 << 3, ""); @@ -758,7 +756,8 @@ class CodeCompletionResult { /// Prints the full documentation comment as XML to the provided \c OS stream. /// - /// \returns true if the result has a full documentation comment, false otherwise. + /// \returns true if the result has a full documentation comment, false + /// otherwise. bool printFullDocComment(raw_ostream &OS) const { if (auto *D = getAssociatedDecl()) return ide::getDocumentationCommentAsXML(D, OS); diff --git a/include/swift/IDE/CodeCompletionResultSink.h b/include/swift/IDE/CodeCompletionResultSink.h index e1e29d01cdc4f..714d98f9d3e20 100644 --- a/include/swift/IDE/CodeCompletionResultSink.h +++ b/include/swift/IDE/CodeCompletionResultSink.h @@ -40,7 +40,7 @@ struct CodeCompletionResultSink { /// Whether to include an item without any default arguments. bool addCallWithNoDefaultArgs = true; - + /// Whether to verify USR to \c Decl reconstruction during completion. bool verifyUSRToDecl = false; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 483fa730dc205..ed433b135922f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2380,7 +2380,7 @@ void ASTContext::addLoadedModule(ModuleDecl *M) { // For example, if '-module-alias Foo=Bar' is passed in to the frontend, // and a source file has 'import Foo', a module called Bar (real name) // will be loaded and added to the map. - + auto RealName = M->getRealName(); auto ABIName = M->getABIName(); diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 872953b0dfbea..a1ef80d45b346 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -27,20 +27,20 @@ #include "swift/AST/DeclNameExtractor.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/Module.h" -#include "swift/AST/NameLookup.h" #include "swift/AST/ModuleNameLookup.h" +#include "swift/AST/NameLookup.h" #include "swift/AST/NameLookupRequests.h" -#include "swift/AST/USRGeneration.h" #include "swift/AST/SILLayout.h" #include "swift/AST/Type.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/Types.h" +#include "swift/AST/USRGeneration.h" #include "swift/Basic/Assertions.h" #include "swift/Basic/Defer.h" #include "swift/Demangling/Demangler.h" #include "swift/Demangling/ManglingMacros.h" -#include "llvm/ADT/StringSwitch.h" #include "clang/Tooling/Refactor/USRFinder.h" +#include "llvm/ADT/StringSwitch.h" using namespace swift; @@ -56,7 +56,7 @@ Decl *swift::Demangle::getDeclForUSR(ASTContext &ctx, StringRef usr, auto node = Dem.demangleSymbolAsNode(mangling); ASTBuilder builder(ctx, genericSig); - + auto hasMatchingUSR = [usr](const ValueDecl *VD) { SmallString<128> candidateUSR; llvm::raw_svector_ostream OS(candidateUSR); @@ -108,27 +108,26 @@ TypeDecl *swift::Demangle::getTypeDeclForUSR(ASTContext &ctx, using ValueDeclPredicate = llvm::function_ref; -static Decl * -findTopLevelClangDecl(ClangModuleLoader *importer, DeclName name, - ValueDeclPredicate predicate) { +static Decl *findTopLevelClangDecl(ClangModuleLoader *importer, DeclName name, + ValueDeclPredicate predicate) { struct Consumer : VisibleDeclConsumer { ValueDecl *Result = nullptr; ValueDeclPredicate Predicate; - + explicit Consumer(ValueDeclPredicate Predicate) : Predicate(Predicate) {} - + void foundDecl(ValueDecl *decl, DeclVisibilityKind reason, DynamicLookupInfo dynamicLookupInfo = {}) override { if (Result != nullptr) return; - + if (Predicate(decl)) Result = decl; } } consumer(predicate); - + importer->lookupValue(name, consumer); - + return consumer.Result; } @@ -157,7 +156,7 @@ Decl *ASTBuilder::findDecl( // We should have arrived at a declaration node by now break; } - + DeclNameExtractor NameExtractor(Ctx); DeclName name; @@ -168,7 +167,7 @@ Decl *ASTBuilder::findDecl( auto contextNode = node->getFirstChild(); if (!contextNode) return nullptr; - + SmallVector candidates; if (contextNode->getKind() == Node::Kind::Module) { // If a foreign Clang module, perform lookup in Clang importer @@ -195,7 +194,7 @@ Decl *ASTBuilder::findDecl( module->lookupMember(candidates, DC, name, privateDiscriminator); } - + for (auto *candidate : candidates) { if (isMatchingValueDecl(candidate)) return candidate; @@ -392,7 +391,7 @@ Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor, auto moduleNode = findModuleNode(definingDecl); if (!moduleNode) return Type(); - + ModuleDecl *scratch; auto potentialParentModules = findPotentialModules(moduleNode, scratch); if (potentialParentModules.empty()) @@ -1330,15 +1329,15 @@ ASTBuilder::createTypeDecl(NodePointer node, llvm::ArrayRef ASTBuilder::findPotentialModules(NodePointer node, ModuleDecl *&scratch) { assert(node->getKind() == Demangle::Node::Kind::Module); - + const auto moduleName = node->getText(); - + if (moduleName == CLANG_HEADER_MODULE_NAME) { auto *importer = Ctx.getClangModuleLoader(); scratch = importer->getImportedHeaderModule(); return ArrayRef(&scratch, 1); } - + return Ctx.getModulesByRealOrABIName(moduleName); } @@ -1562,7 +1561,7 @@ ASTBuilder::findDeclContext(NodePointer node) { bool found = false; for (ModuleDecl *module : moduleDecls) { auto *extensionModule = ext->getParentModule(); - + if (extensionModule == module || extensionModule == module->getUnderlyingModuleIfOverlay()) { found = true; diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index c50e7fb9bfe90..6504fc0f7ca75 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -1,4 +1,5 @@ -//===--- DeclNameExtractor.cpp ----------------------------------------------------===// +//===--- DeclNameExtractor.cpp +//----------------------------------------------------===// // // This source file is part of the Swift.org open source project // @@ -14,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#include "swift/AST/ASTContext.h" #include "swift/AST/DeclNameExtractor.h" +#include "swift/AST/ASTContext.h" using namespace swift; using namespace Demangle; @@ -24,7 +25,7 @@ bool DeclNameExtractor::extractDeclName(Node *node, DeclName &name, Identifier &privateDiscriminator) { if (!node) return false; - + switch (node->getKind()) { case Node::Kind::Class: case Node::Kind::Structure: @@ -38,36 +39,34 @@ bool DeclNameExtractor::extractDeclName(Node *node, DeclName &name, case Node::Kind::Variable: case Node::Kind::Macro: return extractIdentifierName(node, name, privateDiscriminator); - + case Node::Kind::Constructor: case Node::Kind::Allocator: name = DeclName(DeclBaseName::createConstructor()); return true; - + case Node::Kind::Destructor: case Node::Kind::Deallocator: case Node::Kind::IsolatedDeallocator: name = DeclName(DeclBaseName::createDestructor()); return true; - + case Node::Kind::Module: name = extractTextName(node); return true; - + case Node::Kind::Function: case Node::Kind::Subscript: return extractFunctionLikeName(node, name, privateDiscriminator); - + default: // For any other node types, we can't extract a meaningful name return false; } - } -bool -DeclNameExtractor::extractIdentifierName(Node *node, DeclName &declName, - Identifier &privateDiscriminator) { +bool DeclNameExtractor::extractIdentifierName( + Node *node, DeclName &declName, Identifier &privateDiscriminator) { auto Identifier = node->getChild(1); if (!Identifier) return false; @@ -87,17 +86,16 @@ DeclNameExtractor::extractIdentifierName(Node *node, DeclName &declName, DeclName DeclNameExtractor::extractTextName(Node *node) { if (!node->hasText()) return DeclName(); - + auto identifier = getIdentifier(Ctx, node->getText()); return DeclName(identifier); } -bool -DeclNameExtractor::extractFunctionLikeName(Node *node, DeclName &declName, - Identifier &privateDiscriminator) { +bool DeclNameExtractor::extractFunctionLikeName( + Node *node, DeclName &declName, Identifier &privateDiscriminator) { assert(node->getKind() == Node::Kind::Function || node->getKind() == Node::Kind::Subscript); - + DeclBaseName BaseName; if (node->getKind() == Node::Kind::Function) { DeclName name; @@ -108,7 +106,7 @@ DeclNameExtractor::extractFunctionLikeName(Node *node, DeclName &declName, } else { BaseName = DeclBaseName::createSubscript(); } - + if (BaseName.empty()) return false; @@ -119,37 +117,38 @@ DeclNameExtractor::extractFunctionLikeName(Node *node, DeclName &declName, } else { LabelListIdx = 1; } - + auto *LabelsOrType = node->getChild(LabelListIdx); - assert(LabelsOrType != nullptr && (LabelsOrType->getKind() == Node::Kind::LabelList || - LabelsOrType->getKind() == Node::Kind::Type)); - + assert(LabelsOrType != nullptr && + (LabelsOrType->getKind() == Node::Kind::LabelList || + LabelsOrType->getKind() == Node::Kind::Type)); + SmallVector ArgLabels; if (LabelsOrType->getKind() == Node::Kind::LabelList) { extractArgLabelsFromLabelList(LabelsOrType, ArgLabels); } else { extractArgLabelsFromType(LabelsOrType, ArgLabels); } - + if (ArgLabels.empty()) { declName = DeclName(BaseName); return true; } - + declName = DeclName(Ctx, BaseName, ArgLabels); return true; } -void DeclNameExtractor::extractArgLabelsFromLabelList(Node *LabelList, - SmallVectorImpl &ArgLabels) { +void DeclNameExtractor::extractArgLabelsFromLabelList( + Node *LabelList, SmallVectorImpl &ArgLabels) { assert(LabelList->getKind() == Node::Kind::LabelList); - + for (unsigned i = 0; i < LabelList->getNumChildren(); ++i) { auto *Label = LabelList->getChild(i); - + assert(Label && (Label->getKind() == Node::Kind::Identifier || Label->getKind() == Node::Kind::FirstElementMarker)); - + if (Label->getKind() == Node::Kind::Identifier) { ArgLabels.push_back(getIdentifier(Ctx, Label->getText())); } else { @@ -158,29 +157,30 @@ void DeclNameExtractor::extractArgLabelsFromLabelList(Node *LabelList, } } -void DeclNameExtractor::extractArgLabelsFromType(Node *Type, SmallVectorImpl &ArgLabels) { +void DeclNameExtractor::extractArgLabelsFromType( + Node *Type, SmallVectorImpl &ArgLabels) { auto ArgTuple = Type->findByKind(Demangle::Node::Kind::ArgumentTuple, /*maxDepth=*/5); if (ArgTuple == nullptr) return; - + auto Params = ArgTuple->getFirstChild(); auto ParamsType = Params->getFirstChild(); if (ParamsType == nullptr) return; - + if (ParamsType->getKind() != Demangle::Node::Kind::Tuple) { // A single, unnamed parameter ArgLabels.push_back(Identifier()); return; } - + // More than one parameter are present while (Params && Params->getFirstChild() && Params->getFirstChild()->getKind() != Node::Kind::TupleElement) { Params = Params->getFirstChild(); } - + if (Params) { for (size_t i = 0; i < Params->getNumChildren(); ++i) { ArgLabels.push_back(Identifier()); @@ -221,12 +221,12 @@ bool swift::Demangle::extractNameNodeInfo(ASTContext &Ctx, Node *node, case Demangle::Node::Kind::Identifier: name = node->getText(); return true; - + case Demangle::Node::Kind::PrivateDeclName: name = node->getChild(1)->getText(); privateDiscriminator = getIdentifier(Ctx, node->getChild(0)->getText()); return true; - + case Demangle::Node::Kind::RelatedEntityDeclName: name = node->getChild(1)->getText(); relatedEntityKind = node->getFirstChild()->getText(); diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 5a80a3458b632..bfa0811322dcd 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -256,7 +256,7 @@ std::optional swift::ClangUSRGenerationRequest::evaluate( return std::string(OS.str()); } } - + return std::nullopt; } @@ -299,8 +299,7 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, ValueDecl *D, if (!D->hasName() && !isa(D) && !isa(D)) return std::string(); // Ignore. - if (D->getModuleContext()->isBuiltinModule() && - !isa(D)) + if (D->getModuleContext()->isBuiltinModule() && !isa(D)) return std::string(); // Ignore. if (isa(D)) return std::string(); // Ignore. diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp index 8c260bd8ace31..f41299780b820 100644 --- a/lib/IDE/CodeCompletionCache.cpp +++ b/lib/IDE/CodeCompletionCache.cpp @@ -269,8 +269,8 @@ static bool readCachedModule(llvm::MemoryBuffer *in, ContextFreeCodeCompletionResult *result = new (*V.Allocator) ContextFreeCodeCompletionResult( - kind, associatedKind, opKind, roles, isSystem, - hasAsyncAlternative, string, moduleName, briefDocComment, + kind, associatedKind, opKind, roles, isSystem, hasAsyncAlternative, + string, moduleName, briefDocComment, llvm::ArrayRef(assocUSRs).copy(*V.Allocator), swiftUSR, CodeCompletionResultType(resultTypes), notRecommended, diagSeverity, diagMessage, filterName, nameForDiagnostics); diff --git a/lib/IDE/CodeCompletionResult.cpp b/lib/IDE/CodeCompletionResult.cpp index e775a698f00cb..c5ed4323b90b2 100644 --- a/lib/IDE/CodeCompletionResult.cpp +++ b/lib/IDE/CodeCompletionResult.cpp @@ -153,8 +153,8 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( } return new (Sink.getAllocator()) ContextFreeCodeCompletionResult( Kind, /*AssociatedKind=*/0, KnownOperatorKind, /*MacroRoles=*/{}, - /*IsSystem=*/false, /*HasAsyncAlternative=*/false, - CompletionString, /*ModuleName=*/"", BriefDocComment, + /*IsSystem=*/false, /*HasAsyncAlternative=*/false, CompletionString, + /*ModuleName=*/"", BriefDocComment, /*AssociatedUSRs=*/{}, /*SwiftUSR=*/"", ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), @@ -192,8 +192,8 @@ ContextFreeCodeCompletionResult::createLiteralResult( return new (Sink.getAllocator()) ContextFreeCodeCompletionResult( CodeCompletionResultKind::Literal, static_cast(LiteralKind), CodeCompletionOperatorKind::None, /*MacroRoles=*/{}, - /*IsSystem=*/false, /*HasAsyncAlternative=*/false, - CompletionString, /*ModuleName=*/"", /*BriefDocComment=*/"", + /*IsSystem=*/false, /*HasAsyncAlternative=*/false, CompletionString, + /*ModuleName=*/"", /*BriefDocComment=*/"", /*AssociatedUSRs=*/{}, /*SwiftUSR=*/"", ResultType, ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/"", @@ -222,8 +222,7 @@ ContextFreeCodeCompletionResult::createDeclResult( const Decl *AssociatedDecl, bool HasAsyncAlternative, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, ArrayRef AssociatedUSRs, - NullTerminatedStringRef SwiftUSR, - CodeCompletionResultType ResultType, + NullTerminatedStringRef SwiftUSR, CodeCompletionResultType ResultType, ContextFreeNotRecommendedReason NotRecommended, CodeCompletionDiagnosticSeverity DiagnosticSeverity, NullTerminatedStringRef DiagnosticMessage) { @@ -235,9 +234,9 @@ ContextFreeCodeCompletionResult::createDeclResult( CodeCompletionResultKind::Declaration, static_cast(getCodeCompletionDeclKind(AssociatedDecl)), CodeCompletionOperatorKind::None, getCompletionMacroRoles(AssociatedDecl), - getDeclIsSystem(AssociatedDecl), HasAsyncAlternative, - CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, SwiftUSR, - ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, + getDeclIsSystem(AssociatedDecl), HasAsyncAlternative, CompletionString, + ModuleName, BriefDocComment, AssociatedUSRs, SwiftUSR, ResultType, + NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), /*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink)); } @@ -445,7 +444,7 @@ const Decl *CodeCompletionResult::getAssociatedDecl() const { DeclOrCtx = Demangle::getDeclForUSR(*Ctx, SwiftUSR); } - + return DeclOrCtx.dyn_cast(); } @@ -453,9 +452,8 @@ CodeCompletionResult * CodeCompletionResult::withFlair(CodeCompletionFlair NewFlair, CodeCompletionResultSink &Sink) const { return new (*Sink.Allocator) - CodeCompletionResult(ContextFree, DeclOrCtx, SemanticContext, - NewFlair, NumBytesToErase, TypeDistance, - NotRecommended); + CodeCompletionResult(ContextFree, DeclOrCtx, SemanticContext, NewFlair, + NumBytesToErase, TypeDistance, NotRecommended); } CodeCompletionResult * @@ -463,10 +461,9 @@ CodeCompletionResult::withContextFreeResultSemanticContextAndFlair( const ContextFreeCodeCompletionResult &NewContextFree, SemanticContextKind NewSemanticContext, CodeCompletionFlair NewFlair, CodeCompletionResultSink &Sink) const { - return new (*Sink.Allocator) - CodeCompletionResult(NewContextFree, DeclOrCtx, NewSemanticContext, - NewFlair, NumBytesToErase, TypeDistance, - NotRecommended); + return new (*Sink.Allocator) CodeCompletionResult( + NewContextFree, DeclOrCtx, NewSemanticContext, NewFlair, NumBytesToErase, + TypeDistance, NotRecommended); } std::pair diff --git a/lib/IDE/CodeCompletionResultBuilder.cpp b/lib/IDE/CodeCompletionResultBuilder.cpp index 4eea55e379e70..846b835f41fa7 100644 --- a/lib/IDE/CodeCompletionResultBuilder.cpp +++ b/lib/IDE/CodeCompletionResultBuilder.cpp @@ -18,8 +18,8 @@ #include "swift/Basic/Assertions.h" #include "swift/Basic/LLVM.h" #include "swift/IDE/CodeCompletionStringPrinter.h" -#include "swift/IDE/Utils.h" #include "swift/IDE/CommentConversion.h" +#include "swift/IDE/Utils.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Comment.h" #include "clang/Basic/Module.h" @@ -82,8 +82,8 @@ copyAssociatedUSRs(llvm::BumpPtrAllocator &Allocator, const Decl *D) { return {}; } -static NullTerminatedStringRef -copySwiftUSR(llvm::BumpPtrAllocator &Allocator, const Decl *D) { +static NullTerminatedStringRef copySwiftUSR(llvm::BumpPtrAllocator &Allocator, + const Decl *D) { auto *VD = dyn_cast(D); if (!VD || !shouldCopyAssociatedUSRForDecl(VD)) return NullTerminatedStringRef(); @@ -101,15 +101,16 @@ void CodeCompletionResultBuilder::addChunkWithText( addChunkWithTextNoCopy(Kind, Text.copy(*Sink.Allocator)); } -/// Tries to reconstruct the provided \p D declaration using \c Demangle::getDeclForUSR and verifies -/// that the declarations match. -/// This only works if \p D is a \c ValueDecl and \c shouldCopyAssociatedUSRForDecl is true. +/// Tries to reconstruct the provided \p D declaration using \c +/// Demangle::getDeclForUSR and verifies that the declarations match. This only +/// works if \p D is a \c ValueDecl and \c shouldCopyAssociatedUSRForDecl is +/// true. /// /// This is intended for testing only. static void verifyUSRToDeclReconstruction(const Decl *D) { auto *VD = dyn_cast(D); if (!VD) - return; + return; if (!shouldCopyAssociatedUSRForDecl(VD)) return; @@ -291,7 +292,7 @@ void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) { else if (D->getSoftDeprecatedAttr()) setContextFreeNotRecommended( ContextFreeNotRecommendedReason::SoftDeprecated); - + if (D->getClangNode()) { if (auto *ClangD = D->getClangDecl()) { const auto &ClangContext = ClangD->getASTContext(); diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index 3a62106c6ffac..89f716419fe88 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -1157,11 +1157,10 @@ Completion *CompletionBuilder::finish() { contextFreeBase.getKind(), contextFreeBase.getOpaqueAssociatedKind(), opKind, contextFreeBase.getMacroRoles(), contextFreeBase.isSystem(), - contextFreeBase.hasAsyncAlternative(), - newCompletionString, contextFreeBase.getModuleName(), + contextFreeBase.hasAsyncAlternative(), newCompletionString, + contextFreeBase.getModuleName(), contextFreeBase.getBriefDocComment(), - contextFreeBase.getAssociatedUSRs(), - contextFreeBase.getSwiftUSR(), + contextFreeBase.getAssociatedUSRs(), contextFreeBase.getSwiftUSR(), contextFreeBase.getResultType(), contextFreeBase.getNotRecommendedReason(), contextFreeBase.getDiagnosticSeverity(), diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index b0e5e92cf9d4c..cee158f8a8b1c 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -68,7 +68,8 @@ struct SwiftToSourceKitCompletionAdapter { static bool handleResult(SourceKit::CodeCompletionConsumer &consumer, Completion *result, bool leadingPunctuation, bool legacyLiteralToKeyword, - bool annotatedDescription, bool includeFullDocumentation); + bool annotatedDescription, + bool includeFullDocumentation); static void getResultAssociatedUSRs(ArrayRef AssocUSRs, @@ -170,8 +171,9 @@ deliverCodeCompleteResults(SourceKit::CodeCompletionConsumer &SKConsumer, continue; } } - if (!SwiftToSourceKitCompletionAdapter::handleResult(SKConsumer, Result, - CCOpts.annotatedDescription, CCOpts.includeFullDocumentation)) + if (!SwiftToSourceKitCompletionAdapter::handleResult( + SKConsumer, Result, CCOpts.annotatedDescription, + CCOpts.includeFullDocumentation)) break; } @@ -490,7 +492,8 @@ bool SwiftToSourceKitCompletionAdapter::handleResult( Result->printFullDocComment(ccOS); } unsigned DocFullEnd = SS.size(); - Info.DocFull = StringRef(SS.begin() + DocFullBegin, DocFullEnd - DocFullBegin); + Info.DocFull = + StringRef(SS.begin() + DocFullBegin, DocFullEnd - DocFullBegin); } else { Info.DocFull = StringRef(); } @@ -738,7 +741,8 @@ static void translateCodeCompletionOptions(OptionsDictionary &from, static UIdent KeyAddInnerOperators("key.codecomplete.addinneroperators"); static UIdent KeyAddInitsToTopLevel("key.codecomplete.addinitstotoplevel"); static UIdent KeyFuzzyMatching("key.codecomplete.fuzzymatching"); - static UIdent KeyIncludeFullDocumentation("key.codecomplete.includefulldocumentation"); + static UIdent KeyIncludeFullDocumentation( + "key.codecomplete.includefulldocumentation"); static UIdent KeyTopNonLiteral("key.codecomplete.showtopnonliteralresults"); static UIdent KeyContextWeight("key.codecomplete.sort.contextweight"); static UIdent KeyFuzzyWeight("key.codecomplete.sort.fuzzyweight"); @@ -929,8 +933,7 @@ static void transformAndForwardResults( ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( innerSink.swiftSink, CodeCompletionResultKind::BuiltinOperator, completionString, CodeCompletionOperatorKind::None, - /*BriefDocComment=*/"", - CodeCompletionResultType::notApplicable(), + /*BriefDocComment=*/"", CodeCompletionResultType::notApplicable(), ContextFreeNotRecommendedReason::None, CodeCompletionDiagnosticSeverity::None, /*DiagnosticMessage=*/""); diff --git a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp index ec36a87f92671..1922311978386 100644 --- a/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp +++ b/tools/SourceKit/tools/sourcekitd-test/sourcekitd-test.cpp @@ -735,7 +735,8 @@ static int handleTestInvocation(TestOptions Opts, TestOptions &InitOpts) { // Default to sort by name. Opts.RequestOptions.insert(Opts.RequestOptions.begin(), "sort.byname=1"); // Default to verifying USR to Decl conversion to cover many use cases - Opts.RequestOptions.insert(Opts.RequestOptions.begin(), "verifyusrtodecl=1"); + Opts.RequestOptions.insert(Opts.RequestOptions.begin(), + "verifyusrtodecl=1"); addRequestOptions(Req, Opts, KeyCodeCompleteOptions, "key.codecomplete."); break; diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index a9263ee048701..58d1b6643f923 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -1356,10 +1356,10 @@ static void printCodeCompletionResultsImpl( if (!BriefComment.empty()) { OS << "; briefcomment=" << BriefComment; } - + SmallString<256> FullComment; llvm::raw_svector_ostream CommentOS(FullComment); - + if (Result->printFullDocComment(CommentOS) && !FullComment.empty()) OS << "; fullcomment=" << FullComment; } From 732cc766509754942316dbf7c810c9bd255c106d Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 21 Jul 2025 01:31:43 +0300 Subject: [PATCH 39/58] [IDE] NFC: Add doc comment for on-demand CodeCompletionResult::getAssociatedDecl --- include/swift/IDE/CodeCompletionResult.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index 57c90b9a5cca0..b1c60b0b5fe35 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -727,6 +727,7 @@ class CodeCompletionResult { } } + /// Finds the associated declaration on-demand and caches it. const Decl *getAssociatedDecl() const; SemanticContextKind getSemanticContext() const { return SemanticContext; } From f224f3967f0193cc6e73594222c5e3f8784e7645 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 21 Jul 2025 21:24:53 +0300 Subject: [PATCH 40/58] [IDE] Use response scratch in swiftide_completion_item_get_doc_full --- .../bin/InProc/CodeCompletionSwiftInterop.cpp | 13 +++++++------ .../bin/InProc/CodeCompletionSwiftInterop.h | 6 +++--- .../bin/InProc/sourcekitdInProc-darwin.exports | 2 +- .../sourcekitd/bin/InProc/sourcekitdInProc.exports | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp index 8c3f9a7ce3e29..ef8b2e0a57e07 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -663,21 +663,22 @@ void swiftide_completion_item_get_doc_brief( handler(item.getBriefDocComment().data()); } -void swiftide_completion_item_get_doc_full_copy( +void swiftide_completion_item_get_doc_full( swiftide_completion_response_t _response, swiftide_completion_item_t _item, - void (^handler)(char *)) { + void (^handler)(const char *)) { + auto &response = *static_cast(_response); auto &item = *static_cast(_item); - llvm::SmallString<128> buffer; + response.scratch.clear(); { - llvm::raw_svector_ostream OS(buffer); + llvm::raw_svector_ostream OS(response.scratch); item.printFullDocComment(OS); } - if (buffer.empty()) { + if (response.scratch.empty()) { return handler(nullptr); } - handler(strdup(buffer.c_str())); + handler(response.scratch.c_str()); } void swiftide_completion_item_get_associated_usrs( diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h index fd3477d7f0c55..d8abbed279f50 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h @@ -348,9 +348,9 @@ swiftide_completion_item_get_doc_brief(swiftide_completion_response_t, void (^handler)(const char *)); SWIFTIDE_PUBLIC void -swiftide_completion_item_get_doc_full_copy(swiftide_completion_response_t, - swiftide_completion_item_t, - void (^handler)(char *)); +swiftide_completion_item_get_doc_full(swiftide_completion_response_t, + swiftide_completion_item_t, + void (^handler)(const char *)); SWIFTIDE_PUBLIC void swiftide_completion_item_get_associated_usrs( swiftide_completion_response_t, swiftide_completion_item_t, diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports index 22ffcbcd1901c..ddad2c46cafdf 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports @@ -149,7 +149,7 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief -swiftide_completion_item_get_doc_full_copy +swiftide_completion_item_get_doc_full swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports index 05d562cf5bcfa..928e08b49afd0 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports @@ -149,7 +149,7 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief -swiftide_completion_item_get_doc_full_copy +swiftide_completion_item_get_doc_full swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label From 2994fc08dc104387665508f293c8b426949308d7 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 21 Jul 2025 21:49:51 +0300 Subject: [PATCH 41/58] [USR] Remove unneeded code in USR to Decl conversion --- include/swift/AST/ASTDemangler.h | 3 +-- include/swift/AST/TypeCheckRequests.h | 4 ---- lib/AST/ASTDemangler.cpp | 3 +-- lib/AST/DeclNameExtractor.cpp | 12 +----------- 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h index d319a48b7ea1b..3218d5ed448b2 100644 --- a/include/swift/AST/ASTDemangler.h +++ b/include/swift/AST/ASTDemangler.h @@ -133,8 +133,7 @@ class ASTBuilder { /// for which \c isMatchingValueDecl returns true. /// /// \note \p isMatchingValueDecl is not evaluated for type declarations, it's - /// only used to choose - /// among lookup results when \c createTypeDecl fails. + /// only used to choose among lookup results when \c createTypeDecl fails. Decl * findDecl(NodePointer node, llvm::function_ref isMatchingValueDecl); diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 4e4ec9c69f87a..c9a6536e4213f 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -872,10 +872,6 @@ class USRGenerationRequest // Evaluation. std::string evaluate(Evaluator &eval, ValueDecl *d, USRGenerationOptions options) const; - -public: - // No caching - this forwards to other requests - bool isCached() const { return false; } }; /// Generate the mangling for the given local type declaration. diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index a1ef80d45b346..b7900ee2723da 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -150,7 +150,6 @@ Decl *ASTBuilder::findDecl( case Node::Kind::BoundGenericStructure: case Node::Kind::BoundGenericTypeAlias: case Node::Kind::BoundGenericOtherNominalType: - case Node::Kind::Extension: return findDecl(node->getFirstChild(), isMatchingValueDecl); default: // We should have arrived at a declaration node by now @@ -171,7 +170,7 @@ Decl *ASTBuilder::findDecl( SmallVector candidates; if (contextNode->getKind() == Node::Kind::Module) { // If a foreign Clang module, perform lookup in Clang importer - if (auto kind = getForeignModuleKind(contextNode)) { + if (getForeignModuleKind(contextNode)) { auto *importer = Ctx.getClangModuleLoader(); return findTopLevelClangDecl(importer, name, isMatchingValueDecl); } diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index 6504fc0f7ca75..383e6545f4995 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -1,5 +1,4 @@ -//===--- DeclNameExtractor.cpp -//----------------------------------------------------===// +//===--- DeclNameExtractor.cpp --------------------------------------------===// // // This source file is part of the Swift.org open source project // @@ -51,10 +50,6 @@ bool DeclNameExtractor::extractDeclName(Node *node, DeclName &name, name = DeclName(DeclBaseName::createDestructor()); return true; - case Node::Kind::Module: - name = extractTextName(node); - return true; - case Node::Kind::Function: case Node::Kind::Subscript: return extractFunctionLikeName(node, name, privateDiscriminator); @@ -176,11 +171,6 @@ void DeclNameExtractor::extractArgLabelsFromType( } // More than one parameter are present - while (Params && Params->getFirstChild() && - Params->getFirstChild()->getKind() != Node::Kind::TupleElement) { - Params = Params->getFirstChild(); - } - if (Params) { for (size_t i = 0; i < Params->getNumChildren(); ++i) { ArgLabels.push_back(Identifier()); From 8d5f74bb666fc2b709edb6405a0472b0f68ed3d2 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 21 Jul 2025 21:50:10 +0300 Subject: [PATCH 42/58] [Test] Don't print brief comment in diagnostics in swift-ide-test --- tools/swift-ide-test/swift-ide-test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 58d1b6643f923..b5ed42a18ff87 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -1371,7 +1371,7 @@ static void printCodeCompletionResultsImpl( Result->getDiagnosticSeverityAndMessage(Scratch, *Ctx); if (DiagSeverityAndMessage.first != CodeCompletionDiagnosticSeverity::None) { - OS << "; diagnostics=" << BriefComment; + OS << "; diagnostics="; switch (DiagSeverityAndMessage.first) { case CodeCompletionDiagnosticSeverity::Error: OS << "error"; From afda1cf715326e7531fdb8ed17700b620003c388 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 15:05:03 +0300 Subject: [PATCH 43/58] [USR] Move distinguishSynthesizedDecls check from ClangUSRGenerationRequest to USRGenerationRequest --- include/swift/AST/TypeCheckRequests.h | 106 ++++++++------------ include/swift/AST/TypeCheckerTypeIDZone.def | 6 +- lib/AST/USRGeneration.cpp | 103 +++++++++---------- lib/PrintAsClang/ClangSyntaxPrinter.cpp | 3 +- 4 files changed, 92 insertions(+), 126 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index c9a6536e4213f..4c343c58c6816 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -757,69 +757,11 @@ class RequirementRequest : bool isCached() const; }; -struct USRGenerationOptions { - /// @brief Whether to emit USRs using the Swift declaration when it is - /// synthesized from a Clang based declaration. Useful in cases where Swift - /// declarations are synthesized from Clang nodes but the caller actually - /// wants the USR of the Swift declaration. - bool distinguishSynthesizedDecls; - - /// @brief Whether to emit USRs using the Swift declaration for all - /// declarations specifically, emits a Swift USR for all Clang-based - /// declarations. - bool useSwiftUSR; - - friend llvm::hash_code hash_value(const USRGenerationOptions &options) { - return llvm::hash_combine( - llvm::hash_value(options.distinguishSynthesizedDecls), - llvm::hash_value(options.useSwiftUSR)); - } - - friend bool operator==(const USRGenerationOptions &lhs, - const USRGenerationOptions &rhs) { - return lhs.distinguishSynthesizedDecls == rhs.distinguishSynthesizedDecls && - lhs.useSwiftUSR == rhs.useSwiftUSR; - } - - friend bool operator!=(const USRGenerationOptions &lhs, - const USRGenerationOptions &rhs) { - return !(lhs == rhs); - } -}; - -void simple_display(llvm::raw_ostream &out, - const USRGenerationOptions &options); - -struct ClangUSRGenerationOptions { - /// @brief Whether to emit USRs using the Swift declaration when it is - /// synthesized from a Clang based declaration. Useful in cases where Swift - /// declarations are synthesized from Clang nodes but the caller actually - /// wants the USR of the Swift declaration. - bool distinguishSynthesizedDecls; - - friend llvm::hash_code hash_value(const ClangUSRGenerationOptions &options) { - return llvm::hash_value(options.distinguishSynthesizedDecls); - } - - friend bool operator==(const ClangUSRGenerationOptions &lhs, - const ClangUSRGenerationOptions &rhs) { - return lhs.distinguishSynthesizedDecls == rhs.distinguishSynthesizedDecls; - } - - friend bool operator!=(const ClangUSRGenerationOptions &lhs, - const ClangUSRGenerationOptions &rhs) { - return !(lhs == rhs); - } -}; - -void simple_display(llvm::raw_ostream &out, - const ClangUSRGenerationOptions &options); - /// Generate the Clang USR for the given declaration. class ClangUSRGenerationRequest : public SimpleRequest< ClangUSRGenerationRequest, - std::optional(ValueDecl *, ClangUSRGenerationOptions), + std::optional(const ValueDecl *), RequestFlags::SeparatelyCached | RequestFlags::SplitCached> { public: using SimpleRequest::SimpleRequest; @@ -828,8 +770,8 @@ class ClangUSRGenerationRequest friend SimpleRequest; // Evaluation. - std::optional evaluate(Evaluator &eval, ValueDecl *d, - ClangUSRGenerationOptions options) const; + std::optional evaluate(Evaluator &eval, + const ValueDecl *d) const; public: // Split caching. @@ -840,7 +782,8 @@ class ClangUSRGenerationRequest /// Generate the Swift USR for the given declaration. class SwiftUSRGenerationRequest - : public SimpleRequest { public: using SimpleRequest::SimpleRequest; @@ -849,19 +792,52 @@ class SwiftUSRGenerationRequest friend SimpleRequest; // Evaluation. - std::string evaluate(Evaluator &eval, ValueDecl *d) const; + std::string evaluate(Evaluator &eval, const ValueDecl *d) const; public: // Caching bool isCached() const { return true; } }; +struct USRGenerationOptions { + /// @brief Whether to emit USRs using the Swift declaration when it is + /// synthesized from a Clang based declaration. Useful in cases where Swift + /// declarations are synthesized from Clang nodes but the caller actually + /// wants the USR of the Swift declaration. + bool distinguishSynthesizedDecls; + + /// @brief Whether to emit USRs using the Swift declaration for all + /// declarations specifically, emits a Swift USR for all Clang-based + /// declarations. + bool useSwiftUSR; + + friend llvm::hash_code hash_value(const USRGenerationOptions &options) { + return llvm::hash_combine( + llvm::hash_value(options.distinguishSynthesizedDecls), + llvm::hash_value(options.useSwiftUSR)); + } + + friend bool operator==(const USRGenerationOptions &lhs, + const USRGenerationOptions &rhs) { + return lhs.distinguishSynthesizedDecls == rhs.distinguishSynthesizedDecls && + lhs.useSwiftUSR == rhs.useSwiftUSR; + } + + friend bool operator!=(const USRGenerationOptions &lhs, + const USRGenerationOptions &rhs) { + return !(lhs == rhs); + } +}; + +void simple_display(llvm::raw_ostream &out, + const USRGenerationOptions &options); + /// Generate the USR for the given declaration. /// This is an umbrella request that forwards to ClangUSRGenerationRequest or /// SwiftUSRGenerationRequest. class USRGenerationRequest : public SimpleRequest { public: using SimpleRequest::SimpleRequest; @@ -870,7 +846,7 @@ class USRGenerationRequest friend SimpleRequest; // Evaluation. - std::string evaluate(Evaluator &eval, ValueDecl *d, + std::string evaluate(Evaluator &eval, const ValueDecl *d, USRGenerationOptions options) const; }; diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index e2464b60aff7a..83183db3af37d 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -365,13 +365,13 @@ SWIFT_REQUEST(TypeChecker, TypeCheckASTNodeAtLocRequest, SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *), SeparatelyCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, ClangUSRGenerationRequest, - std::optional(ValueDecl *, ClangUSRGenerationOptions), + std::optional(const ValueDecl *), SeparatelyCached | SplitCached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, SwiftUSRGenerationRequest, - std::string(ValueDecl *), + std::string(const ValueDecl *), Cached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, USRGenerationRequest, - std::string(ValueDecl *, USRGenerationOptions), + std::string(const ValueDecl *, USRGenerationOptions), Uncached, NoLocationInfo) SWIFT_REQUEST(TypeChecker, IsABICompatibleOverrideRequest, bool(ValueDecl *), Cached, NoLocationInfo) diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index bfa0811322dcd..2d84a22780d07 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -177,56 +177,13 @@ void swift::simple_display(llvm::raw_ostream &out, << ", useSwiftUSR: " << options.useSwiftUSR << ")"; } -void swift::simple_display(llvm::raw_ostream &out, - const ClangUSRGenerationOptions &options) { - out << "ClangUSRGenerationOptions (distinguishSynthesizedDecls: " - << options.distinguishSynthesizedDecls << ")"; -} - std::optional swift::ClangUSRGenerationRequest::evaluate( - Evaluator &evaluator, ValueDecl *D, - ClangUSRGenerationOptions options) const { - auto interpretAsClangNode = [&options](const ValueDecl *D) -> ClangNode { - auto *importer = D->getASTContext().getClangModuleLoader(); - ClangNode ClangN = importer->getEffectiveClangNode(D); - if (auto ClangD = ClangN.getAsDecl()) { - // NSErrorDomain causes the clang enum to be imported like this: - // - // struct MyError { - // enum Code : Int32 { - // case errFirst - // case errSecond - // } - // static var errFirst: MyError.Code { get } - // static var errSecond: MyError.Code { get } - // } - // - // The clang enum constants are associated with both the static vars and - // the enum cases. - // But we want unique USRs for the above symbols, so use the clang USR - // for the enum cases, and the Swift USR for the vars. - // - if (!options.distinguishSynthesizedDecls) { - return ClangN; - } - if (auto *ClangEnumConst = dyn_cast(ClangD)) { - if (auto *ClangEnum = - dyn_cast(ClangEnumConst->getDeclContext())) { - if (ClangEnum->hasAttr() && isa(D)) - return ClangNode(); - } - } - if (D->getAttrs().hasAttribute()) { - return ClangNode(); - } - } - return ClangN; - }; - + Evaluator &evaluator, const ValueDecl *D) const { llvm::SmallString<128> Buffer; llvm::raw_svector_ostream OS(Buffer); - if (ClangNode ClangN = interpretAsClangNode(D)) { + auto *importer = D->getASTContext().getClangModuleLoader(); + if (ClangNode ClangN = importer->getEffectiveClangNode(D)) { if (auto ClangD = ClangN.getAsDecl()) { bool Ignore = clang::index::generateUSRForDecl(ClangD, Buffer); if (!Ignore) { @@ -273,14 +230,14 @@ void swift::ClangUSRGenerationRequest::cacheResult( std::optional result) const { auto *decl = std::get<0>(getStorage()); if (!result) { - decl->LazySemanticInfo.noClangUSR = 1; + const_cast(decl)->LazySemanticInfo.noClangUSR = 1; return; } decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result)); } std::string swift::SwiftUSRGenerationRequest::evaluate(Evaluator &evaluator, - ValueDecl *D) const { + const ValueDecl *D) const { auto declIFaceTy = D->getInterfaceType(); // Invalid code. @@ -292,7 +249,7 @@ std::string swift::SwiftUSRGenerationRequest::evaluate(Evaluator &evaluator, } std::string -swift::USRGenerationRequest::evaluate(Evaluator &evaluator, ValueDecl *D, +swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, USRGenerationOptions options) const { if (auto *VD = dyn_cast(D)) D = VD->getCanonicalVarDecl(); @@ -303,12 +260,47 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, ValueDecl *D, return std::string(); // Ignore. if (isa(D)) return std::string(); // Ignore. + + /// Checks whether \p D is a synthesized Clang declaration that should have a Swift USR. + auto isSynthesizedDeclWithSwiftUSR = [](const ValueDecl *D) -> bool { + auto *importer = D->getASTContext().getClangModuleLoader(); + ClangNode ClangN = importer->getEffectiveClangNode(D); + if (auto ClangD = ClangN.getAsDecl()) { + // NSErrorDomain causes the clang enum to be imported like this: + // + // struct MyError { + // enum Code : Int32 { + // case errFirst + // case errSecond + // } + // static var errFirst: MyError.Code { get } + // static var errSecond: MyError.Code { get } + // } + // + // The clang enum constants are associated with both the static vars and + // the enum cases. + // But we want unique USRs for the above symbols, so use the clang USR + // for the enum cases, and the Swift USR for the vars. + // + if (auto *ClangEnumConst = dyn_cast(ClangD)) { + if (auto *ClangEnum = + dyn_cast(ClangEnumConst->getDeclContext())) { + if (ClangEnum->hasAttr() && isa(D)) + return true; + } + } + if (D->getAttrs().hasAttribute()) { + return true; + } + } + return false; + }; - if (!options.useSwiftUSR) { - if (auto clangUSR = evaluateOrDefault( - evaluator, - ClangUSRGenerationRequest{D, {options.distinguishSynthesizedDecls}}, - std::nullopt)) { + if (!options.useSwiftUSR && (!options.distinguishSynthesizedDecls || + !isSynthesizedDeclWithSwiftUSR(D))) { + if (auto clangUSR = evaluateOrDefault(evaluator, + ClangUSRGenerationRequest{D}, + std::nullopt)) { return clangUSR.value(); } } @@ -355,8 +347,7 @@ bool ide::printValueDeclUSR(const ValueDecl *D, raw_ostream &OS, bool useSwiftUSR) { auto result = evaluateOrDefault( D->getASTContext().evaluator, - USRGenerationRequest{const_cast(D), - {distinguishSynthesizedDecls, useSwiftUSR}}, + USRGenerationRequest{D, {distinguishSynthesizedDecls, useSwiftUSR}}, std::string()); if (result.empty()) return true; diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.cpp b/lib/PrintAsClang/ClangSyntaxPrinter.cpp index 17820ea03cba8..c7af448606521 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.cpp +++ b/lib/PrintAsClang/ClangSyntaxPrinter.cpp @@ -489,8 +489,7 @@ void ClangSyntaxPrinter::printSymbolUSRAttribute(const ValueDecl *D) const { return; } auto result = evaluateOrDefault( - D->getASTContext().evaluator, - USRGenerationRequest{const_cast(D), {}}, std::string()); + D->getASTContext().evaluator, USRGenerationRequest{D, {}}, std::string()); if (result.empty()) return; os << " SWIFT_SYMBOL(\"" << result << "\")"; From 5fe8274a537db051cf0749fc46530a90d791c0d4 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 15:06:01 +0300 Subject: [PATCH 44/58] [Demangle] Simplify DeclNameExtractor::extractArgLabelsFromType multiple parameters case --- lib/AST/DeclNameExtractor.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index 383e6545f4995..1d32e683cbccb 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -171,10 +171,10 @@ void DeclNameExtractor::extractArgLabelsFromType( } // More than one parameter are present - if (Params) { - for (size_t i = 0; i < Params->getNumChildren(); ++i) { - ArgLabels.push_back(Identifier()); - } + for (size_t i = 0; i < ParamsType->getNumChildren(); ++i) { + assert(ParamsType->getChild(i)->getKind() == Node::Kind::TupleElement && + "Expected a TupleElement"); + ArgLabels.push_back(Identifier()); } } From 6bbe2a59bd013770f72fb1daa66af7f38331bb70 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 15:43:55 +0300 Subject: [PATCH 45/58] [IDE] Remove includeFullDocumentation option in code complete request --- .../include/SourceKit/Core/LangSupport.h | 1 - .../lib/SwiftLang/CodeCompletionOrganizer.h | 1 - .../lib/SwiftLang/SwiftCompletion.cpp | 33 ++++--------------- .../sourcekitd/CodeCompletionResultsArray.h | 1 - .../lib/API/CodeCompletionResultsArray.cpp | 18 +++------- .../tools/sourcekitd/lib/Service/Requests.cpp | 6 ---- 6 files changed, 11 insertions(+), 49 deletions(-) diff --git a/tools/SourceKit/include/SourceKit/Core/LangSupport.h b/tools/SourceKit/include/SourceKit/Core/LangSupport.h index 2213d0d1f8cba..4aa616c391394 100644 --- a/tools/SourceKit/include/SourceKit/Core/LangSupport.h +++ b/tools/SourceKit/include/SourceKit/Core/LangSupport.h @@ -90,7 +90,6 @@ struct CodeCompletionInfo { StringRef TypeName; StringRef ModuleName; StringRef DocBrief; - StringRef DocFull; StringRef AssocUSRs; UIdent SemanticContext; UIdent TypeRelation; diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h index 5357c49337b4e..c83d60e4e662f 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.h @@ -47,7 +47,6 @@ struct Options { bool includeObjectLiterals = true; bool addCallWithNoDefaultArgs = true; bool verifyUSRToDecl = false; - bool includeFullDocumentation = false; unsigned minFuzzyLength = 2; unsigned showTopNonLiteralResults = 3; diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp index cee158f8a8b1c..d576410237d6f 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp @@ -45,8 +45,7 @@ namespace { struct SwiftToSourceKitCompletionAdapter { static bool handleResult(SourceKit::CodeCompletionConsumer &consumer, CodeCompletionResult *result, - bool annotatedDescription, - bool includeFullDocumentation) { + bool annotatedDescription) { llvm::SmallString<64> description; { llvm::raw_svector_ostream OSS(description); @@ -61,15 +60,13 @@ struct SwiftToSourceKitCompletionAdapter { Completion extended(*result, description); return handleResult(consumer, &extended, /*leadingPunctuation=*/false, - /*legacyLiteralToKeyword=*/true, annotatedDescription, - includeFullDocumentation); + /*legacyLiteralToKeyword=*/true, annotatedDescription); } static bool handleResult(SourceKit::CodeCompletionConsumer &consumer, Completion *result, bool leadingPunctuation, bool legacyLiteralToKeyword, - bool annotatedDescription, - bool includeFullDocumentation); + bool annotatedDescription); static void getResultAssociatedUSRs(ArrayRef AssocUSRs, @@ -172,8 +169,7 @@ deliverCodeCompleteResults(SourceKit::CodeCompletionConsumer &SKConsumer, } } if (!SwiftToSourceKitCompletionAdapter::handleResult( - SKConsumer, Result, CCOpts.annotatedDescription, - CCOpts.includeFullDocumentation)) + SKConsumer, Result, CCOpts.annotatedDescription)) break; } @@ -394,7 +390,7 @@ static UIdent KeywordFuncUID("source.lang.swift.keyword.func"); bool SwiftToSourceKitCompletionAdapter::handleResult( SourceKit::CodeCompletionConsumer &Consumer, Completion *Result, bool leadingPunctuation, bool legacyLiteralToKeyword, - bool annotatedDescription, bool includeFullDocumentation) { + bool annotatedDescription) { static UIdent KeywordUID("source.lang.swift.keyword"); static UIdent PatternUID("source.lang.swift.pattern"); @@ -485,19 +481,6 @@ bool SwiftToSourceKitCompletionAdapter::handleResult( Info.TypeName = StringRef(SS.begin() + TypeBegin, TypeEnd - TypeBegin); Info.AssocUSRs = StringRef(SS.begin() + USRsBegin, USRsEnd - USRsBegin); - if (includeFullDocumentation) { - unsigned DocFullBegin = SS.size(); - { - llvm::raw_svector_ostream ccOS(SS); - Result->printFullDocComment(ccOS); - } - unsigned DocFullEnd = SS.size(); - Info.DocFull = - StringRef(SS.begin() + DocFullBegin, DocFullEnd - DocFullBegin); - } else { - Info.DocFull = StringRef(); - } - static UIdent CCCtxNone("source.codecompletion.context.none"); static UIdent CCCtxExpressionSpecific( "source.codecompletion.context.exprspecific"); @@ -709,8 +692,7 @@ class SwiftGroupedCodeCompletionConsumer : public CodeCompletionView::Walker { bool handleResult(Completion *result) override { return SwiftToSourceKitCompletionAdapter::handleResult( consumer, result, /*leadingPunctuation=*/true, - /*legacyLiteralToKeyword=*/false, /*annotatedDescription=*/false, - /*includeFullDocumentation=*/false); + /*legacyLiteralToKeyword=*/false, /*annotatedDescription=*/false); } void startGroup(StringRef name) override { static UIdent GroupUID("source.lang.swift.codecomplete.group"); @@ -741,8 +723,6 @@ static void translateCodeCompletionOptions(OptionsDictionary &from, static UIdent KeyAddInnerOperators("key.codecomplete.addinneroperators"); static UIdent KeyAddInitsToTopLevel("key.codecomplete.addinitstotoplevel"); static UIdent KeyFuzzyMatching("key.codecomplete.fuzzymatching"); - static UIdent KeyIncludeFullDocumentation( - "key.codecomplete.includefulldocumentation"); static UIdent KeyTopNonLiteral("key.codecomplete.showtopnonliteralresults"); static UIdent KeyContextWeight("key.codecomplete.sort.contextweight"); static UIdent KeyFuzzyWeight("key.codecomplete.sort.fuzzyweight"); @@ -768,7 +748,6 @@ static void translateCodeCompletionOptions(OptionsDictionary &from, from.valueForOption(KeyAddInnerOperators, to.addInnerOperators); from.valueForOption(KeyAddInitsToTopLevel, to.addInitsToTopLevel); from.valueForOption(KeyFuzzyMatching, to.fuzzyMatching); - from.valueForOption(KeyIncludeFullDocumentation, to.includeFullDocumentation); from.valueForOption(KeyContextWeight, to.semanticContextWeight); from.valueForOption(KeyFuzzyWeight, to.fuzzyMatchWeight); from.valueForOption(KeyPopularityBonus, to.popularityBonus); diff --git a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h index a182e65359a38..518b5db8f139f 100644 --- a/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h +++ b/tools/SourceKit/tools/sourcekitd/include/sourcekitd/CodeCompletionResultsArray.h @@ -28,7 +28,6 @@ class CodeCompletionResultsArrayBuilder { llvm::StringRef Description, llvm::StringRef SourceText, llvm::StringRef TypeName, std::optional ModuleName, std::optional DocBrief, - std::optional DocFull, std::optional AssocUSRs, SourceKit::UIdent SemanticContext, SourceKit::UIdent TypeRelation, bool NotRecommended, bool IsSystem, unsigned NumBytesToErase); diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp index 211df5e3e7182..113596951a361 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp @@ -24,8 +24,8 @@ using namespace sourcekitd; struct CodeCompletionResultsArrayBuilder::Implementation { CompactArrayBuilder, std::optional, - std::optional, std::optional, - UIdent, UIdent, uint8_t, uint8_t> + std::optional, UIdent, UIdent, uint8_t, + uint8_t> Builder; }; @@ -41,10 +41,9 @@ CodeCompletionResultsArrayBuilder::~CodeCompletionResultsArrayBuilder() { void CodeCompletionResultsArrayBuilder::add( UIdent Kind, StringRef Name, StringRef Description, StringRef SourceText, StringRef TypeName, std::optional ModuleName, - std::optional DocBrief, std::optional DocFull, - std::optional AssocUSRs, UIdent SemanticContext, - UIdent TypeRelation, bool NotRecommended, bool IsSystem, - unsigned NumBytesToErase) { + std::optional DocBrief, std::optional AssocUSRs, + UIdent SemanticContext, UIdent TypeRelation, + bool NotRecommended, bool IsSystem, unsigned NumBytesToErase) { uint8_t Flags = 0; Flags |= NotRecommended << 1; @@ -59,7 +58,6 @@ void CodeCompletionResultsArrayBuilder::add( TypeName, ModuleName, DocBrief, - DocFull, AssocUSRs, SemanticContext, TypeRelation, @@ -85,7 +83,6 @@ class CodeCompletionResultsArray { const char *, const char *, const char *, - const char *, sourcekitd_uid_t, sourcekitd_uid_t, uint8_t, @@ -104,7 +101,6 @@ class CodeCompletionResultsArray { const char *TypeName; const char *ModuleName; const char *DocBrief; - const char *DocFull; const char *AssocUSRs; sourcekitd_uid_t SemanticContext; sourcekitd_uid_t TypeRelation; @@ -119,7 +115,6 @@ class CodeCompletionResultsArray { TypeName, ModuleName, DocBrief, - DocFull, AssocUSRs, SemanticContext, TypeRelation, @@ -148,9 +143,6 @@ class CodeCompletionResultsArray { if (DocBrief) { APPLY(KeyDocBrief, String, DocBrief); } - if (DocFull) { - APPLY(KeyDocFullAsXML, String, DocFull); - } if (AssocUSRs) { APPLY(KeyAssociatedUSRs, String, AssocUSRs); } diff --git a/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp index f08d8c89b41b8..fca57f07de4da 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/Service/Requests.cpp @@ -3189,9 +3189,6 @@ bool SKCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) { std::optional DocBriefOpt; if (!R.DocBrief.empty()) DocBriefOpt = R.DocBrief; - std::optional DocFullOpt; - if (!R.DocFull.empty()) - DocFullOpt = R.DocFull; std::optional AssocUSRsOpt; if (!R.AssocUSRs.empty()) AssocUSRsOpt = R.AssocUSRs; @@ -3205,7 +3202,6 @@ bool SKCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) { R.TypeName, ModuleNameOpt, DocBriefOpt, - DocFullOpt, AssocUSRsOpt, R.SemanticContext, R.TypeRelation, @@ -3381,8 +3377,6 @@ bool SKGroupedCodeCompletionConsumer::handleResult(const CodeCompletionInfo &R) result.set(KeyModuleName, R.ModuleName); if (!R.DocBrief.empty()) result.set(KeyDocBrief, R.DocBrief); - if (!R.DocFull.empty()) - result.set(KeyDocFullAsXML, R.DocFull); if (!R.AssocUSRs.empty()) result.set(KeyAssociatedUSRs, R.AssocUSRs); if (R.ModuleImportDepth) From e3e9468e6799b8c47a2fa7fbc1bdd1f5d0d567f4 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 17:20:22 +0300 Subject: [PATCH 46/58] [Test] Check full doc in completion with swift-ide-test --- .../complete_with_clang_comments.swift | 20 +++++++-- .../CodeComplete/complete_doc_1.swift | 41 ++++--------------- .../CodeComplete/complete_doc_2.swift | 23 +++-------- .../CodeComplete/complete_doc_3.swift | 23 +++-------- .../CodeComplete/complete_doc_package.swift | 18 +++----- .../CodeComplete/complete_doc_spi.swift | 18 +++----- .../complete_from_clang_module.swift | 21 ++++------ .../complete_member.swift.response | 1 - tools/swift-ide-test/swift-ide-test.cpp | 8 ++++ 9 files changed, 60 insertions(+), 113 deletions(-) diff --git a/test/IDE/clang-importing/complete_with_clang_comments.swift b/test/IDE/clang-importing/complete_with_clang_comments.swift index a4262b164f919..ea7db6b9618da 100644 --- a/test/IDE/clang-importing/complete_with_clang_comments.swift +++ b/test/IDE/clang-importing/complete_with_clang_comments.swift @@ -8,7 +8,19 @@ import somemod2 #^TOP^# -// CHECK-TOP: name=some_func11(); briefcomment=some_func11 is cool function.; fullcomment=some_func11c:@F@some_func11func some_func11() some_func11 is cool function. -// CHECK-TOP: name=some_func12(); briefcomment=some_func12 is cool function.; fullcomment=some_func12c:@F@some_func12func some_func12() some_func12 is cool function. -// CHECK-TOP: name=some_func21(); briefcomment=some_func21 is cool function.; fullcomment=some_func21c:@F@some_func21func some_func21() some_func21 is cool function. -// CHECK-TOP: name=some_func22(); briefcomment=some_func22 is cool function.; fullcomment=some_func22c:@F@some_func22func some_func22() some_func22 is cool function. + +// CHECK-TOP: name=some_func11(); +// CHECK-TOP-SAME: briefcomment=some_func11 is cool function.; +// CHECK-TOP-SAME: fullcomment=some_func11c:@F@some_func11func some_func11() some_func11 is cool function. + +// CHECK-TOP: name=some_func12(); +// CHECK-TOP-SAME: briefcomment=some_func12 is cool function.; +// CHECK-TOP-SAME: fullcomment=some_func12c:@F@some_func12func some_func12() some_func12 is cool function. + +// CHECK-TOP: name=some_func21(); +// CHECK-TOP-SAME: briefcomment=some_func21 is cool function.; +// CHECK-TOP-SAME: fullcomment=some_func21c:@F@some_func21func some_func21() some_func21 is cool function. + +// CHECK-TOP: name=some_func22(); +// CHECK-TOP-SAME: briefcomment=some_func22 is cool function.; +// CHECK-TOP-SAME: fullcomment=some_func22c:@F@some_func22func some_func22() some_func22 is cool function. diff --git a/test/SourceKit/CodeComplete/complete_doc_1.swift b/test/SourceKit/CodeComplete/complete_doc_1.swift index aa6610ece1435..8b14b96b3dcb8 100644 --- a/test/SourceKit/CodeComplete/complete_doc_1.swift +++ b/test/SourceKit/CodeComplete/complete_doc_1.swift @@ -19,39 +19,16 @@ struct S: P { } func test() { - S(). + S().#^DOC^# } // All in main module. -// RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=22:7 %s -- %s -module-name DocBriefTest | %FileCheck %s -check-prefix=CHECK +// RUN: %target-swift-ide-test -code-completion -source-filename %s -module-name DocBriefTest -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK -// CHECK: { -// CHECK: key.results: [ -// CHECK-NEXT: { -// CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, -// CHECK-NEXT: key.name: "bar()", -// CHECK-NEXT: key.doc.full_as_xml: "bar()s:12DocBriefTest1PP3baryyFfunc bar()This is a doc comment of P.barMay have default information.This documentation comment was inherited from P.", -// CHECK-NEXT: key.description: "bar()", -// CHECK-NEXT: key.typename: "Void", -// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.bar", -// CHECK-NEXT: key.context: source.codecompletion.context.superclass, -// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, -// CHECK-NEXT: key.num_bytes_to_erase: 0, -// CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1PPAAE3baryyF", -// CHECK-NEXT: key.modulename: "DocBriefTest", -// CHECK-NEXT: key.sourcetext: "bar()" -// CHECK-NEXT: }, -// CHECK-NEXT: { -// CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, -// CHECK-NEXT: key.name: "foo()", -// CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", -// CHECK-NEXT: key.description: "foo()", -// CHECK-NEXT: key.typename: "Void", -// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", -// CHECK-NEXT: key.context: source.codecompletion.context.thisclass, -// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, -// CHECK-NEXT: key.num_bytes_to_erase: 0, -// CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1SV3fooyyF s:12DocBriefTest1PP3fooyyF", -// CHECK-NEXT: key.modulename: "DocBriefTest", -// CHECK-NEXT: key.sourcetext: "foo()" -// CHECK-NEXT: } +// CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); +// CHECK-SAME: briefcomment=This is a doc comment of P.foo; +// CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. + +// CHECK: Decl[InstanceMethod]/Super: bar()[#Void#]; name=bar(); +// CHECK-SAME: briefcomment=This is a doc comment of P.bar; +// CHECK-SAME: fullcomment=bar()s:12DocBriefTest1PP3baryyFfunc bar()This is a doc comment of P.barMay have default information.This documentation comment was inherited from P. diff --git a/test/SourceKit/CodeComplete/complete_doc_2.swift b/test/SourceKit/CodeComplete/complete_doc_2.swift index e355af29f4b10..aaec8cb055afd 100644 --- a/test/SourceKit/CodeComplete/complete_doc_2.swift +++ b/test/SourceKit/CodeComplete/complete_doc_2.swift @@ -24,23 +24,10 @@ struct S: P { } func test() { - // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK - S(). + // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK + S().#^DOC^# - // CHECK: { - // CHECK: key.results: [ - // CHECK-NEXT: { - // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, - // CHECK-NEXT: key.name: "foo()", - // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", - // CHECK-NEXT: key.description: "foo()", - // CHECK-NEXT: key.typename: "Void", - // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", - // CHECK-NEXT: key.context: source.codecompletion.context.thisclass, - // CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, - // CHECK-NEXT: key.num_bytes_to_erase: 0, - // CHECK-NEXT: key.associated_usrs: "s:12DocBriefUser1SV3fooyyF s:12DocBriefTest1PP3fooyyF", - // CHECK-NEXT: key.modulename: "DocBriefUser", - // CHECK-NEXT: key.sourcetext: "foo()" - // CHECK-NEXT: } + // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); + // CHECK-SAME: briefcomment=This is a doc comment of P.foo; + // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. } diff --git a/test/SourceKit/CodeComplete/complete_doc_3.swift b/test/SourceKit/CodeComplete/complete_doc_3.swift index 3b9d718be4f39..5f12fbd1cd020 100644 --- a/test/SourceKit/CodeComplete/complete_doc_3.swift +++ b/test/SourceKit/CodeComplete/complete_doc_3.swift @@ -25,23 +25,10 @@ public struct S: P { //--- User.swift import DocBriefTest func test() { - // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK - S().foo() + // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK + S().#^DOC^#foo() - // CHECK: { - // CHECK: key.results: [ - // CHECK-NEXT: { - // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, - // CHECK-NEXT: key.name: "foo()", - // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", - // CHECK-NEXT: key.description: "foo()", - // CHECK-NEXT: key.typename: "Void", - // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", - // CHECK-NEXT: key.context: source.codecompletion.context.thisclass, - // CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, - // CHECK-NEXT: key.num_bytes_to_erase: 0, - // CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1SV3fooyyF s:12DocBriefTest1PP3fooyyF", - // CHECK-NEXT: key.modulename: "DocBriefTest", - // CHECK-NEXT: key.sourcetext: "foo()" - // CHECK-NEXT: } + // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); + // CHECK-SAME: briefcomment=This is a doc comment of P.foo; + // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. } diff --git a/test/SourceKit/CodeComplete/complete_doc_package.swift b/test/SourceKit/CodeComplete/complete_doc_package.swift index 71c643b06812f..06c9a78a7fe95 100644 --- a/test/SourceKit/CodeComplete/complete_doc_package.swift +++ b/test/SourceKit/CodeComplete/complete_doc_package.swift @@ -27,18 +27,10 @@ package struct S: P { package import DocBriefTest func test() { - // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -package-name DocPackage | %FileCheck %s -check-prefix=CHECK - S().foo() + // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -package-name DocPackage -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK + S().#^DOC^#foo() - // CHECK: { - // CHECK: key.results: [ - // CHECK-NEXT: { - // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, - // CHECK-NEXT: key.name: "foo()", - // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", - // CHECK-NEXT: key.description: "foo()", - // CHECK-NEXT: key.typename: "Void", - // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", - // CHECK: key.sourcetext: "foo()" - // CHECK: } + // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); + // CHECK-SAME: briefcomment=This is a doc comment of P.foo; + // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. } diff --git a/test/SourceKit/CodeComplete/complete_doc_spi.swift b/test/SourceKit/CodeComplete/complete_doc_spi.swift index f07f252a2e8b1..303f9ebd34486 100644 --- a/test/SourceKit/CodeComplete/complete_doc_spi.swift +++ b/test/SourceKit/CodeComplete/complete_doc_spi.swift @@ -28,18 +28,10 @@ public struct S: P { @_spi(SomeSPI) import DocBriefTest func test() { - // RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK - S().foo() + // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK + S().#^DOC^#foo() - // CHECK: { - // CHECK: key.results: [ - // CHECK-NEXT: { - // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, - // CHECK-NEXT: key.name: "foo()", - // CHECK-NEXT: key.doc.full_as_xml: "foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P.", - // CHECK-NEXT: key.description: "foo()", - // CHECK-NEXT: key.typename: "Void", - // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", - // CHECK: key.sourcetext: "foo()" - // CHECK: } + // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); + // CHECK-SAME: briefcomment=This is a doc comment of P.foo; + // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. } diff --git a/test/SourceKit/CodeComplete/complete_from_clang_module.swift b/test/SourceKit/CodeComplete/complete_from_clang_module.swift index a2b5d844673c8..f5eb9f9b34fdc 100644 --- a/test/SourceKit/CodeComplete/complete_from_clang_module.swift +++ b/test/SourceKit/CodeComplete/complete_from_clang_module.swift @@ -1,18 +1,11 @@ import Foo -// REQUIRES: objc_interop -// RUN: %sourcekitd-test -req=complete -req-opts=includefulldocumentation=1 -pos=2:1 %s -- -F %S/../Inputs/libIDE-mock-sdk %s | %FileCheck %s +#^COMPLETE^# -// CHECK-LABEL: key.name: "fooIntVar", -// CHECK-NEXT: key.doc.full_as_xml: "fooIntVarc:@fooIntVarvar fooIntVar: Int32 Aaa. fooIntVar. Bbb.", -// CHECK-NEXT: key.description: "fooIntVar", -// CHECK-NEXT: key.typename: "Int32", -// CHECK-NEXT: key.doc.brief: "Aaa. fooIntVar. Bbb.", -// CHECK-NEXT: key.context: source.codecompletion.context.othermodule, -// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, -// CHECK-NEXT: key.num_bytes_to_erase: 0, -// CHECK-NEXT: key.associated_usrs: "c:@fooIntVar", -// CHECK-NEXT: key.modulename: "Foo", -// CHECK-NEXT: key.sourcetext: "fooIntVar" -// CHECK-NEXT: }, +// REQUIRES: objc_interop +// RUN: %target-swift-ide-test -code-completion -source-filename %s -F %S/../Inputs/libIDE-mock-sdk -code-completion-token=COMPLETE -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK +// CHECK: Decl[GlobalVar]/OtherModule[Foo]: fooIntVar[#Int32#]; +// CHECK-SAME-LABEL: name=fooIntVar; +// CHECK-SAME: briefcomment=Aaa. fooIntVar. Bbb.; +// CHECK-SAME: fullcomment=fooIntVarc:@fooIntVarvar fooIntVar: Int32 Aaa. fooIntVar. Bbb. diff --git a/test/SourceKit/CodeComplete/complete_member.swift.response b/test/SourceKit/CodeComplete/complete_member.swift.response index 3471835c5b27c..489995d707b70 100644 --- a/test/SourceKit/CodeComplete/complete_member.swift.response +++ b/test/SourceKit/CodeComplete/complete_member.swift.response @@ -27,7 +27,6 @@ { key.kind: source.lang.swift.decl.var.instance, key.name: "fooInstanceVar", - key.doc.full_as_xml: "fooInstanceVars:15complete_member11FooProtocolP14fooInstanceVarSivpvar fooInstanceVar: Int { get }fooInstanceVar Aaa. Bbb.Ccc.", key.description: "fooInstanceVar", key.typename: "Int", key.doc.brief: "fooInstanceVar Aaa. Bbb.", diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index b5ed42a18ff87..8c8a7949f75b5 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -770,6 +770,10 @@ static llvm::cl::opt ModuleName("module-name", llvm::cl::desc("The module name of the given test."), llvm::cl::cat(Category), llvm::cl::init("swift_ide_test")); +static llvm::cl::opt +PackageName("package-name", llvm::cl::desc("The package name of the given test."), + llvm::cl::cat(Category)); + static llvm::cl::opt NoEmptyLineBetweenMembers("no-empty-line-between-members", llvm::cl::desc("Print no empty line between members."), @@ -4447,6 +4451,10 @@ int main(int argc, char *argv[]) { InitInvok.setMainExecutablePath(mainExecutablePath); InitInvok.setModuleName(options::ModuleName); + if (!options::PackageName.empty()) { + InitInvok.getLangOptions().PackageName = options::PackageName; + } + InitInvok.setSDKPath(options::SDK); for (auto macro : options::DefineAvailability) { From d18694fbbcb40ac38afe7ed8ce08569563a4dc10 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 17:47:59 +0300 Subject: [PATCH 47/58] NFC: Apply clang-format to full documentation in completion changes --- include/swift/AST/TypeCheckRequests.h | 8 +++---- lib/AST/USRGeneration.cpp | 23 ++++++++++--------- lib/PrintAsClang/ClangSyntaxPrinter.cpp | 4 ++-- .../lib/API/CodeCompletionResultsArray.cpp | 4 ++-- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 4c343c58c6816..8610106101cf7 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -759,10 +759,10 @@ class RequirementRequest : /// Generate the Clang USR for the given declaration. class ClangUSRGenerationRequest - : public SimpleRequest< - ClangUSRGenerationRequest, - std::optional(const ValueDecl *), - RequestFlags::SeparatelyCached | RequestFlags::SplitCached> { + : public SimpleRequest(const ValueDecl *), + RequestFlags::SeparatelyCached | + RequestFlags::SplitCached> { public: using SimpleRequest::SimpleRequest; diff --git a/lib/AST/USRGeneration.cpp b/lib/AST/USRGeneration.cpp index 2d84a22780d07..fd25bc3db6909 100644 --- a/lib/AST/USRGeneration.cpp +++ b/lib/AST/USRGeneration.cpp @@ -177,8 +177,9 @@ void swift::simple_display(llvm::raw_ostream &out, << ", useSwiftUSR: " << options.useSwiftUSR << ")"; } -std::optional swift::ClangUSRGenerationRequest::evaluate( - Evaluator &evaluator, const ValueDecl *D) const { +std::optional +swift::ClangUSRGenerationRequest::evaluate(Evaluator &evaluator, + const ValueDecl *D) const { llvm::SmallString<128> Buffer; llvm::raw_svector_ostream OS(Buffer); @@ -197,8 +198,7 @@ std::optional swift::ClangUSRGenerationRequest::evaluate( auto ClangMacroInfo = ClangN.getAsMacro(); bool Ignore = clang::index::generateUSRForMacro( - D->getBaseIdentifier().str(), - ClangMacroInfo->getDefinitionLoc(), + D->getBaseIdentifier().str(), ClangMacroInfo->getDefinitionLoc(), Importer.getClangASTContext().getSourceManager(), Buffer); if (!Ignore) return std::string(Buffer.str()); @@ -236,8 +236,9 @@ void swift::ClangUSRGenerationRequest::cacheResult( decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result)); } -std::string swift::SwiftUSRGenerationRequest::evaluate(Evaluator &evaluator, - const ValueDecl *D) const { +std::string +swift::SwiftUSRGenerationRequest::evaluate(Evaluator &evaluator, + const ValueDecl *D) const { auto declIFaceTy = D->getInterfaceType(); // Invalid code. @@ -260,8 +261,9 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, return std::string(); // Ignore. if (isa(D)) return std::string(); // Ignore. - - /// Checks whether \p D is a synthesized Clang declaration that should have a Swift USR. + + /// Checks whether \p D is a synthesized Clang declaration that should have a + /// Swift USR. auto isSynthesizedDeclWithSwiftUSR = [](const ValueDecl *D) -> bool { auto *importer = D->getASTContext().getClangModuleLoader(); ClangNode ClangN = importer->getEffectiveClangNode(D); @@ -298,9 +300,8 @@ swift::USRGenerationRequest::evaluate(Evaluator &evaluator, const ValueDecl *D, if (!options.useSwiftUSR && (!options.distinguishSynthesizedDecls || !isSynthesizedDeclWithSwiftUSR(D))) { - if (auto clangUSR = evaluateOrDefault(evaluator, - ClangUSRGenerationRequest{D}, - std::nullopt)) { + if (auto clangUSR = evaluateOrDefault( + evaluator, ClangUSRGenerationRequest{D}, std::nullopt)) { return clangUSR.value(); } } diff --git a/lib/PrintAsClang/ClangSyntaxPrinter.cpp b/lib/PrintAsClang/ClangSyntaxPrinter.cpp index c7af448606521..21078f534907e 100644 --- a/lib/PrintAsClang/ClangSyntaxPrinter.cpp +++ b/lib/PrintAsClang/ClangSyntaxPrinter.cpp @@ -488,8 +488,8 @@ void ClangSyntaxPrinter::printSymbolUSRAttribute(const ValueDecl *D) const { os << "\")"; return; } - auto result = evaluateOrDefault( - D->getASTContext().evaluator, USRGenerationRequest{D, {}}, std::string()); + auto result = evaluateOrDefault(D->getASTContext().evaluator, + USRGenerationRequest{D, {}}, std::string()); if (result.empty()) return; os << " SWIFT_SYMBOL(\"" << result << "\")"; diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp index 113596951a361..a6e16f70dc25f 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/CodeCompletionResultsArray.cpp @@ -42,8 +42,8 @@ void CodeCompletionResultsArrayBuilder::add( UIdent Kind, StringRef Name, StringRef Description, StringRef SourceText, StringRef TypeName, std::optional ModuleName, std::optional DocBrief, std::optional AssocUSRs, - UIdent SemanticContext, UIdent TypeRelation, - bool NotRecommended, bool IsSystem, unsigned NumBytesToErase) { + UIdent SemanticContext, UIdent TypeRelation, bool NotRecommended, + bool IsSystem, unsigned NumBytesToErase) { uint8_t Flags = 0; Flags |= NotRecommended << 1; From 6a93b8f34fae13ba2f46b1ad3537dbb3712de00a Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 18:27:15 +0300 Subject: [PATCH 48/58] [IDE] Remove unused DeclNameExtractor::extractTextName & SourceKit Completion::printFullDocComment --- include/swift/AST/DeclNameExtractor.h | 1 - lib/AST/DeclNameExtractor.cpp | 8 -------- tools/SourceKit/lib/SwiftLang/CodeCompletion.h | 4 ---- 3 files changed, 13 deletions(-) diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h index d5cba781b9416..0932ffc7e4934 100644 --- a/include/swift/AST/DeclNameExtractor.h +++ b/include/swift/AST/DeclNameExtractor.h @@ -37,7 +37,6 @@ class DeclNameExtractor { private: bool extractIdentifierName(Node *node, DeclName &declName, Identifier &privateDiscriminator); - DeclName extractTextName(Node *node); bool extractFunctionLikeName(Node *node, DeclName &declName, Identifier &privateDiscriminator); void extractArgLabelsFromLabelList(Node *LabelList, diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index 1d32e683cbccb..9c70a85d53a91 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -78,14 +78,6 @@ bool DeclNameExtractor::extractIdentifierName( return true; } -DeclName DeclNameExtractor::extractTextName(Node *node) { - if (!node->hasText()) - return DeclName(); - - auto identifier = getIdentifier(Ctx, node->getText()); - return DeclName(identifier); -} - bool DeclNameExtractor::extractFunctionLikeName( Node *node, DeclName &declName, Identifier &privateDiscriminator) { assert(node->getKind() == Node::Kind::Function || diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h index 26aeea5ed4f0b..e6d159b99cce8 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletion.h +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletion.h @@ -166,10 +166,6 @@ class Completion { return getSwiftResult().getBriefDocComment(); } - bool printFullDocComment(llvm::raw_ostream &OS) const { - return getSwiftResult().printFullDocComment(OS); - } - ArrayRef getAssociatedUSRs() const { return getSwiftResult().getAssociatedUSRs(); } From 0c05f8f35ebb8a69e010162a1c0d42d5b53978bc Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 18:53:33 +0300 Subject: [PATCH 49/58] [Test] Revert changes to SourceKit documentation tests --- .../CodeComplete/complete_doc_1.swift | 34 ------------ .../CodeComplete/complete_doc_2.swift | 33 ----------- .../CodeComplete/complete_doc_3.swift | 34 ------------ .../CodeComplete/complete_doc_package.swift | 36 ------------ .../CodeComplete/complete_doc_spi.swift | 37 ------------- .../CodeComplete/complete_docbrief_1.swift | 55 +++++++++++++++++++ .../CodeComplete/complete_docbrief_2.swift | 45 +++++++++++++++ .../CodeComplete/complete_docbrief_3.swift | 46 ++++++++++++++++ .../complete_docbrief_package.swift | 43 +++++++++++++++ .../CodeComplete/complete_docbrief_spi.swift | 44 +++++++++++++++ .../complete_from_clang_module.swift | 20 ++++--- .../CodeComplete/complete_member.swift | 2 +- 12 files changed, 247 insertions(+), 182 deletions(-) delete mode 100644 test/SourceKit/CodeComplete/complete_doc_1.swift delete mode 100644 test/SourceKit/CodeComplete/complete_doc_2.swift delete mode 100644 test/SourceKit/CodeComplete/complete_doc_3.swift delete mode 100644 test/SourceKit/CodeComplete/complete_doc_package.swift delete mode 100644 test/SourceKit/CodeComplete/complete_doc_spi.swift create mode 100644 test/SourceKit/CodeComplete/complete_docbrief_1.swift create mode 100644 test/SourceKit/CodeComplete/complete_docbrief_2.swift create mode 100644 test/SourceKit/CodeComplete/complete_docbrief_3.swift create mode 100644 test/SourceKit/CodeComplete/complete_docbrief_package.swift create mode 100644 test/SourceKit/CodeComplete/complete_docbrief_spi.swift diff --git a/test/SourceKit/CodeComplete/complete_doc_1.swift b/test/SourceKit/CodeComplete/complete_doc_1.swift deleted file mode 100644 index 8b14b96b3dcb8..0000000000000 --- a/test/SourceKit/CodeComplete/complete_doc_1.swift +++ /dev/null @@ -1,34 +0,0 @@ -protocol P { - /// This is a doc comment of P.foo - /// - /// Do whatever. - func foo() - - /// This is a doc comment of P.bar - /// - /// May have default information. - func bar() -} - -extension P { - func bar() {} -} - -struct S: P { - func foo() {} -} - -func test() { - S().#^DOC^# -} - -// All in main module. -// RUN: %target-swift-ide-test -code-completion -source-filename %s -module-name DocBriefTest -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK - -// CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); -// CHECK-SAME: briefcomment=This is a doc comment of P.foo; -// CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. - -// CHECK: Decl[InstanceMethod]/Super: bar()[#Void#]; name=bar(); -// CHECK-SAME: briefcomment=This is a doc comment of P.bar; -// CHECK-SAME: fullcomment=bar()s:12DocBriefTest1PP3baryyFfunc bar()This is a doc comment of P.barMay have default information.This documentation comment was inherited from P. diff --git a/test/SourceKit/CodeComplete/complete_doc_2.swift b/test/SourceKit/CodeComplete/complete_doc_2.swift deleted file mode 100644 index aaec8cb055afd..0000000000000 --- a/test/SourceKit/CodeComplete/complete_doc_2.swift +++ /dev/null @@ -1,33 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %empty-directory(%t/Modules) -// RUN: split-file --leading-lines %s %t - -// RUN: %target-swift-frontend \ -// RUN: -emit-module \ -// RUN: -module-name DocBriefTest \ -// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ -// RUN: -emit-module-doc-path %t/Modules/DocBriefTest.swiftdoc \ -// RUN: %t/Module.swift - -//--- Module.swift -public protocol P { - /// This is a doc comment of P.foo - /// - /// Do whatever. - func foo() -} - -//--- User.swift -import DocBriefTest -struct S: P { - func foo() {} -} - -func test() { - // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK - S().#^DOC^# - - // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); - // CHECK-SAME: briefcomment=This is a doc comment of P.foo; - // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. -} diff --git a/test/SourceKit/CodeComplete/complete_doc_3.swift b/test/SourceKit/CodeComplete/complete_doc_3.swift deleted file mode 100644 index 5f12fbd1cd020..0000000000000 --- a/test/SourceKit/CodeComplete/complete_doc_3.swift +++ /dev/null @@ -1,34 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %empty-directory(%t/Modules) -// RUN: split-file --leading-lines %s %t - -// RUN: %target-swift-frontend \ -// RUN: -emit-module \ -// RUN: -module-name DocBriefTest \ -// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ -// RUN: -emit-module-doc-path %t/Modules/DocBriefTest.swiftdoc \ -// RUN: %t/Module.swift - -//--- Module.swift -public protocol P { - /// This is a doc comment of P.foo - /// - /// Do whatever. - func foo() -} - -public struct S: P { - public init() {} - public func foo() {} -} - -//--- User.swift -import DocBriefTest -func test() { - // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK - S().#^DOC^#foo() - - // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); - // CHECK-SAME: briefcomment=This is a doc comment of P.foo; - // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. -} diff --git a/test/SourceKit/CodeComplete/complete_doc_package.swift b/test/SourceKit/CodeComplete/complete_doc_package.swift deleted file mode 100644 index 06c9a78a7fe95..0000000000000 --- a/test/SourceKit/CodeComplete/complete_doc_package.swift +++ /dev/null @@ -1,36 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %empty-directory(%t/Modules) -// RUN: split-file --leading-lines %s %t - -// RUN: %target-swift-frontend \ -// RUN: -emit-module \ -// RUN: -module-name DocBriefTest \ -// RUN: -package-name DocPackage \ -// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ -// RUN: -emit-module-source-info-path %t/Modules/DocBriefTest.swiftsourceinfo \ -// RUN: %t/Module.swift - -//--- Module.swift -package protocol P { - /// This is a doc comment of P.foo - /// - /// Do whatever. - func foo() -} - -package struct S: P { - public init() {} - public func foo() {} -} - -//--- User.swift -package import DocBriefTest - -func test() { - // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -package-name DocPackage -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK - S().#^DOC^#foo() - - // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); - // CHECK-SAME: briefcomment=This is a doc comment of P.foo; - // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. -} diff --git a/test/SourceKit/CodeComplete/complete_doc_spi.swift b/test/SourceKit/CodeComplete/complete_doc_spi.swift deleted file mode 100644 index 303f9ebd34486..0000000000000 --- a/test/SourceKit/CodeComplete/complete_doc_spi.swift +++ /dev/null @@ -1,37 +0,0 @@ -// RUN: %empty-directory(%t) -// RUN: %empty-directory(%t/Modules) -// RUN: split-file --leading-lines %s %t - -// RUN: %target-swift-frontend \ -// RUN: -emit-module \ -// RUN: -module-name DocBriefTest \ -// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ -// RUN: -emit-module-source-info-path %t/Modules/DocBriefTest.swiftsourceinfo \ -// RUN: %t/Module.swift - -//--- Module.swift -@_spi(SomeSPI) -public protocol P { - /// This is a doc comment of P.foo - /// - /// Do whatever. - func foo() -} - -@_spi(SomeSPI) -public struct S: P { - public init() {} - public func foo() {} -} - -//--- User.swift -@_spi(SomeSPI) import DocBriefTest - -func test() { - // RUN: %target-swift-ide-test -code-completion -source-filename %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -code-completion-token=DOC -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK - S().#^DOC^#foo() - - // CHECK: Decl[InstanceMethod]/CurrNominal: foo()[#Void#]; name=foo(); - // CHECK-SAME: briefcomment=This is a doc comment of P.foo; - // CHECK-SAME: fullcomment=foo()s:12DocBriefTest1PP3fooyyFfunc foo()This is a doc comment of P.fooDo whatever.This documentation comment was inherited from P. -} diff --git a/test/SourceKit/CodeComplete/complete_docbrief_1.swift b/test/SourceKit/CodeComplete/complete_docbrief_1.swift new file mode 100644 index 0000000000000..3a37e12a9f3d6 --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_docbrief_1.swift @@ -0,0 +1,55 @@ +protocol P { + /// This is a doc comment of P.foo + /// + /// Do whatever. + func foo() + + /// This is a doc comment of P.bar + /// + /// May have default information. + func bar() +} + +extension P { + func bar() {} +} + +struct S: P { + func foo() {} +} + +func test() { + S(). +} + +// All in main module. +// RUN: %sourcekitd-test -req=complete -pos=22:7 %s -- %s -module-name DocBriefTest | %FileCheck %s -check-prefix=CHECK + +// CHECK: { +// CHECK: key.results: [ +// CHECK-NEXT: { +// CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, +// CHECK-NEXT: key.name: "bar()", +// CHECK-NEXT: key.description: "bar()", +// CHECK-NEXT: key.typename: "Void", +// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.bar", +// CHECK-NEXT: key.context: source.codecompletion.context.superclass, +// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, +// CHECK-NEXT: key.num_bytes_to_erase: 0, +// CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1PPAAE3baryyF", +// CHECK-NEXT: key.modulename: "DocBriefTest", +// CHECK-NEXT: key.sourcetext: "bar()" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, +// CHECK-NEXT: key.name: "foo()", +// CHECK-NEXT: key.description: "foo()", +// CHECK-NEXT: key.typename: "Void", +// CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", +// CHECK-NEXT: key.context: source.codecompletion.context.thisclass, +// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, +// CHECK-NEXT: key.num_bytes_to_erase: 0, +// CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1SV3fooyyF s:12DocBriefTest1PP3fooyyF", +// CHECK-NEXT: key.modulename: "DocBriefTest", +// CHECK-NEXT: key.sourcetext: "foo()" +// CHECK-NEXT: } diff --git a/test/SourceKit/CodeComplete/complete_docbrief_2.swift b/test/SourceKit/CodeComplete/complete_docbrief_2.swift new file mode 100644 index 0000000000000..2551e84fa9c12 --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_docbrief_2.swift @@ -0,0 +1,45 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/Modules) +// RUN: split-file --leading-lines %s %t + +// RUN: %target-swift-frontend \ +// RUN: -emit-module \ +// RUN: -module-name DocBriefTest \ +// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ +// RUN: -emit-module-doc-path %t/Modules/DocBriefTest.swiftdoc \ +// RUN: %t/Module.swift + +//--- Module.swift +public protocol P { + /// This is a doc comment of P.foo + /// + /// Do whatever. + func foo() +} + +//--- User.swift +import DocBriefTest +struct S: P { + func foo() {} +} + +func test() { + // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK + S(). + + // CHECK: { + // CHECK: key.results: [ + // CHECK-NEXT: { + // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, + // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.description: "foo()", + // CHECK-NEXT: key.typename: "Void", + // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", + // CHECK-NEXT: key.context: source.codecompletion.context.thisclass, + // CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, + // CHECK-NEXT: key.num_bytes_to_erase: 0, + // CHECK-NEXT: key.associated_usrs: "s:12DocBriefUser1SV3fooyyF s:12DocBriefTest1PP3fooyyF", + // CHECK-NEXT: key.modulename: "DocBriefUser", + // CHECK-NEXT: key.sourcetext: "foo()" + // CHECK-NEXT: } +} diff --git a/test/SourceKit/CodeComplete/complete_docbrief_3.swift b/test/SourceKit/CodeComplete/complete_docbrief_3.swift new file mode 100644 index 0000000000000..90d38e18c7ff1 --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_docbrief_3.swift @@ -0,0 +1,46 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/Modules) +// RUN: split-file --leading-lines %s %t + +// RUN: %target-swift-frontend \ +// RUN: -emit-module \ +// RUN: -module-name DocBriefTest \ +// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ +// RUN: -emit-module-doc-path %t/Modules/DocBriefTest.swiftdoc \ +// RUN: %t/Module.swift + +//--- Module.swift +public protocol P { + /// This is a doc comment of P.foo + /// + /// Do whatever. + func foo() +} + +public struct S: P { + public init() {} + public func foo() {} +} + +//--- User.swift +import DocBriefTest +func test() { + // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK + S().foo() + + // CHECK: { + // CHECK: key.results: [ + // CHECK-NEXT: { + // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, + // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.description: "foo()", + // CHECK-NEXT: key.typename: "Void", + // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", + // CHECK-NEXT: key.context: source.codecompletion.context.thisclass, + // CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, + // CHECK-NEXT: key.num_bytes_to_erase: 0, + // CHECK-NEXT: key.associated_usrs: "s:12DocBriefTest1SV3fooyyF s:12DocBriefTest1PP3fooyyF", + // CHECK-NEXT: key.modulename: "DocBriefTest", + // CHECK-NEXT: key.sourcetext: "foo()" + // CHECK-NEXT: } +} diff --git a/test/SourceKit/CodeComplete/complete_docbrief_package.swift b/test/SourceKit/CodeComplete/complete_docbrief_package.swift new file mode 100644 index 0000000000000..4a6dda2a2f5c8 --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_docbrief_package.swift @@ -0,0 +1,43 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/Modules) +// RUN: split-file --leading-lines %s %t + +// RUN: %target-swift-frontend \ +// RUN: -emit-module \ +// RUN: -module-name DocBriefTest \ +// RUN: -package-name DocPackage \ +// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ +// RUN: -emit-module-source-info-path %t/Modules/DocBriefTest.swiftsourceinfo \ +// RUN: %t/Module.swift + +//--- Module.swift +package protocol P { + /// This is a doc comment of P.foo + /// + /// Do whatever. + func foo() +} + +package struct S: P { + public init() {} + public func foo() {} +} + +//--- User.swift +package import DocBriefTest + +func test() { + // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser -package-name DocPackage | %FileCheck %s -check-prefix=CHECK + S().foo() + + // CHECK: { + // CHECK: key.results: [ + // CHECK-NEXT: { + // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, + // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.description: "foo()", + // CHECK-NEXT: key.typename: "Void", + // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", + // CHECK: key.sourcetext: "foo()" + // CHECK: } +} diff --git a/test/SourceKit/CodeComplete/complete_docbrief_spi.swift b/test/SourceKit/CodeComplete/complete_docbrief_spi.swift new file mode 100644 index 0000000000000..ee2ed69123a12 --- /dev/null +++ b/test/SourceKit/CodeComplete/complete_docbrief_spi.swift @@ -0,0 +1,44 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/Modules) +// RUN: split-file --leading-lines %s %t + +// RUN: %target-swift-frontend \ +// RUN: -emit-module \ +// RUN: -module-name DocBriefTest \ +// RUN: -emit-module-path %t/Modules/DocBriefTest.swiftmodule \ +// RUN: -emit-module-source-info-path %t/Modules/DocBriefTest.swiftsourceinfo \ +// RUN: %t/Module.swift + +//--- Module.swift +@_spi(SomeSPI) +public protocol P { + /// This is a doc comment of P.foo + /// + /// Do whatever. + func foo() +} + +@_spi(SomeSPI) +public struct S: P { + public init() {} + public func foo() {} +} + +//--- User.swift +@_spi(SomeSPI) import DocBriefTest + +func test() { + // RUN: %sourcekitd-test -req=complete -pos=%(line+1):7 %t/User.swift -- %t/User.swift -I %t/Modules -target %target-triple -module-name DocBriefUser | %FileCheck %s -check-prefix=CHECK + S().foo() + + // CHECK: { + // CHECK: key.results: [ + // CHECK-NEXT: { + // CHECK-NEXT: key.kind: source.lang.swift.decl.function.method.instance, + // CHECK-NEXT: key.name: "foo()", + // CHECK-NEXT: key.description: "foo()", + // CHECK-NEXT: key.typename: "Void", + // CHECK-NEXT: key.doc.brief: "This is a doc comment of P.foo", + // CHECK: key.sourcetext: "foo()" + // CHECK: } +} diff --git a/test/SourceKit/CodeComplete/complete_from_clang_module.swift b/test/SourceKit/CodeComplete/complete_from_clang_module.swift index f5eb9f9b34fdc..e297de9d50bdb 100644 --- a/test/SourceKit/CodeComplete/complete_from_clang_module.swift +++ b/test/SourceKit/CodeComplete/complete_from_clang_module.swift @@ -1,11 +1,17 @@ import Foo -#^COMPLETE^# - // REQUIRES: objc_interop -// RUN: %target-swift-ide-test -code-completion -source-filename %s -F %S/../Inputs/libIDE-mock-sdk -code-completion-token=COMPLETE -code-completion-comments=true | %FileCheck %s -check-prefix=CHECK +// RUN: %sourcekitd-test -req=complete -pos=2:1 %s -- -F %S/../Inputs/libIDE-mock-sdk %s | %FileCheck %s + +// CHECK-LABEL: key.name: "fooIntVar", +// CHECK-NEXT: key.description: "fooIntVar", +// CHECK-NEXT: key.typename: "Int32", +// CHECK-NEXT: key.doc.brief: "Aaa. fooIntVar. Bbb.", +// CHECK-NEXT: key.context: source.codecompletion.context.othermodule, +// CHECK-NEXT: key.typerelation: source.codecompletion.typerelation.unknown, +// CHECK-NEXT: key.num_bytes_to_erase: 0, +// CHECK-NEXT: key.associated_usrs: "c:@fooIntVar", +// CHECK-NEXT: key.modulename: "Foo", +// CHECK-NEXT: key.sourcetext: "fooIntVar" +// CHECK-NEXT: }, -// CHECK: Decl[GlobalVar]/OtherModule[Foo]: fooIntVar[#Int32#]; -// CHECK-SAME-LABEL: name=fooIntVar; -// CHECK-SAME: briefcomment=Aaa. fooIntVar. Bbb.; -// CHECK-SAME: fullcomment=fooIntVarc:@fooIntVarvar fooIntVar: Int32 Aaa. fooIntVar. Bbb. diff --git a/test/SourceKit/CodeComplete/complete_member.swift b/test/SourceKit/CodeComplete/complete_member.swift index 0222d564edadf..e266560fbd064 100644 --- a/test/SourceKit/CodeComplete/complete_member.swift +++ b/test/SourceKit/CodeComplete/complete_member.swift @@ -39,7 +39,7 @@ func testOverrideUSR() { Derived(). } -// RUN: %sourcekitd-test -req=complete -pos=15:5 %s -- %s | %sed_clean > %t.response +// RUN: %sourcekitd-test -req=complete -pos=15:5 %s -- %s > %t.response // RUN: %diff -u %s.response %t.response // // RUN: %sourcekitd-test -req=complete -pos=19:5 %s -- %s | %FileCheck %s -check-prefix=CHECK-OPTIONAL From 041e85677b8e44f5c0e9a57fb191097a5edb6371 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Fri, 25 Jul 2025 20:52:18 +0300 Subject: [PATCH 50/58] [Test] Add IDE tests for full and brief documentation --- ...omments.swift => complete_doc_clang.swift} | 0 test/IDE/complete_doc_member.swift | 160 ++++++++++++++++++ test/IDE/complete_doc_top_level.swift | 68 ++++++++ 3 files changed, 228 insertions(+) rename test/IDE/clang-importing/{complete_with_clang_comments.swift => complete_doc_clang.swift} (100%) create mode 100644 test/IDE/complete_doc_member.swift create mode 100644 test/IDE/complete_doc_top_level.swift diff --git a/test/IDE/clang-importing/complete_with_clang_comments.swift b/test/IDE/clang-importing/complete_doc_clang.swift similarity index 100% rename from test/IDE/clang-importing/complete_with_clang_comments.swift rename to test/IDE/clang-importing/complete_doc_clang.swift diff --git a/test/IDE/complete_doc_member.swift b/test/IDE/complete_doc_member.swift new file mode 100644 index 0000000000000..68d4137f2e094 --- /dev/null +++ b/test/IDE/complete_doc_member.swift @@ -0,0 +1,160 @@ +// RUN: %batch-code-completion -source-filename %s -module-name CompleteDocTest -code-completion-comments=true + +protocol P1 { + /// requirement1 doc comment + /// + /// more description + var requirement1: String { get } + + func requirement2() + + /// requirement3 comment in P1 + func requirement3(x: Int) +} + +/// struct S +/// +/// More info on struct S +struct S1: P1 { + /// instanceVar1 description + var instanceVar1: String = "OK" + + /// instanceVar2 description + /// + /// Euler-Mascheroni constant + var instanceVar2: Double = 0.5772156649 + + /// struct instance func comment + /// + /// Does stuff with the instance. + func instanceFunc1() {} + + /// struct instance func comment + /// + /// Does stuff with the instance. + /// + /// - Parameters: + /// - x: what is x? + func instanceFunc2(x: String) {} + + /// subscript on struct S + /// + /// - Parameters: + /// - index: an index into S1 + subscript(index: Int) {} + + var requirement1: String = "name" + + func requirement2() {} + + /// requirement3 comment in S1 + func requirement3() {} +} + +extension S1 { + /// doc for extendedFunc1 + func extendedFunc1(x: Int, y: Int) -> Int { + return x + y * 2 + } + + func extendedFunc2() {} +} + +func testWithDot() { + S1().#^MEMBER_DOT^# + + // MEMBER_DOT: Begin completions, 11 items + + // MEMBER_DOT-NEXT: Keyword[self]/CurrNominal: self[#S1#]; name=self + + // MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar1[#String#]; name=instanceVar1; + // MEMBER_DOT-NEXT-SAME: briefcomment=instanceVar1 description; + // MEMBER_DOT-NEXT-SAME: fullcomment=instanceVar1s:15CompleteDocTest2S1V12instanceVar1SSvpvar instanceVar1: StringinstanceVar1 description + + // MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar2[#Double#]; name=instanceVar2; + // MEMBER_DOT-NEXT-SAME: briefcomment=instanceVar2 description; + // MEMBER_DOT-NEXT-SAME: fullcomment=instanceVar2s:15CompleteDocTest2S1V12instanceVar2Sdvpvar instanceVar2: DoubleinstanceVar2 descriptionEuler-Mascheroni constant + + // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc1()[#Void#]; name=instanceFunc1(); + // MEMBER_DOT-NEXT-SAME: briefcomment=struct instance func comment; + // MEMBER_DOT-NEXT-SAME: fullcomment=instanceFunc1()s:15CompleteDocTest2S1V13instanceFunc1yyFfunc instanceFunc1()struct instance func commentDoes stuff with the instance. + + // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc2({#x: String#})[#Void#]; name=instanceFunc2(x:); + // MEMBER_DOT-NEXT-SAME: briefcomment=struct instance func comment; + // MEMBER_DOT-NEXT-SAME: fullcomment=instanceFunc2(x:)s:15CompleteDocTest2S1V13instanceFunc21xySS_tFfunc instanceFunc2(x: String)struct instance func commentxinwhat is x?Does stuff with the instance. + + // MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: requirement1[#String#]; name=requirement1; + // MEMBER_DOT-NEXT-SAME: briefcomment=requirement1 doc comment; + // MEMBER_DOT-NEXT-SAME: fullcomment=requirement1s:15CompleteDocTest2P1P12requirement1SSvpvar requirement1: String { get }requirement1 doc commentmore descriptionThis documentation comment was inherited from P1. + + // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: requirement2()[#Void#]; name=requirement2() + // MEMBER_DOT-NEXT-SAME-NOT: briefcomment= + // MEMBER_DOT-NEXT-SAME-NOT: fullcomment= + + // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: requirement3()[#Void#]; name=requirement3(); + // MEMBER_DOT-NEXT-SAME: briefcomment=requirement3 comment in S1; + // MEMBER_DOT-NEXT-SAME: fullcomment=requirement3()s:15CompleteDocTest2S1V12requirement3yyFfunc requirement3()requirement3 comment in S1 + + // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: extendedFunc1({#x: Int#}, {#y: Int#})[#Int#]; name=extendedFunc1(x:y:); + // MEMBER_DOT-NEXT-SAME: briefcomment=doc for extendedFunc1; + // MEMBER_DOT-NEXT-SAME: fullcomment=extendedFunc1(x:y:)s:15CompleteDocTest2S1V13extendedFunc11x1yS2i_SitFfunc extendedFunc1(x: Int, y: Int) -> Intdoc for extendedFunc1 + + // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: extendedFunc2()[#Void#]; name=extendedFunc2() + // MEMBER_DOT-NEXT-SAME-NOT: briefcomment= + // MEMBER_DOT-NEXT-SAME-NOT: fullcomment= + + // MEMBER_DOT-NEXT: Decl[InstanceMethod]/Super: requirement3({#x: Int#})[#Void#]; name=requirement3(x:); + // MEMBER_DOT-NEXT-SAME: briefcomment=requirement3 comment in P1; + // MEMBER_DOT-NEXT-SAME: fullcomment=requirement3(x:)s:15CompleteDocTest2P1P12requirement31xySi_tFfunc requirement3(x: Int)requirement3 comment in P1 +} + +func testWithNoDot() { + S1()#^MEMBER_NO_DOT^# + + // MEMBER_NO_DOT: Begin completions, 12 items + // MEMBER_NO_DOT-NEXT: Keyword[self]/CurrNominal: .self[#S1#]; name=self + + // MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar1[#String#]; name=instanceVar1; + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=instanceVar1 description; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceVar1s:15CompleteDocTest2S1V12instanceVar1SSvpvar instanceVar1: StringinstanceVar1 description + + // MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar2[#Double#]; name=instanceVar2; + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=instanceVar2 description; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceVar2s:15CompleteDocTest2S1V12instanceVar2Sdvpvar instanceVar2: DoubleinstanceVar2 descriptionEuler-Mascheroni constant + + // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc1()[#Void#]; name=instanceFunc1(); + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=struct instance func comment; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceFunc1()s:15CompleteDocTest2S1V13instanceFunc1yyFfunc instanceFunc1()struct instance func commentDoes stuff with the instance. + + // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc2({#x: String#})[#Void#]; name=instanceFunc2(x:); + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=struct instance func comment; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceFunc2(x:)s:15CompleteDocTest2S1V13instanceFunc21xySS_tFfunc instanceFunc2(x: String)struct instance func commentxinwhat is x?Does stuff with the instance. + + // MEMBER_NO_DOT-NEXT: Decl[Subscript]/CurrNominal: [{#(index): Int#}][#<>#]; name=[:]; + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=subscript on struct S; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=subscript(_:)s:15CompleteDocTest2S1VyXeXecipsubscript(index: Int) -> <<error type>> { get }subscript on struct Sindexinan index into S1 + + // MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .requirement1[#String#]; name=requirement1; + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=requirement1 doc comment; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=requirement1s:15CompleteDocTest2P1P12requirement1SSvpvar requirement1: String { get }requirement1 doc commentmore descriptionThis documentation comment was inherited from P1. + + // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .requirement2()[#Void#]; name=requirement2() + // MEMBER_NO_DOT-NEXT-SAME-NOT: briefcomment= + // MEMBER_NO_DOT-NEXT-SAME-NOT: fullcomment= + + // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .requirement3()[#Void#]; name=requirement3(); + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=requirement3 comment in S1; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=requirement3()s:15CompleteDocTest2S1V12requirement3yyFfunc requirement3()requirement3 comment in S1 + + // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .extendedFunc1({#x: Int#}, {#y: Int#})[#Int#]; name=extendedFunc1(x:y:); + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=doc for extendedFunc1; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=extendedFunc1(x:y:)s:15CompleteDocTest2S1V13extendedFunc11x1yS2i_SitFfunc extendedFunc1(x: Int, y: Int) -> Intdoc for extendedFunc1 + + // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .extendedFunc2()[#Void#]; name=extendedFunc2() + // MEMBER_NO_DOT-NEXT-SAME-NOT: briefcomment= + // MEMBER_NO_DOT-NEXT-SAME-NOT: fullcomment= + + // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/Super: .requirement3({#x: Int#})[#Void#]; name=requirement3(x:); + // MEMBER_NO_DOT-NEXT-SAME: briefcomment=requirement3 comment in P1; + // MEMBER_NO_DOT-NEXT-SAME: fullcomment=requirement3(x:)s:15CompleteDocTest2P1P12requirement31xySi_tFfunc requirement3(x: Int)requirement3 comment in P1 +} diff --git a/test/IDE/complete_doc_top_level.swift b/test/IDE/complete_doc_top_level.swift new file mode 100644 index 0000000000000..0b716e013a9e8 --- /dev/null +++ b/test/IDE/complete_doc_top_level.swift @@ -0,0 +1,68 @@ +/// top-level var 1 comment +var topLevelVar1 = "Swift" + +/// top-level var 2 comment +/// +/// the meaning of life +var topLevelVar2 = 42 + +/// top-level func 1 comment +/// +/// Does stuff. +func topLevelFunc1() {} + +/// top-level func 2 comment +func topLevelFunc2() {} + +/// struct S1 +/// +/// More info on struct S +struct S1 {} + +/// C1 description +/// +/// does some work +class C1 {} + +/// P1 description +/// +/// defines some functionality +protocol P1 {} + +struct S2: P1 {} + +#^TOP_LEVEL^# + +// RUN: %target-swift-ide-test -code-completion -source-filename %s -module-name CompleteDocTest -code-completion-comments=true -code-completion-token=TOP_LEVEL | %FileCheck %s --check-prefix=TOP-LEVEL + +// TOP-LEVEL-DAG: Decl[GlobalVar]/Local: topLevelVar1[#String#]; name=topLevelVar1; +// TOP-LEVEL-DAG-SAME: briefcomment=top-level var 1 comment; +// TOP-LEVEL-DAG-SAME: fullcomment=topLevelVar1s:15CompleteDocTest12topLevelVar1SSvpvar topLevelVar1: Stringtop-level var 1 comment + +// TOP-LEVEL-DAG: Decl[GlobalVar]/Local: topLevelVar2[#Int#]; name=topLevelVar2; +// TOP-LEVEL-DAG-SAME: briefcomment=top-level var 2 comment; +// TOP-LEVEL-DAG-SAME: fullcomment=topLevelVar2s:15CompleteDocTest12topLevelVar2Sivpvar topLevelVar2: Inttop-level var 2 commentthe meaning of life + +// TOP-LEVEL-DAG: Decl[FreeFunction]/CurrModule: topLevelFunc1()[#Void#]; name=topLevelFunc1(); +// TOP-LEVEL-DAG-SAME: briefcomment=top-level func 1 comment; +// TOP-LEVEL-DAG-SAME: fullcomment=topLevelFunc1()s:15CompleteDocTest13topLevelFunc1yyFfunc topLevelFunc1()top-level func 1 commentDoes stuff. + +// TOP-LEVEL-DAG: Decl[FreeFunction]/CurrModule: topLevelFunc2()[#Void#]; name=topLevelFunc2(); +// TOP-LEVEL-DAG-SAME: briefcomment=top-level func 2 comment; +// TOP-LEVEL-DAG-SAME: fullcomment=topLevelFunc2()s:15CompleteDocTest13topLevelFunc2yyFfunc topLevelFunc2()top-level func 2 comment + +// TOP-LEVEL-DAG: Decl[Struct]/CurrModule: S1[#S1#]; name=S1; +// TOP-LEVEL-DAG-SAME: briefcomment=struct S1; +// TOP-LEVEL-DAG-SAME: fullcomment=S1s:15CompleteDocTest2S1Vstruct S1struct S1More info on struct S + +// TOP-LEVEL-DAG: Decl[Class]/CurrModule: C1[#C1#]; name=C1; +// TOP-LEVEL-DAG-SAME: briefcomment=C1 description; +// TOP-LEVEL-DAG-SAME: fullcomment=C1s:15CompleteDocTest2C1Cclass C1C1 descriptiondoes some work + +// TOP-LEVEL-DAG: Decl[Protocol]/CurrModule/Flair[RareType]: P1[#P1#]; name=P1; +// TOP-LEVEL-DAG-SAME: briefcomment=P1 description; +// TOP-LEVEL-DAG-SAME: fullcomment=P1s:15CompleteDocTest2P1Pprotocol P1P1 descriptiondefines some functionality + +// TOP-LEVEL-DAG: Decl[Struct]/CurrModule: S2[#S2#]; name=S2 +// TOP-LEVEL-DAG-SAME-NOT: briefcomment= +// TOP-LEVEL-DAG-SAME-NOT: fullcomment= From 469f24c2adaf1648c0fa78046e30ce969bc3de23 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 26 Jul 2025 18:29:56 +0300 Subject: [PATCH 51/58] [Demangle] Demangle operator function name in DeclNameExtractor --- include/swift/AST/DeclNameExtractor.h | 1 + lib/AST/DeclNameExtractor.cpp | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/include/swift/AST/DeclNameExtractor.h b/include/swift/AST/DeclNameExtractor.h index 0932ffc7e4934..92be7502b87b1 100644 --- a/include/swift/AST/DeclNameExtractor.h +++ b/include/swift/AST/DeclNameExtractor.h @@ -43,6 +43,7 @@ class DeclNameExtractor { SmallVectorImpl &ArgLabels); void extractArgLabelsFromType(Node *Type, SmallVectorImpl &ArgLabels); + DeclBaseName extractOperatorName(Node *node); }; /// Returns an identifier with the given name, automatically removing any diff --git a/lib/AST/DeclNameExtractor.cpp b/lib/AST/DeclNameExtractor.cpp index 9c70a85d53a91..f76ae768c32b3 100644 --- a/lib/AST/DeclNameExtractor.cpp +++ b/lib/AST/DeclNameExtractor.cpp @@ -86,10 +86,11 @@ bool DeclNameExtractor::extractFunctionLikeName( DeclBaseName BaseName; if (node->getKind() == Node::Kind::Function) { DeclName name; - if (!extractIdentifierName(node, name, privateDiscriminator)) - return false; - - BaseName = name.getBaseName(); + if (extractIdentifierName(node, name, privateDiscriminator)) { + BaseName = name.getBaseName(); + } else { + BaseName = extractOperatorName(node); + } } else { BaseName = DeclBaseName::createSubscript(); } @@ -170,6 +171,22 @@ void DeclNameExtractor::extractArgLabelsFromType( } } +DeclBaseName DeclNameExtractor::extractOperatorName(Node *node) { + auto Operator = node->getChild(1); + if (!Operator) + return DeclBaseName(); + + switch (Operator->getKind()) { + case Node::Kind::InfixOperator: + case Node::Kind::PrefixOperator: + case Node::Kind::PostfixOperator: + return getIdentifier(Ctx, Operator->getText()); + + default: + return DeclBaseName(); + } +} + Identifier swift::Demangle::getIdentifier(ASTContext &Ctx, StringRef name) { if (name.size() > 1 && name.front() == '`' && name.back() == '`') { // Raw identifiers have backticks affixed before mangling. We need to From d782aee247fd0a76eae909525bba06b33fb45900 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 26 Jul 2025 18:35:37 +0300 Subject: [PATCH 52/58] [Test] Disable USR to Decl verification in crashers with invalid nameless extension The USR for declarations within the extension with no type name have a USR that looks like a top-level declaration causing the lookup within swift::Demangle::getDeclForUSR to fail. --- .../crashers_fixed/003-swift-typebase-getcanonicaltype.swift | 5 ++++- .../006-swift-declcontext-getprotocolself.swift | 5 ++++- .../crashers_fixed/064-swift-genericfunctiontype-get.swift | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/validation-test/IDE/crashers_fixed/003-swift-typebase-getcanonicaltype.swift b/validation-test/IDE/crashers_fixed/003-swift-typebase-getcanonicaltype.swift index 081aca3826f85..3cb2a8f85892e 100644 --- a/validation-test/IDE/crashers_fixed/003-swift-typebase-getcanonicaltype.swift +++ b/validation-test/IDE/crashers_fixed/003-swift-typebase-getcanonicaltype.swift @@ -1,2 +1,5 @@ -// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s +// We disable USR to Decl verification since the USR for declarations within the +// extension with no type name have a USR that looks like a top-level declaration. + +// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s -code-completion-verify-usr-to-decl=false extension{struct E{enum C{let a{#^A^# diff --git a/validation-test/IDE/crashers_fixed/006-swift-declcontext-getprotocolself.swift b/validation-test/IDE/crashers_fixed/006-swift-declcontext-getprotocolself.swift index 921064a856277..91fdde27dea99 100644 --- a/validation-test/IDE/crashers_fixed/006-swift-declcontext-getprotocolself.swift +++ b/validation-test/IDE/crashers_fixed/006-swift-declcontext-getprotocolself.swift @@ -1,3 +1,6 @@ -// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s +// We disable USR to Decl verification since the USR for declarations within the +// extension with no type name have a USR that looks like a top-level declaration. + +// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s -code-completion-verify-usr-to-decl=false extension{protocol a{func p)struct A{protocol c let a{#^A^# diff --git a/validation-test/IDE/crashers_fixed/064-swift-genericfunctiontype-get.swift b/validation-test/IDE/crashers_fixed/064-swift-genericfunctiontype-get.swift index d51c49171897a..6ec6db919e5c6 100644 --- a/validation-test/IDE/crashers_fixed/064-swift-genericfunctiontype-get.swift +++ b/validation-test/IDE/crashers_fixed/064-swift-genericfunctiontype-get.swift @@ -1,3 +1,6 @@ -// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s +// We disable USR to Decl verification since the USR for declarations within the +// extension with no type name have a USR that looks like a top-level declaration. + +// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s -code-completion-verify-usr-to-decl=false extension{enum a Date: Sat, 2 Aug 2025 11:16:41 +0300 Subject: [PATCH 53/58] [Mangler] Mangle compatibility aliases as decls synthesized by ClangImporter --- lib/AST/ASTMangler.cpp | 15 +++++++++++++++ lib/ClangImporter/ClangImporter.cpp | 11 +++++++++++ test/APINotes/versioned-test-mangling.swift | 4 ++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index b7f53971dcc8b..d12bd36e0192f 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -2533,6 +2533,14 @@ ASTMangler::getSpecialManglingContext(const ValueDecl *decl, if (auto file = dyn_cast(decl->getDeclContext())) { if (file->getKind() == FileUnitKind::ClangModule || file->getKind() == FileUnitKind::DWARFModule) { + + // Use ClangImporterContext for compatibility aliases to avoid conflicting + // with the mangled name of the actual declaration. + if (auto *aliasDecl = dyn_cast(decl)) { + if (aliasDecl->isCompatibilityAlias()) + return ASTMangler::ClangImporterContext; + } + if (decl->getClangDecl()) return ASTMangler::ObjCContext; return ASTMangler::ClangImporterContext; @@ -3126,6 +3134,13 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl, // Always use Clang names for imported Clang declarations, unless they don't // have one. auto tryAppendClangName = [this, decl]() -> bool { + // We use the Swift name rather than the Clang name for compatibility + // aliases since they are ClangImporterContext entities. + if (auto *aliasDecl = dyn_cast(decl)) { + if (aliasDecl->isCompatibilityAlias()) + return false; + } + auto *nominal = dyn_cast(decl); auto namedDecl = getClangDeclForMangling(decl); if (!namedDecl) { diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index f32996e7afa94..e52b11fcedc54 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -3559,6 +3559,17 @@ void ClangImporter::lookupTypeDecl( if (auto ext = dyn_cast_or_null(imported)) { imported = ext->getExtendedNominal(); } + + // Look through compatibility aliases since we must have mangled the + // underlying type (see ASTMangler::getSpecialManglingContext). + if (auto *alias = dyn_cast_or_null(imported)) { + if (alias->isCompatibilityAlias()) { + imported = alias->getUnderlyingType()->getAnyNominal(); + assert(imported != nullptr && + "No underlying decl for a compatibility typealias"); + } + } + if (auto *importedType = dyn_cast_or_null(imported)) { foundViaClang = true; receiver(importedType); diff --git a/test/APINotes/versioned-test-mangling.swift b/test/APINotes/versioned-test-mangling.swift index 212275310d6a5..b75c8b4ac48c2 100644 --- a/test/APINotes/versioned-test-mangling.swift +++ b/test/APINotes/versioned-test-mangling.swift @@ -8,7 +8,7 @@ import APINotesFrameworkTest -// CHECK-TOP-ALIAS-4: typealias ImportantCStruct = VeryImportantCStruct +// CHECK-TOP-ALIAS-4: struct VeryImportantCStruct { // CHECK-TOP-ALIAS-5: struct VeryImportantCStruct { -// CHECK-NESTED-ALIAS-4: typealias InnerInSwift5 = Outer.Inner +// CHECK-NESTED-ALIAS-4: struct Inner { // CHECK-NESTED-ALIAS-5: struct Inner { From 5191756eb1cf9211e818715e56f606af348b0c7b Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Mon, 4 Aug 2025 15:40:11 +0300 Subject: [PATCH 54/58] [Test] Add checks for typealias mangling as Clang-importer-synthesized --- test/APINotes/versioned-test-mangling.swift | 26 ++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/test/APINotes/versioned-test-mangling.swift b/test/APINotes/versioned-test-mangling.swift index b75c8b4ac48c2..87d157639480a 100644 --- a/test/APINotes/versioned-test-mangling.swift +++ b/test/APINotes/versioned-test-mangling.swift @@ -1,14 +1,24 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 4 -find-mangled '$sSo11SomeCStructV' | %FileCheck -check-prefix=CHECK-TOP-ALIAS-4 %s -// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 5 -find-mangled '$sSo11SomeCStructV' | %FileCheck -check-prefix=CHECK-TOP-ALIAS-5 %s +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 4 -find-mangled '$sSo11SomeCStructV' | %FileCheck -check-prefix=CHECK-TOP-ALIAS-UNDERLYING-4 %s +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 5 -find-mangled '$sSo11SomeCStructV' | %FileCheck -check-prefix=CHECK-TOP-ALIAS-UNDERLYING-5 %s -// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 4 -find-mangled '$sSo13InnerInSwift5V' | %FileCheck -check-prefix=CHECK-NESTED-ALIAS-4 %s -// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 5 -find-mangled '$sSo13InnerInSwift5V' | %FileCheck -check-prefix=CHECK-NESTED-ALIAS-5 %s +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 4 -find-mangled '$sSo13InnerInSwift5V' | %FileCheck -check-prefix=CHECK-NESTED-ALIAS-UNDERLYING-4 %s +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 5 -find-mangled '$sSo13InnerInSwift5V' | %FileCheck -check-prefix=CHECK-NESTED-ALIAS-UNDERLYING-5 %s + +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 4 -find-mangled '$sSC16ImportantCStructa' | %FileCheck -check-prefix=CHECK-TOP-ALIAS-SYNTHESIZED-4 %s +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 5 -find-mangled '$sSC16ImportantCStructa' | %FileCheck -check-prefix=CHECK-TOP-ALIAS-SYNTHESIZED-5 %s + +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 4 -find-mangled '$sSC13InnerInSwift5a' | %FileCheck -check-prefix=CHECK-NESTED-ALIAS-SYNTHESIZED-4 %s +// RUN: %target-swift-ide-test -F %S/Inputs/custom-frameworks -print-ast-typechecked -source-filename %s -swift-version 5 -find-mangled '$sSC13InnerInSwift5a' | %FileCheck -check-prefix=CHECK-NESTED-ALIAS-SYNTHESIZED-5 %s import APINotesFrameworkTest -// CHECK-TOP-ALIAS-4: struct VeryImportantCStruct { -// CHECK-TOP-ALIAS-5: struct VeryImportantCStruct { -// CHECK-NESTED-ALIAS-4: struct Inner { -// CHECK-NESTED-ALIAS-5: struct Inner { +// CHECK-TOP-ALIAS-UNDERLYING-4: struct VeryImportantCStruct { +// CHECK-TOP-ALIAS-UNDERLYING-5: struct VeryImportantCStruct { +// CHECK-NESTED-ALIAS-UNDERLYING-4: struct Inner { +// CHECK-NESTED-ALIAS-UNDERLYING-5: struct Inner { +// CHECK-TOP-ALIAS-SYNTHESIZED-4: typealias ImportantCStruct = VeryImportantCStruct +// CHECK-TOP-ALIAS-SYNTHESIZED-5: typealias ImportantCStruct = VeryImportantCStruct +// CHECK-NESTED-ALIAS-SYNTHESIZED-4: typealias InnerInSwift5 = Outer.Inner +// CHECK-NESTED-ALIAS-SYNTHESIZED-5: typealias InnerInSwift5 = Outer.Inner From fb8212a80a8394b1cce41203e2c2d1242bfd16bc Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Wed, 13 Aug 2025 22:19:39 +0300 Subject: [PATCH 55/58] [IDE] Provide raw & XML documentation for completion items --- include/swift/IDE/CodeCompletionResult.h | 17 ++++++++++---- .../bin/InProc/CodeCompletionSwiftInterop.cpp | 22 +++++++++++++++++-- .../bin/InProc/CodeCompletionSwiftInterop.h | 11 +++++++--- .../InProc/sourcekitdInProc-darwin.exports | 3 ++- .../bin/InProc/sourcekitdInProc.exports | 3 ++- tools/swift-ide-test/swift-ide-test.cpp | 19 ++++++++++++---- 6 files changed, 60 insertions(+), 15 deletions(-) diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index b1c60b0b5fe35..c9221ea6b30d3 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -755,17 +755,26 @@ class CodeCompletionResult { return getContextFreeResult().getBriefDocComment(); } - /// Prints the full documentation comment as XML to the provided \c OS stream. + /// Prints the full documentation comment as XML to the provided \p OS stream. /// - /// \returns true if the result has a full documentation comment, false - /// otherwise. - bool printFullDocComment(raw_ostream &OS) const { + /// \returns true if the result has a documentation comment. + bool printFullDocCommentAsXML(raw_ostream &OS) const { if (auto *D = getAssociatedDecl()) return ide::getDocumentationCommentAsXML(D, OS); return false; } + /// Prints the raw documentation comment to the provided \p OS stream. + /// + /// \returns true if the result has a documentation comment. + bool printRawDocComment(raw_ostream &OS) const { + if (auto *D = getAssociatedDecl()) + return ide::getRawDocumentationComment(D, OS); + + return false; + } + ArrayRef getAssociatedUSRs() const { return getContextFreeResult().getAssociatedUSRs(); } diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp index ef8b2e0a57e07..bbca01be8ae67 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.cpp @@ -663,7 +663,7 @@ void swiftide_completion_item_get_doc_brief( handler(item.getBriefDocComment().data()); } -void swiftide_completion_item_get_doc_full( +void swiftide_completion_item_get_doc_full_as_xml( swiftide_completion_response_t _response, swiftide_completion_item_t _item, void (^handler)(const char *)) { auto &response = *static_cast(_response); @@ -672,7 +672,25 @@ void swiftide_completion_item_get_doc_full( response.scratch.clear(); { llvm::raw_svector_ostream OS(response.scratch); - item.printFullDocComment(OS); + item.printFullDocCommentAsXML(OS); + } + + if (response.scratch.empty()) { + return handler(nullptr); + } + handler(response.scratch.c_str()); +} + +void swiftide_completion_item_get_doc_raw( + swiftide_completion_response_t _response, swiftide_completion_item_t _item, + void (^handler)(const char *)) { + auto &response = *static_cast(_response); + auto &item = *static_cast(_item); + + response.scratch.clear(); + { + llvm::raw_svector_ostream OS(response.scratch); + item.printRawDocComment(OS); } if (response.scratch.empty()) { diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h index d8abbed279f50..2b6ea20507ee9 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/CodeCompletionSwiftInterop.h @@ -348,9 +348,14 @@ swiftide_completion_item_get_doc_brief(swiftide_completion_response_t, void (^handler)(const char *)); SWIFTIDE_PUBLIC void -swiftide_completion_item_get_doc_full(swiftide_completion_response_t, - swiftide_completion_item_t, - void (^handler)(const char *)); +swiftide_completion_item_get_doc_full_as_xml(swiftide_completion_response_t, + swiftide_completion_item_t, + void (^handler)(const char *)); + +SWIFTIDE_PUBLIC void +swiftide_completion_item_get_doc_raw(swiftide_completion_response_t, + swiftide_completion_item_t, + void (^handler)(const char *)); SWIFTIDE_PUBLIC void swiftide_completion_item_get_associated_usrs( swiftide_completion_response_t, swiftide_completion_item_t, diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports index ddad2c46cafdf..c22cb61f796c1 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc-darwin.exports @@ -149,7 +149,8 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief -swiftide_completion_item_get_doc_full +swiftide_completion_item_get_doc_full_as_xml +swiftide_completion_item_get_doc_raw swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports index 928e08b49afd0..ed1765152d5e0 100644 --- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports +++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.exports @@ -149,7 +149,8 @@ swiftide_completion_item_get_associated_kind swiftide_completion_item_get_associated_usrs swiftide_completion_item_get_diagnostic swiftide_completion_item_get_doc_brief -swiftide_completion_item_get_doc_full +swiftide_completion_item_get_doc_full_as_xml +swiftide_completion_item_get_doc_raw swiftide_completion_item_get_flair swiftide_completion_item_get_kind swiftide_completion_item_get_label diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 8c8a7949f75b5..40594dc90cef7 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -1361,11 +1361,22 @@ static void printCodeCompletionResultsImpl( OS << "; briefcomment=" << BriefComment; } - SmallString<256> FullComment; - llvm::raw_svector_ostream CommentOS(FullComment); + { + SmallString<256> CommentAsXML; + llvm::raw_svector_ostream CommentOS(CommentAsXML); + + if (Result->printFullDocCommentAsXML(CommentOS) && + !CommentAsXML.empty()) + OS << "; xmlcomment=" << CommentAsXML; + } - if (Result->printFullDocComment(CommentOS) && !FullComment.empty()) - OS << "; fullcomment=" << FullComment; + { + SmallString<256> RawComment; + llvm::raw_svector_ostream CommentOS(RawComment); + + if (Result->printRawDocComment(CommentOS) && !RawComment.empty()) + OS << "; rawcomment=" << RawComment; + } } if (Ctx) { From e59f263e6b10c8a1c9dd7e71c635e6b135e9a0d1 Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 16 Aug 2025 00:54:24 +0300 Subject: [PATCH 56/58] [Test] Enable USR to Decl verification in IDE/complete_crashes & IDE/complete_where_clause --- test/IDE/complete_crashes.swift | 10 ++-------- test/IDE/complete_where_clause.swift | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/test/IDE/complete_crashes.swift b/test/IDE/complete_crashes.swift index 4d30d5adb4483..708084ae4bc01 100644 --- a/test/IDE/complete_crashes.swift +++ b/test/IDE/complete_crashes.swift @@ -84,7 +84,7 @@ private protocol RoundRobin : Sendable, Receivable { #endif // rdar://problem/21435993 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_21435993 -code-completion-verify-usr-to-decl=false +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_21435993 class C2 { func test() { do {} catch { #^RDAR_21435993^# } @@ -194,14 +194,8 @@ struct S_RDAR_28991372 { S_RDAR_28991372(x: #^RDAR_28991372^#, y: <#T##Int#>) // RDAR_28991372: Begin completions -// FIXME: We disable USR to Decl verification in the following test as it -// fails to lookup the ProtocolDecl for P due to extension binding -// triggering module lookup during the first pass of IDE inspection -// (when not all decls have been parsed yet) and caching the top-level -// decls in the module's SourceCacheLookup ignoring decls added later -// through SourceFile::addTopLevelDecl. // rdar://problem/31981486 -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_31981486 -code-completion-verify-usr-to-decl=false | %FileCheck %s -check-prefix=RDAR_31981486 +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_31981486 | %FileCheck %s -check-prefix=RDAR_31981486 protocol P where #^RDAR_31981486^# // RDAR_31981486: Begin completions diff --git a/test/IDE/complete_where_clause.swift b/test/IDE/complete_where_clause.swift index 7512159944216..8a78c99466071 100644 --- a/test/IDE/complete_where_clause.swift +++ b/test/IDE/complete_where_clause.swift @@ -41,14 +41,8 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=EXT_SECONDTYPE | %FileCheck %s -check-prefix=EXT_SECONDTYPE // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=WHERE_CLAUSE_WITH_EQUAL | %FileCheck %s -check-prefix=WHERE_CLAUSE_WITH_EQUAL -// FIXME: We disable USR to Decl verification in the following 2 tests as it -// fails to lookup the ProtocolDecl for P3 and P4 due to extension -// binding triggering module lookup during the first pass of IDE -// inspection (when not all decls have been parsed yet) and caching the -// top-level decls in the module's SourceCacheLookup ignoring decls added -// later through SourceFile::addTopLevelDecl. -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL -code-completion-verify-usr-to-decl=false | %FileCheck %s -check-prefix=PROTOCOL -// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SELF -code-completion-verify-usr-to-decl=false | %FileCheck %s -check-prefix=PROTOCOL_SELF +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL | %FileCheck %s -check-prefix=PROTOCOL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PROTOCOL_SELF | %FileCheck %s -check-prefix=PROTOCOL_SELF class A1 {} From 83da9559d4bef3b60939352331511e2bbed9da1d Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 16 Aug 2025 16:07:12 +0300 Subject: [PATCH 57/58] [Test] Add sort by name option to swift-ide-test for completion --- tools/swift-ide-test/swift-ide-test.cpp | 28 ++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp index 40594dc90cef7..aab092b4e5150 100644 --- a/tools/swift-ide-test/swift-ide-test.cpp +++ b/tools/swift-ide-test/swift-ide-test.cpp @@ -510,6 +510,11 @@ CodeCompletionAnnotateResults("code-completion-annotate-results", llvm::cl::cat(Category), llvm::cl::init(false)); +static llvm::cl::opt +CodeCompletionSortByName("code-completion-sort-by-name", + llvm::cl::desc("Sort completion results by name"), + llvm::cl::cat(Category), llvm::cl::init(false)); + static llvm::cl::opt CodeCompletionVerifyUSRToDecl("code-completion-verify-usr-to-decl", llvm::cl::desc("Verify USR to Decl reconstruction"), @@ -1317,7 +1322,14 @@ doConformingMethodList(const CompilerInvocation &InitInvok, static void printCodeCompletionResultsImpl( ArrayRef Results, llvm::raw_ostream &OS, bool IncludeKeywords, bool IncludeComments, bool IncludeSourceText, - bool PrintAnnotatedDescription, const ASTContext *Ctx) { + bool PrintAnnotatedDescription, bool SortByName, const ASTContext *Ctx) { + std::vector SortedResultsStorage; + if (SortByName) { + SortedResultsStorage = + CodeCompletionContext::sortCompletionResults(Results); + Results = SortedResultsStorage; + } + unsigned NumResults = 0; for (auto Result : Results) { if (!IncludeKeywords && @@ -1437,13 +1449,13 @@ printCodeCompletionLookedupTypeNames(ArrayRef names, static int printCodeCompletionResults( CancellableResult CancellableResult, bool IncludeKeywords, bool IncludeComments, bool IncludeSourceText, - bool PrintAnnotatedDescription) { + bool PrintAnnotatedDescription, bool SortByName) { llvm::raw_fd_ostream &OS = llvm::outs(); return printResult( CancellableResult, [&](const CodeCompleteResult &Result) { printCodeCompletionResultsImpl( Result.ResultSink.Results, OS, IncludeKeywords, IncludeComments, - IncludeSourceText, PrintAnnotatedDescription, + IncludeSourceText, PrintAnnotatedDescription, SortByName, &Result.Info.compilerInstance->getASTContext()); printCodeCompletionLookedupTypeNames( Result.Info.completionContext->LookedupNominalTypeNames, OS); @@ -1457,6 +1469,7 @@ doCodeCompletion(const CompilerInvocation &InitInvok, StringRef SourceFilename, bool CodeCompletionDiagnostics, bool CodeCompletionKeywords, bool CodeCompletionComments, bool CodeCompletionAnnotateResults, + bool CodeCompletionSortByName, bool CodeCompletionAddInitsToTopLevel, bool CodeCompletionAddCallWithNoDefaultArgs, bool CodeCompletionSourceText, @@ -1487,7 +1500,8 @@ doCodeCompletion(const CompilerInvocation &InitInvok, StringRef SourceFilename, [&](CancellableResult Result) { ExitCode = printCodeCompletionResults( Result, CodeCompletionKeywords, CodeCompletionComments, - CodeCompletionSourceText, CodeCompletionAnnotateResults); + CodeCompletionSourceText, CodeCompletionAnnotateResults, + CodeCompletionSortByName); }); return ExitCode; }); @@ -1500,6 +1514,7 @@ static int doBatchCodeCompletion(const CompilerInvocation &InitInvok, bool CodeCompletionKeywords, bool CodeCompletionComments, bool CodeCompletionAnnotateResults, + bool CodeCompletionSortByName, bool CodeCompletionAddInitsToTopLevel, bool CodeCompletionAddCallWithNoDefaultArgs, bool CodeCompletionSourceText, @@ -1673,7 +1688,7 @@ static int doBatchCodeCompletion(const CompilerInvocation &InitInvok, printCodeCompletionResultsImpl( Result->ResultSink.Results, OS, IncludeKeywords, IncludeComments, IncludeSourceText, - CodeCompletionAnnotateResults, + CodeCompletionAnnotateResults, CodeCompletionSortByName, &Result->Info.compilerInstance->getASTContext()); printCodeCompletionLookedupTypeNames( Result->Info.completionContext->LookedupNominalTypeNames, OS); @@ -4412,6 +4427,7 @@ int main(int argc, char *argv[]) { contextualResults, llvm::outs(), options::CodeCompletionKeywords, options::CodeCompletionComments, options::CodeCompletionSourceText, options::CodeCompletionAnnotateResults, + options::CodeCompletionSortByName, /*Ctx=*/nullptr); } @@ -4766,6 +4782,7 @@ int main(int argc, char *argv[]) { InitInvok, options::SourceFilename, options::CodeCompletionDiagnostics, options::CodeCompletionKeywords, options::CodeCompletionComments, options::CodeCompletionAnnotateResults, + options::CodeCompletionSortByName, options::CodeCompleteInitsInPostfixExpr, options::CodeCompletionAddCallWithNoDefaultArgs, options::CodeCompletionSourceText, @@ -4782,6 +4799,7 @@ int main(int argc, char *argv[]) { options::CodeCompletionToken, options::CodeCompletionDiagnostics, options::CodeCompletionKeywords, options::CodeCompletionComments, options::CodeCompletionAnnotateResults, + options::CodeCompletionSortByName, options::CodeCompleteInitsInPostfixExpr, options::CodeCompletionAddCallWithNoDefaultArgs, options::CodeCompletionSourceText, From 380b304d3888cce5089713939ce67bc6ad414b3b Mon Sep 17 00:00:00 2001 From: Ahmed Mahmoud Date: Sat, 16 Aug 2025 16:46:55 +0300 Subject: [PATCH 58/58] [Test] Update completion doc tests to check for raw doc comment --- .../clang-importing/complete_doc_clang.swift | 32 +-- test/IDE/complete_doc_member.swift | 219 ++++++++++-------- test/IDE/complete_doc_top_level.swift | 81 ++++--- 3 files changed, 193 insertions(+), 139 deletions(-) diff --git a/test/IDE/clang-importing/complete_doc_clang.swift b/test/IDE/clang-importing/complete_doc_clang.swift index ea7db6b9618da..d0d2f3f811b77 100644 --- a/test/IDE/clang-importing/complete_doc_clang.swift +++ b/test/IDE/clang-importing/complete_doc_clang.swift @@ -1,6 +1,6 @@ -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP -code-completion-comments=true \ +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP -code-completion-comments -code-completion-sort-by-name \ // RUN: -import-objc-header %S/Inputs/bridge.h -I %S/Inputs/somemod1 -I %S/Inputs/somemod2 | %FileCheck %s -check-prefix=CHECK-TOP -// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP -code-completion-comments=true \ +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -code-completion -source-filename %s -code-completion-token=TOP -code-completion-comments -code-completion-sort-by-name \ // RUN: -import-objc-header %S/Inputs/bridge.h -pch-output-dir %t.pch -I %S/Inputs/somemod1 -I %S/Inputs/somemod2 | %FileCheck %s -check-prefix=CHECK-TOP // REQUIRES: objc_interop @@ -9,18 +9,22 @@ import somemod2 #^TOP^# -// CHECK-TOP: name=some_func11(); -// CHECK-TOP-SAME: briefcomment=some_func11 is cool function.; -// CHECK-TOP-SAME: fullcomment=some_func11c:@F@some_func11func some_func11() some_func11 is cool function. +// CHECK-TOP-LABEL: name=some_func11(); +// CHECK-TOP-SAME: briefcomment=some_func11 is cool function.; +// CHECK-TOP-SAME: xmlcomment=some_func11c:@F@some_func11func some_func11() some_func11 is cool function.; +// CHECK-TOP-SAME: rawcomment=some_func11 is cool function. -// CHECK-TOP: name=some_func12(); -// CHECK-TOP-SAME: briefcomment=some_func12 is cool function.; -// CHECK-TOP-SAME: fullcomment=some_func12c:@F@some_func12func some_func12() some_func12 is cool function. +// CHECK-TOP-LABEL: name=some_func12(); +// CHECK-TOP-SAME: briefcomment=some_func12 is cool function.; +// CHECK-TOP-SAME: xmlcomment=some_func12c:@F@some_func12func some_func12() some_func12 is cool function.; +// CHECK-TOP-SAME: rawcomment=some_func12 is cool function. -// CHECK-TOP: name=some_func21(); -// CHECK-TOP-SAME: briefcomment=some_func21 is cool function.; -// CHECK-TOP-SAME: fullcomment=some_func21c:@F@some_func21func some_func21() some_func21 is cool function. +// CHECK-TOP-LABEL: name=some_func21(); +// CHECK-TOP-SAME: briefcomment=some_func21 is cool function.; +// CHECK-TOP-SAME: xmlcomment=some_func21c:@F@some_func21func some_func21() some_func21 is cool function.; +// CHECK-TOP-SAME: rawcomment=some_func21 is cool function. -// CHECK-TOP: name=some_func22(); -// CHECK-TOP-SAME: briefcomment=some_func22 is cool function.; -// CHECK-TOP-SAME: fullcomment=some_func22c:@F@some_func22func some_func22() some_func22 is cool function. +// CHECK-TOP-LABEL: name=some_func22(); +// CHECK-TOP-SAME: briefcomment=some_func22 is cool function.; +// CHECK-TOP-SAME: xmlcomment=some_func22c:@F@some_func22func some_func22() some_func22 is cool function.; +// CHECK-TOP-SAME: rawcomment=some_func22 is cool function. diff --git a/test/IDE/complete_doc_member.swift b/test/IDE/complete_doc_member.swift index 68d4137f2e094..dc624cd2ddac7 100644 --- a/test/IDE/complete_doc_member.swift +++ b/test/IDE/complete_doc_member.swift @@ -1,4 +1,4 @@ -// RUN: %batch-code-completion -source-filename %s -module-name CompleteDocTest -code-completion-comments=true +// RUN: %batch-code-completion -source-filename %s -module-name CompleteDocTest -code-completion-comments -code-completion-sort-by-name protocol P1 { /// requirement1 doc comment @@ -62,99 +62,134 @@ extension S1 { func testWithDot() { S1().#^MEMBER_DOT^# - - // MEMBER_DOT: Begin completions, 11 items - - // MEMBER_DOT-NEXT: Keyword[self]/CurrNominal: self[#S1#]; name=self - - // MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar1[#String#]; name=instanceVar1; - // MEMBER_DOT-NEXT-SAME: briefcomment=instanceVar1 description; - // MEMBER_DOT-NEXT-SAME: fullcomment=instanceVar1s:15CompleteDocTest2S1V12instanceVar1SSvpvar instanceVar1: StringinstanceVar1 description - - // MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar2[#Double#]; name=instanceVar2; - // MEMBER_DOT-NEXT-SAME: briefcomment=instanceVar2 description; - // MEMBER_DOT-NEXT-SAME: fullcomment=instanceVar2s:15CompleteDocTest2S1V12instanceVar2Sdvpvar instanceVar2: DoubleinstanceVar2 descriptionEuler-Mascheroni constant - - // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc1()[#Void#]; name=instanceFunc1(); - // MEMBER_DOT-NEXT-SAME: briefcomment=struct instance func comment; - // MEMBER_DOT-NEXT-SAME: fullcomment=instanceFunc1()s:15CompleteDocTest2S1V13instanceFunc1yyFfunc instanceFunc1()struct instance func commentDoes stuff with the instance. - - // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc2({#x: String#})[#Void#]; name=instanceFunc2(x:); - // MEMBER_DOT-NEXT-SAME: briefcomment=struct instance func comment; - // MEMBER_DOT-NEXT-SAME: fullcomment=instanceFunc2(x:)s:15CompleteDocTest2S1V13instanceFunc21xySS_tFfunc instanceFunc2(x: String)struct instance func commentxinwhat is x?Does stuff with the instance. - - // MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: requirement1[#String#]; name=requirement1; - // MEMBER_DOT-NEXT-SAME: briefcomment=requirement1 doc comment; - // MEMBER_DOT-NEXT-SAME: fullcomment=requirement1s:15CompleteDocTest2P1P12requirement1SSvpvar requirement1: String { get }requirement1 doc commentmore descriptionThis documentation comment was inherited from P1. - - // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: requirement2()[#Void#]; name=requirement2() - // MEMBER_DOT-NEXT-SAME-NOT: briefcomment= - // MEMBER_DOT-NEXT-SAME-NOT: fullcomment= - - // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: requirement3()[#Void#]; name=requirement3(); - // MEMBER_DOT-NEXT-SAME: briefcomment=requirement3 comment in S1; - // MEMBER_DOT-NEXT-SAME: fullcomment=requirement3()s:15CompleteDocTest2S1V12requirement3yyFfunc requirement3()requirement3 comment in S1 - - // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: extendedFunc1({#x: Int#}, {#y: Int#})[#Int#]; name=extendedFunc1(x:y:); - // MEMBER_DOT-NEXT-SAME: briefcomment=doc for extendedFunc1; - // MEMBER_DOT-NEXT-SAME: fullcomment=extendedFunc1(x:y:)s:15CompleteDocTest2S1V13extendedFunc11x1yS2i_SitFfunc extendedFunc1(x: Int, y: Int) -> Intdoc for extendedFunc1 - - // MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: extendedFunc2()[#Void#]; name=extendedFunc2() - // MEMBER_DOT-NEXT-SAME-NOT: briefcomment= - // MEMBER_DOT-NEXT-SAME-NOT: fullcomment= - - // MEMBER_DOT-NEXT: Decl[InstanceMethod]/Super: requirement3({#x: Int#})[#Void#]; name=requirement3(x:); - // MEMBER_DOT-NEXT-SAME: briefcomment=requirement3 comment in P1; - // MEMBER_DOT-NEXT-SAME: fullcomment=requirement3(x:)s:15CompleteDocTest2P1P12requirement31xySi_tFfunc requirement3(x: Int)requirement3 comment in P1 } +// MEMBER_DOT: Begin completions, 11 items + +// MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: extendedFunc1({#x: Int#}, {#y: Int#})[#Int#]; name=extendedFunc1(x:y:); +// MEMBER_DOT-SAME: briefcomment=doc for extendedFunc1; +// MEMBER_DOT-SAME: xmlcomment=extendedFunc1(x:y:)s:15CompleteDocTest2S1V13extendedFunc11x1yS2i_SitFfunc extendedFunc1(x: Int, y: Int) -> Intdoc for extendedFunc1; +// MEMBER_DOT-SAME: rawcomment=doc for extendedFunc1 + +// MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: extendedFunc2()[#Void#]; name=extendedFunc2(){{$}} + +// MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc1()[#Void#]; name=instanceFunc1(); +// MEMBER_DOT-SAME: briefcomment=struct instance func comment; +// MEMBER_DOT-SAME: xmlcomment=instanceFunc1()s:15CompleteDocTest2S1V13instanceFunc1yyFfunc instanceFunc1()struct instance func commentDoes stuff with the instance.; +// MEMBER_DOT-SAME: rawcomment=struct instance func comment +// MEMBER_DOT-EMPTY: +// MEMBER_DOT-NEXT: Does stuff with the instance. + +// MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: instanceFunc2({#x: String#})[#Void#]; name=instanceFunc2(x:); +// MEMBER_DOT-SAME: briefcomment=struct instance func comment; +// MEMBER_DOT-SAME: xmlcomment=instanceFunc2(x:)s:15CompleteDocTest2S1V13instanceFunc21xySS_tFfunc instanceFunc2(x: String)struct instance func commentxinwhat is x?Does stuff with the instance.; +// MEMBER_DOT-SAME: rawcomment=struct instance func comment +// MEMBER_DOT-EMPTY: +// MEMBER_DOT-NEXT: Does stuff with the instance. +// MEMBER_DOT-EMPTY: +// MEMBER_DOT-NEXT: - Parameters: +// MEMBER_DOT-NEXT: - x: what is x? + +// MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar1[#String#]; name=instanceVar1; +// MEMBER_DOT-SAME: briefcomment=instanceVar1 description; +// MEMBER_DOT-SAME: xmlcomment=instanceVar1s:15CompleteDocTest2S1V12instanceVar1SSvpvar instanceVar1: StringinstanceVar1 description; +// MEMBER_DOT-SAME: rawcomment=instanceVar1 description + +// MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: instanceVar2[#Double#]; name=instanceVar2; +// MEMBER_DOT-SAME: briefcomment=instanceVar2 description; +// MEMBER_DOT-SAME: xmlcomment=instanceVar2s:15CompleteDocTest2S1V12instanceVar2Sdvpvar instanceVar2: DoubleinstanceVar2 descriptionEuler-Mascheroni constant; +// MEMBER_DOT-SAME: rawcomment=instanceVar2 description +// MEMBER_DOT-EMPTY: +// MEMBER_DOT-NEXT: Euler-Mascheroni constant + +// MEMBER_DOT-NEXT: Decl[InstanceVar]/CurrNominal: requirement1[#String#]; name=requirement1; +// MEMBER_DOT-SAME: briefcomment=requirement1 doc comment; +// MEMBER_DOT-SAME: xmlcomment=requirement1s:15CompleteDocTest2P1P12requirement1SSvpvar requirement1: String { get }requirement1 doc commentmore descriptionThis documentation comment was inherited from P1.; +// MEMBER_DOT-SAME: rawcomment=requirement1 doc comment +// MEMBER_DOT-EMPTY: +// MEMBER_DOT-NEXT: more description + +// MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: requirement2()[#Void#]; name=requirement2(){{$}} + +// MEMBER_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: requirement3()[#Void#]; name=requirement3(); +// MEMBER_DOT-SAME: briefcomment=requirement3 comment in S1; +// MEMBER_DOT-SAME: xmlcomment=requirement3()s:15CompleteDocTest2S1V12requirement3yyFfunc requirement3()requirement3 comment in S1; +// MEMBER_DOT-SAME: rawcomment=requirement3 comment in S1 + +// MEMBER_DOT-NEXT: Decl[InstanceMethod]/Super: requirement3({#x: Int#})[#Void#]; name=requirement3(x:); +// MEMBER_DOT-SAME: briefcomment=requirement3 comment in P1; +// MEMBER_DOT-SAME: xmlcomment=requirement3(x:)s:15CompleteDocTest2P1P12requirement31xySi_tFfunc requirement3(x: Int)requirement3 comment in P1; +// MEMBER_DOT-SAME: rawcomment=requirement3 comment in P1 + +// MEMBER_DOT-NEXT: Keyword[self]/CurrNominal: self[#S1#]; name=self{{$}} + func testWithNoDot() { S1()#^MEMBER_NO_DOT^# - - // MEMBER_NO_DOT: Begin completions, 12 items - // MEMBER_NO_DOT-NEXT: Keyword[self]/CurrNominal: .self[#S1#]; name=self - - // MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar1[#String#]; name=instanceVar1; - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=instanceVar1 description; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceVar1s:15CompleteDocTest2S1V12instanceVar1SSvpvar instanceVar1: StringinstanceVar1 description - - // MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar2[#Double#]; name=instanceVar2; - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=instanceVar2 description; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceVar2s:15CompleteDocTest2S1V12instanceVar2Sdvpvar instanceVar2: DoubleinstanceVar2 descriptionEuler-Mascheroni constant - - // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc1()[#Void#]; name=instanceFunc1(); - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=struct instance func comment; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceFunc1()s:15CompleteDocTest2S1V13instanceFunc1yyFfunc instanceFunc1()struct instance func commentDoes stuff with the instance. - - // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc2({#x: String#})[#Void#]; name=instanceFunc2(x:); - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=struct instance func comment; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=instanceFunc2(x:)s:15CompleteDocTest2S1V13instanceFunc21xySS_tFfunc instanceFunc2(x: String)struct instance func commentxinwhat is x?Does stuff with the instance. - - // MEMBER_NO_DOT-NEXT: Decl[Subscript]/CurrNominal: [{#(index): Int#}][#<>#]; name=[:]; - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=subscript on struct S; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=subscript(_:)s:15CompleteDocTest2S1VyXeXecipsubscript(index: Int) -> <<error type>> { get }subscript on struct Sindexinan index into S1 - - // MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .requirement1[#String#]; name=requirement1; - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=requirement1 doc comment; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=requirement1s:15CompleteDocTest2P1P12requirement1SSvpvar requirement1: String { get }requirement1 doc commentmore descriptionThis documentation comment was inherited from P1. - - // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .requirement2()[#Void#]; name=requirement2() - // MEMBER_NO_DOT-NEXT-SAME-NOT: briefcomment= - // MEMBER_NO_DOT-NEXT-SAME-NOT: fullcomment= - - // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .requirement3()[#Void#]; name=requirement3(); - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=requirement3 comment in S1; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=requirement3()s:15CompleteDocTest2S1V12requirement3yyFfunc requirement3()requirement3 comment in S1 - - // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .extendedFunc1({#x: Int#}, {#y: Int#})[#Int#]; name=extendedFunc1(x:y:); - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=doc for extendedFunc1; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=extendedFunc1(x:y:)s:15CompleteDocTest2S1V13extendedFunc11x1yS2i_SitFfunc extendedFunc1(x: Int, y: Int) -> Intdoc for extendedFunc1 - - // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .extendedFunc2()[#Void#]; name=extendedFunc2() - // MEMBER_NO_DOT-NEXT-SAME-NOT: briefcomment= - // MEMBER_NO_DOT-NEXT-SAME-NOT: fullcomment= - - // MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/Super: .requirement3({#x: Int#})[#Void#]; name=requirement3(x:); - // MEMBER_NO_DOT-NEXT-SAME: briefcomment=requirement3 comment in P1; - // MEMBER_NO_DOT-NEXT-SAME: fullcomment=requirement3(x:)s:15CompleteDocTest2P1P12requirement31xySi_tFfunc requirement3(x: Int)requirement3 comment in P1 } + +// MEMBER_NO_DOT: Begin completions, 12 items + +// MEMBER_NO_DOT-NEXT: Decl[Subscript]/CurrNominal: [{#(index): Int#}][#<>#]; name=[:]; +// MEMBER_NO_DOT-SAME: briefcomment=subscript on struct S; +// MEMBER_NO_DOT-SAME: xmlcomment=subscript(_:)s:15CompleteDocTest2S1VyXeXecipsubscript(index: Int) -> <<error type>> { get }subscript on struct Sindexinan index into S1; +// MEMBER_NO_DOT-SAME: rawcomment=subscript on struct S +// MEMBER_NO_DOT-EMPTY: +// MEMBER_NO_DOT-NEXT: - Parameters: +// MEMBER_NO_DOT-NEXT: - index: an index into S1 + +// MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .extendedFunc1({#x: Int#}, {#y: Int#})[#Int#]; name=extendedFunc1(x:y:); +// MEMBER_NO_DOT-SAME: briefcomment=doc for extendedFunc1; +// MEMBER_NO_DOT-SAME: xmlcomment=extendedFunc1(x:y:)s:15CompleteDocTest2S1V13extendedFunc11x1yS2i_SitFfunc extendedFunc1(x: Int, y: Int) -> Intdoc for extendedFunc1; +// MEMBER_NO_DOT-SAME: rawcomment=doc for extendedFunc1 + +// MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .extendedFunc2()[#Void#]; name=extendedFunc2() + +// MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc1()[#Void#]; name=instanceFunc1(); +// MEMBER_NO_DOT-SAME: briefcomment=struct instance func comment; +// MEMBER_NO_DOT-SAME: xmlcomment=instanceFunc1()s:15CompleteDocTest2S1V13instanceFunc1yyFfunc instanceFunc1()struct instance func commentDoes stuff with the instance.; +// MEMBER_NO_DOT-SAME: rawcomment=struct instance func comment +// MEMBER_NO_DOT-EMPTY: +// MEMBER_NO_DOT-NEXT: Does stuff with the instance. + +// MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .instanceFunc2({#x: String#})[#Void#]; name=instanceFunc2(x:); +// MEMBER_NO_DOT-SAME: briefcomment=struct instance func comment; +// MEMBER_NO_DOT-SAME: xmlcomment=instanceFunc2(x:)s:15CompleteDocTest2S1V13instanceFunc21xySS_tFfunc instanceFunc2(x: String)struct instance func commentxinwhat is x?Does stuff with the instance.; +// MEMBER_NO_DOT-SAME: rawcomment=struct instance func comment +// MEMBER_NO_DOT-EMPTY: +// MEMBER_NO_DOT-NEXT: Does stuff with the instance. +// MEMBER_NO_DOT-EMPTY: +// MEMBER_NO_DOT-NEXT: - Parameters: +// MEMBER_NO_DOT-NEXT: - x: what is x? + +// MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar1[#String#]; name=instanceVar1; +// MEMBER_NO_DOT-SAME: briefcomment=instanceVar1 description; +// MEMBER_NO_DOT-SAME: xmlcomment=instanceVar1s:15CompleteDocTest2S1V12instanceVar1SSvpvar instanceVar1: StringinstanceVar1 description; +// MEMBER_NO_DOT-SAME: rawcomment=instanceVar1 description + +// MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .instanceVar2[#Double#]; name=instanceVar2; +// MEMBER_NO_DOT-SAME: briefcomment=instanceVar2 description; +// MEMBER_NO_DOT-SAME: xmlcomment=instanceVar2s:15CompleteDocTest2S1V12instanceVar2Sdvpvar instanceVar2: DoubleinstanceVar2 descriptionEuler-Mascheroni constant; +// MEMBER_NO_DOT-SAME: rawcomment=instanceVar2 description +// MEMBER_NO_DOT-EMPTY: +// MEMBER_NO_DOT-NEXT: Euler-Mascheroni constant + +// MEMBER_NO_DOT-NEXT: Decl[InstanceVar]/CurrNominal: .requirement1[#String#]; name=requirement1; +// MEMBER_NO_DOT-SAME: briefcomment=requirement1 doc comment; +// MEMBER_NO_DOT-SAME: xmlcomment=requirement1s:15CompleteDocTest2P1P12requirement1SSvpvar requirement1: String { get }requirement1 doc commentmore descriptionThis documentation comment was inherited from P1.; +// MEMBER_NO_DOT-SAME: rawcomment=requirement1 doc comment +// MEMBER_NO_DOT-EMPTY: +// MEMBER_NO_DOT-NEXT: more description + +// MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .requirement2()[#Void#]; name=requirement2() + +// MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/CurrNominal: .requirement3()[#Void#]; name=requirement3(); +// MEMBER_NO_DOT-SAME: briefcomment=requirement3 comment in S1; +// MEMBER_NO_DOT-SAME: xmlcomment=requirement3()s:15CompleteDocTest2S1V12requirement3yyFfunc requirement3()requirement3 comment in S1; +// MEMBER_NO_DOT-SAME: rawcomment=requirement3 comment in S1 + +// MEMBER_NO_DOT-NEXT: Decl[InstanceMethod]/Super: .requirement3({#x: Int#})[#Void#]; name=requirement3(x:); +// MEMBER_NO_DOT-SAME: briefcomment=requirement3 comment in P1; +// MEMBER_NO_DOT-SAME: xmlcomment=requirement3(x:)s:15CompleteDocTest2P1P12requirement31xySi_tFfunc requirement3(x: Int)requirement3 comment in P1; +// MEMBER_NO_DOT-SAME: rawcomment=requirement3 comment in P1 + +// MEMBER_NO_DOT-NEXT: Keyword[self]/CurrNominal: .self[#S1#]; name=self diff --git a/test/IDE/complete_doc_top_level.swift b/test/IDE/complete_doc_top_level.swift index 0b716e013a9e8..ef2abd986104f 100644 --- a/test/IDE/complete_doc_top_level.swift +++ b/test/IDE/complete_doc_top_level.swift @@ -33,36 +33,51 @@ struct S2: P1 {} #^TOP_LEVEL^# -// RUN: %target-swift-ide-test -code-completion -source-filename %s -module-name CompleteDocTest -code-completion-comments=true -code-completion-token=TOP_LEVEL | %FileCheck %s --check-prefix=TOP-LEVEL - -// TOP-LEVEL-DAG: Decl[GlobalVar]/Local: topLevelVar1[#String#]; name=topLevelVar1; -// TOP-LEVEL-DAG-SAME: briefcomment=top-level var 1 comment; -// TOP-LEVEL-DAG-SAME: fullcomment=topLevelVar1s:15CompleteDocTest12topLevelVar1SSvpvar topLevelVar1: Stringtop-level var 1 comment - -// TOP-LEVEL-DAG: Decl[GlobalVar]/Local: topLevelVar2[#Int#]; name=topLevelVar2; -// TOP-LEVEL-DAG-SAME: briefcomment=top-level var 2 comment; -// TOP-LEVEL-DAG-SAME: fullcomment=topLevelVar2s:15CompleteDocTest12topLevelVar2Sivpvar topLevelVar2: Inttop-level var 2 commentthe meaning of life - -// TOP-LEVEL-DAG: Decl[FreeFunction]/CurrModule: topLevelFunc1()[#Void#]; name=topLevelFunc1(); -// TOP-LEVEL-DAG-SAME: briefcomment=top-level func 1 comment; -// TOP-LEVEL-DAG-SAME: fullcomment=topLevelFunc1()s:15CompleteDocTest13topLevelFunc1yyFfunc topLevelFunc1()top-level func 1 commentDoes stuff. - -// TOP-LEVEL-DAG: Decl[FreeFunction]/CurrModule: topLevelFunc2()[#Void#]; name=topLevelFunc2(); -// TOP-LEVEL-DAG-SAME: briefcomment=top-level func 2 comment; -// TOP-LEVEL-DAG-SAME: fullcomment=topLevelFunc2()s:15CompleteDocTest13topLevelFunc2yyFfunc topLevelFunc2()top-level func 2 comment - -// TOP-LEVEL-DAG: Decl[Struct]/CurrModule: S1[#S1#]; name=S1; -// TOP-LEVEL-DAG-SAME: briefcomment=struct S1; -// TOP-LEVEL-DAG-SAME: fullcomment=S1s:15CompleteDocTest2S1Vstruct S1struct S1More info on struct S - -// TOP-LEVEL-DAG: Decl[Class]/CurrModule: C1[#C1#]; name=C1; -// TOP-LEVEL-DAG-SAME: briefcomment=C1 description; -// TOP-LEVEL-DAG-SAME: fullcomment=C1s:15CompleteDocTest2C1Cclass C1C1 descriptiondoes some work - -// TOP-LEVEL-DAG: Decl[Protocol]/CurrModule/Flair[RareType]: P1[#P1#]; name=P1; -// TOP-LEVEL-DAG-SAME: briefcomment=P1 description; -// TOP-LEVEL-DAG-SAME: fullcomment=P1s:15CompleteDocTest2P1Pprotocol P1P1 descriptiondefines some functionality - -// TOP-LEVEL-DAG: Decl[Struct]/CurrModule: S2[#S2#]; name=S2 -// TOP-LEVEL-DAG-SAME-NOT: briefcomment= -// TOP-LEVEL-DAG-SAME-NOT: fullcomment= +// RUN: %target-swift-ide-test -code-completion -source-filename %s -module-name CompleteDocTest -code-completion-comments -code-completion-sort-by-name -code-completion-token=TOP_LEVEL | %FileCheck %s --check-prefix=TOP-LEVEL + +// TOP-LEVEL-LABEL: Decl[Class]/CurrModule: C1[#C1#]; name=C1; +// TOP-LEVEL-SAME: briefcomment=C1 description; +// TOP-LEVEL-SAME: xmlcomment=C1s:15CompleteDocTest2C1Cclass C1C1 descriptiondoes some work; +// TOP-LEVEL-SAME: rawcomment=C1 description +// TOP-LEVEL-EMPTY: +// TOP-LEVEL-NEXT: does some work + +// TOP-LEVEL-LABEL: Decl[Protocol]/CurrModule/Flair[RareType]: P1[#P1#]; name=P1; +// TOP-LEVEL-SAME: briefcomment=P1 description; +// TOP-LEVEL-SAME: xmlcomment=P1s:15CompleteDocTest2P1Pprotocol P1P1 descriptiondefines some functionality; +// TOP-LEVEL-SAME: rawcomment=P1 description +// TOP-LEVEL-EMPTY: +// TOP-LEVEL-NEXT: defines some functionality + +// TOP-LEVEL-LABEL: Decl[Struct]/CurrModule: S1[#S1#]; name=S1; +// TOP-LEVEL-SAME: briefcomment=struct S1; +// TOP-LEVEL-SAME: xmlcomment=S1s:15CompleteDocTest2S1Vstruct S1struct S1More info on struct S; +// TOP-LEVEL-SAME: rawcomment=struct S1 +// TOP-LEVEL-EMPTY: +// TOP-LEVEL-NEXT: More info on struct S + +// TOP-LEVEL-LABEL: Decl[Struct]/CurrModule: S2[#S2#]; name=S2{{$}} + +// TOP-LEVEL-LABEL: Decl[FreeFunction]/CurrModule: topLevelFunc1()[#Void#]; name=topLevelFunc1(); +// TOP-LEVEL-SAME: briefcomment=top-level func 1 comment; +// TOP-LEVEL-SAME: xmlcomment=topLevelFunc1()s:15CompleteDocTest13topLevelFunc1yyFfunc topLevelFunc1()top-level func 1 commentDoes stuff.; +// TOP-LEVEL-SAME: rawcomment=top-level func 1 comment +// TOP-LEVEL-EMPTY: +// TOP-LEVEL-NEXT: Does stuff. + +// TOP-LEVEL-LABEL: Decl[FreeFunction]/CurrModule: topLevelFunc2()[#Void#]; name=topLevelFunc2(); +// TOP-LEVEL-SAME: briefcomment=top-level func 2 comment; +// TOP-LEVEL-SAME: xmlcomment=topLevelFunc2()s:15CompleteDocTest13topLevelFunc2yyFfunc topLevelFunc2()top-level func 2 comment; +// TOP-LEVEL-SAME: rawcomment=top-level func 2 comment + +// TOP-LEVEL-LABEL: Decl[GlobalVar]/Local: topLevelVar1[#String#]; name=topLevelVar1; +// TOP-LEVEL-SAME: briefcomment=top-level var 1 comment; +// TOP-LEVEL-SAME: xmlcomment=topLevelVar1s:15CompleteDocTest12topLevelVar1SSvpvar topLevelVar1: Stringtop-level var 1 comment; +// TOP-LEVEL-SAME: rawcomment=top-level var 1 comment + +// TOP-LEVEL-LABEL: Decl[GlobalVar]/Local: topLevelVar2[#Int#]; name=topLevelVar2; +// TOP-LEVEL-SAME: briefcomment=top-level var 2 comment; +// TOP-LEVEL-SAME: xmlcomment=topLevelVar2s:15CompleteDocTest12topLevelVar2Sivpvar topLevelVar2: Inttop-level var 2 commentthe meaning of life; +// TOP-LEVEL-SAME: rawcomment=top-level var 2 comment +// TOP-LEVEL-EMPTY: +// TOP-LEVEL-NEXT: the meaning of life