Skip to content

Commit e4902b7

Browse files
committed
Preserve default argument text through serialization
This allows us to dump it in the generated interface, though it's still not syntax-highlighted. This is necessary for textual module interfaces, but it's also just a longstanding request for Xcode's "Generated Interface" / "Jump to Definition" feature. rdar://problem/18675831
1 parent 9ebbf2f commit e4902b7

File tree

15 files changed

+117
-74
lines changed

15 files changed

+117
-74
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ CHANGELOG
2424
Swift 5.0
2525
---------
2626

27+
* [SR-2608][]
28+
29+
Default arguments are now printed in SourceKit-generated interfaces for Swift
30+
modules, instead of just using a placeholder `default`.
31+
2732
* Notable bug fix: unowned and unowned(unsafe) variables now support optional
2833
types.
2934

@@ -7151,3 +7156,4 @@ Swift 1.0
71517156
[SR-2131]: <https://bugs.swift.org/browse/SR-2131>
71527157
[SR-2388]: <https://bugs.swift.org/browse/SR-2388>
71537158
[SR-2394]: <https://bugs.swift.org/browse/SR-2394>
7159+
[SR-2608]: <https://bugs.swift.org/browse/SR-2608>

include/swift/AST/Decl.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4694,6 +4694,7 @@ class ParamDecl : public VarDecl {
46944694
struct StoredDefaultArgument {
46954695
Expr *DefaultArg = nullptr;
46964696
Initializer *InitContext = nullptr;
4697+
StringRef StringRepresentation;
46974698
};
46984699

46994700
/// The default value, if any, along with whether this is varargs.
@@ -4757,6 +4758,17 @@ class ParamDecl : public VarDecl {
47574758

47584759
void setDefaultArgumentInitContext(Initializer *initContext);
47594760

4761+
/// Returns a saved string representation of the parameter's default value.
4762+
///
4763+
/// This should only be called if the default value expression is absent or
4764+
/// doesn't have a valid source range; otherwise, clients should extract the
4765+
/// source text from that range.
4766+
///
4767+
/// \sa getDefaultValue
4768+
StringRef getDefaultValueStringRepresentation() const;
4769+
4770+
void setDefaultValueStringRepresentation(StringRef stringRepresentation);
4771+
47604772
/// Whether or not this parameter is varargs.
47614773
bool isVariadic() const { return DefaultValueAndIsVariadic.getInt(); }
47624774
void setVariadic(bool value = true) {DefaultValueAndIsVariadic.setInt(value);}

include/swift/AST/DefaultArgumentKind.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@ enum class DefaultArgumentKind : uint8_t {
5555
};
5656
enum { NumDefaultArgumentKindBits = 4 };
5757

58-
/// Retrieve the spelling of this default argument in source code, or
59-
/// an empty string if it has none.
60-
llvm::StringRef getDefaultArgumentSpelling(DefaultArgumentKind kind);
61-
6258
} // end namespace swift
6359

6460
#endif // LLVM_SWIFT_DEFAULTARGUMENTKIND_H

include/swift/Serialization/ModuleFormat.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 431; // Last change: eliminate PARAMETERLIST_ELT
58+
const uint16_t VERSION_MINOR = 432; // Last change: default argument text
5959

6060
using DeclIDField = BCFixed<31>;
6161

@@ -1003,13 +1003,14 @@ namespace decls_block {
10031003

10041004
using ParamLayout = BCRecordLayout<
10051005
PARAM_DECL,
1006-
IdentifierIDField, // argument name
1007-
IdentifierIDField, // parameter name
1008-
DeclContextIDField, // context decl
1006+
IdentifierIDField, // argument name
1007+
IdentifierIDField, // parameter name
1008+
DeclContextIDField, // context decl
10091009
VarDeclSpecifierField, // specifier
1010-
TypeIDField, // interface type
1011-
BCFixed<1>, // isVariadic?
1012-
DefaultArgumentField // default argument
1010+
TypeIDField, // interface type
1011+
BCFixed<1>, // isVariadic?
1012+
DefaultArgumentField, // default argument kind
1013+
BCBlob // default argument text
10131014
>;
10141015

10151016
using FuncLayout = BCRecordLayout<

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,8 +2327,8 @@ void PrintAST::printOneParameter(const ParamDecl *param,
23272327
Printer << "...";
23282328

23292329
if (param->isDefaultArgument()) {
2330-
auto defaultArgStr
2331-
= getDefaultArgumentSpelling(param->getDefaultArgumentKind());
2330+
StringRef defaultArgStr = param->getDefaultValueStringRepresentation();
2331+
23322332
if (defaultArgStr.empty()) {
23332333
if (Options.PrintDefaultParameterPlaceholder)
23342334
Printer << " = " << tok::kw_default;
@@ -2341,6 +2341,7 @@ void PrintAST::printOneParameter(const ParamDecl *param,
23412341
case DefaultArgumentKind::Column:
23422342
case DefaultArgumentKind::Function:
23432343
case DefaultArgumentKind::DSOHandle:
2344+
case DefaultArgumentKind::NilLiteral:
23442345
Printer.printKeyword(defaultArgStr);
23452346
break;
23462347
default:

lib/AST/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ add_swift_library(swiftAST STATIC
2424
Decl.cpp
2525
DeclContext.cpp
2626
DeclNameLoc.cpp
27-
DefaultArgumentKind.cpp
2827
DiagnosticConsumer.cpp
2928
DiagnosticEngine.cpp
3029
DiagnosticList.cpp

lib/AST/Decl.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4830,6 +4830,43 @@ void ParamDecl::setDefaultArgumentInitContext(Initializer *initContext) {
48304830
DefaultValueAndIsVariadic.getPointer()->InitContext = initContext;
48314831
}
48324832

4833+
StringRef ParamDecl::getDefaultValueStringRepresentation() const {
4834+
switch (getDefaultArgumentKind()) {
4835+
case DefaultArgumentKind::None:
4836+
llvm_unreachable("called on a ParamDecl with no default value");
4837+
case DefaultArgumentKind::Normal:
4838+
assert(DefaultValueAndIsVariadic.getPointer() &&
4839+
"default value not provided yet");
4840+
return DefaultValueAndIsVariadic.getPointer()->StringRepresentation;
4841+
case DefaultArgumentKind::Inherited:
4842+
// FIXME: This needs /some/ kind of textual representation, but this isn't
4843+
// a great one.
4844+
return "super";
4845+
case DefaultArgumentKind::File: return "#file";
4846+
case DefaultArgumentKind::Line: return "#line";
4847+
case DefaultArgumentKind::Column: return "#column";
4848+
case DefaultArgumentKind::Function: return "#function";
4849+
case DefaultArgumentKind::DSOHandle: return "#dsohandle";
4850+
case DefaultArgumentKind::NilLiteral: return "nil";
4851+
case DefaultArgumentKind::EmptyArray: return "[]";
4852+
case DefaultArgumentKind::EmptyDictionary: return "[:]";
4853+
}
4854+
}
4855+
4856+
void
4857+
ParamDecl::setDefaultValueStringRepresentation(StringRef stringRepresentation) {
4858+
assert(getDefaultArgumentKind() == DefaultArgumentKind::Normal);
4859+
assert(!stringRepresentation.empty());
4860+
4861+
if (!DefaultValueAndIsVariadic.getPointer()) {
4862+
DefaultValueAndIsVariadic.setPointer(
4863+
getASTContext().Allocate<StoredDefaultArgument>());
4864+
}
4865+
4866+
DefaultValueAndIsVariadic.getPointer()->StringRepresentation =
4867+
stringRepresentation;
4868+
}
4869+
48334870
void DefaultArgumentInitializer::changeFunction(
48344871
DeclContext *parent, ParameterList *paramList) {
48354872
if (parent->isLocalContext()) {

lib/AST/DefaultArgumentKind.cpp

Lines changed: 0 additions & 39 deletions
This file was deleted.

lib/Parse/ParsePattern.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,9 @@ void Parser::DefaultArgumentInfo::setFunctionContext(
6363
}
6464
}
6565

66-
static ParserStatus parseDefaultArgument(Parser &P,
67-
Parser::DefaultArgumentInfo *defaultArgs,
68-
unsigned argIndex,
69-
Expr *&init,
70-
Parser::ParameterContextKind paramContext) {
66+
static ParserStatus parseDefaultArgument(
67+
Parser &P, Parser::DefaultArgumentInfo *defaultArgs, unsigned argIndex,
68+
Expr *&init, Parser::ParameterContextKind paramContext) {
7169
SyntaxParsingContext DefaultArgContext(P.SyntaxContext,
7270
SyntaxKind::InitializerClause);
7371
SourceLoc equalLoc = P.consumeToken(tok::equal);
@@ -576,8 +574,17 @@ mapParsedParameters(Parser &parser,
576574
paramContext == Parser::ParameterContextKind::Initializer ||
577575
paramContext == Parser::ParameterContextKind::EnumElement) &&
578576
"Default arguments are only permitted on the first param clause");
579-
result->setDefaultArgumentKind(getDefaultArgKind(param.DefaultArg));
577+
DefaultArgumentKind kind = getDefaultArgKind(param.DefaultArg);
578+
result->setDefaultArgumentKind(kind);
580579
result->setDefaultValue(param.DefaultArg);
580+
if (kind == DefaultArgumentKind::Normal) {
581+
SourceRange defaultArgRange = param.DefaultArg->getSourceRange();
582+
CharSourceRange charRange =
583+
Lexer::getCharSourceRangeFromSourceRange(parser.SourceMgr,
584+
defaultArgRange);
585+
StringRef defaultArgText = parser.SourceMgr.extractText(charRange);
586+
result->setDefaultValueStringRepresentation(defaultArgText);
587+
}
581588
}
582589

583590
elements.push_back(result);

lib/Serialization/Deserialization.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3057,8 +3057,11 @@ ModuleFile::getDeclCheckedImpl(DeclID DID, Optional<DeclContext *> ForcedContext
30573057

30583058
// Decode the default argument kind.
30593059
// FIXME: Default argument expression, if available.
3060-
if (auto defaultArg = getActualDefaultArgKind(rawDefaultArg))
3060+
if (auto defaultArg = getActualDefaultArgKind(rawDefaultArg)) {
30613061
param->setDefaultArgumentKind(*defaultArg);
3062+
if (!blobData.empty())
3063+
param->setDefaultValueStringRepresentation(blobData);
3064+
}
30623065
break;
30633066
}
30643067

lib/Serialization/Serialization.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3168,6 +3168,12 @@ void Serializer::writeDecl(const Decl *D) {
31683168
auto contextID = addDeclContextRef(param->getDeclContext());
31693169
Type interfaceType = param->getInterfaceType();
31703170

3171+
// Only save the text for normal default arguments, not any of the special
3172+
// ones.
3173+
StringRef defaultArgumentText;
3174+
if (param->getDefaultArgumentKind() == swift::DefaultArgumentKind::Normal)
3175+
defaultArgumentText = param->getDefaultValueStringRepresentation();
3176+
31713177
unsigned abbrCode = DeclTypeAbbrCodes[ParamLayout::Code];
31723178
ParamLayout::emitRecord(Out, ScratchRecord, abbrCode,
31733179
addDeclBaseNameRef(param->getArgumentName()),
@@ -3176,7 +3182,8 @@ void Serializer::writeDecl(const Decl *D) {
31763182
getRawStableVarDeclSpecifier(param->getSpecifier()),
31773183
addTypeRef(interfaceType),
31783184
param->isVariadic(),
3179-
getRawStableDefaultArgumentKind(param->getDefaultArgumentKind()));
3185+
getRawStableDefaultArgumentKind(param->getDefaultArgumentKind()),
3186+
defaultArgumentText);
31803187

31813188
if (interfaceType->hasError()) {
31823189
param->getDeclContext()->dumpContext();

test/IDE/print_ast_tc_decls.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,10 @@ struct d0100_FooStruct {
130130
// PASS_COMMON-NEXT: {{^}} func instanceFunc3(a: Int, b: Double){{$}}
131131

132132
func instanceFuncWithDefaultArg1(a: Int = 0) {}
133-
// PASS_COMMON-NEXT: {{^}} func instanceFuncWithDefaultArg1(a: Int = default){{$}}
133+
// PASS_COMMON-NEXT: {{^}} func instanceFuncWithDefaultArg1(a: Int = 0){{$}}
134134

135135
func instanceFuncWithDefaultArg2(a: Int = 0, b: Double = 0) {}
136-
// PASS_COMMON-NEXT: {{^}} func instanceFuncWithDefaultArg2(a: Int = default, b: Double = default){{$}}
136+
// PASS_COMMON-NEXT: {{^}} func instanceFuncWithDefaultArg2(a: Int = 0, b: Double = 0){{$}}
137137

138138
func varargInstanceFunc0(v: Int...) {}
139139
// PASS_COMMON-NEXT: {{^}} func varargInstanceFunc0(v: Int...){{$}}

test/IDE/print_type_interface.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ extension D {
7979
// RUN: %target-swift-ide-test -print-type-interface -usr=_TtGSaSS_ -module-name print_type_interface -source-filename %s | %FileCheck %s -check-prefix=TYPE5
8080
// TYPE5-DAG: public func prefix(_ maxLength: Int) -> ArraySlice<String>
8181
// TYPE5-DAG: public func suffix(_ maxLength: Int) -> ArraySlice<String>
82-
// TYPE5-DAG: public func split(separator: String, maxSplits: Int = default, omittingEmptySubsequences: Bool = default) -> [ArraySlice<String>]
82+
// TYPE5-DAG: public func split(separator: String, maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true) -> [ArraySlice<String>]
8383
// TYPE5-DAG: public func formIndex(_ i: inout Int, offsetBy distance: Int)
8484
// TYPE5-DAG: public func distance(from start: Int, to end: Int) -> Int
85-
// TYPE5-DAG: public func joined(separator: String = default) -> String
85+
// TYPE5-DAG: public func joined(separator: String = "") -> String
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t/Test~partial.swiftmodule -module-name Test -primary-file %s
3+
// RUN: %target-swift-frontend -merge-modules -emit-module -o %t/Test.swiftmodule %t/Test~partial.swiftmodule
4+
// RUN: %target-swift-ide-test -print-module -module-to-print=Test -source-filename=x -I %t | %FileCheck %s
5+
6+
// CHECK-LABEL: func testDefaultArguments(
7+
public func testDefaultArguments(
8+
// CHECK-SAME: normal: Int = 0
9+
normal: Int = 0,
10+
// CHECK-SAME: multiToken: Int = Int.max
11+
multiToken: Int = Int.max,
12+
// CHECK-SAME: special: Int = #line
13+
special: Int = #line
14+
) {}
15+
// CHECK-SAME: )

test/SourceKit/CursorInfo/cursor_info.swift

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ enum E7: String {
328328

329329
// RUN: %sourcekitd-test -req=cursor -pos=31:7 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK13 %s
330330
// CHECK13: source.lang.swift.decl.function.free (31:6-31:37)
331-
// CHECK13: <Declaration>func testDefaultParam(arg1: <Type usr="s:Si">Int</Type> = default)</Declaration>
332-
// CHECK13: <decl.function.free><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>testDefaultParam</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>arg1</decl.var.parameter.argument_label>: <decl.var.parameter.type><ref.struct usr="s:Si">Int</ref.struct></decl.var.parameter.type> = <syntaxtype.keyword>default</syntaxtype.keyword></decl.var.parameter>)</decl.function.free>
331+
// CHECK13: <Declaration>func testDefaultParam(arg1: <Type usr="s:Si">Int</Type> = 0)</Declaration>
332+
// CHECK13: <decl.function.free><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>testDefaultParam</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>arg1</decl.var.parameter.argument_label>: <decl.var.parameter.type><ref.struct usr="s:Si">Int</ref.struct></decl.var.parameter.type> = 0</decl.var.parameter>)</decl.function.free>
333333

334334
// RUN: %sourcekitd-test -req=cursor -pos=34:4 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK14 %s
335335
// CHECK14: source.lang.swift.ref.function.free ({{.*}}Foo.framework/Frameworks/FooSub.framework/Headers/FooSub.h:4:5-4:16)
@@ -652,13 +652,11 @@ enum E7: String {
652652
// CHECK73-SAME: = <syntaxtype.keyword>#file</syntaxtype.keyword>
653653
// CHECK73-SAME: = <syntaxtype.keyword>#line</syntaxtype.keyword>
654654
// CHECK73-SAME: = <syntaxtype.keyword>#column</syntaxtype.keyword>
655-
// FIXME: []
656-
// CHECK73-SAME: = <syntaxtype.keyword>default</syntaxtype.keyword>
657-
// FIXME: [:]
658-
// CHECK73-SAME: = <syntaxtype.keyword>default</syntaxtype.keyword>
659-
// FIXME: keyword nil
660-
// CHECK73-SAME: = <syntaxtype.keyword>default</syntaxtype.keyword>
661-
// CHECK73-SAME: = <syntaxtype.keyword>default</syntaxtype.keyword>
655+
// CHECK73-SAME: = []
656+
// CHECK73-SAME: = [:]
657+
// FIXME: should be <syntaxtype.keyword>nil</syntaxtype.keyword>
658+
// CHECK73-SAME: = nil
659+
// CHECK73-SAME: = 1
662660

663661
// RUN: %sourcekitd-test -req=cursor -pos=162:8 %s -- -F %S/../Inputs/libIDE-mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck %s -check-prefix=CHECK74
664662
// CHECK74: source.lang.swift.decl.function.method.instance (162:8-162:20)

0 commit comments

Comments
 (0)