5

Prefacing the below. A demo project illustrating this issue can be found at: https://github.com/kirksl/so60384141

I can reference an injected grammar within a native VSCode language

specifying this (package.json)

        "grammars": 
        [
            {
                "scopeName": "source.js.mylang",
                "path": "./syntaxes/mylang-js.tmLanguage.json",
                "injectTo": ["source.js"]
            }
        ]

and this (./syntaxes/mylang-js.tmLanguage.json)

{
  "scopeName": "source.js.mylang",
  "injectionSelector": "L:source",
  "patterns": [
    {
      "include": "#todo-keyword"
    }
  ],
  "repository": {
    "todo-keyword": {
      "match": "TODO",
      "name": "keyword.todo"
    }
  }
}

i'm seeing this (.js file, native JS)

enter image description here

So far so good.

However I can't seem to reference the same injected grammar within my custom language detailed below. Fenced code blocks with triple quotes should utilize it.

Updating, now, this (package.json)

        "languages": [
            {
                "id": "mylang",
                "aliases": ["Mylang", "mylang"],
                "extensions": [".mylang"],
                "configuration": "./language-configuration.json"
            }
        ],
        "grammars": 
        [
            {
                "language": "mylang",
                "scopeName": "source.mylang",
                "path": "./syntaxes/mylang.tmLanguage.json",
                "embeddedLanguages": {
                    "meta.embedded.block.javascript": "javascript"
                }
            },
            {
                "scopeName": "source.js.mylang",
                "path": "./syntaxes/mylang-js.tmLanguage.json",
                "injectTo": ["source.js"]
            }
        ]

and additionally specifying this (./syntaxes/mylang-js.tmLanguage.json)

    "fenced-expression": {
      "begin": "(^|\\G)\\s*[\"]{3}\\s*$",
      "end": "(^|\\G)\\s*[\"]{3}\\s*$",
      "contentName": "meta.embedded.block",
      "beginCaptures": {
        "0": {
          "name": "string.quoted.triple.mylang"
        }
      },
      "endCaptures": {
        "0": {
          "name": "string.quoted.triple.mylang"
        }
      },
      "patterns": [
        {
          "begin": "^(\\s*)(?=[\\S&&[^{<\\[]])",
          "while": "^(?!\\s*[\"]{3}\\s*)",
          "contentName": "meta.embedded.block.javascript",
          "patterns": [
            {
              "include": "source.js"
            }
          ]
        }
      ]
    }

i'm seeing this (.mylang file, JS highlighted, TODO not highlighted)

enter image description here

Finally just showing that some of the plumbing is there to enable the highlighting i'm looking for

if I switch "include": "source.js" to "include": "source.js.mylang"

    "fenced-expression": {
      "begin": "(^|\\G)\\s*[\"]{3}\\s*$",
      "end": "(^|\\G)\\s*[\"]{3}\\s*$",
      "contentName": "meta.embedded.block",
      "beginCaptures": {
        "0": {
          "name": "string.quoted.triple.mylang"
        }
      },
      "endCaptures": {
        "0": {
          "name": "string.quoted.triple.mylang"
        }
      },
      "patterns": [
        {
          "begin": "^(\\s*)(?=[\\S&&[^{<\\[]])",
          "while": "^(?!\\s*[\"]{3}\\s*)",
          "contentName": "meta.embedded.block.javascript",
          "patterns": [
            {
              "include": "source.js.mylang"
            }
          ]
        }
      ]
    }

i'm seeing this (.mylang file, JS not highlighted, TODO highlighted)

enter image description here

Captain Kirk
  • 350
  • 6
  • 24
  • Hm, still not sure we have everything needed to reproduce. What does `mylang.tmLanguage.json` look like? You only show `mylang-js.tmLanguage.json`. – Gama11 Feb 25 '20 at 13:01
  • @Gama11 I've posted a demo project at https://github.com/kirksl/so60384141 – Captain Kirk Feb 25 '20 at 17:51
  • Thanks for pointing out the `"patterns":[{"include": "source.js.mylang"}]` to actually make use of the syntax highlighting – Jens Jensen Dec 22 '20 at 20:57

1 Answers1

2

You need to inject mylang-js.tmLanguage.json into source.mylang as well (injectTo only applies to the top-level scope name, see explanation here):

{
    "scopeName": "source.js.mylang",
    "path": "./syntaxes/mylang-js.tmLanguage.json",
    "injectTo": ["source.js", "source.mylang"]
}

Then it appears to work as intended:

Also, you will have to adjust your injectionSelector to make sure TODO highlighting is only applied within comments in embedded JS blocks:

"injectionSelector": "L:comment.line.double-slash.js"
Gama11
  • 31,714
  • 9
  • 78
  • 100
  • i added "source.mylang" as you recommended to "injectTo" and see TODO highlighted, but i'm seeing a problem. if you remove "//" or use TODO outside of the fenced triple quotes where its not JS it's still highlighting TODO. really hoping to extend only JS code with TODO highlighting. – Captain Kirk Feb 25 '20 at 20:03
  • Using the proper `injectionSelector` seems to solve both of those issues (see my updated answer). – Gama11 Feb 25 '20 at 20:18
  • Good point. Oversight on my part. Massive thank you for helping me solve this. I owe you a beer or whatever beverage you subscribe to. Curious with this setup is "embeddedLanguages" for "javascript" in the grammar even needed at this point? Removing it makes no difference. – Captain Kirk Feb 25 '20 at 20:52
  • 1
    Good question. It seems to be necessary for editor features apart from syntax highlighting to work correctly within the embedded language, such as "toggle line comment", see also: https://github.com/microsoft/vscode/issues/34598 – Gama11 Feb 25 '20 at 21:55