Skip to content

Commit c55e07b

Browse files
authored
Merge pull request #11267 from benlangmuir/cc-generic-where-clause
[code-completion] Generic where clauses
2 parents 8a8f7c8 + 534c0cc commit c55e07b

10 files changed

+160
-55
lines changed

include/swift/AST/DeclNodes.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ ABSTRACT_DECL(Value, Decl)
108108
VALUE_DECL(AssociatedType, AbstractTypeParamDecl)
109109
DECL_RANGE(AbstractTypeParam, GenericTypeParam, AssociatedType)
110110
ABSTRACT_DECL(GenericType, TypeDecl)
111-
VALUE_DECL(TypeAlias, GenericTypeDecl)
111+
CONTEXT_VALUE_DECL(TypeAlias, GenericTypeDecl)
112112
ABSTRACT_DECL(NominalType, GenericTypeDecl)
113113
NOMINAL_TYPE_DECL(Enum, NominalTypeDecl)
114114
NOMINAL_TYPE_DECL(Struct, NominalTypeDecl)
@@ -121,7 +121,7 @@ ABSTRACT_DECL(Value, Decl)
121121
ABSTRACT_DECL(AbstractStorage, ValueDecl)
122122
VALUE_DECL(Var, AbstractStorageDecl)
123123
VALUE_DECL(Param, VarDecl)
124-
VALUE_DECL(Subscript, AbstractStorageDecl)
124+
CONTEXT_VALUE_DECL(Subscript, AbstractStorageDecl)
125125
DECL_RANGE(AbstractStorage, Var, Subscript)
126126
ABSTRACT_DECL(AbstractFunction, ValueDecl)
127127
FUNCTION_DECL(Constructor, AbstractFunctionDecl)

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class CodeCompletionCallbacks {
3838

3939
/// The declaration parsed during delayed parsing that was caused by code
4040
/// completion. This declaration contained the code completion token.
41-
Decl *DelayedParsedDecl = nullptr;
41+
Decl *ParsedDecl = nullptr;
4242

4343
/// If code completion is done inside a controlling expression of a C-style
4444
/// for loop statement, this is the declaration of the iteration variable.
@@ -73,8 +73,11 @@ class CodeCompletionCallbacks {
7373
ExprBeginPosition = PP;
7474
}
7575

76-
void setDelayedParsedDecl(Decl *D) {
77-
DelayedParsedDecl = D;
76+
/// Set the decl inside which the code-completion occurred. This is used when
77+
/// completing inside a parameter list or where clause where the Parser's
78+
/// CurDeclContext will not be where we want to perform lookup.
79+
void setParsedDecl(Decl *D) {
80+
ParsedDecl = D;
7881
}
7982

8083
void setLeadingSequenceExprs(ArrayRef<Expr *> exprs) {

lib/AST/LookupVisibleDecls.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,6 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
885885
// and if so, whether this is a reference to one of them.
886886
while (!DC->isModuleScopeContext()) {
887887
const ValueDecl *BaseDecl = nullptr;
888-
GenericParamList *GenericParams = nullptr;
889888
Type ExtendedType;
890889
auto LS = LookupState::makeUnqualified();
891890

@@ -895,6 +894,8 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
895894
LS = LS.withOnMetatype();
896895
}
897896

897+
GenericParamList *GenericParams = DC->getGenericParamsOfContext();
898+
898899
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
899900
// Look for local variables; normally, the parser resolves these
900901
// for us, but it can't do the right thing inside local types.
@@ -922,9 +923,6 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
922923
if (FD->isStatic())
923924
ExtendedType = MetatypeType::get(ExtendedType);
924925
}
925-
926-
// Look in the generic parameters after checking our local declaration.
927-
GenericParams = AFD->getGenericParams();
928926
} else if (auto CE = dyn_cast<ClosureExpr>(DC)) {
929927
if (Loc.isValid()) {
930928
namelookup::FindLocalVal(SM, Loc, Consumer).visit(CE->getBody());

lib/IDE/CodeCompletion.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,9 +1381,9 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
13811381
}
13821382

13831383
/// \returns true on success, false on failure.
1384-
bool typecheckDelayedParsedDecl() {
1385-
assert(DelayedParsedDecl && "should have a delayed parsed decl");
1386-
return typeCheckCompletionDecl(DelayedParsedDecl);
1384+
bool typecheckParsedDecl() {
1385+
assert(ParsedDecl && "should have a parsed decl");
1386+
return typeCheckCompletionDecl(ParsedDecl);
13871387
}
13881388

13891389
Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
@@ -5117,11 +5117,11 @@ void CodeCompletionCallbacksImpl::doneParsing() {
51175117
if (!typecheckContext())
51185118
return;
51195119

5120-
if (DelayedParsedDecl && !typecheckDelayedParsedDecl())
5120+
if (ParsedDecl && !typecheckParsedDecl())
51215121
return;
51225122

5123-
if (auto *AFD = dyn_cast_or_null<AbstractFunctionDecl>(DelayedParsedDecl))
5124-
CurDeclContext = AFD;
5123+
if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl))
5124+
CurDeclContext = DC;
51255125

51265126
Optional<Type> ExprType;
51275127
ConcreteDeclRef ReferencedDecl = nullptr;

lib/Parse/ParseDecl.cpp

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,9 +3208,7 @@ parseDeclTypeAlias(Parser::ParseDeclOptions Flags, DeclAttributes &Attributes) {
32083208

32093209
// Parse a 'where' clause if present, adding it to our GenericParamList.
32103210
if (Tok.is(tok::kw_where)) {
3211-
auto whereStatus = parseFreestandingGenericWhereClause(genericParams);
3212-
if (whereStatus.shouldStopParsing())
3213-
return whereStatus;
3211+
Status |= parseFreestandingGenericWhereClause(genericParams);
32143212
}
32153213

32163214
if (UnderlyingTy.isNull()) {
@@ -3224,6 +3222,9 @@ parseDeclTypeAlias(Parser::ParseDeclOptions Flags, DeclAttributes &Attributes) {
32243222
TAD->getUnderlyingTypeLoc() = UnderlyingTy.getPtrOrNull();
32253223
TAD->getAttrs() = Attributes;
32263224

3225+
if (Status.hasCodeCompletion() && CodeCompletion)
3226+
CodeCompletion->setParsedDecl(TAD);
3227+
32273228
// Exit the scope introduced for the generic parameters.
32283229
GenericsScope.reset();
32293230

@@ -4771,7 +4772,7 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
47714772
Optional<Scope> GenericsScope;
47724773
GenericsScope.emplace(this, ScopeKind::Generics);
47734774
GenericParamList *GenericParams;
4774-
bool GPHasCodeCompletion = false;
4775+
bool SignatureHasCodeCompletion = false;
47754776
// If the name is an operator token that ends in '<' and the following token
47764777
// is an identifier, split the '<' off as a separate token. This allows things
47774778
// like 'func ==<T>(x:T, y:T) {}' to parse as '==' with generic type variable
@@ -4783,7 +4784,7 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
47834784
SourceLoc LAngleLoc = NameLoc.getAdvancedLoc(SimpleName.str().size());
47844785
auto Result = parseGenericParameters(LAngleLoc);
47854786
GenericParams = Result.getPtrOrNull();
4786-
GPHasCodeCompletion |= Result.hasCodeCompletion();
4787+
SignatureHasCodeCompletion |= Result.hasCodeCompletion();
47874788

47884789
auto NameTokText = NameTok.getRawText();
47894790
markSplitToken(tok::identifier,
@@ -4794,9 +4795,9 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
47944795
} else {
47954796
auto Result = maybeParseGenericParams();
47964797
GenericParams = Result.getPtrOrNull();
4797-
GPHasCodeCompletion |= Result.hasCodeCompletion();
4798+
SignatureHasCodeCompletion |= Result.hasCodeCompletion();
47984799
}
4799-
if (GPHasCodeCompletion && !CodeCompletion)
4800+
if (SignatureHasCodeCompletion && !CodeCompletion)
48004801
return makeParserCodeCompletionStatus();
48014802

48024803
SmallVector<ParameterList*, 8> BodyParams;
@@ -4820,6 +4821,7 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
48204821
parseFunctionSignature(SimpleName, FullName, BodyParams, DefaultArgs,
48214822
throwsLoc, rethrows, FuncRetTy);
48224823

4824+
SignatureHasCodeCompletion |= SignatureStatus.hasCodeCompletion();
48234825
if (SignatureStatus.hasCodeCompletion() && !CodeCompletion) {
48244826
// Trigger delayed parsing, no need to continue.
48254827
return SignatureStatus;
@@ -4830,8 +4832,11 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
48304832
// Parse a 'where' clause if present, adding it to our GenericParamList.
48314833
if (Tok.is(tok::kw_where)) {
48324834
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
4833-
if (whereStatus.shouldStopParsing())
4835+
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
4836+
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
4837+
// Trigger delayed parsing, no need to continue.
48344838
return whereStatus;
4839+
}
48354840
}
48364841

48374842
// Protocol method arguments may not have default values.
@@ -4866,13 +4871,9 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
48664871
// they are available.
48674872
FD->getAttrs() = Attributes;
48684873

4869-
// Code completion for the generic type params.
4870-
if (GPHasCodeCompletion)
4871-
CodeCompletion->setDelayedParsedDecl(FD);
4872-
48734874
// Pass the function signature to code completion.
4874-
if (SignatureStatus.hasCodeCompletion())
4875-
CodeCompletion->setDelayedParsedDecl(FD);
4875+
if (SignatureHasCodeCompletion)
4876+
CodeCompletion->setParsedDecl(FD);
48764877

48774878
DefaultArgs.setFunctionContext(FD);
48784879
for (auto PL : FD->getParameterLists())
@@ -5015,11 +5016,17 @@ ParserResult<EnumDecl> Parser::parseDeclEnum(ParseDeclOptions Flags,
50155016
// Parse a 'where' clause if present, adding it to our GenericParamList.
50165017
if (Tok.is(tok::kw_where)) {
50175018
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
5018-
if (whereStatus.shouldStopParsing())
5019+
Status |= whereStatus;
5020+
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
5021+
// Trigger delayed parsing, no need to continue.
50195022
return whereStatus;
5023+
}
50205024
ED->setGenericParams(GenericParams);
50215025
}
50225026

5027+
if (Status.hasCodeCompletion() && CodeCompletion)
5028+
CodeCompletion->setParsedDecl(ED);
5029+
50235030
SourceLoc LBLoc, RBLoc;
50245031
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_enum)) {
50255032
LBLoc = PreviousLoc;
@@ -5272,11 +5279,16 @@ ParserResult<StructDecl> Parser::parseDeclStruct(ParseDeclOptions Flags,
52725279
// Parse a 'where' clause if present, adding it to our GenericParamList.
52735280
if (Tok.is(tok::kw_where)) {
52745281
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
5275-
if (whereStatus.shouldStopParsing())
5282+
Status |= whereStatus;
5283+
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
5284+
// Trigger delayed parsing, no need to continue.
52765285
return whereStatus;
5286+
}
52775287
SD->setGenericParams(GenericParams);
52785288
}
52795289

5290+
if (Status.hasCodeCompletion() && CodeCompletion)
5291+
CodeCompletion->setParsedDecl(SD);
52805292

52815293
SourceLoc LBLoc, RBLoc;
52825294
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) {
@@ -5355,11 +5367,17 @@ ParserResult<ClassDecl> Parser::parseDeclClass(SourceLoc ClassLoc,
53555367
// Parse a 'where' clause if present, adding it to our GenericParamList.
53565368
if (Tok.is(tok::kw_where)) {
53575369
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
5358-
if (whereStatus.shouldStopParsing())
5370+
Status |= whereStatus;
5371+
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
5372+
// Trigger delayed parsing, no need to continue.
53595373
return whereStatus;
5374+
}
53605375
CD->setGenericParams(GenericParams);
53615376
}
53625377

5378+
if (Status.hasCodeCompletion() && CodeCompletion)
5379+
CodeCompletion->setParsedDecl(CD);
5380+
53635381
SourceLoc LBLoc, RBLoc;
53645382
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_class)) {
53655383
LBLoc = PreviousLoc;
@@ -5502,13 +5520,13 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
55025520
Optional<Scope> GenericsScope;
55035521
GenericsScope.emplace(this, ScopeKind::Generics);
55045522
GenericParamList *GenericParams;
5505-
bool GPHasCodeCompletion = false;
5523+
bool SignatureHasCodeCompletion = false;
55065524

55075525
auto Result = maybeParseGenericParams();
55085526
GenericParams = Result.getPtrOrNull();
5509-
GPHasCodeCompletion |= Result.hasCodeCompletion();
5527+
SignatureHasCodeCompletion |= Result.hasCodeCompletion();
55105528

5511-
if (GPHasCodeCompletion && !CodeCompletion)
5529+
if (SignatureHasCodeCompletion && !CodeCompletion)
55125530
return makeParserCodeCompletionStatus();
55135531

55145532
// Parse the parameter list.
@@ -5537,8 +5555,11 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
55375555
// Parse a 'where' clause if present, adding it to our GenericParamList.
55385556
if (Tok.is(tok::kw_where)) {
55395557
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
5540-
if (whereStatus.shouldStopParsing())
5558+
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
5559+
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
5560+
// Trigger delayed parsing, no need to continue.
55415561
return whereStatus;
5562+
}
55425563
}
55435564

55445565
// Build an AST for the subscript declaration.
@@ -5551,11 +5572,9 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
55515572
GenericParams);
55525573
Subscript->getAttrs() = Attributes;
55535574

5554-
// Code completion for the generic type params.
5555-
//
5556-
// FIXME: What is this?
5557-
if (GPHasCodeCompletion)
5558-
CodeCompletion->setDelayedParsedDecl(Subscript);
5575+
// Pass the function signature to code completion.
5576+
if (SignatureHasCodeCompletion)
5577+
CodeCompletion->setParsedDecl(Subscript);
55595578

55605579
Decls.push_back(Subscript);
55615580

@@ -5633,10 +5652,12 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
56335652
// Parse the parameters.
56345653
DefaultArgumentInfo DefaultArgs(/*inTypeContext*/true);
56355654
llvm::SmallVector<Identifier, 4> namePieces;
5655+
bool SignatureHasCodeCompletion = false;
56365656
ParserResult<ParameterList> Params
56375657
= parseSingleParameterClause(ParameterContextKind::Initializer,
56385658
&namePieces, &DefaultArgs);
56395659

5660+
SignatureHasCodeCompletion |= Params.hasCodeCompletion();
56405661
if (Params.hasCodeCompletion() && !CodeCompletion) {
56415662
// Trigger delayed parsing, no need to continue.
56425663
return makeParserCodeCompletionStatus();
@@ -5661,8 +5682,11 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
56615682
// Parse a 'where' clause if present, adding it to our GenericParamList.
56625683
if (Tok.is(tok::kw_where)) {
56635684
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
5664-
if (whereStatus.shouldStopParsing())
5685+
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
5686+
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
5687+
// Trigger delayed parsing, no need to continue.
56655688
return whereStatus;
5689+
}
56665690
}
56675691

56685692
auto *SelfDecl = ParamDecl::createUnboundSelf(ConstructorLoc, CurDeclContext);
@@ -5686,8 +5710,8 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
56865710
DefaultArgs.setFunctionContext(CD);
56875711

56885712
// Pass the function signature to code completion.
5689-
if (Params.hasCodeCompletion())
5690-
CodeCompletion->setDelayedParsedDecl(CD);
5713+
if (SignatureHasCodeCompletion)
5714+
CodeCompletion->setParsedDecl(CD);
56915715

56925716
if (ConstructorsNotAllowed || Params.isParseError()) {
56935717
// Tell the type checker not to touch this constructor.

lib/Parse/ParseGeneric.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,14 @@ ParserStatus Parser::parseGenericWhereClause(
250250
do {
251251
// Parse the leading type-identifier.
252252
ParserResult<TypeRepr> FirstType = parseTypeIdentifier();
253+
254+
if (FirstType.hasCodeCompletion()) {
255+
Status.setHasCodeCompletion();
256+
FirstTypeInComplete = true;
257+
}
258+
253259
if (FirstType.isNull()) {
254260
Status.setIsParseError();
255-
if (FirstType.hasCodeCompletion()) {
256-
Status.setHasCodeCompletion();
257-
FirstTypeInComplete = true;
258-
}
259261
break;
260262
}
261263

0 commit comments

Comments
 (0)