Skip to content

[CodeCompletion] Call argument label with value placeholder #30383

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 2 commits into from
Mar 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 28 additions & 11 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3936,14 +3936,31 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
}
}

void addArgNameCompletionResults(ArrayRef<StringRef> Names) {
for (auto Name : Names) {
CodeCompletionResultBuilder Builder(Sink,
CodeCompletionResult::ResultKind::Keyword,
SemanticContextKind::ExpressionSpecific, {});
Builder.addTextChunk(Name);
Builder.addCallParameterColon();
Builder.addTypeAnnotation("Argument name");
void addCallArgumentCompletionResults(
ArrayRef<const AnyFunctionType::Param *> Args) {
Type ContextType;
if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
ContextType = typeContext->getDeclaredTypeInContext();

for (auto *Arg : Args) {
CodeCompletionResultBuilder Builder(
Sink, CodeCompletionResult::ResultKind::Pattern,
SemanticContextKind::ExpressionSpecific, {});
Builder.addCallParameter(Arg->getLabel(), Identifier(),
Arg->getPlainType(), ContextType,
Arg->isVariadic(), Arg->isInOut(),
/*isIUO=*/false, Arg->isAutoClosure());
auto Ty = Arg->getPlainType();
if (Arg->isInOut()) {
Ty = InOutType::get(Ty);
} else if (Arg->isAutoClosure()) {
// 'Ty' may be ErrorType.
if (auto funcTy = Ty->getAs<FunctionType>())
Ty = funcTy->getResult();
}
addTypeAnnotation(Builder, Ty);
Builder.setExpectedTypeRelation(
CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
}
}

Expand Down Expand Up @@ -5432,7 +5449,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
}
} else {
// Add argument labels, then fallthrough to get values.
Lookup.addArgNameCompletionResults(ContextInfo.getPossibleNames());
Lookup.addCallArgumentCompletionResults(ContextInfo.getPossibleParams());
}

if (!Lookup.FoundFunctionCalls ||
Expand Down Expand Up @@ -5570,8 +5587,8 @@ void CodeCompletionCallbacksImpl::doneParsing() {
!Lookup.FoundFunctionCalls ||
(Lookup.FoundFunctionCalls &&
Lookup.FoundFunctionsWithoutFirstKeyword);
} else if (!ContextInfo.getPossibleNames().empty()) {
Lookup.addArgNameCompletionResults(ContextInfo.getPossibleNames());
} else if (!ContextInfo.getPossibleParams().empty()) {
Lookup.addCallArgumentCompletionResults(ContextInfo.getPossibleParams());

shouldPerformGlobalCompletion = !ContextInfo.getPossibleTypes().empty();
}
Expand Down
42 changes: 24 additions & 18 deletions lib/IDE/ExprContextAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ class ExprContextAnalyzer {

// Results populated by Analyze()
SmallVectorImpl<Type> &PossibleTypes;
SmallVectorImpl<StringRef> &PossibleNames;
SmallVectorImpl<const AnyFunctionType::Param *> &PossibleParams;
SmallVectorImpl<FunctionTypeAndDecl> &PossibleCallees;
bool &singleExpressionBody;

Expand All @@ -548,7 +548,9 @@ class ExprContextAnalyzer {
PossibleTypes.push_back(ty->getRValueType());
}

void recordPossibleName(StringRef name) { PossibleNames.push_back(name); }
void recordPossibleParam(const AnyFunctionType::Param &arg) {
PossibleParams.push_back(&arg);
}

/// Collect context information at call argument position.
bool analyzeApplyExpr(Expr *E) {
Expand Down Expand Up @@ -585,7 +587,7 @@ class ExprContextAnalyzer {
(isa<CallExpr>(E) | isa<SubscriptExpr>(E) ||
isa<UnresolvedMemberExpr>(E));
SmallPtrSet<TypeBase *, 4> seenTypes;
SmallPtrSet<Identifier, 4> seenNames;
llvm::SmallSet<std::pair<Identifier, TypeBase *>, 4> seenArgs;
for (auto &typeAndDecl : Candidates) {
DeclContext *memberDC = nullptr;
if (typeAndDecl.Decl)
Expand All @@ -603,23 +605,27 @@ class ExprContextAnalyzer {
}
for (auto Pos = Position; Pos < Params.size(); ++Pos) {
const auto &Param = Params[Pos];
Type ty = Param.getPlainType();
if (memberDC && ty->hasTypeParameter())
ty = memberDC->mapTypeIntoContext(ty);

if (Param.hasLabel() && MayNeedName) {
if (seenNames.insert(Param.getLabel()).second)
recordPossibleName(Param.getLabel().str());
if (seenArgs.insert({Param.getLabel(), ty.getPointer()}).second)
recordPossibleParam(Param);
if (paramList && paramList->get(Position)->isDefaultArgument())
continue;
} else {
Type ty = Param.getOldType();
if (memberDC && ty->hasTypeParameter())
ty = memberDC->mapTypeIntoContext(ty);
if (seenTypes.insert(ty.getPointer()).second)
recordPossibleType(ty);
auto argTy = ty;
if (Param.isInOut())
argTy = InOutType::get(argTy);
if (seenTypes.insert(argTy.getPointer()).second)
recordPossibleType(argTy);
}
break;
}
}
}
return !PossibleTypes.empty() || !PossibleNames.empty();
return !PossibleTypes.empty() || !PossibleParams.empty();
}

void analyzeExpr(Expr *Parent) {
Expand Down Expand Up @@ -879,14 +885,14 @@ class ExprContextAnalyzer {
}

public:
ExprContextAnalyzer(DeclContext *DC, Expr *ParsedExpr,
SmallVectorImpl<Type> &PossibleTypes,
SmallVectorImpl<StringRef> &PossibleNames,
SmallVectorImpl<FunctionTypeAndDecl> &PossibleCallees,
bool &singleExpressionBody)
ExprContextAnalyzer(
DeclContext *DC, Expr *ParsedExpr, SmallVectorImpl<Type> &PossibleTypes,
SmallVectorImpl<const AnyFunctionType::Param *> &PossibleArgs,
SmallVectorImpl<FunctionTypeAndDecl> &PossibleCallees,
bool &singleExpressionBody)
: DC(DC), ParsedExpr(ParsedExpr), SM(DC->getASTContext().SourceMgr),
Context(DC->getASTContext()), PossibleTypes(PossibleTypes),
PossibleNames(PossibleNames), PossibleCallees(PossibleCallees),
PossibleParams(PossibleArgs), PossibleCallees(PossibleCallees),
singleExpressionBody(singleExpressionBody) {}

void Analyze() {
Expand Down Expand Up @@ -990,7 +996,7 @@ class ExprContextAnalyzer {
} // end anonymous namespace

ExprContextInfo::ExprContextInfo(DeclContext *DC, Expr *TargetExpr) {
ExprContextAnalyzer Analyzer(DC, TargetExpr, PossibleTypes, PossibleNames,
ExprContextAnalyzer Analyzer(DC, TargetExpr, PossibleTypes, PossibleParams,
PossibleCallees, singleExpressionBody);
Analyzer.Analyze();
}
Expand Down
8 changes: 5 additions & 3 deletions lib/IDE/ExprContextAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
#define SWIFT_IDE_EXPRCONTEXTANALYSIS_H

#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/SourceLoc.h"

namespace swift {
class DeclContext;
class Expr;
class ValueDecl;
class AnyFunctionType;

namespace ide {
enum class SemanticContextKind;
Expand Down Expand Up @@ -54,7 +54,7 @@ struct FunctionTypeAndDecl {
/// the expected type of the expression by analyzing its context.
class ExprContextInfo {
SmallVector<Type, 2> PossibleTypes;
SmallVector<StringRef, 2> PossibleNames;
SmallVector<const AnyFunctionType::Param *, 2> PossibleParams;
SmallVector<FunctionTypeAndDecl, 2> PossibleCallees;
bool singleExpressionBody = false;

Expand All @@ -73,7 +73,9 @@ class ExprContextInfo {

// Returns a list of possible argument label names.
// Valid only if \c getKind() is \c CallArgument.
ArrayRef<StringRef> getPossibleNames() const { return PossibleNames; }
ArrayRef<const AnyFunctionType::Param *> getPossibleParams() const {
return PossibleParams;
}

// Returns a list of possible callee
// Valid only if \c getKind() is \c CallArgument.
Expand Down
73 changes: 55 additions & 18 deletions test/IDE/complete_call_arg.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG3 | %FileCheck %s -check-prefix=ARG-NAME2
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG4 | %FileCheck %s -check-prefix=EXPECT_INT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG5 | %FileCheck %s -check-prefix=EXPECT_OSTRING
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG6 | %FileCheck %s -check-prefix=ARG-NAME2
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG7 | %FileCheck %s -check-prefix=ARG-NAME1
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG6 | %FileCheck %s -check-prefix=ARG-NAME3
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG7 | %FileCheck %s -check-prefix=ARG-NAME4
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG8 | %FileCheck %s -check-prefix=EXPECT_STRING

// RUN-FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=OVERLOAD1 | %FileCheck %s -check-prefix=OVERLOAD1
Expand Down Expand Up @@ -96,6 +96,12 @@
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TYPECHECKED_OVERLOADED | %FileCheck %s -check-prefix=TYPECHECKED_OVERLOADED
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TYPECHECKED_TYPEEXPR | %FileCheck %s -check-prefix=TYPECHECKED_TYPEEXPR

// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG_PARAMFLAG_INOUT | %FileCheck %s -check-prefix=ARG_PARAMFLAG_INOUT
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG_PARAMFLAG_AUTOCLOSURE| %FileCheck %s -check-prefix=ARG_PARAMFLAG_AUTOCLOSURE
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG_PARAMFLAG_IUO | %FileCheck %s -check-prefix=ARG_PARAMFLAG_IUO
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ARG_PARAMFLAG_VARIADIC | %FileCheck %s -check-prefix=ARG_PARAMFLAG_VARIADIC


var i1 = 1
var i2 = 2
var oi1 : Int?
Expand Down Expand Up @@ -171,11 +177,19 @@ class C1 {
}

// ARG-NAME1: Begin completions, 2 items
// ARG-NAME1-DAG: Keyword/ExprSpecific: b1: [#Argument name#]; name=b1:
// ARG-NAME1-DAG: Keyword/ExprSpecific: b2: [#Argument name#]; name=b2:
// ARG-NAME1-DAG: Pattern/ExprSpecific: {#b1: Int?#}[#Int?#];
// ARG-NAME1-DAG: Pattern/ExprSpecific: {#b2: Int?#}[#Int?#];

// ARG-NAME2: Begin completions, 1 items
// ARG-NAME2-DAG: Keyword/ExprSpecific: b: [#Argument name#]; name=b:
// ARG-NAME2-DAG: Pattern/ExprSpecific: {#b: Int#}[#Int#];

// ARG-NAME3: Begin completions, 1 items
// ARG-NAME3-DAG: Pattern/ExprSpecific: {#b: String?#}[#String?#];

// ARG-NAME4: Begin completions, 2 items
// ARG-NAME4-DAG: Pattern/ExprSpecific: {#b1: String#}[#String#];
// ARG-NAME4-DAG: Pattern/ExprSpecific: {#b2: String#}[#String#];
// ARG-NAME4: End completions

// EXPECT_OINT: Begin completions
// EXPECT_OINT-DAG: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: f1()[#Void#]; name=f1()
Expand Down Expand Up @@ -336,7 +350,7 @@ extension C3 {
// HASERROR2: End completions

// HASERROR3: Begin completions
// HASERROR3-DAG: Keyword/ExprSpecific: b1: [#Argument name#];
// HASERROR3-DAG: Pattern/ExprSpecific: {#b1: <<error type>>#}[#<<error type>>#];
// HASERROR3: End completions

// HASERROR4: Begin completions
Expand Down Expand Up @@ -464,7 +478,7 @@ func testArg2Name1() {
func testArg2Name3() {
firstArg(#^FIRST_ARG_NAME_3^#,
}
// FIRST_ARG_NAME_3: Keyword/ExprSpecific: arg1: [#Argument name#]
// FIRST_ARG_NAME_3: Pattern/ExprSpecific: {#arg1: Int#}[#Int#];
// FIRST_ARG_NAME_4: Decl[FreeFunction]/CurrModule: ['(']{#arg1: Int#}, {#arg2: Int#}[')'][#Void#];

func takeArray<T>(_ x: [T]) {}
Expand Down Expand Up @@ -582,7 +596,7 @@ func testSubscript(obj: HasSubscript, intValue: Int, strValue: String) {

let _ = obj[42, #^SUBSCRIPT_2^#
// SUBSCRIPT_2: Begin completions, 1 items
// SUBSCRIPT_2-NEXT: Keyword/ExprSpecific: default: [#Argument name#]; name=default:
// SUBSCRIPT_2-NEXT: Pattern/ExprSpecific: {#default: String#}[#String#];

let _ = obj[42, .#^SUBSCRIPT_2_DOT^#
// SUBSCRIPT_2_DOT-NOT: Begin completions
Expand Down Expand Up @@ -659,16 +673,16 @@ func testStaticMemberCall() {

let _ = TestStaticMemberCall.create2(1, #^STATIC_METHOD_SECOND^#)
// STATIC_METHOD_SECOND: Begin completions, 3 items
// STATIC_METHOD_SECOND: Keyword/ExprSpecific: arg2: [#Argument name#];
// STATIC_METHOD_SECOND: Keyword/ExprSpecific: arg3: [#Argument name#];
// STATIC_METHOD_SECOND: Keyword/ExprSpecific: arg4: [#Argument name#];
// STATIC_METHOD_SECOND: Pattern/ExprSpecific: {#arg2: Int#}[#Int#];
// STATIC_METHOD_SECOND: Pattern/ExprSpecific: {#arg3: Int#}[#Int#];
// STATIC_METHOD_SECOND: Pattern/ExprSpecific: {#arg4: Int#}[#Int#];
// STATIC_METHOD_SECOND: End completions

let _ = TestStaticMemberCall.create2(1, arg3: 2, #^STATIC_METHOD_SKIPPED^#)
// STATIC_METHOD_SKIPPED: Begin completions, 2 items
// FIXME: 'arg3' shouldn't be suggested.
// STATIC_METHOD_SKIPPED: Keyword/ExprSpecific: arg3: [#Argument name#];
// STATIC_METHOD_SKIPPED: Keyword/ExprSpecific: arg4: [#Argument name#];
// STATIC_METHOD_SKIPPED: Pattern/ExprSpecific: {#arg3: Int#}[#Int#];
// STATIC_METHOD_SKIPPED: Pattern/ExprSpecific: {#arg4: Int#}[#Int#];
// STATIC_METHOD_SKIPPED: End completions
}
func testImplicitMember() {
Expand All @@ -687,16 +701,16 @@ func testImplicitMember() {

let _: TestStaticMemberCall = .create2(1, #^IMPLICIT_MEMBER_SECOND^#)
// IMPLICIT_MEMBER_SECOND: Begin completions, 3 items
// IMPLICIT_MEMBER_SECOND: Keyword/ExprSpecific: arg2: [#Argument name#];
// IMPLICIT_MEMBER_SECOND: Keyword/ExprSpecific: arg3: [#Argument name#];
// IMPLICIT_MEMBER_SECOND: Keyword/ExprSpecific: arg4: [#Argument name#];
// IMPLICIT_MEMBER_SECOND: Pattern/ExprSpecific: {#arg2: Int#}[#Int#];
// IMPLICIT_MEMBER_SECOND: Pattern/ExprSpecific: {#arg3: Int#}[#Int#];
// IMPLICIT_MEMBER_SECOND: Pattern/ExprSpecific: {#arg4: Int#}[#Int#];
// IMPLICIT_MEMBER_SECOND: End completions

let _: TestStaticMemberCall = .create2(1, arg3: 2, #^IMPLICIT_MEMBER_SKIPPED^#)
// IMPLICIT_MEMBER_SKIPPED: Begin completions, 2 items
// FIXME: 'arg3' shouldn't be suggested.
// IMPLICIT_MEMBER_SKIPPED: Keyword/ExprSpecific: arg3: [#Argument name#];
// IMPLICIT_MEMBER_SKIPPED: Keyword/ExprSpecific: arg4: [#Argument name#];
// IMPLICIT_MEMBER_SKIPPED: Pattern/ExprSpecific: {#arg3: Int#}[#Int#];
// IMPLICIT_MEMBER_SKIPPED: Pattern/ExprSpecific: {#arg4: Int#}[#Int#];
// IMPLICIT_MEMBER_SKIPPED: End completions
}
func testImplicitMemberInArrayLiteral() {
Expand Down Expand Up @@ -779,3 +793,26 @@ func testTypecheckedTypeExpr() {
// TYPECHECKED_TYPEEXPR: Decl[Constructor]/CurrNominal: ['(']{#arg1: String#}, {#arg2: _#}[')'][#MyType<_>#]; name=arg1: String, arg2: _
// TYPECHECKED_TYPEEXPR: Decl[Constructor]/CurrNominal: ['(']{#(intVal): Int#}[')'][#MyType<Int>#]; name=intVal: Int
// TYPECHECKED_TYPEEXPR: End completions

func testPamrameterFlags(_: Int, inoutArg: inout Int, autoclosureArg: @autoclosure () -> Int, iuoArg: Int!, variadicArg: Int...) {
var intVal = 1
testPamrameterFlags(intVal, #^ARG_PARAMFLAG_INOUT^#)
// ARG_PARAMFLAG_INOUT: Begin completions, 1 items
// ARG_PARAMFLAG_INOUT-DAG: Pattern/ExprSpecific: {#inoutArg: &Int#}[#inout Int#]; name=inoutArg:
// ARG_PARAMFLAG_INOUT: End completions

testPamrameterFlags(intVal, inoutArg: &intVal, #^ARG_PARAMFLAG_AUTOCLOSURE^#)
// ARG_PARAMFLAG_AUTOCLOSURE: Begin completions, 1 items
// ARG_PARAMFLAG_AUTOCLOSURE-DAG: Pattern/ExprSpecific: {#autoclosureArg: Int#}[#Int#];
// ARG_PARAMFLAG_AUTOCLOSURE: End completions

testPamrameterFlags(intVal, inoutArg: &intVal, autoclosureArg: intVal, #^ARG_PARAMFLAG_IUO^#)
// ARG_PARAMFLAG_IUO: Begin completions, 1 items
// ARG_PARAMFLAG_IUO-DAG: Pattern/ExprSpecific: {#iuoArg: Int?#}[#Int?#];
// ARG_PARAMFLAG_IUO: End completions

testPamrameterFlags(intVal, inoutArg: &intVal, autoclosureArg: intVal, iuoArg: intVal, #^ARG_PARAMFLAG_VARIADIC^#)
// ARG_PARAMFLAG_VARIADIC: Begin completions, 1 items
// ARG_PARAMFLAG_VARIADIC-DAG: Pattern/ExprSpecific: {#variadicArg: Int...#}[#Int#];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you really don't like this. I can make it '[#Int...#]'. But I think this is OK because this specific argument itself is Int.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that Int is fine here.

// ARG_PARAMFLAG_VARIADIC: End completions
}
6 changes: 3 additions & 3 deletions test/IDE/complete_call_as_function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func testCallAsFunction(add: Adder, addTy: Adder.Type) {

let _ = add(x: 12, #^INSTANCE_ARG2^#)
// INSTANCE_ARG2: Begin completions, 1 items
// INSTANCE_ARG2: Keyword/ExprSpecific: y: [#Argument name#];
// INSTANCE_ARG2: Pattern/ExprSpecific: {#y: Int#}[#Int#];
// INSTANCE_ARG2: End completions

let _ = addTy#^METATYPE_NO_DOT^#;
Expand Down Expand Up @@ -105,8 +105,8 @@ func testCallAsFunctionOverloaded(fn: Functor) {
fn(h: .left, #^OVERLOADED_ARG2_LABEL^#)
// FIXME: Should only suggest 'v:' (rdar://problem/60346573).
//OVERLOADED_ARG2_LABEL: Begin completions, 2 items
//OVERLOADED_ARG2_LABEL-DAG: Keyword/ExprSpecific: v: [#Argument name#];
//OVERLOADED_ARG2_LABEL-DAG: Keyword/ExprSpecific: h: [#Argument name#];
//OVERLOADED_ARG2_LABEL-DAG: Pattern/ExprSpecific: {#v: Functor.Vertical#}[#Functor.Vertical#];
//OVERLOADED_ARG2_LABEL-DAG: Pattern/ExprSpecific: {#h: Functor.Horizontal#}[#Functor.Horizontal#];
//OVERLOADED_ARG2_LABEL: End completions

fn(h: .left, v: .#^OVERLOADED_ARG2_VALUE^#)
Expand Down
4 changes: 2 additions & 2 deletions test/IDE/complete_subscript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ func test2<U>(value: MyStruct<U>) {

let _ = MyStruct<U>[42, #^METATYPE_LABEL^#
// METATYPE_LABEL: Begin completions, 1 items
// METATYPE_LABEL-DAG: Keyword/ExprSpecific: static: [#Argument name#];
// METATYPE_LABEL-DAG: Pattern/ExprSpecific: {#static: U#}[#U#];
// METATYPE_LABEL: End completions

let _ = value[42, #^INSTANCE_LABEL^#
// INSTANCE_LABEL: Begin completions, 1 items
// INSTANCE_LABEL-DAG: Keyword/ExprSpecific: instance: [#Argument name#];
// INSTANCE_LABEL-DAG: Pattern/ExprSpecific: {#instance: U#}[#U#];
// INSTANCE_LABEL: End completions
}

Expand Down
2 changes: 1 addition & 1 deletion test/IDE/complete_value_expr.swift
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ func testInsideFunctionCall4() {
func testInsideFunctionCall5() {
FooStruct().instanceFunc2(42, #^INSIDE_FUNCTION_CALL_5^#
// INSIDE_FUNCTION_CALL_5: Begin completions
// INSIDE_FUNCTION_CALL_5-DAG: Keyword/ExprSpecific: b: [#Argument name#]; name=b:
// INSIDE_FUNCTION_CALL_5-DAG: Pattern/ExprSpecific: {#b: &Double#}[#inout Double#];
// INSIDE_FUNCTION_CALL_5: End completions
}

Expand Down