Skip to content

Commit 8149134

Browse files
committed
Remove redundant closing parenthesis from last line in suggestions
1 parent c7f20a2 commit 8149134

File tree

2 files changed

+236
-0
lines changed

2 files changed

+236
-0
lines changed

Tool/Sources/SuggestionProvider/PostProcessingSuggestionServiceMiddleware.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public struct PostProcessingSuggestionServiceMiddleware: SuggestionServiceMiddle
1515
var suggestion = $0
1616
if suggestion.text.allSatisfy({ $0.isWhitespace || $0.isNewline }) { return nil }
1717
Self.removeTrailingWhitespacesAndNewlines(&suggestion)
18+
Self.removeRedundantClosingParenthesis(&suggestion, lines: request.lines)
1819
if !Self.checkIfSuggestionHasNoEffect(suggestion, request: request) { return nil }
1920
return suggestion
2021
}
@@ -28,6 +29,44 @@ public struct PostProcessingSuggestionServiceMiddleware: SuggestionServiceMiddle
2829
suggestion.text = String(text)
2930
}
3031

32+
/// Remove the parenthesis in the last line of the suggestion if
33+
/// - It contains only closing parenthesis
34+
/// - It's identical to the next line below the range of the suggestion
35+
static func removeRedundantClosingParenthesis(
36+
_ suggestion: inout CodeSuggestion,
37+
lines: [String]
38+
) {
39+
let nextLineIndex = suggestion.range.end.line + 1
40+
guard nextLineIndex < lines.endIndex, nextLineIndex >= 0 else { return }
41+
let nextLine = lines[nextLineIndex].dropLast(1)
42+
let lineBreakIndex = suggestion.text.lastIndex(where: { $0.isNewline })
43+
let lastLineIndex = if let index = lineBreakIndex {
44+
suggestion.text.index(after: index)
45+
} else {
46+
suggestion.text.startIndex
47+
}
48+
guard lastLineIndex < suggestion.text.endIndex else { return }
49+
let lastSuggestionLine = suggestion.text[lastLineIndex...]
50+
guard lastSuggestionLine == nextLine else { return }
51+
52+
let closingParenthesis: [Character] = [")", "]", "}", ">"]
53+
let validCharacters = Set(closingParenthesis + [" ", ","])
54+
55+
let trimmedLastSuggestionLine = nextLine.trimmingCharacters(in: .whitespacesAndNewlines)
56+
guard !trimmedLastSuggestionLine.isEmpty else { return }
57+
58+
if trimmedLastSuggestionLine == "```"
59+
|| trimmedLastSuggestionLine == "\"\"\""
60+
|| trimmedLastSuggestionLine.allSatisfy({ validCharacters.contains($0) })
61+
{
62+
if let lastIndex = lineBreakIndex {
63+
suggestion.text = String(suggestion.text[..<lastIndex])
64+
} else {
65+
suggestion.text = ""
66+
}
67+
}
68+
}
69+
3170
static func checkIfSuggestionHasNoEffect(
3271
_ suggestion: CodeSuggestion,
3372
request: SuggestionRequest

Tool/Tests/SuggestionProviderTests/PostProcessingSuggestionServiceMiddlewareTests.swift

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,33 @@ class PostProcessingSuggestionServiceMiddlewareTests: XCTestCase {
3434
relevantCodeSnippets: []
3535
)
3636
}
37+
38+
func test_empty() async throws {
39+
let middleware = PostProcessingSuggestionServiceMiddleware()
40+
41+
let handler: PostProcessingSuggestionServiceMiddleware.Next = { _ in
42+
[
43+
.init(
44+
id: "1",
45+
text: "",
46+
position: .init(line: 0, character: 0),
47+
range: .init(startPair: (0, 0), endPair: (0, 0))
48+
),
49+
]
50+
}
51+
52+
let suggestions = try await middleware.getSuggestion(
53+
createRequest("", .init(line: 0, character: 0)),
54+
configuration: .init(
55+
acceptsRelevantCodeSnippets: true,
56+
mixRelevantCodeSnippetsInSource: true,
57+
acceptsRelevantSnippetsFromOpenedFiles: true
58+
),
59+
next: handler
60+
)
61+
62+
XCTAssertEqual(suggestions, [])
63+
}
3764

