Skip to content

[code-completion] Generic where clauses #11267

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 1 commit into from
Jul 31, 2017
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
4 changes: 2 additions & 2 deletions include/swift/AST/DeclNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ABSTRACT_DECL(Value, Decl)
VALUE_DECL(AssociatedType, AbstractTypeParamDecl)
DECL_RANGE(AbstractTypeParam, GenericTypeParam, AssociatedType)
ABSTRACT_DECL(GenericType, TypeDecl)
VALUE_DECL(TypeAlias, GenericTypeDecl)
CONTEXT_VALUE_DECL(TypeAlias, GenericTypeDecl)
ABSTRACT_DECL(NominalType, GenericTypeDecl)
NOMINAL_TYPE_DECL(Enum, NominalTypeDecl)
NOMINAL_TYPE_DECL(Struct, NominalTypeDecl)
Expand All @@ -121,7 +121,7 @@ ABSTRACT_DECL(Value, Decl)
ABSTRACT_DECL(AbstractStorage, ValueDecl)
VALUE_DECL(Var, AbstractStorageDecl)
VALUE_DECL(Param, VarDecl)
VALUE_DECL(Subscript, AbstractStorageDecl)
CONTEXT_VALUE_DECL(Subscript, AbstractStorageDecl)
DECL_RANGE(AbstractStorage, Var, Subscript)
ABSTRACT_DECL(AbstractFunction, ValueDecl)
FUNCTION_DECL(Constructor, AbstractFunctionDecl)
Expand Down
9 changes: 6 additions & 3 deletions include/swift/Parse/CodeCompletionCallbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class CodeCompletionCallbacks {

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

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

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

void setLeadingSequenceExprs(ArrayRef<Expr *> exprs) {
Expand Down
6 changes: 2 additions & 4 deletions lib/AST/LookupVisibleDecls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,6 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
// and if so, whether this is a reference to one of them.
while (!DC->isModuleScopeContext()) {
const ValueDecl *BaseDecl = nullptr;
GenericParamList *GenericParams = nullptr;
Type ExtendedType;
auto LS = LookupState::makeUnqualified();

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

GenericParamList *GenericParams = DC->getGenericParamsOfContext();

if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
// Look for local variables; normally, the parser resolves these
// for us, but it can't do the right thing inside local types.
Expand Down Expand Up @@ -922,9 +923,6 @@ void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer,
if (FD->isStatic())
ExtendedType = MetatypeType::get(ExtendedType);
}

// Look in the generic parameters after checking our local declaration.
GenericParams = AFD->getGenericParams();
} else if (auto CE = dyn_cast<ClosureExpr>(DC)) {
if (Loc.isValid()) {
namelookup::FindLocalVal(SM, Loc, Consumer).visit(CE->getBody());
Expand Down
12 changes: 6 additions & 6 deletions lib/IDE/CodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1381,9 +1381,9 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
}

/// \returns true on success, false on failure.
bool typecheckDelayedParsedDecl() {
assert(DelayedParsedDecl && "should have a delayed parsed decl");
return typeCheckCompletionDecl(DelayedParsedDecl);
bool typecheckParsedDecl() {
assert(ParsedDecl && "should have a parsed decl");
return typeCheckCompletionDecl(ParsedDecl);
}

Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
Expand Down Expand Up @@ -5117,11 +5117,11 @@ void CodeCompletionCallbacksImpl::doneParsing() {
if (!typecheckContext())
return;

if (DelayedParsedDecl && !typecheckDelayedParsedDecl())
if (ParsedDecl && !typecheckParsedDecl())
return;

if (auto *AFD = dyn_cast_or_null<AbstractFunctionDecl>(DelayedParsedDecl))
CurDeclContext = AFD;
if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl))
CurDeclContext = DC;

Optional<Type> ExprType;
ConcreteDeclRef ReferencedDecl = nullptr;
Expand Down
82 changes: 53 additions & 29 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3208,9 +3208,7 @@ parseDeclTypeAlias(Parser::ParseDeclOptions Flags, DeclAttributes &Attributes) {

// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
auto whereStatus = parseFreestandingGenericWhereClause(genericParams);
if (whereStatus.shouldStopParsing())
return whereStatus;
Status |= parseFreestandingGenericWhereClause(genericParams);
}

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

if (Status.hasCodeCompletion() && CodeCompletion)
CodeCompletion->setParsedDecl(TAD);

// Exit the scope introduced for the generic parameters.
GenericsScope.reset();

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

auto NameTokText = NameTok.getRawText();
markSplitToken(tok::identifier,
Expand All @@ -4794,9 +4795,9 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
} else {
auto Result = maybeParseGenericParams();
GenericParams = Result.getPtrOrNull();
GPHasCodeCompletion |= Result.hasCodeCompletion();
SignatureHasCodeCompletion |= Result.hasCodeCompletion();
}
if (GPHasCodeCompletion && !CodeCompletion)
if (SignatureHasCodeCompletion && !CodeCompletion)
return makeParserCodeCompletionStatus();

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

SignatureHasCodeCompletion |= SignatureStatus.hasCodeCompletion();
if (SignatureStatus.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return SignatureStatus;
Expand All @@ -4830,8 +4832,11 @@ Parser::parseDeclFunc(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
if (whereStatus.shouldStopParsing())
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
}

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

// Code completion for the generic type params.
if (GPHasCodeCompletion)
CodeCompletion->setDelayedParsedDecl(FD);

// Pass the function signature to code completion.
if (SignatureStatus.hasCodeCompletion())
CodeCompletion->setDelayedParsedDecl(FD);
if (SignatureHasCodeCompletion)
CodeCompletion->setParsedDecl(FD);

DefaultArgs.setFunctionContext(FD);
for (auto PL : FD->getParameterLists())
Expand Down Expand Up @@ -5015,11 +5016,17 @@ ParserResult<EnumDecl> Parser::parseDeclEnum(ParseDeclOptions Flags,
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
if (whereStatus.shouldStopParsing())
Status |= whereStatus;
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
ED->setGenericParams(GenericParams);
}

if (Status.hasCodeCompletion() && CodeCompletion)
CodeCompletion->setParsedDecl(ED);

SourceLoc LBLoc, RBLoc;
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_enum)) {
LBLoc = PreviousLoc;
Expand Down Expand Up @@ -5272,11 +5279,16 @@ ParserResult<StructDecl> Parser::parseDeclStruct(ParseDeclOptions Flags,
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
if (whereStatus.shouldStopParsing())
Status |= whereStatus;
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
SD->setGenericParams(GenericParams);
}

if (Status.hasCodeCompletion() && CodeCompletion)
CodeCompletion->setParsedDecl(SD);

SourceLoc LBLoc, RBLoc;
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) {
Expand Down Expand Up @@ -5355,11 +5367,17 @@ ParserResult<ClassDecl> Parser::parseDeclClass(SourceLoc ClassLoc,
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
if (whereStatus.shouldStopParsing())
Status |= whereStatus;
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
CD->setGenericParams(GenericParams);
}

if (Status.hasCodeCompletion() && CodeCompletion)
CodeCompletion->setParsedDecl(CD);

SourceLoc LBLoc, RBLoc;
if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_class)) {
LBLoc = PreviousLoc;
Expand Down Expand Up @@ -5502,13 +5520,13 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
Optional<Scope> GenericsScope;
GenericsScope.emplace(this, ScopeKind::Generics);
GenericParamList *GenericParams;
bool GPHasCodeCompletion = false;
bool SignatureHasCodeCompletion = false;

auto Result = maybeParseGenericParams();
GenericParams = Result.getPtrOrNull();
GPHasCodeCompletion |= Result.hasCodeCompletion();
SignatureHasCodeCompletion |= Result.hasCodeCompletion();

if (GPHasCodeCompletion && !CodeCompletion)
if (SignatureHasCodeCompletion && !CodeCompletion)
return makeParserCodeCompletionStatus();

// Parse the parameter list.
Expand Down Expand Up @@ -5537,8 +5555,11 @@ Parser::parseDeclSubscript(ParseDeclOptions Flags,
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
if (whereStatus.shouldStopParsing())
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
}

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

// Code completion for the generic type params.
//
// FIXME: What is this?
if (GPHasCodeCompletion)
CodeCompletion->setDelayedParsedDecl(Subscript);
// Pass the function signature to code completion.
if (SignatureHasCodeCompletion)
CodeCompletion->setParsedDecl(Subscript);

Decls.push_back(Subscript);

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

SignatureHasCodeCompletion |= Params.hasCodeCompletion();
if (Params.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return makeParserCodeCompletionStatus();
Expand All @@ -5661,8 +5682,11 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
// Parse a 'where' clause if present, adding it to our GenericParamList.
if (Tok.is(tok::kw_where)) {
auto whereStatus = parseFreestandingGenericWhereClause(GenericParams);
if (whereStatus.shouldStopParsing())
SignatureHasCodeCompletion |= whereStatus.hasCodeCompletion();
if (whereStatus.hasCodeCompletion() && !CodeCompletion) {
// Trigger delayed parsing, no need to continue.
return whereStatus;
}
}

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

// Pass the function signature to code completion.
if (Params.hasCodeCompletion())
CodeCompletion->setDelayedParsedDecl(CD);
if (SignatureHasCodeCompletion)
CodeCompletion->setParsedDecl(CD);

if (ConstructorsNotAllowed || Params.isParseError()) {
// Tell the type checker not to touch this constructor.
Expand Down
10 changes: 6 additions & 4 deletions lib/Parse/ParseGeneric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,14 @@ ParserStatus Parser::parseGenericWhereClause(
do {
// Parse the leading type-identifier.
ParserResult<TypeRepr> FirstType = parseTypeIdentifier();

if (FirstType.hasCodeCompletion()) {
Status.setHasCodeCompletion();
FirstTypeInComplete = true;
}

if (FirstType.isNull()) {
Status.setIsParseError();
if (FirstType.hasCodeCompletion()) {
Status.setHasCodeCompletion();
FirstTypeInComplete = true;
}
break;
}

Expand Down
Loading