mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #29741 from hamishknight/moving-states
Move PersistentParserState onto SourceFile
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
class PersistentParserState;
|
||||
|
||||
/// A file containing Swift source code.
|
||||
///
|
||||
/// This is a .swift or .sil file (or a virtual file, such as the contents of
|
||||
@@ -154,6 +156,16 @@ private:
|
||||
/// mechanism which is not SourceFile-dependent.)
|
||||
SeparatelyImportedOverlayMap separatelyImportedOverlays;
|
||||
|
||||
/// A pointer to PersistentParserState with a function reference to its
|
||||
/// deleter to handle the fact that it's forward declared.
|
||||
using ParserStatePtr =
|
||||
std::unique_ptr<PersistentParserState, void (*)(PersistentParserState *)>;
|
||||
|
||||
/// Stores delayed parser state that code completion needs to be able to
|
||||
/// resume parsing at the code completion token in the file.
|
||||
ParserStatePtr DelayedParserState =
|
||||
ParserStatePtr(/*ptr*/ nullptr, /*deleter*/ nullptr);
|
||||
|
||||
friend ASTContext;
|
||||
friend Impl;
|
||||
|
||||
@@ -405,6 +417,20 @@ public:
|
||||
/// Retrieve the scope that describes this source file.
|
||||
ASTScope &getScope();
|
||||
|
||||
/// Retrieves the previously set delayed parser state, asserting that it
|
||||
/// exists.
|
||||
PersistentParserState *getDelayedParserState() {
|
||||
auto *state = DelayedParserState.get();
|
||||
assert(state && "Didn't set any delayed parser state!");
|
||||
return state;
|
||||
}
|
||||
|
||||
/// Record delayed parser state for the source file. This is needed for code
|
||||
/// completion's second pass.
|
||||
void setDelayedParserState(ParserStatePtr &&state) {
|
||||
DelayedParserState = std::move(state);
|
||||
}
|
||||
|
||||
SWIFT_DEBUG_DUMP;
|
||||
void dump(raw_ostream &os) const;
|
||||
|
||||
|
||||
@@ -400,8 +400,6 @@ class CompilerInstance {
|
||||
std::unique_ptr<Lowering::TypeConverter> TheSILTypes;
|
||||
std::unique_ptr<SILModule> TheSILModule;
|
||||
|
||||
std::unique_ptr<PersistentParserState> PersistentState;
|
||||
|
||||
/// Null if no tracker.
|
||||
std::unique_ptr<DependencyTracker> DepTracker;
|
||||
/// If there is no stats output directory by the time the
|
||||
@@ -431,6 +429,9 @@ class CompilerInstance {
|
||||
/// buffer will also have its buffer ID in PrimaryBufferIDs.
|
||||
std::vector<SourceFile *> PrimarySourceFiles;
|
||||
|
||||
/// The file that has been registered for code completion.
|
||||
NullablePtr<SourceFile> CodeCompletionFile;
|
||||
|
||||
/// Return whether there is an entry in PrimaryInputs for buffer \p BufID.
|
||||
bool isPrimaryInput(unsigned BufID) const {
|
||||
return PrimaryBufferIDs.count(BufID) != 0;
|
||||
@@ -550,12 +551,13 @@ public:
|
||||
return Invocation;
|
||||
}
|
||||
|
||||
bool hasPersistentParserState() const {
|
||||
return bool(PersistentState);
|
||||
}
|
||||
/// If a code completion buffer has been set, returns the corresponding source
|
||||
/// file.
|
||||
NullablePtr<SourceFile> getCodeCompletionFile() { return CodeCompletionFile; }
|
||||
|
||||
PersistentParserState &getPersistentParserState() {
|
||||
return *PersistentState.get();
|
||||
/// Set a new file that we're performing code completion on.
|
||||
void setCodeCompletionFile(SourceFile *file) {
|
||||
CodeCompletionFile = file;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -223,6 +223,13 @@ public:
|
||||
/// lazily parsed and type checked.
|
||||
bool DelayBodyParsing;
|
||||
|
||||
/// Whether to evaluate the conditions of #if decls, meaning that the bodies
|
||||
/// of any active clauses are hoisted such that they become sibling nodes with
|
||||
/// the #if decl.
|
||||
// FIXME: When condition evaluation moves to a later phase, remove this bit
|
||||
// and adjust the client call 'performParseOnly'.
|
||||
bool EvaluateConditionals;
|
||||
|
||||
/// The receiver to collect all consumed tokens.
|
||||
ConsumeTokenReceiver *TokReceiver;
|
||||
|
||||
@@ -401,16 +408,16 @@ public:
|
||||
SILParserTUStateBase *SIL,
|
||||
PersistentParserState *PersistentState,
|
||||
std::shared_ptr<SyntaxParseActions> SPActions = nullptr,
|
||||
bool DelayBodyParsing = true);
|
||||
bool DelayBodyParsing = true, bool EvaluateConditionals = true);
|
||||
Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
|
||||
PersistentParserState *PersistentState = nullptr,
|
||||
std::shared_ptr<SyntaxParseActions> SPActions = nullptr,
|
||||
bool DelayBodyParsing = true);
|
||||
bool DelayBodyParsing = true, bool EvaluateConditionals = true);
|
||||
Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF,
|
||||
SILParserTUStateBase *SIL = nullptr,
|
||||
PersistentParserState *PersistentState = nullptr,
|
||||
std::shared_ptr<SyntaxParseActions> SPActions = nullptr,
|
||||
bool DelayBodyParsing = true);
|
||||
bool DelayBodyParsing = true, bool EvaluateConditionals = true);
|
||||
~Parser();
|
||||
|
||||
/// Returns true if the buffer being parsed is allowed to contain SIL.
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#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"
|
||||
|
||||
@@ -58,11 +57,6 @@ public:
|
||||
|
||||
/// Parser state persistent across multiple parses.
|
||||
class PersistentParserState {
|
||||
public:
|
||||
// FIXME: When condition evaluation moves to a later phase, remove this bit
|
||||
// and adjust the client call 'performParseOnly'.
|
||||
bool PerformConditionEvaluation = true;
|
||||
private:
|
||||
swift::ScopeInfo ScopeInfo;
|
||||
|
||||
std::unique_ptr<CodeCompletionDelayedDeclState> CodeCompletionDelayedDeclStat;
|
||||
@@ -85,13 +79,17 @@ public:
|
||||
void restoreCodeCompletionDelayedDeclState(
|
||||
const CodeCompletionDelayedDeclState &other);
|
||||
|
||||
bool hasCodeCompletionDelayedDeclState() {
|
||||
bool hasCodeCompletionDelayedDeclState() const {
|
||||
return CodeCompletionDelayedDeclStat.get() != nullptr;
|
||||
}
|
||||
|
||||
CodeCompletionDelayedDeclState &getCodeCompletionDelayedDeclState() {
|
||||
return *CodeCompletionDelayedDeclStat.get();
|
||||
}
|
||||
const CodeCompletionDelayedDeclState &
|
||||
getCodeCompletionDelayedDeclState() const {
|
||||
return *CodeCompletionDelayedDeclStat.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<CodeCompletionDelayedDeclState>
|
||||
takeCodeCompletionDelayedDeclState() {
|
||||
|
||||
@@ -55,7 +55,6 @@ namespace swift {
|
||||
class ModuleDecl;
|
||||
typedef void *OpaqueSyntaxNode;
|
||||
class Parser;
|
||||
class PersistentParserState;
|
||||
class SerializationOptions;
|
||||
class SILOptions;
|
||||
class SILModule;
|
||||
@@ -110,20 +109,17 @@ namespace swift {
|
||||
///
|
||||
/// \param BufferID The buffer to parse from.
|
||||
///
|
||||
/// \param PersistentState If non-null the same PersistentState object can be
|
||||
/// used to save parser state for code completion.
|
||||
///
|
||||
/// \param DelayBodyParsing Whether parsing of type and function bodies can be
|
||||
/// delayed.
|
||||
void parseIntoSourceFile(SourceFile &SF, unsigned BufferID,
|
||||
PersistentParserState *PersistentState = nullptr,
|
||||
bool DelayBodyParsing = true);
|
||||
bool DelayBodyParsing = true,
|
||||
bool EvaluateConditionals = true);
|
||||
|
||||
/// Parse a source file's SIL declarations into a given SIL module.
|
||||
void parseSourceFileSIL(SourceFile &SF, SILParserState *sil);
|
||||
|
||||
/// Finish the code completion.
|
||||
void performCodeCompletionSecondPass(PersistentParserState &PersistentState,
|
||||
void performCodeCompletionSecondPass(SourceFile &SF,
|
||||
CodeCompletionCallbacksFactory &Factory);
|
||||
|
||||
/// Lex and return a vector of tokens for the given buffer.
|
||||
|
||||
@@ -906,8 +906,6 @@ void CompilerInstance::parseAndCheckTypesUpTo(
|
||||
const ImplicitImports &implicitImports, SourceFile::ASTStage_t limitStage) {
|
||||
FrontendStatsTracer tracer(getStatsReporter(), "parse-and-check-types");
|
||||
|
||||
PersistentState = std::make_unique<PersistentParserState>();
|
||||
|
||||
bool hadLoadError = parsePartialModulesAndLibraryFiles(implicitImports);
|
||||
if (Invocation.isCodeCompletion()) {
|
||||
// When we are doing code completion, make sure to emit at least one
|
||||
@@ -978,8 +976,7 @@ void CompilerInstance::parseLibraryFile(
|
||||
auto DidSuppressWarnings = Diags.getSuppressWarnings();
|
||||
Diags.setSuppressWarnings(DidSuppressWarnings || !IsPrimary);
|
||||
|
||||
parseIntoSourceFile(*NextInput, BufferID, PersistentState.get(),
|
||||
/*DelayedBodyParsing=*/!IsPrimary);
|
||||
parseIntoSourceFile(*NextInput, BufferID, /*DelayedBodyParsing=*/!IsPrimary);
|
||||
|
||||
Diags.setSuppressWarnings(DidSuppressWarnings);
|
||||
|
||||
@@ -1026,7 +1023,7 @@ void CompilerInstance::parseAndTypeCheckMainFileUpTo(
|
||||
Diags.setSuppressWarnings(DidSuppressWarnings || !mainIsPrimary);
|
||||
|
||||
// Parse the Swift decls into the source file.
|
||||
parseIntoSourceFile(MainFile, MainBufferID, PersistentState.get(),
|
||||
parseIntoSourceFile(MainFile, MainBufferID,
|
||||
/*delayBodyParsing*/ !mainIsPrimary);
|
||||
|
||||
// For a primary, also perform type checking if needed. Otherwise, just do
|
||||
@@ -1096,6 +1093,11 @@ SourceFile *CompilerInstance::createSourceFileForMainModule(
|
||||
recordPrimarySourceFile(inputFile);
|
||||
}
|
||||
|
||||
if (bufferID == SourceMgr.getCodeCompletionBufferID()) {
|
||||
assert(!CodeCompletionFile && "Multiple code completion files?");
|
||||
CodeCompletionFile = inputFile;
|
||||
}
|
||||
|
||||
return inputFile;
|
||||
}
|
||||
|
||||
@@ -1121,9 +1123,6 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
|
||||
MainBufferID);
|
||||
}
|
||||
|
||||
PersistentState = std::make_unique<PersistentParserState>();
|
||||
PersistentState->PerformConditionEvaluation = EvaluateConditionals;
|
||||
|
||||
auto shouldDelayBodies = [&](unsigned bufferID) -> bool {
|
||||
if (!CanDelayBodies)
|
||||
return false;
|
||||
@@ -1141,8 +1140,8 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
|
||||
SourceFileKind::Library, SourceFile::ImplicitModuleImportKind::None,
|
||||
BufferID);
|
||||
|
||||
parseIntoSourceFile(*NextInput, BufferID, PersistentState.get(),
|
||||
shouldDelayBodies(BufferID));
|
||||
parseIntoSourceFile(*NextInput, BufferID, shouldDelayBodies(BufferID),
|
||||
EvaluateConditionals);
|
||||
}
|
||||
|
||||
// Now parse the main file.
|
||||
@@ -1152,8 +1151,8 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
|
||||
MainFile.SyntaxParsingCache = Invocation.getMainFileSyntaxParsingCache();
|
||||
assert(MainBufferID == MainFile.getBufferID());
|
||||
|
||||
parseIntoSourceFile(MainFile, MainBufferID, PersistentState.get(),
|
||||
shouldDelayBodies(MainBufferID));
|
||||
parseIntoSourceFile(MainFile, MainBufferID, shouldDelayBodies(MainBufferID),
|
||||
EvaluateConditionals);
|
||||
}
|
||||
|
||||
assert(Context->LoadedModules.size() == 1 &&
|
||||
@@ -1161,7 +1160,6 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
|
||||
}
|
||||
|
||||
void CompilerInstance::freeASTContext() {
|
||||
PersistentState.reset();
|
||||
TheSILTypes.reset();
|
||||
Context.reset();
|
||||
MainModule = nullptr;
|
||||
|
||||
@@ -176,21 +176,17 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
|
||||
return false;
|
||||
|
||||
auto &CI = *CachedCI;
|
||||
auto *oldSF = CI.getCodeCompletionFile().get();
|
||||
|
||||
if (!CI.hasPersistentParserState())
|
||||
return false;
|
||||
auto &oldState = CI.getPersistentParserState();
|
||||
if (!oldState.hasCodeCompletionDelayedDeclState())
|
||||
return false;
|
||||
auto *oldState = oldSF->getDelayedParserState();
|
||||
assert(oldState->hasCodeCompletionDelayedDeclState());
|
||||
auto &oldInfo = oldState->getCodeCompletionDelayedDeclState();
|
||||
|
||||
auto &SM = CI.getSourceMgr();
|
||||
if (SM.getIdentifierForBuffer(SM.getCodeCompletionBufferID()) !=
|
||||
completionBuffer->getBufferIdentifier())
|
||||
return false;
|
||||
|
||||
auto &oldInfo = oldState.getCodeCompletionDelayedDeclState();
|
||||
auto *oldSF = oldInfo.ParentContext->getParentSourceFile();
|
||||
|
||||
// Parse the new buffer into temporary SourceFile.
|
||||
SourceManager tmpSM;
|
||||
auto tmpBufferID = tmpSM.addMemBufferCopy(completionBuffer);
|
||||
@@ -207,19 +203,20 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
|
||||
registerTypeCheckerRequestFunctions(tmpCtx->evaluator);
|
||||
registerSILGenRequestFunctions(tmpCtx->evaluator);
|
||||
ModuleDecl *tmpM = ModuleDecl::create(Identifier(), *tmpCtx);
|
||||
PersistentParserState newState;
|
||||
SourceFile *tmpSF =
|
||||
new (*tmpCtx) SourceFile(*tmpM, oldSF->Kind, tmpBufferID,
|
||||
SourceFile::ImplicitModuleImportKind::None);
|
||||
tmpSF->enableInterfaceHash();
|
||||
// Ensure all non-function-body tokens are hashed into the interface hash
|
||||
tmpCtx->LangOpts.EnableTypeFingerprints = false;
|
||||
parseIntoSourceFile(*tmpSF, tmpBufferID, &newState);
|
||||
parseIntoSourceFile(*tmpSF, tmpBufferID);
|
||||
|
||||
// Couldn't find any completion token?
|
||||
if (!newState.hasCodeCompletionDelayedDeclState())
|
||||
auto *newState = tmpSF->getDelayedParserState();
|
||||
if (!newState->hasCodeCompletionDelayedDeclState())
|
||||
return false;
|
||||
|
||||
auto &newInfo = newState.getCodeCompletionDelayedDeclState();
|
||||
auto &newInfo = newState->getCodeCompletionDelayedDeclState();
|
||||
unsigned newBufferID;
|
||||
|
||||
switch (newInfo.Kind) {
|
||||
@@ -273,7 +270,7 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
|
||||
|
||||
// Construct dummy scopes. We don't need to restore the original scope
|
||||
// because they are probably not 'isResolvable()' anyway.
|
||||
auto &SI = oldState.getScopeInfo();
|
||||
auto &SI = oldState->getScopeInfo();
|
||||
assert(SI.getCurrentScope() == nullptr);
|
||||
Scope Top(SI, ScopeKind::TopLevel);
|
||||
Scope Body(SI, ScopeKind::FunctionBody);
|
||||
@@ -282,7 +279,7 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
|
||||
oldInfo.StartOffset = newInfo.StartOffset;
|
||||
oldInfo.EndOffset = newInfo.EndOffset;
|
||||
oldInfo.PrevOffset = newInfo.PrevOffset;
|
||||
oldState.restoreCodeCompletionDelayedDeclState(oldInfo);
|
||||
oldState->restoreCodeCompletionDelayedDeclState(oldInfo);
|
||||
|
||||
auto *AFD = cast<AbstractFunctionDecl>(DC);
|
||||
if (AFD->isBodySkipped())
|
||||
@@ -324,14 +321,22 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
|
||||
CompilerInstance::addAdditionalInitialImportsTo(newSF, implicitImport);
|
||||
newSF->enableInterfaceHash();
|
||||
|
||||
// Tell the compiler instance we've replaced the code completion file.
|
||||
CI.setCodeCompletionFile(newSF);
|
||||
|
||||
// Re-parse the whole file. Still re-use imported modules.
|
||||
(void)oldState.takeCodeCompletionDelayedDeclState();
|
||||
parseIntoSourceFile(*newSF, newBufferID, &oldState);
|
||||
parseIntoSourceFile(*newSF, newBufferID);
|
||||
performNameBinding(*newSF);
|
||||
bindExtensions(*newSF);
|
||||
|
||||
assert(oldState.hasCodeCompletionDelayedDeclState() &&
|
||||
oldState.getCodeCompletionDelayedDeclState().Kind == newInfo.Kind);
|
||||
#ifndef NDEBUG
|
||||
const auto *reparsedState = newSF->getDelayedParserState();
|
||||
assert(reparsedState->hasCodeCompletionDelayedDeclState() &&
|
||||
"Didn't find completion token?");
|
||||
|
||||
auto &reparsedInfo = reparsedState->getCodeCompletionDelayedDeclState();
|
||||
assert(reparsedInfo.Kind == newInfo.Kind);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -360,10 +365,16 @@ bool CompletionInstance::performNewOperation(
|
||||
llvm::function_ref<void(CompilerInstance &)> Callback) {
|
||||
|
||||
auto TheInstance = std::make_unique<CompilerInstance>();
|
||||
{
|
||||
auto &CI = *TheInstance;
|
||||
if (DiagC)
|
||||
CI.addDiagnosticConsumer(DiagC);
|
||||
|
||||
SWIFT_DEFER {
|
||||
if (DiagC)
|
||||
CI.removeDiagnosticConsumer(DiagC);
|
||||
};
|
||||
|
||||
if (FileSystem != llvm::vfs::getRealFileSystem())
|
||||
CI.getSourceMgr().setFileSystem(FileSystem);
|
||||
|
||||
@@ -376,11 +387,20 @@ bool CompletionInstance::performNewOperation(
|
||||
registerIDERequestFunctions(CI.getASTContext().evaluator);
|
||||
|
||||
CI.performParseAndResolveImportsOnly();
|
||||
if (CI.hasPersistentParserState())
|
||||
Callback(CI);
|
||||
|
||||
if (DiagC)
|
||||
CI.removeDiagnosticConsumer(DiagC);
|
||||
// If we didn't create a source file for completion, bail. This can happen
|
||||
// if for example we fail to load the stdlib.
|
||||
auto completionFile = CI.getCodeCompletionFile();
|
||||
if (!completionFile)
|
||||
return true;
|
||||
|
||||
// If we didn't find a code completion token, bail.
|
||||
auto *state = completionFile.get()->getDelayedParserState();
|
||||
if (!state->hasCodeCompletionDelayedDeclState())
|
||||
return true;
|
||||
|
||||
Callback(CI);
|
||||
}
|
||||
|
||||
if (ArgsHash.hasValue()) {
|
||||
CachedCI = std::move(TheInstance);
|
||||
|
||||
@@ -232,11 +232,10 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
|
||||
newSF.addImports(importsWithOptions);
|
||||
}
|
||||
|
||||
PersistentParserState PersistentState;
|
||||
parseIntoSourceFile(newSF, *BufferID, &PersistentState);
|
||||
parseIntoSourceFile(newSF, *BufferID);
|
||||
performTypeChecking(newSF);
|
||||
|
||||
performCodeCompletionSecondPass(PersistentState, *CompletionCallbacksFactory);
|
||||
performCodeCompletionSecondPass(newSF, *CompletionCallbacksFactory);
|
||||
|
||||
// Reset the error state because it's only relevant to the code that we just
|
||||
// processed, which now gets thrown away.
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
#include "swift/IDE/REPLCodeCompletion.h"
|
||||
#include "swift/IDE/Utils.h"
|
||||
#include "swift/Parse/PersistentParserState.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
#include "swift/SILOptimizer/PassManager/Passes.h"
|
||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||
@@ -157,7 +156,6 @@ static void convertToUTF8(llvm::ArrayRef<wchar_t> wide,
|
||||
|
||||
static ModuleDecl *
|
||||
typeCheckREPLInput(ModuleDecl *MostRecentModule, StringRef Name,
|
||||
PersistentParserState &PersistentState,
|
||||
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
|
||||
using ImplicitModuleImportKind = SourceFile::ImplicitModuleImportKind;
|
||||
assert(MostRecentModule);
|
||||
@@ -187,7 +185,7 @@ typeCheckREPLInput(ModuleDecl *MostRecentModule, StringRef Name,
|
||||
REPLInputFile.addImports(ImportsWithOptions);
|
||||
}
|
||||
|
||||
parseIntoSourceFile(REPLInputFile, BufferID, &PersistentState);
|
||||
parseIntoSourceFile(REPLInputFile, BufferID);
|
||||
performTypeChecking(REPLInputFile);
|
||||
return REPLModule;
|
||||
}
|
||||
@@ -753,7 +751,6 @@ class REPLEnvironment {
|
||||
const SILOptions SILOpts;
|
||||
|
||||
REPLInput Input;
|
||||
PersistentParserState PersistentState;
|
||||
unsigned NextLineNumber = 0;
|
||||
|
||||
private:
|
||||
@@ -858,7 +855,7 @@ private:
|
||||
SmallString<8> Name{"REPL_"};
|
||||
llvm::raw_svector_ostream(Name) << NextLineNumber;
|
||||
++NextLineNumber;
|
||||
ModuleDecl *M = typeCheckREPLInput(MostRecentModule, Name, PersistentState,
|
||||
ModuleDecl *M = typeCheckREPLInput(MostRecentModule, Name,
|
||||
std::move(InputBuf));
|
||||
|
||||
// SILGen the module and produce SIL diagnostics.
|
||||
@@ -957,8 +954,7 @@ public:
|
||||
DumpModule("REPL", LLVMContext),
|
||||
IRGenOpts(),
|
||||
SILOpts(),
|
||||
Input(*this),
|
||||
PersistentState()
|
||||
Input(*this)
|
||||
{
|
||||
ASTContext &Ctx = CI.getASTContext();
|
||||
Ctx.LangOpts.EnableAccessControl = false;
|
||||
@@ -1005,8 +1001,7 @@ public:
|
||||
auto Buffer =
|
||||
llvm::MemoryBuffer::getMemBufferCopy(WarmUpStmt,
|
||||
"<REPL Initialization>");
|
||||
(void)typeCheckREPLInput(MostRecentModule, "__Warmup", PersistentState,
|
||||
std::move(Buffer));
|
||||
(void)typeCheckREPLInput(MostRecentModule, "__Warmup", std::move(Buffer));
|
||||
|
||||
if (Ctx.hadError())
|
||||
return;
|
||||
|
||||
@@ -609,7 +609,7 @@ ParserResult<IfConfigDecl> Parser::parseIfConfig(
|
||||
|
||||
bool shouldEvaluate =
|
||||
// Don't evaluate if it's in '-parse' mode, etc.
|
||||
State->PerformConditionEvaluation &&
|
||||
EvaluateConditionals &&
|
||||
// If it's in inactive #if ... #endif block, there's no point to do it.
|
||||
!getScopeInfo().isInactiveConfigBlock();
|
||||
|
||||
|
||||
@@ -112,20 +112,20 @@ using namespace swift::syntax;
|
||||
void SILParserTUStateBase::anchor() { }
|
||||
|
||||
void swift::performCodeCompletionSecondPass(
|
||||
PersistentParserState &ParserState,
|
||||
CodeCompletionCallbacksFactory &Factory) {
|
||||
if (!ParserState.hasCodeCompletionDelayedDeclState())
|
||||
SourceFile &SF, CodeCompletionCallbacksFactory &Factory) {
|
||||
// If we didn't find the code completion token, bail.
|
||||
auto *parserState = SF.getDelayedParserState();
|
||||
if (!parserState->hasCodeCompletionDelayedDeclState())
|
||||
return;
|
||||
|
||||
auto state = ParserState.takeCodeCompletionDelayedDeclState();
|
||||
auto &SF = *state->ParentContext->getParentSourceFile();
|
||||
auto state = parserState->takeCodeCompletionDelayedDeclState();
|
||||
auto &Ctx = SF.getASTContext();
|
||||
|
||||
FrontendStatsTracer tracer(Ctx.Stats,
|
||||
"CodeCompletionSecondPass");
|
||||
|
||||
auto BufferID = Ctx.SourceMgr.getCodeCompletionBufferID();
|
||||
Parser TheParser(BufferID, SF, nullptr, &ParserState, nullptr);
|
||||
Parser TheParser(BufferID, SF, nullptr, parserState, nullptr);
|
||||
|
||||
std::unique_ptr<CodeCompletionCallbacks> CodeCompletion(
|
||||
Factory.createCodeCompletionCallbacks(TheParser));
|
||||
@@ -366,15 +366,15 @@ static LexerMode sourceFileKindToLexerMode(SourceFileKind kind) {
|
||||
Parser::Parser(unsigned BufferID, SourceFile &SF, SILParserTUStateBase *SIL,
|
||||
PersistentParserState *PersistentState,
|
||||
std::shared_ptr<SyntaxParseActions> SPActions,
|
||||
bool DelayBodyParsing)
|
||||
bool DelayBodyParsing, bool EvaluateConditionals)
|
||||
: Parser(BufferID, SF, &SF.getASTContext().Diags, SIL, PersistentState,
|
||||
std::move(SPActions), DelayBodyParsing) {}
|
||||
std::move(SPActions), DelayBodyParsing, EvaluateConditionals) {}
|
||||
|
||||
Parser::Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags,
|
||||
SILParserTUStateBase *SIL,
|
||||
PersistentParserState *PersistentState,
|
||||
std::shared_ptr<SyntaxParseActions> SPActions,
|
||||
bool DelayBodyParsing)
|
||||
bool DelayBodyParsing, bool EvaluateConditionals)
|
||||
: Parser(
|
||||
std::unique_ptr<Lexer>(new Lexer(
|
||||
SF.getASTContext().LangOpts, SF.getASTContext().SourceMgr,
|
||||
@@ -389,7 +389,8 @@ Parser::Parser(unsigned BufferID, SourceFile &SF, DiagnosticEngine* LexerDiags,
|
||||
SF.shouldBuildSyntaxTree()
|
||||
? TriviaRetentionMode::WithTrivia
|
||||
: TriviaRetentionMode::WithoutTrivia)),
|
||||
SF, SIL, PersistentState, std::move(SPActions), DelayBodyParsing) {}
|
||||
SF, SIL, PersistentState, std::move(SPActions), DelayBodyParsing,
|
||||
EvaluateConditionals) {}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -510,7 +511,7 @@ Parser::Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF,
|
||||
SILParserTUStateBase *SIL,
|
||||
PersistentParserState *PersistentState,
|
||||
std::shared_ptr<SyntaxParseActions> SPActions,
|
||||
bool DelayBodyParsing)
|
||||
bool DelayBodyParsing, bool EvaluateConditionals)
|
||||
: SourceMgr(SF.getASTContext().SourceMgr),
|
||||
Diags(SF.getASTContext().Diags),
|
||||
SF(SF),
|
||||
@@ -520,6 +521,7 @@ Parser::Parser(std::unique_ptr<Lexer> Lex, SourceFile &SF,
|
||||
Context(SF.getASTContext()),
|
||||
CurrentTokenHash(SF.getInterfaceHashPtr()),
|
||||
DelayBodyParsing(DelayBodyParsing),
|
||||
EvaluateConditionals(EvaluateConditionals),
|
||||
TokReceiver(SF.shouldCollectToken() ?
|
||||
new TokenRecorder(SF, L->getBufferID()) :
|
||||
new ConsumeTokenReceiver()),
|
||||
|
||||
@@ -113,9 +113,16 @@ void PrettyStackTraceParser::print(llvm::raw_ostream &out) const {
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
/// A thunk that deletes an allocated PersistentParserState. This is needed for
|
||||
/// us to be able to forward declare a unique_ptr to the state in the AST.
|
||||
static void deletePersistentParserState(PersistentParserState *state) {
|
||||
delete state;
|
||||
}
|
||||
|
||||
void swift::parseIntoSourceFile(SourceFile &SF, unsigned int BufferID,
|
||||
PersistentParserState *PersistentState,
|
||||
bool DelayBodyParsing) {
|
||||
bool DelayBodyParsing,
|
||||
bool EvaluateConditionals) {
|
||||
auto &ctx = SF.getASTContext();
|
||||
std::shared_ptr<SyntaxTreeCreator> STreeCreator;
|
||||
if (SF.shouldBuildSyntaxTree()) {
|
||||
STreeCreator = std::make_shared<SyntaxTreeCreator>(
|
||||
@@ -133,10 +140,18 @@ void swift::parseIntoSourceFile(SourceFile &SF, unsigned int BufferID,
|
||||
if (SF.shouldBuildSyntaxTree())
|
||||
DelayBodyParsing = false;
|
||||
|
||||
// If this buffer is for code completion, hook up the state needed by its
|
||||
// second pass.
|
||||
PersistentParserState *state = nullptr;
|
||||
if (ctx.SourceMgr.getCodeCompletionBufferID() == BufferID) {
|
||||
state = new PersistentParserState();
|
||||
SF.setDelayedParserState({state, &deletePersistentParserState});
|
||||
}
|
||||
|
||||
FrontendStatsTracer tracer(SF.getASTContext().Stats,
|
||||
"Parsing");
|
||||
Parser P(BufferID, SF, /*SIL*/ nullptr, PersistentState, STreeCreator,
|
||||
DelayBodyParsing);
|
||||
Parser P(BufferID, SF, /*SIL*/ nullptr, state, STreeCreator, DelayBodyParsing,
|
||||
EvaluateConditionals);
|
||||
PrettyStackTraceParser StackTrace(P);
|
||||
|
||||
llvm::SaveAndRestore<NullablePtr<llvm::MD5>> S(P.CurrentTokenHash,
|
||||
|
||||
@@ -137,8 +137,9 @@ static bool swiftCodeCompleteImpl(
|
||||
|
||||
SwiftConsumer.setContext(&CI.getASTContext(), &CI.getInvocation(),
|
||||
&CompletionContext);
|
||||
performCodeCompletionSecondPass(CI.getPersistentParserState(),
|
||||
*callbacksFactory);
|
||||
|
||||
auto SF = CI.getCodeCompletionFile();
|
||||
performCodeCompletionSecondPass(*SF.get(), *callbacksFactory);
|
||||
SwiftConsumer.clearContext();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ static bool swiftConformingMethodListImpl(
|
||||
ide::makeConformingMethodListCallbacksFactory(ExpectedTypeNames,
|
||||
Consumer));
|
||||
|
||||
performCodeCompletionSecondPass(CI.getPersistentParserState(),
|
||||
*callbacksFactory);
|
||||
auto SF = CI.getCodeCompletionFile();
|
||||
performCodeCompletionSecondPass(*SF.get(), *callbacksFactory);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -715,7 +715,7 @@ public:
|
||||
Parser->getDiagnosticEngine().addConsumer(DiagConsumer);
|
||||
|
||||
// Collecting syntactic information shouldn't evaluate # conditions.
|
||||
Parser->getParser().State->PerformConditionEvaluation = false;
|
||||
Parser->getParser().EvaluateConditionals = false;
|
||||
|
||||
// If there is a syntax parsing cache, incremental syntax parsing is
|
||||
// performed and thus the generated AST may not be up-to-date.
|
||||
|
||||
@@ -39,8 +39,8 @@ static bool swiftTypeContextInfoImpl(
|
||||
std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory(
|
||||
ide::makeTypeContextInfoCallbacksFactory(Consumer));
|
||||
|
||||
performCodeCompletionSecondPass(CI.getPersistentParserState(),
|
||||
*callbacksFactory);
|
||||
auto SF = CI.getCodeCompletionFile();
|
||||
performCodeCompletionSecondPass(*SF.get(), *callbacksFactory);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ swiftparse_client_node_t SynParser::parse(const char *source) {
|
||||
"syntax_parse_module", std::move(parseActions),
|
||||
/*SyntaxCache=*/nullptr);
|
||||
// Evaluating pound conditions may lead to unknown syntax.
|
||||
PU.getParser().State->PerformConditionEvaluation = false;
|
||||
PU.getParser().EvaluateConditionals = false;
|
||||
std::unique_ptr<SynParserDiagConsumer> pConsumer;
|
||||
if (DiagHandler) {
|
||||
pConsumer = std::make_unique<SynParserDiagConsumer>(*this, bufID);
|
||||
|
||||
@@ -776,8 +776,8 @@ static bool doCodeCompletionImpl(
|
||||
Offset, /*EnableASTCaching=*/false, Error,
|
||||
CodeCompletionDiagnostics ? &PrintDiags : nullptr,
|
||||
[&](CompilerInstance &CI) {
|
||||
performCodeCompletionSecondPass(CI.getPersistentParserState(),
|
||||
*callbacksFactory);
|
||||
auto SF = CI.getCodeCompletionFile();
|
||||
performCodeCompletionSecondPass(*SF.get(), *callbacksFactory);
|
||||
});
|
||||
return isSuccess ? 0 : 1;
|
||||
}
|
||||
@@ -1124,7 +1124,7 @@ static int doSyntaxColoring(const CompilerInvocation &InitInvok,
|
||||
registerTypeCheckerRequestFunctions(Parser.getParser().Context.evaluator);
|
||||
|
||||
// Collecting syntactic information shouldn't evaluate # conditions.
|
||||
Parser.getParser().State->PerformConditionEvaluation = false;
|
||||
Parser.getParser().EvaluateConditionals = false;
|
||||
Parser.getDiagnosticEngine().addConsumer(PrintDiags);
|
||||
|
||||
(void)Parser.parse();
|
||||
@@ -1361,7 +1361,7 @@ static int doStructureAnnotation(const CompilerInvocation &InitInvok,
|
||||
Parser.getParser().Context.evaluator);
|
||||
|
||||
// Collecting syntactic information shouldn't evaluate # conditions.
|
||||
Parser.getParser().State->PerformConditionEvaluation = false;
|
||||
Parser.getParser().EvaluateConditionals = false;
|
||||
|
||||
// Display diagnostics to stderr.
|
||||
PrintingDiagnosticConsumer PrintDiags;
|
||||
|
||||
Reference in New Issue
Block a user