diff --git a/include/swift/IDE/CodeCompletionCache.h b/include/swift/IDE/CodeCompletionCache.h index 0bd24450ecd..061831ecd23 100644 --- a/include/swift/IDE/CodeCompletionCache.h +++ b/include/swift/IDE/CodeCompletionCache.h @@ -116,9 +116,7 @@ public: struct RequestedCachedModule { CodeCompletionCache::Key Key; const ModuleDecl *TheModule; - bool OnlyTypes; - bool OnlyPrecedenceGroups; - bool OnlyMacros; + CodeCompletionFilter Filter; }; } // end namespace ide diff --git a/include/swift/IDE/CodeCompletionResult.h b/include/swift/IDE/CodeCompletionResult.h index b620fa1ba1a..9333d90cfe5 100644 --- a/include/swift/IDE/CodeCompletionResult.h +++ b/include/swift/IDE/CodeCompletionResult.h @@ -316,6 +316,39 @@ enum class CodeCompletionResultKind : uint8_t { MAX_VALUE = BuiltinOperator }; +enum class CodeCompletionMacroRole : uint8_t { + Expression = 1 << 0, + Declaration = 1 << 1, + CodeItem = 1 << 2, + AttachedVar = 1 << 3, + AttachedContext = 1 << 4, + AttachedDecl = 1 << 5, +}; +using CodeCompletionMacroRoles = OptionSet; + +enum class CodeCompletionFilterFlag : uint16_t { + Expr = 1 << 0, + Type = 1 << 1, + PrecedenceGroup = 1 << 2, + Module = 1 << 3, + ExpressionMacro = 1 << 4, + DeclarationMacro = 1 << 5, + CodeItemMacro = 1 << 6, + AttachedVarMacro = 1 << 7, + AttachedContextMacro = 1 << 8, + AttachedDeclMacro = 1 << 9, +}; +using CodeCompletionFilter = OptionSet; + +CodeCompletionMacroRoles getCompletionMacroRoles(const Decl *D); + +CodeCompletionMacroRoles +getCompletionMacroRoles(OptionSet kinds); + +CodeCompletionMacroRoles getCompletionMacroRoles(CodeCompletionFilter filter); + +CodeCompletionFilter getCompletionFilter(CodeCompletionMacroRoles roles); + /// The parts of a \c CodeCompletionResult that are not dependent on the context /// it appears in and can thus be cached. class ContextFreeCodeCompletionResult { @@ -334,6 +367,8 @@ class ContextFreeCodeCompletionResult { CodeCompletionOperatorKind KnownOperatorKind : 6; static_assert(int(CodeCompletionOperatorKind::MAX_VALUE) < 1 << 6, ""); + CodeCompletionMacroRoles MacroRoles; + bool IsSystem : 1; bool IsAsync : 1; /// Whether the result has been annotated as having an async alternative that @@ -359,17 +394,18 @@ class ContextFreeCodeCompletionResult { NullTerminatedStringRef NameForDiagnostics; public: - /// Memberwise initializer. \p AssociatedKInd is opaque and will be + /// Memberwise initializer. \p AssociatedKind is opaque and will be /// interpreted based on \p Kind. If \p KnownOperatorKind is \c None and the /// completion item is an operator, it will be determined based on the - /// compleiton string. + /// completion string. /// - /// \note The caller must ensure that the \p CompleitonString and all the + /// \note The caller must ensure that the \p CompletionString and all the /// \c Ref types outlive this result, typically by storing them in the same /// \c CodeCompletionResultSink as the result itself. ContextFreeCodeCompletionResult( CodeCompletionResultKind Kind, uint8_t AssociatedKind, - CodeCompletionOperatorKind KnownOperatorKind, bool IsSystem, bool IsAsync, + CodeCompletionOperatorKind KnownOperatorKind, + CodeCompletionMacroRoles MacroRoles, bool IsSystem, bool IsAsync, bool HasAsyncAlternative, CodeCompletionString *CompletionString, NullTerminatedStringRef ModuleName, NullTerminatedStringRef BriefDocComment, @@ -380,8 +416,9 @@ public: NullTerminatedStringRef DiagnosticMessage, NullTerminatedStringRef FilterName, NullTerminatedStringRef NameForDiagnostics) - : Kind(Kind), KnownOperatorKind(KnownOperatorKind), IsSystem(IsSystem), - IsAsync(IsAsync), HasAsyncAlternative(HasAsyncAlternative), + : Kind(Kind), KnownOperatorKind(KnownOperatorKind), + MacroRoles(MacroRoles), IsSystem(IsSystem), IsAsync(IsAsync), + HasAsyncAlternative(HasAsyncAlternative), CompletionString(CompletionString), ModuleName(ModuleName), BriefDocComment(BriefDocComment), AssociatedUSRs(AssociatedUSRs), ResultType(ResultType), NotRecommended(NotRecommended), @@ -488,6 +525,8 @@ public: return KnownOperatorKind; } + CodeCompletionMacroRoles getMacroRoles() const { return MacroRoles; } + bool isSystem() const { return IsSystem; }; bool isAsync() const { return IsAsync; }; diff --git a/include/swift/IDE/CodeCompletionResultType.h b/include/swift/IDE/CodeCompletionResultType.h index 6f83fe8c331..280eb61604d 100644 --- a/include/swift/IDE/CodeCompletionResultType.h +++ b/include/swift/IDE/CodeCompletionResultType.h @@ -28,8 +28,12 @@ enum class CustomAttributeKind : uint8_t { ResultBuilder = 1 << 1, /// A type that can be used as a global actor. GlobalActor = 1 << 2, - /// A macro can be used as a custom attribute. - Macro = 1 << 3, + /// A macro that can be used on variables or subscripts. + VarMacro = 1 << 3, + /// A macro that can be used on any type context. + ContextMacro = 1 << 4, + /// A macro that can be used on any declaration. + DeclMacro = 1 << 5, }; /// The expected contextual type(s) for code-completion. diff --git a/include/swift/IDE/CompletionLookup.h b/include/swift/IDE/CompletionLookup.h index debd0f3f563..33d38e66e9f 100644 --- a/include/swift/IDE/CompletionLookup.h +++ b/include/swift/IDE/CompletionLookup.h @@ -137,7 +137,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { bool IsUnwrappedOptional = false; SourceLoc DotLoc; bool NeedLeadingDot = false; - bool NeedLeadingMacroPound = false; bool NeedOptionalUnwrap = false; unsigned NumBytesToEraseForOptionalUnwrap = 0; @@ -186,53 +185,27 @@ private: public: struct RequestedResultsTy { const ModuleDecl *TheModule; - bool OnlyTypes; - bool OnlyPrecedenceGroups; - bool OnlyMacros; + CodeCompletionFilter Filter; bool NeedLeadingDot; - bool NeedPound; - bool IncludeModuleQualifier; - static RequestedResultsTy fromModule(const ModuleDecl *TheModule) { - return {TheModule, false, false, false, false, false, true}; + static RequestedResultsTy fromModule(const ModuleDecl *mod, + CodeCompletionFilter filter) { + return {mod, filter, /*NeedLeadingDot=*/false}; } - RequestedResultsTy onlyTypes() const { - return {TheModule, true, false, false, NeedLeadingDot, false, - IncludeModuleQualifier}; + static RequestedResultsTy topLevelResults(CodeCompletionFilter filter) { + return {nullptr, filter, /*NeedLeadingDot=*/false}; } - RequestedResultsTy onlyPrecedenceGroups() const { - assert(!OnlyTypes && "onlyTypes() already includes precedence groups"); - return {TheModule, false, true, false, false, false, true}; - } - - RequestedResultsTy onlyMacros(bool needPound) const { - return {TheModule, false, false, true, false, needPound, false}; - } - - RequestedResultsTy needLeadingDot(bool NeedDot) const { - return {TheModule, OnlyTypes, OnlyPrecedenceGroups, OnlyMacros, NeedDot, - NeedPound, IncludeModuleQualifier}; - } - - RequestedResultsTy withModuleQualifier(bool IncludeModule) const { - return {TheModule, OnlyTypes, OnlyPrecedenceGroups, OnlyMacros, - NeedLeadingDot, NeedPound, IncludeModule}; - } - - static RequestedResultsTy toplevelResults() { - return {nullptr, false, false, false, false, true, true}; + RequestedResultsTy needLeadingDot(bool needDot) const { + return {TheModule, Filter, needDot}; } friend bool operator==(const RequestedResultsTy &LHS, const RequestedResultsTy &RHS) { - return LHS.TheModule == RHS.TheModule && LHS.OnlyTypes == RHS.OnlyTypes && - LHS.OnlyPrecedenceGroups == RHS.OnlyPrecedenceGroups && - LHS.OnlyMacros == RHS.OnlyMacros && - LHS.NeedLeadingDot == RHS.NeedLeadingDot && - LHS.NeedPound == RHS.NeedPound && - LHS.IncludeModuleQualifier == RHS.IncludeModuleQualifier; + return LHS.TheModule == RHS.TheModule && + LHS.Filter.containsOnly(RHS.Filter) && + LHS.NeedLeadingDot == RHS.NeedLeadingDot; } }; @@ -524,7 +497,7 @@ public: Type ExprType, const ValueDecl *VD, Optional SemanticContext = None); - bool tryModuleCompletions(Type ExprType, bool TypesOnly = false); + bool tryModuleCompletions(Type ExprType, CodeCompletionFilter Filter); /// If the given ExprType is optional, this adds completions for the unwrapped /// type. @@ -562,7 +535,7 @@ public: void addObjCPoundKeywordCompletions(bool needPound); - void getMacroCompletions(bool needPound); + void getMacroCompletions(CodeCompletionMacroRoles roles); struct FilteredDeclConsumer : public swift::VisibleDeclConsumer { swift::VisibleDeclConsumer &Consumer; @@ -626,7 +599,7 @@ public: void getTypeCompletionsInDeclContext(SourceLoc Loc, bool ModuleQualifier = true); - void getToplevelCompletions(bool OnlyTypes, bool OnlyMacros); + void getToplevelCompletions(CodeCompletionFilter Filter); void lookupExternalModuleDecls(const ModuleDecl *TheModule, ArrayRef AccessPath, @@ -645,18 +618,15 @@ using RequestedResultsTy = swift::ide::CompletionLookup::RequestedResultsTy; template <> struct DenseMapInfo { static inline RequestedResultsTy getEmptyKey() { - return {DenseMapInfo::getEmptyKey(), false, false, - false, false, false, false}; + return {DenseMapInfo::getEmptyKey(), {}, false}; } static inline RequestedResultsTy getTombstoneKey() { - return {DenseMapInfo::getTombstoneKey(), false, false, - false, false, false, false}; + return {DenseMapInfo::getTombstoneKey(), {}, false}; } static unsigned getHashValue(const RequestedResultsTy &Val) { return hash_combine( DenseMapInfo::getHashValue(Val.TheModule), - Val.OnlyTypes, Val.OnlyPrecedenceGroups, Val.OnlyMacros, - Val.NeedLeadingDot, Val.NeedPound, Val.IncludeModuleQualifier); + Val.Filter.toRaw(), Val.NeedLeadingDot); } static bool isEqual(const RequestedResultsTy &LHS, const RequestedResultsTy &RHS) { diff --git a/lib/IDE/AfterPoundExprCompletion.cpp b/lib/IDE/AfterPoundExprCompletion.cpp index f2ed9273921..41ae1772b12 100644 --- a/lib/IDE/AfterPoundExprCompletion.cpp +++ b/lib/IDE/AfterPoundExprCompletion.cpp @@ -52,7 +52,7 @@ void AfterPoundExprCompletion::deliverResults( /*expectsNonVoid=*/true); Lookup.addPoundAvailable(ParentStmtKind); Lookup.addObjCPoundKeywordCompletions(/*needPound=*/false); - Lookup.getMacroCompletions(/*needPound=*/false); + Lookup.getMacroCompletions(CodeCompletionMacroRole::Expression); } deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 02f7778d3db..5e1d6c8b725 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -1130,6 +1130,8 @@ static void addPoundDirectives(CodeCompletionResultSink &Sink) { Builder.addSimpleTypedParameter("Int"); Builder.addRightParen(); }); + +#ifndef SWIFT_SWIFT_PARSER addWithName("warning", CodeCompletionKeywordKind::pound_warning, [&] (CodeCompletionResultBuilder &Builder) { Builder.addLeftParen(); @@ -1146,6 +1148,7 @@ static void addPoundDirectives(CodeCompletionResultSink &Sink) { Builder.addTextChunk("\""); Builder.addRightParen(); }); +#endif addWithName("if ", CodeCompletionKeywordKind::pound_if, [&] (CodeCompletionResultBuilder &Builder) { @@ -1352,11 +1355,10 @@ void swift::ide::deliverCompletionResults( std::pair Result = ImportsSeen.insert(K); if (!Result.second) return; // already handled. - RequestedModules.push_back({std::move(K), TheModule, - Request.OnlyTypes, Request.OnlyPrecedenceGroups, Request.OnlyMacros}); + RequestedModules.push_back({std::move(K), TheModule, Request.Filter}); auto TheModuleName = TheModule->getName(); - if (Request.IncludeModuleQualifier && + if (Request.Filter.contains(CodeCompletionFilterFlag::Module) && (!Lookup.isHiddenModuleName(TheModuleName) || explictlyImportedModules.contains(TheModule)) && seenModuleNames.insert(TheModuleName).second) @@ -1371,11 +1373,11 @@ void swift::ide::deliverCompletionResults( } } else { // Add results from current module. - Lookup.getToplevelCompletions(Request.OnlyTypes, Request.OnlyMacros); + Lookup.getToplevelCompletions(Request.Filter); // Add the qualifying module name auto curModule = SF.getParentModule(); - if (Request.IncludeModuleQualifier && + if (Request.Filter.contains(CodeCompletionFilterFlag::Module) && seenModuleNames.insert(curModule->getName()).second) Lookup.addModuleName(curModule); @@ -1790,15 +1792,35 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) { default: break; } - } - if (!ExpectedCustomAttributeKinds) { + + switch (*AttTargetDK) { + case DeclKind::Var: + case DeclKind::Subscript: + ExpectedCustomAttributeKinds |= CustomAttributeKind::VarMacro; + break; + case DeclKind::Struct: + case DeclKind::Class: + case DeclKind::Protocol: + case DeclKind::Enum: + case DeclKind::Extension: + ExpectedCustomAttributeKinds |= CustomAttributeKind::ContextMacro; + break; + default: + break; + } + if (*AttTargetDK != DeclKind::Param) { + ExpectedCustomAttributeKinds |= CustomAttributeKind::DeclMacro; + } + } else { // If we don't know on which decl kind we are completing, suggest all // attribute kinds. ExpectedCustomAttributeKinds |= CustomAttributeKind::PropertyWrapper; ExpectedCustomAttributeKinds |= CustomAttributeKind::ResultBuilder; ExpectedCustomAttributeKinds |= CustomAttributeKind::GlobalActor; + ExpectedCustomAttributeKinds |= CustomAttributeKind::VarMacro; + ExpectedCustomAttributeKinds |= CustomAttributeKind::ContextMacro; + ExpectedCustomAttributeKinds |= CustomAttributeKind::DeclMacro; } - ExpectedCustomAttributeKinds |= CustomAttributeKind::Macro; Lookup.setExpectedTypes(/*Types=*/{}, /*isImplicitSingleExpressionReturn=*/false, @@ -1814,8 +1836,11 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) { P.Context.SourceMgr.getIDEInspectionTargetLoc()); // Macro name at attribute position after '@'. - Lookup.getToplevelCompletions( - /*OnlyTypes=*/false, /*OnlyMacros=*/true); + CodeCompletionMacroRoles macroRoles = + getCompletionMacroRoles(ExpectedCustomAttributeKinds); + if (macroRoles) { + Lookup.getMacroCompletions(macroRoles); + } break; } case CompletionKind::AttributeDeclParen: { @@ -1968,6 +1993,15 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) { case CompletionKind::AfterPoundDirective: { addPoundDirectives(CompletionContext.getResultSink()); + + CodeCompletionMacroRoles roles; + if (!CurDeclContext || !CurDeclContext->isTypeContext()) { + roles |= CodeCompletionMacroRole::Expression; + roles |= CodeCompletionMacroRole::CodeItem; + } + roles |= CodeCompletionMacroRole::Declaration; + Lookup.getMacroCompletions(roles); + // FIXME: Add pound expressions (e.g. '#selector()') if it's at statements // position. break; diff --git a/lib/IDE/CodeCompletionCache.cpp b/lib/IDE/CodeCompletionCache.cpp index 9f609ff28e0..e988d8a7e07 100644 --- a/lib/IDE/CodeCompletionCache.cpp +++ b/lib/IDE/CodeCompletionCache.cpp @@ -104,7 +104,7 @@ CodeCompletionCache::~CodeCompletionCache() {} /// This should be incremented any time we commit a change to the format of the /// cached results. This isn't expected to change very often. static constexpr uint32_t onDiskCompletionCacheVersion = - 10; // Store if decl has an async alternative + 11; // Added macro roles /// Deserializes CodeCompletionResults from \p in and stores them in \p V. /// \see writeCacheModule. @@ -230,6 +230,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in, auto kind = static_cast(*cursor++); auto associatedKind = static_cast(*cursor++); auto opKind = static_cast(*cursor++); + auto roles = CodeCompletionMacroRoles(*cursor++); auto notRecommended = static_cast(*cursor++); auto diagSeverity = @@ -266,7 +267,7 @@ static bool readCachedModule(llvm::MemoryBuffer *in, ContextFreeCodeCompletionResult *result = new (*V.Allocator) ContextFreeCodeCompletionResult( - kind, associatedKind, opKind, isSystem, isAsync, + kind, associatedKind, opKind, roles, isSystem, isAsync, hasAsyncAlternative, string, moduleName, briefDocComment, makeArrayRef(assocUSRs).copy(*V.Allocator), CodeCompletionResultType(resultTypes), notRecommended, diagSeverity, @@ -423,6 +424,7 @@ static void writeCachedModule(llvm::raw_ostream &out, } else { LE.write(static_cast(CodeCompletionOperatorKind::None)); } + LE.write(static_cast(R->getMacroRoles().toRaw())); LE.write(static_cast(R->getNotRecommendedReason())); LE.write(static_cast(R->getDiagnosticSeverity())); LE.write(static_cast(R->isSystem())); diff --git a/lib/IDE/CodeCompletionConsumer.cpp b/lib/IDE/CodeCompletionConsumer.cpp index f5c7afdce36..1ab5eec476f 100644 --- a/lib/IDE/CodeCompletionConsumer.cpp +++ b/lib/IDE/CodeCompletionConsumer.cpp @@ -18,9 +18,9 @@ using namespace swift::ide; static MutableArrayRef copyCodeCompletionResults( CodeCompletionResultSink &targetSink, CodeCompletionCache::Value &source, - bool onlyTypes, bool onlyPrecedenceGroups, bool onlyMacros, - const ExpectedTypeContext *TypeContext, const DeclContext *DC, - bool CanCurrDeclContextHandleAsync) { + CodeCompletionFilter filter, const ExpectedTypeContext *TypeContext, + const DeclContext *DC, bool CanCurrDeclContextHandleAsync) { + assert(filter && "Should never have an empty filter"); // We will be adding foreign results (from another sink) into TargetSink. // TargetSink should have an owning pointer to the allocator that keeps the @@ -28,61 +28,53 @@ static MutableArrayRef copyCodeCompletionResults( targetSink.ForeignAllocators.push_back(source.Allocator); auto startSize = targetSink.Results.size(); + CodeCompletionMacroRoles expectedMacroRoles = getCompletionMacroRoles(filter); std::function - shouldIncludeResult; - if (onlyTypes) { - shouldIncludeResult = [](const ContextFreeCodeCompletionResult *R) -> bool { - if (R->getKind() != CodeCompletionResultKind::Declaration) - return false; - switch (R->getAssociatedDeclKind()) { - case CodeCompletionDeclKind::Module: - case CodeCompletionDeclKind::Class: - case CodeCompletionDeclKind::Actor: - case CodeCompletionDeclKind::Struct: - case CodeCompletionDeclKind::Enum: - case CodeCompletionDeclKind::Protocol: - case CodeCompletionDeclKind::TypeAlias: - case CodeCompletionDeclKind::AssociatedType: - case CodeCompletionDeclKind::GenericTypeParam: - return true; - case CodeCompletionDeclKind::PrecedenceGroup: - case CodeCompletionDeclKind::EnumElement: - case CodeCompletionDeclKind::Constructor: - case CodeCompletionDeclKind::Destructor: - case CodeCompletionDeclKind::Subscript: - case CodeCompletionDeclKind::StaticMethod: - case CodeCompletionDeclKind::InstanceMethod: - case CodeCompletionDeclKind::PrefixOperatorFunction: - case CodeCompletionDeclKind::PostfixOperatorFunction: - case CodeCompletionDeclKind::InfixOperatorFunction: - case CodeCompletionDeclKind::FreeFunction: - case CodeCompletionDeclKind::StaticVar: - case CodeCompletionDeclKind::InstanceVar: - case CodeCompletionDeclKind::LocalVar: - case CodeCompletionDeclKind::GlobalVar: - case CodeCompletionDeclKind::Macro: - return false; - } + shouldIncludeResult = + [filter, expectedMacroRoles]( + const ContextFreeCodeCompletionResult *R) -> bool { + if (R->getKind() != CodeCompletionResultKind::Declaration) + return false; - llvm_unreachable("Unhandled CodeCompletionDeclKind in switch."); - }; - } else if (onlyPrecedenceGroups) { - shouldIncludeResult = [](const ContextFreeCodeCompletionResult *R) -> bool { - return R->getAssociatedDeclKind() == - CodeCompletionDeclKind::PrecedenceGroup; - }; - } else if (onlyMacros) { - shouldIncludeResult = [](const ContextFreeCodeCompletionResult *R) -> bool { - return R->getAssociatedDeclKind() == - CodeCompletionDeclKind::Macro; - }; - } else { - shouldIncludeResult = [](const ContextFreeCodeCompletionResult *R) -> bool { - // PrecedenceGroups are only valid in 'onlyPrecedenceGroups'. - return R->getAssociatedDeclKind() != - CodeCompletionDeclKind::PrecedenceGroup; - }; - } + switch (R->getAssociatedDeclKind()) { + case CodeCompletionDeclKind::PrefixOperatorFunction: + case CodeCompletionDeclKind::PostfixOperatorFunction: + case CodeCompletionDeclKind::InfixOperatorFunction: + case CodeCompletionDeclKind::FreeFunction: + case CodeCompletionDeclKind::GlobalVar: + return filter.contains(CodeCompletionFilterFlag::Expr); + + case CodeCompletionDeclKind::Module: + case CodeCompletionDeclKind::Class: + case CodeCompletionDeclKind::Actor: + case CodeCompletionDeclKind::Struct: + case CodeCompletionDeclKind::Enum: + case CodeCompletionDeclKind::Protocol: + case CodeCompletionDeclKind::TypeAlias: + case CodeCompletionDeclKind::AssociatedType: + case CodeCompletionDeclKind::GenericTypeParam: + return filter.contains(CodeCompletionFilterFlag::Type); + + case CodeCompletionDeclKind::PrecedenceGroup: + return filter.contains(CodeCompletionFilterFlag::PrecedenceGroup); + + case CodeCompletionDeclKind::Macro: + return (bool)(R->getMacroRoles() & expectedMacroRoles); + + case CodeCompletionDeclKind::EnumElement: + case CodeCompletionDeclKind::Constructor: + case CodeCompletionDeclKind::Destructor: + case CodeCompletionDeclKind::Subscript: + case CodeCompletionDeclKind::StaticMethod: + case CodeCompletionDeclKind::InstanceMethod: + case CodeCompletionDeclKind::StaticVar: + case CodeCompletionDeclKind::InstanceVar: + case CodeCompletionDeclKind::LocalVar: + break; + } + + return false; + }; USRBasedTypeContext USRTypeContext(TypeContext, source.USRTypeArena); @@ -151,9 +143,9 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules( context.Cache.set(R.Key, *V); } assert(V.has_value()); - auto newItems = copyCodeCompletionResults( - context.getResultSink(), **V, R.OnlyTypes, R.OnlyPrecedenceGroups, - R.OnlyMacros, TypeContext, DC, CanCurrDeclContextHandleAsync); + auto newItems = copyCodeCompletionResults(context.getResultSink(), **V, + R.Filter, TypeContext, DC, + CanCurrDeclContextHandleAsync); postProcessCompletionResults(newItems, context.CodeCompletionKind, DC, &context.getResultSink()); } diff --git a/lib/IDE/CodeCompletionResult.cpp b/lib/IDE/CodeCompletionResult.cpp index 123312ba525..7173aafc76d 100644 --- a/lib/IDE/CodeCompletionResult.cpp +++ b/lib/IDE/CodeCompletionResult.cpp @@ -20,6 +20,100 @@ using namespace swift; using namespace swift::ide; +CodeCompletionMacroRoles swift::ide::getCompletionMacroRoles(const Decl *D) { + CodeCompletionMacroRoles roles; + + auto *MD = dyn_cast(D); + if (!MD) + return roles; + + MacroRoles macroRoles = MD->getMacroRoles(); + if (macroRoles.contains(MacroRole::Expression)) { + roles |= CodeCompletionMacroRole::Expression; + } + if (macroRoles.contains(MacroRole::Declaration)) { + roles |= CodeCompletionMacroRole::Declaration; + } + if (macroRoles.contains(MacroRole::CodeItem)) { + roles |= CodeCompletionMacroRole::CodeItem; + } + if (macroRoles.contains(MacroRole::Accessor)) { + roles |= CodeCompletionMacroRole::AttachedVar; + } + if (macroRoles & MacroRoles({MacroRole::MemberAttribute, MacroRole::Member, + MacroRole::Conformance})) { + roles |= CodeCompletionMacroRole::AttachedContext; + } + if (macroRoles.contains(MacroRole::Peer)) { + roles |= CodeCompletionMacroRole::AttachedDecl; + } + + return roles; +} + +CodeCompletionMacroRoles +swift::ide::getCompletionMacroRoles(OptionSet kinds) { + CodeCompletionMacroRoles roles; + if (kinds.contains(CustomAttributeKind::VarMacro)) { + roles |= CodeCompletionMacroRole::AttachedVar; + } + if (kinds.contains(CustomAttributeKind::ContextMacro)) { + roles |= CodeCompletionMacroRole::AttachedContext; + } + if (kinds.contains(CustomAttributeKind::DeclMacro)) { + roles |= CodeCompletionMacroRole::AttachedDecl; + } + return roles; +} + +CodeCompletionMacroRoles +swift::ide::getCompletionMacroRoles(CodeCompletionFilter filter) { + CodeCompletionMacroRoles roles; + if (filter.contains(CodeCompletionFilterFlag::ExpressionMacro)) { + roles |= CodeCompletionMacroRole::Expression; + } + if (filter.contains(CodeCompletionFilterFlag::DeclarationMacro)) { + roles |= CodeCompletionMacroRole::Declaration; + } + if (filter.contains(CodeCompletionFilterFlag::CodeItemMacro)) { + roles |= CodeCompletionMacroRole::CodeItem; + } + if (filter.contains(CodeCompletionFilterFlag::AttachedVarMacro)) { + roles |= CodeCompletionMacroRole::AttachedVar; + } + if (filter.contains(CodeCompletionFilterFlag::AttachedContextMacro)) { + roles |= CodeCompletionMacroRole::AttachedContext; + } + if (filter.contains(CodeCompletionFilterFlag::AttachedDeclMacro)) { + roles |= CodeCompletionMacroRole::AttachedDecl; + } + return roles; +} + +CodeCompletionFilter +swift::ide::getCompletionFilter(CodeCompletionMacroRoles roles) { + CodeCompletionFilter filter; + if (roles.contains(CodeCompletionMacroRole::Expression)) { + filter |= CodeCompletionFilterFlag::ExpressionMacro; + } + if (roles.contains(CodeCompletionMacroRole::Declaration)) { + filter |= CodeCompletionFilterFlag::DeclarationMacro; + } + if (roles.contains(CodeCompletionMacroRole::CodeItem)) { + filter |= CodeCompletionFilterFlag::CodeItemMacro; + } + if (roles.contains(CodeCompletionMacroRole::AttachedVar)) { + filter |= CodeCompletionFilterFlag::AttachedVarMacro; + } + if (roles.contains(CodeCompletionMacroRole::AttachedContext)) { + filter |= CodeCompletionFilterFlag::AttachedContextMacro; + } + if (roles.contains(CodeCompletionMacroRole::AttachedDecl)) { + filter |= CodeCompletionFilterFlag::AttachedDeclMacro; + } + return filter; +} + // MARK: - ContextFreeCodeCompletionResult ContextFreeCodeCompletionResult * @@ -42,8 +136,9 @@ ContextFreeCodeCompletionResult::createPatternOrBuiltInOperatorResult( NameForDiagnostics = "operator"; } return new (Sink.getAllocator()) ContextFreeCodeCompletionResult( - Kind, /*AssociatedKind=*/0, KnownOperatorKind, - /*IsSystem=*/false, IsAsync, /*HasAsyncAlternative=*/false, CompletionString, + Kind, /*AssociatedKind=*/0, KnownOperatorKind, /*MacroRoles=*/{}, + /*IsSystem=*/false, IsAsync, /*HasAsyncAlternative=*/false, + CompletionString, /*ModuleName=*/"", BriefDocComment, /*AssociatedUSRs=*/{}, ResultType, NotRecommended, DiagnosticSeverity, DiagnosticMessage, @@ -62,7 +157,8 @@ ContextFreeCodeCompletionResult::createKeywordResult( } return new (Sink.getAllocator()) ContextFreeCodeCompletionResult( CodeCompletionResultKind::Keyword, static_cast(Kind), - CodeCompletionOperatorKind::None, /*IsSystem=*/false, /*IsAsync=*/false, + CodeCompletionOperatorKind::None, /*MacroRoles=*/{}, + /*IsSystem=*/false, /*IsAsync=*/false, /*HasAsyncAlternative=*/false, CompletionString, /*ModuleName=*/"", BriefDocComment, /*AssociatedUSRs=*/{}, ResultType, ContextFreeNotRecommendedReason::None, @@ -81,7 +177,7 @@ ContextFreeCodeCompletionResult::createLiteralResult( } return new (Sink.getAllocator()) ContextFreeCodeCompletionResult( CodeCompletionResultKind::Literal, static_cast(LiteralKind), - CodeCompletionOperatorKind::None, + CodeCompletionOperatorKind::None, /*MacroRoles=*/{}, /*IsSystem=*/false, /*IsAsync=*/false, /*HasAsyncAlternative=*/false, CompletionString, /*ModuleName=*/"", @@ -124,10 +220,10 @@ ContextFreeCodeCompletionResult::createDeclResult( return new (Sink.getAllocator()) ContextFreeCodeCompletionResult( CodeCompletionResultKind::Declaration, static_cast(getCodeCompletionDeclKind(AssociatedDecl)), - CodeCompletionOperatorKind::None, getDeclIsSystem(AssociatedDecl), - IsAsync, HasAsyncAlternative, CompletionString, ModuleName, - BriefDocComment, AssociatedUSRs, ResultType, NotRecommended, - DiagnosticSeverity, DiagnosticMessage, + CodeCompletionOperatorKind::None, getCompletionMacroRoles(AssociatedDecl), + getDeclIsSystem(AssociatedDecl), IsAsync, HasAsyncAlternative, + CompletionString, ModuleName, BriefDocComment, AssociatedUSRs, ResultType, + NotRecommended, DiagnosticSeverity, DiagnosticMessage, getCodeCompletionResultFilterName(CompletionString, Sink.getAllocator()), /*NameForDiagnostics=*/getDeclNameForDiagnostics(AssociatedDecl, Sink)); } diff --git a/lib/IDE/CompletionLookup.cpp b/lib/IDE/CompletionLookup.cpp index aeabd7dd088..a27880e5d72 100644 --- a/lib/IDE/CompletionLookup.cpp +++ b/lib/IDE/CompletionLookup.cpp @@ -1791,23 +1791,21 @@ void CompletionLookup::addMacroExpansion(const MacroDecl *MD, MD->shouldHideFromEditor()) return; - // If this is the wrong kind of macro, we don't need it. - bool wantAttachedMacro = - expectedTypeContext.getExpectedCustomAttributeKinds() - .contains(CustomAttributeKind::Macro); - if ((wantAttachedMacro && !isAttachedMacro(MD->getMacroRoles())) || - (!wantAttachedMacro && !isFreestandingMacro(MD->getMacroRoles()))) - return; + OptionSet expectedKinds = + expectedTypeContext.getExpectedCustomAttributeKinds(); + if (expectedKinds) { + CodeCompletionMacroRoles expectedRoles = + getCompletionMacroRoles(expectedKinds); + CodeCompletionMacroRoles roles = getCompletionMacroRoles(MD); + if (!(roles & expectedRoles)) + return; + } CodeCompletionResultBuilder Builder( Sink, CodeCompletionResultKind::Declaration, getSemanticContext(MD, Reason, DynamicLookupInfo())); Builder.setAssociatedDecl(MD); - if (NeedLeadingMacroPound && !wantAttachedMacro) { - Builder.addTextChunk("#"); - } - addValueBaseName(Builder, MD->getBaseIdentifier()); Type macroType = MD->getInterfaceType(); @@ -2207,7 +2205,8 @@ bool CompletionLookup::tryFunctionCallCompletions( return false; } -bool CompletionLookup::tryModuleCompletions(Type ExprType, bool TypesOnly) { +bool CompletionLookup::tryModuleCompletions(Type ExprType, + CodeCompletionFilter Filter) { if (auto MT = ExprType->getAs()) { ModuleDecl *M = MT->getModule(); @@ -2225,11 +2224,8 @@ bool CompletionLookup::tryModuleCompletions(Type ExprType, bool TypesOnly) { ShadowingOrOriginal.push_back(M); } for (ModuleDecl *M : ShadowingOrOriginal) { - RequestedResultsTy Request = RequestedResultsTy::fromModule(M) - .needLeadingDot(needDot()) - .withModuleQualifier(false); - if (TypesOnly) - Request = Request.onlyTypes(); + RequestedResultsTy Request = + RequestedResultsTy::fromModule(M, Filter).needLeadingDot(needDot()); RequestedCachedResults.insert(Request); } return true; @@ -2345,7 +2341,8 @@ void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD) { bool isIUO = VD && VD->isImplicitlyUnwrappedOptional(); if (tryFunctionCallCompletions(ExprType, VD)) return; - if (tryModuleCompletions(ExprType)) + if (tryModuleCompletions(ExprType, {CodeCompletionFilterFlag::Expr, + CodeCompletionFilterFlag::Type})) return; if (tryTupleExprCompletions(ExprType)) return; @@ -2726,9 +2723,9 @@ void CompletionLookup::addObjCPoundKeywordCompletions(bool needPound) { } } -void CompletionLookup::getMacroCompletions(bool needPound) { +void CompletionLookup::getMacroCompletions(CodeCompletionMacroRoles roles) { RequestedCachedResults.insert( - RequestedResultsTy::toplevelResults().onlyMacros(needPound)); + RequestedResultsTy::topLevelResults(getCompletionFilter(roles))); } void CompletionLookup::getValueCompletionsInDeclContext(SourceLoc Loc, @@ -2744,9 +2741,13 @@ void CompletionLookup::getValueCompletionsInDeclContext(SourceLoc Loc, lookupVisibleDecls(FilteringConsumer, CurrDeclContext, /*IncludeTopLevel=*/false, Loc); - RequestedCachedResults.insert( - RequestedResultsTy::toplevelResults().withModuleQualifier( - ModuleQualifier)); + + CodeCompletionFilter filter{CodeCompletionFilterFlag::Expr, + CodeCompletionFilterFlag::Type}; + if (ModuleQualifier) { + filter |= CodeCompletionFilterFlag::Module; + } + RequestedCachedResults.insert(RequestedResultsTy::topLevelResults(filter)); if (CompletionContext) { // FIXME: this is an awful simplification that says all and only enums can @@ -2891,7 +2892,7 @@ void CompletionLookup::addCallArgumentCompletionResults( } void CompletionLookup::getTypeCompletions(Type BaseType) { - if (tryModuleCompletions(BaseType, /*OnlyTypes=*/true)) + if (tryModuleCompletions(BaseType, CodeCompletionFilterFlag::Type)) return; Kind = LookupKind::Type; this->BaseType = BaseType; @@ -3047,9 +3048,8 @@ void CompletionLookup::collectPrecedenceGroups() { if (Module == CurrModule) continue; - RequestedCachedResults.insert(RequestedResultsTy::fromModule(Module) - .onlyPrecedenceGroups() - .withModuleQualifier(false)); + RequestedCachedResults.insert(RequestedResultsTy::fromModule( + Module, CodeCompletionFilterFlag::PrecedenceGroup)); } } @@ -3139,24 +3139,38 @@ void CompletionLookup::getTypeCompletionsInDeclContext(SourceLoc Loc, lookupVisibleDecls(AccessFilteringConsumer, CurrDeclContext, /*IncludeTopLevel=*/false, Loc); - RequestedCachedResults.insert( - RequestedResultsTy::toplevelResults().onlyTypes().withModuleQualifier( - ModuleQualifier)); + CodeCompletionFilter filter{CodeCompletionFilterFlag::Type}; + if (ModuleQualifier) { + filter |= CodeCompletionFilterFlag::Module; + } + RequestedCachedResults.insert(RequestedResultsTy::topLevelResults(filter)); } -void CompletionLookup::getToplevelCompletions(bool OnlyTypes, bool OnlyMacros) { - Kind = OnlyTypes ? LookupKind::TypeInDeclContext - : LookupKind::ValueInDeclContext; +void CompletionLookup::getToplevelCompletions(CodeCompletionFilter Filter) { + Kind = (Filter - CodeCompletionFilterFlag::Module) + .containsOnly(CodeCompletionFilterFlag::Type) + ? LookupKind::TypeInDeclContext + : LookupKind::ValueInDeclContext; NeedLeadingDot = false; - NeedLeadingMacroPound = !OnlyMacros; UsableFilteringDeclConsumer UsableFilteringConsumer( Ctx.SourceMgr, CurrDeclContext, Ctx.SourceMgr.getIDEInspectionTargetLoc(), *this); AccessFilteringDeclConsumer AccessFilteringConsumer(CurrDeclContext, UsableFilteringConsumer); - DeclFilter Filter = OnlyMacros ? MacroFilter : DefaultFilter; - FilteredDeclConsumer FilteringConsumer(AccessFilteringConsumer, Filter); + + CodeCompletionMacroRoles ExpectedRoles = getCompletionMacroRoles(Filter); + DeclFilter VisibleFilter = + [ExpectedRoles](ValueDecl *VD, DeclVisibilityKind Kind, + DynamicLookupInfo DynamicLookupInfo) { + CodeCompletionMacroRoles Roles = getCompletionMacroRoles(VD); + if (!ExpectedRoles) + return !Roles; + return (bool)(Roles & ExpectedRoles); + }; + + FilteredDeclConsumer FilteringConsumer(AccessFilteringConsumer, + VisibleFilter); CurrModule->lookupVisibleDecls({}, FilteringConsumer, NLKind::UnqualifiedLookup); diff --git a/test/IDE/complete_decl_attribute.swift b/test/IDE/complete_decl_attribute.swift index bcbd8b6f6aa..4b5ca99dd13 100644 --- a/test/IDE/complete_decl_attribute.swift +++ b/test/IDE/complete_decl_attribute.swift @@ -57,9 +57,6 @@ actor MyGenericGlobalActor { static let shared = MyGenricGlobalActor() } -@attached(member) -macro MyMacro() = #externalMacro(module: "Macros", type: "MyMacro") - @available(#^AVAILABILITY1^#) // NOTE: Please do not include the ", N items" after "Begin completions". The @@ -81,7 +78,6 @@ macro MyMacro() = #externalMacro(module: "Macros", type: "MyMacro") // AVAILABILITY1-NEXT: Keyword/None: macCatalystApplicationExtension[#Platform#]; name=macCatalystApplicationExtension // AVAILABILITY1-NEXT: Keyword/None: OpenBSD[#Platform#]; name=OpenBSD{{$}} // AVAILABILITY1-NEXT: Keyword/None: Windows[#Platform#]; name=Windows{{$}} -// AVAILABILITY1-NEXT: End completions @available(*, #^AVAILABILITY2^#) @@ -91,7 +87,6 @@ macro MyMacro() = #externalMacro(module: "Macros", type: "MyMacro") // AVAILABILITY2-NEXT: Keyword/None: renamed: [#Specify replacing name#]; name=renamed{{$}} // AVAILABILITY2-NEXT: Keyword/None: introduced: [#Specify version number#]; name=introduced{{$}} // AVAILABILITY2-NEXT: Keyword/None: deprecated: [#Specify version number#]; name=deprecated{{$}} -// AVAILABILITY2-NEXT: End completions @#^KEYWORD2^# func method(){} @@ -119,8 +114,6 @@ macro MyMacro() = #externalMacro(module: "Macros", type: "MyMacro") // KEYWORD2-DAG: Decl[Struct]/CurrModule: MyPropertyWrapper[#MyPropertyWrapper#]; name=MyPropertyWrapper // KEYWORD2-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: MyResultBuilder[#MyResultBuilder#]; name=MyResultBuilder // KEYWORD2-DAG: Decl[Actor]/CurrModule/TypeRelation[Convertible]: MyGlobalActor[#MyGlobalActor#]; name=MyGlobalActor -// KEYWORD2-DAG: Decl[Macro]/CurrModule: MyMacro[#Void#]; name=MyMacro -// KEYWORD2: End completions @#^KEYWORD3^# class C {} @@ -141,8 +134,6 @@ macro MyMacro() = #externalMacro(module: "Macros", type: "MyMacro") // KEYWORD3-NEXT: Keyword/None: globalActor[#Class Attribute#]; name=globalActor // KEYWORD3-NEXT: Keyword/None: preconcurrency[#Class Attribute#]; name=preconcurrency // KEYWORD3-NEXT: Keyword/None: runtimeMetadata[#Class Attribute#]; name=runtimeMetadata -// KEYWORD3-NEXT: Decl[Macro]/CurrModule: MyMacro[#Void#]; name=MyMacro -// KEYWORD3-NEXT: End completions @#^KEYWORD3_2^#IB class C2 {} // Same as KEYWORD3. @@ -161,8 +152,6 @@ macro MyMacro() = #externalMacro(module: "Macros", type: "MyMacro") // KEYWORD4-NEXT: Keyword/None: globalActor[#Enum Attribute#]; name=globalActor // KEYWORD4-NEXT: Keyword/None: preconcurrency[#Enum Attribute#]; name=preconcurrency // KEYWORD4-NEXT: Keyword/None: runtimeMetadata[#Enum Attribute#]; name=runtimeMetadata -// KEYWORD4-NEXT: Decl[Macro]/CurrModule: MyMacro[#Void#]; name=MyMacro -// KEYWORD4-NEXT: End completions @#^KEYWORD5^# struct S{} // KEYWORD5: Begin completions @@ -177,8 +166,6 @@ macro MyMacro() = #externalMacro(module: "Macros", type: "MyMacro") // KEYWORD5-NEXT: Keyword/None: globalActor[#Struct Attribute#]; name=globalActor // KEYWORD5-NEXT: Keyword/None: preconcurrency[#Struct Attribute#]; name=preconcurrency // KEYWORD5-NEXT: Keyword/None: runtimeMetadata[#Struct Attribute#]; name=runtimeMetadata -// KEYWORD5-NEXT: Decl[Macro]/CurrModule: MyMacro[#Void#]; name=MyMacro -// KEYWORD5-NEXT: End completions @#^ON_GLOBALVAR^# var globalVar // ON_GLOBALVAR-DAG: Keyword/None: available[#Var Attribute#]; name=available diff --git a/test/IDE/complete_macros.swift b/test/IDE/complete_macros.swift new file mode 100644 index 00000000000..ae90d0393a1 --- /dev/null +++ b/test/IDE/complete_macros.swift @@ -0,0 +1,172 @@ +// RUN: %empty-directory(%t) +// RUN: %empty-directory(%t/mods) +// RUN: %empty-directory(%t/co-same) +// RUN: %empty-directory(%t/co-across) +// RUN: split-file %s %t + +// Completion in the current file/module +// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t/co-same + +// Completion across modules +// RUN: %target-swift-frontend -emit-module %t/MacroDefinitions.swift -o %t/mods/ -experimental-allow-module-with-compiler-errors +// RUN: %target-swift-ide-test -batch-code-completion -source-filename %t/MacroUses.swift -filecheck %raw-FileCheck -completion-output-dir %t/co-across -I %t/mods -D SEPARATED + +//--- MacroDefinitions.swift +@freestanding(expression) +public macro freestandingExprIntMacro() -> Int + +@freestanding(expression) +public macro freestandingExprStringMacro() -> String + +@freestanding(expression) +public macro freestandingExprTMacro(_ value: T) -> T + +@freestanding(declaration) +public macro freestandingDeclMacro() + +@freestanding(codeItem) +public macro freestandingCodeItemMacro() + +@attached(accessor) +public macro AttachedAccessorMacro() + +@attached(member) +public macro AttachedMemberMacro() + +@attached(member) +public macro AttachedMemberMacroWithArgs(arg1: Int) + +@attached(memberAttribute) +public macro AttachedMemberAttributeMacro() + +@attached(peer) +public macro AttachedPeerMacro() + +@attached(conformance) +public macro AttachedConformanceMacro() + +@freestanding(expression) +@freestanding(declaration) +@attached(accessor) +@attached(member) +@attached(memberAttribute) +@attached(peer) +@attached(conformance) +public macro EverythingMacro() + +//--- MacroUses.swift +#if SEPARATED +import MacroDefinitions +#endif + +@#^CLASS_ATTR?check=NOMINAL_ATTR^# class C {} +@#^EXTRA_FILTER?check=NOMINAL_ATTR^#IB class C2 {} +@#^ENUM_ATTR?check=NOMINAL_ATTR^# enum E {} +@#^STRUCT_ATTR?check=NOMINAL_ATTR^# struct S{} +// NOMINAL_ATTR-NOT: freestanding +// NOMINAL_ATTR-NOT: AttachedAccessorMacro +// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacro[#Void#]; name=AttachedMemberMacro +// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacroWithArgs({#arg1: Int#})[#Void#]; name=AttachedMemberMacroWithArgs +// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberAttributeMacro[#Void#]; name=AttachedMemberAttributeMacro +// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro +// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedConformanceMacro[#Void#]; name=AttachedConformanceMacro +// NOMINAL_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro + +@#^FUNC_ATTR?check=DECL_ATTR^# func method() {} +struct MethodAttrs { + @#^INIT_ATTR?check=DECL_ATTR^# init() {} + @#^DEINIT_ATTR?check=DECL_ATTR^# deinit{} + @#^METHOD_ATTR?check=DECL_ATTR^# func method() {} +} +// DECL_ATTR-NOT: freestanding +// DECL_ATTR-NOT: AttachedAccessorMacro +// DECL_ATTR-NOT: AttachedMemberMacro +// DECL_ATTR-NOT: AttachedMemberMacroWithArgs +// DECL_ATTR-NOT: AttachedConformanceMacro +// DECL_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro +// DECL_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro + +@#^GLOBAL_ATTR?check=VAR_ATTR^# var globalVar +struct PropAttr { + @#^PROP_ATTR?check=VAR_ATTR^# var propVar + func localAttr() { + @#^LOCAL_ATTR?check=VAR_ATTR^# var localVar + } +} +// VAR_ATTR-NOT: freestanding +// VAR_ATTR-NOT: AttachedMemberMacro +// VAR_ATTR-NOT: AttachedMemberMacroWithArgs +// VAR_ATTR-NOT: AttachedMemberAttributeMacro +// VAR_ATTR-NOT: AttachedConformanceMacro +// VAR_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedAccessorMacro[#Void#]; name=AttachedAccessorMacro +// VAR_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro +// VAR_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro + +func paramAttr(@#^PARAM_ATTR?check=PARAM_ATTR^#) {} +func paramAttr2(@#^PARAM2_ATTR?check=PARAM_ATTR^# arg: Int) {} +// TODO: These should both be PARAM_ATTR +func takeNoArgClosure(_: (Int) -> Void) { + takeClosure { @#^NO_ARG_CLOSURE_ATTR?check=INDEPENDENT_ATTR^# in + print("x") + } +} +func takeNoArgClosure(_: () -> Void) { + takeClosure { @#^CLOSURE_ATTR?check=INDEPENDENT_ATTR^# in + print("x") + } +} +// PARAM_ATTR-NOT: freestanding +// PARAM_ATTR-NOT: AttachedAccessorMacro +// PARAM_ATTR-NOT: AttachedMemberMacro +// PARAM_ATTR-NOT: AttachedMemberMacroWithArgs +// PARAM_ATTR-NOT: AttachedMemberAttributeMacro +// PARAM_ATTR-NOT: AttachedPeerMacro +// PARAM_ATTR-NOT: AttachedConformanceMacro +// PARAM_ATTR-NOT: EverythingMacro + +##^TOP_LEVEL_FREESTANDING?check=ALL_FREESTANDING^# +func nestedFreestanding() { + ##^TOP_NESTED_FREESTANDING?check=ALL_FREESTANDING^# +} +// ALL_FREESTANDING-NOT: Attached +// ALL_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingDeclMacro[#Void#]; name=freestandingDeclMacro +// ALL_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingCodeItemMacro[#Void#]; name=freestandingCodeItemMacro +// ALL_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingExprIntMacro[#Int#]; name=freestandingExprIntMacro +// ALL_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingExprStringMacro[#String#]; name=freestandingExprStringMacro +// ALL_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingExprTMacro({#(value): T#})[#T#]; name=freestandingExprTMacro(:) +// ALL_FREESTANDING-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro + +func exprFreestanding(arg: Int) { + _ = arg + ##^EXPR_FREESTANDING^# +} +// EXPR_FREESTANDING-NOT: freestandingDeclMacro +// EXPR_FREESTANDING-NOT: freestandingCodeItemMacro +// EXPR_FREESTANDING-NOT: Attached +// EXPR_FREESTANDING-DAG: Decl[Macro]/{{.*}}/TypeRelation[Convertible]: freestandingExprIntMacro[#Int#]; name=freestandingExprIntMacro +// EXPR_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingExprStringMacro[#String#]; name=freestandingExprStringMacro +// EXPR_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingExprTMacro({#(value): T#})[#T#]; name=freestandingExprTMacro(:) +// TODO: This should be invalid in both same module and across modules +// EXPR_FREESTANDING-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro + +struct NestedFreestanding { + ##^TYPE_NESTED_FREESTANDING?check=ITEM_FREESTANDING^# +} +// ITEM_FREESTANDING-NOT: Attached +// ITEM_FREESTANDING-NOT: freestandingExpr +// ITEM_FREESTANDING-NOT: freestandingCodeItemMacro +// ITEM_FREESTANDING-DAG: Decl[Macro]/{{.*}}: freestandingDeclMacro[#Void#]; name=freestandingDeclMacro +// ITEM_FREESTANDING-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro + +struct LastMember { + @#^LAST_MEMBER_ATTR?check=INDEPENDENT_ATTR^# +} +@#^INDEPENDENT?check=INDEPENDENT_ATTR^# +// INDEPENDENT_ATTR-NOT: freestandingExprMacro +// INDEPENDENT_ATTR-NOT: freestandingDeclMacro +// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedAccessorMacro[#Void#]; name=AttachedAccessorMacro +// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacro[#Void#]; name=AttachedMemberMacro +// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberMacroWithArgs({#arg1: Int#})[#Void#]; name=AttachedMemberMacroWithArgs +// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedMemberAttributeMacro[#Void#]; name=AttachedMemberAttributeMacro +// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedPeerMacro[#Void#]; name=AttachedPeerMacro +// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: AttachedConformanceMacro[#Void#]; name=AttachedConformanceMacro +// INDEPENDENT_ATTR-DAG: Decl[Macro]/{{.*}}: EverythingMacro[#Void#]; name=EverythingMacro diff --git a/test/IDE/complete_pound_directive.swift b/test/IDE/complete_pound_directive.swift index 4e6da73fcb1..d823357e2ae 100644 --- a/test/IDE/complete_pound_directive.swift +++ b/test/IDE/complete_pound_directive.swift @@ -14,14 +14,15 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-sourcetext -code-completion-token=CONDITION_GLOBAL_2 | %FileCheck %s -check-prefix=CONDITION -check-prefix=NOFLAG // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-sourcetext -code-completion-token=CONDITION_GLOBAL_2 -D FOO -D BAR | %FileCheck %s -check-prefix=CONDITION -check-prefix=WITHFLAG -// POUND_DIRECTIVE: Begin completions, 7 items // POUND_DIRECTIVE-DAG: Keyword[#sourceLocation]/None: sourceLocation(file: {#String#}, line: {#Int#}); name=sourceLocation(file:line:); sourcetext=sourceLocation(file: <#T##String#>, line: <#T##Int#>) -// POUND_DIRECTIVE-DAG: Keyword[#warning]/None: warning("{#(message)#}"); name=warning(""); sourcetext=warning(\"<#T##message#>\") -// POUND_DIRECTIVE-DAG: Keyword[#error]/None: error("{#(message)#}"); name=error(""); sourcetext=error(\"<#T##message#>\") // POUND_DIRECTIVE-DAG: Keyword[#if]/None: if {#(condition)#}; name=if ; sourcetext=if <#T##condition#> // POUND_DIRECTIVE-DAG: Keyword[#elseif]/None: elseif {#(condition)#}; name=elseif ; sourcetext=elseif <#T##condition#> // POUND_DIRECTIVE-DAG: Keyword[#else]/None: else; name=else; sourcetext=else // POUND_DIRECTIVE-DAG: Keyword[#endif]/None: endif; name=endif; sourcetext=endif +// TODO: These currently do not match between when macros are enabled and when +// they aren't. Update to macros when +// POUND_DIRECTIVE-DAG: name=warning +// POUND_DIRECTIVE-DAG: name=error class C { ##^POUND_NOMINAL_TOP^# diff --git a/test/IDE/complete_pound_expr.swift b/test/IDE/complete_pound_expr.swift index 8d45ec910c8..bb074a1ab0d 100644 --- a/test/IDE/complete_pound_expr.swift +++ b/test/IDE/complete_pound_expr.swift @@ -15,10 +15,9 @@ func test1() { let _ = useSelector(##^POUND_EXPR_3^#) } -// POUND_EXPR_INTCONTEXT: Begin completions, 10 items +// POUND_EXPR_INTCONTEXT-NOT: warning +// POUND_EXPR_INTCONTEXT-NOT: error // POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: function[#ExpressibleByStringLiteral#]; name=function -// POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: warning({#(message): String#})[#Void#]; name=warning(:) -// POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: error({#(message): String#})[#Void#]; name=error(:) // POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: fileID[#ExpressibleByStringLiteral#]; name=fileID // POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: file[#ExpressibleByStringLiteral#]; name=file // POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: dsohandle[#UnsafeRawPointer#]; name=dsohandle @@ -27,10 +26,9 @@ func test1() { // POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: externalMacro({#module: String#}, {#type: String#})[#T#]; name=externalMacro(module:type:) // POUND_EXPR_INTCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: filePath[#ExpressibleByStringLiteral#]; name=filePath -// POUND_EXPR_STRINGCONTEXT: Begin completions, 11 items +// POUND_EXPR_STRINGCONTEXT-NOT: warning +// POUND_EXPR_STRINGCONTEXT-NOT: error // POUND_EXPR_STRINGCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: function[#ExpressibleByStringLiteral#]; name=function -// POUND_EXPR_STRINGCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: warning({#(message): String#})[#Void#]; name=warning(:) -// POUND_EXPR_STRINGCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: error({#(message): String#})[#Void#]; name=error(:) // POUND_EXPR_STRINGCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: fileID[#ExpressibleByStringLiteral#]; name=fileID // POUND_EXPR_STRINGCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: file[#ExpressibleByStringLiteral#]; name=file // POUND_EXPR_STRINGCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: dsohandle[#UnsafeRawPointer#]; name=dsohandle @@ -40,10 +38,9 @@ func test1() { // POUND_EXPR_STRINGCONTEXT-DAG: Keyword/None/TypeRelation[Convertible]: keyPath({#@objc property sequence#})[#String#]; // POUND_EXPR_STRINGCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: externalMacro({#module: String#}, {#type: String#})[#T#]; name=externalMacro(module:type:) -// POUND_EXPR_SELECTORCONTEXT: Begin completions, 11 items +// POUND_EXPR_SELECTORCONTEXT-NOT: warning +// POUND_EXPR_SELECTORCONTEXT-NOT: error // POUND_EXPR_SELECTORCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: function[#ExpressibleByStringLiteral#]; name=function -// POUND_EXPR_SELECTORCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: warning({#(message): String#})[#Void#]; name=warning(:) -// POUND_EXPR_SELECTORCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: error({#(message): String#})[#Void#]; name=error(:) // POUND_EXPR_SELECTORCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: fileID[#ExpressibleByStringLiteral#]; name=fileID // POUND_EXPR_SELECTORCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: file[#ExpressibleByStringLiteral#]; name=file // POUND_EXPR_SELECTORCONTEXT-DAG: Decl[Macro]/OtherModule[Swift]/IsSystem: dsohandle[#UnsafeRawPointer#]; name=dsohandle diff --git a/test/SourceKit/CodeComplete/complete_sort_order.swift b/test/SourceKit/CodeComplete/complete_sort_order.swift index 226ffbddccf..30851bde8c0 100644 --- a/test/SourceKit/CodeComplete/complete_sort_order.swift +++ b/test/SourceKit/CodeComplete/complete_sort_order.swift @@ -13,7 +13,6 @@ func test() { // RUN: %FileCheck -check-prefix=NAME_UNSORTED %s < %t.orig.off // RUN: not %diff -u %t.orig %t.orig.off -// NAME_SORTED: key.name: "column" // NAME_SORTED: key.name: "foo(a:)" // NAME_SORTED-NOT: key.name: // NAME_SORTED: key.name: "foo(a:)" @@ -46,7 +45,6 @@ func test() { // CONTEXT: key.name: "foo(b:)" // CONTEXT-NOT: key.name: // CONTEXT: key.name: "test()" -// CONTEXT: key.name: "column" // CONTEXT: key.name: "complete_sort_order" // RUN: %complete-test -tok=STMT_0 %s | %FileCheck %s -check-prefix=STMT @@ -242,7 +240,3 @@ func test8() { // CALLARG: String // CALLARG: intVal } - -// REQUIRES: swift_swift_parser -// FIXME: Swift parser is not enabled on Linux CI yet. -// REQUIRES: OS=macosx diff --git a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp index baad6d1c339..eea69a75bfd 100644 --- a/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp +++ b/tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp @@ -1167,9 +1167,9 @@ Completion *CompletionBuilder::finish() { new (sink.allocator) ContextFreeCodeCompletionResult( contextFreeBase.getKind(), contextFreeBase.getOpaqueAssociatedKind(), opKind, - contextFreeBase.isSystem(), contextFreeBase.isAsync(), - contextFreeBase.hasAsyncAlternative(), newCompletionString, - contextFreeBase.getModuleName(), + contextFreeBase.getMacroRoles(), contextFreeBase.isSystem(), + contextFreeBase.isAsync(), contextFreeBase.hasAsyncAlternative(), + newCompletionString, contextFreeBase.getModuleName(), contextFreeBase.getBriefDocComment(), contextFreeBase.getAssociatedUSRs(), contextFreeBase.getResultType(),