Skip to content

Commit

Permalink
stdlib: Use unqualified names in 'print'.
Browse files Browse the repository at this point in the history
Leave the qualification off of enum cases and type names when 'print'-ing them, but keep them on 'debugPrint'. (At least, at the outermost level; since ad-hoc printing of structs and tuples uses debugPrint, we'll still get qualification at depth, which kind of sucks but needs more invasive state management in print to make possible.) Implements rdar://problem/21788604.

Swift SVN r30166
  • Loading branch information
jckarter committed Jul 13, 2015
1 parent adab465 commit db0fea5
Show file tree
Hide file tree
Showing 20 changed files with 247 additions and 75 deletions.
1 change: 1 addition & 0 deletions include/swift/Basic/Demangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct DemangleOptions {
bool SynthesizeSugarOnTypes = false;
bool DisplayTypeOfIVarFieldOffset = true;
bool DisplayDebuggerGeneratedModule = true;
bool QualifyEntities = true;
bool Simplified = false;

DemangleOptions() {}
Expand Down
3 changes: 2 additions & 1 deletion include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -2618,7 +2618,8 @@ swift_demangleSimpleClass(const char *mangledName,


/// Return the type name for a given type metadata.
std::string nameForMetadata(const Metadata *type);
std::string nameForMetadata(const Metadata *type,
bool qualified = true);

} // end namespace swift

Expand Down
15 changes: 9 additions & 6 deletions lib/Basic/Demangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2739,7 +2739,8 @@ void NodePrinter::printSimplifiedEntityType(NodePointer context,
void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType) {
// Common code for handling entities.
auto printEntity = [&](bool hasName, bool hasType, StringRef extraName) {
printContext(pointer->getChild(0));
if (Options.QualifyEntities)
printContext(pointer->getChild(0));

bool printType = (hasType && !suppressType);
bool useParens = (printType && asContext);
Expand Down Expand Up @@ -2777,10 +2778,12 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
case Node::Kind::Extension:
assert((pointer->getNumChildren() == 2 || pointer->getNumChildren() == 3)
&& "Extension expects 2 or 3 children.");
Printer << "ext.";
// Print the module where extension is defined.
print(pointer->getChild(0), true);
Printer << ".";
if (Options.QualifyEntities) {
Printer << "ext.";
// Print the module where extension is defined.
print(pointer->getChild(0), true);
Printer << ".";
}
print(pointer->getChild(1), asContext);
if (pointer->getNumChildren() == 3)
print(pointer->getChild(2), true);
Expand Down Expand Up @@ -2937,7 +2940,7 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
print(pointer->getChild(0));
return;
case Node::Kind::NonObjCAttribute:
Printer << "@!objc ";
Printer << "@nonobjc ";
return;
case Node::Kind::ObjCAttribute:
Printer << "@objc ";
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/ErrorType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ public func _bridgeErrorTypeToNSError(e: ErrorType) -> AnyObject
/// throws an error.
@asmname("swift_unexpectedError")
public func _unexpectedError(error: ErrorType) {
preconditionFailure("'try!' expression unexpectedly raised an error: \(error)")
preconditionFailure("'try!' expression unexpectedly raised an error: \(String(reflecting: error))")
}

/// Invoked by the compiler when code at top level throws an uncaught error.
@asmname("swift_errorInMain")
public func _errorInMain(error: ErrorType) {
fatalError("Error raised at top level: \(error)")
fatalError("Error raised at top level: \(String(reflecting: error))")
}
11 changes: 7 additions & 4 deletions stdlib/public/core/Misc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,15 @@ func _withUninitializedString<R>(
public func _stdlib_getDemangledTypeNameImpl<T>(value: T, _ result: UnsafeMutablePointer<String>)

@asmname("swift_stdlib_getDemangledMetatypeName")
public func _stdlib_getDemangledMetatypeNameImpl(type: Any.Type, _ result: UnsafeMutablePointer<String>)
public func _stdlib_getDemangledMetatypeNameImpl(type: Any.Type, qualified: Bool, _ result: UnsafeMutablePointer<String>)

/// Returns the demangled name of a metatype.
public func _typeName(type: Any.Type) -> String {
@asmname("swift_stdlib_getDemangledUnqualifiedMetatypeName")
public func _stdlib_getDemangledUnqualifiedMetatypeNameImpl(type: Any.Type, _ result: UnsafeMutablePointer<String>)

/// Returns the demangled qualified name of a metatype.
public func _typeName(type: Any.Type, qualified: Bool = true) -> String {
let stringPtr = UnsafeMutablePointer<String>.alloc(1)
_stdlib_getDemangledMetatypeNameImpl(type, stringPtr)
_stdlib_getDemangledMetatypeNameImpl(type, qualified: qualified, stringPtr)
let result = stringPtr.move()
stringPtr.dealloc(1)
return result
Expand Down
49 changes: 34 additions & 15 deletions stdlib/public/core/OutputStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,20 @@ public typealias Printable = CustomStringConvertible
// Default (ad-hoc) printing
//===----------------------------------------------------------------------===//

/// Do our best to print a value that can not be printed directly.
/// Do our best to print a value that cannot be printed directly.
internal func _adHocPrint<T, TargetStream : OutputStreamType>(
value: T, inout _ target: TargetStream
value: T, inout _ target: TargetStream, isDebugPrint: Bool
) {
func printTypeName(type: Any.Type) {
// Print type names without qualification, unless we're debugPrint'ing.
target.write(_typeName(type, qualified: isDebugPrint))
}

let mirror = _reflect(value)
switch mirror {
// Checking the mirror kind is not a good way to implement this, but we don't
// have a more expressive reflection API now.
if mirror is _TupleMirror {
case is _TupleMirror:
target.write("(")
var first = true
for i in 0..<mirror.count {
Expand All @@ -108,10 +114,9 @@ internal func _adHocPrint<T, TargetStream : OutputStreamType>(
debugPrint(elt, &target, appendNewline: false)
}
target.write(")")
return
}
if mirror is _StructMirror {
print(mirror.summary, &target, appendNewline: false)

case is _StructMirror:
printTypeName(mirror.valueType)
target.write("(")
var first = true
for i in 0..<mirror.count {
Expand All @@ -126,10 +131,20 @@ internal func _adHocPrint<T, TargetStream : OutputStreamType>(
debugPrint(elementMirror.value, &target, appendNewline: false)
}
target.write(")")
return
}
if mirror is _EnumMirror {
print(mirror.summary, &target, appendNewline: false)

case let enumMirror as _EnumMirror:
if let caseName = String.fromCString(enumMirror.caseName) {
// Write the qualified type name in debugPrint.
if isDebugPrint {
target.write(_typeName(mirror.valueType))
target.write(".")
}
target.write(caseName)
} else {
// If the case name is garbage, just print the type name.
printTypeName(mirror.valueType)
}

if mirror.count == 0 {
return
}
Expand All @@ -141,9 +156,13 @@ internal func _adHocPrint<T, TargetStream : OutputStreamType>(
target.write("(")
debugPrint(payload.value, &target, appendNewline: false)
target.write(")")
return

case is _MetatypeMirror:
printTypeName(mirror.value as! Any.Type)

default:
print(mirror.summary, &target, appendNewline: false)
}
print(mirror.summary, &target, appendNewline: false)
}

@inline(never)
Expand All @@ -165,7 +184,7 @@ internal func _print_unlocked<T, TargetStream : OutputStreamType>(
return
}

_adHocPrint(value, &target)
_adHocPrint(value, &target, isDebugPrint: false)
}

/// Returns the result of `print`'ing `x` into a `String`.
Expand Down Expand Up @@ -210,7 +229,7 @@ public func _debugPrint_unlocked<T, TargetStream : OutputStreamType>(
return
}

_adHocPrint(value, &target)
_adHocPrint(value, &target, isDebugPrint: true)
}

//===----------------------------------------------------------------------===//
Expand Down
38 changes: 26 additions & 12 deletions stdlib/public/runtime/Casting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,16 @@ namespace {

static void _buildNameForMetadata(const Metadata *type,
TypeSyntaxLevel level,
bool qualified,
std::string &result);

static void _buildNominalTypeName(const NominalTypeDescriptor *ntd,
const Metadata *type,
bool qualified,
std::string &result) {
auto options = Demangle::DemangleOptions();
options.DisplayDebuggerGeneratedModule = false;
options.QualifyEntities = qualified;

// Demangle the basic type name.
result += Demangle::demangleTypeAsString(ntd->Name,
Expand All @@ -109,7 +112,8 @@ static void _buildNominalTypeName(const NominalTypeDescriptor *ntd,
i < e; ++i, ++genericParam) {
if (i > 0)
result += ", ";
_buildNameForMetadata(*genericParam, TypeSyntaxLevel::Type, result);
_buildNameForMetadata(*genericParam, TypeSyntaxLevel::Type, qualified,
result);
}

result += ">";
Expand All @@ -125,8 +129,10 @@ static const char *_getProtocolName(const ProtocolDescriptor *protocol) {
}

static void _buildExistentialTypeName(const ProtocolDescriptorList *protocols,
bool qualified,
std::string &result) {
auto options = Demangle::DemangleOptions();
options.QualifyEntities = qualified;
options.DisplayDebuggerGeneratedModule = false;

// If there's only one protocol, the existential type name is the protocol
Expand Down Expand Up @@ -154,6 +160,7 @@ static void _buildExistentialTypeName(const ProtocolDescriptorList *protocols,
}

static void _buildFunctionTypeName(const FunctionTypeMetadata *func,
bool qualified,
std::string &result) {

if (func->getNumArguments() == 1) {
Expand All @@ -165,13 +172,15 @@ static void _buildFunctionTypeName(const FunctionTypeMetadata *func,
if (auto tupleMetadata = dyn_cast<TupleTypeMetadata>(firstArgument)) {
_buildNameForMetadata(tupleMetadata,
TypeSyntaxLevel::TypeSimple,
qualified,
result);
} else {
if (isInout)
result += "inout ";

_buildNameForMetadata(firstArgument,
TypeSyntaxLevel::TypeSimple,
qualified,
result);
}
} else {
Expand All @@ -181,7 +190,8 @@ static void _buildFunctionTypeName(const FunctionTypeMetadata *func,
bool isInout = func->getArguments()[i].getFlag();
if (isInout)
result += "inout ";
_buildNameForMetadata(arg, TypeSyntaxLevel::TypeSimple, result);
_buildNameForMetadata(arg, TypeSyntaxLevel::TypeSimple,
qualified, result);
if (i < func->getNumArguments() - 1) {
result += ", ";
}
Expand All @@ -196,13 +206,15 @@ static void _buildFunctionTypeName(const FunctionTypeMetadata *func,
result += " -> ";
_buildNameForMetadata(func->ResultType,
TypeSyntaxLevel::Type,
qualified,
result);
}

// Build a user-comprehensible name for a type.
static void _buildNameForMetadata(const Metadata *type,
TypeSyntaxLevel level,
std::string &result) {
TypeSyntaxLevel level,
bool qualified,
std::string &result) {
auto options = Demangle::DemangleOptions();
options.DisplayDebuggerGeneratedModule = false;

Expand All @@ -221,14 +233,14 @@ static void _buildNameForMetadata(const Metadata *type,
}
#endif
return _buildNominalTypeName(classType->getDescription(),
classType,
classType, qualified,
result);
}
case MetadataKind::Enum:
case MetadataKind::Struct: {
auto structType = static_cast<const StructMetadata *>(type);
return _buildNominalTypeName(structType->Description,
type, result);
type, qualified, result);
}
case MetadataKind::ObjCClassWrapper: {
#if SWIFT_OBJC_INTEROP
Expand All @@ -248,12 +260,13 @@ static void _buildNameForMetadata(const Metadata *type,
}
case MetadataKind::Existential: {
auto exis = static_cast<const ExistentialTypeMetadata *>(type);
_buildExistentialTypeName(&exis->Protocols, result);
_buildExistentialTypeName(&exis->Protocols, qualified, result);
return;
}
case MetadataKind::ExistentialMetatype: {
auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);
_buildNameForMetadata(metatype->InstanceType, TypeSyntaxLevel::TypeSimple,
qualified,
result);
result += ".Type";
return;
Expand All @@ -278,7 +291,7 @@ static void _buildNameForMetadata(const Metadata *type,
break;
}

_buildFunctionTypeName(func, result);
_buildFunctionTypeName(func, qualified, result);

if (level >= TypeSyntaxLevel::TypeSimple)
result += ")";
Expand All @@ -287,7 +300,7 @@ static void _buildNameForMetadata(const Metadata *type,
case MetadataKind::Metatype: {
auto metatype = static_cast<const MetatypeMetadata *>(type);
_buildNameForMetadata(metatype->InstanceType, TypeSyntaxLevel::TypeSimple,
result);
qualified, result);
if (metatype->InstanceType->isAnyExistentialType())
result += ".Protocol";
else
Expand All @@ -301,7 +314,7 @@ static void _buildNameForMetadata(const Metadata *type,
for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) {
if (i > 0)
result += ", ";
_buildNameForMetadata(elts[i].Type, TypeSyntaxLevel::Type,
_buildNameForMetadata(elts[i].Type, TypeSyntaxLevel::Type, qualified,
result);
}
result += ")";
Expand All @@ -321,9 +334,10 @@ static void _buildNameForMetadata(const Metadata *type,
}

// Return a user-comprehensible name for the given type.
std::string swift::nameForMetadata(const Metadata *type) {
std::string swift::nameForMetadata(const Metadata *type,
bool qualified) {
std::string result;
_buildNameForMetadata(type, TypeSyntaxLevel::Type, result);
_buildNameForMetadata(type, TypeSyntaxLevel::Type, qualified, result);
return result;
}

Expand Down
9 changes: 6 additions & 3 deletions stdlib/public/runtime/Reflection.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1293,8 +1293,9 @@ static Mirror ObjC_getMirrorForSuperclass(Class sup,
}

extern "C" void
swift_stdlib_getDemangledMetatypeName(const Metadata *type, String *outString) {
std::string name = nameForMetadata(type);
swift_stdlib_getDemangledMetatypeName(const Metadata *type,
bool qualified, String *outString) {
std::string name = nameForMetadata(type, qualified);
swift_stringFromUTF8InRawMemory(outString, name.data(), name.length());
}

Expand Down Expand Up @@ -1336,7 +1337,9 @@ static void swift_stdlib_getDemangledTypeNameImpl(OpaqueValue *value,
case MetadataKind::Metatype:
case MetadataKind::ObjCClassWrapper:
case MetadataKind::ForeignClass:
return swift_stdlib_getDemangledMetatypeName(dynamicType, result);
return swift_stdlib_getDemangledMetatypeName(dynamicType,
/*qualified*/ true,
result);

// Values should never use these metadata kinds.
case MetadataKind::HeapLocalVariable:
Expand Down
2 changes: 1 addition & 1 deletion test/1_stdlib/ArrayBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func testBridgedVerbatim() {

// Verify that NSArray class methods are inherited by a Swift bridging class.
// CHECK-NEXT: Swift.{{.*}}Array
print(basesConvertedToNSArray.dynamicType)
debugPrint(basesConvertedToNSArray.dynamicType)
// CHECK-NEXT: true
print(basesConvertedToNSArray.dynamicType.supportsSecureCoding())

Expand Down
Loading

0 comments on commit db0fea5

Please sign in to comment.