Skip to content

Commit b15c1fd

Browse files
author
Nathan Hawes
committed
[CodeCompletion] Deduplicate the two isMemberCompletion functions in ParseExpr.cpp and ParseDecl.cpp
Also: - propagate the Solution -> Result rename to Solution parameter of deliverDotExprResults - fixup header comment in CodeCompletionTypeChecking.h
1 parent 7a06792 commit b15c1fd

File tree

6 files changed

+56
-51
lines changed

6 files changed

+56
-51
lines changed

include/swift/Parse/Parser.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,15 @@ class Parser {
696696
Context.LangOpts.ParseForSyntaxTreeOnly;
697697
}
698698

699+
/// If a function or closure body consists of a single expression, determine
700+
/// whether we should turn wrap it in a return statement or not.
701+
///
702+
/// We don't do this transformation for non-solver-based code completion
703+
/// positions, as the source may be incomplete and the type mismatch in the
704+
/// return statement will just confuse the type checker.
705+
bool shouldSuppressSingleExpressionBodyTransform(
706+
ParserStatus Status, MutableArrayRef<ASTNode> BodyElems);
707+
699708
public:
700709
InFlightDiagnostic diagnose(SourceLoc Loc, Diagnostic Diag) {
701710
if (Diags.isDiagnosticPointsToFirstBadToken(Diag.getID()) &&

include/swift/Sema/CodeCompletionTypeChecking.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//===--- CodeCompletionTypeChecking.h --------------------------*- C++ -*-===//
12
//
23
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
34
// Licensed under Apache License v2.0 with Runtime Library Exception

lib/IDE/CodeCompletion.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5911,7 +5911,7 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
59115911
}
59125912

59135913
void deliverDotExprResults(
5914-
ArrayRef<DotExprTypeCheckCompletionCallback::Result> Solutions,
5914+
ArrayRef<DotExprTypeCheckCompletionCallback::Result> Results,
59155915
Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
59165916
ide::CodeCompletionContext &CompletionCtx,
59175917
CodeCompletionConsumer &Consumer) {
@@ -5935,15 +5935,15 @@ void deliverDotExprResults(
59355935
Lookup.setPreferFunctionReferencesToCalls();
59365936
}
59375937

5938-
for (auto &Solution: Solutions) {
5939-
Lookup.setIsStaticMetatype(Solution.BaseIsStaticMetaType);
5940-
Lookup.getPostfixKeywordCompletions(Solution.BaseTy, BaseExpr);
5941-
Lookup.setExpectedTypes(Solution.ExpectedTypes,
5942-
Solution.IsSingleExpressionBody,
5943-
Solution.ExpectsNonVoid);
5944-
if (isDynamicLookup(Solution.BaseTy))
5938+
for (auto &Result: Results) {
5939+
Lookup.setIsStaticMetatype(Result.BaseIsStaticMetaType);
5940+
Lookup.getPostfixKeywordCompletions(Result.BaseTy, BaseExpr);
5941+
Lookup.setExpectedTypes(Result.ExpectedTypes,
5942+
Result.IsSingleExpressionBody,
5943+
Result.ExpectsNonVoid);
5944+
if (isDynamicLookup(Result.BaseTy))
59455945
Lookup.setIsDynamicLookup();
5946-
Lookup.getValueExprCompletions(Solution.BaseTy, Solution.BaseDecl);
5946+
Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl);
59475947
}
59485948

59495949
SourceFile *SF = DC->getParentSourceFile();

lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6443,22 +6443,6 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
64436443
return DCC.fixupParserResult(FD);
64446444
}
64456445

6446-
static bool isMemberCompletion(ASTNode Node) {
6447-
struct HasMemberCompletion: public ASTWalker {
6448-
bool Value = false;
6449-
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
6450-
if (auto *CCE = dyn_cast<CodeCompletionExpr>(E)) {
6451-
Value = CCE->getBase();
6452-
return {false, nullptr};
6453-
}
6454-
return {true, E};
6455-
}
6456-
};
6457-
HasMemberCompletion Check;
6458-
Node.walk(Check);
6459-
return Check.Value;
6460-
}
6461-
64626446
/// Parse a function body for \p AFD, setting the body to \p AFD before
64636447
/// returning it.
64646448
BraceStmt *Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
@@ -6506,11 +6490,10 @@ BraceStmt *Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
65066490
// If the body consists of a single expression, turn it into a return
65076491
// statement.
65086492
//
6509-
// But don't do this transformation during code completion, as the source
6510-
// may be incomplete and the type mismatch in return statement will just
6511-
// confuse the type checker.
6512-
if (BS->getNumElements() != 1 ||
6513-
(Body.hasCodeCompletion() && !isMemberCompletion(BS->getFirstElement())))
6493+
// But don't do this transformation when performing certain kinds of code
6494+
// completion, as the source may be incomplete and the type mismatch in return
6495+
// statement will just confuse the type checker.
6496+
if (shouldSuppressSingleExpressionBodyTransform(Body, BS->getElements()))
65146497
return BS;
65156498

