Skip to content

Teach swift-ide-test to print type interface via a given mangled type name. #3501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 14, 2016
7 changes: 5 additions & 2 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ struct PrintOptions {
/// Whether to use an empty line to separate two members in a single decl.
bool EmptyLineBetweenMembers = false;

/// Whether to print the extensions from conforming protocols.
bool PrintExtensionFromConformingProtocols = false;

enum class ArgAndParamPrintingMode {
ArgumentOnly,
MatchSource,
Expand Down Expand Up @@ -352,9 +355,9 @@ struct PrintOptions {
return result;
}

static PrintOptions printTypeInterface(Type T, const DeclContext *DC);
static PrintOptions printTypeInterface(Type T, DeclContext *DC);

void setArchetypeTransform(Type T, const DeclContext *DC);
void setArchetypeTransform(Type T, DeclContext *DC);

void setArchetypeTransformForQuickHelp(Type T, DeclContext *DC);

Expand Down
24 changes: 15 additions & 9 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,16 +654,18 @@ hasMergeGroup(MergeGroupKind Kind) {
return false;
}
}
PrintOptions PrintOptions::printTypeInterface(Type T, const DeclContext *DC) {

PrintOptions PrintOptions::printTypeInterface(Type T, DeclContext *DC) {
PrintOptions result = printInterface();
result.PrintExtensionFromConformingProtocols = true;
result.TransformContext = std::make_shared<ArchetypeTransformContext>(
new PrinterArchetypeNameTransformer(T, DC), T);
new ArchetypeSelfTransformer(T, *DC), T);
return result;
}

void PrintOptions::setArchetypeTransform(Type T, const DeclContext *DC) {
void PrintOptions::setArchetypeTransform(Type T, DeclContext *DC) {
TransformContext = std::make_shared<ArchetypeTransformContext>(
new PrinterArchetypeNameTransformer(T, DC));
new ArchetypeSelfTransformer(T, *DC));
}

void PrintOptions::setArchetypeTransformForQuickHelp(Type T, DeclContext *DC) {
Expand Down Expand Up @@ -802,12 +804,8 @@ bool ASTPrinter::printTypeInterface(Type Ty, DeclContext *DC,
Ty = Ty->getRValueType();
PrintOptions Options = PrintOptions::printTypeInterface(Ty.getPointer(), DC);
if (auto ND = Ty->getNominalOrBoundGenericNominal()) {
llvm::SmallPtrSet<const ExtensionDecl*, 4> AllExts;
for (auto Ext : ND->getExtensions()) {
AllExts.insert(Ext);
}
Options.printExtensionContentAsMembers = [&](const ExtensionDecl *ED) {
return AllExts.count(ED) == 1 && isExtensionApplied(*ND->getDeclContext(), Ty, ED);
return isExtensionApplied(*ND->getDeclContext(), Ty, ED);
};
ND->print(OS, Options);
return true;
Expand Down Expand Up @@ -1904,6 +1902,14 @@ void PrintAST::printMembersOfDecl(Decl *D, bool needComma,
if (Options.printExtensionContentAsMembers(Ext))
AddDeclFunc(Ext->getMembers());
}
if (Options.PrintExtensionFromConformingProtocols) {
for (auto Conf : NTD->getAllConformances()) {
for (auto Ext : Conf->getProtocol()->getExtensions()) {
if (Options.printExtensionContentAsMembers(Ext))
AddDeclFunc(Ext->getMembers());
}
}
}
}
printMembers(Members, needComma, openBracket, closeBracket);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/USRGeneration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static inline StringRef getUSRSpacePrefix() {
bool ide::printTypeUSR(Type Ty, raw_ostream &OS) {
using namespace Mangle;
Mangler Mangler(true);
Mangler.mangleType(Ty->getRValueType(), 0);
Mangler.mangleTypeForDebugger(Ty->getRValueType(), nullptr);
Mangler.finalize(OS);
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/IDE/SwiftSourceDocInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
using namespace swift;
using namespace swift::ide;

Optional<std::pair<unsigned, unsigned>> swift::ide::parseLineCol(StringRef LineCol) {
Optional<std::pair<unsigned, unsigned>>
swift::ide::parseLineCol(StringRef LineCol) {
unsigned Line, Col;
size_t ColonIdx = LineCol.find(':');
if (ColonIdx == StringRef::npos) {
Expand Down
29 changes: 25 additions & 4 deletions test/IDE/print_type_interface.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@


public struct A {
public func fa() {}
}
Expand All @@ -10,13 +12,14 @@ extension A {
class C1 {
func f1() {
var abcd : A
abcd.fa()
abcd.fa()
var intarr : [Int]
intarr.append(1)
}
}

// RUN: %target-swift-ide-test -print-type-interface -pos=13:6 -source-filename %s | FileCheck %s -check-prefix=TYPE1
// RUN: %target-swift-ide-test -print-type-interface -pos=15:6 -source-filename %s | FileCheck %s -check-prefix=TYPE1
// RUN: %target-swift-ide-test -print-type-interface -usr=_TtV20print_type_interface1A -module-name print_type_interface -source-filename %s | FileCheck %s -check-prefix=TYPE1
// TYPE1: public struct A {
// TYPE1: public func fa()
// TYPE1: public func fea1()
Expand All @@ -36,8 +39,10 @@ class C2 {
}
}

// RUN: %target-swift-ide-test -print-type-interface -pos=34:6 -source-filename %s | FileCheck %s -check-prefix=TYPE2
// RUN: %target-swift-ide-test -print-type-interface -pos=35:6 -source-filename %s | FileCheck %s -check-prefix=TYPE3
// RUN: %target-swift-ide-test -print-type-interface -pos=37:6 -source-filename %s | FileCheck %s -check-prefix=TYPE2
// RUN: %target-swift-ide-test -print-type-interface -usr=_TtGC20print_type_interface1DCS_2T1_ -module-name print_type_interface -source-filename %s | FileCheck %s -check-prefix=TYPE2
// RUN: %target-swift-ide-test -print-type-interface -pos=38:6 -source-filename %s | FileCheck %s -check-prefix=TYPE3
// RUN: %target-swift-ide-test -print-type-interface -usr=_TtGC20print_type_interface1DSi_ -module-name print_type_interface -source-filename %s | FileCheck %s -check-prefix=TYPE3

extension D where T : P1 {
public func conditionalFunc1() {}
Expand All @@ -62,3 +67,19 @@ extension D {
// TYPE3: public func unconditionalFunc1()
// TYPE3: public func unconditionalFunc2(t: Int) -> Int
// TYPE3: }

// RUN: %target-swift-ide-test -print-type-interface -usr=_TtGSaSi_ -module-name print_type_interface -source-filename %s | FileCheck %s -check-prefix=TYPE4
// TYPE4-DAG: public typealias Index = Int
// TYPE4-DAG: public func min() -> Int?
// TYPE4-DAG: public mutating func insert<Int>(contentsOf newElements: C, at i: Int)
// TYPE4-DAG: public mutating func removeFirst(_ n: Int)
// TYPE4-DAG: public mutating func replaceSubrange<Int>(_ subrange: CountableRange<Int>, with newElements: C)
// TYPE4-NOT: public func joined

// RUN: %target-swift-ide-test -print-type-interface -usr=_TtGSaSS_ -module-name print_type_interface -source-filename %s | FileCheck %s -check-prefix=TYPE5
// TYPE5-DAG: public func prefix(_ maxLength: Int) -> ArraySlice<String>
// TYPE5-DAG: public func suffix(_ maxLength: Int) -> ArraySlice<String>
// TYPE5-DAG: public func split(separator: String, maxSplits: Int = default, omittingEmptySubsequences: Bool = default) -> [ArraySlice<String>]
// TYPE5-DAG: public func formIndex(_ i: inout Int, offsetBy n: Int)
// TYPE5-DAG: public func distance(from start: Int, to end: Int) -> Int
// TYPE5-DAG: public func joined(separator: String) -> String
2 changes: 1 addition & 1 deletion test/SourceKit/CursorInfo/cursor_info.swift
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func rethrowingFunction1(_: (Int) throws -> Void) rethrows -> Void {}
// CHECK8-NEXT: s:FC11cursor_info2CCcFT1xSi_S0_
// CHECK8-NEXT: (CC.Type) -> (x: Int) -> CC
// CHECK8-NEXT: _TtFT1xSi_C11cursor_info2CC
// CHECK8-NEXT: <Container>C11cursor_info2CC</Container>
// CHECK8-NEXT: <Container>_TtC11cursor_info2CC</Container>
// CHECK8-NEXT: <Declaration>convenience init(x: <Type usr="s:Si">Int</Type>)</Declaration>
// CHECK8-NEXT: <decl.function.constructor><syntaxtype.keyword>convenience</syntaxtype.keyword> <syntaxtype.keyword>init</syntaxtype.keyword>(<decl.var.parameter><decl.var.parameter.argument_label>x</decl.var.parameter.argument_label>: <decl.var.parameter.type><ref.struct usr="s:Si">Int</ref.struct></decl.var.parameter.type></decl.var.parameter>)</decl.function.constructor>

Expand Down
14 changes: 7 additions & 7 deletions test/SourceKit/CursorInfo/cursor_info_container.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,27 @@ func SArrayGen() -> [S] { return [] }
// RUN: %sourcekitd-test -req=cursor -pos=24:12 %s -- %s | FileCheck -check-prefix=CHECK1 %s
// RUN: %sourcekitd-test -req=cursor -pos=25:12 %s -- %s | FileCheck -check-prefix=CHECK1 %s
// RUN: %sourcekitd-test -req=cursor -pos=34:19 %s -- %s | FileCheck -check-prefix=CHECK1 %s
// CHECK1: <Container>V21cursor_info_container1S</Container>
// CHECK1: <Container>_TtV21cursor_info_container1S</Container>

// RUN: %sourcekitd-test -req=cursor -pos=26:12 %s -- %s | FileCheck -check-prefix=CHECK2 %s
// CHECK2: <Container>MV21cursor_info_container1S</Container>
// CHECK2: <Container>_TtMV21cursor_info_container1S</Container>

// RUN: %sourcekitd-test -req=cursor -pos=27:12 %s -- %s | FileCheck -check-prefix=CHECK3 %s
// RUN: %sourcekitd-test -req=cursor -pos=28:12 %s -- %s | FileCheck -check-prefix=CHECK3 %s
// RUN: %sourcekitd-test -req=cursor -pos=35:19 %s -- %s | FileCheck -check-prefix=CHECK3 %s
// CHECK3: <Container>C21cursor_info_container1C</Container>
// CHECK3: <Container>_TtC21cursor_info_container1C</Container>

// RUN: %sourcekitd-test -req=cursor -pos=29:12 %s -- %s | FileCheck -check-prefix=CHECK4 %s
// CHECK4: <Container>MC21cursor_info_container1C</Container>
// CHECK4: <Container>_TtMC21cursor_info_container1C</Container>

// RUN: %sourcekitd-test -req=cursor -pos=30:12 %s -- %s | FileCheck -check-prefix=CHECK5 %s
// RUN: %sourcekitd-test -req=cursor -pos=31:12 %s -- %s | FileCheck -check-prefix=CHECK5 %s
// RUN: %sourcekitd-test -req=cursor -pos=36:19 %s -- %s | FileCheck -check-prefix=CHECK5 %s
// CHECK5: <Container>O21cursor_info_container1E</Container>
// CHECK5: <Container>_TtO21cursor_info_container1E</Container>

// RUN: %sourcekitd-test -req=cursor -pos=32:12 %s -- %s | FileCheck -check-prefix=CHECK6 %s
// RUN: %sourcekitd-test -req=cursor -pos=33:12 %s -- %s | FileCheck -check-prefix=CHECK6 %s
// CHECK6: <Container>MO21cursor_info_container1E</Container>
// CHECK6: <Container>_TtMO21cursor_info_container1E</Container>

// RUN: %sourcekitd-test -req=cursor -pos=37:22 %s -- %s | FileCheck -check-prefix=CHECK7 %s
// CHECK7: <Container>GSaV21cursor_info_container1S_</Container>
// CHECK7: <Container>_TtGSaV21cursor_info_container1S_</Container>
48 changes: 43 additions & 5 deletions tools/swift-ide-test/swift-ide-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,13 @@ HeaderToPrint("header-to-print",
static llvm::cl::opt<std::string>
LineColumnPair("pos", llvm::cl::desc("Line:Column pair"));

static llvm::cl::opt<std::string>
USR("usr", llvm::cl::desc("USR"));

static llvm::cl::opt<std::string>
ModuleName("module-name", llvm::cl::desc("The module name of the given test."),
llvm::cl::init("swift_ide_test"));

static llvm::cl::opt<bool>
NoEmptyLineBetweenMembers("no-empty-line-between-members",
llvm::cl::desc("Print no empty line between members."),
Expand Down Expand Up @@ -2362,6 +2369,33 @@ static int doPrintTypeInterface(const CompilerInvocation &InitInvok,
return 0;
}

static int doPrintTypeInterfaceForTypeUsr(const CompilerInvocation &InitInvok,
const StringRef FileName,
const StringRef Usr) {
CompilerInvocation Invocation(InitInvok);
Invocation.addInputFilename(FileName);
CompilerInstance CI;
if (CI.setup(Invocation))
return 1;
CI.performSema();
SourceFile *SF = nullptr;
for (auto Unit : CI.getMainModule()->getFiles()) {
SF = dyn_cast<SourceFile>(Unit);
if (SF)
break;
}
assert(SF && "no source file?");
std::string Error;
Type ReconstructedType = getTypeFromMangledSymbolname(SF->getASTContext(),
Usr, Error);
if (!Error.empty()) {
llvm::errs() << Error << '\n';
return 1;
}
ASTPrinter::printTypeInterface(ReconstructedType, SF, llvm::outs());
return 0;
}

//===----------------------------------------------------------------------===//
// Print USRs
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2665,8 +2699,7 @@ int main(int argc, char *argv[]) {
InitInvok.setMainExecutablePath(
llvm::sys::fs::getMainExecutable(argv[0],
reinterpret_cast<void *>(&anchorForGetMainExecutable)));

InitInvok.setModuleName("swift_ide_test");
InitInvok.setModuleName(options::ModuleName);

InitInvok.setSDKPath(options::SDK);
if (!options::Triple.empty())
Expand Down Expand Up @@ -2892,9 +2925,14 @@ int main(int argc, char *argv[]) {
ExitCode = doPrintUSRs(InitInvok, options::SourceFilename);
break;
case ActionType::PrintTypeInterface:
ExitCode = doPrintTypeInterface(InitInvok,
options::SourceFilename,
options::LineColumnPair);
if (options::LineColumnPair.getNumOccurrences() == 1)
ExitCode = doPrintTypeInterface(InitInvok,
options::SourceFilename,
options::LineColumnPair);
else
ExitCode = doPrintTypeInterfaceForTypeUsr(InitInvok,
options::SourceFilename,
options::USR);
break;
case ActionType::ReconstructType:
ExitCode = doReconstructType(InitInvok, options::SourceFilename);
Expand Down