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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
//===--- ImportEnumInfo.h - Importable Clang enums information --*- C++ -*-===//
//
// 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 provides ImportEnumInfo, which describes a Clang enum ready to be
// imported
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_CLANG_IMPORT_ENUM_H
#define SWIFT_CLANG_IMPORT_ENUM_H
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
class EnumDecl;
class Preprocessor;
class MacroInfo;
}
namespace swift {
namespace importer {
/// Describes how a particular C enumeration type will be imported
/// into Swift. All of the possibilities have the same storage
/// representation, but can be used in different ways.
enum class EnumKind {
/// The enumeration type should map to a frozen enum, which means that
/// all of the cases are independent and there are no private cases.
FrozenEnum,
/// The enumeration type should map to a non-frozen enum, which means that
/// all of the cases are independent, but there may be values not represented
/// in the listed cases.
NonFrozenEnum,
/// The enumeration type should map to an option set, which means that
/// the constants represent combinations of independent flags.
Options,
/// The enumeration type should map to a distinct type, but we don't
/// know the intended semantics of the enum constants, so conservatively
/// map them to independent constants.
Unknown,
/// The enumeration constants should simply map to the appropriate
/// integer values.
Constants,
};
class EnumInfo {
/// The kind
EnumKind kind = EnumKind::Unknown;
/// The enum's common constant name prefix, which will be stripped from
/// constants
StringRef constantNamePrefix = StringRef();
/// The name of the NS error domain for Cocoa error enums.
StringRef nsErrorDomain = StringRef();
public:
EnumInfo() = default;
EnumInfo(const clang::EnumDecl *decl, clang::Preprocessor &pp) {
classifyEnum(decl, pp);
determineConstantNamePrefix(decl);
}
EnumKind getKind() const { return kind; }
StringRef getConstantNamePrefix() const { return constantNamePrefix; }
/// Whether this maps to an enum who also provides an error domain
bool isErrorEnum() const {
switch (getKind()) {
case EnumKind::FrozenEnum:
case EnumKind::NonFrozenEnum:
return !nsErrorDomain.empty();
case EnumKind::Options:
case EnumKind::Unknown:
case EnumKind::Constants:
return false;
}
llvm_unreachable("unhandled kind");
}
/// For this error enum, extract the name of the error domain constant
StringRef getErrorDomain() const {
assert(isErrorEnum() && "not error enum");
return nsErrorDomain;
}
private:
void determineConstantNamePrefix(const clang::EnumDecl *);
void classifyEnum(const clang::EnumDecl *, clang::Preprocessor &);
};
/// Provide a cache of enum infos, so that we don't have to re-calculate their
/// information.
class EnumInfoCache {
clang::Preprocessor &clangPP;
llvm::DenseMap<const clang::EnumDecl *, EnumInfo> enumInfos;
// Never copy
EnumInfoCache(const EnumInfoCache &) = delete;
EnumInfoCache &operator = (const EnumInfoCache &) = delete;
public:
explicit EnumInfoCache(clang::Preprocessor &cpp) : clangPP(cpp) {}
EnumInfo getEnumInfo(const clang::EnumDecl *decl);
EnumKind getEnumKind(const clang::EnumDecl *decl) {
return getEnumInfo(decl).getKind();
}
/// The prefix to be stripped from the names of the enum constants within the
/// given enum.
StringRef getEnumConstantNamePrefix(const clang::EnumDecl *decl) {
return getEnumInfo(decl).getConstantNamePrefix();
}
};
// Utility functions of primary interest to enum constant naming
/// Returns the common prefix of two strings at camel-case word granularity.
///
/// For example, given "NSFooBar" and "NSFooBas", returns "NSFoo"
/// (not "NSFooBa"). The returned StringRef is a slice of the "a" argument.
///
/// If either string has a non-identifier character immediately after the
/// prefix, \p followedByNonIdentifier will be set to \c true. If both strings
/// have identifier characters after the prefix, \p followedByNonIdentifier will
/// be set to \c false. Otherwise, \p followedByNonIdentifier will not be
/// changed from its initial value.
///
/// This is used to derive the common prefix of enum constants so we can elide
/// it from the Swift interface.
StringRef getCommonWordPrefix(StringRef a, StringRef b,
bool &followedByNonIdentifier);
/// Returns the common word-prefix of two strings, allowing the second string
/// to be a common English plural form of the first.
///
/// For example, given "NSProperty" and "NSProperties", the full "NSProperty"
/// is returned. Given "NSMagicArmor" and "NSMagicArmory", only
/// "NSMagic" is returned.
///
/// The "-s", "-es", and "-ies" patterns cover every plural NS_OPTIONS name
/// in Cocoa and Cocoa Touch.
///
/// \see getCommonWordPrefix
StringRef getCommonPluralPrefix(StringRef singular, StringRef plural);
/// Returns the underlying integer type of an enum. If clang treats the type as
/// an elaborated type, an unwrapped type is returned.
const clang::Type *getUnderlyingType(const clang::EnumDecl *decl);
}
}
#endif // SWIFT_CLANG_IMPORT_ENUM_H
|