mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Add frontend flag to serialize Syntax tree (#11095)
* Add frontend flag to serialize Syntax tree * Rename dump-serialized-syntax-tree to emit-syntax
This commit is contained in:
@@ -161,6 +161,7 @@ public:
|
|||||||
Typecheck, ///< Parse and type-check only
|
Typecheck, ///< Parse and type-check only
|
||||||
DumpParse, ///< Parse only and dump AST
|
DumpParse, ///< Parse only and dump AST
|
||||||
DumpInterfaceHash, ///< Parse and dump the interface token hash.
|
DumpInterfaceHash, ///< Parse and dump the interface token hash.
|
||||||
|
EmitSyntax, ///< Parse and dump Syntax tree as JSON
|
||||||
DumpAST, ///< Parse, type-check, and dump AST
|
DumpAST, ///< Parse, type-check, and dump AST
|
||||||
PrintAST, ///< Parse, type-check, and pretty-print AST
|
PrintAST, ///< Parse, type-check, and pretty-print AST
|
||||||
|
|
||||||
|
|||||||
@@ -400,6 +400,9 @@ def emit_sorted_sil : Flag<["-"], "emit-sorted-sil">,
|
|||||||
HelpText<"When printing SIL, print out all sil entities sorted by name to "
|
HelpText<"When printing SIL, print out all sil entities sorted by name to "
|
||||||
"ease diffing">;
|
"ease diffing">;
|
||||||
|
|
||||||
|
def emit_syntax : Flag<["-"], "emit-syntax">,
|
||||||
|
HelpText<"Parse input file(s) and emit the Syntax tree(s) as JSON">, ModeOpt;
|
||||||
|
|
||||||
def use_malloc : Flag<["-"], "use-malloc">,
|
def use_malloc : Flag<["-"], "use-malloc">,
|
||||||
HelpText<"Allocate internal data structures using malloc "
|
HelpText<"Allocate internal data structures using malloc "
|
||||||
"(for memory debugging)">;
|
"(for memory debugging)">;
|
||||||
|
|||||||
@@ -1168,6 +1168,7 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
|
|||||||
case options::OPT_typecheck:
|
case options::OPT_typecheck:
|
||||||
case options::OPT_dump_parse:
|
case options::OPT_dump_parse:
|
||||||
case options::OPT_dump_ast:
|
case options::OPT_dump_ast:
|
||||||
|
case options::OPT_emit_syntax:
|
||||||
case options::OPT_print_ast:
|
case options::OPT_print_ast:
|
||||||
case options::OPT_dump_type_refinement_contexts:
|
case options::OPT_dump_type_refinement_contexts:
|
||||||
case options::OPT_dump_scope_maps:
|
case options::OPT_dump_scope_maps:
|
||||||
|
|||||||
@@ -320,6 +320,8 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
Action = FrontendOptions::DumpParse;
|
Action = FrontendOptions::DumpParse;
|
||||||
} else if (Opt.matches(OPT_dump_ast)) {
|
} else if (Opt.matches(OPT_dump_ast)) {
|
||||||
Action = FrontendOptions::DumpAST;
|
Action = FrontendOptions::DumpAST;
|
||||||
|
} else if (Opt.matches(OPT_emit_syntax)) {
|
||||||
|
Action = FrontendOptions::EmitSyntax;
|
||||||
} else if (Opt.matches(OPT_dump_scope_maps)) {
|
} else if (Opt.matches(OPT_dump_scope_maps)) {
|
||||||
Action = FrontendOptions::DumpScopeMaps;
|
Action = FrontendOptions::DumpScopeMaps;
|
||||||
|
|
||||||
@@ -531,6 +533,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
case FrontendOptions::DumpParse:
|
case FrontendOptions::DumpParse:
|
||||||
case FrontendOptions::DumpInterfaceHash:
|
case FrontendOptions::DumpInterfaceHash:
|
||||||
case FrontendOptions::DumpAST:
|
case FrontendOptions::DumpAST:
|
||||||
|
case FrontendOptions::EmitSyntax:
|
||||||
case FrontendOptions::PrintAST:
|
case FrontendOptions::PrintAST:
|
||||||
case FrontendOptions::DumpScopeMaps:
|
case FrontendOptions::DumpScopeMaps:
|
||||||
case FrontendOptions::DumpTypeRefinementContexts:
|
case FrontendOptions::DumpTypeRefinementContexts:
|
||||||
@@ -743,6 +746,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
case FrontendOptions::DumpParse:
|
case FrontendOptions::DumpParse:
|
||||||
case FrontendOptions::DumpInterfaceHash:
|
case FrontendOptions::DumpInterfaceHash:
|
||||||
case FrontendOptions::DumpAST:
|
case FrontendOptions::DumpAST:
|
||||||
|
case FrontendOptions::EmitSyntax:
|
||||||
case FrontendOptions::PrintAST:
|
case FrontendOptions::PrintAST:
|
||||||
case FrontendOptions::DumpScopeMaps:
|
case FrontendOptions::DumpScopeMaps:
|
||||||
case FrontendOptions::DumpTypeRefinementContexts:
|
case FrontendOptions::DumpTypeRefinementContexts:
|
||||||
@@ -774,6 +778,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
case FrontendOptions::DumpParse:
|
case FrontendOptions::DumpParse:
|
||||||
case FrontendOptions::DumpInterfaceHash:
|
case FrontendOptions::DumpInterfaceHash:
|
||||||
case FrontendOptions::DumpAST:
|
case FrontendOptions::DumpAST:
|
||||||
|
case FrontendOptions::EmitSyntax:
|
||||||
case FrontendOptions::PrintAST:
|
case FrontendOptions::PrintAST:
|
||||||
case FrontendOptions::EmitPCH:
|
case FrontendOptions::EmitPCH:
|
||||||
case FrontendOptions::DumpScopeMaps:
|
case FrontendOptions::DumpScopeMaps:
|
||||||
@@ -806,6 +811,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
case FrontendOptions::DumpParse:
|
case FrontendOptions::DumpParse:
|
||||||
case FrontendOptions::DumpInterfaceHash:
|
case FrontendOptions::DumpInterfaceHash:
|
||||||
case FrontendOptions::DumpAST:
|
case FrontendOptions::DumpAST:
|
||||||
|
case FrontendOptions::EmitSyntax:
|
||||||
case FrontendOptions::PrintAST:
|
case FrontendOptions::PrintAST:
|
||||||
case FrontendOptions::DumpScopeMaps:
|
case FrontendOptions::DumpScopeMaps:
|
||||||
case FrontendOptions::DumpTypeRefinementContexts:
|
case FrontendOptions::DumpTypeRefinementContexts:
|
||||||
@@ -840,6 +846,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||||||
case FrontendOptions::DumpParse:
|
case FrontendOptions::DumpParse:
|
||||||
case FrontendOptions::DumpInterfaceHash:
|
case FrontendOptions::DumpInterfaceHash:
|
||||||
case FrontendOptions::DumpAST:
|
case FrontendOptions::DumpAST:
|
||||||
|
case FrontendOptions::EmitSyntax:
|
||||||
case FrontendOptions::PrintAST:
|
case FrontendOptions::PrintAST:
|
||||||
case FrontendOptions::EmitPCH:
|
case FrontendOptions::EmitPCH:
|
||||||
case FrontendOptions::DumpScopeMaps:
|
case FrontendOptions::DumpScopeMaps:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ bool FrontendOptions::actionHasOutput() const {
|
|||||||
case Typecheck:
|
case Typecheck:
|
||||||
case DumpParse:
|
case DumpParse:
|
||||||
case DumpAST:
|
case DumpAST:
|
||||||
|
case EmitSyntax:
|
||||||
case DumpInterfaceHash:
|
case DumpInterfaceHash:
|
||||||
case PrintAST:
|
case PrintAST:
|
||||||
case DumpScopeMaps:
|
case DumpScopeMaps:
|
||||||
@@ -56,6 +57,7 @@ bool FrontendOptions::actionIsImmediate() const {
|
|||||||
case Typecheck:
|
case Typecheck:
|
||||||
case DumpParse:
|
case DumpParse:
|
||||||
case DumpAST:
|
case DumpAST:
|
||||||
|
case EmitSyntax:
|
||||||
case DumpInterfaceHash:
|
case DumpInterfaceHash:
|
||||||
case PrintAST:
|
case PrintAST:
|
||||||
case DumpScopeMaps:
|
case DumpScopeMaps:
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "swift/AST/DiagnosticsSema.h"
|
#include "swift/AST/DiagnosticsSema.h"
|
||||||
#include "swift/AST/IRGenOptions.h"
|
#include "swift/AST/IRGenOptions.h"
|
||||||
#include "swift/AST/ASTMangler.h"
|
#include "swift/AST/ASTMangler.h"
|
||||||
|
#include "swift/AST/LegacyASTTransformer.h"
|
||||||
#include "swift/AST/ReferencedNameTracker.h"
|
#include "swift/AST/ReferencedNameTracker.h"
|
||||||
#include "swift/AST/TypeRefinementContext.h"
|
#include "swift/AST/TypeRefinementContext.h"
|
||||||
#include "swift/Basic/Dwarf.h"
|
#include "swift/Basic/Dwarf.h"
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
#include "swift/Serialization/SerializationOptions.h"
|
#include "swift/Serialization/SerializationOptions.h"
|
||||||
#include "swift/Serialization/SerializedModuleLoader.h"
|
#include "swift/Serialization/SerializedModuleLoader.h"
|
||||||
#include "swift/SILOptimizer/PassManager/Passes.h"
|
#include "swift/SILOptimizer/PassManager/Passes.h"
|
||||||
|
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
|
||||||
|
|
||||||
// FIXME: We're just using CompilerInstance::createOutputFile.
|
// FIXME: We're just using CompilerInstance::createOutputFile.
|
||||||
// This API should be sunk down to LLVM.
|
// This API should be sunk down to LLVM.
|
||||||
@@ -228,17 +230,72 @@ static bool emitLoadedModuleTrace(ASTContext &ctxt,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Gets an output stream for the provided output filename, or diagnoses to the
|
||||||
|
/// provided AST Context and returns null if there was an error getting the
|
||||||
|
/// stream.
|
||||||
|
static std::unique_ptr<llvm::raw_fd_ostream>
|
||||||
|
getFileOutputStream(StringRef OutputFilename, ASTContext &Ctx) {
|
||||||
|
std::error_code errorCode;
|
||||||
|
auto os = llvm::make_unique<llvm::raw_fd_ostream>(
|
||||||
|
OutputFilename, errorCode, llvm::sys::fs::F_None);
|
||||||
|
if (errorCode) {
|
||||||
|
Ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||||
|
OutputFilename, errorCode.message());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes the Syntax tree to the given file
|
||||||
|
static bool emitSyntax(SourceFile *SF, LangOptions &LangOpts,
|
||||||
|
SourceManager &SM, StringRef OutputFilename) {
|
||||||
|
auto bufferID = SF->getBufferID();
|
||||||
|
assert(bufferID && "frontend should have a buffer ID "
|
||||||
|
"for the main source file");
|
||||||
|
|
||||||
|
// Get a full token stream with associated Trivia.
|
||||||
|
syntax::TokenPositionList tokens =
|
||||||
|
tokenizeWithTrivia(LangOpts, SM, *bufferID);
|
||||||
|
|
||||||
|
llvm::SmallVector<Decl *, 16> topLevelDecls;
|
||||||
|
SF->getTopLevelDecls(topLevelDecls);
|
||||||
|
|
||||||
|
// Convert the old ASTs to the Syntax tree and print
|
||||||
|
// them out.
|
||||||
|
SyntaxASTMap ASTMap;
|
||||||
|
std::vector<RC<syntax::RawSyntax>> topLevelRaw;
|
||||||
|
for (auto *decl : topLevelDecls) {
|
||||||
|
if (decl->escapedFromIfConfig()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto newNode = transformAST(ASTNode(decl), ASTMap, SM, *bufferID, tokens);
|
||||||
|
if (newNode.hasValue()) {
|
||||||
|
topLevelRaw.push_back(newNode->getRaw());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the EOF token -- this ensures that any remaining trivia in the
|
||||||
|
// file is serialized as the EOF's leading trivia.
|
||||||
|
if (!tokens.empty() && tokens.back().first->getTokenKind() == tok::eof) {
|
||||||
|
topLevelRaw.push_back(tokens.back().first);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto os = getFileOutputStream(OutputFilename, SF->getASTContext());
|
||||||
|
if (!os) return true;
|
||||||
|
|
||||||
|
json::Output jsonOut(*os);
|
||||||
|
jsonOut << topLevelRaw;
|
||||||
|
*os << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Writes SIL out to the given file.
|
/// Writes SIL out to the given file.
|
||||||
static bool writeSIL(SILModule &SM, ModuleDecl *M, bool EmitVerboseSIL,
|
static bool writeSIL(SILModule &SM, ModuleDecl *M, bool EmitVerboseSIL,
|
||||||
StringRef OutputFilename, bool SortSIL) {
|
StringRef OutputFilename, bool SortSIL) {
|
||||||
std::error_code EC;
|
auto OS = getFileOutputStream(OutputFilename, M->getASTContext());
|
||||||
llvm::raw_fd_ostream OS(OutputFilename, EC, llvm::sys::fs::F_None);
|
if (!OS) return true;
|
||||||
if (EC) {
|
SM.print(*OS, EmitVerboseSIL, M, SortSIL);
|
||||||
M->getASTContext().Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
|
||||||
OutputFilename, EC.message());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
SM.print(OS, EmitVerboseSIL, M, SortSIL);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,6 +625,7 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
// so dump or print the main source file and return.
|
// so dump or print the main source file and return.
|
||||||
if (Action == FrontendOptions::DumpParse ||
|
if (Action == FrontendOptions::DumpParse ||
|
||||||
Action == FrontendOptions::DumpAST ||
|
Action == FrontendOptions::DumpAST ||
|
||||||
|
Action == FrontendOptions::EmitSyntax ||
|
||||||
Action == FrontendOptions::PrintAST ||
|
Action == FrontendOptions::PrintAST ||
|
||||||
Action == FrontendOptions::DumpScopeMaps ||
|
Action == FrontendOptions::DumpScopeMaps ||
|
||||||
Action == FrontendOptions::DumpTypeRefinementContexts ||
|
Action == FrontendOptions::DumpTypeRefinementContexts ||
|
||||||
@@ -627,7 +685,10 @@ static bool performCompile(CompilerInstance &Instance,
|
|||||||
SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr);
|
SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr);
|
||||||
else if (Action == FrontendOptions::DumpInterfaceHash)
|
else if (Action == FrontendOptions::DumpInterfaceHash)
|
||||||
SF->dumpInterfaceHash(llvm::errs());
|
SF->dumpInterfaceHash(llvm::errs());
|
||||||
else
|
else if (Action == FrontendOptions::EmitSyntax) {
|
||||||
|
emitSyntax(SF, Invocation.getLangOptions(), Instance.getSourceMgr(),
|
||||||
|
opts.getSingleOutputFilename());
|
||||||
|
} else
|
||||||
SF->dump();
|
SF->dump();
|
||||||
return Context.hadError();
|
return Context.hadError();
|
||||||
} else if (Action == FrontendOptions::EmitImportedModules) {
|
} else if (Action == FrontendOptions::EmitImportedModules) {
|
||||||
|
|||||||
20
test/Frontend/emit-syntax.swift
Normal file
20
test/Frontend/emit-syntax.swift
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// RUN: %target-swift-frontend -emit-syntax %s | %FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: "kind": "kw_struct"
|
||||||
|
// CHECK: "kind": "identifier",
|
||||||
|
// CHECK: "text": "Foo"
|
||||||
|
// CHECK: "kind": "l_brace"
|
||||||
|
struct Foo {
|
||||||
|
// CHECK: "kind": "kw_let"
|
||||||
|
// CHECK: "kind": "colon"
|
||||||
|
// CHECK: "kind": "identifier"
|
||||||
|
// CHECK: "text": "Int"
|
||||||
|
let x: Int
|
||||||
|
// CHECK: "kind": "r_brace"
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: "leadingTrivia": [
|
||||||
|
// CHECK: "kind": "LineComment",
|
||||||
|
// CHECK: "value": "\/\/ Comment at the end of the file"
|
||||||
|
|
||||||
|
// Comment at the end of the file
|
||||||
Reference in New Issue
Block a user