36
36
#include " llvm/ADT/SmallString.h"
37
37
#include " llvm/ADT/StringRef.h"
38
38
#include " llvm/ADT/STLExtras.h"
39
+ #include " llvm/Support/BinaryByteStream.h"
39
40
#include " llvm/Support/MemoryBuffer.h"
40
41
#include " llvm/Support/NativeFormatting.h"
41
42
#include " llvm/Support/Path.h"
@@ -77,6 +78,8 @@ struct SKEditorConsumerOptions {
77
78
bool EnableStructure = false ;
78
79
bool EnableDiagnostics = false ;
79
80
SyntaxTreeTransferMode SyntaxTransferMode = SyntaxTreeTransferMode::Off;
81
+ SyntaxTreeSerializationFormat SyntaxSerializationFormat =
82
+ SyntaxTreeSerializationFormat::JSON;
80
83
bool SyntacticOnly = false ;
81
84
bool EnableSyntaxReuseInfo = false ;
82
85
};
@@ -263,6 +266,20 @@ static SyntaxTreeTransferMode syntaxTransferModeFromUID(sourcekitd_uid_t UID) {
263
266
}
264
267
}
265
268
269
+ static llvm::Optional<SyntaxTreeSerializationFormat>
270
+ syntaxSerializationFormatFromUID (sourcekitd_uid_t UID) {
271
+ if (UID == nullptr ) {
272
+ // Default is JSON
273
+ return SyntaxTreeSerializationFormat::JSON;
274
+ } else if (UID == KindSyntaxTreeSerializationJSON) {
275
+ return SyntaxTreeSerializationFormat::JSON;
276
+ } else if (UID == KindSyntaxTreeSerializationByteTree) {
277
+ return SyntaxTreeSerializationFormat::ByteTree;
278
+ } else {
279
+ return llvm::None;
280
+ }
281
+ }
282
+
266
283
static void handleRequestImpl (sourcekitd_object_t Req,
267
284
ResponseReceiver Receiver);
268
285
@@ -451,6 +468,7 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) {
451
468
int64_t EnableDiagnostics = true ;
452
469
Req.getInt64 (KeyEnableDiagnostics, EnableDiagnostics, /* isOptional=*/ true );
453
470
auto TransferModeUID = Req.getUID (KeySyntaxTreeTransferMode);
471
+ auto SerializationFormatUID = Req.getUID (KeySyntaxTreeSerializationFormat);
454
472
int64_t SyntacticOnly = false ;
455
473
Req.getInt64 (KeySyntacticOnly, SyntacticOnly, /* isOptional=*/ true );
456
474
int64_t EnableSyntaxReuseInfo = false ;
@@ -462,6 +480,11 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) {
462
480
Opts.EnableStructure = EnableStructure;
463
481
Opts.EnableDiagnostics = EnableDiagnostics;
464
482
Opts.SyntaxTransferMode = syntaxTransferModeFromUID (TransferModeUID);
483
+ auto SyntaxSerializationFormat =
484
+ syntaxSerializationFormatFromUID (SerializationFormatUID);
485
+ if (!SyntaxSerializationFormat)
486
+ return Rec (createErrorRequestFailed (" Invalid serialization format" ));
487
+ Opts.SyntaxSerializationFormat = SyntaxSerializationFormat.getValue ();
465
488
Opts.SyntacticOnly = SyntacticOnly;
466
489
Opts.EnableSyntaxReuseInfo = EnableSyntaxReuseInfo;
467
490
return Rec (editorOpen (*Name, InputBuf.get (), Opts, Args));
@@ -494,18 +517,24 @@ void handleRequestImpl(sourcekitd_object_t ReqObj, ResponseReceiver Rec) {
494
517
Req.getInt64 (KeyEnableStructure, EnableStructure, /* isOptional=*/ true );
495
518
int64_t EnableDiagnostics = true ;
496
519
Req.getInt64 (KeyEnableDiagnostics, EnableDiagnostics, /* isOptional=*/ true );
497
- auto TransferModeUID = Req.getUID (KeySyntaxTreeTransferMode);
498
520
int64_t SyntacticOnly = false ;
499
521
Req.getInt64 (KeySyntacticOnly, SyntacticOnly, /* isOptional=*/ true );
500
522
int64_t EnableSyntaxReuseInfo = false ;
501
523
Req.getInt64 (KeyEnableSyntaxReuseRegions, EnableSyntaxReuseInfo,
502
524
/* isOptional=*/ true );
525
+ auto TransferModeUID = Req.getUID (KeySyntaxTreeTransferMode);
526
+ auto SerializationFormatUID = Req.getUID (KeySyntaxTreeSerializationFormat);
503
527
504
528
SKEditorConsumerOptions Opts;
505
529
Opts.EnableSyntaxMap = EnableSyntaxMap;
506
530
Opts.EnableStructure = EnableStructure;
507
531
Opts.EnableDiagnostics = EnableDiagnostics;
508
532
Opts.SyntaxTransferMode = syntaxTransferModeFromUID (TransferModeUID);
533
+ auto SyntaxSerializationFormat =
534
+ syntaxSerializationFormatFromUID (SerializationFormatUID);
535
+ if (!SyntaxSerializationFormat)
536
+ return Rec (createErrorRequestFailed (" Invalid serialization format" ));
537
+ Opts.SyntaxSerializationFormat = SyntaxSerializationFormat.getValue ();
509
538
Opts.EnableSyntaxReuseInfo = EnableSyntaxReuseInfo;
510
539
Opts.SyntacticOnly = SyntacticOnly;
511
540
Opts.EnableSyntaxReuseInfo = EnableSyntaxReuseInfo;
@@ -2420,11 +2449,39 @@ void SKEditorConsumer::handleSourceText(StringRef Text) {
2420
2449
Dict.set (KeySourceText, Text);
2421
2450
}
2422
2451
2423
- void serializeSyntaxTreeAsJson (
2452
+ void serializeSyntaxTreeAsByteTree (
2424
2453
const swift::syntax::SourceFileSyntax &SyntaxTree,
2425
2454
std::unordered_set<unsigned > &ReusedNodeIds,
2426
2455
ResponseBuilder::Dictionary &Dict) {
2427
2456
auto StartClock = clock ();
2457
+ // Serialize the syntax tree as a ByteTree
2458
+ llvm::AppendingBinaryByteStream Stream (llvm::support::endianness::little);
2459
+ llvm::BinaryStreamWriter Writer (Stream);
2460
+ swift::byteTree::ByteTreeWriter::write (/* ProtocolVersion=*/ 1 , Writer,
2461
+ *SyntaxTree.getRaw ());
2462
+
2463
+ std::unique_ptr<llvm::WritableMemoryBuffer> Buf =
2464
+ llvm::WritableMemoryBuffer::getNewUninitMemBuffer (Stream.data ().size ());
2465
+ memcpy (Buf->getBufferStart (), Stream.data ().data (), Stream.data ().size ());
2466
+
2467
+ Dict.setCustomBuffer (KeySerializedSyntaxTree, CustomBufferKind::RawData,
2468
+ std::move (Buf));
2469
+
2470
+ auto EndClock = clock ();
2471
+ LOG_SECTION (" incrParse Performance" , InfoLowPrio) {
2472
+ Log->getOS () << " Serialized " << Stream.data ().size ()
2473
+ << " bytes as ByteTree in " ;
2474
+ auto Seconds = (double )(EndClock - StartClock) * 1000 / CLOCKS_PER_SEC;
2475
+ llvm::write_double (Log->getOS (), Seconds, llvm::FloatStyle::Fixed, 2 );
2476
+ Log->getOS () << " ms" ;
2477
+ }
2478
+ }
2479
+
2480
+ void serializeSyntaxTreeAsJson (
2481
+ const swift::syntax::SourceFileSyntax &SyntaxTree,
2482
+ std::unordered_set<unsigned > ReusedNodeIds,
2483
+ ResponseBuilder::Dictionary &Dict) {
2484
+ auto StartClock = clock ();
2428
2485
// 4096 is a heuristic buffer size that appears to usually be able to fit an
2429
2486
// incremental syntax tree
2430
2487
size_t ReserveBufferSize = 4096 ;
@@ -2443,21 +2500,41 @@ void serializeSyntaxTreeAsJson(
2443
2500
2444
2501
auto EndClock = clock ();
2445
2502
LOG_SECTION (" incrParse Performance" , InfoLowPrio) {
2446
- Log->getOS () << " Serialized " << SyntaxTreeString.size () << " bytes in " ;
2447
- llvm::write_double (Log-> getOS (),
2448
- (double )(EndClock - StartClock) * 1000 / CLOCKS_PER_SEC,
2449
- llvm::FloatStyle::Fixed, 2 );
2503
+ Log->getOS () << " Serialized " << SyntaxTreeString.size ()
2504
+ << " bytes as JSON in " ;
2505
+ auto Seconds = (double )(EndClock - StartClock) * 1000 / CLOCKS_PER_SEC;
2506
+ llvm::write_double (Log-> getOS (), Seconds, llvm::FloatStyle::Fixed, 2 );
2450
2507
Log->getOS () << " ms" ;
2451
2508
}
2452
2509
}
2453
2510
2454
2511
void SKEditorConsumer::handleSyntaxTree (
2455
2512
const swift::syntax::SourceFileSyntax &SyntaxTree,
2456
2513
std::unordered_set<unsigned > &ReusedNodeIds) {
2457
- if (Opts.SyntaxTransferMode == SyntaxTreeTransferMode::Off)
2514
+
2515
+ std::unordered_set<unsigned > OmitNodes;
2516
+ switch (Opts.SyntaxTransferMode ) {
2517
+ case SourceKit::SyntaxTreeTransferMode::Off:
2518
+ // Don't serialize the tree at all
2458
2519
return ;
2520
+ case SourceKit::SyntaxTreeTransferMode::Full:
2521
+ // Serialize the tree without omitting any nodes
2522
+ OmitNodes = {};
2523
+ break ;
2524
+ case SourceKit::SyntaxTreeTransferMode::Incremental:
2525
+ // Serialize the tree and omit all nodes that have been reused
2526
+ OmitNodes = ReusedNodeIds;
2527
+ break ;
2528
+ }
2459
2529
2460
- serializeSyntaxTreeAsJson (SyntaxTree, ReusedNodeIds, Dict);
2530
+ switch (Opts.SyntaxSerializationFormat ) {
2531
+ case SourceKit::SyntaxTreeSerializationFormat::JSON:
2532
+ serializeSyntaxTreeAsJson (SyntaxTree, OmitNodes, Dict);
2533
+ break ;
2534
+ case SourceKit::SyntaxTreeSerializationFormat::ByteTree:
2535
+ serializeSyntaxTreeAsByteTree (SyntaxTree, OmitNodes, Dict);
2536
+ break ;
2537
+ }
2461
2538
}
2462
2539
2463
2540
void SKEditorConsumer::handleSyntaxReuseRegions (
0 commit comments