3865
func test_trailing_whitespaces_and_new_lines_should_be_removed() async throws {
3966
let middleware = PostProcessingSuggestionServiceMiddleware()
@@ -184,5 +211,175 @@ class PostProcessingSuggestionServiceMiddlewareTests: XCTestCase {
184211
),
185212
])
186213
}
214+
215+
func test_remove_duplicated_trailing_closing_parenthesis_single_parenthesis() async throws {
216+
let middleware = PostProcessingSuggestionServiceMiddleware()
217+
218+
let handler: PostProcessingSuggestionServiceMiddleware.Next = { _ in
219+
[
220+
.init(
221+
id: "1",
222+
text: "hello world\n}",
223+
position: .init(line: 0, character: 1),
224+
range: .init(startPair: (0, 0), endPair: (0, 1))
225+
),
226+
]
227+
}
228+
229+
let suggestions = try await middleware.getSuggestion(
230+
createRequest("h\n}\n", .init(line: 0, character: 1)),
231+
configuration: .init(
232+
acceptsRelevantCodeSnippets: true,
233+
mixRelevantCodeSnippetsInSource: true,
234+
acceptsRelevantSnippetsFromOpenedFiles: true
235+
),
236+
next: handler
237+
)
238+
239+
XCTAssertEqual(suggestions, [
240+
.init(
241+
id: "1",
242+
text: "hello world",
243+
position: .init(line: 0, character: 1),
244+
range: .init(startPair: (0, 0), endPair: (0, 1))
245+
),
246+
])
247+
}
248+
249+
func test_remove_duplicated_trailing_closing_parenthesis_single_line() async throws {
250+
let middleware = PostProcessingSuggestionServiceMiddleware()
251+
252+
let handler: PostProcessingSuggestionServiceMiddleware.Next = { _ in
253+
[
254+
.init(
255+
id: "1",
256+
text: "}",
257+
position: .init(line: 0, character: 0),
258+
range: .init(startPair: (0, 0), endPair: (0, 0))
259+
),
260+
]
261+
}
262+
263+
let suggestions = try await middleware.getSuggestion(
264+
createRequest("\n}\n", .init(line: 0, character: 0)),
265+
configuration: .init(
266+
acceptsRelevantCodeSnippets: true,
267+
mixRelevantCodeSnippetsInSource: true,
268+
acceptsRelevantSnippetsFromOpenedFiles: true
269+
),
270+
next: handler
271+
)
272+
273+
XCTAssertEqual(suggestions, [
274+
.init(
275+
id: "1",
276+
text: "",
277+
position: .init(line: 0, character: 0),
278+
range: .init(startPair: (0, 0), endPair: (0, 0))
279+
),
280+
])
281+
}
282+
283+
func test_remove_duplicated_trailing_closing_parenthesis_leading_space() async throws {
284+
let middleware = PostProcessingSuggestionServiceMiddleware()
285+
286+
let handler: PostProcessingSuggestionServiceMiddleware.Next = { _ in
287+
[
288+
.init(
289+
id: "1",
290+
text: "hello world\n }",
291+
position: .init(line: 0, character: 1),
292+
range: .init(startPair: (0, 0), endPair: (0, 1))
293+
),
294+
]
295+
}
296+
297+
let suggestions = try await middleware.getSuggestion(
298+
createRequest("h\n }\n", .init(line: 0, character: 1)),
299+
configuration: .init(
300+
acceptsRelevantCodeSnippets: true,
301+
mixRelevantCodeSnippetsInSource: true,
302+
acceptsRelevantSnippetsFromOpenedFiles: true
303+
),
304+
next: handler
305+
)
306+
307+
XCTAssertEqual(suggestions, [
308+
.init(
309+
id: "1",
310+
text: "hello world",
311+
position: .init(line: 0, character: 1),
312+
range: .init(startPair: (0, 0), endPair: (0, 1))
313+
),
314+
])
315+
}
316+
317+
func test_remove_duplicated_trailing_closing_parenthesis_commas() async throws {
318+
let middleware = PostProcessingSuggestionServiceMiddleware()
319+
320+
let handler: PostProcessingSuggestionServiceMiddleware.Next = { _ in
321+
[
322+
.init(
323+
id: "1",
324+
text: "hello world\n,},",
325+
position: .init(line: 0, character: 1),
326+
range: .init(startPair: (0, 0), endPair: (0, 1))
327+
),
328+
]
329+
}
330+
331+
let suggestions = try await middleware.getSuggestion(
332+
createRequest("h\n,},\n", .init(line: 0, character: 1)),
333+
configuration: .init(
334+
acceptsRelevantCodeSnippets: true,
335+
mixRelevantCodeSnippetsInSource: true,
336+
acceptsRelevantSnippetsFromOpenedFiles: true
337+
),
338+
next: handler
339+
)
340+
341+
XCTAssertEqual(suggestions, [
342+
.init(
343+
id: "1",
344+
text: "hello world",
345+
position: .init(line: 0, character: 1),
346+
range: .init(startPair: (0, 0), endPair: (0, 1))
347+
),
348+
])
349+
}
350+
351+
func test_remove_duplicated_trailing_closing_parenthesis_multiple_parenthesis() async throws {
352+
let middleware = PostProcessingSuggestionServiceMiddleware()
353+
354+
let handler: PostProcessingSuggestionServiceMiddleware.Next = { _ in
355+
[
356+
.init(
357+
id: "1",
358+
text: "hello world\n}))>}}",
359+
position: .init(line: 0, character: 1),
360+
range: .init(startPair: (0, 0), endPair: (0, 1))
361+
),
362+
]
363+
}
364+
365+
let suggestions = try await middleware.getSuggestion(
366+
createRequest("h\n}))>}}\n", .init(line: 0, character: 1)),
367+
configuration: .init(
368+
acceptsRelevantCodeSnippets: true,
369+
mixRelevantCodeSnippetsInSource: true,
370+
acceptsRelevantSnippetsFromOpenedFiles: true
371+
),
372+
next: handler
373+
)
374+
375+
XCTAssertEqual(suggestions, [
376+
.init(
377+
id: "1",
378+
text: "hello world",
379+
position: .init(line: 0, character: 1),
380+
range: .init(startPair: (0, 0), endPair: (0, 1))
381+
),
382+
])
383+
}
187384
}
188385

0 commit comments

Comments
 (0)