Skip to content

Commit 9beeb56

Browse files
committed
[TypeInterface] When printing type-specific interfaces, replace parameter and return types with instantiated types.
1 parent 606cc82 commit 9beeb56

File tree

7 files changed

+110
-36
lines changed

7 files changed

+110
-36
lines changed

include/swift/AST/ASTPrinter.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
namespace swift {
2222
class Decl;
23+
class DeclContext;
2324
class ModuleEntity;
2425
class TypeDecl;
2526
class Type;
@@ -103,8 +104,8 @@ class ASTPrinter {
103104

104105
/// To sanitize a malformatted utf8 string to a well-formatted one.
105106
static std::string sanitizeUtf8(StringRef Text);
106-
static bool printTypeInterface(Type Ty, std::string &Result);
107-
static bool printTypeInterface(Type Ty, llvm::raw_ostream &Out);
107+
static bool printTypeInterface(Type Ty, DeclContext *DC, std::string &Result);
108+
static bool printTypeInterface(Type Ty, DeclContext *DC, llvm::raw_ostream &Out);
108109

109110
private:
110111
virtual void anchor();

include/swift/AST/PrintOptions.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ class GenericParamList;
2121
class CanType;
2222
class ExtensionDecl;
2323
class TypeBase;
24+
class DeclContext;
25+
class Type;
2426
enum DeclAttrKind : unsigned;
27+
class PrinterArchetypeTransformer;
2528

2629
/// Options for printing AST nodes.
2730
///
@@ -191,8 +194,7 @@ struct PrintOptions {
191194
/// \brief When printing a type interface, register the type to print.
192195
TypeBase *TypeToPrint = nullptr;
193196

194-
/// \brief When printing a type interface, whether we instantiate archetypes.
195-
bool InstantiateArchetype = false;
197+
std::shared_ptr<PrinterArchetypeTransformer> pTransformer;
196198

197199
/// Retrieve the set of options for verbose printing to users.
198200
static PrintOptions printVerbose() {
@@ -234,12 +236,7 @@ struct PrintOptions {
234236
return result;
235237
}
236238

237-
static PrintOptions printTypeInterface(TypeBase *T) {
238-
PrintOptions result = printInterface();
239-
result.TypeToPrint = T;
240-
result.InstantiateArchetype = true;
241-
return result;
242-
}
239+
static PrintOptions printTypeInterface(Type T, DeclContext *DC);
243240

244241
/// Retrive the print options that are suitable to print the testable interface.
245242
static PrintOptions printTestableInterface() {

include/swift/IDE/Utils.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,12 @@ struct SemaToken {
138138
bool IsRef = true;
139139
bool IsKeywordArgument = false;
140140
Type Ty;
141+
DeclContext *DC = nullptr;
141142

142143
SemaToken() = default;
143144
SemaToken(ValueDecl *ValueD, TypeDecl *CtorTyRef, SourceLoc Loc, bool IsRef,
144145
Type Ty) : ValueD(ValueD), CtorTyRef(CtorTyRef), Loc(Loc),
145-
IsRef(IsRef), Ty(Ty) { }
146+
IsRef(IsRef), Ty(Ty), DC(ValueD->getDeclContext()) {}
146147
SemaToken(ModuleEntity Mod, SourceLoc Loc) : Mod(Mod), Loc(Loc) { }
147148

148149
bool isValid() const { return ValueD != nullptr || Mod; }
@@ -179,17 +180,18 @@ class SemaLocResolver : public SourceEntityWalker {
179180
bool IsOpenBracket) override;
180181
};
181182

183+
} // namespace ide
184+
182185
class ArchetypeTransformer {
186+
std::function<Type(Type)> TheFunc = nullptr;
183187
DeclContext *DC;
184188
Type BaseTy;
185189
llvm::DenseMap<TypeBase *, Type> Cache;
186190
TypeSubstitutionMap Map;
187-
std::function<Type(Type)> TheFunc = nullptr;
188191
public:
189192
ArchetypeTransformer(DeclContext *DC, Type Ty);
190193
llvm::function_ref<Type(Type)> getTransformerFunc();
191194
};
192-
} // namespace ide
193195
} // namespace swift
194196

195197
#endif // SWIFT_IDE_UTILS_H

lib/AST/ASTPrinter.cpp

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
#include "swift/Basic/PrimitiveParsing.h"
3333
#include "swift/Basic/STLExtras.h"
3434
#include "swift/Config.h"
35-
#include "swift/IDE/Utils.h"
3635
#include "swift/Sema/CodeCompletionTypeChecking.h"
3736
#include "swift/Strings.h"
3837
#include "clang/AST/ASTContext.h"
@@ -45,6 +44,63 @@
4544
#include <algorithm>
4645

4746
using namespace swift;
47+
namespace swift {
48+
class PrinterArchetypeTransformer {
49+
Type BaseTy;
50+
DeclContext *DC;
51+
llvm::DenseMap<TypeBase *, Type> Cache;
52+
llvm::DenseMap<StringRef, Type> IdMap;
53+
54+
public:
55+
PrinterArchetypeTransformer(Type Ty, DeclContext *DC) :
56+
BaseTy(Ty->getRValueType()), DC(DC){
57+
(void) this->DC;
58+
auto D = BaseTy->getNominalOrBoundGenericNominal();
59+
if (!D || !D->getGenericParams())
60+
return;
61+
SmallVector<Type, 3> Scrach;
62+
auto Args = BaseTy->getAllGenericArgs(Scrach);
63+
const auto ParamDecls = D->getGenericParams()->getParams();
64+
assert(ParamDecls.size() == Args.size());
65+
66+
// Map type parameter names with their instantiating arguments.
67+
for(unsigned I = 0, N = ParamDecls.size(); I < N; I ++) {
68+
IdMap[ParamDecls[I]->getName().str()] = Args[I];
69+
}
70+
}
71+
72+
Type transformByName(Type Ty) {
73+
if (Ty->getKind() != TypeKind::Archetype)
74+
return Ty;
75+
76+
// First, we try to find the map from cache.
77+
if (Cache.count(Ty.getPointer()) > 0) {
78+
return Cache[Ty.getPointer()];
79+
}
80+
auto Id = cast<ArchetypeType>(Ty.getPointer())->getName().str();
81+
auto Result = Ty;
82+
83+
// Iterate the IdMap to find the argument type of the given param name.
84+
for (auto It = IdMap.begin(); It != IdMap.end(); ++ It) {
85+
if (Id == It->getFirst()) {
86+
Result = It->getSecond();
87+
break;
88+
}
89+
}
90+
91+
// Put the result into cache.
92+
Cache[Ty.getPointer()] = Result;
93+
return Result;
94+
}
95+
};
96+
}
97+
98+
PrintOptions PrintOptions::printTypeInterface(Type T, DeclContext *DC) {
99+
PrintOptions result = printInterface();
100+
result.pTransformer = std::make_shared<PrinterArchetypeTransformer>(T, DC);
101+
result.TypeToPrint = T.getPointer();
102+
return result;
103+
}
48104

49105
std::string ASTPrinter::sanitizeUtf8(StringRef Text) {
50106
llvm::SmallString<256> Builder;
@@ -71,11 +127,12 @@ std::string ASTPrinter::sanitizeUtf8(StringRef Text) {
71127
return Builder.str();
72128
}
73129

74-
bool ASTPrinter::printTypeInterface(Type Ty, llvm::raw_ostream &OS) {
130+
bool ASTPrinter::printTypeInterface(Type Ty, DeclContext *DC,
131+
llvm::raw_ostream &OS) {
75132
if (!Ty)
76133
return false;
77134
Ty = Ty->getRValueType();
78-
PrintOptions Options = PrintOptions::printTypeInterface(Ty.getPointer());
135+
PrintOptions Options = PrintOptions::printTypeInterface(Ty.getPointer(), DC);
79136
if (auto ND = Ty->getNominalOrBoundGenericNominal()) {
80137
Options.printExtensionContentAsMembers = [&](const ExtensionDecl *ED) {
81138
return isExtensionApplied(*ND->getDeclContext(), Ty, ED);
@@ -86,9 +143,9 @@ bool ASTPrinter::printTypeInterface(Type Ty, llvm::raw_ostream &OS) {
86143
return false;
87144
}
88145

89-
bool ASTPrinter::printTypeInterface(Type Ty, std::string &Buffer) {
146+
bool ASTPrinter::printTypeInterface(Type Ty, DeclContext *DC, std::string &Buffer) {
90147
llvm::raw_string_ostream OS(Buffer);
91-
auto Result = printTypeInterface(Ty, OS);
148+
auto Result = printTypeInterface(Ty, DC, OS);
92149
OS.str();
93150
return Result;
94151
}
@@ -351,6 +408,13 @@ class PrintAST : public ASTVisitor<PrintAST> {
351408
}
352409

353410
void printTypeLoc(const TypeLoc &TL) {
411+
if (Options.pTransformer && TL.getType()) {
412+
if (auto RT = Options.pTransformer->transformByName(TL.getType())) {
413+
PrintOptions FreshOptions;
414+
RT.print(Printer, FreshOptions);
415+
return;
416+
}
417+
}
354418
// Print a TypeRepr if instructed to do so by options, or if the type
355419
// is null.
356420
if ((Options.PreferTypeRepr && TL.hasLocation()) ||
@@ -596,7 +660,7 @@ void PrintAST::printGenericParams(GenericParamList *Params) {
596660
Printer << "<";
597661
bool IsFirst = true;
598662
SmallVector<Type, 4> Scrach;
599-
if (Options.InstantiateArchetype) {
663+
if (Options.pTransformer) {
600664
auto ArgArr = Options.TypeToPrint->getAllGenericArgs(Scrach);
601665
for (auto Arg : ArgArr) {
602666
if (IsFirst) {
@@ -1749,7 +1813,12 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
17491813
Type ResultTy = decl->getResultType();
17501814
if (ResultTy && !ResultTy->isEqual(TupleType::getEmpty(Context))) {
17511815
Printer << " -> ";
1752-
ResultTy->print(Printer, Options);
1816+
if (Options.pTransformer) {
1817+
ResultTy = Options.pTransformer->transformByName(ResultTy);
1818+
PrintOptions FreshOptions;
1819+
ResultTy->print(Printer, FreshOptions);
1820+
} else
1821+
ResultTy->print(Printer, Options);
17531822
}
17541823

17551824
if (!Options.FunctionDefinitions || !decl->getBody()) {

test/IDE/print_type_interface.swift

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,6 @@ public protocol P1 { }
2727
public class T1 : P1 { }
2828
public class D<T> { public func foo() {}}
2929

30-
extension D where T : P1 {
31-
public func conditionalFunc1() {}
32-
}
33-
34-
extension D {
35-
public func unconditionalFunc1(){}
36-
}
37-
3830
class C2 {
3931
func f() {
4032
let D1 = D<T1>()
@@ -44,17 +36,29 @@ class C2 {
4436
}
4537
}
4638

47-
// RUN: %target-swift-ide-test -print-type-interface -pos=42:6 -source-filename %s | FileCheck %s -check-prefix=TYPE2
48-
// RUN: %target-swift-ide-test -print-type-interface -pos=43:6 -source-filename %s | FileCheck %s -check-prefix=TYPE3
39+
// RUN: %target-swift-ide-test -print-type-interface -pos=34:6 -source-filename %s | FileCheck %s -check-prefix=TYPE2
40+
// RUN: %target-swift-ide-test -print-type-interface -pos=35:6 -source-filename %s | FileCheck %s -check-prefix=TYPE3
4941

42+
extension D where T : P1 {
43+
public func conditionalFunc1() {}
44+
public func conditionalFunc2(t : T) -> T {return t}
45+
}
46+
47+
extension D {
48+
public func unconditionalFunc1(){}
49+
public func unconditionalFunc2(t : T) -> T {return t}
50+
}
5051

51-
// TYPE2: public class D<T1> {
52-
// TYPE2-NEXT: public func foo()
53-
// TYPE2-NEXT: public func conditionalFunc1()
54-
// TYPE2-NEXT: public func unconditionalFunc1()
52+
// TYPE2: public class D<T1> {
53+
// TYPE2-NEXT: public func foo()
54+
// TYPE2-NEXT: public func conditionalFunc1()
55+
// TYPE2-NEXT: public func conditionalFunc2(t: T1) -> T1
56+
// TYPE2-NEXT: public func unconditionalFunc1()
57+
// TYPE2-NEXT: public func unconditionalFunc2(t: T1) -> T1
5558
// TYPE2-NEXT: }
5659

5760
// TYPE3: public class D<Int> {
5861
// TYPE3-NEXT: public func foo()
5962
// TYPE3-NEXT: public func unconditionalFunc1()
63+
// TYPE3-NEXT: public func unconditionalFunc2(t: Int) -> Int
6064
// TYPE3-NEXT: }

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@ static bool passCursorInfoForDecl(const ValueDecl *VD,
391391
Info.OverrideUSRs = OverUSRs;
392392
Info.AnnotatedRelatedDeclarations = AnnotatedRelatedDecls;
393393
Info.IsSystem = IsSystem;
394-
Info.TypeInteface = ASTPrinter::printTypeInterface(Ty, TypeInterface) ?
394+
Info.TypeInteface = ASTPrinter::printTypeInterface(Ty, VD->getDeclContext(),
395+
TypeInterface) ?
395396
StringRef(TypeInterface) : StringRef();
396397
Receiver(Info);
397398
return false;

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2263,7 +2263,7 @@ static int doPrintTypeInterface(const CompilerInvocation &InitInvok,
22632263
llvm::errs() << "Cannot get type of the sema token.\n";
22642264
return 1;
22652265
}
2266-
ASTPrinter::printTypeInterface(SemaT.Ty, llvm::outs());
2266+
ASTPrinter::printTypeInterface(SemaT.Ty, SemaT.DC, llvm::outs());
22672267
return 0;
22682268
}
22692269

0 commit comments

Comments
 (0)