Skip to content

Commit f57299a

Browse files
committed
Formalize some SourceFile parsing outputs
Currently when parsing a SourceFile, the parser gets handed pointers so that it can write the interface hash and collected tokens directly into the file. It can also call `setSyntaxRoot` at the end of parsing to set the syntax tree. In preparation for the removal of `performParseOnly`, this commit formalizes these values as outputs of `ParseSourceFileRequest`, ensuring that the file gets parsed when the interface hash, collected tokens, or syntax tree is queried.
1 parent 5fdc5f3 commit f57299a

File tree

17 files changed

+166
-90
lines changed

17 files changed

+166
-90
lines changed

include/swift/AST/ASTContext.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ class ASTContext final {
407407
array.size());
408408
}
409409

410+
template <typename T>
411+
MutableArrayRef<T>
412+
AllocateCopy(const std::vector<T> &vec,
413+
AllocationArena arena = AllocationArena::Permanent) const {
414+
return AllocateCopy(ArrayRef<T>(vec), arena);
415+
}
410416

411417
template<typename T>
412418
ArrayRef<T> AllocateCopy(const SmallVectorImpl<T> &vec,

include/swift/AST/ParseRequests.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/ASTTypeIDs.h"
2020
#include "swift/AST/EvaluatorDependencies.h"
2121
#include "swift/AST/SimpleRequest.h"
22+
#include "swift/Syntax/SyntaxNodes.h"
2223

2324
namespace swift {
2425

@@ -81,10 +82,17 @@ class ParseAbstractFunctionBodyRequest :
8182
void cacheResult(BraceStmt *value) const;
8283
};
8384

85+
struct SourceFileParsingResult {
86+
ArrayRef<Decl *> TopLevelDecls;
87+
Optional<ArrayRef<Token>> CollectedTokens;
88+
Optional<llvm::MD5> InterfaceHash;
89+
Optional<syntax::SourceFileSyntax> SyntaxRoot;
90+
};
91+
8492
/// Parse the top-level decls of a SourceFile.
8593
class ParseSourceFileRequest
8694
: public SimpleRequest<
87-
ParseSourceFileRequest, ArrayRef<Decl *>(SourceFile *),
95+
ParseSourceFileRequest, SourceFileParsingResult(SourceFile *),
8896
RequestFlags::SeparatelyCached | RequestFlags::DependencySource> {
8997
public:
9098
using SimpleRequest::SimpleRequest;
@@ -93,13 +101,13 @@ class ParseSourceFileRequest
93101
friend SimpleRequest;
94102

95103
// Evaluation.
96-
ArrayRef<Decl *> evaluate(Evaluator &evaluator, SourceFile *SF) const;
104+
SourceFileParsingResult evaluate(Evaluator &evaluator, SourceFile *SF) const;
97105

98106
public:
99107
// Caching.
100108
bool isCached() const { return true; }
101-
Optional<ArrayRef<Decl *>> getCachedResult() const;
102-
void cacheResult(ArrayRef<Decl *> decls) const;
109+
Optional<SourceFileParsingResult> getCachedResult() const;
110+
void cacheResult(SourceFileParsingResult result) const;
103111

104112
public:
105113
evaluator::DependencySource

include/swift/AST/ParseTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ SWIFT_REQUEST(Parse, ParseAbstractFunctionBodyRequest,
2323
BraceStmt *(AbstractFunctionDecl *), SeparatelyCached,
2424
NoLocationInfo)
2525
SWIFT_REQUEST(Parse, ParseSourceFileRequest,
26-
ArrayRef<Decl *>(SourceFile *), SeparatelyCached,
26+
SourceFileParsingResult(SourceFile *), SeparatelyCached,
2727
NoLocationInfo)

include/swift/AST/SourceFile.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -558,26 +558,15 @@ class SourceFile final : public FileUnit {
558558
return ParsingOpts.contains(ParsingFlags::EnableInterfaceHash);
559559
}
560560

561-
NullablePtr<llvm::MD5> getInterfaceHashPtr() {
562-
return InterfaceHash ? InterfaceHash.getPointer() : nullptr;
563-
}
564-
565-
void getInterfaceHash(llvm::SmallString<32> &str) const {
566-
// Copy to preserve idempotence.
567-
llvm::MD5 md5 = *InterfaceHash;
568-
llvm::MD5::MD5Result result;
569-
md5.final(result);
570-
llvm::MD5::stringifyResult(result, str);
571-
}
561+
/// Output this file's interface hash into the provided string buffer.
562+
void getInterfaceHash(llvm::SmallString<32> &str) const;
572563

573564
void dumpInterfaceHash(llvm::raw_ostream &out) {
574565
llvm::SmallString<32> str;
575566
getInterfaceHash(str);
576567
out << str << '\n';
577568
}
578569

579-
std::vector<Token> &getTokenVector();
580-
581570
/// If this source file has been told to collect its parsed tokens, retrieve
582571
/// those tokens.
583572
ArrayRef<Token> getAllTokens() const;
@@ -593,7 +582,6 @@ class SourceFile final : public FileUnit {
593582
bool hasDelayedBodyParsing() const;
594583

595584
syntax::SourceFileSyntax getSyntaxRoot() const;
596-
void setSyntaxRoot(syntax::SourceFileSyntax &&Root);
597585
bool hasSyntaxRoot() const;
598586

599587
OpaqueTypeDecl *lookupOpaqueResultType(StringRef MangledName) override;
@@ -611,7 +599,7 @@ class SourceFile final : public FileUnit {
611599

612600
/// If not \c None, the underlying vector contains the parsed tokens of this
613601
/// source file.
614-
Optional<std::vector<Token>> AllCollectedTokens;
602+
Optional<ArrayRef<Token>> AllCollectedTokens;
615603

616604
/// The root of the syntax tree representing the source file.
617605
std::unique_ptr<syntax::SourceFileSyntax> SyntaxRoot;

include/swift/Parse/Parser.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/Expr.h"
2323
#include "swift/AST/DiagnosticsParse.h"
2424
#include "swift/AST/LayoutConstraint.h"
25+
#include "swift/AST/ParseRequests.h"
2526
#include "swift/AST/Pattern.h"
2627
#include "swift/AST/Stmt.h"
2728
#include "swift/Basic/OptionSet.h"
@@ -92,8 +93,11 @@ class ConsumeTokenReceiver {
9293
/// This is called to update the kind of a token whose start location is Loc.
9394
virtual void registerTokenKindChange(SourceLoc Loc, tok NewKind) {};
9495

95-
/// This is called when a source file is fully parsed.
96-
virtual void finalize() {};
96+
/// This is called when a source file is fully parsed. It returns the
97+
/// finalized vector of tokens, or \c None if the receiver isn't configured to
98+
/// record them.
99+
virtual Optional<std::vector<Token>> finalize() { return None; }
100+
97101
virtual ~ConsumeTokenReceiver() = default;
98102
};
99103

@@ -124,7 +128,10 @@ class Parser {
124128
/// Tracks parsed decls that LLDB requires to be inserted at the top-level.
125129
std::vector<Decl *> ContextSwitchedTopLevelDecls;
126130

127-
NullablePtr<llvm::MD5> CurrentTokenHash;
131+
/// The current token hash, or \c None if the parser isn't computing a hash
132+
/// for the token stream.
133+
Optional<llvm::MD5> CurrentTokenHash;
134+
128135
void recordTokenHash(const Token Tok) {
129136
if (!Tok.getText().empty())
130137
recordTokenHash(Tok.getText());
@@ -416,6 +423,14 @@ class Parser {
416423
return SyntaxContext->finalizeRoot();
417424
}
418425

426+
/// Retrieve the token receiver from the parser once it has finished parsing.
427+
std::unique_ptr<ConsumeTokenReceiver> takeTokenReceiver() {
428+
assert(Tok.is(tok::eof) && "not done parsing yet");
429+
auto *receiver = TokReceiver;
430+
TokReceiver = nullptr;
431+
return std::unique_ptr<ConsumeTokenReceiver>(receiver);
432+
}
433+
419434
//===--------------------------------------------------------------------===//
420435
// Routines to save and restore parser state.
421436

include/swift/Parse/SyntaxParseActions.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ namespace swift {
2424

2525
class CharSourceRange;
2626
class ParsedTriviaPiece;
27+
class SourceFile;
2728
class SourceLoc;
2829
enum class tok;
2930

3031
namespace syntax {
31-
enum class SyntaxKind;
32+
class SourceFileSyntax;
33+
enum class SyntaxKind;
3234
}
3335

3436
typedef void *OpaqueSyntaxNode;
@@ -55,6 +57,12 @@ class SyntaxParseActions {
5557
ArrayRef<OpaqueSyntaxNode> elements,
5658
CharSourceRange range) = 0;
5759

60+
/// Attempt to realize an opaque raw syntax node for a source file into a
61+
/// SourceFileSyntax node. This will return \c None if the parsing action
62+
/// doesn't support the realization of syntax nodes.
63+
virtual Optional<syntax::SourceFileSyntax>
64+
realizeSyntaxRoot(OpaqueSyntaxNode root, const SourceFile &SF) = 0;
65+
5866
/// Discard raw syntax node.
5967
///
6068
/// FIXME: This breaks invariant that any recorded node will be a part of the

include/swift/SyntaxParse/SyntaxTreeCreator.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ namespace swift {
2323
class SourceFile;
2424

2525
namespace syntax {
26-
class SyntaxArena;
26+
class SyntaxArena;
27+
class SourceFileSyntax;
2728
}
2829

2930
/// Receives the parsed syntax info from the parser and constructs a persistent
@@ -51,7 +52,8 @@ class SyntaxTreeCreator: public SyntaxParseActions {
5152
RC<syntax::SyntaxArena> arena);
5253
~SyntaxTreeCreator();
5354

54-
void acceptSyntaxRoot(OpaqueSyntaxNode root, SourceFile &SF);
55+
Optional<syntax::SourceFileSyntax>
56+
realizeSyntaxRoot(OpaqueSyntaxNode root, const SourceFile &SF) override;
5557

5658
private:
5759
OpaqueSyntaxNode recordToken(tok tokenKind,

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#include "swift/AST/TypeCheckRequests.h"
4545
#include "swift/AST/TypeLoc.h"
4646
#include "swift/AST/SwiftNameTranslation.h"
47-
#include "swift/Parse/Lexer.h"
47+
#include "swift/Parse/Lexer.h" // FIXME: Bad dependency
4848
#include "clang/Lex/MacroInfo.h"
4949
#include "llvm/ADT/SmallPtrSet.h"
5050
#include "llvm/ADT/SmallSet.h"

lib/AST/Module.cpp

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,17 +1077,27 @@ LookupConformanceInModuleRequest::evaluate(
10771077
return ProtocolConformanceRef(conformance);
10781078
}
10791079

1080+
void SourceFile::getInterfaceHash(llvm::SmallString<32> &str) const {
1081+
assert(hasInterfaceHash() && "Interface hash not enabled");
1082+
auto &eval = getASTContext().evaluator;
1083+
auto *mutableThis = const_cast<SourceFile *>(this);
1084+
auto md5 = *evaluateOrDefault(eval, ParseSourceFileRequest{mutableThis}, {})
1085+
.InterfaceHash;
1086+
llvm::MD5::MD5Result result;
1087+
md5.final(result);
1088+
llvm::MD5::stringifyResult(result, str);
1089+
}
1090+
10801091
bool SourceFile::hasSyntaxRoot() const {
10811092
return ParsingOpts.contains(ParsingFlags::BuildSyntaxTree);
10821093
}
10831094

10841095
syntax::SourceFileSyntax SourceFile::getSyntaxRoot() const {
1085-
assert(hasSyntaxRoot() && "no syntax root is set.");
1086-
return *SyntaxRoot;
1087-
}
1088-
1089-
void SourceFile::setSyntaxRoot(syntax::SourceFileSyntax &&Root) {
1090-
SyntaxRoot = std::make_unique<syntax::SourceFileSyntax>(std::move(Root));
1096+
assert(hasSyntaxRoot() && "has no syntax root");
1097+
auto &eval = getASTContext().evaluator;
1098+
auto *mutableThis = const_cast<SourceFile *>(this);
1099+
return *evaluateOrDefault(eval, ParseSourceFileRequest{mutableThis}, {})
1100+
.SyntaxRoot;
10911101
}
10921102

10931103
void DirectOperatorLookupRequest::writeDependencySink(
@@ -2222,18 +2232,6 @@ SourceFile::SourceFile(ModuleDecl &M, SourceFileKind K,
22222232
assert(!problem && "multiple main files?");
22232233
(void)problem;
22242234
}
2225-
2226-
if (hasInterfaceHash()) {
2227-
InterfaceHash.emplace();
2228-
}
2229-
if (shouldCollectTokens()) {
2230-
AllCollectedTokens = std::vector<Token>();
2231-
}
2232-
}
2233-
2234-
std::vector<Token> &SourceFile::getTokenVector() {
2235-
assert(shouldCollectTokens() && "Disabled");
2236-
return *AllCollectedTokens;
22372235
}
22382236

22392237
SourceFile::ParsingOptions
@@ -2248,7 +2246,10 @@ SourceFile::getDefaultParsingOptions(const LangOptions &langOpts) {
22482246

22492247
ArrayRef<Token> SourceFile::getAllTokens() const {
22502248
assert(shouldCollectTokens() && "Disabled");
2251-
return *AllCollectedTokens;
2249+
auto &eval = getASTContext().evaluator;
2250+
auto *mutableThis = const_cast<SourceFile *>(this);
2251+
return *evaluateOrDefault(eval, ParseSourceFileRequest{mutableThis}, {})
2252+
.CollectedTokens;
22522253
}
22532254

22542255
bool SourceFile::shouldCollectTokens() const {
@@ -2282,7 +2283,7 @@ ArrayRef<Decl *> SourceFile::getTopLevelDecls() const {
22822283
auto &ctx = getASTContext();
22832284
auto *mutableThis = const_cast<SourceFile *>(this);
22842285
return evaluateOrDefault(ctx.evaluator, ParseSourceFileRequest{mutableThis},
2285-
{});
2286+
{}).TopLevelDecls;
22862287
}
22872288

22882289
bool FileUnit::walk(ASTWalker &walker) {

lib/Parse/ParseDecl.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,8 @@ void Parser::parseTopLevel(SmallVectorImpl<Decl *> &decls) {
236236
decls.push_back(decl);
237237
}
238238

239-
// Finalize the token receiver.
239+
// Finalize the syntax context.
240240
SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
241-
TokReceiver->finalize();
242241
}
243242

244243
bool Parser::parseTopLevelSIL() {
@@ -4470,16 +4469,14 @@ Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag,
44704469
ParseDeclOptions Options, IterableDeclContext *IDC,
44714470
bool &hadError) {
44724471

4473-
// Record the curly braces but nothing inside.
4472+
// If we're hashing the type body separately, record the curly braces but
4473+
// nothing inside for the interface hash.
4474+
Optional<llvm::SaveAndRestore<Optional<llvm::MD5>>> S;
44744475
if (IDC->areTokensHashedForThisBodyInsteadOfInterfaceHash()) {
44754476
recordTokenHash("{");
44764477
recordTokenHash("}");
4478+
S.emplace(CurrentTokenHash, llvm::MD5());
44774479
}
4478-
llvm::MD5 tokenHashForThisDeclList;
4479-
llvm::SaveAndRestore<NullablePtr<llvm::MD5>> T(
4480-
CurrentTokenHash, IDC->areTokensHashedForThisBodyInsteadOfInterfaceHash()
4481-
? &tokenHashForThisDeclList
4482-
: CurrentTokenHash);
44834480

44844481
std::vector<Decl *> decls;
44854482
ParserStatus Status;
@@ -4514,6 +4511,7 @@ Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag,
45144511
return std::make_pair(decls, None);
45154512

45164513
llvm::MD5::MD5Result result;
4514+
auto tokenHashForThisDeclList = CurrentTokenHash.getValueOr(llvm::MD5());
45174515
tokenHashForThisDeclList.final(result);
45184516
llvm::SmallString<32> tokenHashString;
45194517
llvm::MD5::stringifyResult(result, tokenHashString);
@@ -6409,7 +6407,7 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
64096407
recordTokenHash("{");
64106408
recordTokenHash("}");
64116409

6412-
llvm::SaveAndRestore<NullablePtr<llvm::MD5>> T(CurrentTokenHash, nullptr);
6410+
llvm::SaveAndRestore<Optional<llvm::MD5>> T(CurrentTokenHash, None);
64136411

64146412
// If we can delay parsing this body, or this is the first pass of code
64156413
// completion, skip until the end. If we encounter a code completion token

lib/Parse/ParseIfConfig.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,9 @@ ParserResult<IfConfigDecl> Parser::parseIfConfig(
677677
llvm::SaveAndRestore<bool> S(InInactiveClauseEnvironment,
678678
InInactiveClauseEnvironment || !isActive);
679679
// Disable updating the interface hash inside inactive blocks.
680-
llvm::SaveAndRestore<NullablePtr<llvm::MD5>> T(
681-
CurrentTokenHash, isActive ? CurrentTokenHash : nullptr);
680+
Optional<llvm::SaveAndRestore<Optional<llvm::MD5>>> T;
681+
if (!isActive)
682+
T.emplace(CurrentTokenHash, None);
682683

683684
if (isActive || !isVersionCondition) {
684685
parseElements(Elements, isActive);

0 commit comments

Comments
 (0)