/
input4.txt
93 lines (84 loc) · 3.47 KB
/
input4.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import SwiftSyntax
final class SnakeCaseRewriter: SyntaxRewriter {
// We'll consider an identifier snake case if it has two or more
// non-underscore groups of characters separated by underscores
private func isSnakeCase(_ identifier: String) -> Bool {
return identifier
.components(separatedBy: "_")
.filter({!$0.isEmpty})
.count > 1
}
/// Removes all underscores from the identifier and capitalizes characters
/// following underscores. Assumes `identifier` is a valid identifier. Ignores
/// leading underscores.
private func convertToCamelCase(_ identifier: String) -> String {
let identifier = Array(identifier)
var new_identifier = ""
var i = 0
var has_seen_non_underscore_character = false
while i < identifier.count {
if identifier[i] != "_" {
has_seen_non_underscore_character = true
}
if identifier[i] == "_" && !has_seen_non_underscore_character {
new_identifier.append("_")
i += 1
} else if identifier[i] == "_" &&
i+1 < identifier.count &&
("a"..."z").contains(identifier[i+1]) {
new_identifier.append(identifier[i+1].uppercased())
i += 2
} else if identifier[i] != "_" {
new_identifier.append(identifier[i])
i += 1
} else {
i += 1
}
}
return new_identifier
}
override func visit(_ node: IdentifierPatternSyntax) -> PatternSyntax {
guard case .identifier(let identifier) = node.identifier.tokenKind else { return node }
if isSnakeCase(identifier) {
let new_identifier = convertToCamelCase(identifier)
let new_token = node.identifier.withKind(.identifier(new_identifier))
let new_node = node.withIdentifier(new_token)
return super.visit(new_node)
}
return super.visit(node)
}
override func visit(_ node: IdentifierExprSyntax) -> ExprSyntax {
guard case .identifier(let identifier) = node.identifier.tokenKind else { return node }
if isSnakeCase(identifier) {
let new_identifier = convertToCamelCase(identifier)
let new_token = node.identifier.withKind(.identifier(new_identifier))
let new_node = node.withIdentifier(new_token)
return super.visit(new_node)
}
return super.visit(node)
}
override func visit(_ node: FunctionParameterSyntax) -> Syntax {
// If both firstName and secondName are non nil then it's a function
// parameter name like foo(withX x: ...) and we want to modify the
// secondName. If only firstName is non nil then it's a function parameter
// like foo(x: ...) and we wont to modify the first name.
if let _ = node.firstName,
let second_name_token = node.secondName,
case .identifier(let identifier) = second_name_token.tokenKind,
isSnakeCase(identifier) {
let new_identifier = convertToCamelCase(identifier)
let new_second_name = second_name_token.withKind(.identifier(new_identifier))
let new_node = node.withSecondName(new_second_name)
return super.visit(new_node)
} else if let first_name_token = node.firstName,
case .identifier(let identifier) = first_name_token.tokenKind,
isSnakeCase(identifier) {
let new_identifier = convertToCamelCase(identifier)
let new_first_name = first_name_token.withKind(.identifier(new_identifier))
let new_node = node.withFirstName(new_first_name)
return super.visit(new_node)
}
// We should never get here. You can't have an unnamed parameter!
return super.visit(node)
}
}