[CodeCompletion] Migrate postfix expr completion to solver-based

This commit is contained in:
Alex Hoppen
2023-03-14 16:37:14 -07:00
parent c385fe5e87
commit 00eaed3af9
25 changed files with 503 additions and 161 deletions

View File

@@ -519,7 +519,14 @@ public:
void getPostfixKeywordCompletions(Type ExprType, Expr *ParsedExpr);
void getValueExprCompletions(Type ExprType, ValueDecl *VD = nullptr);
/// Add code completion results after an expression of type \p ExprType.
/// This includes members as well as call patterns if \p ExprType is a
/// function type.
/// If \p IsDeclUnapplied is \c true, we are completing after a refernce to
/// \p VD that hasn't been called yet. Thus, \p VD has type \p ExprType and we
/// can use \p VD to enrich call pattern completions of \p ExprType.
void getValueExprCompletions(Type ExprType, ValueDecl *VD = nullptr,
bool IsDeclUnapplied = false);
void collectOperators(SmallVectorImpl<OperatorDecl *> &results);
@@ -529,7 +536,7 @@ public:
void tryPostfixOperator(Expr *expr, PostfixOperatorDecl *op);
void addAssignmentOperator(Type RHSType, Type resultType);
void addAssignmentOperator(Type RHSType);
void addInfixOperatorCompletion(OperatorDecl *op, Type resultType,
Type RHSType);

View File

