Skip to content

Commit b3843af

Browse files
committed
Add an Abstraction For Full Qualification to DiagnosticEngine
Teach the diagnostic engine about a new wrapper type `FullyQualified<T>`. The intent is to clarify which parameters will be printed with additional qualification in diagnostic text. For now, this is only useful for types, so there's a bit of SFINAE guarding against misuse of the abstraction. rdar://63199963
1 parent c2b13cd commit b3843af

File tree

2 files changed

+44
-7
lines changed

2 files changed

+44
-7
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,24 @@ namespace swift {
7474
typedef T type;
7575
};
7676
}
77-
77+
78+
/// A family of wrapper types for compiler data types that forces its
79+
/// underlying data to be formatted with full qualification.
80+
///
81+
/// So far, this is only useful for \c Type, hence the SFINAE'ing.
82+
template <typename T, typename = void> struct FullyQualified {};
83+
84+
template <typename T>
85+
struct FullyQualified<
86+
T, typename std::enable_if<std::is_convertible<T, Type>::value>::type> {
87+
Type t;
88+
89+
public:
90+
FullyQualified(T t) : t(t){};
91+
92+
Type getType() const { return t; }
93+
};
94+
7895
/// Describes the kind of diagnostic argument we're storing.
7996
///
8097
enum class DiagnosticArgumentKind {
@@ -86,6 +103,7 @@ namespace swift {
86103
ValueDecl,
87104
Type,
88105
TypeRepr,
106+
FullyQualifiedType,
89107
PatternKind,
90108
SelfAccessKind,
91109
ReferenceOwnership,
@@ -116,6 +134,7 @@ namespace swift {
116134
ValueDecl *TheValueDecl;
117135
Type TypeVal;
118136
TypeRepr *TyR;
137+
FullyQualified<Type> FullyQualifiedTypeVal;
119138
PatternKind PatternKindVal;
120139
SelfAccessKind SelfAccessKindVal;
121140
ReferenceOwnership ReferenceOwnershipVal;
@@ -172,6 +191,10 @@ namespace swift {
172191
: Kind(DiagnosticArgumentKind::TypeRepr), TyR(T) {
173192
}
174193

194+
DiagnosticArgument(FullyQualified<Type> FQT)
195+
: Kind(DiagnosticArgumentKind::FullyQualifiedType),
196+
FullyQualifiedTypeVal(FQT) {}
197+
175198
DiagnosticArgument(const TypeLoc &TL) {
176199
if (TypeRepr *tyR = TL.getTypeRepr()) {
177200
Kind = DiagnosticArgumentKind::TypeRepr;
@@ -268,7 +291,12 @@ namespace swift {
268291
assert(Kind == DiagnosticArgumentKind::TypeRepr);
269292
return TyR;
270293
}
271-
294+
295+
FullyQualified<Type> getAsFullyQualifiedType() const {
296+
assert(Kind == DiagnosticArgumentKind::FullyQualifiedType);
297+
return FullyQualifiedTypeVal;
298+
}
299+
272300
PatternKind getAsPatternKind() const {
273301
assert(Kind == DiagnosticArgumentKind::PatternKind);
274302
return PatternKindVal;

lib/AST/DiagnosticEngine.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,21 +526,30 @@ static void formatDiagnosticArgument(StringRef Modifier,
526526
Out << FormatOpts.ClosingQuotationMark;
527527
break;
528528

529+
case DiagnosticArgumentKind::FullyQualifiedType:
529530
case DiagnosticArgumentKind::Type: {
530531
assert(Modifier.empty() && "Improper modifier for Type argument");
531532

532533
// Strip extraneous parentheses; they add no value.
533-
auto type = Arg.getAsType()->getWithoutParens();
534+
Type type;
535+
bool needsQualification = false;
536+
537+
if (Arg.getKind() == DiagnosticArgumentKind::Type) {
538+
type = Arg.getAsType()->getWithoutParens();
539+
needsQualification = typeSpellingIsAmbiguous(type, Args);
540+
} else {
541+
assert(Arg.getKind() == DiagnosticArgumentKind::FullyQualifiedType);
542+
type = Arg.getAsFullyQualifiedType().getType()->getWithoutParens();
543+
needsQualification = true;
544+
}
534545

535546
// If a type has an unresolved type, print it with syntax sugar removed for
536547
// clarity. For example, print `Array<_>` instead of `[_]`.
537548
if (type->hasUnresolvedType()) {
538549
type = type->getWithoutSyntaxSugar();
539550
}
540551

541-
bool isAmbiguous = typeSpellingIsAmbiguous(type, Args);
542-
543-
if (isAmbiguous && isa<OpaqueTypeArchetypeType>(type.getPointer())) {
552+
if (needsQualification && isa<OpaqueTypeArchetypeType>(type.getPointer())) {
544553
auto opaqueTypeDecl = type->castTo<OpaqueTypeArchetypeType>()->getDecl();
545554

546555
llvm::SmallString<256> NamingDeclText;
@@ -562,7 +571,7 @@ static void formatDiagnosticArgument(StringRef Modifier,
562571

563572
} else {
564573
auto printOptions = PrintOptions();
565-
printOptions.FullyQualifiedTypes = isAmbiguous;
574+
printOptions.FullyQualifiedTypes = needsQualification;
566575
std::string typeName = type->getString(printOptions);
567576

568577
if (shouldShowAKA(type, typeName)) {

0 commit comments

Comments
 (0)