Improved FIDL2 syntax highlighting.

Generate the fidl.tmLanguage.json from a script to make it easier to
construct comprehensive regexes.

Change-Id: Ibc53c733c60401f8104c6a3d286cffb0ad32b202
diff --git a/vscode-language-fidl/CHANGELOG.md b/vscode-language-fidl/CHANGELOG.md
index e689528..ee8c181 100644
--- a/vscode-language-fidl/CHANGELOG.md
+++ b/vscode-language-fidl/CHANGELOG.md
@@ -4,4 +4,8 @@
 
 # v0.0.3
 
- - Offer a "FIDL: Go To Source" command to jump from generated bindings to FIDL source when working in the Fuchsia tree.
\ No newline at end of file
+- Offer a "FIDL: Go To Source" command to jump from generated bindings to FIDL source when working in the Fuchsia tree.
+
+# v0.1.0
+
+- FIDL2 syntax highlighting.
\ No newline at end of file
diff --git a/vscode-language-fidl/README.md b/vscode-language-fidl/README.md
index 65adeef..d406fa3 100644
--- a/vscode-language-fidl/README.md
+++ b/vscode-language-fidl/README.md
@@ -5,4 +5,10 @@
  - a command to jump from generated bindings to FIDL source.
 
 
-[fidl]: https://fuchsia.googlesource.com/fidl
+The syntax highlighting is generated by a script called `generate-syntax.ts`. That can be run by:
+```
+npm install
+npm run-script build-syntax
+```
+
+[fidl]: https://fuchsia.googlesource.com/docs/+/master/development/languages/fidl/
diff --git a/vscode-language-fidl/generate-syntax.ts b/vscode-language-fidl/generate-syntax.ts
new file mode 100644
index 0000000..c39df55
--- /dev/null
+++ b/vscode-language-fidl/generate-syntax.ts
@@ -0,0 +1,398 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This generates a language definition file because writing it by hand is too hard.
+
+// Format of language definition JSON
+const tmSchema = 'https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json';
+type TmCaptures = { [k: string]: { name: string } };
+type TmIncludePattern = { include: string };
+type TmMatchPattern = {
+    name?: string,
+    match: string,
+    captures?: TmCaptures
+};
+type TmBlockPattern = {
+    name?: string,
+    begin: string,
+    beginCaptures?: TmCaptures,
+    end: string,
+    endCaptures?: TmCaptures,
+    patterns: TmPattern[]
+};
+type TmPattern = TmIncludePattern | TmMatchPattern | TmBlockPattern;
+type TmLanguage = {
+    '$schema': string,
+    name: string,
+    scopeName: string,
+    patterns: TmPattern[],
+    repository: {
+        [key: string]: { patterns: TmPattern[] }
+    },
+};
+
+
+class Pattern {
+    readonly re: string;
+    readonly names: string[];
+    constructor(re: string, names: string[]) {
+        this.re = re;
+        this.names = names;
+        const num_groups = new RegExp(re + '|').exec('')!.length - 1;
+        if (num_groups !== this.names.length) {
+            throw new Error(`Found ${num_groups} but expected ${this.names.length} groups in ${re}`);
+        }
+    }
+
+    toString() {
+        return this.re;
+    }
+
+    assert(s: string) {
+        const re = new RegExp(this.re);
+        const m = s.match(re);
+        if (!m) {
+            throw Error(`${JSON.stringify(s)} did not match pattern ${JSON.stringify(this.re)}`);
+        }
+        if (m[0] !== s) {
+            throw Error(`${JSON.stringify(s)} did not fully match pattern ${JSON.stringify(this.re)}, only matched ${JSON.stringify(m[0])}`);
+        }
+    }
+
+    captures(): TmCaptures {
+        const captures: { [k: string]: { name: string } } = {};
+        for (let i = 0; i < this.names.length; i++) {
+            captures[`${i + 1}`] = { name: this.names[i] };
+        }
+        return captures;
+    }
+}
+
+function include(name: string): TmIncludePattern {
+    return { include: `#${name}` };
+}
+
+function match(name: string, pat: Pattern): TmMatchPattern {
+    return {
+        name: `${name}.fidl`,
+        match: pat.re,
+        captures: pat.captures(),
+    };
+}
+
+function anonMatch(pattern: Pattern | TmPattern): TmPattern {
+    if (pattern instanceof Pattern) {
+        return {
+            match: pattern.re,
+            captures: pattern.captures(),
+        };
+    }
+    return pattern;
+}
+
+function block(args: { name: string, begin: Pattern, end: Pattern, patterns: Array<Pattern | TmPattern> }): TmBlockPattern {
+    return {
+        name: `${args.name}.fidl`,
+        begin: args.begin.re,
+        beginCaptures: args.begin.captures(),
+        end: args.end.re,
+        endCaptures: args.end.captures(),
+        patterns: args.patterns.map(anonMatch),
+    };
+}
+
+
+enum Whitespace {
+    None, Optional
+}
+
+function p(re: string, names?: string[]): Pattern {
+    return new Pattern(re, names || []);
+}
+
+
+function _join(pats: Pattern[], prefix: string, separator: string, suffix: string): Pattern {
+    const re = pats.map(p => p.toString()).join(separator);
+    const names = pats.reduce((ns, p) => [...ns, ...p.names], [] as string[]);
+    return p(prefix + re + suffix, names);
+}
+
+/**
+ * Create a new pattern consisting of adjacent input patterns.
+ * @param pats Patterns
+ */
+function seq(...pats: Pattern[]): Pattern {
+    return _join(pats, '', '', '');
+}
+
+/**
+ * Create a new pattern consisting of adjacent input patterns optionally separated by whitespace.
+ * @param pats Patterns
+ */
+function ws_seq(...pats: Pattern[]): Pattern {
+    return _join(pats, '', '\\s*', '');
+}
+
+function one_of(...pats: Pattern[]): Pattern {
+    return _join(pats, '(?:', '|', ')');
+}
+
+function one_of_words(...words: string[]) {
+    return word(one_of(...words.map(word => p(word))));
+}
+
+function optional(pat: Pattern): Pattern {
+    return p(`(?:${pat})?`, pat.names);
+}
+
+function word(word: Pattern): Pattern {
+    return p(`\\b${word}\\b`, word.names);
+}
+
+function named(pat: Pattern, name: string) {
+    return p(`(${pat.re})`, [name, ...pat.names]);
+}
+
+const NUMERIC_CONSTANT = named(p("-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b"), 'constant.numeric');
+const BOOLEAN_CONSTANT = named(one_of_words('true', 'false'), 'constant.language');
+const STRING_CONSTANT = named(p('"(?:[^\\"]|\\.)*"'), 'string.quoted.double');
+const LITERAL = one_of(NUMERIC_CONSTANT, BOOLEAN_CONSTANT, STRING_CONSTANT);
+
+const IDENTIFIER = p("@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b");
+const QUALIFIED_IDENTIFIER = p(`${IDENTIFIER}(?:\\.${IDENTIFIER})*`);
+
+const NULLABLE = p('([?])?', ['punctuation.nullable']);
+
+function nullable(pat: Pattern): Pattern {
+    return seq(pat, NULLABLE);
+}
+
+const SIZE = seq(p('[:]'), one_of(NUMERIC_CONSTANT, QUALIFIED_IDENTIFIER));
+
+function sized(pat: Pattern, size_required: boolean) {
+    let size = SIZE;
+    if (!size_required) {
+        size = optional(size);
+    }
+    return seq(pat, size);
+}
+
+function keyword(keyword: string, name: string = 'keyword.control') {
+    return word(named(p(keyword), name));
+}
+
+function separator(sep: string) {
+    return named(p(sep), 'punctuation.separator');
+}
+
+const PRIMITIVE_TYPE = p("\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b", ['storage.type.basic']);
+const HANDLE_TYPE = named(nullable(p("\\bhandle\\b(?:<(?:process|thread|vmo|event|port|log|socket|eventpair|job|vmar|fifo|timer|channel|interrupt)>)?")), 'storage.type.basic');
+const STRING_TYPE = named(nullable(sized(p(`\\bstring\\b`), false)), 'storage.type.basic');
+const REQUEST_TYPE = named(nullable(seq(keyword('request'), p('<'), named(QUALIFIED_IDENTIFIER, 'entity.type.name'), p('>'))), 'storage.type.basic');
+const BASIC_TYPE = one_of(PRIMITIVE_TYPE, HANDLE_TYPE, STRING_TYPE, REQUEST_TYPE);
+
+const EOL = p('(;)', ['punctuation.terminator']);
+const LIBRARY_NAME = named(QUALIFIED_IDENTIFIER, 'entity.name.type');
+const LOCAL_TYPE = named(IDENTIFIER, 'entity.name.type');
+const NULLABLE_CUSTOM_TYPE = named(nullable(QUALIFIED_IDENTIFIER), 'entity.name.type');
+const VARIABLE = named(IDENTIFIER, 'variable');
+
+const LOOKAHEAD_IDENTIFIER = p('(?=[a-zA-Z_@])');
+
+
+// Checks
+
+QUALIFIED_IDENTIFIER.assert('foo');
+QUALIFIED_IDENTIFIER.assert('foo_bar');
+QUALIFIED_IDENTIFIER.assert('foo.bar.baz');
+
+STRING_TYPE.assert('string');
+STRING_TYPE.assert('string?');
+STRING_TYPE.assert('string:2');
+STRING_TYPE.assert('string:strings_size');
+STRING_TYPE.assert('string:2?');
+STRING_TYPE.assert('string:strings_size?');
+
+NUMERIC_CONSTANT.assert('-42');
+
+
+
+// TODO: support attributes
+const tmLanguage: TmLanguage = {
+    '$schema': tmSchema,
+    name: "FIDL",
+    scopeName: "source.fidl",
+    patterns: [
+        include('comments'),
+
+        // Library declaration
+        match('meta.library', ws_seq(keyword('library'), LIBRARY_NAME, EOL)),
+
+        // Variations of using
+        match('meta.library', ws_seq(keyword('using'), LIBRARY_NAME, EOL)),
+        match('meta.library', ws_seq(keyword('using'), LIBRARY_NAME, keyword('as'), LOCAL_TYPE, EOL)),
+        match('meta.library', ws_seq(keyword('using'), LOCAL_TYPE, separator('='), PRIMITIVE_TYPE, EOL)),
+
+        // Const declaration
+        // TODO: allow string constants
+        match('meta.const', ws_seq(keyword('const'), PRIMITIVE_TYPE, named(IDENTIFIER, 'variable.constant'), separator('='),
+        one_of(QUALIFIED_IDENTIFIER, NUMERIC_CONSTANT, BOOLEAN_CONSTANT), EOL)),
+
+        // Interfaces
+        // TODO: inheritance
+        block({
+            name: 'meta.interface-block',
+            begin: ws_seq(keyword('interface'), LOCAL_TYPE, p('{')),
+            end: p("}"),
+            patterns: [include('method'), include('comments')],
+        }),
+
+        // Enums
+        block({
+            name: 'meta.enum-block',
+            // TODO: need to have a NUMERIC_TYPE
+            begin: ws_seq(keyword('enum'), LOCAL_TYPE, optional(ws_seq(separator(':'), PRIMITIVE_TYPE)), p('{')),
+            end: p("}"),
+            patterns: [include('enum-member'), include('comments')]
+        }),
+
+        // Struct
+        block({
+            name: 'meta.struct-block',
+            begin: ws_seq(keyword('struct'), LOCAL_TYPE, p('{')),
+            end: p("}"),
+            patterns: [include('struct-member'), include('comments')],
+        }),
+
+        // Union
+        block({
+            name: 'meta.union-block',
+            begin: ws_seq(keyword('union'), LOCAL_TYPE, p('{')),
+            end: p("}"),
+            patterns: [include('union-member'), include('comments')],
+        })
+    ],
+    repository: {
+        "comments": {
+            patterns: [
+                block({
+                    name: 'comment.block',
+                    begin: p("/\\*"),
+                    end: p("\\*/"),
+                    patterns: [],
+                }),
+                match('invalid.illegal.stray-comment-end', p("\\*/.*\\n")),
+                match('comment.line.double-slash', p('//.*\\n')),
+            ]
+        },
+        "method": {
+            patterns: [
+                block({
+                    name: 'meta.method',
+                    begin: ws_seq(NUMERIC_CONSTANT, separator(':'), named(IDENTIFIER, 'entity.name.function')),
+                    end: EOL,
+                    patterns: [
+                        include('method-arguments'),
+                        separator('->'),
+                    ],
+                }),
+                block({
+                    name: 'meta.method.event',
+                    begin: ws_seq(NUMERIC_CONSTANT, separator(':'), separator('->'), named(IDENTIFIER, 'entity.name.function'), p('[(]')),
+                    end: ws_seq(p('[)]'), EOL),
+                    patterns: [
+                        include('method-argument'),
+                    ],
+                }),]
+        },
+        "method-arguments": {
+            patterns: [
+                block({
+                    name: 'meta.method.arguments',
+                    begin: p("\\("),
+                    end: p("\\)"),
+                    patterns: [
+                        include('method-argument')
+                    ]
+                })
+            ]
+        },
+        "method-argument": {
+            patterns: [
+                block({
+                    name: "meta.method.argument",
+                    begin: LOOKAHEAD_IDENTIFIER,
+                    end: ws_seq(named(IDENTIFIER, 'variable.name'), p('(?:(?:,)|(?=\\)))')),
+                    patterns: [
+                        include('type'),
+                        named(IDENTIFIER, 'variable.parameter'),
+                    ]
+                })
+            ]
+        },
+        "enum-member": {
+            patterns: [
+                match('meta.enum.member', ws_seq(VARIABLE, separator('='), NUMERIC_CONSTANT, EOL))
+            ]
+        },
+        "struct-member": {
+            patterns: [
+                match('meta.struct.member', ws_seq(BASIC_TYPE, VARIABLE, EOL)),
+                match('meta.struct.member', ws_seq(BASIC_TYPE, VARIABLE, separator('='), LITERAL, EOL)),
+                match('meta.struct.member', ws_seq(NULLABLE_CUSTOM_TYPE, VARIABLE, EOL)),
+                block({
+                    name: 'meta.struct.member',
+                    begin: LOOKAHEAD_IDENTIFIER,
+                    end: ws_seq(VARIABLE, EOL),
+                    patterns: [include('type')]
+                }),
+            ]
+        },
+        "union-member": {
+            patterns: [
+                match('meta.union.member', ws_seq(BASIC_TYPE, VARIABLE, EOL)),
+                match('meta.union.member', ws_seq(NULLABLE_CUSTOM_TYPE, VARIABLE, EOL)),
+                block({
+                    name: 'meta.union.member',
+                    begin: LOOKAHEAD_IDENTIFIER,
+                    end: ws_seq(VARIABLE, EOL),
+                    patterns: [include('type')]
+                }),
+            ]
+        },
+        "type": {
+            patterns: [
+                include('array-type'),
+                include('vector-type'),
+                anonMatch(BASIC_TYPE),
+            ]
+        },
+        "array-type": {
+            patterns: [
+                block({
+                    name: "storage.type.array",
+                    begin: seq(keyword('array', 'storage.type.array'), p('<')),
+                    end: seq(p(">"), SIZE),
+                    patterns: [
+                        include('type')
+                    ]
+                }),
+            ]
+        },
+        "vector-type": {
+            patterns: [
+                block({
+                    name: "storage.type.vector",
+                    begin: seq(keyword('vector', 'storage.type.array'), p('<')),
+                    end: seq(p(">"), optional(SIZE), NULLABLE),
+                    patterns: [
+                        include('type'),
+                    ]
+                }),
+            ]
+        },
+    },
+};
+
+console.log(JSON.stringify(tmLanguage, null, '    '));
diff --git a/vscode-language-fidl/package.json b/vscode-language-fidl/package.json
index c5cb57b..e1c15c6 100644
--- a/vscode-language-fidl/package.json
+++ b/vscode-language-fidl/package.json
@@ -1,68 +1,69 @@
 {
-    "name": "language-fidl",
-    "displayName": "FIDL Language Support",
-    "description": "Support for FIDL files",
-    "license": "SEE LICENSE IN LICENSE",
-    "version": "0.0.3",
-    "publisher": "fuchsia-authors",
-    "engines": {
-        "vscode": "^1.10.0"
-    },
-    "categories": [
-        "Languages"
-    ],
-    "activationEvents": [
-        "onCommand:extension.goToFidlSource"
-    ],
-    "main": "./out/extension",
-    "contributes": {
-        "languages": [
-            {
-                "id": "fidl",
-                "aliases": [
-                    "FIDL",
-                    "fidl"
-                ],
-                "extensions": [
-                    ".fidl"
-                ],
-                "configuration": "./language-configuration.json"
-            }
+  "name": "language-fidl",
+  "displayName": "FIDL Language Support",
+  "description": "Support for FIDL files",
+  "license": "SEE LICENSE IN LICENSE",
+  "version": "0.0.3",
+  "publisher": "fuchsia-authors",
+  "engines": {
+    "vscode": "^1.10.0"
+  },
+  "categories": [
+    "Programming Languages"
+  ],
+  "activationEvents": [
+    "onCommand:extension.goToFidlSource"
+  ],
+  "main": "./out/extension",
+  "contributes": {
+    "languages": [
+      {
+        "id": "fidl",
+        "aliases": [
+          "FIDL",
+          "fidl"
         ],
-        "grammars": [
-            {
-                "language": "fidl",
-                "scopeName": "source.fidl",
-                "path": "./syntaxes/fidl.tmLanguage.json"
-            }
+        "extensions": [
+          ".fidl"
         ],
-        "commands": [
-            {
-                "command": "extension.goToFidlSource",
-                "title": "FIDL: Go To Source"
-            }
-        ]
-    },
-    "homepage": "https://fuchsia.googlesource.com/vscode-language-fidl",
-    "repository": {
-        "type": "git",
-        "url": "https://fuchsia.googlesource.com/vscode-language-fidl"
-    },
-    "icon": "images/fuchsia_logo_128x128.png",
-    "scripts": {
-        "vscode:prepublish": "npm run compile",
-        "compile": "tsc -p ./",
-        "watch": "tsc -watch -p ./",
-        "postinstall": "node ./node_modules/vscode/bin/install",
-        "test": "mocha --require ts-node/register ./test/*.test.ts"
-    },
-    "devDependencies": {
-        "@types/mocha": "^2.2.48",
-        "@types/node": "^7.0.43",
-        "mocha": "^5.0.1",
-        "ts-node": "^5.0.1",
-        "tslint": "^5.8.0",
-        "typescript": "^2.6.1",
-        "vscode": "^1.1.6"
-    }
-}
\ No newline at end of file
+        "configuration": "./language-configuration.json"
+      }
+    ],
+    "grammars": [
+      {
+        "language": "fidl",
+        "scopeName": "source.fidl",
+        "path": "./syntaxes/fidl.tmLanguage.json"
+      }
+    ],
+    "commands": [
+      {
+        "command": "extension.goToFidlSource",
+        "title": "FIDL: Go To Source"
+      }
+    ]
+  },
+  "homepage": "https://fuchsia.googlesource.com/vscode-language-fidl",
+  "repository": {
+    "type": "git",
+    "url": "https://fuchsia.googlesource.com/vscode-language-fidl"
+  },
+  "icon": "images/fuchsia_logo_128x128.png",
+  "scripts": {
+    "vscode:prepublish": "npm run compile",
+    "compile": "tsc -p ./",
+    "watch": "tsc -watch -p ./",
+    "postinstall": "node ./node_modules/vscode/bin/install",
+    "test": "mocha --require ts-node/register ./test/*.test.ts",
+    "build-syntax": "ts-node ./generate-syntax.ts > ./syntaxes/fidl.tmLanguage.json"
+  },
+  "devDependencies": {
+    "@types/mocha": "^2.2.48",
+    "@types/node": "^7.0.43",
+    "mocha": "^5.0.1",
+    "ts-node": "^5.0.1",
+    "tslint": "^5.8.0",
+    "typescript": "^2.6.1",
+    "vscode": "^1.1.6"
+  }
+}
diff --git a/vscode-language-fidl/syntaxes/fidl.tmLanguage.json b/vscode-language-fidl/syntaxes/fidl.tmLanguage.json
index 2ad9785..40657da 100644
--- a/vscode-language-fidl/syntaxes/fidl.tmLanguage.json
+++ b/vscode-language-fidl/syntaxes/fidl.tmLanguage.json
@@ -1,221 +1,676 @@
 {
-	"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
-	"name": "FIDL",
-	"patterns": [
-		{
-			"include": "#comments"
-		},
-		{
-			"include": "#literal"
-		},
-		{
-			"match": "\\b(import|module)\\b",
-			"name": "keyword.control.fidl"
-		},
-		{
-			"match": "\\b(default|const)\\b",
-			"name": "keyword.fidl"
-		},
-		{
-			"match": "\\b(bool|float|double|int8|int16|int32|int64|uint8|uint16|uint32|uint64|string)\\b",
-			"name": "storage.type.basic.fidl"
-		},
-		{
-			"match": "\\b(handle|array|map)\\b",
-			"name": "storage.type.compound.fidl"
-		},
-		{
-			"begin": "\\b(struct|union)\\b\\s*([_A-Za-z][_A-Za-z0-9]*)\\b",
-			"beginCaptures": {
-				"1": {
-					"name": "storage.type.fidl"
-				},
-				"2": {
-					"name": "entity.name.type.fidl"
-				}
-			},
-			"end": "(?<=\\})",
-			"name": "meta.struct-union-block.fidl",
-			"patterns": [
-				{
-					"begin": "\\{",
-					"beginCaptures": {
-						"0": {
-							"name": "punctuation.section.block.begin.fidl"
-						}
-					},
-					"end": "\\}",
-					"endCaptures": {
-						"0": {
-							"name": "punctuation.section.block.end.fidl"
-						}
-					},
-					"name": "meta.block.cpp",
-					"patterns": [
-						{
-							"include": "$base"
-						}
-					]
-				}
-			]
-		},
-		{
-			"begin": "\\b(interface)\\b\\s*([_A-Za-z][_A-Za-z0-9]*)\\b",
-			"beginCaptures": {
-				"1": {
-					"name": "storage.type.fidl"
-				},
-				"2": {
-					"name": "entity.name.type.fidl"
-				}
-			},
-			"end": "(?<=\\})",
-			"name": "meta.interface-block.fidl",
-			"patterns": [
-				{
-					"begin": "\\b([_A-Za-z][_A-Za-z0-9]*)\\b",
-					"beginCaptures": {
-						"1": {
-							"name": "entity.name.function.fidl"
-						}
-					},
-					"end": "(?<=;)",
-					"patterns": [
-						{
-							"include": "$base"
-						}
-					]
-				},
-				{
-					"include": "$base"
-				}
-			]
-		},
-		{
-			"begin": "\\b(enum)\\b\\s*([_A-Za-z][_A-Za-z0-9]*)\\b",
-			"beginCaptures": {
-				"1": {
-					"name": "storage.type.fidl"
-				},
-				"2": {
-					"name": "entity.name.type.fidl"
-				}
-			},
-			"end": "(?<=\\})",
-			"name": "meta.enum-block.fidl",
-			"patterns": [
-				{
-					"include": "$base"
-				}
-			]
-		}
-	],
-	"repository": {
-		"comments": {
-			"patterns": [
-				{
-					"begin": "/\\*",
-					"beginCaptures": {
-						"0": {
-							"name": "punctuation.definition.comment.begin.fidl"
-						}
-					},
-					"end": "\\*/",
-					"endCaptures": {
-						"0": {
-							"name": "punctuation.definition.comment.end.fidl"
-						}
-					},
-					"name": "comment.block.fidl"
-				},
-				{
-					"match": "\\*/.*\\n",
-					"name": "invalid.illegal.stray-comment-end.fidl"
-				},
-				{
-					"begin": "(^[ \\t]+)?(?=//)",
-					"beginCaptures": {
-						"1": {
-							"name": "punctuation.whitespace.comment.leading.fidl"
-						}
-					},
-					"end": "(?!\\G)",
-					"patterns": [
-						{
-							"begin": "//",
-							"beginCaptures": {
-								"0": {
-									"name": "punctuation.definition.comment.fidl"
-								}
-							},
-							"end": "\\n",
-							"name": "comment.line.double-slash",
-							"patterns": [
-								{
-									"match": "(?>\\\\\\s*\\n)",
-									"name": "punctuation.separator.continuation.fidl"
-								}
-							]
-						}
-					]
-				}
-			]
-		},
-		"literal": {
-			"patterns": [
-				{
-					"include": "#string"
-				},
-				{
-					"match": "\\b(true|false)\\b",
-					"name": "constant.bool.language.fidl"
-				},
-				{
-					"match": "\\b(float|double)(.INFINITY|.NEGATIVE_INFINITY|.NAN)\\b",
-					"name": "constant.float.language.fidl"
-				},
-				{
-					"match": "\\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)\\b",
-					"name": "constant.numeric.c"
-				}
-			]
-		},
-		"string": {
-			"patterns": [
-				{
-					"begin": "\"",
-					"beginCaptures": {
-						"0": {
-							"name": "punctuation.definition.string.begin.fidl"
-						}
-					},
-					"end": "\"",
-					"endCaptures": {
-						"0": {
-							"name": "punctuation.definition.string.end.fidl"
-						}
-					},
-					"name": "string.quoted.double.fidl",
-					"patterns": [
-						{
-							"include": "#string_escaped_char"
-						}
-					]
-				}
-			]
-		},
-		"string_escaped_char": {
-			"patterns": [
-				{
-					"match": "\\\\(\\\\|[abefnprtv'\"?]|[0-3]\\d{,2}|[4-7]\\d?|x[a-fA-F0-9]{,2}|u[a-fA-F0-9]{,4}|U[a-fA-F0-9]{,8})",
-					"name": "constant.character.escape.fidl"
-				},
-				{
-					"match": "\\\\.",
-					"name": "invalid.illegal.unknown-escape.fidl"
-				}
-			]
-		}
-	},
-	"scopeName": "source.fidl"
-}
\ No newline at end of file
+    "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
+    "name": "FIDL",
+    "scopeName": "source.fidl",
+    "patterns": [
+        {
+            "include": "#comments"
+        },
+        {
+            "name": "meta.library.fidl",
+            "match": "\\b(library)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*(;)",
+            "captures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                },
+                "3": {
+                    "name": "punctuation.terminator"
+                }
+            }
+        },
+        {
+            "name": "meta.library.fidl",
+            "match": "\\b(using)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*(;)",
+            "captures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                },
+                "3": {
+                    "name": "punctuation.terminator"
+                }
+            }
+        },
+        {
+            "name": "meta.library.fidl",
+            "match": "\\b(using)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*\\b(as)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(;)",
+            "captures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                },
+                "3": {
+                    "name": "keyword.control"
+                },
+                "4": {
+                    "name": "entity.name.type"
+                },
+                "5": {
+                    "name": "punctuation.terminator"
+                }
+            }
+        },
+        {
+            "name": "meta.library.fidl",
+            "match": "\\b(using)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(=)\\s*\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b\\s*(;)",
+            "captures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                },
+                "3": {
+                    "name": "punctuation.separator"
+                },
+                "4": {
+                    "name": "storage.type.basic"
+                },
+                "5": {
+                    "name": "punctuation.terminator"
+                }
+            }
+        },
+        {
+            "name": "meta.const.fidl",
+            "match": "\\b(const)\\b\\s*\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(=)\\s*(?:@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*|(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b))\\s*(;)",
+            "captures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "storage.type.basic"
+                },
+                "3": {
+                    "name": "variable.constant"
+                },
+                "4": {
+                    "name": "punctuation.separator"
+                },
+                "5": {
+                    "name": "constant.numeric"
+                },
+                "6": {
+                    "name": "constant.language"
+                },
+                "7": {
+                    "name": "punctuation.terminator"
+                }
+            }
+        },
+        {
+            "name": "meta.interface-block.fidl",
+            "begin": "\\b(interface)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*{",
+            "beginCaptures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                }
+            },
+            "end": "}",
+            "endCaptures": {},
+            "patterns": [
+                {
+                    "include": "#method"
+                },
+                {
+                    "include": "#comments"
+                }
+            ]
+        },
+        {
+            "name": "meta.enum-block.fidl",
+            "begin": "\\b(enum)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(?:(:)\\s*\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b)?\\s*{",
+            "beginCaptures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                },
+                "3": {
+                    "name": "punctuation.separator"
+                },
+                "4": {
+                    "name": "storage.type.basic"
+                }
+            },
+            "end": "}",
+            "endCaptures": {},
+            "patterns": [
+                {
+                    "include": "#enum-member"
+                },
+                {
+                    "include": "#comments"
+                }
+            ]
+        },
+        {
+            "name": "meta.struct-block.fidl",
+            "begin": "\\b(struct)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*{",
+            "beginCaptures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                }
+            },
+            "end": "}",
+            "endCaptures": {},
+            "patterns": [
+                {
+                    "include": "#struct-member"
+                },
+                {
+                    "include": "#comments"
+                }
+            ]
+        },
+        {
+            "name": "meta.union-block.fidl",
+            "begin": "\\b(union)\\b\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*{",
+            "beginCaptures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                }
+            },
+            "end": "}",
+            "endCaptures": {},
+            "patterns": [
+                {
+                    "include": "#union-member"
+                },
+                {
+                    "include": "#comments"
+                }
+            ]
+        }
+    ],
+    "repository": {
+        "comments": {
+            "patterns": [
+                {
+                    "name": "comment.block.fidl",
+                    "begin": "/\\*",
+                    "beginCaptures": {},
+                    "end": "\\*/",
+                    "endCaptures": {},
+                    "patterns": []
+                },
+                {
+                    "name": "invalid.illegal.stray-comment-end.fidl",
+                    "match": "\\*/.*\\n",
+                    "captures": {}
+                },
+                {
+                    "name": "comment.line.double-slash.fidl",
+                    "match": "//.*\\n",
+                    "captures": {}
+                }
+            ]
+        },
+        "method": {
+            "patterns": [
+                {
+                    "name": "meta.method.fidl",
+                    "begin": "(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:)\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)",
+                    "beginCaptures": {
+                        "1": {
+                            "name": "constant.numeric"
+                        },
+                        "2": {
+                            "name": "punctuation.separator"
+                        },
+                        "3": {
+                            "name": "entity.name.function"
+                        }
+                    },
+                    "end": "(;)",
+                    "endCaptures": {
+                        "1": {
+                            "name": "punctuation.terminator"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#method-arguments"
+                        },
+                        {
+                            "match": "(->)",
+                            "captures": {
+                                "1": {
+                                    "name": "punctuation.separator"
+                                }
+                            }
+                        }
+                    ]
+                },
+                {
+                    "name": "meta.method.event.fidl",
+                    "begin": "(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:)\\s*(->)\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*[(]",
+                    "beginCaptures": {
+                        "1": {
+                            "name": "constant.numeric"
+                        },
+                        "2": {
+                            "name": "punctuation.separator"
+                        },
+                        "3": {
+                            "name": "punctuation.separator"
+                        },
+                        "4": {
+                            "name": "entity.name.function"
+                        }
+                    },
+                    "end": "[)]\\s*(;)",
+                    "endCaptures": {
+                        "1": {
+                            "name": "punctuation.terminator"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#method-argument"
+                        }
+                    ]
+                }
+            ]
+        },
+        "method-arguments": {
+            "patterns": [
+                {
+                    "name": "meta.method.arguments.fidl",
+                    "begin": "\\(",
+                    "beginCaptures": {},
+                    "end": "\\)",
+                    "endCaptures": {},
+                    "patterns": [
+                        {
+                            "include": "#method-argument"
+                        }
+                    ]
+                }
+            ]
+        },
+        "method-argument": {
+            "patterns": [
+                {
+                    "name": "meta.method.argument.fidl",
+                    "begin": "(?=[a-zA-Z_@])",
+                    "beginCaptures": {},
+                    "end": "(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(?:(?:,)|(?=\\)))",
+                    "endCaptures": {
+                        "1": {
+                            "name": "variable.name"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#type"
+                        },
+                        {
+                            "match": "(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)",
+                            "captures": {
+                                "1": {
+                                    "name": "variable.parameter"
+                                }
+                            }
+                        }
+                    ]
+                }
+            ]
+        },
+        "enum-member": {
+            "patterns": [
+                {
+                    "name": "meta.enum.member.fidl",
+                    "match": "(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(=)\\s*(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(;)",
+                    "captures": {
+                        "1": {
+                            "name": "variable"
+                        },
+                        "2": {
+                            "name": "punctuation.separator"
+                        },
+                        "3": {
+                            "name": "constant.numeric"
+                        },
+                        "4": {
+                            "name": "punctuation.terminator"
+                        }
+                    }
+                }
+            ]
+        },
+        "struct-member": {
+            "patterns": [
+                {
+                    "name": "meta.struct.member.fidl",
+                    "match": "(?:\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b|(\\bhandle\\b(?:<(?:process|thread|vmo|event|port|log|socket|eventpair|job|vmar|fifo|timer|channel|interrupt)>)?([?])?)|(\\bstring\\b(?:[:](?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?([?])?)|(\\b(request)\\b<(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)>([?])?))\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(;)",
+                    "captures": {
+                        "1": {
+                            "name": "storage.type.basic"
+                        },
+                        "2": {
+                            "name": "storage.type.basic"
+                        },
+                        "3": {
+                            "name": "punctuation.nullable"
+                        },
+                        "4": {
+                            "name": "storage.type.basic"
+                        },
+                        "5": {
+                            "name": "constant.numeric"
+                        },
+                        "6": {
+                            "name": "punctuation.nullable"
+                        },
+                        "7": {
+                            "name": "storage.type.basic"
+                        },
+                        "8": {
+                            "name": "keyword.control"
+                        },
+                        "9": {
+                            "name": "entity.type.name"
+                        },
+                        "10": {
+                            "name": "punctuation.nullable"
+                        },
+                        "11": {
+                            "name": "variable"
+                        },
+                        "12": {
+                            "name": "punctuation.terminator"
+                        }
+                    }
+                },
+                {
+                    "name": "meta.struct.member.fidl",
+                    "match": "(?:\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b|(\\bhandle\\b(?:<(?:process|thread|vmo|event|port|log|socket|eventpair|job|vmar|fifo|timer|channel|interrupt)>)?([?])?)|(\\bstring\\b(?:[:](?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?([?])?)|(\\b(request)\\b<(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)>([?])?))\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(=)\\s*(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))\\s*(;)",
+                    "captures": {
+                        "1": {
+                            "name": "storage.type.basic"
+                        },
+                        "2": {
+                            "name": "storage.type.basic"
+                        },
+                        "3": {
+                            "name": "punctuation.nullable"
+                        },
+                        "4": {
+                            "name": "storage.type.basic"
+                        },
+                        "5": {
+                            "name": "constant.numeric"
+                        },
+                        "6": {
+                            "name": "punctuation.nullable"
+                        },
+                        "7": {
+                            "name": "storage.type.basic"
+                        },
+                        "8": {
+                            "name": "keyword.control"
+                        },
+                        "9": {
+                            "name": "entity.type.name"
+                        },
+                        "10": {
+                            "name": "punctuation.nullable"
+                        },
+                        "11": {
+                            "name": "variable"
+                        },
+                        "12": {
+                            "name": "punctuation.separator"
+                        },
+                        "13": {
+                            "name": "constant.numeric"
+                        },
+                        "14": {
+                            "name": "constant.language"
+                        },
+                        "15": {
+                            "name": "string.quoted.double"
+                        },
+                        "16": {
+                            "name": "punctuation.terminator"
+                        }
+                    }
+                },
+                {
+                    "name": "meta.struct.member.fidl",
+                    "match": "(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*([?])?)\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(;)",
+                    "captures": {
+                        "1": {
+                            "name": "entity.name.type"
+                        },
+                        "2": {
+                            "name": "punctuation.nullable"
+                        },
+                        "3": {
+                            "name": "variable"
+                        },
+                        "4": {
+                            "name": "punctuation.terminator"
+                        }
+                    }
+                },
+                {
+                    "name": "meta.struct.member.fidl",
+                    "begin": "(?=[a-zA-Z_@])",
+                    "beginCaptures": {},
+                    "end": "(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(;)",
+                    "endCaptures": {
+                        "1": {
+                            "name": "variable"
+                        },
+                        "2": {
+                            "name": "punctuation.terminator"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#type"
+                        }
+                    ]
+                }
+            ]
+        },
+        "union-member": {
+            "patterns": [
+                {
+                    "name": "meta.union.member.fidl",
+                    "match": "(?:\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b|(\\bhandle\\b(?:<(?:process|thread|vmo|event|port|log|socket|eventpair|job|vmar|fifo|timer|channel|interrupt)>)?([?])?)|(\\bstring\\b(?:[:](?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?([?])?)|(\\b(request)\\b<(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)>([?])?))\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(;)",
+                    "captures": {
+                        "1": {
+                            "name": "storage.type.basic"
+                        },
+                        "2": {
+                            "name": "storage.type.basic"
+                        },
+                        "3": {
+                            "name": "punctuation.nullable"
+                        },
+                        "4": {
+                            "name": "storage.type.basic"
+                        },
+                        "5": {
+                            "name": "constant.numeric"
+                        },
+                        "6": {
+                            "name": "punctuation.nullable"
+                        },
+                        "7": {
+                            "name": "storage.type.basic"
+                        },
+                        "8": {
+                            "name": "keyword.control"
+                        },
+                        "9": {
+                            "name": "entity.type.name"
+                        },
+                        "10": {
+                            "name": "punctuation.nullable"
+                        },
+                        "11": {
+                            "name": "variable"
+                        },
+                        "12": {
+                            "name": "punctuation.terminator"
+                        }
+                    }
+                },
+                {
+                    "name": "meta.union.member.fidl",
+                    "match": "(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*([?])?)\\s*(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(;)",
+                    "captures": {
+                        "1": {
+                            "name": "entity.name.type"
+                        },
+                        "2": {
+                            "name": "punctuation.nullable"
+                        },
+                        "3": {
+                            "name": "variable"
+                        },
+                        "4": {
+                            "name": "punctuation.terminator"
+                        }
+                    }
+                },
+                {
+                    "name": "meta.union.member.fidl",
+                    "begin": "(?=[a-zA-Z_@])",
+                    "beginCaptures": {},
+                    "end": "(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(;)",
+                    "endCaptures": {
+                        "1": {
+                            "name": "variable"
+                        },
+                        "2": {
+                            "name": "punctuation.terminator"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#type"
+                        }
+                    ]
+                }
+            ]
+        },
+        "type": {
+            "patterns": [
+                {
+                    "include": "#array-type"
+                },
+                {
+                    "include": "#vector-type"
+                },
+                {
+                    "match": "(?:\\b(bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b|(\\bhandle\\b(?:<(?:process|thread|vmo|event|port|log|socket|eventpair|job|vmar|fifo|timer|channel|interrupt)>)?([?])?)|(\\bstring\\b(?:[:](?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?([?])?)|(\\b(request)\\b<(@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)>([?])?))",
+                    "captures": {
+                        "1": {
+                            "name": "storage.type.basic"
+                        },
+                        "2": {
+                            "name": "storage.type.basic"
+                        },
+                        "3": {
+                            "name": "punctuation.nullable"
+                        },
+                        "4": {
+                            "name": "storage.type.basic"
+                        },
+                        "5": {
+                            "name": "constant.numeric"
+                        },
+                        "6": {
+                            "name": "punctuation.nullable"
+                        },
+                        "7": {
+                            "name": "storage.type.basic"
+                        },
+                        "8": {
+                            "name": "keyword.control"
+                        },
+                        "9": {
+                            "name": "entity.type.name"
+                        },
+                        "10": {
+                            "name": "punctuation.nullable"
+                        }
+                    }
+                }
+            ]
+        },
+        "array-type": {
+            "patterns": [
+                {
+                    "name": "storage.type.array.fidl",
+                    "begin": "\\b(array)\\b<",
+                    "beginCaptures": {
+                        "1": {
+                            "name": "storage.type.array"
+                        }
+                    },
+                    "end": ">[:](?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)",
+                    "endCaptures": {
+                        "1": {
+                            "name": "constant.numeric"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#type"
+                        }
+                    ]
+                }
+            ]
+        },
+        "vector-type": {
+            "patterns": [
+                {
+                    "name": "storage.type.vector.fidl",
+                    "begin": "\\b(vector)\\b<",
+                    "beginCaptures": {
+                        "1": {
+                            "name": "storage.type.array"
+                        }
+                    },
+                    "end": ">(?:[:](?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.@?\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?([?])?",
+                    "endCaptures": {
+                        "1": {
+                            "name": "constant.numeric"
+                        },
+                        "2": {
+                            "name": "punctuation.nullable"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#type"
+                        }
+                    ]
+                }
+            ]
+        }
+    }
+}