]> git.ipfire.org Git - thirdparty/git.git/commitdiff
userdiff: add support for Swift
authorShlok Kulshreshtha <diy2903@gmail.com>
Tue, 21 Jul 2026 06:57:36 +0000 (12:27 +0530)
committerJunio C Hamano <gitster@pobox.com>
Thu, 23 Jul 2026 14:14:34 +0000 (07:14 -0700)
Add a built-in userdiff driver for the Swift programming language so that
diff hunk headers and word diffs work out of the box for ".swift" files.

The funcname pattern is built for Swift's own declaration grammar: an
optional run of attributes ("@objc", "@available(iOS 13, *)", ...),
followed by an optional run of lowercase modifiers ("public", "static",
"final", ...), followed by a declaration keyword (func, class, struct,
enum, protocol, extension, actor, init, deinit, subscript). The keyword
is followed by a boundary that allows whitespace, "(" (init/subscript),
"?" or "!" (failable init), or "<" (generics), while still acting as a
word boundary so e.g. "initialize(" does not match.

The word regex recognizes Swift identifiers, hexadecimal, octal, binary,
integer and floating-point literals, and the language's operators.

Signed-off-by: Shlok Kulshreshtha <diy2903@gmail.com>
Acked-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
15 files changed:
Documentation/gitattributes.adoc
t/t4018/swift-actor [new file with mode: 0644]
t/t4018/swift-attribute-with-args [new file with mode: 0644]
t/t4018/swift-class [new file with mode: 0644]
t/t4018/swift-enum [new file with mode: 0644]
t/t4018/swift-extension [new file with mode: 0644]
t/t4018/swift-failable-init [new file with mode: 0644]
t/t4018/swift-func [new file with mode: 0644]
t/t4018/swift-generic-subscript [new file with mode: 0644]
t/t4018/swift-init [new file with mode: 0644]
t/t4018/swift-inline-attribute [new file with mode: 0644]
t/t4018/swift-modifiers [new file with mode: 0644]
t/t4018/swift-protocol [new file with mode: 0644]
t/t4018/swift-struct [new file with mode: 0644]
userdiff.c

index bd76167a45eb716cbeecefb030ec307ccf7ae01a..9fea75f96f928fa1e5f0d96efa43c93f18b319bf 100644 (file)
@@ -914,6 +914,8 @@ patterns are available:
 - `scheme` suitable for source code in most Lisp dialects,
   including Scheme, Emacs Lisp, Common Lisp, and Clojure.
 
+- `swift` suitable for source code in the Swift language.
+
 - `tex` suitable for source code for LaTeX documents.
 
 
