aboutsummaryrefslogtreecommitdiff
path: root/userdiff.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2024-04-16 14:50:28 -0700
committerJunio C Hamano <gitster@pobox.com>2024-04-16 14:50:28 -0700
commit2d642afb0a469c0c344f23bc715ea70b6a2dcade (patch)
treeb3ed8a6b6609bc9b9366026336aa803036f7018c /userdiff.c
parent625ef1c6f16a3e58a26f695ee314adbcd97b8c7b (diff)
parentec0e3075d245afa3f3a848bd7bdc6376dea85fe0 (diff)
downloadgit-2d642afb0a469c0c344f23bc715ea70b6a2dcade.tar.xz
Merge branch 'sj/userdiff-c-sharp'
The userdiff patterns for C# has been updated. Acked-by: Johannes Sixt <j6t@kdbg.org> cf. <c2154457-3f2f-496e-9b8b-c8ea7257027b@kdbg.org> * sj/userdiff-c-sharp: userdiff: better method/property matching for C#
Diffstat (limited to 'userdiff.c')
-rw-r--r--userdiff.c48
1 files changed, 42 insertions, 6 deletions
diff --git a/userdiff.c b/userdiff.c
index 92ef649c99..82bc76b910 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -90,12 +90,48 @@ PATTERNS("cpp",
"|\\.[0-9][0-9]*([Ee][-+]?[0-9]+)?[fFlL]?"
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->\\*?|\\.\\*|<=>"),
PATTERNS("csharp",
- /* Keywords */
- "!^[ \t]*(do|while|for|if|else|instanceof|new|return|switch|case|throw|catch|using)\n"
- /* Methods and constructors */
- "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe|async)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[<>@._[:alnum:]]+[ \t]*\\(.*\\))[ \t]*$\n"
- /* Properties */
- "^[ \t]*(((static|public|internal|private|protected|new|virtual|sealed|override|unsafe)[ \t]+)*[][<>@.~_[:alnum:]]+[ \t]+[@._[:alnum:]]+)[ \t]*$\n"
+ /*
+ * Jump over reserved keywords which are illegal method names, but which
+ * can be followed by parentheses without special characters in between,
+ * making them look like methods.
+ */
+ "!(^|[ \t]+)" /* Start of line or whitespace. */
+ "(do|while|for|foreach|if|else|new|default|return|switch|case|throw"
+ "|catch|using|lock|fixed)"
+ "([ \t(]+|$)\n" /* Whitespace, "(", or end of line. */
+ /*
+ * Methods/constructors:
+ * The strategy is to identify a minimum of two groups (any combination
+ * of keywords/type/name) before the opening parenthesis, and without
+ * final unexpected characters, normally only used in ordinary statements.
+ */
+ "^[ \t]*" /* Remove leading whitespace. */
+ "(" /* Start chunk header capture. */
+ "(" /* First group. */
+ "[][[:alnum:]@_.]" /* Name. */
+ "(<[][[:alnum:]@_, \t<>]+>)?" /* Optional generic parameters. */
+ ")+"
+ "([ \t]+" /* Subsequent groups, prepended with space. */
+ "([][[:alnum:]@_.](<[][[:alnum:]@_, \t<>]+>)?)+"
+ ")+"
+ "[ \t]*" /* Optional space before parameters start. */
+ "\\(" /* Start of method parameters. */
+ "[^;]*" /* Allow complex parameters, but exclude statements (;). */
+ ")$\n" /* Close chunk header capture. */
+ /*
+ * Properties:
+ * As with methods, expect a minimum of two groups. But, more trivial than
+ * methods, the vast majority of properties long enough to be worth
+ * showing a chunk header for don't include "=:;,()" on the line they are
+ * defined, since they don't have a parameter list.
+ */
+ "^[ \t]*("
+ "([][[:alnum:]@_.](<[][[:alnum:]@_, \t<>]+>)?)+"
+ "([ \t]+"
+ "([][[:alnum:]@_.](<[][[:alnum:]@_, \t<>]+>)?)+"
+ ")+" /* Up to here, same as methods regex. */
+ "[^;=:,()]*" /* Compared to methods, no parameter list allowed. */
+ ")$\n"
/* Type definitions */
"^[ \t]*(((static|public|internal|private|protected|new|unsafe|sealed|abstract|partial)[ \t]+)*(class|enum|interface|struct|record)[ \t]+.*)$\n"
/* Namespace */