65166499
auto Element = BS->getFirstElement();

lib/Parse/ParseExpr.cpp

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,22 +2753,6 @@ parseClosureSignatureIfPresent(SourceRange &bracketRange,
27532753
return invalid;
27542754
}
27552755

2756-
static bool isMemberCompletion(ASTNode Node) {
2757-
struct HasMemberCompletion: public ASTWalker {
2758-
bool Value = false;
2759-
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
2760-
if (auto *CCE = dyn_cast<CodeCompletionExpr>(E)) {
2761-
Value = CCE->getBase();
2762-
return {false, nullptr};
2763-
}
2764-
return {true, E};
2765-
}
2766-
};
2767-
HasMemberCompletion Check;
2768-
Node.walk(Check);
2769-
return Check.Value;
2770-
}
2771-
27722756
ParserResult<Expr> Parser::parseExprClosure() {
27732757
assert(Tok.is(tok::l_brace) && "Not at a left brace?");
27742758
SyntaxParsingContext ClosureContext(SyntaxContext, SyntaxKind::ClosureExpr);
@@ -2875,12 +2859,12 @@ ParserResult<Expr> Parser::parseExprClosure() {
28752859
// If the body consists of a single expression, turn it into a return
28762860
// statement.
28772861
//
2878-
// But don't do this transformation during code completion, as the source
2879-
// may be incomplete and the type mismatch in return statement will just
2880-
// confuse the type checker.
2862+
// But don't do this transformation when performing certain kinds of code
2863+
// completion, as the source may be incomplete and the type mismatch in return
2864+
// statement will just confuse the type checker.
28812865
bool hasSingleExpressionBody = false;
2882-
if (!missingRBrace && bodyElements.size() == 1 &&
2883-
(!Status.hasCodeCompletion() || isMemberCompletion(bodyElements[0]))) {
2866+
if (!missingRBrace &&
2867+
!shouldSuppressSingleExpressionBodyTransform(Status, bodyElements)) {
28842868
// If the closure's only body element is a single return statement,
28852869
// use that instead of creating a new wrapping return expression.
28862870
Expr *returnExpr = nullptr;

lib/Parse/Parser.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,34 @@ Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc,
11851185
Segments.front().Length));
11861186
}
11871187

1188+
bool Parser::
1189+
shouldSuppressSingleExpressionBodyTransform(ParserStatus Status,
1190+
MutableArrayRef<ASTNode> BodyElems) {
1191+
if (BodyElems.size() != 1)
1192+
return true;
1193+
1194+
if (!Status.hasCodeCompletion())
1195+
return false;
1196+
1197+
struct HasMemberCompletion: public ASTWalker {
1198+
bool Value = false;
1199+
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
1200+
if (auto *CCE = dyn_cast<CodeCompletionExpr>(E)) {
1201+
// If it has a base expression this is member completion, which is
1202+
// performed using the new solver-based mechanism, so it's ok to go
1203+
// ahead with the transform (and necessary to pick up the correct
1204+
// expected type).
1205+
Value = CCE->getBase();
1206+
return {false, nullptr};
1207+
}
1208+
return {true, E};
1209+
}
1210+
};
1211+
HasMemberCompletion Check;
1212+
BodyElems.front().walk(Check);
1213+
return !Check.Value;
1214+
}
1215+
11881216
struct ParserUnit::Implementation {
11891217
std::shared_ptr<SyntaxParseActions> SPActions;
11901218
LangOptions LangOpts;

0 commit comments

Comments
 (0)