diff --git a/t/t4018/swift-actor b/t/t4018/swift-actor
new file mode 100644 (file)
index 0000000..e4852f4
--- /dev/null
@@ -0,0 +1,5 @@
+actor RIGHT {
+    let a = 1
+    // a comment
+    let b = ChangeMe
+}
diff --git a/t/t4018/swift-attribute-with-args b/t/t4018/swift-attribute-with-args
new file mode 100644 (file)
index 0000000..22b1ee3
--- /dev/null
@@ -0,0 +1,7 @@
+struct View {
+    @available(iOS 13, *) public func RIGHT() {
+        let a = 1
+        // a comment
+        print(ChangeMe)
+    }
+}
diff --git a/t/t4018/swift-class b/t/t4018/swift-class
new file mode 100644 (file)
index 0000000..c3a9336
--- /dev/null
@@ -0,0 +1,5 @@
+class RIGHT {
+    let a = 1
+    // a comment
+    let b = ChangeMe
+}
diff --git a/t/t4018/swift-enum b/t/t4018/swift-enum
new file mode 100644 (file)
index 0000000..0a84302
--- /dev/null
@@ -0,0 +1,5 @@
+enum RIGHT {
+    case first
+    // a comment
+    case ChangeMe
+}
diff --git a/t/t4018/swift-extension b/t/t4018/swift-extension
new file mode 100644 (file)
index 0000000..cbc18ab
--- /dev/null
@@ -0,0 +1,5 @@
+extension RIGHT {
+    static let a = 1
+    // a comment
+    static let b = ChangeMe
+}
diff --git a/t/t4018/swift-failable-init b/t/t4018/swift-failable-init
new file mode 100644 (file)
index 0000000..4bbd621
--- /dev/null
@@ -0,0 +1,7 @@
+class Bar {
+    init?(RIGHT: Int) {
+        let x = 0
+        // a comment
+        print(ChangeMe)
+    }
+}
diff --git a/t/t4018/swift-func b/t/t4018/swift-func
new file mode 100644 (file)
index 0000000..1fecae0
--- /dev/null
@@ -0,0 +1,5 @@
+func RIGHT(x: Int) -> Int {
+    let y = x
+    // a comment
+    return ChangeMe
+}
diff --git a/t/t4018/swift-generic-subscript b/t/t4018/swift-generic-subscript
new file mode 100644 (file)
index 0000000..423cb58
--- /dev/null
@@ -0,0 +1,7 @@
+struct Container {
+    subscript<RIGHT>(index: Int) -> Int {
+        let a = 0
+        // a comment
+        return ChangeMe
+    }
+}
diff --git a/t/t4018/swift-init b/t/t4018/swift-init
new file mode 100644 (file)
index 0000000..dc7a298
--- /dev/null
@@ -0,0 +1,7 @@
+class Foo {
+    init(RIGHT: Int) {
+        let x = 0
+        // a comment
+        print(ChangeMe)
+    }
+}
diff --git a/t/t4018/swift-inline-attribute b/t/t4018/swift-inline-attribute
new file mode 100644 (file)
index 0000000..2374c4b
--- /dev/null
@@ -0,0 +1,7 @@
+class Service {
+    @objc func RIGHT() {
+        let path = "/api"
+        // a comment
+        log(ChangeMe)
+    }
+}
diff --git a/t/t4018/swift-modifiers b/t/t4018/swift-modifiers
new file mode 100644 (file)
index 0000000..9d80685
--- /dev/null
@@ -0,0 +1,4 @@
+public static func RIGHT() -> Int {
+    // a comment
+    return ChangeMe
+}
diff --git a/t/t4018/swift-protocol b/t/t4018/swift-protocol
new file mode 100644 (file)
index 0000000..07c39ec
--- /dev/null
@@ -0,0 +1,5 @@
+protocol RIGHT {
+    var first: Int { get }
+    // a comment
+    var second: ChangeMe { get }
+}
diff --git a/t/t4018/swift-struct b/t/t4018/swift-struct
new file mode 100644 (file)
index 0000000..e399ed7
--- /dev/null
@@ -0,0 +1,5 @@
+struct RIGHT {
+    let a = 1
+    // a comment
+    let b = ChangeMe
+}
index b5412e6bc3ecd390d71a31e4d884d66d2af6c910..7129bf148266b7d53cf83465f6c916b4bcaf3014 100644 (file)
@@ -362,6 +362,16 @@ PATTERNS("scheme",
         "\\|([^|\\\\]|\\\\.)*\\|"
         /* All other words should be delimited by spaces or parentheses. */
         "|([^][)(}{ \t])+"),
+PATTERNS("swift",
+        "^[ \t]*((@[A-Za-z_][A-Za-z0-9_]*(\\([^()]*\\))?[ \t]+)*([a-z]+[ \t]+)*(func|init|deinit|subscript|class|struct|enum|protocol|extension|actor)[ \t(?!<].*)$",
+        /* -- */
+        "[a-zA-Z_][a-zA-Z0-9_]*"
+        /* hexadecimal, octal, and binary literals */
+        "|0[xX][0-9a-fA-F_]+|0[oO][0-7_]+|0[bB][01_]+"
+        /* integers and floating-point numbers */
+        "|[0-9][0-9_]*([.][0-9_]+)?([eE][-+]?[0-9]+)?"
+        /* unary and binary operators */
+        "|[-+*/%<>=!&|^~?]=|&&|\\|\\||<<=?|>>=?|\\?\\?|\\.\\.[.<]|->"),
 PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
         "\\\\[a-zA-Z@]+|\\\\.|([a-zA-Z0-9]|[^\x01-\x7f])+"),
 { .name = "default", .binary = -1 },