1
1
import SwiftSyntax
2
2
import Foundation
3
3
4
+ extension SyntaxClassification {
5
+ var tag : String {
6
+ switch self {
7
+ case . none: return " "
8
+ case . keyword: return " kw "
9
+ case . identifier: return " "
10
+ case . typeIdentifier: return " type "
11
+ case . dollarIdentifier: return " dollar "
12
+ case . integerLiteral: return " int "
13
+ case . floatingLiteral: return " float "
14
+ case . stringLiteral: return " str "
15
+ case . stringInterpolationAnchor: return " anchor "
16
+ case . poundDirectiveKeyword: return " #kw "
17
+ case . buildConfigId: return " #id "
18
+ case . attribute: return " attr-builtin "
19
+ case . objectLiteral: return " object-literal "
20
+ case . editorPlaceholder: return " placeholder "
21
+ case . lineComment: return " comment-line "
22
+ case . blockComment: return " comment-block "
23
+ case . docLineComment: return " doc-comment-line "
24
+ case . docBlockComment: return " doc-comment-block "
25
+ }
26
+ }
27
+ }
28
+
4
29
class ClassifiedSyntaxTreePrinter : SyntaxVisitor {
5
30
private let classifications : [ TokenSyntax : SyntaxClassification ]
6
- private var currentTag = " "
31
+ private var currentClassification = SyntaxClassification . none
7
32
private var skipNextNewline = false
8
33
private var result = " "
9
34
@@ -17,56 +42,58 @@ class ClassifiedSyntaxTreePrinter: SyntaxVisitor {
17
42
result = " "
18
43
visit ( tree)
19
44
// Emit the last closing tag
20
- recordCurrentTag ( " " )
45
+ recordCurrentClassification ( . none )
21
46
return result
22
47
}
23
48
24
49
// MARK: Implementation
25
50
26
51
/// Closes the current tag if it is different from the previous one and opens
27
52
/// a tag with the specified ID.
28
- private func recordCurrentTag( _ tag: String ) {
29
- if currentTag != tag {
30
- if !currentTag. isEmpty {
31
- result += " </ " + currentTag + " > "
53
+ private func recordCurrentClassification(
54
+ _ classification: SyntaxClassification
55
+ ) {
56
+ if currentClassification != classification {
57
+ if currentClassification != . none {
58
+ result += " </ " + currentClassification. tag + " > "
32
59
}
33
- if !tag . isEmpty {
34
- result += " < " + tag + " > "
60
+ if classification != . none {
61
+ result += " < " + classification . tag + " > "
35
62
}
36
63
}
37
- currentTag = tag
64
+ currentClassification = classification
38
65
}
39
66
40
67
private func visit( _ piece: TriviaPiece ) {
41
- let tag : String
68
+ let classification : SyntaxClassification
42
69
switch piece {
43
70
case . spaces, . tabs, . verticalTabs, . formfeeds:
44
- tag = " "
71
+ classification = . none
45
72
case . newlines, . carriageReturns, . carriageReturnLineFeeds:
46
73
if skipNextNewline {
47
74
skipNextNewline = false
48
75
return
49
76
}
50
- tag = " "
77
+ classification = . none
51
78
case . backticks:
52
- tag = " "
79
+ classification = . none
53
80
case . lineComment( let text) :
54
81
// Don't print CHECK lines
55
82
if text. hasPrefix ( " // CHECK " ) {
56
83
skipNextNewline = true
57
84
return
58
85
}
59
- tag = " comment-line "
86
+ classification = . lineComment
60
87
case . blockComment:
61
- tag = " comment-block "
88
+ classification = . blockComment
62
89
case . docLineComment:
63
- tag = " doc-comment-line "
90
+ classification = . docLineComment
64
91
case . docBlockComment:
65
- tag = " doc-comment-block "
92
+ classification = . docBlockComment
66
93
case . garbageText:
67
- tag = " "
94
+ classification = . none
68
95
}
69
- recordCurrentTag ( tag )
96
+ recordCurrentClassification ( classification )
70
97
piece. write ( to: & result)
71
98
}
72
99
@@ -76,31 +103,10 @@ class ClassifiedSyntaxTreePrinter: SyntaxVisitor {
76
103
}
77
104
}
78
105
79
- private func getTagForSyntaxClassification(
80
- _ classification: SyntaxClassification
81
- ) -> String {
82
- switch ( classification) {
83
- case . none: return " "
84
- case . keyword: return " kw "
85
- case . identifier: return " "
86
- case . typeIdentifier: return " type "
87
- case . dollarIdentifier: return " dollar "
88
- case . integerLiteral: return " int "
89
- case . floatingLiteral: return " float "
90
- case . stringLiteral: return " str "
91
- case . stringInterpolationAnchor: return " anchor "
92
- case . poundDirectiveKeyword: return " #kw "
93
- case . buildConfigId: return " #id "
94
- case . attribute: return " attr-builtin "
95
- case . objectLiteral: return " object-literal "
96
- case . editorPlaceholder: return " placeholder "
97
- }
98
- }
99
-
100
106
override func visit( _ node: TokenSyntax ) {
101
107
visit ( node. leadingTrivia)
102
108
let classification = classifications [ node] ?? SyntaxClassification . none
103
- recordCurrentTag ( getTagForSyntaxClassification ( classification) )
109
+ recordCurrentClassification ( classification)
104
110
result += node. text
105
111
visit ( node. trailingTrivia)
106
112
}
0 commit comments