Skip to content

Commit 0efc3ea

Browse files
committed
[SourceKit] Add option for returning fully qualified types in expression type request
1 parent 8491f52 commit 0efc3ea

File tree

10 files changed

+73
-51
lines changed

10 files changed

+73
-51
lines changed

include/swift/Sema/IDETypeChecking.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,10 @@ namespace swift {
231231

232232
/// Collect type information for every expression in \c SF; all types will
233233
/// be printed to \c OS.
234-
ArrayRef<ExpressionTypeInfo> collectExpressionType(SourceFile &SF,
235-
ArrayRef<const char *> ExpectedProtocols,
236-
std::vector<ExpressionTypeInfo> &scratch,
237-
bool CanonicalType,
238-
llvm::raw_ostream &OS);
234+
ArrayRef<ExpressionTypeInfo> collectExpressionType(
235+
SourceFile &SF, ArrayRef<const char *> ExpectedProtocols,
236+
std::vector<ExpressionTypeInfo> &scratch, bool FullyQualified,
237+
bool CanonicalType, llvm::raw_ostream &OS);
239238

240239
/// Resolve a list of mangled names to accessible protocol decls from
241240
/// the decl context.

lib/IDE/IDETypeChecking.cpp

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,9 @@ class ExpressionTypeCollector: public SourceEntityWalker {
630630
// these protocols.
631631
llvm::MapVector<ProtocolDecl*, StringRef> &InterestedProtocols;
632632

633+
// Specified by the client whether we should print fully qualified types
634+
const bool FullyQualified;
635+
633636
// Specified by the client whether we should canonicalize types before printing
634637
const bool CanonicalType;
635638

@@ -676,16 +679,15 @@ class ExpressionTypeCollector: public SourceEntityWalker {
676679

677680

678681
public:
679-
ExpressionTypeCollector(SourceFile &SF,
680-
llvm::MapVector<ProtocolDecl*, StringRef> &InterestedProtocols,
681-
std::vector<ExpressionTypeInfo> &Results,
682-
bool CanonicalType,
683-
llvm::raw_ostream &OS): Module(*SF.getParentModule()),
684-
SM(SF.getASTContext().SourceMgr),
685-
BufferId(*SF.getBufferID()),
686-
Results(Results), OS(OS),
687-
InterestedProtocols(InterestedProtocols),
688-
CanonicalType(CanonicalType) {}
682+
ExpressionTypeCollector(
683+
SourceFile &SF,
684+
llvm::MapVector<ProtocolDecl *, StringRef> &InterestedProtocols,
685+
std::vector<ExpressionTypeInfo> &Results, bool FullyQualified,
686+
bool CanonicalType, llvm::raw_ostream &OS)
687+
: Module(*SF.getParentModule()), SM(SF.getASTContext().SourceMgr),
688+
BufferId(*SF.getBufferID()), Results(Results), OS(OS),
689+
InterestedProtocols(InterestedProtocols),
690+
FullyQualified(FullyQualified), CanonicalType(CanonicalType) {}
689691
bool walkToExprPre(Expr *E) override {
690692
if (E->getSourceRange().isInvalid())
691693
return true;
@@ -701,10 +703,12 @@ class ExpressionTypeCollector: public SourceEntityWalker {
701703
{
702704
llvm::raw_svector_ostream OS(Buffer);
703705
auto Ty = E->getType()->getRValueType();
706+
PrintOptions printOptions = PrintOptions();
707+
printOptions.FullyQualifiedTypes = FullyQualified;
704708
if (CanonicalType) {
705-
Ty->getCanonicalType()->print(OS);
709+
Ty->getCanonicalType()->print(OS, printOptions);
706710
} else {
707-
Ty->reconstituteSugar(true)->print(OS);
711+
Ty->reconstituteSugar(true)->print(OS, printOptions);
708712
}
709713
}
710714
auto Ty = getTypeOffsets(Buffer.str());
@@ -729,12 +733,10 @@ ProtocolDecl* swift::resolveProtocolName(DeclContext *dc, StringRef name) {
729733
nullptr);
730734
}
731735

732-
ArrayRef<ExpressionTypeInfo>
733-
swift::collectExpressionType(SourceFile &SF,
734-
ArrayRef<const char *> ExpectedProtocols,
735-
std::vector<ExpressionTypeInfo> &Scratch,
736-
bool CanonicalType,
737-
llvm::raw_ostream &OS) {
736+
ArrayRef<ExpressionTypeInfo> swift::collectExpressionType(
737+
SourceFile &SF, ArrayRef<const char *> ExpectedProtocols,
738+
std::vector<ExpressionTypeInfo> &Scratch, bool FullyQualified,
739+
bool CanonicalType, llvm::raw_ostream &OS) {
738740
llvm::MapVector<ProtocolDecl*, StringRef> InterestedProtocols;
739741
for (auto Name: ExpectedProtocols) {
740742
if (auto *pd = resolveProtocolName(&SF, Name)) {
@@ -744,7 +746,7 @@ swift::collectExpressionType(SourceFile &SF,
744746
}
745747
}
746748
ExpressionTypeCollector Walker(SF, InterestedProtocols, Scratch,
747-
CanonicalType, OS);
749+
FullyQualified, CanonicalType, OS);
748750
Walker.walk(SF);
749751
return Scratch;
750752
}

test/IDE/expr_type_qualified.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swift-ide-test -print-expr-type -fully-qualified-types -source-filename %S/Inputs/ExprType.swift -swift-version 5 | %FileCheck %s -check-prefix=CHECK-SUGAR
2+
// RUN: %target-swift-ide-test -print-expr-type -fully-qualified-types -source-filename %S/Inputs/ExprType.swift -swift-version 5 -canonicalize-type | %FileCheck %s -check-prefix=CHECK-CANON
3+
4+
// CHECK-SUGAR: func foo() -> Int { return <expr type:"Swift.Int">1</expr> }
5+
// CHECK-SUGAR: func bar(f: Float) -> Float { return <expr type:"Swift.Float"><expr type:"(Swift.Float) -> Swift.Float">bar</expr>(f: <expr type:"Swift.Float">1</expr>)</expr> }
6+
// CHECK-SUGAR: func fooP(_ p: P) { <expr type:"()"><expr type:"(swift_ide_test.P) -> ()">fooP</expr>(<expr type:"swift_ide_test.P">p</expr>)</expr> }
7+
// CHECK-SUGAR: <expr type:"()"><expr type:"Swift.Int">_</expr> = <expr type:"Swift.Int"><expr type:"[swift_ide_test.C]">a</expr>.count</expr></expr>
8+
// CHECK-SUGAR: <expr type:"()"><expr type:"Swift.String">_</expr> = <expr type:"Swift.String"><expr type:"Swift.Int"><expr type:"(Swift.Int) -> Swift.Int"><expr type:"Swift.Int"><expr type:"Swift.String"><expr type:"[swift_ide_test.C]">a</expr>.description</expr>.count</expr>.<expr type:"(Swift.Int) -> (Swift.Int) -> Swift.Int">advanced</expr></expr>(by: <expr type:"Swift.Int">1</expr>)</expr>.description</expr></expr>
9+
// CHECK-SUGAR: <expr type:"()"><expr type:"Swift.Int?">_</expr> = <expr type:"Swift.Int?"><expr type:"Swift.Int"><expr type:"(Swift.Int) -> Swift.Int"><expr type:"Swift.Int"><expr type:"swift_ide_test.S"><expr type:"swift_ide_test.S?"><expr type:"[Swift.Int : swift_ide_test.S]">a</expr>[<expr type:"Swift.Int">2</expr>]</expr>?</expr>.val</expr>.<expr type:"(Swift.Int) -> (Swift.Int) -> Swift.Int">advanced</expr></expr>(by: <expr type:"Swift.Int">1</expr>)</expr>.byteSwapped</expr></expr>
10+
11+
12+
// CHECK-SUGAR: return <expr type:"swift_ide_test.MyInt"><expr type:"swift_ide_test.MyInt">a</expr> <expr type:"(Swift.Int, Swift.Int) -> Swift.Int">+</expr> <expr type:"swift_ide_test.MyInt">b</expr></expr>
13+
// CHECK-CANON: return <expr type:"Swift.Int"><expr type:"Swift.Int">a</expr> <expr type:"(Swift.Int, Swift.Int) -> Swift.Int">+</expr> <expr type:"Swift.Int">b</expr></expr>

tools/SourceKit/docs/Protocol.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -751,14 +751,15 @@ type checking and the necessary compiler arguments to help resolve all dependenc
751751

752752
```
753753
{
754-
<key.request>: (UID) <source.request.expression.type>,
755-
<key.sourcefile>: (string) // Absolute path to the file.
756-
<key.compilerargs>: [string*] // Array of zero or more strings for the compiler arguments,
757-
// e.g ["-sdk", "/path/to/sdk"]. If key.sourcefile is provided,
758-
// these must include the path to that file.
759-
<key.expectedtypes>: [string*] // A list of interested protocol USRs.
760-
// When empty, we report all expressions in the file.
761-
// When non-empty, we report expressions whose types conform to any of the give protocols.
754+
<key.request>: (UID) <source.request.expression.type>,
755+
<key.sourcefile>: (string) // Absolute path to the file.
756+
<key.compilerargs>: [string*] // Array of zero or more strings for the compiler arguments,
757+
// e.g ["-sdk", "/path/to/sdk"]. If key.sourcefile is provided,
758+
// these must include the path to that file.
759+
<key.expectedtypes>: [string*] // A list of interested protocol USRs.
760+
// When empty, we report all expressions in the file.
761+
// When non-empty, we report expressions whose types conform to any of the give protocols.
762+
[opt] <key.fully_qualified>: (bool) // True when fully qualified type should be returned. Defaults to False.
762763
}
763764
```
764765

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -911,8 +911,8 @@ class LangSupport {
911911

912912
virtual void collectExpressionTypes(
913913
StringRef FileName, ArrayRef<const char *> Args,
914-
ArrayRef<const char *> ExpectedProtocols, bool CanonicalType,
915-
SourceKitCancellationToken CancellationToken,
914+
ArrayRef<const char *> ExpectedProtocols, bool FullyQualified,
915+
bool CanonicalType, SourceKitCancellationToken CancellationToken,
916916
std::function<void(const RequestResult<ExpressionTypesInFile> &)>
917917
Receiver) = 0;
918918

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,8 @@ class SwiftLangSupport : public LangSupport {
686686

687687
void collectExpressionTypes(
688688
StringRef FileName, ArrayRef<const char *> Args,
689-
ArrayRef<const char *> ExpectedProtocols, bool CanonicalType,
690-
SourceKitCancellationToken CancellationToken,
689+
ArrayRef<const char *> ExpectedProtocols, bool FullyQualified,
690+
bool CanonicalType, SourceKitCancellationToken CancellationToken,
691691
std::function<void(const RequestResult<ExpressionTypesInFile> &)>
692692
Receiver) override;
693693

tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,8 +2526,8 @@ void SwiftLangSupport::semanticRefactoring(
25262526

25272527
void SwiftLangSupport::collectExpressionTypes(
25282528
StringRef FileName, ArrayRef<const char *> Args,
2529-
ArrayRef<const char *> ExpectedProtocols, bool CanonicalType,
2530-
SourceKitCancellationToken CancellationToken,
2529+
ArrayRef<const char *> ExpectedProtocols, bool FullyQualified,
2530+
bool CanonicalType, SourceKitCancellationToken CancellationToken,
25312531
std::function<void(const RequestResult<ExpressionTypesInFile> &)>
25322532
Receiver) {
25332533
std::string Error;
@@ -2542,23 +2542,26 @@ void SwiftLangSupport::collectExpressionTypes(
25422542
class ExpressionTypeCollector: public SwiftASTConsumer {
25432543
std::function<void(const RequestResult<ExpressionTypesInFile> &)> Receiver;
25442544
std::vector<const char *> ExpectedProtocols;
2545+
bool FullyQualified;
25452546
bool CanonicalType;
25462547
public:
25472548
ExpressionTypeCollector(
2548-
std::function<void(const RequestResult<ExpressionTypesInFile> &)> Receiver,
2549-
ArrayRef<const char *> ExpectedProtocols,
2550-
bool CanonicalType):
2551-
Receiver(std::move(Receiver)),
2549+
std::function<void(const RequestResult<ExpressionTypesInFile> &)>
2550+
Receiver,
2551+
ArrayRef<const char *> ExpectedProtocols, bool FullyQualified,
2552+
bool CanonicalType)
2553+
: Receiver(std::move(Receiver)),
25522554
ExpectedProtocols(ExpectedProtocols.vec()),
2553-
CanonicalType(CanonicalType) {}
2555+
FullyQualified(FullyQualified), CanonicalType(CanonicalType) {}
25542556
void handlePrimaryAST(ASTUnitRef AstUnit) override {
25552557
auto *SF = AstUnit->getCompilerInstance().getPrimarySourceFile();
25562558
std::vector<ExpressionTypeInfo> Scratch;
25572559
llvm::SmallString<256> TypeBuffer;
25582560
llvm::raw_svector_ostream OS(TypeBuffer);
25592561
ExpressionTypesInFile Result;
2560-
for (auto Item: collectExpressionType(*SF, ExpectedProtocols, Scratch,
2561-
CanonicalType, OS)) {
2562+
for (auto Item :
2563+
collectExpressionType(*SF, ExpectedProtocols, Scratch,
2564+
FullyQualified, CanonicalType, OS)) {
25622565
Result.Results.push_back({Item.offset, Item.length, Item.typeOffset, {}});
25632566
for (auto P: Item.protocols) {
25642567
Result.Results.back().ProtocolOffsets.push_back(P.first);
@@ -2576,9 +2579,8 @@ void SwiftLangSupport::collectExpressionTypes(
25762579
Receiver(RequestResult<ExpressionTypesInFile>::fromError(Error));
25772580
}
25782581
};
2579-
auto Collector = std::make_shared<ExpressionTypeCollector>(Receiver,
2580-
ExpectedProtocols,
2581-
CanonicalType);
2582+
auto Collector = std::make_shared<ExpressionTypeCollector>(
2583+
Receiver, ExpectedProtocols, FullyQualified, CanonicalType);
25822584
/// FIXME: When request cancellation is implemented and Xcode adopts it,
25832585
/// don't use 'OncePerASTToken'.
25842586
static const char OncePerASTToken = 0;

tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,10 +1233,13 @@ static void handleSemanticRequest(
12331233
SmallVector<const char *, 8> ExpectedProtocols;
12341234
if (Req.getStringArray(KeyExpectedTypes, ExpectedProtocols, true))
12351235
return Rec(createErrorRequestInvalid("invalid 'key.expectedtypes'"));
1236+
int64_t FullyQualified = false;
1237+
Req.getInt64(KeyFullyQualified, FullyQualified, /*isOptional=*/true);
12361238
int64_t CanonicalTy = false;
12371239
Req.getInt64(KeyCanonicalizeType, CanonicalTy, /*isOptional=*/true);
12381240
return Lang.collectExpressionTypes(
1239-
*SourceFile, Args, ExpectedProtocols, CanonicalTy, CancellationToken,
1241+
*SourceFile, Args, ExpectedProtocols, FullyQualified, CanonicalTy,
1242+
CancellationToken,
12401243
[Rec](const RequestResult<ExpressionTypesInFile> &Result) {
12411244
reportExpressionTypeInfo(Result, Rec);
12421245
});

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,8 +2596,9 @@ static int doPrintExpressionTypes(const CompilerInvocation &InitInvok,
25962596
for (auto &u: options::UsrFilter)
25972597
Usrs.push_back(u.c_str());
25982598
// Collect all tags of expressions.
2599-
for (auto R: collectExpressionType(*CI.getPrimarySourceFile(), Usrs, Scratch,
2600-
options::CanonicalizeType, OS)) {
2599+
for (auto R : collectExpressionType(*CI.getPrimarySourceFile(), Usrs, Scratch,
2600+
options::FullyQualifiedTypes,
2601+
options::CanonicalizeType, OS)) {
26012602
SortedTags.push_back({R.offset,
26022603
(llvm::Twine("<expr type:\"") + TypeBuffer.str().substr(R.typeOffset,
26032604
R.typeLength) + "\">").str()});

utils/gyb_sourcekit_support/UIDs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def __init__(self, internal_name, external_name):
182182
KEY('VariableLength', 'key.variable_length'),
183183
KEY('VariableType', 'key.variable_type'),
184184
KEY('VariableTypeExplicit', 'key.variable_type_explicit'),
185+
KEY('FullyQualified', 'key.fully_qualified'),
185186
KEY('CanonicalizeType', 'key.canonicalize_type'),
186187
KEY('InternalDiagnostic', 'key.internal_diagnostic'),
187188
KEY('VFSName', 'key.vfs.name'),

0 commit comments

Comments
 (0)