diff --git a/include/swift/AST/PropertyDelegates.h b/include/swift/AST/PropertyDelegates.h index 4d2ad3f645a..6fc018e8464 100644 --- a/include/swift/AST/PropertyDelegates.h +++ b/include/swift/AST/PropertyDelegates.h @@ -126,6 +126,10 @@ void simple_display( llvm::raw_ostream &out, const PropertyDelegateBackingPropertyInfo &backingInfo); +/// Given the initializer for the given property with an attached property +/// delegate, dig out the original initialization expression. +Expr *findOriginalPropertyDelegateInitialValue(VarDecl *var, Expr *init); + } // end namespace swift #endif // SWIFT_AST_PROPERTY_DELEGATES_H diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 17abeba2b28..7e4fdfe8c7e 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -42,6 +42,7 @@ #include "swift/AST/TypeCheckRequests.h" #include "swift/AST/TypeLoc.h" #include "swift/AST/SwiftNameTranslation.h" +#include "swift/Parse/Lexer.h" #include "clang/Lex/MacroInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallPtrSet.h" @@ -5522,6 +5523,31 @@ void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) { DefaultValueAndFlags.getPointer()->InitContext = initContext; } +Expr *swift::findOriginalPropertyDelegateInitialValue(VarDecl *var, + Expr *init) { + auto attr = var->getAttachedPropertyDelegate(); + assert(attr && "No attached property delegate?"); + + // Direct initialization implies no original initial value. + if (attr->getArg()) + return nullptr; + + // Look through any expressions wrapping the initializer. + init = init->getSemanticsProvidingExpr(); + auto initCall = dyn_cast(init); + if (!initCall) + return nullptr; + + auto initArg = cast(initCall->getArg())->getElement(0); + initArg = initArg->getSemanticsProvidingExpr(); + if (auto autoclosure = dyn_cast(initArg)) { + initArg = + autoclosure->getSingleExpressionBody()->getSemanticsProvidingExpr(); + } + + return initArg; +} + StringRef ParamDecl::getDefaultValueStringRepresentation( SmallVectorImpl &scratch) const { @@ -5552,6 +5578,23 @@ ParamDecl::getDefaultValueStringRepresentation( if (!existing.empty()) return existing; auto var = getStoredProperty(); + + if (auto original = var->getOriginalDelegatedProperty()) { + if (auto attr = original->getAttachedPropertyDelegate()) { + if (auto arg = attr->getArg()) { + SourceRange fullRange(attr->getTypeLoc().getSourceRange().Start, + arg->getEndLoc()); + auto charRange = Lexer::getCharSourceRangeFromSourceRange( + getASTContext().SourceMgr, fullRange); + return getASTContext().SourceMgr.extractText(charRange); + } + + auto init = findOriginalPropertyDelegateInitialValue( + original, original->getParentInitializer()); + return extractInlinableText(getASTContext().SourceMgr, init, scratch); + } + } + return extractInlinableText(getASTContext().SourceMgr, var->getParentInitializer(), scratch); diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 423cd3f49f8..678a54c1d3b 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -1455,33 +1455,6 @@ void swift::completeLazyVarImplementation(VarDecl *VD) { Storage->overwriteSetterAccess(AccessLevel::Private); } -/// Given the initializer for the given property with an attached property -/// delegate, dig out the original initialization expression. -static Expr *findOriginalPropertyDelegateInitialValue(VarDecl *var, - Expr *init) { - auto attr = var->getAttachedPropertyDelegate(); - assert(attr && "No attached property delegate?"); - - // Direct initialization implies no original initial value. - if (attr->getArg()) - return nullptr; - - // Look through any expressions wrapping the initializer. - init = init->getSemanticsProvidingExpr(); - auto initCall = dyn_cast(init); - if (!initCall) - return nullptr; - - auto initArg = cast(initCall->getArg())->getElement(0); - initArg = initArg->getSemanticsProvidingExpr(); - if (auto autoclosure = dyn_cast(initArg)) { - initArg = - autoclosure->getSingleExpressionBody()->getSemanticsProvidingExpr(); - } - - return initArg; -} - /// Synthesize a computed property `$foo` for a property with an attached /// delegate that has a `delegateValue` property. static VarDecl *synthesizePropertyDelegateStorageDelegateProperty( @@ -1604,7 +1577,7 @@ PropertyDelegateBackingPropertyInfoRequest::evaluate(Evaluator &evaluator, // Take the initializer from the original property. auto parentPBD = var->getParentPatternBinding(); unsigned patternNumber = parentPBD->getPatternEntryIndexForVarDecl(var); - if (parentPBD->getInit(patternNumber) && + if (parentPBD->isInitialized(patternNumber) && !parentPBD->isInitializerChecked(patternNumber)) { auto &tc = *static_cast(ctx.getLazyResolver()); tc.typeCheckPatternBinding(parentPBD, patternNumber); diff --git a/test/IDE/print_property_delegates.swift b/test/IDE/print_property_delegates.swift new file mode 100644 index 00000000000..5a654b1be11 --- /dev/null +++ b/test/IDE/print_property_delegates.swift @@ -0,0 +1,38 @@ +// RUN: %empty-directory(%t) + +// Directly printing the type-checked AST +// RUN: %target-swift-ide-test -print-ast-typechecked -source-filename %s | %FileCheck %s + +@propertyDelegate +struct Delegate { + var value: Value + + init(initialValue: Value) { + self.value = initialValue + } + + init(closure: () -> Value) { + self.value = closure() + } +} + +func foo() -> Int { return 17 } + +// CHECK: struct HasDelegates { +struct HasDelegates { + // CHECK: @Delegate var x: Int { + // CHECK-NEXT: get + // CHECK: var $x: Delegate + @Delegate(closure: foo) + var x: Int + + @Delegate + var y = true + + // Memberwise initializer. + // CHECK: init(x: Delegate = Delegate(closure: foo), y: Bool = true) +} + +func trigger() { + _ = HasDelegates(y: false) +}