From 13ce4cc3152bb69e319642af5d35fd94dd9f2d86 Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Mon, 23 Oct 2023 11:55:51 -0700 Subject: [PATCH] [Macros] Improve visitation of auxiliary decls Use the same pattern as 'getAllMembers()'. This supports nested macro expansion: ``` std::function visit; visit = [&](Decl *d) { doIt(d); d->visitAuxiliaryDecls(visit); }; for (auto *d : decls) visit(d); ``` Don't visit auxiliary decls in `PrintAST::visit(Decl *)` this function is only intended for single decl printing. The caller should visit them separately. For that, add `ModuleDecl::getTopLevelDeclsWithAuxiliaryDecls()` (cherry picked from commit 6f5283ebfc5bfe6426641297566864f2943a1490) (cherry picked from commit 03bf34977835c4f080495c5cf50b22a1362b8bea) (cherry picked from commit 55144fb302c3f2caa583d35904fb431ec04fbe2d) --- include/swift/AST/Module.h | 4 +++ lib/AST/ASTPrinter.cpp | 17 +++++----- lib/AST/Module.cpp | 21 ++++++++++--- lib/AST/NameLookup.cpp | 10 ++---- lib/Frontend/ModuleInterfaceSupport.cpp | 2 +- lib/Sema/LookupVisibleDecls.cpp | 17 +++------- .../Inputs/syntax_macro_definitions.swift | 2 +- test/ModuleInterface/macros.swift | 31 +++++++++++++++++-- test/SourceKit/Macros/macro_basic.swift | 12 +++++++ 9 files changed, 80 insertions(+), 36 deletions(-) diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index aa1d88cb63882..a42dbabe2f68f 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -951,6 +951,10 @@ class ModuleDecl /// The order of the results is not guaranteed to be meaningful. void getTopLevelDecls(SmallVectorImpl &Results) const; + /// Finds all top-level decls of this module including auxiliary decls. + void + getTopLevelDeclsWithAuxiliaryDecls(SmallVectorImpl &Results) const; + void getExportedPrespecializations(SmallVectorImpl &results) const; /// Finds top-level decls of this module filtered by their attributes. diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index df1fe7ca3bd35..d56ddf29baeb4 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -1020,12 +1020,6 @@ class PrintAST : public ASTVisitor { Options.TransformContext->isPrintingSynthesizedExtension() && isa(D); - SWIFT_DEFER { - D->visitAuxiliaryDecls([&](Decl *auxDecl) { - visit(auxDecl); - }); - }; - if (!shouldPrint(D, true) && !Synthesize) return false; @@ -4328,13 +4322,20 @@ bool PrintAST::printASTNodes(const ArrayRef &Elements, bool NeedIndent) { IndentRAII IndentMore(*this, NeedIndent); bool PrintedSomething = false; + + std::function printDecl; + printDecl = [&](Decl *d) { + if (d->shouldPrintInContext(Options)) + visit(d); + d->visitAuxiliaryDecls(printDecl); + }; + for (auto element : Elements) { PrintedSomething = true; Printer.printNewline(); indent(); if (auto decl = element.dyn_cast()) { - if (decl->shouldPrintInContext(Options)) - visit(decl); + printDecl(decl); } else if (auto stmt = element.dyn_cast()) { visit(stmt); } else { diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 46b1108561b1f..3709a54759995 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1329,6 +1329,11 @@ void ModuleDecl::getTopLevelDecls(SmallVectorImpl &Results) const { FORWARD(getTopLevelDecls, (Results)); } +void ModuleDecl::getTopLevelDeclsWithAuxiliaryDecls( + SmallVectorImpl &Results) const { + FORWARD(getTopLevelDeclsWithAuxiliaryDecls, (Results)); +} + void ModuleDecl::dumpDisplayDecls() const { SmallVector Decls; getDisplayDecls(Decls); @@ -3132,7 +3137,9 @@ void SourceFile::print(raw_ostream &OS, const PrintOptions &PO) { void SourceFile::print(ASTPrinter &Printer, const PrintOptions &PO) { std::set MajorDeclKinds = {DeclKind::Class, DeclKind::Enum, DeclKind::Extension, DeclKind::Protocol, DeclKind::Struct}; - for (auto decl : getTopLevelDecls()) { + SmallVector topLevelDecls; + getTopLevelDeclsWithAuxiliaryDecls(topLevelDecls); + for (auto decl : topLevelDecls) { if (!decl->shouldPrintInContext(PO)) continue; // For a major decl, we print an empty line before it. @@ -4179,14 +4186,18 @@ void FileUnit::getTopLevelDeclsWhereAttributesMatch( void FileUnit::getTopLevelDeclsWithAuxiliaryDecls( SmallVectorImpl &results) const { + + std::function addResult; + addResult = [&](Decl *decl) { + results.push_back(decl); + decl->visitAuxiliaryDecls(addResult); + }; + SmallVector nonExpandedDecls; nonExpandedDecls.reserve(results.capacity()); getTopLevelDecls(nonExpandedDecls); for (auto *decl : nonExpandedDecls) { - decl->visitAuxiliaryDecls([&](Decl *auxDecl) { - results.push_back(auxDecl); - }); - results.push_back(decl); + addResult(decl); } } diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index d43ac9b80ba8b..fde5b3f97f8cc 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -3939,16 +3939,12 @@ void FindLocalVal::visitBraceStmt(BraceStmt *S, bool isTopLevelCode) { } } - auto visitDecl = [&](Decl *D) { + std::function visitDecl; + visitDecl = [&](Decl *D) { if (auto *VD = dyn_cast(D)) checkValueDecl(VD, DeclVisibilityKind::LocalVariable); - D->visitAuxiliaryDecls([&](Decl *D) { - if (auto *VD = dyn_cast(D)) - checkValueDecl(VD, DeclVisibilityKind::LocalVariable); - // FIXME: Recursively call `visitDecl` to handle nested macros. - }); + D->visitAuxiliaryDecls(visitDecl); }; - for (auto elem : S->getElements()) { if (auto *E = elem.dyn_cast()) { // 'MacroExpansionExpr' at code-item position may introduce value decls. diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 7287deb0ff022..8c084658afec7 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -833,7 +833,7 @@ bool swift::emitSwiftInterface(raw_ostream &out, InheritedProtocolCollector::PerTypeMap inheritedProtocolMap; SmallVector topLevelDecls; - M->getTopLevelDecls(topLevelDecls); + M->getTopLevelDeclsWithAuxiliaryDecls(topLevelDecls); for (const Decl *D : topLevelDecls) { InheritedProtocolCollector::collectProtocols(inheritedProtocolMap, D); diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index 745186b513622..2c8a34e208da6 100644 --- a/lib/Sema/LookupVisibleDecls.cpp +++ b/lib/Sema/LookupVisibleDecls.cpp @@ -217,24 +217,17 @@ static void collectVisibleMemberDecls(const DeclContext *CurrDC, LookupState LS, Type BaseType, IterableDeclContext *Parent, SmallVectorImpl &FoundDecls) { - auto check = [&](Decl *decl) { - auto *VD = dyn_cast(decl); + for (auto Member : Parent->getAllMembers()) { + auto *VD = dyn_cast(Member); if (!VD) - return; + continue; if (!isDeclVisibleInLookupMode(VD, LS, CurrDC)) - return; + continue; if (!evaluateOrDefault(CurrDC->getASTContext().evaluator, IsDeclApplicableRequest(DeclApplicabilityOwner(CurrDC, BaseType, VD)), false)) - return; + continue; FoundDecls.push_back(VD); - }; - - for (auto Member : Parent->getAllMembers()) { - check(Member); - Member->visitAuxiliaryDecls([&](Decl *d) { - check(d); - }); } } diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index 9fd409df64c86..07902bbb9c84a 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -1928,7 +1928,7 @@ public struct AddPeerStoredPropertyMacro: PeerMacro, Sendable { return [ """ - private var _foo: Int = 100 + public var _foo: Int = 100 """ ] } diff --git a/test/ModuleInterface/macros.swift b/test/ModuleInterface/macros.swift index 5a800294dad6f..033db89335c51 100644 --- a/test/ModuleInterface/macros.swift +++ b/test/ModuleInterface/macros.swift @@ -64,8 +64,35 @@ macro structWithUnqualifiedLookup() = #externalMacro(module: "MacroDefinition", let world = 17 -// CHECK-NOT: structWithUnqualifiedLookup public #structWithUnqualifiedLookup - +// CHECK-NOT: structWithUnqualifiedLookup +// CHECK-NOT: struct StructWithUnqualifiedLookup // CHECK: struct StructWithUnqualifiedLookup +// CHECK-NOT: struct StructWithUnqualifiedLookup + +@attached(peer, names: named(_foo)) +macro AddPeerStoredProperty() = #externalMacro(module: "MacroDefinition", type: "AddPeerStoredPropertyMacro") + +@AddPeerStoredProperty +public var test: Int = 10 +// CHECK: var test +// CHECK-NOT: var _foo +// CHECK: var _foo +// CHECK-NOT: var _foo + +// CHECK: struct TestStruct { +public struct TestStruct { + public #structWithUnqualifiedLookup + // CHECK-NOT: structWithUnqualifiedLookup + // CHECK-NOT: struct StructWithUnqualifiedLookup + // CHECK: struct StructWithUnqualifiedLookup + // CHECK-NOT: struct StructWithUnqualifiedLookup + + @AddPeerStoredProperty + public var test: Int = 10 + // CHECK: var test + // CHECK-NOT: var _foo + // CHECK: var _foo + // CHECK-NOT: var _foo +} diff --git a/test/SourceKit/Macros/macro_basic.swift b/test/SourceKit/Macros/macro_basic.swift index 544602b206b6d..7a689eaf955ca 100644 --- a/test/SourceKit/Macros/macro_basic.swift +++ b/test/SourceKit/Macros/macro_basic.swift @@ -60,6 +60,13 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition" @freestanding(expression) macro assert(_: String) = #externalMacro(module: "MacroDefinition", type: "AssertMacro") #assert("foobar") +@attached(peer, names: named(_foo)) +macro AddPeerStoredProperty() = #externalMacro(module: "MacroDefinition", type: "AddPeerStoredPropertyMacro") +struct S5 { + @AddPeerStoredProperty + var test: Int = 10 +} + // REQUIRES: swift_swift_parser, executable_test, shell // RUN: %empty-directory(%t) @@ -284,3 +291,8 @@ macro anonymousTypes(_: () -> String) = #externalMacro(module: "MacroDefinition" //##-- Expansion on "fails to typecheck" macro expression // RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=61:2 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ERRONEOUS_EXPAND %s // ERRONEOUS_EXPAND: 61:1-61:18 (@__swiftmacro_{{.+}}.swift) "assert("foobar")" + +//##-- Cursor-info on a decl where a peer macro attached. +// RUN: %sourcekitd-test -req=cursor -pos=67:7 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=CURSOR_ON_DECL_WITH_PEER %s +// CURSOR_ON_DECL_WITH_PEER: var test: Int +// CURSOR_ON_DECL_WITH_PEER-NOT: _foo