@@ -20,9 +20,8 @@
namespace swift {
namespace ide {
/// Used to collect and store information needed to perform member completion
/// (\c CompletionKind::DotExpr ) from the solutions formed during expression
/// type-checking.
/// Used to collect and store information needed to perform postfix completion
/// (either <base>.#^COMPLETE^# or <base> #^COMPLETE^#).
class PostfixCompletionCallback : public TypeCheckCompletionCallback {
struct Result {
/// The type that we are completing on. Will never be null.
@@ -32,6 +31,11 @@ class PostfixCompletionCallback : public TypeCheckCompletionCallback {
/// on an expression.
ValueDecl *BaseDecl;
/// Whether \c BaseDecl refers to a function that has not been called yet.
/// In such cases, we know that \p BaseTy is the type of \p BaseDecl and we
/// can use \p BaseDecl for more detailed call pattern completions.
bool IsBaseDeclUnapplied;
/// If the expression we are completing on statically refers to a metatype,
/// that is if it's something like 'MyType'. In such cases we want to offer
/// constructor call pattern completions and don't want to suggeste
@@ -90,8 +94,18 @@ public:
/// \c sawSolution for each solution formed.
void fallbackTypeCheck(DeclContext *DC) override;
void deliverResults(Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc,
bool IsInSelector, CodeCompletionContext &CompletionCtx,
/// Deliver code completion results that were discoverd by \c sawSolution to
/// \p Consumer.
/// \param DotLoc If we are completing after a dot, the location of the dot,
/// otherwise an invalid SourceLoc.
/// \param IsInSelector Whether we are completing in an Objective-C selector.
/// \param IncludeOperators If operators should be suggested. Assumes that
/// \p DotLoc is invalid
/// \param HasLeadingSpace Whether there is a space separating the exiting
/// expression and the code completion token.
void deliverResults(SourceLoc DotLoc, bool IsInSelector,
bool IncludeOperators, bool HasLeadingSpace,
CodeCompletionContext &CompletionCtx,
CodeCompletionConsumer &Consumer);
};

View File

@@ -147,8 +147,9 @@ public:
/// Complete the \c in keyword in a for-each loop.
virtual void completeForEachInKeyword(){};
/// Complete a given expr-postfix.
virtual void completePostfixExpr(Expr *E, bool hasSpace) {};
/// Complete a expr-postfix. The \c CodeCompletionExpr has the expression it
/// is completing after set as its base.
virtual void completePostfixExpr(CodeCompletionExpr *E, bool hasSpace){};
/// Complete a given expr-postfix, given that there is a following
/// left parenthesis.

View File

@@ -259,7 +259,7 @@ public:
void completePostfixExprBeginning(CodeCompletionExpr *E) override;
void completeForEachSequenceBeginning(CodeCompletionExpr *E) override;
void completeForEachInKeyword() override;
void completePostfixExpr(Expr *E, bool hasSpace) override;
void completePostfixExpr(CodeCompletionExpr *E, bool hasSpace) override;
void completePostfixExprParen(Expr *E, Expr *CodeCompletionE) override;
void completeExprKeyPath(KeyPathExpr *KPE, SourceLoc DotLoc) override;
@@ -391,7 +391,8 @@ void CodeCompletionCallbacksImpl::completeForEachInKeyword() {
CurDeclContext = P.CurDeclContext;
}
void CodeCompletionCallbacksImpl::completePostfixExpr(Expr *E, bool hasSpace) {
void CodeCompletionCallbacksImpl::completePostfixExpr(CodeCompletionExpr *E,
bool hasSpace) {
assert(P.Tok.is(tok::code_complete));
// Don't produce any results in an enum element.
@@ -405,7 +406,8 @@ void CodeCompletionCallbacksImpl::completePostfixExpr(Expr *E, bool hasSpace) {
CompleteExprSelectorContext = ParseExprSelectorContext;
}
ParsedExpr = E;
ParsedExpr = E->getBase();
CodeCompleteTokenExpr = E;
CurDeclContext = P.CurDeclContext;
}
@@ -1469,6 +1471,7 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
};
switch (Kind) {
case CompletionKind::PostfixExpr:
case CompletionKind::DotExpr: {
assert(CodeCompleteTokenExpr);
assert(CurDeclContext);
@@ -1478,9 +1481,10 @@ bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
Expr *CheckedBase = CodeCompleteTokenExpr->getBase();
Lookup.deliverResults(CheckedBase, CurDeclContext, DotLoc,
isInsideObjCSelector(), CompletionContext, Consumer);
bool IncludeOperators = (Kind == CompletionKind::PostfixExpr);
Lookup.deliverResults(DotLoc, isInsideObjCSelector(), IncludeOperators,
HasSpace, CompletionContext, Consumer);
return true;
}
case CompletionKind::UnresolvedMember: {
@@ -1694,26 +1698,10 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
case CompletionKind::AccessorBeginning:
case CompletionKind::CaseStmtBeginning:
case CompletionKind::PostfixExprParen:
case CompletionKind::PostfixExpr:
llvm_unreachable("should be already handled");
return;
case CompletionKind::PostfixExpr: {
Lookup.setHaveLeadingSpace(HasSpace);
if (isDynamicLookup(*ExprType))
Lookup.setIsDynamicLookup();
Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
/// We set the type of ParsedExpr explicitly above. But we don't want an
/// unresolved type in our AST when we type check again for operator
/// completions. Remove the type of the ParsedExpr and see if we can come up
/// with something more useful based on the the full sequence expression.
if (ParsedExpr->getType()->is<UnresolvedType>()) {
ParsedExpr->setType(nullptr);
}
Lookup.getOperatorCompletions(ParsedExpr, leadingSequenceExprs);
Lookup.getPostfixKeywordCompletions(*ExprType, ParsedExpr);
break;
}
case CompletionKind::KeyPathExprObjC: {
if (DotLoc.isValid())
Lookup.setHaveDot(DotLoc);
@@ -1724,7 +1712,8 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
if (isDynamicLookup(*ExprType))
Lookup.setIsDynamicLookup();
Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl(),
/*IncludeFunctionCallCompletions=*/true);
} else {
SourceLoc Loc = P.Context.SourceMgr.getIDEInspectionTargetLoc();
Lookup.getValueCompletionsInDeclContext(Loc, KeyPathFilter,
@@ -1949,7 +1938,8 @@ void CodeCompletionCallbacksImpl::doneParsing(SourceFile *SrcFile) {
if (isDynamicLookup(resultTy))
Lookup.setIsDynamicLookup();
Lookup.getValueExprCompletions(resultTy, /*VD=*/nullptr);
Lookup.getValueExprCompletions(resultTy, /*VD=*/nullptr,
/*IncludeFunctionCallCompletions=*/true);
Lookup.getOperatorCompletions(analyzedExpr, leadingSequenceExprs);
Lookup.getPostfixKeywordCompletions(resultTy, analyzedExpr);
}

View File

@@ -2307,6 +2307,8 @@ void CompletionLookup::getPostfixKeywordCompletions(Type ExprType,
if (IsSuperRefExpr)
return;
NeedLeadingDot = !HaveDot;
if (!ExprType->getAs<ModuleType>()) {
addKeyword(getTokenText(tok::kw_self), ExprType->getRValueType(),
SemanticContextKind::CurrentNominal,
@@ -2329,7 +2331,8 @@ void CompletionLookup::getPostfixKeywordCompletions(Type ExprType,
}
}
void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD) {
void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD,
bool IsDeclUnapplied) {
Kind = LookupKind::ValueExpr;
NeedLeadingDot = !HaveDot;
@@ -2362,7 +2365,7 @@ void CompletionLookup::getValueExprCompletions(Type ExprType, ValueDecl *VD) {
// Handle special cases
bool isIUO = VD && VD->isImplicitlyUnwrappedOptional();
if (tryFunctionCallCompletions(ExprType, VD))
if (tryFunctionCallCompletions(ExprType, IsDeclUnapplied ? VD : nullptr))
return;
if (tryModuleCompletions(ExprType, {CodeCompletionFilterFlag::Expr,
CodeCompletionFilterFlag::Type}))
@@ -2425,7 +2428,7 @@ void CompletionLookup::tryPostfixOperator(Expr *expr, PostfixOperatorDecl *op) {
addPostfixOperatorCompletion(op, funcTy->getResult());
}
void CompletionLookup::addAssignmentOperator(Type RHSType, Type resultType) {
void CompletionLookup::addAssignmentOperator(Type RHSType) {
CodeCompletionResultBuilder builder = makeResultBuilder(
CodeCompletionResultKind::BuiltinOperator, SemanticContextKind::None);
@@ -2435,12 +2438,11 @@ void CompletionLookup::addAssignmentOperator(Type RHSType, Type resultType) {
builder.addWhitespace(" ");
builder.addEqual();
builder.addWhitespace(" ");
assert(RHSType && resultType);
assert(RHSType);
Type contextTy;
if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
contextTy = typeContext->getDeclaredTypeInContext();
builder.addCallArgument(Identifier(), RHSType, contextTy);
addTypeAnnotation(builder, resultType);
}
void CompletionLookup::addInfixOperatorCompletion(OperatorDecl *op,
@@ -2559,8 +2561,7 @@ void CompletionLookup::getOperatorCompletions(
if (leadingSequence.empty() && LHS->getType() &&
LHS->getType()->hasLValueType()) {
addAssignmentOperator(LHS->getType()->getRValueType(),
CurrDeclContext->getASTContext().TheEmptyTupleType);
addAssignmentOperator(LHS->getType()->getRValueType());
}
// FIXME: unify this with the ?.member completions.

View File

@@ -47,7 +47,7 @@ public:
// Only handle callbacks for suffix completions.
// {
void completeDotExpr(CodeCompletionExpr *E, SourceLoc DotLoc) override;
void completePostfixExpr(Expr *E, bool hasSpace) override;
void completePostfixExpr(CodeCompletionExpr *E, bool hasSpace) override;
// }
void doneParsing(SourceFile *SrcFile) override;
@@ -59,10 +59,10 @@ void ConformingMethodListCallbacks::completeDotExpr(CodeCompletionExpr *E,
ParsedExpr = E->getBase();
}
void ConformingMethodListCallbacks::completePostfixExpr(Expr *E,
void ConformingMethodListCallbacks::completePostfixExpr(CodeCompletionExpr *E,
bool hasSpace) {
CurDeclContext = P.CurDeclContext;
ParsedExpr = E;
ParsedExpr = E->getBase();
}
void ConformingMethodListCallbacks::doneParsing(SourceFile *SrcFile) {

View File

@@ -38,6 +38,7 @@ void PostfixCompletionCallback::Result::merge(const Result &Other,
DeclContext &DC) {
assert(canBeMergedWith(Other, DC));
// These properties should match if we are talking about the same BaseDecl.
assert(IsBaseDeclUnapplied == Other.IsBaseDeclUnapplied);
assert(BaseIsStaticMetaType == Other.BaseIsStaticMetaType);
if (!BaseTy->isEqual(Other.BaseTy) &&
@@ -126,6 +127,29 @@ getClosureActorIsolation(const Solution &S, AbstractClosureExpr *ACE) {
getClosureActorIsolationThunk);
}
/// Returns \c true if \p Choice refers to a function that hasn't been called
/// yet.
static bool isUnappliedFunctionRef(const OverloadChoice &Choice) {
if (!Choice.isDecl()) {
return false;
}
switch (Choice.getFunctionRefKind()) {
case FunctionRefKind::Unapplied:
return true;
case FunctionRefKind::SingleApply:
if (auto BaseTy = Choice.getBaseType()) {
// We consider curried member calls as unapplied. E.g.
// MyStruct.someInstanceFunc(theInstance)#^COMPLETE^#
// is unapplied.
return BaseTy->is<MetatypeType>();
} else {
return false;
}
default:
return false;
}
}
void PostfixCompletionCallback::sawSolutionImpl(
const constraints::Solution &S) {
auto &CS = S.getConstraintSystem();
@@ -147,16 +171,10 @@ void PostfixCompletionCallback::sawSolutionImpl(
auto *CalleeLocator = S.getCalleeLocator(Locator);
ValueDecl *ReferencedDecl = nullptr;
if (auto SelectedOverload = S.getOverloadChoiceIfAvailable(CalleeLocator))
bool IsBaseDeclUnapplied = false;
if (auto SelectedOverload = S.getOverloadChoiceIfAvailable(CalleeLocator)) {
ReferencedDecl = SelectedOverload->choice.getDeclOrNull();
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
ClosureActorIsolations;
bool IsAsync = isContextAsync(S, DC);
for (auto SAT : S.targets) {
if (auto ACE = getAsExpr<AbstractClosureExpr>(SAT.second.getAsASTNode())) {
ClosureActorIsolations[ACE] = getClosureActorIsolation(S, ACE);
}
IsBaseDeclUnapplied = isUnappliedFunctionRef(SelectedOverload->choice);
}
bool BaseIsStaticMetaType = S.isStaticallyDerivedMetatype(ParsedExpr);
@@ -184,30 +202,204 @@ void PostfixCompletionCallback::sawSolutionImpl(
bool IsImplicitSingleExpressionReturn =
isImplicitSingleExpressionReturn(CS, CompletionExpr);
bool IsInAsyncContext = isContextAsync(S, DC);
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
ClosureActorIsolations;
for (auto SAT : S.targets) {
if (auto ACE = getAsExpr<AbstractClosureExpr>(SAT.second.getAsASTNode())) {
ClosureActorIsolations[ACE] = getClosureActorIsolation(S, ACE);
}
}
Result Res = {
BaseTy,
ReferencedDecl,
IsBaseDeclUnapplied,
BaseIsStaticMetaType,
ExpectedTypes,
ExpectsNonVoid,
IsImplicitSingleExpressionReturn,
IsAsync,
IsInAsyncContext,
ClosureActorIsolations
};
addResult(Res);
}
/// Returns \c true if \p T is '_OptionalNilComparisonType'.
static bool isOptionalNilComparisonType(Type T) {
if (!T) {
return false;
}
auto *nominal = T->getAnyNominal();
if (!nominal) {
return false;
}
return (nominal->isStdlibDecl() &&
nominal->getName() ==
nominal->getASTContext().Id_OptionalNilComparisonType);
}
static DeclRefKind getDeclRefKindOfOperator(OperatorDecl *op) {
switch (op->getKind()) {
case DeclKind::PrefixOperator:
return DeclRefKind::PrefixOperator;
case DeclKind::PostfixOperator:
return DeclRefKind::PostfixOperator;
case DeclKind::InfixOperator:
return DeclRefKind::BinaryOperator;
default:
llvm_unreachable("unexpected operator kind");
}
}
/// Return type of \c getOperatorCompletionTypes.
struct OperatorResultTypes {
/// If we are trying to complete a binary operator, the type the operator
/// expects for the RHS. Null for postfix operators.
Type RHSType;
/// The type the operator returns when called.
Type ResultType;
bool operator==(const OperatorResultTypes &Other) const {
return nullableTypesEqual(RHSType, Other.RHSType) &&
nullableTypesEqual(ResultType, Other.ResultType);
}
};
/// Builds a constriant system that tries applying the operator \p op on a LHS
/// of type \p LHSType. If that succeeds, returns the result type of the
/// operator call and (in case of binary operators) the expected type for the
/// RHS.
static SmallVector<OperatorResultTypes>
getOperatorCompletionTypes(DeclContext *DC, Type LHSType, OperatorDecl *Op) {
ConstraintSystemOptions options;
options |= ConstraintSystemFlags::SuppressDiagnostics;
ConstraintSystem CS(DC, options);
// The source loc of the generated expression doesn't matter.
SourceLoc Loc;
// We represent the LHS and RHS by CodeCompletionExprs because there's no
// other better choice. rhs will have its type set in the constraint system
// below and, in case of binary operators, rhs will be inspected for its type
// when the constraint system has been solved.
CodeCompletionExpr LHS(Loc);
CodeCompletionExpr RHS(Loc);
UnresolvedDeclRefExpr UDRE(DeclNameRef(Op->getName()),
getDeclRefKindOfOperator(Op), DeclNameLoc(Loc));
DiagnosticTransaction IgnoreDiags(DC->getASTContext().Diags);
Expr *OpExpr =
resolveDeclRefExpr(&UDRE, DC, /*replaceInvalidRefsWithErrors=*/true);
IgnoreDiags.abort();
if (isa<ErrorExpr>(OpExpr)) {
// If we couldn't resolve the operator (e.g. because there is only an
// operator definition but no decls that implement it), we can't call the
// operator.
return {};
}
Expr *OpCallExpr;
switch (Op->getKind()) {
case DeclKind::PrefixOperator:
// Don't insert prefix operators in postfix position.
return {};
case DeclKind::PostfixOperator:
OpCallExpr = PostfixUnaryExpr::create(DC->getASTContext(), OpExpr, &LHS);
break;
case DeclKind::InfixOperator:
OpCallExpr = BinaryExpr::create(DC->getASTContext(), &LHS, OpExpr, &RHS,
/*implicit*/ true);
break;
default:
llvm_unreachable("unexpected operator kind");
}
CS.preCheckExpression(OpCallExpr, DC, /*replaceInvalidRefsWithErrors=*/true,
/*leaveClosureBodyUnchecked=*/false);
OpCallExpr = CS.generateConstraints(OpCallExpr, DC);
CS.assignFixedType(CS.getType(&LHS)->getAs<TypeVariableType>(), LHSType);
SmallVector<Solution, 1> Solutions;
CS.solve(Solutions);
SmallVector<OperatorResultTypes> Results;
for (auto &S : Solutions) {
Type RHSType;
if (Op->getKind() == DeclKind::InfixOperator) {
RHSType = getTypeForCompletion(S, &RHS);
}
Type ResultType = getTypeForCompletion(S, OpCallExpr);
OperatorResultTypes ResultTypes = {RHSType, ResultType};
if (llvm::is_contained(Results, ResultTypes)) {
continue;
}
if (S.getFixedScore().Data[SK_ValueToOptional] > 0) {
if (Op->getName().str() == "??" || isOptionalNilComparisonType(RHSType)) {
// Don't suggest optional operators that need to demote the LHS to an
// Optional to become applicable.
continue;
}
}
Results.push_back(ResultTypes);
}
return Results;
}
/// Adds applicable operator suggestions to \p Lookup.
static void addOperatorResults(Type LHSType, ArrayRef<OperatorDecl *> Operators,
DeclContext *DC, CompletionLookup &Lookup) {
for (auto Op : Operators) {
switch (Op->getKind()) {
case DeclKind::PrefixOperator:
break;
case DeclKind::PostfixOperator:
for (auto operatorType : getOperatorCompletionTypes(DC, LHSType, Op)) {
Lookup.addPostfixOperatorCompletion(Op, operatorType.ResultType);
}
break;
case DeclKind::InfixOperator:
for (auto operatorType : getOperatorCompletionTypes(DC, LHSType, Op)) {
Lookup.addInfixOperatorCompletion(Op, operatorType.ResultType,
operatorType.RHSType);
}
break;
default:
llvm_unreachable("unexpected operator kind");
}
}
if (LHSType->hasLValueType()) {
Lookup.addAssignmentOperator(LHSType->getRValueType());
}
if (auto ValueT = LHSType->getRValueType()->getOptionalObjectType()) {
Lookup.addPostfixBang(ValueT);
}
}
void PostfixCompletionCallback::deliverResults(
Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
CodeCompletionContext &CompletionCtx, CodeCompletionConsumer &Consumer) {
SourceLoc DotLoc, bool IsInSelector, bool IncludeOperators,
bool HasLeadingSpace, CodeCompletionContext &CompletionCtx,
CodeCompletionConsumer &Consumer) {
ASTContext &Ctx = DC->getASTContext();
CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
&CompletionCtx);
if (DotLoc.isValid())
if (DotLoc.isValid()) {
assert(!IncludeOperators && "We shouldn't be suggesting operators if we "
"are completing after a dot");
Lookup.setHaveDot(DotLoc);
}
Lookup.setHaveLeadingSpace(HasLeadingSpace);
Expr *BaseExpr = CompletionExpr->getBase();
Lookup.setIsSuperRefExpr(isa<SuperRefExpr>(BaseExpr));
if (auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
@@ -220,6 +412,10 @@ void PostfixCompletionCallback::deliverResults(
Lookup.includeInstanceMembers();
Lookup.setPreferFunctionReferencesToCalls();
}
SmallVector<OperatorDecl *> Operators;
if (IncludeOperators) {
Lookup.collectOperators(Operators);
}
Lookup.shouldCheckForDuplicates(Results.size() > 1);
for (auto &Result : Results) {
@@ -232,7 +428,12 @@ void PostfixCompletionCallback::deliverResults(
Result.ExpectsNonVoid);
if (isDynamicLookup(Result.BaseTy))
Lookup.setIsDynamicLookup();
Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl);
Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl,
Result.IsBaseDeclUnapplied);
if (IncludeOperators && !Result.BaseIsStaticMetaType) {
addOperatorResults(Result.BaseTy, Operators, DC, Lookup);
}
}
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);

View File

@@ -1491,9 +1491,20 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic,
return Result;
}
if (CodeCompletionCallbacks && Result.isNonNull()) {
// FIXME: We should be able to remove the InBindingPattern checks once
// apple/swift#64280 is merged.
if (CodeCompletionCallbacks && Result.isNonNull() &&
InBindingPattern != PatternBindingState::ImplicitlyImmutable &&
InBindingPattern != PatternBindingState::InVar &&
InBindingPattern != PatternBindingState::InLet) {
// Don't do postfix completions when in a binding pattern. It doesn't
// make sense to offer completions eg. in
// if let myVar#^COMPLETE^# = someOptional {}
bool hasSpace = Tok.getLoc() != getEndOfPreviousLoc();
CodeCompletionCallbacks->completePostfixExpr(Result.get(), hasSpace);
auto CCExpr =
new (Context) CodeCompletionExpr(Result.get(), Tok.getLoc());
CodeCompletionCallbacks->completePostfixExpr(CCExpr, hasSpace);
Result = makeParserResult(Result, CCExpr);
}
// Eat the code completion token because we handled it.
consumeToken(tok::code_complete);

View File

@@ -515,7 +515,7 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(
// If we have a locator that starts with a key path component element, we
// may have a callee given by a property or subscript component.
if (auto componentElt =
locator->getFirstElementAs<LocatorPathElt::KeyPathComponent>()) {
locator->getFirstElementAs<LocatorPathElt::KeyPathComponent>()) {
auto *kpExpr = castToExpr<KeyPathExpr>(anchor);
auto component = kpExpr->getComponents()[componentElt->getIndex()];
@@ -525,7 +525,7 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(
case ComponentKind::Subscript:
// For a subscript the callee is given by 'component -> subscript member'.
return getConstraintLocator(
anchor, {*componentElt, ConstraintLocator::SubscriptMember});
anchor, {*componentElt, ConstraintLocator::SubscriptMember});
case ComponentKind::UnresolvedProperty:
case ComponentKind::Property:
// For a property, the choice is just given by the component.
@@ -563,14 +563,14 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(
if (fnTy->is<AnyMetatypeType>()) {
return getConstraintLocator(anchor,
{LocatorPathElt::ApplyFunction(),
LocatorPathElt::ConstructorMember()});
LocatorPathElt::ConstructorMember()});
}
// Handle an apply of a nominal type which supports callAsFunction.
if (fnTy->isCallAsFunctionType(DC)) {
return getConstraintLocator(anchor,
{LocatorPathElt::ApplyFunction(),
LocatorPathElt::ImplicitCallAsFunction()});
LocatorPathElt::ImplicitCallAsFunction()});
}
// Handling an apply for a nominal type that supports @dynamicCallable.
@@ -605,13 +605,13 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(
UDE->getName().getBaseName() == Context.Id_callAsFunction) {
return getConstraintLocator(anchor,
{LocatorPathElt::ApplyFunction(),
LocatorPathElt::ImplicitCallAsFunction()});
LocatorPathElt::ImplicitCallAsFunction()});
}
return getConstraintLocator(
anchor, TypeChecker::getSelfForInitDelegationInConstructor(DC, UDE)
? ConstraintLocator::ConstructorMember
: ConstraintLocator::Member);
anchor, TypeChecker::getSelfForInitDelegationInConstructor(DC, UDE)
? ConstraintLocator::ConstructorMember
: ConstraintLocator::Member);
}
if (auto *UME = getAsExpr<UnresolvedMemberExpr>(anchor)) {
@@ -632,6 +632,9 @@ ConstraintLocator *ConstraintSystem::getCalleeLocator(
getOverloadFor);
}
if (auto FVE = getAsExpr<ForceValueExpr>(anchor))
return getConstraintLocator(FVE->getSubExpr(), ConstraintLocator::Member);
return getConstraintLocator(anchor);
}

View File

@@ -116,8 +116,17 @@ class SuperDerivedA : SuperBaseA {
init() {
super#^CONSTRUCTOR_SUPER_NO_DOT_1?check=COMMON_BASE_A_NO_DOT;check=CONSTRUCTOR_SUPER_NO_DOT_1^#
// CONSTRUCTOR_SUPER_NO_DOT_1: Begin completions, 8 items
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[Constructor]/CurrNominal/Flair[SuperChain]: .init()[#SuperBaseA#]{{; name=.+$}}
// CONSTRUCTOR_SUPER_NO_DOT_1: Begin completions, 10 items
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseInstanceVar[#Int#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseProp[#Int#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc0()[#Void#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc1({#(a): Int#})[#Void#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[Subscript]/CurrNominal: [{#(i): Int#}][#Double#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[Constructor]/CurrNominal/Flair[SuperChain]: .init()[#SuperBaseA#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseExtProp[#Int#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseExtFunc0()[#Void#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: !== {#AnyObject?#}[#Bool#];
// CONSTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: === {#AnyObject?#}[#Bool#];
}
init(a: Int) {
@@ -136,17 +145,26 @@ class SuperDerivedA : SuperBaseA {
init (a: Float) {
super.init#^CONSTRUCTOR_SUPER_INIT_1^#
// CONSTRUCTOR_SUPER_INIT_1-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ()[#SuperBaseA#]; name=()
// CONSTRUCTOR_SUPER_INIT_1-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ()[#SuperBaseA#];
}
init (b: Float) {
super.init(#^CONSTRUCTOR_SUPER_INIT_PAREN_1^#
// CONSTRUCTOR_SUPER_INIT_PAREN_1: Begin completions, 1 items
// CONSTRUCTOR_SUPER_INIT_PAREN_1: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['('][')'][#SuperBaseA#]; name=
// CONSTRUCTOR_SUPER_INIT_PAREN_1: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['('][')'][#SuperBaseA#];
}
deinit {
super#^DESTRUCTOR_SUPER_NO_DOT_1?check=COMMON_BASE_A_NO_DOT;check=DESTRUCTOR_SUPER_NO_DOT_1;check=NO_CONSTRUCTORS^#
// DESTRUCTOR_SUPER_NO_DOT_1: Begin completions, 7 items
// DESTRUCTOR_SUPER_NO_DOT_1: Begin completions, 9 items
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseInstanceVar[#Int#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseProp[#Int#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc0()[#Void#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc1({#(a): Int#})[#Void#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[Subscript]/CurrNominal: [{#(i): Int#}][#Double#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseExtProp[#Int#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseExtFunc0()[#Void#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: !== {#AnyObject?#}[#Bool#];
// DESTRUCTOR_SUPER_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: === {#AnyObject?#}[#Bool#];
var resyncParser = 42
@@ -156,7 +174,16 @@ class SuperDerivedA : SuperBaseA {
func test1() {
super#^FUNC_SUPER_NO_DOT_1?check=COMMON_BASE_A_NO_DOT;check=FUNC_SUPER_NO_DOT_1;check=NO_CONSTRUCTORS^#
// FUNC_SUPER_NO_DOT_1: Begin completions, 7 items
// FUNC_SUPER_NO_DOT_1: Begin completions, 9 items
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseInstanceVar[#Int#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseProp[#Int#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc0()[#Void#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc1({#(a): Int#})[#Void#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[Subscript]/CurrNominal: [{#(i): Int#}][#Double#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InstanceVar]/CurrNominal: .baseExtProp[#Int#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal: .baseExtFunc0()[#Void#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: !== {#AnyObject?#}[#Bool#];
// FUNC_SUPER_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: === {#AnyObject?#}[#Bool#];
}
func test2() {
@@ -271,10 +298,19 @@ class SuperDerivedB : SuperBaseB {
init() {
super#^CONSTRUCTOR_SUPER_NO_DOT_2?check=COMMON_BASE_B_NO_DOT;check=CONSTRUCTOR_SUPER_NO_DOT_2^#
// CONSTRUCTOR_SUPER_NO_DOT_2: Begin completions, 10 items
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Constructor]/CurrNominal/Flair[SuperChain]: .init()[#SuperBaseB#]{{; name=.+$}}
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Constructor]/CurrNominal: .init({#a: Double#})[#SuperBaseB#]{{; name=.+$}}
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Constructor]/CurrNominal: .init({#int: Int#})[#SuperBaseB#]{{; name=.+$}}
// CONSTRUCTOR_SUPER_NO_DOT_2: Begin completions, 12 items
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseInstanceVar[#Int#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseProp[#Int#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Constructor]/CurrNominal/Flair[SuperChain]: .init()[#SuperBaseB#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Constructor]/CurrNominal: .init({#a: Double#})[#SuperBaseB#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Constructor]/CurrNominal: .init({#int: Int#})[#SuperBaseB#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc0()[#Void#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc1({#(a): Int#})[#Void#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Subscript]/CurrNominal: [{#(i): Int#}][#Double#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseExtProp[#Int#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseExtFunc0()[#Void#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: !== {#AnyObject?#}[#Bool#];
// CONSTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: === {#AnyObject?#}[#Bool#];
}
init(int a: Int) {
@@ -287,17 +323,41 @@ class SuperDerivedB : SuperBaseB {
deinit {
super#^DESTRUCTOR_SUPER_NO_DOT_2?check=COMMON_BASE_B_NO_DOT;check=DESTRUCTOR_SUPER_NO_DOT_2;check=NO_CONSTRUCTORS^#
// DESTRUCTOR_SUPER_NO_DOT_2: Begin completions, 7 items
// DESTRUCTOR_SUPER_NO_DOT_2: Begin completions, 9 items
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseInstanceVar[#Int#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseProp[#Int#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc0()[#Void#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc1({#(a): Int#})[#Void#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[Subscript]/CurrNominal: [{#(i): Int#}][#Double#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseExtProp[#Int#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseExtFunc0()[#Void#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: !== {#AnyObject?#}[#Bool#];
// DESTRUCTOR_SUPER_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: === {#AnyObject?#}[#Bool#];
var resyncParser = 42
super.#^DESTRUCTOR_SUPER_DOT_2?check=COMMON_BASE_B_DOT;check=DESTRUCTOR_SUPER_DOT_2;check=NO_CONSTRUCTORS^#
// DESTRUCTOR_SUPER_DOT_2: Begin completions, 6 items
// DESTRUCTOR_SUPER_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: baseInstanceVar[#Int#];
// DESTRUCTOR_SUPER_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: baseProp[#Int#];
// DESTRUCTOR_SUPER_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: baseFunc0()[#Void#];
// DESTRUCTOR_SUPER_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: baseFunc1({#(a): Int#})[#Void#];
// DESTRUCTOR_SUPER_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: baseExtProp[#Int#];
// DESTRUCTOR_SUPER_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: baseExtFunc0()[#Void#];
}
func test1() {
super#^FUNC_SUPER_NO_DOT_2?check=COMMON_BASE_B_NO_DOT;check=FUNC_SUPER_NO_DOT_2;check=NO_CONSTRUCTORS^#
// FUNC_SUPER_NO_DOT_2: Begin completions, 7 items
// FUNC_SUPER_NO_DOT_2: Begin completions, 9 items
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseInstanceVar[#Int#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseProp[#Int#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc0()[#Void#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseFunc1({#(a): Int#})[#Void#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[Subscript]/CurrNominal: [{#(i): Int#}][#Double#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InstanceVar]/CurrNominal: .baseExtProp[#Int#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InstanceMethod]/CurrNominal: .baseExtFunc0()[#Void#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: !== {#AnyObject?#}[#Bool#];
// FUNC_SUPER_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: === {#AnyObject?#}[#Bool#];
}
func test2() {

View File

@@ -51,8 +51,9 @@ func testCallAsFunctionDeduplication() {
overloaded()#^SKIP_CALLASFUNCTION_DUPLICATES^#
}
// FIXME: Update this to check the callAsFunction pattern only appears once when PostfixExpr completion is migrated to the solver-based implementation (which handles ambiguity).
// SKIP_CALLASFUNCTION_DUPLICATES-NOT: Begin completions
// SKIP_CALLASFUNCTION_DUPLICATES: Begin completions
// SKIP_CALLASFUNCTION_DUPLICATES-DAG: Decl[InstanceMethod]/CurrNominal: .callAsFunction({#x: Int#})[#Void#];
// SKIP_CALLASFUNCTION_DUPLICATES: End completions
givenErrorExpr(undefined).#^ERROR_IN_BASE?check=SIMPLE^#

View File

@@ -40,7 +40,7 @@ func resyncParser1() {}
fooObject#^TYPE_CHECKED_EXPR_1^#
// TYPE_CHECKED_EXPR_1-DAG: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_1-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc({#(a): Int#})[#Void#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_1-DAG: BuiltinOperator/None: = {#FooStruct#}[#Void#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_1-DAG: BuiltinOperator/None: = {#FooStruct#}{{; name=.+$}}
// TYPE_CHECKED_EXPR_1-DAG: Keyword[self]/CurrNominal: .self[#FooStruct#]{{; name=.+$}}
func resyncParser2() {}
@@ -51,7 +51,7 @@ var _tmpVar1 : FooStruct
fooObject#^TYPE_CHECKED_EXPR_2^#
// TYPE_CHECKED_EXPR_2-DAG: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_2-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc({#(a): Int#})[#Void#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_2-DAG: BuiltinOperator/None: = {#FooStruct#}[#Void#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_2-DAG: BuiltinOperator/None: = {#FooStruct#}{{; name=.+$}}
// TYPE_CHECKED_EXPR_2-DAG: Keyword[self]/CurrNominal: .self[#FooStruct#]{{; name=.+$}}
func resyncParser3() {}
@@ -59,7 +59,7 @@ func resyncParser3() {}
fooObject#^TYPE_CHECKED_EXPR_3^#.bar
// TYPE_CHECKED_EXPR_3-DAG: Decl[InstanceVar]/CurrNominal: .instanceVar[#Int#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_3-DAG: Decl[InstanceMethod]/CurrNominal: .instanceFunc({#(a): Int#})[#Void#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_3-DAG: BuiltinOperator/None: = {#FooStruct#}[#Void#]{{; name=.+$}}
// TYPE_CHECKED_EXPR_3-DAG: BuiltinOperator/None: = {#FooStruct#}{{; name=.+$}}
// TYPE_CHECKED_EXPR_3-DAG: Keyword[self]/CurrNominal: .self[#FooStruct#]{{; name=.+$}}
func resyncParser4() {}

View File

@@ -39,11 +39,13 @@ func testCallAsFunction(add: Adder, addTy: Adder.Type) {
// INSTANCE_ARG2: Pattern/Local/Flair[ArgLabels]: {#y: Int#}[#Int#];
let _ = addTy#^METATYPE_NO_DOT^#;
// METATYPE_NO_DOT: Begin completions, 3 items
// METATYPE_NO_DOT: Begin completions, 5 items
// METATYPE_NO_DOT-NOT: {#x: Int#}, {#y: Int#}
// METATYPE_NO_DOT-DAG: Decl[InstanceMethod]/CurrNominal: .callAsFunction({#(self): Adder#})[#(x: Int, y: Int) -> Int#];
// METATYPE_NO_DOT-DAG: Decl[Constructor]/CurrNominal: .init({#base: Int#})[#Adder#];
// METATYPE_NO_DOT-DAG: Keyword[self]/CurrNominal: .self[#Adder.Type#];
// METATYPE_NO_DOT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#Any.Type?#}[#Bool#];
// METATYPE_NO_DOT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#Any.Type?#}[#Bool#];
let _ = addTy.#^METATYPE_DOT^#;
// METATYPE_DOT: Begin completions, 3 items

View File

@@ -213,8 +213,6 @@ func foo_38149042(bar: Bar_38149042) {
}
// RDAR_38149042-DAG: Decl[InstanceVar]/CurrNominal: .x[#Int#]; name=x
// RDAR_38149042-DAG: Keyword[self]/CurrNominal: .self[#Baz_38149042#]; name=self
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']=== {#AnyObject?#}[#Bool#]; name====
// RDAR_38149042-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']!== {#AnyObject?#}[#Bool#]; name=!==
// rdar://problem/38272904
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=RDAR_38272904 | %FileCheck %s -check-prefix=RDAR_38272904
@@ -239,7 +237,7 @@ func foo_38272904(a: A_38272904) {
// rdar://problem/41159258
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_1 | %FileCheck %s -check-prefix=RDAR_41159258
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_2 | %FileCheck %s -check-prefix=RDAR_41159258
// RUN: %target-swift-ide-test -code-completion -source-filename=%s -code-completion-token=RDAR41159258_2
public func ==(lhs: RDAR41159258_MyResult1, rhs: RDAR41159258_MyResult1) -> Bool {
fatalError()
}
@@ -278,15 +276,15 @@ public final class IntStore {
_ = true ? 1 : provider.nextInt() #^RDAR41232519_2^#
}
}
// RDAR_41232519: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']+ {#Int#}[#Int#]; name=+
// RDAR_41232519: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: [' ']+ {#Int#}[#Int#]; name=+
// rdar://problem/28188259
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_28188259 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_28188259
func test_28188259(x: ((Int) -> Void) -> Void) {
x({_ in }#^RDAR_28188259^#)
}
// RDAR_28188259-DAG: Pattern/CurrModule/Flair[ArgLabels]: ({#Int#})[#Void#]; name=()
// RDAR_28188259-DAG: Keyword[self]/CurrNominal: .self[#(Int) -> ()#]; name=self
// RDAR_28188259-DAG: Pattern/CurrModule/Flair[ArgLabels]/TypeRelation[Invalid]: ({#_#})[#Void#]; name=()
// RDAR_28188259-DAG: Keyword[self]/CurrNominal: .self[#(_) -> ()#]; name=self
// rdar://problem/40956846
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_40956846 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_40956846
@@ -341,14 +339,13 @@ extension Foo {
// RDAR_41234606-DAG: Decl[AssociatedType]/CurrNominal/IsSystem: .Iterator; name=Iterator
// rdar://problem/41071587
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_41071587 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_41071587
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_41071587 -source-filename=%s
func test_41071587(x: Any) {
switch x {
case (let (_, _)) #^RDAR_41071587^#:
()
}
}
// RDAR_41071587: Begin completions
// rdar://problem/54215016
// RUN: %target-swift-ide-test -code-completion -code-completion-token=RDAR_54215016 -source-filename=%s | %FileCheck %s -check-prefix=RDAR_54215016

View File

@@ -99,7 +99,7 @@ enum BarEnum {
// BAR_ENUM_NO_DOT-DAG: Decl[EnumElement]/CurrNominal: .Bar12({#Int#}, {#(Float, Double)#})[#BarEnum#]{{; name=.+$}}
// BAR_ENUM_NO_DOT-DAG: Decl[InstanceMethod]/CurrNominal: .barInstanceFunc({#(self): &BarEnum#})[#() -> Void#]{{; name=.+$}}
// BAR_ENUM_NO_DOT-DAG: Decl[StaticVar]/CurrNominal: .staticVar[#Int#]{{; name=.+$}}
// BAR_ENUM_NO_DOT-DAG: Decl[StaticMethod]/CurrNominal: .barStaticFunc()[#Void#]{{; name=.+$}}
// BAR_ENUM_NO_DOT-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Invalid]: .barStaticFunc()[#Void#]{{; name=.+$}}
// BAR_ENUM_NO_DOT-DAG: Keyword[self]/CurrNominal: .self[#BarEnum.Type#]; name=self
// BAR_ENUM_NO_DOT-DAG: Keyword/CurrNominal: .Type[#BarEnum.Type#]; name=Type
@@ -141,7 +141,7 @@ enum BazEnum<T> {
// BAZ_INT_ENUM_NO_DOT-DAG: Decl[InstanceMethod]/CurrNominal: .bazInstanceFunc({#(self): &BazEnum<Int>#})[#() -> Void#]{{; name=.+$}}
// BAZ_INT_ENUM_NO_DOT-DAG: Decl[StaticVar]/CurrNominal: .staticVar[#Int#]{{; name=.+$}}
// BAZ_INT_ENUM_NO_DOT-DAG: Decl[StaticVar]/CurrNominal: .staticVarT[#Int#]{{; name=.+$}}
// BAZ_INT_ENUM_NO_DOT-DAG: Decl[StaticMethod]/CurrNominal: .bazStaticFunc()[#Void#]{{; name=.+$}}
// BAZ_INT_ENUM_NO_DOT-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Invalid]: .bazStaticFunc()[#Void#]{{; name=.+$}}
// BAZ_INT_ENUM_NO_DOT-DAG: Keyword[self]/CurrNominal: .self[#BazEnum<Int>.Type#]; name=self
// BAZ_INT_ENUM_NO_DOT-DAG: Keyword/CurrNominal: .Type[#BazEnum<Int>.Type#]; name=Type
@@ -150,7 +150,7 @@ enum BazEnum<T> {
// BAZ_T_ENUM_NO_DOT-DAG: Decl[InstanceMethod]/CurrNominal: .bazInstanceFunc({#(self): &BazEnum<_>#})[#() -> Void#]{{; name=.+$}}
// BAZ_T_ENUM_NO_DOT-DAG: Decl[StaticVar]/CurrNominal: .staticVar[#Int#]{{; name=.+$}}
// BAZ_T_ENUM_NO_DOT-DAG: Decl[StaticVar]/CurrNominal: .staticVarT[#_#]{{; name=.+$}}
// BAZ_T_ENUM_NO_DOT-DAG: Decl[StaticMethod]/CurrNominal: .bazStaticFunc()[#Void#]{{; name=.+$}}
// BAZ_T_ENUM_NO_DOT-DAG: Decl[StaticMethod]/CurrNominal/TypeRelation[Invalid]: .bazStaticFunc()[#Void#]{{; name=.+$}}
// BAZ_T_ENUM_NO_DOT-DAG: Keyword[self]/CurrNominal: .self[#BazEnum<_>.Type#]; name=self
// BAZ_T_ENUM_NO_DOT-DAG: Keyword/CurrNominal: .Type[#BazEnum<_>.Type#]; name=Type
@@ -395,7 +395,7 @@ func ~=(pattern: OtherEnum, value: EnumWithCustomPatternMatchingOperator) -> Boo
func completeEnumWithCustomPatternMatchingOperator(x: EnumWithCustomPatternMatchingOperator) {
switch x {
case .#^PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING^#
// We should be suggesting static members of `OtherEnum`, because we can match it to `EnumWithCustomPatternMatchingOperator` using the custom pattern match operator.
// We should be suggesting static members of `OtherEnum`, because we can match it to `EnumWithCustomPatternMatchingOperator` using the custom pattern match operator.
// We should also suggest enum cases from `EnumWithCustomPatternMatchingOperator` whose pattern matching doesn't go through any `~=` operator.
// We shouldn't suggest `staticMember` because `EnumWithCustomPatternMatchingOperator` doesn`t have `~=` defined between two of its instances.
// PATTERN_MATCH_ENUM_WITH_CUSTOM_PATTERN_MATCHING: Begin completions, 4 items

View File

@@ -36,8 +36,8 @@ func testTupleNoDot1() {
// TUPLE_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: < {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: > {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_1-DAG: BuiltinOperator/None: = {#(Int, Double)#}[#Void#]{{; name=.+$}}
// TUPLE_NO_DOT_1-NEXT: Keyword[self]/CurrNominal: .self[#(Int, Double)#]; name=self
// TUPLE_NO_DOT_1-DAG: BuiltinOperator/None: = {#(Int, Double)#}{{; name=.+$}}
// TUPLE_NO_DOT_1-DAG: Keyword[self]/CurrNominal: .self[#(Int, Double)#]; name=self
func testTupleNoDot2() {
var t = (foo: 1, bar: 2.0)
@@ -52,7 +52,7 @@ func testTupleNoDot2() {
// TUPLE_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: < {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: > {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_2-DAG: BuiltinOperator/None: = {#(foo: Int, bar: Double)#}[#Void#]{{; name=.+$}}
// TUPLE_NO_DOT_2-DAG: BuiltinOperator/None: = {#(foo: Int, bar: Double)#}{{; name=.+$}}
// TUPLE_NO_DOT_2-DAG: Keyword[self]/CurrNominal: .self[#(foo: Int, bar: Double)#]; name=self
func testTupleNoDot3() {
@@ -68,7 +68,7 @@ func testTupleNoDot3() {
// TUPLE_NO_DOT_3-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: < {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_3-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_3-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: > {#(Int, Double)#}[#Bool#]{{; name=.+$}}
// TUPLE_NO_DOT_3-DAG: BuiltinOperator/None: = {#(foo: Int, Double)#}[#Void#]{{; name=.+$}}
// TUPLE_NO_DOT_3-DAG: BuiltinOperator/None: = {#(foo: Int, Double)#}{{; name=.+$}}
// TUPLE_NO_DOT_3-DAG: Keyword[self]/CurrNominal: .self[#(foo: Int, Double)#]; name=self
func testTupleDot1() {

View File

@@ -185,10 +185,16 @@ func testInfixOperator3(_ x: String) {
func testInfixOperator4(_ x: String) {
x == ""#^INFIX_EXT_STRING_1?check=INFIX_EXT_STRING^#
}
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: + {#String#}[#String#]
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: || {#Bool#}[#Bool#]
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: && {#Bool#}[#Bool#]
// INFIX_EXT_STRING-NOT: ==
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: >= {#String#}[#Bool#]; name=>=
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: ... {#String#}[#ClosedRange<String>#]; name=...
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: ..< {#String#}[#Range<String>#]; name=..<
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: <= {#String#}[#Bool#]; name=<=
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: ~= {#Substring#}[#Bool#]; name=~=
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#String#}[#Bool#]; name=!=
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: + {#String#}[#String#]; name=+
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#String#}[#Bool#]; name===
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: < {#String#}[#Bool#]; name=<
// INFIX_EXT_STRING-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: > {#String#}[#Bool#]; name=>
class TestSequence : Sequence {
#^CONFORM_SEQUENCE^#

View File

@@ -336,7 +336,7 @@ var foo = {
func testWithMemoryRebound(_ bar: UnsafePointer<UInt64>) {
_ = bar.withMemoryRebound(to: Int64.self, capacity: 3) { ptr in
return ptr #^SINGLE_EXPR_CLOSURE_CONTEXT^#
// SINGLE_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: .deallocate()[#Void#]; name=deallocate()
// SINGLE_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Invalid]: .deallocate()[#Void#]; name=deallocate()
// SINGLE_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .pointee[#Int64#]; name=pointee
}
}
@@ -344,14 +344,14 @@ func testWithMemoryRebound(_ bar: UnsafePointer<UInt64>) {
func testInsideTernaryClosureReturn(test: Bool) -> [String] {
return "hello".map { thing in
test ? String(thing #^SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT^#).uppercased() : String(thing).lowercased()
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .utf8[#Character.UTF8View#]; name=utf8
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .description[#String#]; name=description
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .isWhitespace[#Bool#]; name=isWhitespace
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem: .uppercased()[#String#]; name=uppercased()
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']... {#String.Element#}[#ClosedRange<String.Element>#]; name=...
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']< {#Character#}[#Bool#]; name=<
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']>= {#String.Element#}[#Bool#]; name=>=
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']== {#Character#}[#Bool#]; name===
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Convertible]: .utf8[#Character.UTF8View#]; name=utf8
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Convertible]: .description[#String#]; name=description
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Convertible]: .isWhitespace[#Bool#]; name=isWhitespace
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InstanceMethod]/CurrNominal/IsSystem/TypeRelation[Convertible]: .uppercased()[#String#]; name=uppercased()
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: [' ']... {#String.Element#}[#ClosedRange<String.Element>#]; name=...
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: [' ']< {#Character#}[#Bool#]; name=<
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: [' ']>= {#String.Element#}[#Bool#]; name=>=
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: [' ']== {#Character#}[#Bool#]; name===
// SINGLE_TERNARY_EXPR_CLOSURE_CONTEXT-DAG: Keyword[self]/CurrNominal: .self[#String.Element#]; name=self
}
}

View File

@@ -76,7 +76,8 @@ func testArray(f1: Float) {
func testDict(f1: Float) {
_ = ["foo": f1, "bar": "baz"] #^LITERAL9^#
}
// LITERAL9-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .keys[#Dictionary<String, Any>.Keys#]; name=keys
// LITERAL9-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .keys[#Dictionary<String, String>.Keys#]; name=keys
// LITERAL9-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .keys[#Dictionary<String, Float>.Keys#]; name=keys
// LITERAL9-DAG: Decl[InstanceVar]/CurrNominal/IsSystem: .isEmpty[#Bool#]; name=isEmpty
func testEditorPlaceHolder() {

View File

@@ -167,7 +167,7 @@ func postfixExpr() {
// POSTFIX_TestProtocol_NODOT-DAG: Decl[InstanceMethod]/CurrNominal: .foo({#arg1: TestProtocol.Assoc1#}, {#arg2: (Comparable) -> TestProtocol.Assoc1##(Comparable) -> TestProtocol.Assoc1#})[#Comparable#]; name={{.*$}}
// POSTFIX_TestProtocol_NODOT-DAG: Decl[Subscript]/CurrNominal: [{#(idx): TestProtocol.Assoc1#}, {#(idx2): Comparable#}][#TestProtocol#]; name={{.*$}}
// POSTFIX_TestProtocol_NODOT-DAG: Decl[InstanceVar]/CurrNominal: .value[#(TestProtocol.Assoc1, Comparable)#]; name={{.*$}}
// POSTFIX_TestProtocol_NODOT-DAG: BuiltinOperator/None: = {#TestProtocol#}[#Void#]; name={{.*$}}
// POSTFIX_TestProtocol_NODOT-DAG: BuiltinOperator/None: = {#TestProtocol#}; name={{.*$}}
// POSTFIX_TestProtocol_NODOT-DAG: Keyword[self]/CurrNominal: .self[#TestProtocol#]; name={{.*$}}
protocol TestProtocol2 {

View File

@@ -45,7 +45,7 @@ postfix func ***<G: Fooable>(x: G) -> G { return x }
func testPostfix6() {
1 + 2 * 3#^POSTFIX_6^#
}
// POSTFIX_6: Decl[PostfixOperatorFunction]/CurrModule: ***[#Int#]
// POSTFIX_6: Decl[PostfixOperatorFunction]/CurrModule/TypeRelation[Convertible]: ***[#Int#]
func testPostfix7() {
1 + 2 * 3.0#^POSTFIX_7^#
@@ -119,7 +119,7 @@ func testInfix2(x: inout S2) {
// S2_INFIX_LVALUE-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: + {#S2#}[#S2#]
// S2_INFIX_LVALUE-DAG: Decl[InfixOperatorFunction]/CurrModule: ** {#Int#}[#S2#]
// S2_INFIX_LVALUE-DAG: Decl[InfixOperatorFunction]/CurrModule: **= {#Int#}[#Void#]
// S2_INFIX_LVALUE-DAG: BuiltinOperator/None: = {#S2#}[#Void#]
// S2_INFIX_LVALUE-DAG: BuiltinOperator/None: = {#S2#}
// NEGATIVE_S2_INFIX_LVALUE-NOT: +=
// NEGATIVE_S2_INFIX_LVALUE-NOT: \* {#Int#}
// NEGATIVE_S2_INFIX_LVALUE-NOT: ??
@@ -205,11 +205,13 @@ func testInfix14() {
func testInfix15<T: P where T.T == S2>() {
T#^INFIX_15^#
}
// INFIX_15: Begin completions, 4 items
// INFIX_15-NEXT: Decl[AssociatedType]/CurrNominal: .T; name=T
// INFIX_15-NEXT: Decl[InstanceMethod]/CurrNominal: .foo({#(self): P#})[#() -> S2#]; name=foo(:)
// INFIX_15-NEXT: Keyword[self]/CurrNominal: .self[#T.Type#]; name=self
// INFIX_15-NEXT: Keyword/CurrNominal: .Type[#T.Type#]; name=Type
// INFIX_15: Begin completions, 6 items
// INFIX_15-DAG: Decl[AssociatedType]/CurrNominal: .T; name=T
// INFIX_15-DAG: Decl[InstanceMethod]/CurrNominal: .foo({#(self): P#})[#() -> S2#]; name=foo(:)
// INFIX_15-DAG: Keyword[self]/CurrNominal: .self[#T.Type#]; name=self
// INFIX_15-DAG: Keyword/CurrNominal: .Type[#T.Type#]; name=Type
// INFIX_15-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: != {#Any.Type?#}[#Bool#];
// INFIX_15-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#Any.Type?#}[#Bool#];
func testInfix16<T: P where T.T == S2>() {
T.foo#^INFIX_16^#
@@ -264,8 +266,12 @@ func testSpace(x: S2) {
// S2_INFIX_SPACE-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: [' ']+ {#S2#}[#S2#]
func testExtInfix1(x: inout S2) {
x + S2() + x + S2() + x + S2() + x#^EXT_INFIX_1?check=S2_INFIX^#
x + S2() + x + S2() + x + S2() + x#^EXT_INFIX_1^#
}
// EXT_INFIX_1: Begin completions
// EXT_INFIX_1-DAG: Decl[InfixOperatorFunction]/CurrModule/TypeRelation[Convertible]: ** {#Int#}[#S2#]
// EXT_INFIX_1-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: + {#S2#}[#S2#]
// EXT_INFIX_1: End completions
struct S4 {}
func +(x: S4, y: S4) -> S4 { return x }
@@ -285,26 +291,27 @@ precedencegroup ReallyHighPrecedence {
func &&&(x: Bool, y: Bool) -> S4 { return x }
func testExtInfix2(x: S4) {
x + x == x + x#^EXT_INFIX_2?check=S4_EXT_INFIX;check=S4_EXT_INFIX_NEG^#
x + x == x + x#^EXT_INFIX_2^#
}
// S4_EXT_INFIX-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: + {#S4#}[#S4#]
// S4_EXT_INFIX-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: && {#Bool#}[#Bool#]
// S4_EXT_INFIX-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: || {#Bool#}[#Bool#]
// S4_EXT_INFIX-NEG-NOT: !=
// S4_EXT_INFIX-NEG-NOT: ==
// S4_EXT_INFIX_NEG-NOT: +++
// S4_EXT_INFIX_NEG-NOT: &&&
// EXT_INFIX_2: Begin completions, 4 items
// EXT_INFIX_2-DAG: Keyword[self]/CurrNominal: .self[#S4#];
// EXT_INFIX_2-DAG: Decl[InfixOperatorFunction]/CurrModule/TypeRelation[Convertible]: +++ {#S4#}[#S4#];
// EXT_INFIX_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: + {#S4#}[#S4#];
// EXT_INFIX_2-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: == {#S4#}[#Bool#];
func testExtInfix3(x: S4) {
x + x#^EXT_INFIX_3?check=S4_EXT_INFIX_SIMPLE^#
x + x#^EXT_INFIX_3^#
}
// S4_EXT_INFIX_SIMPLE-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: + {#S4#}[#S4#]
// S4_EXT_INFIX_SIMPLE-DAG: Decl[InfixOperatorFunction]/CurrModule: +++ {#S4#}[#S4#]
// EXT_INFIX_3-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem/TypeRelation[Convertible]: + {#S4#}[#S4#]
// EXT_INFIX_3-DAG: Decl[InfixOperatorFunction]/CurrModule/TypeRelation[Convertible]: +++ {#S4#}[#S4#]
func testExtInfix4(x: S4) {
1 + 1.0 + x#^EXT_INFIX_4?check=S4_EXT_INFIX_SIMPLE^#
1 + 1.0 + x#^EXT_INFIX_4^#
}
// EXT_INFIX_4: Begin completions
// EXT_INFIX_4-DAG: Decl[InfixOperatorFunction]/OtherModule[Swift]/IsSystem: + {#S4#}[#S4#]
// EXT_INFIX_4-DAG: Decl[InfixOperatorFunction]/CurrModule: +++ {#S4#}[#S4#]
// EXT_INFIX_4: End completions
func testAssignTuple1() {
()#^ASSIGN_TUPLE_1^#
@@ -323,7 +330,7 @@ func testAssignTuple2() {
var y: S2
(x, y)#^ASSIGN_TUPLE_2^#
}
// ASSIGN_TUPLE_2: BuiltinOperator/None: = {#(S2, S2)#}[#Void#];
// ASSIGN_TUPLE_2: BuiltinOperator/None: = {#(S2, S2)#};
infix operator ====: ComparisonPrecedence
@@ -336,12 +343,18 @@ func ||||(x: Boolish, y: @autoclosure ()->Boolish) -> Boolish { return x }
func testAutoclosure(x: Boolish, y: Boolish) {
if x #^INFIX_AUTOCLOSURE_1^# {}
if x &&&& y #^INFIX_AUTOCLOSURE_2?check=INFIX_AUTOCLOSURE_1^# {}
if x |||| y #^INFIX_AUTOCLOSURE_3?check=INFIX_AUTOCLOSURE_1^# {}
if x &&&& x |||| y #^INFIX_AUTOCLOSURE_4?check=INFIX_AUTOCLOSURE_1^# {}
if x &&&& y #^INFIX_AUTOCLOSURE_2^# {}
if x |||| y #^INFIX_AUTOCLOSURE_3?check=INFIX_AUTOCLOSURE_2^# {}
if x &&&& x |||| y #^INFIX_AUTOCLOSURE_4?check=INFIX_AUTOCLOSURE_2^# {}
}
// INFIX_AUTOCLOSURE_1-DAG: Decl[InfixOperatorFunction]/CurrModule: [' ']&&&& {#Boolish#}[#Boolish#];
// INFIX_AUTOCLOSURE_1-DAG: Decl[InfixOperatorFunction]/CurrModule: [' ']==== {#Boolish#}[#Boolish#];
// INFIX_AUTOCLOSURE_1-DAG: Decl[InfixOperatorFunction]/CurrModule: [' ']|||| {#Boolish#}[#Boolish#];
// INFIX_AUTOCLOSURE_2: Begin completions
// INFIX_AUTOCLOSURE_2-DAG: Decl[InfixOperatorFunction]/CurrModule/TypeRelation[Convertible]: [' ']&&&& {#Boolish#}[#Boolish#];
// INFIX_AUTOCLOSURE_2-DAG: Decl[InfixOperatorFunction]/CurrModule/TypeRelation[Convertible]: [' ']==== {#Boolish#}[#Boolish#];
// INFIX_AUTOCLOSURE_2-DAG: Decl[InfixOperatorFunction]/CurrModule/TypeRelation[Convertible]: [' ']|||| {#Boolish#}[#Boolish#];
// INFIX_AUTOCLOSURE_2: End completions

View File

@@ -206,3 +206,22 @@ func test_cc_in_pattern(subject: IntHolder, i1: Int) {
}
// CC_IN_PATTERN_1-DAG: Decl[LocalVar]/Local/TypeRelation[Convertible]: i1[#Int#]; name=i1
func testCompleteAfterPatternInClosure() {
func takeClosure(_ x: () -> Void) {}
enum MyEnum {
case failure(Int)
}
func test(value: MyEnum) {
takeClosure {
switch value {
case let .failure(error)#^AFTER_PATTERN_IN_CLOSURE^#:
break
}
}
}
// AFTER_PATTERN_IN_CLOSURE-NOT: Begin completions
}

View File

@@ -1,5 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
// Check that we don't crash
func myGlobalFunction() -> Invalid {}
@@ -7,21 +8,18 @@ struct Test {
func myInstanceMethod() -> Invalid {}
func testInstanceMethod() {
Test.myInstanceMethod#^INSTANCE_METHOD^#
// Check that we don't crash
// INSTANCE_METHOD-NOT: Begin completions
Test.myInstanceMethod#^INSTANCE_METHOD?check=NO_RESULTS^#
}
func testGlobalFunctionMethod() {
myGlobalFunction#^GLOBAL_FUNCTION^#
myGlobalFunction#^GLOBAL_FUNCTION?check=NO_RESULTS^#
// Check that we don't crash
// GLOBAL_FUNCTION: Keyword[self]/CurrNominal: .self[#_#]
}
func testLocalFunction() {
func myLocalFunction() -> Invalid {}
myLocalFunction#^LOCAL_FUNCTION^#
// LOCAL_FUNCTION: Keyword[self]/CurrNominal: .self[#_#]
myLocalFunction#^LOCAL_FUNCTION?check=NO_RESULTS^#
}
}
// NO_RESULTS-NOT: Begin completions

View File

@@ -5,8 +5,6 @@
// NOCRASH: Token
// NORESULT: Token
struct FooStruct {
lazy var lazyInstanceVar = 0
var instanceVar = 0
@@ -352,8 +350,12 @@ struct NoMetaCompletions {
typealias Foo = Int
}
func testMetatypeCompletions() {
NoMetaCompletions.Type.#^FOO_STRUCT_META_1?check=FOO_STRUCT_META^#
NoMetaCompletions.Type.#^FOO_STRUCT_META_1^#
}
// FOO_STRUCT_META_1: Begin completions, 2 items
// FOO_STRUCT_META_1-DAG: Keyword[self]/CurrNominal: self[#NoMetaCompletions.Type.Type#]; name=self
// FOO_STRUCT_META_1-DAG: Keyword/CurrNominal: Type[#NoMetaCompletions.Type.Type#]; name=Type
// FOO_STRUCT_META_1: End completions
func testMetatypeCompletionsWithoutDot() {
NoMetaCompletions.Type#^FOO_STRUCT_META_2?check=FOO_STRUCT_META^#
}
@@ -388,11 +390,23 @@ func testImplicitlyCurriedFunc(_ fs: inout FooStruct) {
// This call is ambiguous, and the expression is invalid.
// Ensure that we don't suggest to call the result.
FooStruct.overloadedInstanceFunc1(&fs)#^IMPLICITLY_CURRIED_OVERLOADED_FUNC_1?check=NORESULT^#
FooStruct.overloadedInstanceFunc1(&fs)#^IMPLICITLY_CURRIED_OVERLOADED_FUNC_1^#
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_1: Begin completions, 4 items
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_1-DAG: Keyword[self]/CurrNominal: .self[#() -> Int#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_1-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]: ()[#Int#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_1-DAG: Keyword[self]/CurrNominal: .self[#() -> Double#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_1-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]: ()[#Double#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_1: End completions
// This call is ambiguous, and the expression is invalid.
// Ensure that we don't suggest to call the result.
FooStruct.overloadedInstanceFunc2(&fs)#^IMPLICITLY_CURRIED_OVERLOADED_FUNC_2?check=NORESULT^#
FooStruct.overloadedInstanceFunc2(&fs)#^IMPLICITLY_CURRIED_OVERLOADED_FUNC_2^#
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_2: Begin completions, 4 items
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_2-DAG: Keyword[self]/CurrNominal: .self[#(Int) -> Int#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_2-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]: ({#(x): Int#})[#Int#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_2-DAG: Keyword[self]/CurrNominal: .self[#(Double) -> Int#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_2-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]: ({#(x): Double#})[#Int#];
// IMPLICITLY_CURRIED_OVERLOADED_FUNC_2: End completions
}
//===---
@@ -619,13 +633,15 @@ class FuncTypeVars {
var funcTypeVarsObject: FuncTypeVars
func testFuncTypeVars() {
funcTypeVarsObject.funcVar1#^VF1^#
// VF1: Begin completions, 3 items
// VF1-DAG: Pattern/CurrModule/Flair[ArgLabels]: ()[#Double#]{{; name=.+$}}
// VF1-DAG: BuiltinOperator/None: = {#() -> Double##() -> Double#}[#Void#]
// VF1-DAG: BuiltinOperator/None: = {#() -> Double##() -> Double#}
// VF1-DAG: Keyword[self]/CurrNominal: .self[#() -> Double#]; name=self
funcTypeVarsObject.funcVar2#^VF2^#
// VF2: Begin completions, 3 items
// VF2-DAG: Pattern/CurrModule/Flair[ArgLabels]: ({#Int#})[#Double#]{{; name=.+$}}
// VF2-DAG: BuiltinOperator/None: = {#(Int) -> Double##(_ a: Int) -> Double#}[#Void#]
// VF2-DAG: BuiltinOperator/None: = {#(Int) -> Double##(_ a: Int) -> Double#}
// VF2-DAG: Keyword[self]/CurrNominal: .self[#(Int) -> Double#]; name=self
}
@@ -1685,7 +1701,7 @@ func testKeyword(cat: Cat) {
let _ = cat.class#^KEYWORD_2^#
// KEYWORD_2-DAG: Decl[InstanceVar]/CurrNominal: .prop1[#String#]; name=prop1
// KEYWORD_2-DAG: Decl[InstanceVar]/CurrNominal: .prop2[#String#]; name=prop2
// KEYWORD_2-DAG: BuiltinOperator/None: = {#Cat.Inner#}[#Void#]; name==
// KEYWORD_2-DAG: BuiltinOperator/None: = {#Cat.Inner#}; name==
let _ = cat.class.#^KEYWORD_3^#
// KEYWORD_3-DAG: Decl[InstanceVar]/CurrNominal: prop1[#String#]; name=prop1

View File

@@ -1,11 +1,12 @@
// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s | %FileCheck %s
// RUN: %target-swift-ide-test -code-completion -code-completion-token=B -source-filename=%s | %FileCheck %s
// RUN: %empty-directory(%t)
// RUN: %target-swift-ide-test -batch-code-completion -source-filename=%s -filecheck %raw-FileCheck -completion-output-dir %t
func test1() {
1 + [0]#^A^#
// A: Decl[InstanceVar]/CurrNominal/IsSystem/TypeRelation[Convertible]: .startIndex[#Int#]; name=startIndex
}
func test2() {
"" + [""]#^B^#
// B: Decl[InstanceVar]/CurrNominal/IsSystem: .startIndex[#Int#]; name=startIndex
}
// Sanity check results.
// CHECK: Decl[InstanceVar]/CurrNominal/IsSystem: .startIndex[#Int#]; name=startIndex