//===--- DerivedConformanceError.cpp - Derived Error ----------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 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/Types.h" using namespace swift; using namespace DerivedConformance; 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->getAsEnumOrEnumExtensionContext(); 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(TypeChecker &tc, Decl *parentDecl, EnumDecl *enumDecl) { // 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 = tc.Context; auto stringTy = C.getStringDecl()->getDeclaredType(); // Define the getter. auto getterDecl = declareDerivedPropertyGetter(tc, parentDecl, enumDecl, stringTy, stringTy, /*isStatic=*/true, /*isFinal=*/true); getterDecl->setBodySynthesizer(&deriveBodyBridgedNSError_enum_nsErrorDomain); // Define the property. VarDecl *propDecl; PatternBindingDecl *pbDecl; std::tie(propDecl, pbDecl) = declareDerivedReadOnlyProperty(tc, parentDecl, enumDecl, C.Id_nsErrorDomain, stringTy, stringTy, getterDecl, /*isStatic=*/true, /*isFinal=*/true); auto dc = cast(parentDecl); dc->addMember(getterDecl); dc->addMember(propDecl); dc->addMember(pbDecl); return propDecl; } ValueDecl *DerivedConformance::deriveBridgedNSError(TypeChecker &tc, Decl *parentDecl, NominalTypeDecl *type, ValueDecl *requirement) { if (!isa(type)) return nullptr; auto enumType = cast(type); if (requirement->getName() == tc.Context.Id_nsErrorDomain) return deriveBridgedNSError_enum_nsErrorDomain(tc, parentDecl, enumType); tc.diagnose(requirement->getLoc(), diag::broken_errortype_requirement); return nullptr; }