@@ -38,12 +38,30 @@ final class HighlighterTests: XCTestCase {
38
38
func attributesFor( _ capture: CaptureName ? ) -> [ NSAttributedString . Key : Any ] { [ : ] }
39
39
}
40
40
41
+ class SentryStorageDelegate : NSObject , NSTextStorageDelegate {
42
+ var editedIndices : IndexSet = IndexSet ( )
43
+
44
+ func textStorage(
45
+ _ textStorage: NSTextStorage ,
46
+ didProcessEditing editedMask: NSTextStorageEditActions ,
47
+ range editedRange: NSRange ,
48
+ changeInLength delta: Int ) {
49
+ editedIndices. insert ( integersIn: editedRange)
50
+ }
51
+ }
52
+
53
+ var attributeProvider : MockAttributeProvider !
54
+ var textView : TextView !
55
+
56
+ override func setUp( ) {
57
+ attributeProvider = MockAttributeProvider ( )
58
+ textView = Mock . textView ( )
59
+ textView. frame = NSRect ( x: 0 , y: 0 , width: 1000 , height: 1000 )
60
+ }
61
+
41
62
@MainActor
42
63
func test_canceledHighlightsAreInvalidated( ) {
43
64
let highlightProvider = MockHighlightProvider ( )
44
- let attributeProvider = MockAttributeProvider ( )
45
- let textView = Mock . textView ( )
46
- textView. frame = NSRect ( x: 0 , y: 0 , width: 1000 , height: 1000 )
47
65
textView. setText ( " Hello World! " )
48
66
let highlighter = Mock . highlighter (
49
67
textView: textView,
@@ -62,23 +80,8 @@ final class HighlighterTests: XCTestCase {
62
80
63
81
@MainActor
64
82
func test_highlightsDoNotInvalidateEntireTextView( ) {
65
- class SentryStorageDelegate : NSObject , NSTextStorageDelegate {
66
- var editedIndices : IndexSet = IndexSet ( )
67
-
68
- func textStorage(
69
- _ textStorage: NSTextStorage ,
70
- didProcessEditing editedMask: NSTextStorageEditActions ,
71
- range editedRange: NSRange ,
72
- changeInLength delta: Int ) {
73
- editedIndices. insert ( integersIn: editedRange)
74
- }
75
- }
76
-
77
83
let highlightProvider = TreeSitterClient ( )
78
84
highlightProvider. forceSyncOperation = true
79
- let attributeProvider = MockAttributeProvider ( )
80
- let textView = Mock . textView ( )
81
- textView. frame = NSRect ( x: 0 , y: 0 , width: 1000 , height: 1000 )
82
85
textView. setText ( " func helloWorld() { \n \t print( \" Hello World! \" ) \n } " )
83
86
84
87
let highlighter = Mock . highlighter (
@@ -97,4 +100,49 @@ final class HighlighterTests: XCTestCase {
97
100
98
101
XCTAssertEqual ( sentryStorage. editedIndices, invalidSet) // Should only cause highlights on the first line
99
102
}
103
+
104
+ // This test isn't testing much highlighter functionality. However, we've seen crashes and other errors after normal
105
+ // editing that were caused by the highlighter and would only have been caught by an integration test like this.
106
+ @MainActor
107
+ func test_editFile( ) {
108
+ let highlightProvider = TreeSitterClient ( )
109
+ highlightProvider. forceSyncOperation = true
110
+ textView. setText ( " func helloWorld() { \n \t print( \" Hello World! \" ) \n } " ) // 44 chars
111
+
112
+ let highlighter = Mock . highlighter (
113
+ textView: textView,
114
+ highlightProvider: highlightProvider,
115
+ attributeProvider: attributeProvider
116
+ )
117
+ textView. addStorageDelegate ( highlighter)
118
+ highlighter. setLanguage ( language: . swift)
119
+ highlighter. invalidate ( )
120
+
121
+ // Delete Characters
122
+ textView. replaceCharacters ( in: [ NSRange ( location: 43 , length: 1 ) ] , with: " " )
123
+ textView. replaceCharacters ( in: [ NSRange ( location: 0 , length: 4 ) ] , with: " " )
124
+ textView. replaceCharacters ( in: [ NSRange ( location: 6 , length: 5 ) ] , with: " " )
125
+ textView. replaceCharacters ( in: [ NSRange ( location: 25 , length: 5 ) ] , with: " " )
126
+
127
+ XCTAssertEqual ( textView. string, " hello() { \n \t print( \" Hello ! \" ) \n " )
128
+
129
+ // Insert Characters
130
+ textView. replaceCharacters ( in: [ NSRange ( location: 29 , length: 0 ) ] , with: " } " )
131
+ textView. replaceCharacters (
132
+ in: [ NSRange ( location: 25 , length: 0 ) , NSRange ( location: 6 , length: 0 ) ] ,
133
+ with: " World "
134
+ )
135
+ // emulate typing with a cursor
136
+ textView. selectionManager. setSelectedRange ( NSRange ( location: 0 , length: 0 ) )
137
+ textView. insertText ( " f " )
138
+ textView. insertText ( " u " )
139
+ textView. insertText ( " n " )
140
+ textView. insertText ( " c " )
141
+ XCTAssertEqual ( textView. string, " func helloWorld() { \n \t print( \" Hello World! \" ) \n } " )
142
+
143
+ // Replace contents
144
+ textView. replaceCharacters ( in: textView. documentRange, with: " " )
145
+ textView. insertText ( " func helloWorld() { \n \t print( \" Hello World! \" ) \n } " )
146
+ XCTAssertEqual ( textView. string, " func helloWorld() { \n \t print( \" Hello World! \" ) \n } " )
147
+ }
100
148
}
0 commit comments