CleanCocoa / CleanCocoa/DeclarativeTextKit
Skip evaluation of a Modifying block iff it doesn't do anything
- Ngôn ngữ chính
- Swift
- Star
- 50
- Fork
- 0
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Mô tả
The `Modifying() { }` construct always evaluates even if the block is empty.
With TextKit integration, this means
1. an undo group is being started (and ended)
2. `NSTextView.shouldChangeText(in:replacementString:)` and `didChangeText()` are being run to guard against unwanted changes
With syntax highlighting in the text storage, you may end up processing the text for what's essentially a no-op.
## How to test
To get an empty block, use a for-loop to trigger the `buildArray` path of the result builder, but without any actual iterations:
```swift
Modifying(selectedRange) { _ in
for _ in 0 ..< 0 {
Insert(0) { "loop never runs" }
}
}
```
I'm not sure whether we can figure out at all whether a result builder produces nothing (i.e. empty array).
## Complete test case
This test fails with a thrown error at `try buffer.evaluate` because the text view doesn't permit changes in the range.
This should not be a problem, because the range is not actually changed.
```swift
func testModifying_EmptyLoopBlock_SkipsEvaluation() throws {
class TextViewSpy: NSTextView {
var didCallShouldChangeText = false
var didCallDidChangeText = false
override func shouldChangeText(in affectedCharRange: NSRange, replacementString: String?) -> Bool {
didCallShouldChangeText = true
return false // Would abort modification an error
}
override func didChangeText() {
didCallDidChangeText = true
}
}
let textViewSpy = TextViewSpy()
textViewSpy.string = "Lorem ipsum."
let buffer = NSTextViewBuffer(textView: textViewSpy)
let selectedRange: SelectedRange = .init(location: 6, length: 5)
assertBufferState(buffer, "Lorem ipsum.ˇ")
try buffer.evaluate {
Modifying(selectedRange) { _ in
for _ in 0 ..< 0 {
Insert(0) { "loop never runs" }
}
}
}
XCTAssertFalse(textViewSpy.didCallShouldChangeText)
XCTAssertFalse(textViewSpy.didCallDidChangeText)
}
```
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Hướng nghiên cứu
Bắt đầu từ construct Modifying và entry point buffer.evaluate, sau đó kiểm tra cách một block result-builder rỗng được biểu diễn cho đường dẫn buildArray. Tái hiện vấn đề bằng testModifying_EmptyLoopBlock_SkipsEvaluation và TextViewSpy được cung cấp. Hoàn thành khi block vòng lặp rỗng bỏ qua việc đánh giá và không callback thay đổi văn bản nào được gọi.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- swift
- Lĩnh vực
- desktop
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 35/100