diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index 9d07eb6969343..bc2f166c26723 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -66,6 +66,7 @@ IDENTIFIER(decodeIfPresent) IDENTIFIER(Decoder) IDENTIFIER(decoder) IDENTIFIER_(Differentiation) +IDENTIFIER_WITH_NAME(PatternMatchVar, "$match") IDENTIFIER(dynamicallyCall) IDENTIFIER(dynamicMember) IDENTIFIER(Element) diff --git a/include/swift/Sema/CodeCompletionTypeChecking.h b/include/swift/Sema/CodeCompletionTypeChecking.h index 0ea51047f3f07..b54ade5688da0 100644 --- a/include/swift/Sema/CodeCompletionTypeChecking.h +++ b/include/swift/Sema/CodeCompletionTypeChecking.h @@ -89,21 +89,26 @@ namespace swift { /// formed during expression type-checking. class UnresolvedMemberTypeCheckCompletionCallback: public TypeCheckCompletionCallback { public: - struct Result { + struct ExprResult { Type ExpectedTy; bool IsImplicitSingleExpressionReturn; }; private: CodeCompletionExpr *CompletionExpr; - SmallVector Results; + SmallVector ExprResults; + SmallVector EnumPatternTypes; bool GotCallback = false; public: UnresolvedMemberTypeCheckCompletionCallback(CodeCompletionExpr *CompletionExpr) : CompletionExpr(CompletionExpr) {} - ArrayRef getResults() const { return Results; } + ArrayRef getExprResults() const { return ExprResults; } + + /// If we are completing in a pattern matching position, the types of all + /// enums for whose cases are valid as an \c EnumElementPattern. + ArrayRef getEnumPatternTypes() const { return EnumPatternTypes; } /// True if at least one solution was passed via the \c sawSolution /// callback. diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index d83358cd657a4..922e87aee5015 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -3312,8 +3312,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { getSemanticContext(EED, Reason, dynamicLookupInfo), expectedTypeContext); Builder.setAssociatedDecl(EED); - if (HasTypeContext) - Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific); addLeadingDot(Builder); addValueBaseName(Builder, EED->getBaseIdentifier()); @@ -4372,6 +4370,23 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { addObjCPoundKeywordCompletions(/*needPound=*/true); } + /// Returns \c true if \p VD is an initializer on the \c Optional or \c + /// Id_OptionalNilComparisonType type from the Swift stdlib. + static bool isInitializerOnOptional(Type T, ValueDecl *VD) { + bool IsOptionalType = false; + IsOptionalType |= static_cast(T->getOptionalObjectType()); + if (auto *NTD = T->getAnyNominal()) { + IsOptionalType |= NTD->getBaseIdentifier() == + VD->getASTContext().Id_OptionalNilComparisonType; + } + if (IsOptionalType && VD->getModuleContext()->isStdlibModule() && + isa(VD)) { + return true; + } else { + return false; + } + } + void getUnresolvedMemberCompletions(Type T) { if (!T->mayHaveMembers()) return; @@ -4389,16 +4404,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { // We can only say .foo where foo is a static member of the contextual // type and has the same type (or if the member is a function, then the // same result type) as the contextual type. - FilteredDeclConsumer consumer(*this, [=](ValueDecl *VD, - DeclVisibilityKind Reason) { - if (T->getOptionalObjectType() && - VD->getModuleContext()->isStdlibModule()) { - // In optional context, ignore '.init()', 'init(nilLiteral:)', - if (isa(VD)) - return false; - } - return true; - }); + FilteredDeclConsumer consumer( + *this, [=](ValueDecl *VD, DeclVisibilityKind Reason) { + // In optional context, ignore '.init()', 'init(nilLiteral:)', + return !isInitializerOnOptional(T, VD); + }); auto baseType = MetatypeType::get(T); llvm::SaveAndRestore SaveLook(Kind, LookupKind::ValueExpr); @@ -4410,6 +4420,21 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { /*includeProtocolExtensionMembers*/true); } + /// Complete all enum members declared on \p T. + void getEnumElementPatternCompletions(Type T) { + if (!isa_and_nonnull(T->getAnyNominal())) + return; + + auto baseType = MetatypeType::get(T); + llvm::SaveAndRestore SaveLook(Kind, LookupKind::EnumElement); + llvm::SaveAndRestore SaveType(ExprType, baseType); + llvm::SaveAndRestore SaveUnresolved(IsUnresolvedMember, true); + lookupVisibleMemberDecls(*this, baseType, CurrDeclContext, + /*includeInstanceMembers=*/false, + /*includeDerivedRequirements=*/false, + /*includeProtocolExtensionMembers=*/true); + } + void getUnresolvedMemberCompletions(ArrayRef Types) { NeedLeadingDot = !HaveDot; @@ -6461,8 +6486,8 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext, } void deliverUnresolvedMemberResults( - ArrayRef Results, - DeclContext *DC, SourceLoc DotLoc, + ArrayRef Results, + ArrayRef EnumPatternTypes, DeclContext *DC, SourceLoc DotLoc, ide::CodeCompletionContext &CompletionCtx, CodeCompletionConsumer &Consumer) { ASTContext &Ctx = DC->getASTContext(); @@ -6471,7 +6496,7 @@ void deliverUnresolvedMemberResults( assert(DotLoc.isValid()); Lookup.setHaveDot(DotLoc); - Lookup.shouldCheckForDuplicates(Results.size() > 1); + Lookup.shouldCheckForDuplicates(Results.size() + EnumPatternTypes.size() > 1); // Get the canonical versions of the top-level types SmallPtrSet originalTypes; @@ -6496,6 +6521,22 @@ void deliverUnresolvedMemberResults( Lookup.getUnresolvedMemberCompletions(Result.ExpectedTy); } + // Offer completions when interpreting the pattern match as an + // EnumElementPattern. + for (auto &Ty : EnumPatternTypes) { + Lookup.setExpectedTypes({Ty}, /*IsImplicitSingleExpressionReturn=*/false, + /*expectsNonVoid=*/true); + Lookup.setIdealExpectedType(Ty); + + // We can pattern match MyEnum against Optional + if (Ty->getOptionalObjectType()) { + Type Unwrapped = Ty->lookThroughAllOptionalTypes(); + Lookup.getEnumElementPatternCompletions(Unwrapped); + } + + Lookup.getEnumElementPatternCompletions(Ty); + } + deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer); } @@ -6608,8 +6649,9 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) { Lookup.fallbackTypeCheck(CurDeclContext); addKeywords(CompletionContext.getResultSink(), MaybeFuncBody); - deliverUnresolvedMemberResults(Lookup.getResults(), CurDeclContext, DotLoc, - CompletionContext, Consumer); + deliverUnresolvedMemberResults(Lookup.getExprResults(), + Lookup.getEnumPatternTypes(), CurDeclContext, + DotLoc, CompletionContext, Consumer); return true; } case CompletionKind::KeyPathExprSwift: { diff --git a/lib/Sema/TypeCheckCodeCompletion.cpp b/lib/Sema/TypeCheckCodeCompletion.cpp index 4706719235849..ea70d8365f454 100644 --- a/lib/Sema/TypeCheckCodeCompletion.cpp +++ b/lib/Sema/TypeCheckCodeCompletion.cpp @@ -811,59 +811,11 @@ class CompletionContextFinder : public ASTWalker { } // end namespace -// Determine if the target expression is the implicit BinaryExpr generated for -// pattern-matching in a switch/if/guard case ( ~= matchValue). -static bool isForPatternMatch(SolutionApplicationTarget &target) { - if (target.getExprContextualTypePurpose() != CTP_Condition) - return false; - Expr *condition = target.getAsExpr(); - if (!condition->isImplicit()) - return false; - if (auto *BE = dyn_cast(condition)) { - Identifier id; - if (auto *ODRE = dyn_cast(BE->getFn())) { - id = ODRE->getDecls().front()->getBaseIdentifier(); - } else if (auto *DRE = dyn_cast(BE->getFn())) { - id = DRE->getDecl()->getBaseIdentifier(); - } - if (id != target.getDeclContext()->getASTContext().Id_MatchOperator) - return false; - return isa(BE->getLHS()); - } - return false; -} - -/// Remove any solutions from the provided vector that both require fixes and have a -/// score worse than the best. +/// Remove any solutions from the provided vector that both require fixes and +/// have a score worse than the best. static void filterSolutions(SolutionApplicationTarget &target, SmallVectorImpl &solutions, CodeCompletionExpr *completionExpr) { - // FIXME: this is only needed because in pattern matching position, the - // code completion expression always becomes an expression pattern, which - // requires the ~= operator to be defined on the type being matched against. - // Pattern matching against an enum doesn't require that however, so valid - // solutions always end up having fixes. This is a problem because there will - // always be a valid solution as well. Optional defines ~= between Optional - // and _OptionalNilComparisonType (which defines a nilLiteral initializer), - // and the matched-against value can implicitly be made Optional if it isn't - // already, so _OptionalNilComparisonType is always a valid solution for the - // completion. That only generates the 'nil' completion, which is rarely what - // the user intends to write in this position and shouldn't be preferred over - // the other formed solutions (which require fixes). We should generate enum - // pattern completions separately, but for now ignore the - // _OptionalNilComparisonType solution. - if (isForPatternMatch(target) && completionExpr) { - solutions.erase(llvm::remove_if(solutions, [&](const Solution &S) { - ASTContext &ctx = S.getConstraintSystem().getASTContext(); - if (!S.hasType(completionExpr)) - return false; - if (auto ty = S.getResolvedType(completionExpr)) - if (auto *NTD = ty->getAnyNominal()) - return NTD->getBaseIdentifier() == ctx.Id_OptionalNilComparisonType; - return false; - }), solutions.end()); - } - if (solutions.size() <= 1) return; @@ -1286,6 +1238,69 @@ sawSolution(const constraints::Solution &S) { } } +/// If the code completion variable occurs in a pattern matching position, we +/// have an AST that looks like this. +/// \code +/// (binary_expr implicit type='$T3' +/// (overloaded_decl_ref_expr function_ref=compound decls=[ +/// Swift.(file).~=, +/// Swift.(file).Optional extension.~=]) +/// (tuple_expr implicit type='($T1, (OtherEnum))' +/// (code_completion_expr implicit type='$T1') +/// (declref_expr implicit decl=swift_ide_test.(file).foo(x:).$match))) +/// \endcode +/// If the code completion expression occurs in such an AST, return the +/// declaration of the \c $match variable, otherwise return \c nullptr. +VarDecl *getMatchVarIfInPatternMatch(CodeCompletionExpr *CompletionExpr, + ConstraintSystem &CS) { + auto &Context = CS.getASTContext(); + + TupleExpr *ArgTuple = + dyn_cast_or_null(CS.getParentExpr(CompletionExpr)); + if (!ArgTuple || !ArgTuple->isImplicit() || ArgTuple->getNumElements() != 2) { + return nullptr; + } + + auto Binary = dyn_cast_or_null(CS.getParentExpr(ArgTuple)); + if (!Binary || !Binary->isImplicit()) { + return nullptr; + } + + auto CalledOperator = Binary->getFn(); + if (!CalledOperator || !CalledOperator->isImplicit()) { + return nullptr; + } + // The reference to the ~= operator might be an OverloadedDeclRefExpr or a + // DeclRefExpr, depending on how many ~= operators are viable. + if (auto Overloaded = + dyn_cast_or_null(CalledOperator)) { + if (!llvm::all_of(Overloaded->getDecls(), [&Context](ValueDecl *D) { + return D->getBaseName() == Context.Id_MatchOperator; + })) { + return nullptr; + } + } else if (auto Ref = dyn_cast_or_null(CalledOperator)) { + if (Ref->getDecl()->getBaseName() != Context.Id_MatchOperator) { + return nullptr; + } + } else { + return nullptr; + } + + auto MatchArg = dyn_cast_or_null(ArgTuple->getElement(1)); + if (!MatchArg || !MatchArg->isImplicit()) { + return nullptr; + } + + auto MatchVar = MatchArg->getDecl(); + if (MatchVar && MatchVar->isImplicit() && + MatchVar->getBaseName() == Context.Id_PatternMatchVar) { + return dyn_cast(MatchVar); + } else { + return nullptr; + } +} + void UnresolvedMemberTypeCheckCompletionCallback:: sawSolution(const constraints::Solution &S) { GotCallback = true; @@ -1295,18 +1310,34 @@ sawSolution(const constraints::Solution &S) { // If the type couldn't be determined (e.g. because there isn't any context // to derive it from), let's not attempt to do a lookup since it wouldn't // produce any useful results anyway. - if (!ExpectedTy || ExpectedTy->is()) - return; - - // If ExpectedTy is a duplicate of any other result, ignore this solution. - if (llvm::any_of(Results, [&](const Result &R) { - return R.ExpectedTy->isEqual(ExpectedTy); - })) { - return; + if (ExpectedTy && !ExpectedTy->is()) { + // If ExpectedTy is a duplicate of any other result, ignore this solution. + if (!llvm::any_of(ExprResults, [&](const ExprResult &R) { + return R.ExpectedTy->isEqual(ExpectedTy); + })) { + bool SingleExprBody = + isImplicitSingleExpressionReturn(CS, CompletionExpr); + ExprResults.push_back({ExpectedTy, SingleExprBody}); + } } - bool SingleExprBody = isImplicitSingleExpressionReturn(CS, CompletionExpr); - Results.push_back({ExpectedTy, SingleExprBody}); + if (auto MatchVar = getMatchVarIfInPatternMatch(CompletionExpr, CS)) { + Type MatchVarType; + // If the MatchVar has an explicit type, it's not part of the solution. But + // we can look it up in the constraint system directly. + if (auto T = S.getConstraintSystem().getVarType(MatchVar)) { + MatchVarType = T; + } else { + MatchVarType = S.getResolvedType(MatchVar); + } + if (MatchVarType && !MatchVarType->is()) { + if (!llvm::any_of(EnumPatternTypes, [&](const Type &R) { + return R->isEqual(MatchVarType); + })) { + EnumPatternTypes.push_back(MatchVarType); + } + } + } } void KeyPathTypeCheckCompletionCallback::sawSolution( diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 01a5a07e596f1..c3305b6e68fb9 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -633,11 +633,9 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC, PrettyStackTracePattern stackTrace(Context, "type-checking", EP); // Create a 'let' binding to stand in for the RHS value. - auto *matchVar = new (Context) VarDecl(/*IsStatic*/false, - VarDecl::Introducer::Let, - EP->getLoc(), - Context.getIdentifier("$match"), - DC); + auto *matchVar = + new (Context) VarDecl(/*IsStatic*/ false, VarDecl::Introducer::Let, + EP->getLoc(), Context.Id_PatternMatchVar, DC); matchVar->setInterfaceType(rhsType->mapTypeOutOfContext()); matchVar->setImplicit(); diff --git a/test/IDE/complete_enum_elements.swift b/test/IDE/complete_enum_elements.swift index 3e059f8ee8093..096c0e2482a08 100644 --- a/test/IDE/complete_enum_elements.swift +++ b/test/IDE/complete_enum_elements.swift @@ -384,3 +384,116 @@ func testUnqualified1(x: QuxEnum) { // UNRESOLVED_3: End completions } + +struct SomeStruct: Equatable { + let structMember: String +} + +enum OtherEnum { + case otherEnumCase + + static var otherStaticMember: OtherEnum { fatalError() } +} + +enum PlainEnum { + case caseWithAssociatedType(SomeStruct) + + static var staticMember: PlainEnum { fatalError() } +} + +func completeEquatableEnum(x: PlainEnum) { + switch x { + case .#^PATTERN_MATCH_PLAIN_ENUM^# +// We shouldn't suggest staticMember here because PlainEnum isn't equatable and thus doesn't have a ~= operator defined between instances +// PATTERN_MATCH_PLAIN_ENUM: Begin completions, 1 items +// PATTERN_MATCH_PLAIN_ENUM-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: caseWithAssociatedType({#SomeStruct#})[#PlainEnum#]; +// PATTERN_MATCH_PLAIN_ENUM: End completions + } +} + +enum EnumWithCustomPatternMatchingOperator { + case caseWithAssociatedType(SomeStruct) + + static var staticMember: EnumWithCustomPatternMatchingOperator { fatalError() } +} + +func ~=(pattern: OtherEnum, value: EnumWithCustomPatternMatchingOperator) -> Bool { + return true +} + +func completeEnumWithCustomPatternMatchingOperator(x: EnumWithCustomPatternMatchingOperator) { + switch x { + case .#^PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING^# +// We should be suggesting static members of `OtherEnum`, because we can match it to `EnumWithCustomPatternMatchingOperator` using the custom pattern match operator. +// We should also suggest enum cases from `EnumWithCustomPatternMatchingOperator` whose pattern matching doesn't go through any `~=` operator. +// We shouldn't suggest `staticMember` because `EnumWithCustomPatternMatchingOperator` doesn`t have `~=` defined between two of its instances. +// PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING: Begin completions, 4 items +// PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: otherEnumCase[#OtherEnum#]; +// PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[StaticVar]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: otherStaticMember[#OtherEnum#]; +// PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): OtherEnum#})[#(into: inout Hasher) -> Void#]; +// PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: caseWithAssociatedType({#SomeStruct#})[#EnumWithCustomPatternMatchingOperator#]; +// PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING: End completions + } +} + +func completeEnumAssociatedTypeWithCustomPatternMatchingOperator(x: EnumWithCustomPatternMatchingOperator) { + switch x { + case .caseWithAssociatedType(.#^COMPLETE_ASSOCIATED_TYPE_WITH_CUSTOM_PATTERN_MATCHING^#) +// COMPLETE_ASSOCIATED_TYPE_WITH_CUSTOM_PATTERN_MATCHING: Begin completions, 1 items +// COMPLETE_ASSOCIATED_TYPE_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Identical]: init({#structMember: String#})[#SomeStruct#]; +// COMPLETE_ASSOCIATED_TYPE_WITH_CUSTOM_PATTERN_MATCHING: End completions + } +} + +enum EquatableEnum: Equatable { + case caseWithAssociatedType(SomeStruct) + + static var staticMember: EnumWithCustomPatternMatchingOperator { fatalError() } +} + +func completeEquatableEnum(x: EquatableEnum) { + switch x { + case .#^PATTERN_MATCH_EQUATABLE_ENUM^# +// Suggest all static members of `EquatableEnum` because we can pattern match through the `~=` operator between two equatable types defined in the stdlib. +// PATTERN_MATCH_EQUATABLE_ENUM: Begin completions, 2 items +// PATTERN_MATCH_EQUATABLE_ENUM-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: caseWithAssociatedType({#SomeStruct#})[#EquatableEnum#]; +// PATTERN_MATCH_EQUATABLE_ENUM-DAG: Decl[StaticVar]/CurrNominal: staticMember[#EnumWithCustomPatternMatchingOperator#]; +// PATTERN_MATCH_EQUATABLE_ENUM: End completions + } +} + +enum EquatableEnumWithCustomPatternMatchingOperator: Equatable { + case caseWithAssociatedType(SomeStruct) + + static var staticMember: EnumWithCustomPatternMatchingOperator { fatalError() } +} + +func ~=(pattern: OtherEnum, value: EquatableEnumWithCustomPatternMatchingOperator) -> Bool { + return true +} + +func completeEnumWithCustomPatternMatchingOperator(x: EquatableEnumWithCustomPatternMatchingOperator) { + switch x { + case .#^PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING^# +// Same as PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING but also suggest static members on `EquatableEnumWithCustomPatternMatchingOperator` because its `Equatable` +// PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING: Begin completions, 5 items +// PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: otherEnumCase[#OtherEnum#]; +// PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[StaticVar]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: otherStaticMember[#OtherEnum#]; +// PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: hash({#(self): OtherEnum#})[#(into: inout Hasher) -> Void#]; +// PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: caseWithAssociatedType({#SomeStruct#})[#EquatableEnumWithCustomPatternMatchingOperator#]; +// PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING-DAG: Decl[StaticVar]/CurrNominal: staticMember[#EnumWithCustomPatternMatchingOperator#]; +// PATTERN_MATCH_EQUATABLE_ENUM_WITH_CUSTOM_PATTERN_MATCHING: End completions + } +} + +enum WithNestedEnum { + case bar(PlainEnum) +} + +func completeInNestedPatternMatching(x: WithNestedEnum) { + switch x { + case .bar(.#^NESTED_ENUM_PATTERN_MATCHING^#) +} +// NESTED_ENUM_PATTERN_MATCHING: Begin completions, 1 items +// NESTED_ENUM_PATTERN_MATCHING-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: caseWithAssociatedType({#SomeStruct#})[#PlainEnum#]; +// NESTED_ENUM_PATTERN_MATCHING: End completions diff --git a/test/IDE/complete_exception.swift b/test/IDE/complete_exception.swift index f9918464b7838..104922dd13362 100644 --- a/test/IDE/complete_exception.swift +++ b/test/IDE/complete_exception.swift @@ -108,8 +108,8 @@ func test002() { func test003() { do {} catch Error4.#^CATCH2^# // CATCH2: Begin completions -// CATCH2: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E1[#Error4#]{{; name=.+$}} -// CATCH2: Decl[EnumElement]/CurrNominal/TypeRelation[Convertible]: E2({#Int32#})[#Error4#]{{; name=.+$}} +// CATCH2: Decl[EnumElement]/CurrNominal: E1[#Error4#]{{; name=.+$}} +// CATCH2: Decl[EnumElement]/CurrNominal: E2({#Int32#})[#Error4#]{{; name=.+$}} // CATCH2: End completions } diff --git a/test/IDE/complete_in_result_builder.swift b/test/IDE/complete_in_result_builder.swift index 480c42c59d606..6192a00c789f7 100644 --- a/test/IDE/complete_in_result_builder.swift +++ b/test/IDE/complete_in_result_builder.swift @@ -123,19 +123,9 @@ func testPatternMatching() { @TupleBuilder var x3 { let x: FooStruct? = FooStruct() guard case .#^GUARD_CASE_PATTERN_1?check=OPTIONAL_FOOSTRUCT^# = x {} - // OPTIONAL_FOOSTRUCT: Begin completions, 9 items - // OPTIONAL_FOOSTRUCT-DAG: Keyword[nil]/None/Erase[1]/TypeRelation[Identical]: nil[#FooStruct?#]; name=nil + // OPTIONAL_FOOSTRUCT: Begin completions, 2 items // OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: none[#Optional#]; name=none // OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: some({#FooStruct#})[#Optional#]; name=some() - // FIXME: 'FooStruct' members should not be shown. - // OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init()[#FooStruct#]; name=init() - // OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init({#Int#})[#FooStruct#]; name=init() - // OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: boolGen({#(self): FooStruct#})[#() -> Bool#]; name=boolGen(:) - // OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: intGen({#(self): FooStruct#})[#() -> Int#]; name=intGen(:) - // OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(self): Optional#})[#((FooStruct) throws -> U) -> U?#]; name=map(:) - // OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: flatMap({#(self): Optional#})[#((FooStruct) throws -> U?) -> U?#]; name=flatMap(:) - // OPTIONAL_FOOSTRUCT-NOT: init({#(some): - // OPTIONAL_FOOSTRUCT-NOT: init({#nilLiteral: // OPTIONAL_FOOSTRUCT: End completions } diff --git a/test/IDE/complete_stmt_controlling_expr.swift b/test/IDE/complete_stmt_controlling_expr.swift index 358cdfc63d881..83bd80d2e2e58 100644 --- a/test/IDE/complete_stmt_controlling_expr.swift +++ b/test/IDE/complete_stmt_controlling_expr.swift @@ -543,17 +543,7 @@ func testGuardCase(x:FooStruct?) { // FOOSTRUCT_LOCALVAL-DAG: Decl[LocalVar]/Local{{(/TypeRelation\[Convertible\])?}}: boundVal[#FooStruct#]; // FOOSTRUCT_LOCALVAL: End completions -// OPTIONAL_FOOSTRUCT: Begin completions, 9 items -// OPTIONAL_FOOSTRUCT-DAG: Keyword[nil]/None/Erase[1]/TypeRelation[Identical]: nil[#FooStruct?#]; name=nil +// OPTIONAL_FOOSTRUCT: Begin completions, 2 items // OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: none[#Optional#]; name=none // OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem/TypeRelation[Identical]: some({#FooStruct#})[#Optional#]; name=some() -// FIXME: 'FooStruct' members should not be shown. -// OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init()[#FooStruct#]; name=init() -// OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init({#Int#})[#FooStruct#]; name=init() -// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: boolGen({#(self): FooStruct#})[#() -> Bool#]; name=boolGen(:) -// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal: intGen({#(self): FooStruct#})[#() -> Int#]; name=intGen(:) -// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: map({#(self): Optional#})[#((FooStruct) throws -> U) -> U?#]; name=map(:) -// OPTIONAL_FOOSTRUCT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: flatMap({#(self): Optional#})[#((FooStruct) throws -> U?) -> U?#]; name=flatMap(:) -// OPTIONAL_FOOSTRUCT-NOT: init({#(some): -// OPTIONAL_FOOSTRUCT-NOT: init({#nilLiteral: // OPTIONAL_FOOSTRUCT: End completions diff --git a/test/IDE/complete_unresolved_members.swift b/test/IDE/complete_unresolved_members.swift index 05b5c25a86aab..0cc2bb602ed85 100644 --- a/test/IDE/complete_unresolved_members.swift +++ b/test/IDE/complete_unresolved_members.swift @@ -477,7 +477,6 @@ case let .#^GENERIC_4?check=GENERIC_1_INT^# // GENERIC_1_INT: Begin completions // GENERIC_1_INT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: contains({#content: Int#})[#Generic#]; // GENERIC_1_INT-DAG: Decl[EnumElement]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: empty[#Generic#]; -// GENERIC_1_INT-DAG: Decl[StaticMethod]/CurrNominal/Flair[ExprSpecific]/TypeRelation[Identical]: create({#Int#})[#Generic#]; // GENERIC_1_INT: End completions // GENERIC_1_U: Begin completions @@ -524,7 +523,7 @@ func testOverload(val: HasOverloaded) { // Same as OVERLOADED_METHOD_1. } -protocol HasStatic { +protocol HasStatic: Equatable { static var instance: Self { get } } func receiveHasStatic(x: T) {}