forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDerivedConformanceError.cpp
97 lines (80 loc) · 3.03 KB
/
DerivedConformanceError.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//===--- DerivedConformanceError.cpp - Derived Error ----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements implicit derivation of the Error
// protocol.
//
//===----------------------------------------------------------------------===//
#include "TypeChecker.h"
#include "DerivedConformances.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/Types.h"
using namespace swift;
static void deriveBodyBridgedNSError_enum_nsErrorDomain(
AbstractFunctionDecl *domainDecl) {
// enum SomeEnum {
// @derived
// static var _nsErrorDomain: String {
// return "ModuleName.SomeEnum"
// }
// }
auto M = domainDecl->getParentModule();
auto &C = M->getASTContext();
auto TC = domainDecl->getInnermostTypeContext();
auto ED = TC->getSelfEnumDecl();
std::string buffer = M->getNameStr();
buffer += ".";
buffer += ED->getNameStr();
StringRef value(C.AllocateCopy(buffer));
auto string = new (C) StringLiteralExpr(value, SourceRange(), /*implicit*/ true);
auto ret = new (C) ReturnStmt(SourceLoc(), string, /*implicit*/ true);
auto body = BraceStmt::create(C, SourceLoc(),
ASTNode(ret),
SourceLoc());
domainDecl->setBody(body);
}
static ValueDecl *
deriveBridgedNSError_enum_nsErrorDomain(DerivedConformance &derived) {
// enum SomeEnum {
// @derived
// static var _nsErrorDomain: String {
// return "\(self)"
// }
// }
// Note that for @objc enums the format is assumed to be "MyModule.SomeEnum".
// If this changes, please change PrintAsObjC as well.
ASTContext &C = derived.TC.Context;
auto stringTy = C.getStringDecl()->getDeclaredType();
// Define the property.
VarDecl *propDecl;
PatternBindingDecl *pbDecl;
std::tie(propDecl, pbDecl) = derived.declareDerivedProperty(
C.Id_nsErrorDomain, stringTy, stringTy, /*isStatic=*/true,
/*isFinal=*/true);
// Define the getter.
auto getterDecl = derived.addGetterToReadOnlyDerivedProperty(
derived.TC, propDecl, stringTy);
getterDecl->setBodySynthesizer(&deriveBodyBridgedNSError_enum_nsErrorDomain);
derived.addMembersToConformanceContext({getterDecl, propDecl, pbDecl});
return propDecl;
}
ValueDecl *DerivedConformance::deriveBridgedNSError(ValueDecl *requirement) {
if (!isa<EnumDecl>(Nominal))
return nullptr;
if (requirement->getBaseName() == TC.Context.Id_nsErrorDomain)
return deriveBridgedNSError_enum_nsErrorDomain(*this);
TC.diagnose(requirement->getLoc(), diag::broken_errortype_requirement);
return nullptr;
}