Files
swift-mirror/lib/SyntaxParse/SyntaxTreeCreator.cpp
Jordan Rose 853caa66d4 [AST] Split FileUnit and its subclasses out of Module.h
Most of AST, Parse, and Sema deal with FileUnits regularly, but SIL
and IRGen certainly don't. Split FileUnit out into its own header to
cut down on recompilation times when something changes.

No functionality change.
2019-09-17 17:54:41 -07:00

177 lines
6.3 KiB
C++

//===--- SyntaxTreeCreator.cpp - Syntax Tree Creation ----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/SyntaxParse/SyntaxTreeCreator.h"
#include "swift/Syntax/RawSyntax.h"
#include "swift/Syntax/SyntaxVisitor.h"
#include "swift/Syntax/Trivia.h"
#include "swift/Parse/ParsedTrivia.h"
#include "swift/Parse/SyntaxParsingCache.h"
#include "swift/Parse/Token.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/Module.h"
#include "swift/Basic/OwnedString.h"
#include "RawSyntaxTokenCache.h"
using namespace swift;
using namespace swift::syntax;
static RC<RawSyntax> transferOpaqueNode(OpaqueSyntaxNode opaqueN) {
if (!opaqueN)
return nullptr;
RC<RawSyntax> raw{(RawSyntax *)opaqueN};
raw->Release(); // -1 since it's transfer of ownership.
return raw;
}
SyntaxTreeCreator::SyntaxTreeCreator(SourceManager &SM, unsigned bufferID,
SyntaxParsingCache *syntaxCache,
RC<syntax::SyntaxArena> arena)
: SM(SM), BufferID(bufferID),
Arena(std::move(arena)),
SyntaxCache(syntaxCache),
TokenCache(new RawSyntaxTokenCache()) {
}
SyntaxTreeCreator::~SyntaxTreeCreator() = default;
namespace {
/// This verifier traverses a syntax node to emit proper diagnostics.
class SyntaxVerifier: public SyntaxVisitor {
SourceManager &SourceMgr;
unsigned BufferID;
DiagnosticEngine &Diags;
template<class T>
SourceLoc getSourceLoc(T Node) {
return SourceMgr.getLocForOffset(BufferID,
Node.getAbsolutePosition().getOffset());
}
public:
SyntaxVerifier( SourceManager &SM, unsigned bufID, DiagnosticEngine &diags)
: SourceMgr(SM), BufferID(bufID), Diags(diags) {}
void visit(UnknownDeclSyntax Node) override {
Diags.diagnose(getSourceLoc(Node), diag::unknown_syntax_entity,
"declaration");
visitChildren(Node);
}
void visit(UnknownExprSyntax Node) override {
Diags.diagnose(getSourceLoc(Node), diag::unknown_syntax_entity,
"expression");
visitChildren(Node);
}
void visit(UnknownStmtSyntax Node) override {
Diags.diagnose(getSourceLoc(Node), diag::unknown_syntax_entity,
"statement");
visitChildren(Node);
}
void visit(UnknownTypeSyntax Node) override {
Diags.diagnose(getSourceLoc(Node), diag::unknown_syntax_entity,
"type");
visitChildren(Node);
}
void visit(UnknownPatternSyntax Node) override {
Diags.diagnose(getSourceLoc(Node), diag::unknown_syntax_entity,
"pattern");
visitChildren(Node);
}
void verify(Syntax Node) {
Node.accept(*this);
}
};
} // anonymous namespace
void SyntaxTreeCreator::acceptSyntaxRoot(OpaqueSyntaxNode rootN,
SourceFile &SF) {
auto raw = transferOpaqueNode(rootN);
SF.setSyntaxRoot(make<SourceFileSyntax>(raw));
// Verify the tree if specified.
if (SF.getASTContext().LangOpts.VerifySyntaxTree) {
ASTContext &ctx = SF.getASTContext();
SyntaxVerifier Verifier(ctx.SourceMgr, SF.getBufferID().getValue(),
ctx.Diags);
Verifier.verify(SF.getSyntaxRoot());
}
}
OpaqueSyntaxNode
SyntaxTreeCreator::recordToken(tok tokenKind,
ArrayRef<ParsedTriviaPiece> leadingTriviaPieces,
ArrayRef<ParsedTriviaPiece> trailingTriviaPieces,
CharSourceRange range) {
size_t leadingTriviaLen =
ParsedTriviaPiece::getTotalLength(leadingTriviaPieces);
size_t trailingTriviaLen =
ParsedTriviaPiece::getTotalLength(trailingTriviaPieces);
SourceLoc tokLoc = range.getStart().getAdvancedLoc(leadingTriviaLen);
unsigned tokLength = range.getByteLength() -
leadingTriviaLen - trailingTriviaLen;
CharSourceRange tokRange = CharSourceRange{tokLoc, tokLength};
SourceLoc leadingTriviaLoc = range.getStart();
SourceLoc trailingTriviaLoc = tokLoc.getAdvancedLoc(tokLength);
Trivia syntaxLeadingTrivia =
ParsedTriviaPiece::convertToSyntaxTrivia(leadingTriviaPieces,
leadingTriviaLoc, SM, BufferID);
Trivia syntaxTrailingTrivia =
ParsedTriviaPiece::convertToSyntaxTrivia(trailingTriviaPieces,
trailingTriviaLoc, SM, BufferID);
StringRef tokenText = SM.extractText(tokRange, BufferID);
auto ownedText = OwnedString::makeRefCounted(tokenText);
auto raw = TokenCache->getToken(Arena, tokenKind, ownedText,
syntaxLeadingTrivia.Pieces, syntaxTrailingTrivia.Pieces);
OpaqueSyntaxNode opaqueN = raw.get();
raw.resetWithoutRelease();
return opaqueN;
}
OpaqueSyntaxNode
SyntaxTreeCreator::recordMissingToken(tok kind, SourceLoc loc) {
auto ownedText = OwnedString::makeRefCounted(getTokenText(kind));
auto raw = RawSyntax::missing(kind, ownedText, Arena);
OpaqueSyntaxNode opaqueN = raw.get();
raw.resetWithoutRelease();
return opaqueN;
}
OpaqueSyntaxNode
SyntaxTreeCreator::recordRawSyntax(syntax::SyntaxKind kind,
ArrayRef<OpaqueSyntaxNode> elements,
CharSourceRange range) {
SmallVector<RC<RawSyntax>, 16> parts;
parts.reserve(elements.size());
for (OpaqueSyntaxNode opaqueN : elements) {
parts.push_back(transferOpaqueNode(opaqueN));
}
auto raw = RawSyntax::make(kind, parts, SourcePresence::Present, Arena);
OpaqueSyntaxNode opaqueN = raw.get();
raw.resetWithoutRelease();
return opaqueN;
}
std::pair<size_t, OpaqueSyntaxNode>
SyntaxTreeCreator::lookupNode(size_t lexerOffset, syntax::SyntaxKind kind) {
if (!SyntaxCache)
return {0, nullptr};
auto cacheLookup = SyntaxCache->lookUp(lexerOffset, kind);
if (!cacheLookup)
return {0, nullptr};
RC<RawSyntax> raw = cacheLookup->getRaw();
OpaqueSyntaxNode opaqueN = raw.get();
size_t length = raw->getTextLength();
raw.resetWithoutRelease();
return {length, opaqueN};
}