Skip to content

[Parse/CodeCompletion] Cleanup code completion facilities in Parse #28182

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 3 commits into from
Nov 13, 2019
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
18 changes: 11 additions & 7 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace llvm {

namespace swift {
class CodeCompletionCallbacks;
class CodeCompletionCallbacksFactory;
class DefaultArgumentInitializer;
class DiagnosticEngine;
class Expr;
Expand Down Expand Up @@ -867,8 +868,6 @@ class Parser {
BraceItemListKind::Brace);
ParserResult<BraceStmt> parseBraceItemList(Diag<> ID);

void parseTopLevelCodeDeclDelayed();

//===--------------------------------------------------------------------===//
// Decl Parsing

Expand All @@ -895,8 +894,6 @@ class Parser {
/// Options that control the parsing of declarations.
using ParseDeclOptions = OptionSet<ParseDeclFlags>;

void delayParseFromBeginningToHere(ParserPosition BeginParserPosition,
ParseDeclOptions Flags);
void consumeDecl(ParserPosition BeginParserPosition, ParseDeclOptions Flags,
bool IsTopLevel);

Expand All @@ -921,8 +918,6 @@ class Parser {
bool IsAtStartOfLineOrPreviousHadSemi,
llvm::function_ref<void(Decl*)> Handler);

void parseDeclDelayed();

std::vector<Decl *> parseDeclListDelayed(IterableDeclContext *IDC);

bool parseMemberDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
Expand Down Expand Up @@ -1091,7 +1086,6 @@ class Parser {
bool HasFuncKeyword = true);
void parseAbstractFunctionBody(AbstractFunctionDecl *AFD);
BraceStmt *parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
void parseAbstractFunctionBodyDelayed();
ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags,
DeclAttributes &Attributes);

Expand Down Expand Up @@ -1585,6 +1579,16 @@ class Parser {
parsePlatformVersionConstraintSpec();
ParserResult<PlatformAgnosticVersionConstraintAvailabilitySpec>
parsePlatformAgnosticVersionConstraintSpec();

//===--------------------------------------------------------------------===//
// Code completion second pass.

static void
performCodeCompletionSecondPass(PersistentParserState &ParserState,
CodeCompletionCallbacksFactory &Factory);

void performCodeCompletionSecondPassImpl(
PersistentParserState::CodeCompletionDelayedDeclState &info);
};

/// Describes a parsed declaration name.
Expand Down
83 changes: 29 additions & 54 deletions include/swift/Parse/PersistentParserState.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@
#ifndef SWIFT_PARSE_PERSISTENTPARSERSTATE_H
#define SWIFT_PARSE_PERSISTENTPARSERSTATE_H

#include "swift/AST/LazyResolver.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/Parse/LocalContext.h"
#include "swift/Parse/ParserPosition.h"
#include "swift/Parse/Scope.h"
#include "llvm/ADT/DenseMap.h"

namespace swift {
class AbstractFunctionDecl;

class SourceFile;
class DeclContext;
class IterableDeclContext;

/// Parser state persistent across multiple parses.
class PersistentParserState {
Expand All @@ -37,32 +39,16 @@ class PersistentParserState {
bool isValid() const { return Loc.isValid(); }
};

class FunctionBodyState {
ParserPos BodyPos;
SavedScope Scope;
friend class Parser;

SavedScope takeScope() {
return std::move(Scope);
}

public:
FunctionBodyState(SourceRange BodyRange, SourceLoc PreviousLoc,
SavedScope &&Scope)
: BodyPos{BodyRange.Start, PreviousLoc}, Scope(std::move(Scope))
{}
};

enum class DelayedDeclKind {
enum class CodeCompletionDelayedDeclKind {
TopLevelCodeDecl,
Decl,
FunctionBody,
};

class DelayedDeclState {
class CodeCompletionDelayedDeclState {
friend class PersistentParserState;
friend class Parser;
DelayedDeclKind Kind;
CodeCompletionDelayedDeclKind Kind;
unsigned Flags;
DeclContext *ParentContext;
ParserPos BodyPos;
Expand All @@ -74,13 +60,13 @@ class PersistentParserState {
}

public:
DelayedDeclState(DelayedDeclKind Kind, unsigned Flags,
DeclContext *ParentContext, SourceRange BodyRange,
SourceLoc PreviousLoc, SavedScope &&Scope)
: Kind(Kind), Flags(Flags), ParentContext(ParentContext),
BodyPos{BodyRange.Start, PreviousLoc},
BodyEnd(BodyRange.End), Scope(std::move(Scope))
{}
CodeCompletionDelayedDeclState(CodeCompletionDelayedDeclKind Kind,
unsigned Flags, DeclContext *ParentContext,
SourceRange BodyRange, SourceLoc PreviousLoc,
SavedScope &&Scope)
: Kind(Kind), Flags(Flags),
ParentContext(ParentContext), BodyPos{BodyRange.Start, PreviousLoc},
BodyEnd(BodyRange.End), Scope(std::move(Scope)) {}
};

bool InPoundLineEnvironment = false;
Expand All @@ -89,15 +75,11 @@ class PersistentParserState {
bool PerformConditionEvaluation = true;
private:
ScopeInfo ScopeInfo;
using DelayedFunctionBodiesTy =
llvm::DenseMap<AbstractFunctionDecl *,
std::unique_ptr<FunctionBodyState>>;
DelayedFunctionBodiesTy DelayedFunctionBodies;

/// Parser sets this if it stopped parsing before the buffer ended.
ParserPosition MarkedPos;

std::unique_ptr<DelayedDeclState> CodeCompletionDelayedDeclState;
std::unique_ptr<CodeCompletionDelayedDeclState> CodeCompletionDelayedDeclStat;

std::vector<IterableDeclContext *> DelayedDeclLists;

Expand All @@ -110,31 +92,24 @@ class PersistentParserState {
PersistentParserState(ASTContext &ctx) : PersistentParserState() { }
~PersistentParserState();

void delayDecl(DelayedDeclKind Kind, unsigned Flags,
DeclContext *ParentContext,
SourceRange BodyRange, SourceLoc PreviousLoc);

void delayDeclList(IterableDeclContext *D);
void setCodeCompletionDelayedDeclState(CodeCompletionDelayedDeclKind Kind,
unsigned Flags,
DeclContext *ParentContext,
SourceRange BodyRange,
SourceLoc PreviousLoc);

void delayTopLevel(TopLevelCodeDecl *TLCD, SourceRange BodyRange,
SourceLoc PreviousLoc);

bool hasDelayedDecl() {
return CodeCompletionDelayedDeclState.get() != nullptr;
}
DelayedDeclKind getDelayedDeclKind() {
return CodeCompletionDelayedDeclState->Kind;
bool hasCodeCompletionDelayedDeclState() {
return CodeCompletionDelayedDeclStat.get() != nullptr;
}
SourceLoc getDelayedDeclLoc() {
return CodeCompletionDelayedDeclState->BodyPos.Loc;
}
DeclContext *getDelayedDeclContext() {
return CodeCompletionDelayedDeclState->ParentContext;
}
std::unique_ptr<DelayedDeclState> takeDelayedDeclState() {
return std::move(CodeCompletionDelayedDeclState);

std::unique_ptr<CodeCompletionDelayedDeclState>
takeCodeCompletionDelayedDeclState() {
assert(hasCodeCompletionDelayedDeclState());
return std::move(CodeCompletionDelayedDeclStat);
}

void delayDeclList(IterableDeclContext *D);

void parseAllDelayedDeclLists();

TopLevelContext &getTopLevelContext() {
Expand Down
111 changes: 19 additions & 92 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3008,9 +3008,10 @@ void Parser::consumeDecl(ParserPosition BeginParserPosition,
backtrackToPosition(BeginParserPosition);
SourceLoc BeginLoc = Tok.getLoc();

State->delayDecl(PersistentParserState::DelayedDeclKind::Decl, Flags.toRaw(),
CurDeclContext, {BeginLoc, EndLoc},
BeginParserPosition.PreviousLoc);
State->setCodeCompletionDelayedDeclState(
PersistentParserState::CodeCompletionDelayedDeclKind::Decl,
Flags.toRaw(), CurDeclContext, {BeginLoc, EndLoc},
BeginParserPosition.PreviousLoc);

while (SourceMgr.isBeforeInBuffer(Tok.getLoc(), CurrentLoc))
consumeToken();
Expand Down Expand Up @@ -3045,21 +3046,6 @@ void Parser::setLocalDiscriminatorToParamList(ParameterList *PL) {
}
}

void Parser::delayParseFromBeginningToHere(ParserPosition BeginParserPosition,
ParseDeclOptions Flags) {
auto CurLoc = Tok.getLoc();
backtrackToPosition(BeginParserPosition);
SourceLoc BeginLoc = Tok.getLoc();
SourceLoc EndLoc = CurLoc;
State->delayDecl(PersistentParserState::DelayedDeclKind::Decl,
Flags.toRaw(),
CurDeclContext, {BeginLoc, EndLoc},
BeginParserPosition.PreviousLoc);

while (Tok.isNot(tok::eof))
consumeToken();
}

/// Parse a single syntactic declaration and return a list of decl
/// ASTs. This can return multiple results for var decls that bind to multiple
/// values, structs that define a struct decl and a constructor, etc.
Expand Down Expand Up @@ -3429,26 +3415,23 @@ Parser::parseDecl(ParseDeclOptions Flags,
consumeToken(tok::code_complete);
}

if (AttrStatus.hasCodeCompletion()) {
if (CodeCompletion) {
if (AttrStatus.hasCodeCompletion() || DeclResult.hasCodeCompletion()) {
if (isCodeCompletionFirstPass() &&
!CurDeclContext->isModuleScopeContext() &&
!isa<TopLevelCodeDecl>(CurDeclContext) &&
!isa<AbstractClosureExpr>(CurDeclContext)) {
// Only consume non-toplevel decls.
consumeDecl(BeginParserPosition, Flags, /*IsTopLevel=*/false);

return makeParserError();
}
if (AttrStatus.hasCodeCompletion() && CodeCompletion) {
Optional<DeclKind> DK;
if (DeclResult.isNonNull())
DK = DeclResult.get()->getKind();
CodeCompletion->setAttrTargetDeclKind(DK);
} else {
delayParseFromBeginningToHere(BeginParserPosition, Flags);
return makeParserError();
}
}

if (DeclResult.hasCodeCompletion() && isCodeCompletionFirstPass() &&
!CurDeclContext->isModuleScopeContext() &&
!isa<TopLevelCodeDecl>(CurDeclContext) &&
!isa<AbstractClosureExpr>(CurDeclContext)) {
// Only consume non-toplevel decls.
consumeDecl(BeginParserPosition, Flags, /*IsTopLevel=*/false);

return makeParserError();
DeclResult.setHasCodeCompletion();
}

if (auto SF = CurDeclContext->getParentSourceFile()) {
Expand Down Expand Up @@ -3593,48 +3576,6 @@ std::vector<Decl *> Parser::parseDeclListDelayed(IterableDeclContext *IDC) {
return parseDeclList(LBLoc, RBLoc, Id, Options, IDC, hadError);
}

void Parser::parseDeclDelayed() {
auto DelayedState = State->takeDelayedDeclState();
assert(DelayedState.get() && "should have delayed state");

auto BeginParserPosition = getParserPosition(DelayedState->BodyPos);
auto EndLexerState = L->getStateForEndOfTokenLoc(DelayedState->BodyEnd);

// ParserPositionRAII needs a primed parser to restore to.
if (Tok.is(tok::NUM_TOKENS))
consumeTokenWithoutFeedingReceiver();

// Ensure that we restore the parser state at exit.
ParserPositionRAII PPR(*this);

// Create a lexer that cannot go past the end state.
Lexer LocalLex(*L, BeginParserPosition.LS, EndLexerState);

// Temporarily swap out the parser's current lexer with our new one.
llvm::SaveAndRestore<Lexer *> T(L, &LocalLex);

// Rewind to the beginning of the decl.
restoreParserPosition(BeginParserPosition);

// Re-enter the lexical scope.
Scope S(this, DelayedState->takeScope());
ContextChange CC(*this, DelayedState->ParentContext);

parseDecl(ParseDeclOptions(DelayedState->Flags),
/*IsAtStartOfLineOrPreviousHadSemi=*/true,
[&](Decl *D) {
if (auto *parent = DelayedState->ParentContext) {
if (auto *NTD = dyn_cast<NominalTypeDecl>(parent)) {
NTD->addMember(D);
} else if (auto *ED = dyn_cast<ExtensionDecl>(parent)) {
ED->addMember(D);
} else if (auto *SF = dyn_cast<SourceFile>(parent)) {
SF->Decls.push_back(D);
}
}
});
}

/// Parse an 'import' declaration, doing no token skipping on error.
///
/// \verbatim
Expand Down Expand Up @@ -5658,9 +5599,9 @@ void Parser::consumeAbstractFunctionBody(AbstractFunctionDecl *AFD,

if (isCodeCompletionFirstPass()) {
if (SourceMgr.rangeContainsCodeCompletionLoc(BodyRange)) {
State->delayDecl(PersistentParserState::DelayedDeclKind::FunctionBody,
PD_Default, AFD, BodyRange,
BeginParserPosition.PreviousLoc);
State->setCodeCompletionDelayedDeclState(
PersistentParserState::CodeCompletionDelayedDeclKind::FunctionBody,
PD_Default, AFD, BodyRange, BeginParserPosition.PreviousLoc);
} else {
AFD->setBodySkipped(BodyRange);
}
Expand Down Expand Up @@ -5975,20 +5916,6 @@ BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
return parseBraceItemList(diag::func_decl_without_brace).getPtrOrNull();
}

/// Parse a delayed function body from the 'PersistentParserState'.
void Parser::parseAbstractFunctionBodyDelayed() {
auto DelayedState = State->takeDelayedDeclState();
assert(DelayedState.get() && "should have delayed state");
auto CD = DelayedState->ParentContext->getAsDecl();
auto AFD = cast<AbstractFunctionDecl>(CD);

// Eagarly parse local decls or nested function bodies inside the body.
llvm::SaveAndRestore<bool> DisableDelayedBody(DelayBodyParsing, false);

auto body = parseAbstractFunctionBodyDelayed(AFD);
AFD->setBodyParsed(body);
}

/// Parse a 'enum' declaration, returning true (and doing no token
/// skipping) on error.
///
Expand Down
Loading