[Property delegates] Fix printing of memberwise initializer default arguments

This commit is contained in:
Doug Gregor
2019-04-15 23:27:24 -07:00
parent 261b879b54
commit 7df695536e
4 changed files with 86 additions and 28 deletions

View File

@@ -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

View File

@@ -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<CallExpr>(init);
if (!initCall)
return nullptr;
auto initArg = cast<TupleExpr>(initCall->getArg())->getElement(0);
initArg = initArg->getSemanticsProvidingExpr();
if (auto autoclosure = dyn_cast<AutoClosureExpr>(initArg)) {
initArg =
autoclosure->getSingleExpressionBody()->getSemanticsProvidingExpr();
}
return initArg;
}
StringRef
ParamDecl::getDefaultValueStringRepresentation(
SmallVectorImpl<char> &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);

View File

@@ -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<CallExpr>(init);
if (!initCall)
return nullptr;
auto initArg = cast<TupleExpr>(initCall->getArg())->getElement(0);
initArg = initArg->getSemanticsProvidingExpr();
if (auto autoclosure = dyn_cast<AutoClosureExpr>(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<TypeChecker *>(ctx.getLazyResolver());
tc.typeCheckPatternBinding(parentPBD, patternNumber);

View File

@@ -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<Value> {
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<Int>
@Delegate(closure: foo)
var x: Int
@Delegate
var y = true
// Memberwise initializer.
// CHECK: init(x: Delegate<Int> = Delegate(closure: foo), y: Bool = true)
}
func trigger() {
_ = HasDelegates(y: false)
}