diff options
| author | Jostein Kjønigsen | 2025-08-27 11:05:28 +0200 |
|---|---|---|
| committer | Yuan Fu | 2025-09-16 19:07:16 -0700 |
| commit | 2135e7aa0169639083996fb2a3f82792cdd7a9c0 (patch) | |
| tree | d06eafdc2a429c7a113dc33f6e3330d33091176e | |
| parent | 32d959e48becc240a6630e294472b4b4218df807 (diff) | |
| download | emacs-2135e7aa0169639083996fb2a3f82792cdd7a9c0.tar.gz emacs-2135e7aa0169639083996fb2a3f82792cdd7a9c0.zip | |
Fixes for csharp-ts-mode fontification (bug#79406)
- hightlight reserved keywords agressively, dont allow misuse as
variables etc (the compiler will fail!)
- highlight lambda-valued variables as funtions.
- improve semantics of function/class annotations using attributes
(maps closer to using-something than declaring it). also: rename to
"attribute". "property" has a different, defined meaning in C#.
- better highlight variable-use in different scenarios (function-calls,
if-statements, assignment-expressions, property-use, anonymous object
initializers).
- better highlight for property-use (anonymous object initializers).
- highlight field-declaration using font-lock-variable-face.
- fontify attributes using new face csharp-ts-mode-attribute-face
(defaults to font-lock-property-use-face).
- remove extensive use of "override" making evalutation hard-to-reason about.
* lisp/progmodes/csharp-mode.el (csharp-ts-mode--indent-rules):
Update indent rules.
(csharp-ts-mode-faces): New group.
(csharp-ts-mode-attribute-face): New face.
(csharp-ts-mode--font-lock-settings): Rule updates.
(csharp-ts-mode): Change property feature to attribute
| -rw-r--r-- | etc/NEWS | 6 | ||||
| -rw-r--r-- | lisp/progmodes/csharp-mode.el | 89 |
2 files changed, 76 insertions, 19 deletions
| @@ -972,6 +972,12 @@ are highlighted like other comments. When non-nil, Doxygen comment | |||
| 972 | blocks are syntax-highlighted if the Doxygen grammar library is | 972 | blocks are syntax-highlighted if the Doxygen grammar library is |
| 973 | available. | 973 | available. |
| 974 | 974 | ||
| 975 | ** Csharp-ts-mode | ||
| 976 | |||
| 977 | *** Renamed feature in 'treesit-font-lock-feature-list' | ||
| 978 | The feature 'property' has been renamed to 'attribute', since this is | ||
| 979 | what it is called in the general C# community. | ||
| 980 | |||
| 975 | ** Go-ts mode | 981 | ** Go-ts mode |
| 976 | 982 | ||
| 977 | +++ | 983 | +++ |
diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 0c44fff18bf..d8b20e1f6f0 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el | |||
| @@ -673,7 +673,7 @@ compilation and evaluation time conflicts." | |||
| 673 | ((parent-is "namespace_declaration") parent-bol 0) | 673 | ((parent-is "namespace_declaration") parent-bol 0) |
| 674 | ((parent-is "class_declaration") parent-bol 0) | 674 | ((parent-is "class_declaration") parent-bol 0) |
| 675 | ((parent-is "constructor_declaration") parent-bol 0) | 675 | ((parent-is "constructor_declaration") parent-bol 0) |
| 676 | ((parent-is "array_creation_expression") parent-bol 0) ;; actual initialization is in contained initializer_expression | 676 | ((parent-is "array_creation_expression") parent-bol 0) ;; actual initialization is in contained initializer_expression. |
| 677 | ((match "{" "initializer_expression" ) parent-bol 0) | 677 | ((match "{" "initializer_expression" ) parent-bol 0) |
| 678 | ((parent-is "initializer_expression") parent-bol csharp-ts-mode-indent-offset) | 678 | ((parent-is "initializer_expression") parent-bol csharp-ts-mode-indent-offset) |
| 679 | ((match "{" "anonymous_object_creation_expression") parent-bol 0) | 679 | ((match "{" "anonymous_object_creation_expression") parent-bol 0) |
| @@ -735,6 +735,15 @@ compilation and evaluation time conflicts." | |||
| 735 | "readonly" "unmanaged") | 735 | "readonly" "unmanaged") |
| 736 | "C# keywords for tree-sitter font-locking.") | 736 | "C# keywords for tree-sitter font-locking.") |
| 737 | 737 | ||
| 738 | (defgroup csharp-ts-mode-faces nil | ||
| 739 | "Font faces." | ||
| 740 | :group 'cshap) | ||
| 741 | |||
| 742 | (defface csharp-ts-mode-attribute-face | ||
| 743 | '((t . (:inherit font-lock-property-use-face))) | ||
| 744 | "Font face used for fontification of attributes." | ||
| 745 | :group 'csharp-ts-mode-faces) | ||
| 746 | |||
| 738 | (defun csharp-ts-mode--test-this-expression () | 747 | (defun csharp-ts-mode--test-this-expression () |
| 739 | "Return non-nil if (this_expression) is named in csharp grammar." | 748 | "Return non-nil if (this_expression) is named in csharp grammar." |
| 740 | (treesit-query-valid-p 'c-sharp "(this_expression)")) | 749 | (treesit-query-valid-p 'c-sharp "(this_expression)")) |
| @@ -782,6 +791,18 @@ compilation and evaluation time conflicts." | |||
| 782 | '((conditional_expression (identifier) @font-lock-variable-use-face) | 791 | '((conditional_expression (identifier) @font-lock-variable-use-face) |
| 783 | (postfix_unary_expression (identifier)* @font-lock-variable-use-face) | 792 | (postfix_unary_expression (identifier)* @font-lock-variable-use-face) |
| 784 | (initializer_expression (assignment_expression left: (identifier) @font-lock-property-use-face)) | 793 | (initializer_expression (assignment_expression left: (identifier) @font-lock-property-use-face)) |
| 794 | (anonymous_object_creation_expression | ||
| 795 | (identifier) @font-lock-property-use-face | ||
| 796 | (identifier) @font-lock-variable-use-face) | ||
| 797 | (anonymous_object_creation_expression | ||
| 798 | (identifier) @font-lock-property-use-face | ||
| 799 | [(object_creation_expression) | ||
| 800 | (integer_literal) | ||
| 801 | (string_literal) | ||
| 802 | (binary_expression) | ||
| 803 | (invocation_expression) | ||
| 804 | (member_access_expression) | ||
| 805 | (conditional_expression)]) | ||
| 785 | (interpolated_string_expression | 806 | (interpolated_string_expression |
| 786 | (interpolation | 807 | (interpolation |
| 787 | (identifier) @font-lock-variable-use-face)) | 808 | (identifier) @font-lock-variable-use-face)) |
| @@ -823,7 +844,24 @@ compilation and evaluation time conflicts." | |||
| 823 | (:match "^[a-z][A-Za-z0-9]+" @font-lock-variable-use-face)) | 844 | (:match "^[a-z][A-Za-z0-9]+" @font-lock-variable-use-face)) |
| 824 | ((binary_expression | 845 | ((binary_expression |
| 825 | right: (identifier) @font-lock-variable-use-face) | 846 | right: (identifier) @font-lock-variable-use-face) |
| 826 | (:match "^[a-z][A-Za-z0-9]+" @font-lock-variable-use-face))) | 847 | (:match "^[a-z][A-Za-z0-9]+" @font-lock-variable-use-face)) |
| 848 | (assignment_expression | ||
| 849 | right: (identifier) @font-lock-variable-use-face) | ||
| 850 | (expression_statement ;; capture parent node to NOT shadow variable_declaration. | ||
| 851 | (assignment_expression | ||
| 852 | left: (identifier) @font-lock-variable-use-face)) | ||
| 853 | (if_statement condition: (identifier) @font-lock-variable-use-face) | ||
| 854 | |||
| 855 | ;; handle more specific matchers before generalized variable-use fallback. | ||
| 856 | (invocation_expression | ||
| 857 | function: (member_access_expression | ||
| 858 | name: (identifier) @font-lock-function-call-face)) | ||
| 859 | (invocation_expression | ||
| 860 | function: (member_access_expression | ||
| 861 | name: (generic_name (identifier) @font-lock-function-call-face))) | ||
| 862 | (member_access_expression | ||
| 863 | expression: (identifier) @font-lock-variable-use-face | ||
| 864 | name: (identifier) @font-lock-property-use-face)) | ||
| 827 | 865 | ||
| 828 | :language 'c-sharp | 866 | :language 'c-sharp |
| 829 | :feature 'bracket | 867 | :feature 'bracket |
| @@ -849,13 +887,19 @@ compilation and evaluation time conflicts." | |||
| 849 | (modifier) @font-lock-keyword-face | 887 | (modifier) @font-lock-keyword-face |
| 850 | ,@(if (csharp-ts-mode--test-this-expression) | 888 | ,@(if (csharp-ts-mode--test-this-expression) |
| 851 | '((this_expression) @font-lock-keyword-face) | 889 | '((this_expression) @font-lock-keyword-face) |
| 852 | '("this" @font-lock-keyword-face))) | 890 | '("this" @font-lock-keyword-face)) |
| 891 | |||
| 892 | ;; avoid fontifying indentifiers with a keyword-values as identifiers. | ||
| 893 | ((identifier) @font-lock-keyword-face | ||
| 894 | (:match ,(concat "\\`" (regexp-opt csharp-ts-mode--keywords t) "\\'") @font-lock-keyword-face))) | ||
| 853 | 895 | ||
| 854 | :language 'c-sharp | 896 | :language 'c-sharp |
| 855 | :override t | 897 | :override t |
| 856 | :feature 'property | 898 | :feature 'attribute |
| 857 | `((attribute (identifier) @font-lock-property-use-face (attribute_argument_list)) | 899 | `((attribute_list |
| 858 | (attribute (identifier) @font-lock-property-use-face)) | 900 | "[" @csharp-ts-mode-attribute-face |
| 901 | (attribute name: (identifier) @csharp-ts-mode-attribute-face) | ||
| 902 | "]" @csharp-ts-mode-attribute-face)) | ||
| 859 | 903 | ||
| 860 | :language 'c-sharp | 904 | :language 'c-sharp |
| 861 | :override t | 905 | :override t |
| @@ -890,7 +934,6 @@ compilation and evaluation time conflicts." | |||
| 890 | @font-lock-string-face) | 934 | @font-lock-string-face) |
| 891 | 935 | ||
| 892 | :language 'c-sharp | 936 | :language 'c-sharp |
| 893 | :override t | ||
| 894 | :feature 'type | 937 | :feature 'type |
| 895 | `((predefined_type) @font-lock-type-face | 938 | `((predefined_type) @font-lock-type-face |
| 896 | (implicit_type) @font-lock-type-face | 939 | (implicit_type) @font-lock-type-face |
| @@ -935,7 +978,6 @@ compilation and evaluation time conflicts." | |||
| 935 | 978 | ||
| 936 | :language 'c-sharp | 979 | :language 'c-sharp |
| 937 | :feature 'definition | 980 | :feature 'definition |
| 938 | :override t | ||
| 939 | `((qualified_name (identifier) @font-lock-type-face) | 981 | `((qualified_name (identifier) @font-lock-type-face) |
| 940 | (using_directive (identifier) @font-lock-type-face) | 982 | (using_directive (identifier) @font-lock-type-face) |
| 941 | ,@(when (csharp-ts-mode--test-name-equals) | 983 | ,@(when (csharp-ts-mode--test-name-equals) |
| @@ -944,6 +986,8 @@ compilation and evaluation time conflicts." | |||
| 944 | 986 | ||
| 945 | (enum_declaration (identifier) @font-lock-type-face) | 987 | (enum_declaration (identifier) @font-lock-type-face) |
| 946 | (enum_member_declaration (identifier) @font-lock-variable-name-face) | 988 | (enum_member_declaration (identifier) @font-lock-variable-name-face) |
| 989 | (field_declaration (variable_declaration (variable_declarator | ||
| 990 | name: (identifier) @font-lock-variable-name-face))) | ||
| 947 | 991 | ||
| 948 | (interface_declaration (identifier) @font-lock-type-face) | 992 | (interface_declaration (identifier) @font-lock-type-face) |
| 949 | 993 | ||
| @@ -974,6 +1018,18 @@ compilation and evaluation time conflicts." | |||
| 974 | (method_declaration ,csharp-ts-mode--type-field (generic_name (identifier) @font-lock-type-face)) | 1018 | (method_declaration ,csharp-ts-mode--type-field (generic_name (identifier) @font-lock-type-face)) |
| 975 | (method_declaration name: (_) @font-lock-function-name-face) | 1019 | (method_declaration name: (_) @font-lock-function-name-face) |
| 976 | 1020 | ||
| 1021 | ;; only fontify known expression-types, to avoid the need to use :override | ||
| 1022 | ;; for lambda-expressions in 'function below. | ||
| 1023 | (variable_declarator | ||
| 1024 | name: (identifier) @font-lock-variable-name-face | ||
| 1025 | [(object_creation_expression) | ||
| 1026 | (integer_literal) | ||
| 1027 | (string_literal) | ||
| 1028 | (binary_expression) | ||
| 1029 | (invocation_expression) | ||
| 1030 | (member_access_expression) | ||
| 1031 | (conditional_expression)]) | ||
| 1032 | |||
| 977 | (catch_declaration | 1033 | (catch_declaration |
| 978 | ((identifier) @font-lock-type-face)) | 1034 | ((identifier) @font-lock-type-face)) |
| 979 | (catch_declaration | 1035 | (catch_declaration |
| @@ -984,7 +1040,6 @@ compilation and evaluation time conflicts." | |||
| 984 | (variable_declaration (qualified_name | 1040 | (variable_declaration (qualified_name |
| 985 | name: (generic_name (identifier) @font-lock-type-face))) | 1041 | name: (generic_name (identifier) @font-lock-type-face))) |
| 986 | (variable_declaration (generic_name (identifier) @font-lock-type-face)) | 1042 | (variable_declaration (generic_name (identifier) @font-lock-type-face)) |
| 987 | (variable_declarator (identifier) @font-lock-variable-name-face) | ||
| 988 | 1043 | ||
| 989 | (parameter type: (identifier) @font-lock-type-face) | 1044 | (parameter type: (identifier) @font-lock-type-face) |
| 990 | (parameter type: (generic_name (identifier) @font-lock-type-face)) | 1045 | (parameter type: (generic_name (identifier) @font-lock-type-face)) |
| @@ -1001,14 +1056,6 @@ compilation and evaluation time conflicts." | |||
| 1001 | :feature 'function | 1056 | :feature 'function |
| 1002 | '((invocation_expression | 1057 | '((invocation_expression |
| 1003 | function: (identifier) @font-lock-function-call-face) | 1058 | function: (identifier) @font-lock-function-call-face) |
| 1004 | (invocation_expression | ||
| 1005 | function: (member_access_expression | ||
| 1006 | name: (identifier) @font-lock-function-call-face)) | ||
| 1007 | (invocation_expression | ||
| 1008 | function: (member_access_expression | ||
| 1009 | name: (generic_name (identifier) @font-lock-function-call-face))) | ||
| 1010 | (invocation_expression | ||
| 1011 | function: (generic_name (identifier) @font-lock-function-call-face)) | ||
| 1012 | ((invocation_expression | 1059 | ((invocation_expression |
| 1013 | function: (member_access_expression | 1060 | function: (member_access_expression |
| 1014 | expression: (identifier) @font-lock-variable-use-face)) | 1061 | expression: (identifier) @font-lock-variable-use-face)) |
| @@ -1018,7 +1065,11 @@ compilation and evaluation time conflicts." | |||
| 1018 | expression: (identifier) @font-lock-variable-use-face)) | 1065 | expression: (identifier) @font-lock-variable-use-face)) |
| 1019 | (:match "^[a-z][A-Za-z0-9]+" @font-lock-variable-use-face)) | 1066 | (:match "^[a-z][A-Za-z0-9]+" @font-lock-variable-use-face)) |
| 1020 | (argument (member_access_expression | 1067 | (argument (member_access_expression |
| 1021 | name: (identifier) @font-lock-property-use-face))) | 1068 | name: (identifier) @font-lock-property-use-face)) |
| 1069 | ;; only highlight as function if variable contains lambda expression | ||
| 1070 | (variable_declarator | ||
| 1071 | name: (identifier) @font-lock-function-name-face | ||
| 1072 | (lambda_expression))) | ||
| 1022 | 1073 | ||
| 1023 | :language 'c-sharp | 1074 | :language 'c-sharp |
| 1024 | :feature 'escape-sequence | 1075 | :feature 'escape-sequence |
| @@ -1198,7 +1249,7 @@ Key bindings: | |||
| 1198 | (setq-local treesit-font-lock-feature-list | 1249 | (setq-local treesit-font-lock-feature-list |
| 1199 | '(( comment definition) | 1250 | '(( comment definition) |
| 1200 | ( keyword string type directives) | 1251 | ( keyword string type directives) |
| 1201 | ( constant escape-sequence expression literal property) | 1252 | ( constant escape-sequence expression literal attribute) |
| 1202 | ( function bracket delimiter error))) | 1253 | ( function bracket delimiter error))) |
| 1203 | 1254 | ||
| 1204 | ;; Imenu. | 1255 | ;; Imenu. |