Hi,
I'm working on improving the fontification of c# in csharp-mode, which
depends on cc-mode.
In most cases in cc-mode, reference to the c-lang-const symbols are done
through a variable of the same name, rather than directly through the
(c-lang-const ...) fn. The pattern for defining the variable looks like
this:
(c-lang-defconst c-brace-list-key
;; Regexp matching the start of declarations where the following
;; block is a brace list.
t (c-make-keywords-re t (c-lang-const c-brace-list-decl-kwds)))
(c-lang-defvar c-brace-list-key (c-lang-const c-brace-list-key))
And then the code in cc-mode references the value either via the variable,
or (c-lang-const ...). This is nice because it offers the chance for a
cc-mode language to set its own regex into that symbol, and that regex may
or may not be the result of a simple call to c-make-keywords-re.
But, in some cases this approach is not used faithfully. One case in
particular causes problems for fontification of C#.
In c-basic-matchers-after (defined in cc-fonts.el), the first case in that
fn deals with identifiers inside enum lists, and "hard-codes" the regex
used to recognize brace-lists . See below, the call to concat, and
specifically the comment that begins with "Disallow".
(c-lang-defconst c-basic-matchers-after
"Font lock matchers for various things that should be fontified
after
generic casts and declarations are fontified. Used on level 2 and
higher."
t `(;; Fontify the identifiers inside enum lists. (The enum type
;; name is handled by `c-simple-decl-matchers' or
;; `c-complex-decl-matchers' below.
,@(when (c-lang-const c-brace-id-list-kwds)
`((,(c-make-font-lock-search-function
(concat
"\\<\\("
(c-make-keywords-re nil (c-lang-const
c-brace-id-list-kwds))
"\\)\\>"
;; Disallow various common punctuation chars that
can't come
;; before the '{' of the enum list, to avoid searching
too far.
"[^\]\[{}();,/#=]*"
"{")
'((c-font-lock-declarators limit t nil)
(save-match-data
(goto-char (match-end 0))
(c-put-char-property (1- (point)) 'c-type
'c-decl-id-start)
(c-forward-syntactic-ws))
(goto-char (match-end 0)))))))
This works in many languages, but it does not work in C#, specifically for
the case of object initializers, which take this form:
var x = new MyType(arg1, arg2, ...) {
Field1 = "foo",
Field2 = "bar",
};
This syntax creates a new instance using the given constructor, and then
sets public fields or properties on that instance to the given values.
When I say "it does not work" what I mean is that regex in the matcher
doesn't match, and as a result the char property c-decl-id-start is not
applied to the open curly. As a result of that, the assignment statements
inside the curlies are not fontified properly.
C# 3.0 also allows this simpler syntax:
var x = new MyType {
Field1 = "foo",
Field2 = "bar",
};
...which invokes the default constructor, and then performs the
assignments. This syntax is fontified correctly. The difference is the
absence of the (), which is "disallowed" by the hard-coded regex.
The difference is shown here:
http://i40.tinypic.com/29qo0go.jpg
What I'd like to see is that regex in c-basic-matchers-after to be a pure
c-lang-const. Rather than augmenting that regex deep inside the matcher
to stipulate that () must be disallowed in that context, if that regex
could refer to an unadorned c-lang-const, then any mode dependent upon
cc-mode would be able to set the appropriate regex for the matcher, in an
appropriate c-lang-defconst .
In other words, change the code for c-basic-matchers-after to
t `(;; Fontify the identifiers inside enum lists. (The enum type
;; name is handled by `c-simple-decl-matchers' or
;; `c-complex-decl-matchers' below.
,@(when (c-lang-const c-brace-id-list-kwds)
`((,(c-make-font-lock-search-function
(c-lang-const c-brace-id-list-beginning-re)
'((c-font-lock-declarators limit t nil)
and introduce c-brace-id-list-beginning-re , as
(c-lang-defconst c-brace-id-list-beginning-re
;; Regexp matching the start of a brace list, including the opening
;; brace.
t (concat
"\\<\\("
(c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds))
"\\)\\>"
;; Disallow various common punctuation chars that can't come
;; before the '{' of the enum list, to avoid searching too far.
"[^\]\[{}();,/#=]*"
"{")
)
Have I understood this properly? Does this request make sense?
-Dino Chiesa