Rudolf Gröhling
Rudolf Gröhling

Reputation: 4825

TextMate Grammar -- precedence of rules

I'm trying modify syntax highlighting for CSharp language, so I will get syntax highlighting for SQL in C# string. TextMate has support for embeded languages, so this seems possible.

I build on csharp.tmLanguage.json and I would like to be able to enable embeded SQL with special comment before string like

string query = /*SQL*/ $@"SELECT something FROM ..."

Thanks to TextMate's Language Grammars and Introduction to scopes I came up with this JSON rule

"repository": {
    "embeded-sql": {
        "contentName": "source.sql",            
        "begin": "/\\*\\s*SQL\\s*\\*/\\s*\\$?@?\"",
        "end": "\";",
        "patterns": [
            {
                "include": "source.sql"
            }
        ]
    },
    ...
}

And thanks to VSCode's Themes, Snippets and Colorizers and Running and Debugging Your Extension I was able to test, that this rule works.

But I have one problem, which I'm unable to solve.

My grammar rule works only if signifficant portion of csharp rules are disabled, If I disable all #declarations and #script-top-level, embeded SQL works:

enter image description here

Otherwise, my rule is overridden by csharp rules like

enter image description here

The problem is, that my rule works on several language elements and the csharp definition wins on targeting these elements.

On which basis are the elements tagged? How to write my rule, so it will win and tag that syntax before other language rules? Is there any algorithm for calculating weight of rules?


Solution

If you cannot hijack comment syntax in csharp, lets us work with comment in SQL. I made a rule enabled by -- SQL comment and I applied this to verbatim string. Now it works but the styles are sometimes mixed with string. Needs some additional improvements, but looks promising.

enter image description here

The rule that proves to work goes like this

    "embeded-sql": {
        "contentName": "source.sql",
        "begin": "--\\s*SQL",
        "end": "(?:\\b|^)(?=\"\\s*;)",
        "patterns": [
            {
                "include": "source.sql"
            }
        ]
    },

Now I would like to enable Intellisense and error checking in such embedded language.

Upvotes: 4

Views: 4415

Answers (1)

colinfang
colinfang

Reputation: 21727

The rules in the patterns list are matched in order.

Your rule appears like a specialisation of comment, so you can put it just before the comment.block.cs

    "comment": {
        "patterns": [
            {
                "contentName": "source.sql",
                "begin": "(/\\*\\s*SQL\\s*\\*/)\\s*\\$?@?\"",
                "beginCaptures": {
                    "1": {
                        "patterns": [
                            {
                                "include": "#comment"
                            }
                        ]
                    }
                },
                "end": "\";",
                "patterns": [
                    {
                        "include": "source.sql"
                    }
                ]
            },
            {
                "name": "comment.block.cs",
                "begin": "/\\*",
                "beginCaptures": {
                    "0": {
                        "name": "punctuation.definition.comment.cs"
                    }
                },
                "end": "\\*/",
                "endCaptures": {
                    "0": {
                        "name": "punctuation.definition.comment.cs"
                    }
                }
            },
            ...

The snapshot is done on a language my which is just a copy of c# json plus your sql embedding.

enter image description here

Upvotes: 3

Related Questions