Search code examples
visual-studio-codevscode-extensionstmlanguage

How to use multiple tmLanguage files in vscode extension


I am creating a language extension in vscode for myself. Because it will associate with different file types, I plan to make different tmlanguge files for specific rules. According to this, I could extend the scopeName to achieve that.

So I created in my ./package.json files something like this:

{
    "name": "tst",
    "displayName": "Test Language",
    "description": "A test for language extension",
    "version": "0.0.1",
    "engines": {
        "vscode": "^1.34.0"
    },
    "contributes": {
        "languages": [{
            "id": "tst",
            "aliases": ["Test", "tst"],
            "extensions": [".tst",".type1",".type2"],
            "configuration": "./language-configuration.json"
        }],
        "grammars": [{
            "language": "tst",
            "scopeName": "source.tst",
            "path": "./syntaxes/tst.tmLanguage.json"
        },
        {
            "scopeName": "source.tst.type1",
            "path": "./syntaxes/type1.tmLanguage.json"
        },
        {
            "scopeName": "source.tst.type2",
            "path": "./syntaxes/type2.tmLanguage.json"
        }]
    }
}

Then I create the base rules in ./syntaxes/tst.tmLanguage.json and both .type1 and .type2 have been applied with my grammars.

{
    "name": "Test",
    "patterns": [
        {
            "match": "test",
            "name": "constant.character"
        }
    ],
    "scopeName": "source.tst"
}

Afterwards I also make ./syntaxes/type1.tmLanguage.json something like this:

{
    "name": "type1",
    "patterns": [
        {
            "match": "type1",
            "name": "constant.language"
        }
    ],  
    "scopeName": "source.tst.type1"
}

Nothing works for any rules in .type1.

enter image description here

I hope both file in the picture can recognize test and type1. I checked the vscode pre-installed cpp language extension. They also use scopeName for source.c and source.c.platform. I guess it is for the similar purpose?

Did I overlook something? Thanks for the help.


Solution

  • If you want to use these scopes from different tmLanguage files in the main grammar, you have to explicitly include them:

    {
        "name": "Test",
        "patterns": [
            {
                "match": "test",
                "name": "constant.character"
            },
            {
                "include": "source.tst.type1"
            },
            {
                "include": "source.tst.type2"
            }
        ],
        "scopeName": "source.tst"
    }
    


    Regarding the built-in cpp extension and platform.tmLanguage.json - as far as I can tell, it's not actively being used by the c and cpp grammars. There's this comment in cpp/build/update-grammars.js:

    // `source.c.platform` which is still included by other grammars
    

    So that sounds more like a backwards-compatibility measure in case any third-party grammars still use it.