10
10
//
11
11
//===----------------------------------------------------------------------===//
12
12
13
- import SwiftSyntax
13
+ @ _spi ( RawSyntax ) import SwiftSyntax
14
14
15
15
/// A rewriter that performs a "basic" format of the passed tree.
16
16
///
@@ -271,7 +271,7 @@ open class BasicFormat: SyntaxRewriter {
271
271
( . keyword( . `init`) , . leftParen) , // init()
272
272
( . keyword( . self ) , . period) , // self.someProperty
273
273
( . keyword( . Self) , . period) , // self.someProperty
274
- ( . keyword( . set) , . leftParen) , // var mYar : Int { set(value) {} }
274
+ ( . keyword( . set) , . leftParen) , // var mVar : Int { set(value) {} }
275
275
( . keyword( . subscript) , . leftParen) , // subscript(x: Int)
276
276
( . keyword( . super) , . period) , // super.someProperty
277
277
( . leftBrace, . rightBrace) , // {}
@@ -348,6 +348,26 @@ open class BasicFormat: SyntaxRewriter {
348
348
return true
349
349
}
350
350
351
+ /// Change the text of a token during formatting.
352
+ ///
353
+ /// This allows formats to e.g. replace missing tokens by placeholder tokens.
354
+ ///
355
+ /// - Parameter token: The token whose text should be changed
356
+ /// - Returns: The new text or `nil` if the text should not be changed
357
+ open func transformTokenText( _ token: TokenSyntax ) -> String ? {
358
+ return nil
359
+ }
360
+
361
+ /// Change the presence of a token during formatting.
362
+ ///
363
+ /// This allows formats to e.g. replace missing tokens by placeholder tokens.
364
+ ///
365
+ /// - Parameter token: The token whose presence should be changed
366
+ /// - Returns: The new presence or `nil` if the presence should not be changed
367
+ open func transformTokenPresence( _ token: TokenSyntax ) -> SourcePresence ? {
368
+ return nil
369
+ }
370
+
351
371
// MARK: - Formatting a token
352
372
353
373
open override func visit( _ token: TokenSyntax ) -> TokenSyntax {
@@ -357,6 +377,8 @@ open class BasicFormat: SyntaxRewriter {
357
377
let isInitialToken = self . previousToken == nil
358
378
let previousToken = self . previousToken ?? token. previousToken ( viewMode: viewMode)
359
379
let nextToken = token. nextToken ( viewMode: viewMode)
380
+ let transformedTokenText = self . transformTokenText ( token)
381
+ let transformedTokenPresence = self . transformTokenPresence ( token)
360
382
361
383
/// In addition to existing trivia of `previousToken`, also considers
362
384
/// `previousToken` as ending with whitespace if it and `token` should be
@@ -372,7 +394,7 @@ open class BasicFormat: SyntaxRewriter {
372
394
|| ( requiresWhitespace ( between: previousToken, and: token) && isMutable ( previousToken) )
373
395
} ( )
374
396
375
- /// This method does not consider any posssible mutations to `previousToken`
397
+ /// This method does not consider any possible mutations to `previousToken`
376
398
/// because newlines should be added to the next token's leading trivia.
377
399
let previousTokenWillEndWithNewline : Bool = {
378
400
guard let previousToken = previousToken else {
@@ -416,6 +438,14 @@ open class BasicFormat: SyntaxRewriter {
416
438
if nextToken. leadingTrivia. startsWithNewline {
417
439
return true
418
440
}
441
+ if nextToken. leadingTrivia. isEmpty {
442
+ if nextToken. text. first? . isNewline ?? false {
443
+ return true
444
+ }
445
+ if nextToken. text. isEmpty && nextToken. trailingTrivia. startsWithNewline {
446
+ return true
447
+ }
448
+ }
419
449
if requiresNewline ( between: token, and: nextToken) ,
420
450
isMutable ( nextToken) ,
421
451
!token. trailingTrivia. endsWithNewline,
@@ -436,6 +466,19 @@ open class BasicFormat: SyntaxRewriter {
436
466
return trailingTrivia + Trivia( pieces: nextTokenLeadingWhitespace)
437
467
} ( )
438
468
469
+ /// Whether the leading trivia of the token is followed by a newline.
470
+ let leadingTriviaIsFollowedByNewline : Bool = {
471
+ if ( transformedTokenText ?? token. text) . isEmpty && token. trailingTrivia. startsWithNewline {
472
+ return true
473
+ } else if token. text. first? . isNewline ?? false {
474
+ return true
475
+ } else if ( transformedTokenText ?? token. text) . isEmpty && token. trailingTrivia. isEmpty && nextTokenWillStartWithNewline {
476
+ return true
477
+ } else {
478
+ return false
479
+ }
480
+ } ( )
481
+
439
482
if requiresNewline ( between: previousToken, and: token) {
440
483
// Add a leading newline if the token requires it unless
441
484
// - it already starts with a newline or
@@ -455,7 +498,8 @@ open class BasicFormat: SyntaxRewriter {
455
498
}
456
499
}
457
500
458
- if leadingTrivia. indentation ( isOnNewline: isInitialToken || previousTokenWillEndWithNewline) == [ ] {
501
+ let isEmptyLine = token. leadingTrivia. isEmpty && leadingTriviaIsFollowedByNewline
502
+ if leadingTrivia. indentation ( isOnNewline: isInitialToken || previousTokenWillEndWithNewline) == [ ] && !isEmptyLine {
459
503
// If the token starts on a new line and does not have indentation, this
460
504
// is the last non-indented token. Store its indentation level
461
505
anchorPoints [ token] = currentIndentationLevel
@@ -501,14 +545,24 @@ open class BasicFormat: SyntaxRewriter {
501
545
leadingTrivia = leadingTrivia. indented ( indentation: leadingTriviaIndentation, isOnNewline: previousTokenIsStringLiteralEndingInNewline)
502
546
trailingTrivia = trailingTrivia. indented ( indentation: trailingTriviaIndentation, isOnNewline: false )
503
547
504
- leadingTrivia = leadingTrivia. trimmingTrailingWhitespaceBeforeNewline ( isBeforeNewline: false )
548
+ leadingTrivia = leadingTrivia. trimmingTrailingWhitespaceBeforeNewline ( isBeforeNewline: leadingTriviaIsFollowedByNewline )
505
549
trailingTrivia = trailingTrivia. trimmingTrailingWhitespaceBeforeNewline ( isBeforeNewline: nextTokenWillStartWithNewline)
506
550
507
- if leadingTrivia == token. leadingTrivia && trailingTrivia == token. trailingTrivia {
508
- return token
551
+ var result = token. detached
552
+ if leadingTrivia != result. leadingTrivia {
553
+ result = result. with ( \. leadingTrivia, leadingTrivia)
509
554
}
510
-
511
- return token. detached. with ( \. leadingTrivia, leadingTrivia) . with ( \. trailingTrivia, trailingTrivia)
555
+ if trailingTrivia != result. trailingTrivia {
556
+ result = result. with ( \. trailingTrivia, trailingTrivia)
557
+ }
558
+ if let transformedTokenText {
559
+ let newKind = TokenKind . fromRaw ( kind: token. tokenKind. decomposeToRaw ( ) . rawKind, text: transformedTokenText)
560
+ result = result. with ( \. tokenKind, newKind) . with ( \. presence, . present)
561
+ }
562
+ if let transformedTokenPresence {
563
+ result = result. with ( \. presence, transformedTokenPresence)
564
+ }
565
+ return result
512
566
}
513
567
}
514
568
0 commit comments