emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

cc-mode help - c-basic-matchers-after


From: D Chiesa
Subject: cc-mode help - c-basic-matchers-after
Date: Sat, 24 Apr 2010 09:37:57 -0400

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







reply via email to

[Prev in Thread] Current Thread [Next in Thread]