{ startIndex: 5, type: 'keyword.other.js' }

/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { testTokenization } from '../test/testRunner';

testTokenization('typescript', [
	// Keywords
	[
		{
			line: 'var x = function() { };',
			tokens: [
				{ startIndex: 0, type: 'keyword.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'keyword.ts' },
				{ startIndex: 16, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 18, type: '' },
				{ startIndex: 19, type: 'delimiter.bracket.ts' },
				{ startIndex: 20, type: '' },
				{ startIndex: 21, type: 'delimiter.bracket.ts' },
				{ startIndex: 22, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: '    var    ',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 4, type: 'keyword.ts' },
				{ startIndex: 7, type: '' }
			]
		}
	],

	// Comments - single line
	[
		{
			line: '//',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: '    // a comment',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 4, type: 'comment.ts' }
			]
		}
	],

	[
		{
			line: '// a comment',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: '// a comment /*',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: '// a comment /**',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: '//sticky comment',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: 'var x = 1; // my comment // is a nice one',
			tokens: [
				{ startIndex: 0, type: 'keyword.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'number.ts' },
				{ startIndex: 9, type: 'delimiter.ts' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'comment.ts' }
			]
		}
	],

	// Comments - range comment, single line
	[
		{
			line: '/* a simple comment */',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: 'var x = /* a simple comment */ 1;',
			tokens: [
				{ startIndex: 0, type: 'keyword.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'comment.ts' },
				{ startIndex: 30, type: '' },
				{ startIndex: 31, type: 'number.ts' },
				{ startIndex: 32, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: 'x = /**/;',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'comment.ts' },
				{ startIndex: 8, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: 'x = /*/;',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'comment.ts' }
			]
		}
	],

	// Comments - range comment, multi lines
	[
		{
			line: '/* a multiline comment',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		},
		{
			line: 'can actually span',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		},
		{
			line: 'multiple lines */',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: 'var x = /* start a comment',
			tokens: [
				{ startIndex: 0, type: 'keyword.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'comment.ts' }
			]
		},
		{
			line: ' a ',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		},
		{
			line: 'and end it */ var a = 2;',
			tokens: [
				{ startIndex: 0, type: 'comment.ts' },
				{ startIndex: 13, type: '' },
				{ startIndex: 14, type: 'keyword.ts' },
				{ startIndex: 17, type: '' },
				{ startIndex: 18, type: 'identifier.ts' },
				{ startIndex: 19, type: '' },
				{ startIndex: 20, type: 'delimiter.ts' },
				{ startIndex: 21, type: '' },
				{ startIndex: 22, type: 'number.ts' },
				{ startIndex: 23, type: 'delimiter.ts' }
			]
		}
	],

	// Strings
	[
		{
			line: "var a = 'a';",
			tokens: [
				{ startIndex: 0, type: 'keyword.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'string.ts' },
				{ startIndex: 11, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: '"use strict";',
			tokens: [
				{ startIndex: 0, type: 'string.ts' },
				{ startIndex: 12, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: 'b = a + " \'cool\'  "',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'string.ts' }
			]
		}
	],

	[
		{
			line: '"escaping \\"quotes\\" is cool"',
			tokens: [
				{ startIndex: 0, type: 'string.ts' },
				{ startIndex: 10, type: 'string.escape.ts' },
				{ startIndex: 12, type: 'string.ts' },
				{ startIndex: 18, type: 'string.escape.ts' },
				{ startIndex: 20, type: 'string.ts' }
			]
		}
	],

	[
		{
			line: "'''",
			tokens: [
				{ startIndex: 0, type: 'string.ts' },
				{ startIndex: 2, type: 'string.invalid.ts' }
			]
		}
	],

	[
		{
			line: "'\\''",
			tokens: [
				{ startIndex: 0, type: 'string.ts' },
				{ startIndex: 1, type: 'string.escape.ts' },
				{ startIndex: 3, type: 'string.ts' }
			]
		}
	],

	[
		{
			line: "'be careful \\not to escape'",
			tokens: [
				{ startIndex: 0, type: 'string.ts' },
				{ startIndex: 12, type: 'string.escape.ts' },
				{ startIndex: 14, type: 'string.ts' }
			]
		}
	],

	// Numbers
	[
		{
			line: '0',
			tokens: [{ startIndex: 0, type: 'number.ts' }]
		}
	],

	[
		{
			line: ' 0',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: ' 0 ',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.ts' },
				{ startIndex: 2, type: '' }
			]
		}
	],

	[
		{
			line: '0 ',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: '' }
			]
		}
	],

	[
		{
			line: '0+0',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: 'delimiter.ts' },
				{ startIndex: 2, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: '100+10',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 3, type: 'delimiter.ts' },
				{ startIndex: 4, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: '0 + 0',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: '0123',
			tokens: [{ startIndex: 0, type: 'number.octal.ts' }]
		}
	],

	[
		{
			line: '01239',
			tokens: [
				{ startIndex: 0, type: 'number.octal.ts' },
				{ startIndex: 4, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: '0o123',
			tokens: [{ startIndex: 0, type: 'number.octal.ts' }]
		}
	],

	[
		{
			line: '0O123',
			tokens: [{ startIndex: 0, type: 'number.octal.ts' }]
		}
	],

	[
		{
			line: '0x',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: 'identifier.ts' }
			]
		}
	],

	[
		{
			line: '0x123',
			tokens: [{ startIndex: 0, type: 'number.hex.ts' }]
		}
	],

	[
		{
			line: '0X123',
			tokens: [{ startIndex: 0, type: 'number.hex.ts' }]
		}
	],

	[
		{
			line: '0b101',
			tokens: [{ startIndex: 0, type: 'number.binary.ts' }]
		}
	],

	[
		{
			line: '0B101',
			tokens: [{ startIndex: 0, type: 'number.binary.ts' }]
		}
	],

	// Bigint
	[
		{
			line: '0n',
			tokens: [{ startIndex: 0, type: 'number.ts' }]
		}
	],

	[
		{
			line: ' 0n',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: ' 0n ',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.ts' },
				{ startIndex: 3, type: '' }
			]
		}
	],

	[
		{
			line: '0n ',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 2, type: '' }
			]
		}
	],

	[
		{
			line: '0n+0n',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: '100n+10n',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 4, type: 'delimiter.ts' },
				{ startIndex: 5, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: '0n + 0n',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 2, type: '' },
				{ startIndex: 3, type: 'delimiter.ts' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: '0b101n',
			tokens: [{ startIndex: 0, type: 'number.binary.ts' }]
		}
	],

	[
		{
			line: '0123n',
			tokens: [{ startIndex: 0, type: 'number.octal.ts' }]
		}
	],

	[
		{
			line: '0o123n',
			tokens: [{ startIndex: 0, type: 'number.octal.ts' }]
		}
	],

	[
		{
			line: '0x123n',
			tokens: [{ startIndex: 0, type: 'number.hex.ts' }]
		}
	],

	// Regular Expressions
	[
		{
			line: '//',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: '/**/',
			tokens: [{ startIndex: 0, type: 'comment.ts' }]
		}
	],

	[
		{
			line: '/***/',
			tokens: [{ startIndex: 0, type: 'comment.doc.ts' }]
		}
	],

	[
		{
			line: '5 / 3;',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.ts' },
				{ startIndex: 5, type: 'delimiter.ts' }
			]
		}
	],

	// Advanced regular expressions
	[
		{
			line: '1 / 2; /* comment',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.ts' },
				{ startIndex: 5, type: 'delimiter.ts' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'comment.ts' }
			]
		}
	],

	[
		{
			line: '1 / 2 / x / b;',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'identifier.ts' },
				{ startIndex: 9, type: '' },
				{ startIndex: 10, type: 'delimiter.ts' },
				{ startIndex: 11, type: '' },
				{ startIndex: 12, type: 'identifier.ts' },
				{ startIndex: 13, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: "x = /foo/.test('')",
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'regexp.ts' },
				{ startIndex: 9, type: 'delimiter.ts' },
				{ startIndex: 10, type: 'identifier.ts' },
				{ startIndex: 14, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 15, type: 'string.ts' },
				{ startIndex: 17, type: 'delimiter.parenthesis.ts' }
			]
		}
	],

	[
		{
			line: "var x = !/`/.test('a');",
			tokens: [
				{ startIndex: 0, type: 'keyword.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'delimiter.ts' },
				{ startIndex: 9, type: 'regexp.ts' },
				{ startIndex: 12, type: 'delimiter.ts' },
				{ startIndex: 13, type: 'identifier.ts' },
				{ startIndex: 17, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 18, type: 'string.ts' },
				{ startIndex: 21, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 22, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: '/foo/',
			tokens: [{ startIndex: 0, type: 'regexp.ts' }]
		}
	],

	[
		{
			line: '/foo/g',
			tokens: [
				{ startIndex: 0, type: 'regexp.ts' },
				{ startIndex: 5, type: 'keyword.other.ts' }
			]
		}
	],

	[
		{
			line: '/foo/gimsuy',
			tokens: [
				{ startIndex: 0, type: 'regexp.ts' },
				{ startIndex: 5, type: 'keyword.other.ts' }
			]
		}
	],

	[
		{
			line: '/foo/q', // invalid flag
			tokens: [
				{ startIndex: 0, type: 'delimiter.ts' },
				{ startIndex: 1, type: 'identifier.ts' },
				{ startIndex: 4, type: 'delimiter.ts' },
				{ startIndex: 5, type: 'identifier.ts' }
			]
		}
	],

	[
		{
			line: 'x = 1 + f(2 / 3, /foo/)',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'identifier.ts' },
				{ startIndex: 9, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 10, type: 'number.ts' },
				{ startIndex: 11, type: '' },
				{ startIndex: 12, type: 'delimiter.ts' },
				{ startIndex: 13, type: '' },
				{ startIndex: 14, type: 'number.ts' },
				{ startIndex: 15, type: 'delimiter.ts' },
				{ startIndex: 16, type: '' },
				{ startIndex: 17, type: 'regexp.ts' },
				{ startIndex: 22, type: 'delimiter.parenthesis.ts' }
			]
		}
	],

	[
		{
			line: 'a /ads/ b;',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: 'identifier.ts' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'identifier.ts' },
				{ startIndex: 9, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: '1/(2/3)/2/3;',
			tokens: [
				{ startIndex: 0, type: 'number.ts' },
				{ startIndex: 1, type: 'delimiter.ts' },
				{ startIndex: 2, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 3, type: 'number.ts' },
				{ startIndex: 4, type: 'delimiter.ts' },
				{ startIndex: 5, type: 'number.ts' },
				{ startIndex: 6, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 7, type: 'delimiter.ts' },
				{ startIndex: 8, type: 'number.ts' },
				{ startIndex: 9, type: 'delimiter.ts' },
				{ startIndex: 10, type: 'number.ts' },
				{ startIndex: 11, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: '{ key: 123 }',
			tokens: [
				{ startIndex: 0, type: 'delimiter.bracket.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'identifier.ts' },
				{ startIndex: 5, type: 'delimiter.ts' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'number.ts' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'delimiter.bracket.ts' }
			]
		}
	],

	[
		{
			line: '[1,2,3]',
			tokens: [
				{ startIndex: 0, type: 'delimiter.square.ts' },
				{ startIndex: 1, type: 'number.ts' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: 'number.ts' },
				{ startIndex: 4, type: 'delimiter.ts' },
				{ startIndex: 5, type: 'number.ts' },
				{ startIndex: 6, type: 'delimiter.square.ts' }
			]
		}
	],

	[
		{
			line: 'foo(123);',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 3, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 4, type: 'number.ts' },
				{ startIndex: 7, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 8, type: 'delimiter.ts' }
			]
		}
	],

	[
		{
			line: '{a:{b:[]}}',
			tokens: [
				{ startIndex: 0, type: 'delimiter.bracket.ts' },
				{ startIndex: 1, type: 'identifier.ts' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: 'delimiter.bracket.ts' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: 'delimiter.ts' },
				{ startIndex: 6, type: 'delimiter.square.ts' },
				{ startIndex: 8, type: 'delimiter.bracket.ts' }
			]
		}
	],

	[
		{
			line: 'x = "[{()}]"',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'string.ts' }
			]
		}
	],

	[
		{
			line: 'test ? 1 : 2',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.ts' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'number.ts' },
				{ startIndex: 8, type: '' },
				{ startIndex: 9, type: 'delimiter.ts' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: 'couldBeNullish ?? 1',
			tokens: [
				{ startIndex: 0, type: 'identifier.ts' },
				{ startIndex: 14, type: '' },
				{ startIndex: 15, type: 'delimiter.ts' },
				{ startIndex: 17, type: '' },
				{ startIndex: 18, type: 'number.ts' }
			]
		}
	],

	[
		{
			line: "`${5 + 'x' + (<any>)3}a${4}`",
			tokens: [
				{ startIndex: 0, type: 'string.ts' },
				{ startIndex: 1, type: 'delimiter.bracket.ts' },
				{ startIndex: 3, type: 'number.ts' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.ts' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'string.ts' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'delimiter.ts' },
				{ startIndex: 12, type: '' },
				{ startIndex: 13, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 14, type: 'delimiter.angle.ts' },
				{ startIndex: 15, type: 'keyword.ts' },
				{ startIndex: 18, type: 'delimiter.angle.ts' },
				{ startIndex: 19, type: 'delimiter.parenthesis.ts' },
				{ startIndex: 20, type: 'number.ts' },
				{ startIndex: 21, type: 'delimiter.bracket.ts' },
				{ startIndex: 22, type: 'string.ts' },
				{ startIndex: 23, type: 'delimiter.bracket.ts' },
				{ startIndex: 25, type: 'number.ts' },
				{ startIndex: 26, type: 'delimiter.bracket.ts' },
				{ startIndex: 27, type: 'string.ts' }
			]
		}
	],

	[
		{
			line: 'let x = 2 / 2; //asd',
			tokens: [
				{ startIndex: 0, type: 'keyword.ts' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.ts' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.ts' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'number.ts' },
				{ startIndex: 9, type: '' },
				{ startIndex: 10, type: 'delimiter.ts' },
				{ startIndex: 11, type: '' },
				{ startIndex: 12, type: 'number.ts' },
				{ startIndex: 13, type: 'delimiter.ts' },
				{ startIndex: 14, type: '' },
				{ startIndex: 15, type: 'comment.ts' }
			]
		}
	]
]);


keep keep keep keep keep replace keep keep keep

/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { registerLanguage } from '../_.contribution';

registerLanguage({
	id: 'xml',
	extensions: [
		'.xml',
		'.dtd',
		'.ascx',
		'.csproj',
		'.config',
		'.wxi',
		'.wxl',
		'.wxs',
		'.xaml',
		'.svg',
		'.svgz',
		'.opf',
		'.xsl'
	],
	firstLine: '(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)',
	aliases: ['XML', 'xml'],
	mimetypes: ['text/xml', 'application/xml', 'application/xaml+xml', 'application/xml-dtd'],
	loader: () => import('./xml')
});


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import type { languages } from '../fillers/monaco-editor-core';

export const conf: languages.LanguageConfiguration = {
	comments: {
		blockComment: ['<!--', '-->']
	},
	brackets: [
		['{', '}'],
		['[', ']'],
		['(', ')']
	],
	autoClosingPairs: [
		{ open: '{', close: '}' },
		{ open: '[', close: ']' },
		{ open: '(', close: ')' },
		{ open: '<', close: '>', notIn: ['string'] }
	],
	surroundingPairs: [
		{ open: '(', close: ')' },
		{ open: '[', close: ']' },
		{ open: '`', close: '`' }
	],
	folding: {
		markers: {
			start: new RegExp('^\\s*<!--\\s*#?region\\b.*-->'),
			end: new RegExp('^\\s*<!--\\s*#?endregion\\b.*-->')
		}
	}
};

export const language = <languages.IMonarchLanguage>{
	defaultToken: '',
	tokenPostfix: '.md',

	// escape codes
	control: /[\\`*_\[\]{}()#+\-\.!]/,
	noncontrol: /[^\\`*_\[\]{}()#+\-\.!]/,
	escapes: /\\(?:@control)/,

	// escape codes for javascript/CSS strings
	jsescapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,

	// non matched elements
	empty: [
		'area',
		'base',
		'basefont',
		'br',
		'col',
		'frame',
		'hr',
		'img',
		'input',
		'isindex',
		'link',
		'meta',
		'param'
	],

	tokenizer: {
		root: [
			// markdown tables
			[/^\s*\|/, '@rematch', '@table_header'],

			// headers (with #)
			[
				/^(\s{0,3})(#+)((?:[^\\#]|@escapes)+)((?:#+)?)/,
				['white', 'keyword', 'keyword', 'keyword']
			],

			// headers (with =)
			[/^\s*(=+|\-+)\s*$/, 'keyword'],

			// headers (with ***)
			[/^\s*((\*[ ]?)+)\s*$/, 'meta.separator'],

			// quote
			[/^\s*>+/, 'comment'],

			// list (starting with * or number)
			[/^\s*([\*\-+:]|\d+\.)\s/, 'keyword'],

			// code block (4 spaces indent)
			[/^(\t|[ ]{4})[^ ].*$/, 'string'],

			// code block (3 tilde)
			[/^\s*~~~\s*((?:\w|[\/\-#])+)?\s*$/, { token: 'string', next: '@codeblock' }],

			// github style code blocks (with backticks and language)
			[
				/^\s*```\s*((?:\w|[\/\-#])+).*$/,
				{ token: 'string', next: '@codeblockgh', nextEmbedded: '$1' }
			],

			// github style code blocks (with backticks but no language)
			[/^\s*```\s*$/, { token: 'string', next: '@codeblock' }],

			// markup within lines
			{ include: '@linecontent' }
		],

		table_header: [
			{ include: '@table_common' },
			[/[^\|]+/, 'keyword.table.header'] // table header
		],

		table_body: [{ include: '@table_common' }, { include: '@linecontent' }],

		table_common: [
			[/\s*[\-:]+\s*/, { token: 'keyword', switchTo: 'table_body' }], // header-divider
			[/^\s*\|/, 'keyword.table.left'], // opening |
			[/^\s*[^\|]/, '@rematch', '@pop'], // exiting
			[/^\s*$/, '@rematch', '@pop'], // exiting
			[
				/\|/,
				{
					cases: {
						'@eos': 'keyword.table.right', // closing |
						'@default': 'keyword.table.middle' // inner |
					}
				}
			]
		],

		codeblock: [
			[/^\s*~~~\s*$/, { token: 'string', next: '@pop' }],
			[/^\s*```\s*$/, { token: 'string', next: '@pop' }],
			[/.*$/, 'variable.source']
		],

		// github style code blocks
		codeblockgh: [
			[/```\s*$/, { token: 'variable.source', next: '@pop', nextEmbedded: '@pop' }],
			[/[^`]+/, 'variable.source']
		],

		linecontent: [
			// escapes
			[/&\w+;/, 'string.escape'],
			[/@escapes/, 'escape'],

			// various markup
			[/\b__([^\\_]|@escapes|_(?!_))+__\b/, 'strong'],
			[/\*\*([^\\*]|@escapes|\*(?!\*))+\*\*/, 'strong'],
			[/\b_[^_]+_\b/, 'emphasis'],
			[/\*([^\\*]|@escapes)+\*/, 'emphasis'],
			[/`([^\\`]|@escapes)+`/, 'variable'],

			// links
			[/\{+[^}]+\}+/, 'string.target'],
			[/(!?\[)((?:[^\]\\]|@escapes)*)(\]\([^\)]+\))/, ['string.link', '', 'string.link']],
			[/(!?\[)((?:[^\]\\]|@escapes)*)(\])/, 'string.link'],

			// or html
			{ include: 'html' }
		],

		// Note: it is tempting to rather switch to the real HTML mode instead of building our own here
		// but currently there is a limitation in Monarch that prevents us from doing it: The opening
		// '<' would start the HTML mode, however there is no way to jump 1 character back to let the
		// HTML mode also tokenize the opening angle bracket. Thus, even though we could jump to HTML,
		// we cannot correctly tokenize it in that mode yet.
		html: [
			// html tags
			[/<(\w+)\/>/, 'tag'],
			[
				/<(\w+)/,
				{
					cases: {
						'@empty': { token: 'tag', next: '@tag.$1' },
						'@default': { token: 'tag', next: '@tag.$1' }
					}
				}
			],
			[/<\/(\w+)\s*>/, { token: 'tag' }],

			[/<!--/, 'comment', '@comment']
		],

		comment: [
			[/[^<\-]+/, 'comment.content'],
			[/-->/, 'comment', '@pop'],
			[/<!--/, 'comment.content.invalid'],
			[/[<\-]/, 'comment.content']
		],

		// Almost full HTML tag matching, complete with embedded scripts & styles
		tag: [
			[/[ \t\r\n]+/, 'white'],
			[
				/(type)(\s*=\s*)(")([^"]+)(")/,
				[
					'attribute.name.html',
					'delimiter.html',
					'string.html',
					{ token: 'string.html', switchTo: '@tag.$S2.$4' },
					'string.html'
				]
			],
			[
				/(type)(\s*=\s*)(')([^']+)(')/,
				[
					'attribute.name.html',
					'delimiter.html',
					'string.html',
					{ token: 'string.html', switchTo: '@tag.$S2.$4' },
					'string.html'
				]
			],
			[
				/(\w+)(\s*=\s*)("[^"]*"|'[^']*')/,
				['attribute.name.html', 'delimiter.html', 'string.html']
			],
			[/\w+/, 'attribute.name.html'],
			[/\/>/, 'tag', '@pop'],
			[
				/>/,
				{
					cases: {
						'$S2==style': {
							token: 'tag',
							switchTo: 'embeddedStyle',
							nextEmbedded: 'text/css'
						},
						'$S2==script': {
							cases: {
								$S3: {
									token: 'tag',
									switchTo: 'embeddedScript',
									nextEmbedded: '$S3'
								},
								'@default': {
									token: 'tag',
									switchTo: 'embeddedScript',
									nextEmbedded: 'text/javascript'
								}
							}
						},
						'@default': { token: 'tag', next: '@pop' }
					}
				}
			]
		],

		embeddedStyle: [
			[/[^<]+/, ''],
			[/<\/style\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
			[/</, '']
		],

		embeddedScript: [
			[/[^<]+/, ''],
			[/<\/script\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
			[/</, '']
		]
	}
};


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { conf as tsConf, language as tsLanguage } from '../typescript/typescript';
import type { languages } from '../fillers/monaco-editor-core';

export const conf: languages.LanguageConfiguration = tsConf;

export const language = <languages.IMonarchLanguage>{
	// Set defaultToken to invalid to see what you do not tokenize yet
	defaultToken: 'invalid',
	tokenPostfix: '.js',

	keywords: [
		'break',
		'case',
		'catch',
		'class',
		'continue',
		'const',
		'constructor',
		'debugger',
		'default',
		'delete',
		'do',
		'else',
		'export',
		'extends',
		'false',
		'finally',
		'for',
		'from',
		'function',
		'get',
		'if',
		'import',
		'in',
		'instanceof',
		'let',
		'new',
		'null',
		'return',
		'set',
		'super',
		'switch',
		'symbol',
		'this',
		'throw',
		'true',
		'try',
		'typeof',
		'undefined',
		'var',
		'void',
		'while',
		'with',
		'yield',
		'async',
		'await',
		'of'
	],
	typeKeywords: [],

	operators: tsLanguage.operators,
	symbols: tsLanguage.symbols,
	escapes: tsLanguage.escapes,
	digits: tsLanguage.digits,
	octaldigits: tsLanguage.octaldigits,
	binarydigits: tsLanguage.binarydigits,
	hexdigits: tsLanguage.hexdigits,
	regexpctl: tsLanguage.regexpctl,
	regexpesc: tsLanguage.regexpesc,
	tokenizer: tsLanguage.tokenizer
};


{ startIndex: 5, type: 'keyword.other.ts' }

keep keep keep keep keep replace keep keep keep keep

/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { languages } from '../fillers/monaco-editor-core';

export const conf: languages.LanguageConfiguration = {
	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,

	comments: {
		lineComment: '//',
		blockComment: ['/*', '*/']
	},

	brackets: [
		['{', '}'],
		['[', ']'],
		['(', ')']
	],

	onEnterRules: [
		{
			// e.g. /** | */
			beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
			afterText: /^\s*\*\/$/,
			action: {
				indentAction: languages.IndentAction.IndentOutdent,
				appendText: ' * '
			}
		},
		{
			// e.g. /** ...|
			beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
			action: {
				indentAction: languages.IndentAction.None,
				appendText: ' * '
			}
		},
		{
			// e.g.  * ...|
			beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
			action: {
				indentAction: languages.IndentAction.None,
				appendText: '* '
			}
		},
		{
			// e.g.  */|
			beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
			action: {
				indentAction: languages.IndentAction.None,
				removeText: 1
			}
		}
	],

	autoClosingPairs: [
		{ open: '{', close: '}' },
		{ open: '[', close: ']' },
		{ open: '(', close: ')' },
		{ open: '"', close: '"', notIn: ['string'] },
		{ open: "'", close: "'", notIn: ['string', 'comment'] },
		{ open: '`', close: '`', notIn: ['string', 'comment'] },
		{ open: '/**', close: ' */', notIn: ['string'] }
	],

	folding: {
		markers: {
			start: new RegExp('^\\s*//\\s*#?region\\b'),
			end: new RegExp('^\\s*//\\s*#?endregion\\b')
		}
	}
};

export const language = {
	// Set defaultToken to invalid to see what you do not tokenize yet
	defaultToken: 'invalid',
	tokenPostfix: '.ts',

	keywords: [
		// Should match the keys of textToKeywordObj in
		// https://github.com/microsoft/TypeScript/blob/master/src/compiler/scanner.ts
		'abstract',
		'any',
		'as',
		'asserts',
		'bigint',
		'boolean',
		'break',
		'case',
		'catch',
		'class',
		'continue',
		'const',
		'constructor',
		'debugger',
		'declare',
		'default',
		'delete',
		'do',
		'else',
		'enum',
		'export',
		'extends',
		'false',
		'finally',
		'for',
		'from',
		'function',
		'get',
		'if',
		'implements',
		'import',
		'in',
		'infer',
		'instanceof',
		'interface',
		'is',
		'keyof',
		'let',
		'module',
		'namespace',
		'never',
		'new',
		'null',
		'number',
		'object',
		'package',
		'private',
		'protected',
		'public',
		'readonly',
		'require',
		'global',
		'return',
		'set',
		'static',
		'string',
		'super',
		'switch',
		'symbol',
		'this',
		'throw',
		'true',
		'try',
		'type',
		'typeof',
		'undefined',
		'unique',
		'unknown',
		'var',
		'void',
		'while',
		'with',
		'yield',
		'async',
		'await',
		'of'
	],

	operators: [
		'<=',
		'>=',
		'==',
		'!=',
		'===',
		'!==',
		'=>',
		'+',
		'-',
		'**',
		'*',
		'/',
		'%',
		'++',
		'--',
		'<<',
		'</',
		'>>',
		'>>>',
		'&',
		'|',
		'^',
		'!',
		'~',
		'&&',
		'||',
		'??',
		'?',
		':',
		'=',
		'+=',
		'-=',
		'*=',
		'**=',
		'/=',
		'%=',
		'<<=',
		'>>=',
		'>>>=',
		'&=',
		'|=',
		'^=',
		'@'
	],

	// we include these common regular expressions
	symbols: /[=><!~?:&|+\-*\/\^%]+/,
	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
	digits: /\d+(_+\d+)*/,
	octaldigits: /[0-7]+(_+[0-7]+)*/,
	binarydigits: /[0-1]+(_+[0-1]+)*/,
	hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,

	regexpctl: /[(){}\[\]\$\^|\-*+?\.]/,
	regexpesc: /\\(?:[bBdDfnrstvwWn0\\\/]|@regexpctl|c[A-Z]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/,

	// The main tokenizer for our languages
	tokenizer: {
		root: [[/[{}]/, 'delimiter.bracket'], { include: 'common' }],

		common: [
			// identifiers and keywords
			[
				/[a-z_$][\w$]*/,
				{
					cases: {
						'@keywords': 'keyword',
						'@default': 'identifier'
					}
				}
			],
			[/[A-Z][\w\$]*/, 'type.identifier'], // to show class names nicely
			// [/[A-Z][\w\$]*/, 'identifier'],

			// whitespace
			{ include: '@whitespace' },

			// regular expression: ensure it is terminated before beginning (otherwise it is an opeator)
			[
				/\/(?=([^\\\/]|\\.)+\/([gimsuy]*)(\s*)(\.|;|,|\)|\]|\}|$))/,
				{ token: 'regexp', bracket: '@open', next: '@regexp' }
			],

			// delimiters and operators
			[/[()\[\]]/, '@brackets'],
			[/[<>](?!@symbols)/, '@brackets'],
			[/!(?=([^=]|$))/, 'delimiter'],
			[
				/@symbols/,
				{
					cases: {
						'@operators': 'delimiter',
						'@default': ''
					}
				}
			],

			// numbers
			[/(@digits)[eE]([\-+]?(@digits))?/, 'number.float'],
			[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/, 'number.float'],
			[/0[xX](@hexdigits)n?/, 'number.hex'],
			[/0[oO]?(@octaldigits)n?/, 'number.octal'],
			[/0[bB](@binarydigits)n?/, 'number.binary'],
			[/(@digits)n?/, 'number'],

			// delimiter: after number because of .\d floats
			[/[;,.]/, 'delimiter'],

			// strings
			[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
			[/'([^'\\]|\\.)*$/, 'string.invalid'], // non-teminated string
			[/"/, 'string', '@string_double'],
			[/'/, 'string', '@string_single'],
			[/`/, 'string', '@string_backtick']
		],

		whitespace: [
			[/[ \t\r\n]+/, ''],
			[/\/\*\*(?!\/)/, 'comment.doc', '@jsdoc'],
			[/\/\*/, 'comment', '@comment'],
			[/\/\/.*$/, 'comment']
		],

		comment: [
			[/[^\/*]+/, 'comment'],
			[/\*\//, 'comment', '@pop'],
			[/[\/*]/, 'comment']
		],

		jsdoc: [
			[/[^\/*]+/, 'comment.doc'],
			[/\*\//, 'comment.doc', '@pop'],
			[/[\/*]/, 'comment.doc']
		],

		// We match regular expression quite precisely
		regexp: [
			[
				/(\{)(\d+(?:,\d*)?)(\})/,
				['regexp.escape.control', 'regexp.escape.control', 'regexp.escape.control']
			],
			[
				/(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/,
				['regexp.escape.control', { token: 'regexp.escape.control', next: '@regexrange' }]
			],
			[/(\()(\?:|\?=|\?!)/, ['regexp.escape.control', 'regexp.escape.control']],
			[/[()]/, 'regexp.escape.control'],
			[/@regexpctl/, 'regexp.escape.control'],
			[/[^\\\/]/, 'regexp'],
			[/@regexpesc/, 'regexp.escape'],
			[/\\\./, 'regexp.invalid'],
			[
				/(\/)([gimsuy]*)/,
				[{ token: 'regexp', bracket: '@close', next: '@pop' }, 'keyword.other']
			]
		],

		regexrange: [
			[/-/, 'regexp.escape.control'],
			[/\^/, 'regexp.invalid'],
			[/@regexpesc/, 'regexp.escape'],
			[/[^\]]/, 'regexp'],
			[
				/\]/,
				{
					token: 'regexp.escape.control',
					next: '@pop',
					bracket: '@close'
				}
			]
		],

		string_double: [
			[/[^\\"]+/, 'string'],
			[/@escapes/, 'string.escape'],
			[/\\./, 'string.escape.invalid'],
			[/"/, 'string', '@pop']
		],

		string_single: [
			[/[^\\']+/, 'string'],
			[/@escapes/, 'string.escape'],
			[/\\./, 'string.escape.invalid'],
			[/'/, 'string', '@pop']
		],

		string_backtick: [
			[/\$\{/, { token: 'delimiter.bracket', next: '@bracketCounting' }],
			[/[^\\`$]+/, 'string'],
			[/@escapes/, 'string.escape'],
			[/\\./, 'string.escape.invalid'],
			[/`/, 'string', '@pop']
		],

		bracketCounting: [
			[/\{/, 'delimiter.bracket', '@bracketCounting'],
			[/\}/, 'delimiter.bracket', '@pop'],
			{ include: 'common' }
		]
	}
};


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { registerLanguage } from '../_.contribution';

registerLanguage({
	id: 'apex',
	extensions: ['.cls'],
	aliases: ['Apex', 'apex'],
	mimetypes: ['text/x-apex-source', 'text/x-apex'],
	loader: () => import('./apex')
});


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { testTokenization } from '../test/testRunner';

testTokenization('swift', [
	// Attributes
	[
		{
			line: '@noescape',
			tokens: [
				{
					startIndex: 0,
					type: 'keyword.control.swift'
				} /* '@noescape' */
			]
		}
	],
	//Keyword and Type Identifier
	[
		{
			line: 'class App: UI, UIApp, UIView {',
			tokens: [
				{ startIndex: 0, type: 'keyword.swift' } /* 'class' */,
				{ startIndex: 5, type: 'white.swift' },
				{ startIndex: 6, type: 'type.identifier.swift' } /* 'App' */,
				{ startIndex: 9, type: 'operator.swift' } /* ':' */,
				{ startIndex: 10, type: 'white.swift' },
				{ startIndex: 11, type: 'type.identifier.swift' } /* 'UI' */,
				{ startIndex: 13, type: 'operator.swift' } /* ',' */,
				{ startIndex: 14, type: 'white.swift' },
				{ startIndex: 15, type: 'type.identifier.swift' } /* 'UIApp' */,
				{ startIndex: 20, type: 'operator.swift' } /* ',' */,
				{ startIndex: 21, type: 'white.swift' },
				{
					startIndex: 22,
					type: 'type.identifier.swift'
				} /* 'UIView' */,
				{ startIndex: 28, type: 'white.swift' },
				{ startIndex: 29, type: 'delimiter.curly.swift' } /* '{' */
			]
		}
	],
	// Keyword, Identifier, and Type Identifier
	[
		{
			line: '    var window: UIWindow?',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 4, type: 'keyword.swift' } /* 'var' */,
				{ startIndex: 7, type: 'white.swift' },
				{ startIndex: 8, type: 'identifier.swift' } /* 'window' */,
				{ startIndex: 14, type: 'operator.swift' } /* ':' */,
				{ startIndex: 15, type: 'white.swift' },
				{
					startIndex: 16,
					type: 'type.identifier.swift'
				} /* 'UIWindow' */,
				{ startIndex: 24, type: 'operator.swift' } /* '?' */
			]
		}
	],
	//Comment
	[
		{
			line: '    // Comment',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 4, type: 'comment.swift' } /* '// Comment' */
			]
		}
	],
	//Block Comment with Embedded Comment followed by code
	[
		{
			line: '    /* Comment //Embedded */ var y = 0b10',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 4, type: 'comment.swift' }, // /* '/* Comment //Embedded */' */,
				{ startIndex: 28, type: 'white.swift' },
				{ startIndex: 29, type: 'keyword.swift' } /* 'var' */,
				{ startIndex: 32, type: 'white.swift' },
				{ startIndex: 33, type: 'identifier.swift' } /* 'y' */,
				{ startIndex: 34, type: 'white.swift' },
				{ startIndex: 35, type: 'operator.swift' } /* '=' */,
				{ startIndex: 36, type: 'white.swift' },
				{ startIndex: 37, type: 'number.binary.swift' } /* '0b10' */
			]
		}
	],
	// Method signature (broken on two lines)
	[
		{
			line: '    public func app(app: App, opts:',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 4, type: 'keyword.swift' } /* 'public' */,
				{ startIndex: 10, type: 'white.swift' },
				{ startIndex: 11, type: 'keyword.swift' } /* 'func' */,
				{ startIndex: 15, type: 'white.swift' },
				{ startIndex: 16, type: 'identifier.swift' } /* 'app' */,
				{
					startIndex: 19,
					type: 'delimiter.parenthesis.swift'
				} /* '(' */,
				{ startIndex: 20, type: 'identifier.swift' } /* 'app' */,
				{ startIndex: 23, type: 'operator.swift' } /* ':' */,
				{ startIndex: 24, type: 'white.swift' },
				{ startIndex: 25, type: 'type.identifier.swift' } /* 'App' */,
				{ startIndex: 28, type: 'operator.swift' } /* ',' */,
				{ startIndex: 29, type: 'white.swift' },
				{ startIndex: 30, type: 'identifier.swift' } /* 'opts' */,
				{ startIndex: 34, type: 'operator.swift' } /* ':' */
			]
		}
	],
	// Method signature Continued
	[
		{
			line: '        [NSObject: AnyObject]?) -> Bool {',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 8, type: 'delimiter.square.swift' } /* '[' */,
				{
					startIndex: 9,
					type: 'type.identifier.swift'
				} /* 'NSObject' */,
				{ startIndex: 17, type: 'operator.swift' } /* ':' */,
				{ startIndex: 18, type: 'white.swift' },
				{
					startIndex: 19,
					type: 'type.identifier.swift'
				} /* 'AnyObject' */,
				{ startIndex: 28, type: 'delimiter.square.swift' } /* ']' */,
				{ startIndex: 29, type: 'operator.swift' } /* '?' */,
				{
					startIndex: 30,
					type: 'delimiter.parenthesis.swift'
				} /* ')' */,
				{ startIndex: 31, type: 'white.swift' },
				{ startIndex: 32, type: 'operator.swift' } /* '->' */,
				{ startIndex: 34, type: 'white.swift' },
				{ startIndex: 35, type: 'type.identifier.swift' } /* 'Bool' */,
				{ startIndex: 39, type: 'white.swift' },
				{ startIndex: 40, type: 'delimiter.curly.swift' } /* '{' */
			]
		}
	],
	// String with escapes
	[
		{
			line: '        var `String` = "String w/ \\"escape\\""',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 8, type: 'keyword.swift' } /* 'var' */,
				{ startIndex: 11, type: 'white.swift' },
				{ startIndex: 12, type: 'operator.swift' } /* '`' */,
				{ startIndex: 13, type: 'identifier.swift' } /* 'String' */,
				{ startIndex: 19, type: 'operator.swift' } /* '`' */,
				{ startIndex: 20, type: 'white.swift' },
				{ startIndex: 21, type: 'operator.swift' } /* '=' */,
				{ startIndex: 22, type: 'white.swift' },
				{ startIndex: 23, type: 'string.quote.swift' } /* '"' */,
				{
					startIndex: 24,
					type: 'string.swift'
				} /* 'String w/ \\"escape\\""' */,
				{ startIndex: 44, type: 'string.quote.swift' } /* '"' */
			]
		}
	],
	// String with interpolated expression
	[
		{
			line: '        let message = "\\(y) times 2.5 is \\(Double(25) * 2.5)"',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 8, type: 'keyword.swift' } /* 'let' */,
				{ startIndex: 11, type: 'white.swift' },
				{ startIndex: 12, type: 'identifier.swift' } /* 'message' */,
				{ startIndex: 19, type: 'white.swift' },
				{ startIndex: 20, type: 'operator.swift' } /* '=' */,
				{ startIndex: 21, type: 'white.swift' },
				{ startIndex: 22, type: 'string.quote.swift' } /* '"' */,
				{ startIndex: 23, type: 'operator.swift' } /* '\(' */,
				{ startIndex: 25, type: 'identifier.swift' },
				{ startIndex: 26, type: 'operator.swift' } /* ')' */,
				{ startIndex: 27, type: 'string.swift' } /* ' times 2.5 is ' */,
				{ startIndex: 41, type: 'operator.swift' } /* '\(' */,
				{
					startIndex: 43,
					type: 'type.identifier.swift'
				} /* 'Double' */,
				{ startIndex: 49, type: 'operator.swift' } /* '(' */,
				{ startIndex: 50, type: 'number.swift' } /* '25' */,
				{ startIndex: 52, type: 'operator.swift' } /* ')' */,
				{ startIndex: 53, type: '' },
				{ startIndex: 54, type: 'operator.swift' } /* '*' */,
				{ startIndex: 55, type: '' },
				{ startIndex: 56, type: 'number.float.swift' } /* '2.5' */,
				{ startIndex: 59, type: 'operator.swift' } /* ')' */,
				{ startIndex: 60, type: 'string.quote.swift' } /* '"' */
			]
		}
	],
	// Multiline string
	[
		{
			line: '"""test"test', // Separate new lines into separate objects within this same array.
			tokens: [
				{ startIndex: 0, type: 'string.quote.swift' } /* '"""' */,
				{ startIndex: 3, type: 'string.swift' } /* test"test */
			]
		},
		{
			line: ' keepsgoing"""',
			tokens: [
				{ startIndex: 0, type: 'string.swift' } /* ' keepsgoing' */,
				{ startIndex: 11, type: 'string.quote.swift' } /* '"""' */
			]
		}
	],
	// Method invocation/property accessor.
	[
		{
			line: '        let view = self.window!.contr as! UIView',
			tokens: [
				{ startIndex: 0, type: 'white.swift' },
				{ startIndex: 8, type: 'keyword.swift' } /* 'let' */,
				{ startIndex: 11, type: 'white.swift' },
				{ startIndex: 12, type: 'identifier.swift' } /* 'view' */,
				{ startIndex: 16, type: 'white.swift' },
				{ startIndex: 17, type: 'operator.swift' } /* '=' */,
				{ startIndex: 18, type: 'white.swift' },
				{ startIndex: 19, type: 'keyword.swift' } /* 'self' */,
				{ startIndex: 23, type: 'delimeter.swift' } /* '.' */,
				{
					startIndex: 24,
					type: 'type.identifier.swift'
				} /* 'window' */,
				{ startIndex: 30, type: 'operator.swift' } /* '!' */,
				{ startIndex: 31, type: 'delimeter.swift' } /* '.' */,
				{ startIndex: 32, type: 'type.identifier.swift' } /* 'contr' */,
				{ startIndex: 37, type: 'white.swift' },
				{ startIndex: 38, type: 'keyword.swift' } /* 'as' */,
				{ startIndex: 40, type: 'operator.swift' } /* '!' */,
				{ startIndex: 41, type: 'white.swift' },
				{ startIndex: 42, type: 'type.identifier.swift' } /* 'UIView' */
			]
		}
	]
]);


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import type { languages } from '../fillers/monaco-editor-core';

export const conf: languages.LanguageConfiguration = {
	comments: {
		lineComment: "'"
	},
	brackets: [
		['(', ')'],
		['[', ']'],
		['If', 'EndIf'],
		['While', 'EndWhile'],
		['For', 'EndFor'],
		['Sub', 'EndSub']
	],
	autoClosingPairs: [
		{ open: '"', close: '"', notIn: ['string', 'comment'] },
		{ open: '(', close: ')', notIn: ['string', 'comment'] },
		{ open: '[', close: ']', notIn: ['string', 'comment'] }
	]
};

export const language = <languages.IMonarchLanguage>{
	defaultToken: '',
	tokenPostfix: '.sb',
	ignoreCase: true,

	brackets: [
		{ token: 'delimiter.array', open: '[', close: ']' },
		{ token: 'delimiter.parenthesis', open: '(', close: ')' },

		// Special bracket statement pairs
		{ token: 'keyword.tag-if', open: 'If', close: 'EndIf' },
		{ token: 'keyword.tag-while', open: 'While', close: 'EndWhile' },
		{ token: 'keyword.tag-for', open: 'For', close: 'EndFor' },
		{ token: 'keyword.tag-sub', open: 'Sub', close: 'EndSub' }
	],

	keywords: [
		'Else',
		'ElseIf',
		'EndFor',
		'EndIf',
		'EndSub',
		'EndWhile',
		'For',
		'Goto',
		'If',
		'Step',
		'Sub',
		'Then',
		'To',
		'While'
	],

	tagwords: ['If', 'Sub', 'While', 'For'],

	operators: ['>', '<', '<>', '<=', '>=', 'And', 'Or', '+', '-', '*', '/', '='],

	// we include these common regular expressions
	identifier: /[a-zA-Z_][\w]*/,
	symbols: /[=><:+\-*\/%\.,]+/,
	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,

	// The main tokenizer for our languages
	tokenizer: {
		root: [
			// whitespace
			{ include: '@whitespace' },

			// classes
			[/(@identifier)(?=[.])/, 'type'],

			// identifiers, tagwords, and keywords
			[
				/@identifier/,
				{
					cases: {
						'@keywords': { token: 'keyword.$0' },
						'@operators': 'operator',
						'@default': 'variable.name'
					}
				}
			],

			// methods, properties, and events
			[
				/([.])(@identifier)/,
				{
					cases: {
						$2: ['delimiter', 'type.member'],
						'@default': ''
					}
				}
			],

			// numbers
			[/\d*\.\d+/, 'number.float'],
			[/\d+/, 'number'],

			// delimiters and operators
			[/[()\[\]]/, '@brackets'],
			[
				/@symbols/,
				{
					cases: {
						'@operators': 'operator',
						'@default': 'delimiter'
					}
				}
			],

			// strings
			[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
			[/"/, 'string', '@string']
		],

		whitespace: [
			[/[ \t\r\n]+/, ''],
			[/(\').*$/, 'comment']
		],

		string: [
			[/[^\\"]+/, 'string'],
			[/@escapes/, 'string.escape'],
			[/\\./, 'string.escape.invalid'],
			[/"C?/, 'string', '@pop']
		]
	}
};


// regular expression: ensure it is terminated before beginning (otherwise it is an opeator)

{ token: 'regexp', bracket: '@open', next: '@regexp' }

keep keep keep keep replace keep keep keep keep keep

/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { testTokenization } from '../test/testRunner';

testTokenization('javascript', [
	// Keywords
	[
		{
			line: 'var x = function() { };',
			tokens: [
				{ startIndex: 0, type: 'keyword.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'keyword.js' },
				{ startIndex: 16, type: 'delimiter.parenthesis.js' },
				{ startIndex: 18, type: '' },
				{ startIndex: 19, type: 'delimiter.bracket.js' },
				{ startIndex: 20, type: '' },
				{ startIndex: 21, type: 'delimiter.bracket.js' },
				{ startIndex: 22, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: '    var    ',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 4, type: 'keyword.js' },
				{ startIndex: 7, type: '' }
			]
		}
	],

	// Comments - single line
	[
		{
			line: '//',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: '    // a comment',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 4, type: 'comment.js' }
			]
		}
	],

	[
		{
			line: '// a comment',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: '// a comment /*',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: '// a comment /**',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: '//sticky comment',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: 'var x = 1; // my comment // is a nice one',
			tokens: [
				{ startIndex: 0, type: 'keyword.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'number.js' },
				{ startIndex: 9, type: 'delimiter.js' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'comment.js' }
			]
		}
	],

	// Comments - range comment, single line
	[
		{
			line: '/* a simple comment */',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: 'var x = /* a simple comment */ 1;',
			tokens: [
				{ startIndex: 0, type: 'keyword.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'comment.js' },
				{ startIndex: 30, type: '' },
				{ startIndex: 31, type: 'number.js' },
				{ startIndex: 32, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: 'x = /**/;',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'comment.js' },
				{ startIndex: 8, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: 'x = /*/;',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'comment.js' }
			]
		}
	],

	// Comments - range comment, multi lines
	[
		{
			line: '/* a multiline comment',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		},
		{
			line: 'can actually span',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		},
		{
			line: 'multiple lines */',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: 'var x = /* start a comment',
			tokens: [
				{ startIndex: 0, type: 'keyword.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'comment.js' }
			]
		},
		{
			line: ' a ',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		},
		{
			line: 'and end it */ var a = 2;',
			tokens: [
				{ startIndex: 0, type: 'comment.js' },
				{ startIndex: 13, type: '' },
				{ startIndex: 14, type: 'keyword.js' },
				{ startIndex: 17, type: '' },
				{ startIndex: 18, type: 'identifier.js' },
				{ startIndex: 19, type: '' },
				{ startIndex: 20, type: 'delimiter.js' },
				{ startIndex: 21, type: '' },
				{ startIndex: 22, type: 'number.js' },
				{ startIndex: 23, type: 'delimiter.js' }
			]
		}
	],

	// Strings
	[
		{
			line: "var a = 'a';",
			tokens: [
				{ startIndex: 0, type: 'keyword.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'string.js' },
				{ startIndex: 11, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: '"use strict";',
			tokens: [
				{ startIndex: 0, type: 'string.js' },
				{ startIndex: 12, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: 'b = a + " \'cool\'  "',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'identifier.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'string.js' }
			]
		}
	],

	[
		{
			line: '"escaping \\"quotes\\" is cool"',
			tokens: [
				{ startIndex: 0, type: 'string.js' },
				{ startIndex: 10, type: 'string.escape.js' },
				{ startIndex: 12, type: 'string.js' },
				{ startIndex: 18, type: 'string.escape.js' },
				{ startIndex: 20, type: 'string.js' }
			]
		}
	],

	[
		{
			line: "'''",
			tokens: [
				{ startIndex: 0, type: 'string.js' },
				{ startIndex: 2, type: 'string.invalid.js' }
			]
		}
	],

	[
		{
			line: "'\\''",
			tokens: [
				{ startIndex: 0, type: 'string.js' },
				{ startIndex: 1, type: 'string.escape.js' },
				{ startIndex: 3, type: 'string.js' }
			]
		}
	],

	[
		{
			line: "'be careful \\not to escape'",
			tokens: [
				{ startIndex: 0, type: 'string.js' },
				{ startIndex: 12, type: 'string.escape.js' },
				{ startIndex: 14, type: 'string.js' }
			]
		}
	],

	// Numbers
	[
		{
			line: '0',
			tokens: [{ startIndex: 0, type: 'number.js' }]
		}
	],

	[
		{
			line: ' 0',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.js' }
			]
		}
	],

	[
		{
			line: ' 0 ',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.js' },
				{ startIndex: 2, type: '' }
			]
		}
	],

	[
		{
			line: '0 ',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: '' }
			]
		}
	],

	[
		{
			line: '0+0',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: 'delimiter.js' },
				{ startIndex: 2, type: 'number.js' }
			]
		}
	],

	[
		{
			line: '100+10',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 3, type: 'delimiter.js' },
				{ startIndex: 4, type: 'number.js' }
			]
		}
	],

	[
		{
			line: '0 + 0',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.js' }
			]
		}
	],

	[
		{
			line: '0123',
			tokens: [{ startIndex: 0, type: 'number.octal.js' }]
		}
	],

	[
		{
			line: '01239',
			tokens: [
				{ startIndex: 0, type: 'number.octal.js' },
				{ startIndex: 4, type: 'number.js' }
			]
		}
	],

	[
		{
			line: '0o123',
			tokens: [{ startIndex: 0, type: 'number.octal.js' }]
		}
	],

	[
		{
			line: '0O123',
			tokens: [{ startIndex: 0, type: 'number.octal.js' }]
		}
	],

	[
		{
			line: '0x',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: 'identifier.js' }
			]
		}
	],

	[
		{
			line: '0x123',
			tokens: [{ startIndex: 0, type: 'number.hex.js' }]
		}
	],

	[
		{
			line: '0X123',
			tokens: [{ startIndex: 0, type: 'number.hex.js' }]
		}
	],

	[
		{
			line: '0b101',
			tokens: [{ startIndex: 0, type: 'number.binary.js' }]
		}
	],

	[
		{
			line: '0B101',
			tokens: [{ startIndex: 0, type: 'number.binary.js' }]
		}
	],

	// Bigint
	[
		{
			line: '0n',
			tokens: [{ startIndex: 0, type: 'number.js' }]
		}
	],

	[
		{
			line: ' 0n',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.js' }
			]
		}
	],

	[
		{
			line: ' 0n ',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 1, type: 'number.js' },
				{ startIndex: 3, type: '' }
			]
		}
	],

	[
		{
			line: '0n ',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 2, type: '' }
			]
		}
	],

	[
		{
			line: '0n+0n',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: 'number.js' }
			]
		}
	],

	[
		{
			line: '100n+10n',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 4, type: 'delimiter.js' },
				{ startIndex: 5, type: 'number.js' }
			]
		}
	],

	[
		{
			line: '0n + 0n',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 2, type: '' },
				{ startIndex: 3, type: 'delimiter.js' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'number.js' }
			]
		}
	],

	[
		{
			line: '0b101n',
			tokens: [{ startIndex: 0, type: 'number.binary.js' }]
		}
	],

	[
		{
			line: '0123n',
			tokens: [{ startIndex: 0, type: 'number.octal.js' }]
		}
	],

	[
		{
			line: '0o123n',
			tokens: [{ startIndex: 0, type: 'number.octal.js' }]
		}
	],

	[
		{
			line: '0x123n',
			tokens: [{ startIndex: 0, type: 'number.hex.js' }]
		}
	],

	// Regular Expressions
	[
		{
			line: '//',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: '/**/',
			tokens: [{ startIndex: 0, type: 'comment.js' }]
		}
	],

	[
		{
			line: '/***/',
			tokens: [{ startIndex: 0, type: 'comment.doc.js' }]
		}
	],

	[
		{
			line: '5 / 3;',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.js' },
				{ startIndex: 5, type: 'delimiter.js' }
			]
		}
	],

	// Advanced regular expressions
	[
		{
			line: '1 / 2; /* comment',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.js' },
				{ startIndex: 5, type: 'delimiter.js' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'comment.js' }
			]
		}
	],

	[
		{
			line: '1 / 2 / x / b;',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'identifier.js' },
				{ startIndex: 9, type: '' },
				{ startIndex: 10, type: 'delimiter.js' },
				{ startIndex: 11, type: '' },
				{ startIndex: 12, type: 'identifier.js' },
				{ startIndex: 13, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: "x = /foo/.test('')",
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'regexp.js' },
				{ startIndex: 9, type: 'delimiter.js' },
				{ startIndex: 10, type: 'identifier.js' },
				{ startIndex: 14, type: 'delimiter.parenthesis.js' },
				{ startIndex: 15, type: 'string.js' },
				{ startIndex: 17, type: 'delimiter.parenthesis.js' }
			]
		}
	],

	[
		{
			line: '/foo/',
			tokens: [{ startIndex: 0, type: 'regexp.js' }]
		}
	],

	[
		{
			line: '/foo/g',
			tokens: [
				{ startIndex: 0, type: 'regexp.js' },
				{ startIndex: 5, type: 'keyword.other.js' }
			]
		}
	],

	[
		{
			line: '/foo/gimsuy',
			tokens: [
				{ startIndex: 0, type: 'regexp.js' },
				{ startIndex: 5, type: 'keyword.other.js' }
			]
		}
	],

	[
		{
			line: '/foo/q', // invalid flag
			tokens: [
				{ startIndex: 0, type: 'delimiter.js' },
				{ startIndex: 1, type: 'identifier.js' },
				{ startIndex: 4, type: 'delimiter.js' },
				{ startIndex: 5, type: 'identifier.js' }
			]
		}
	],

	[
		{
			line: 'x = 1 + f(2 / 3, /foo/)',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'number.js' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'identifier.js' },
				{ startIndex: 9, type: 'delimiter.parenthesis.js' },
				{ startIndex: 10, type: 'number.js' },
				{ startIndex: 11, type: '' },
				{ startIndex: 12, type: 'delimiter.js' },
				{ startIndex: 13, type: '' },
				{ startIndex: 14, type: 'number.js' },
				{ startIndex: 15, type: 'delimiter.js' },
				{ startIndex: 16, type: '' },
				{ startIndex: 17, type: 'regexp.js' },
				{ startIndex: 22, type: 'delimiter.parenthesis.js' }
			]
		}
	],

	[
		{
			line: 'a /ads/ b;',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: 'identifier.js' },
				{ startIndex: 6, type: 'delimiter.js' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'identifier.js' },
				{ startIndex: 9, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: '1/(2/3)/2/3;',
			tokens: [
				{ startIndex: 0, type: 'number.js' },
				{ startIndex: 1, type: 'delimiter.js' },
				{ startIndex: 2, type: 'delimiter.parenthesis.js' },
				{ startIndex: 3, type: 'number.js' },
				{ startIndex: 4, type: 'delimiter.js' },
				{ startIndex: 5, type: 'number.js' },
				{ startIndex: 6, type: 'delimiter.parenthesis.js' },
				{ startIndex: 7, type: 'delimiter.js' },
				{ startIndex: 8, type: 'number.js' },
				{ startIndex: 9, type: 'delimiter.js' },
				{ startIndex: 10, type: 'number.js' },
				{ startIndex: 11, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: '{ key: 123 }',
			tokens: [
				{ startIndex: 0, type: 'delimiter.bracket.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'identifier.js' },
				{ startIndex: 5, type: 'delimiter.js' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'number.js' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'delimiter.bracket.js' }
			]
		}
	],

	[
		{
			line: '[1,2,3]',
			tokens: [
				{ startIndex: 0, type: 'delimiter.square.js' },
				{ startIndex: 1, type: 'number.js' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: 'number.js' },
				{ startIndex: 4, type: 'delimiter.js' },
				{ startIndex: 5, type: 'number.js' },
				{ startIndex: 6, type: 'delimiter.square.js' }
			]
		}
	],

	[
		{
			line: 'foo(123);',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 3, type: 'delimiter.parenthesis.js' },
				{ startIndex: 4, type: 'number.js' },
				{ startIndex: 7, type: 'delimiter.parenthesis.js' },
				{ startIndex: 8, type: 'delimiter.js' }
			]
		}
	],

	[
		{
			line: '{a:{b:[]}}',
			tokens: [
				{ startIndex: 0, type: 'delimiter.bracket.js' },
				{ startIndex: 1, type: 'identifier.js' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: 'delimiter.bracket.js' },
				{ startIndex: 4, type: 'identifier.js' },
				{ startIndex: 5, type: 'delimiter.js' },
				{ startIndex: 6, type: 'delimiter.square.js' },
				{ startIndex: 8, type: 'delimiter.bracket.js' }
			]
		}
	],

	[
		{
			line: 'x = "[{()}]"',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.js' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'string.js' }
			]
		}
	],

	[
		{
			line: 'test ? 1 : 2',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.js' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'number.js' },
				{ startIndex: 8, type: '' },
				{ startIndex: 9, type: 'delimiter.js' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'number.js' }
			]
		}
	],

	[
		{
			line: 'couldBeNullish ?? 1',
			tokens: [
				{ startIndex: 0, type: 'identifier.js' },
				{ startIndex: 14, type: '' },
				{ startIndex: 15, type: 'delimiter.js' },
				{ startIndex: 17, type: '' },
				{ startIndex: 18, type: 'number.js' }
			]
		}
	],

	[
		{
			line: "`${5 + 'x' + 3}a${4}`",
			tokens: [
				{ startIndex: 0, type: 'string.js' },
				{ startIndex: 1, type: 'delimiter.bracket.js' },
				{ startIndex: 3, type: 'number.js' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.js' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'string.js' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'delimiter.js' },
				{ startIndex: 12, type: '' },
				{ startIndex: 13, type: 'number.js' },
				{ startIndex: 14, type: 'delimiter.bracket.js' },
				{ startIndex: 15, type: 'string.js' },
				{ startIndex: 16, type: 'delimiter.bracket.js' },
				{ startIndex: 18, type: 'number.js' },
				{ startIndex: 19, type: 'delimiter.bracket.js' },
				{ startIndex: 20, type: 'string.js' }
			]
		}
	]
]);


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { testTokenization } from '../test/testRunner';

testTokenization('css', [
	// Skip whitespace
	[
		{
			line: '      body',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 6, type: 'tag.css' }
			]
		}
	],

	// CSS rule
	//	body {
	//	  margin: 0;
	//	  padding: 3em 6em;
	//	  font-family: tahoma, arial, sans-serif;
	//	  text-decoration: none !important;
	//	  color: #000
	//	}
	[
		{
			line: 'body {',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  margin: 0;',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 9, type: '' },
				{ startIndex: 10, type: 'attribute.value.number.css' },
				{ startIndex: 11, type: 'delimiter.css' }
			]
		},
		{
			line: '  padding: 3em 6em;',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'attribute.value.number.css' },
				{ startIndex: 12, type: 'attribute.value.unit.css' },
				{ startIndex: 14, type: '' },
				{ startIndex: 15, type: 'attribute.value.number.css' },
				{ startIndex: 16, type: 'attribute.value.unit.css' },
				{ startIndex: 18, type: 'delimiter.css' }
			]
		},
		{
			line: '  font-family: tahoma, arial, sans-serif;',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 14, type: '' },
				{ startIndex: 15, type: 'attribute.value.css' },
				{ startIndex: 21, type: 'delimiter.css' },
				{ startIndex: 22, type: '' },
				{ startIndex: 23, type: 'attribute.value.css' },
				{ startIndex: 28, type: 'delimiter.css' },
				{ startIndex: 29, type: '' },
				{ startIndex: 30, type: 'attribute.value.css' },
				{ startIndex: 40, type: 'delimiter.css' }
			]
		},
		{
			line: '  text-decoration: none !important;',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 18, type: '' },
				{ startIndex: 19, type: 'attribute.value.css' },
				{ startIndex: 23, type: '' },
				{ startIndex: 24, type: 'keyword.css' },
				{ startIndex: 34, type: 'delimiter.css' }
			]
		},
		{
			line: '  color: #000',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 8, type: '' },
				{ startIndex: 9, type: 'attribute.value.hex.css' }
			]
		},
		{
			line: '  }',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'delimiter.bracket.css' }
			]
		}
	],

	// CSS units and numbers
	[
		{
			line: '* { padding: 3em -9pt -0.5px; }',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.bracket.css' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'attribute.name.css' },
				{ startIndex: 12, type: '' },
				{ startIndex: 13, type: 'attribute.value.number.css' },
				{ startIndex: 14, type: 'attribute.value.unit.css' },
				{ startIndex: 16, type: '' },
				{ startIndex: 17, type: 'attribute.value.number.css' },
				{ startIndex: 19, type: 'attribute.value.unit.css' },
				{ startIndex: 21, type: '' },
				{ startIndex: 22, type: 'attribute.value.number.css' },
				{ startIndex: 26, type: 'attribute.value.unit.css' },
				{ startIndex: 28, type: 'delimiter.css' },
				{ startIndex: 29, type: '' },
				{ startIndex: 30, type: 'delimiter.bracket.css' }
			]
		}
	],

	// CSS unfinished unit and numbers
	[
		{
			line: '* { padding: -',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 1, type: '' },
				{ startIndex: 2, type: 'delimiter.bracket.css' },
				{ startIndex: 3, type: '' },
				{ startIndex: 4, type: 'attribute.name.css' },
				{ startIndex: 12, type: '' },
				{ startIndex: 13, type: 'delimiter.css' }
			]
		}
	],

	// CSS single line comment
	//	h1 /*comment*/ p  {
	[
		{
			line: 'h1 /*comment*/ p {',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 2, type: '' },
				{ startIndex: 3, type: 'comment.css' },
				{ startIndex: 14, type: '' },
				{ startIndex: 15, type: 'tag.css' },
				{ startIndex: 16, type: '' },
				{ startIndex: 17, type: 'delimiter.bracket.css' }
			]
		}
	],

	// CSS multi line comment
	//	h1 /*com
	//  ment*/ p  {
	[
		{
			line: 'h1 /*com',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 2, type: '' },
				{ startIndex: 3, type: 'comment.css' }
			]
		},
		{
			line: 'ment*/ p',
			tokens: [
				{ startIndex: 0, type: 'comment.css' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'tag.css' }
			]
		}
	],

	// CSS ID rule
	[
		{
			line: '#myID {',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.bracket.css' }
			]
		}
	],

	// CSS Class rules
	[
		{
			line: '.myID {',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.bracket.css' }
			]
		}
	],

	// CSS @import etc
	[
		{
			line: '@import url("something.css");',
			tokens: [
				{ startIndex: 0, type: 'keyword.css' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'attribute.value.css' },
				{ startIndex: 11, type: 'delimiter.parenthesis.css' },
				{ startIndex: 12, type: 'string.css' },
				{ startIndex: 27, type: 'delimiter.parenthesis.css' },
				{ startIndex: 28, type: 'delimiter.css' }
			]
		}
	],

	// CSS multi-line string with an escaped newline
	//	body {
	//	content: 'con\
	//  tent';
	[
		{
			line: 'body {',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  content: "con\\',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'string.css' }
			]
		},
		{
			line: 'tent";',
			tokens: [
				{ startIndex: 0, type: 'string.css' },
				{ startIndex: 5, type: 'delimiter.css' }
			]
		}
	],

	// CSS empty string value
	//	body {
	//	content: '';
	[
		{
			line: 'body {',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  content: "";',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'string.css' },
				{ startIndex: 13, type: 'delimiter.css' }
			]
		}
	],

	// CSS font face
	// @font-face {
	//     font-family: 'Opificio';
	// }
	[
		{
			line: '@font-face {',
			tokens: [
				{ startIndex: 0, type: 'keyword.css' },
				{ startIndex: 10, type: '' },
				{ startIndex: 11, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  font-family: "Opificio";',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 14, type: '' },
				{ startIndex: 15, type: 'string.css' },
				{ startIndex: 25, type: 'delimiter.css' }
			]
		}
	],

	// CSS string with escaped quotes
	//	's\"tr'
	[
		{
			line: '"s\\"tr" ',
			tokens: [
				{ startIndex: 0, type: 'string.css' },
				{ startIndex: 7, type: '' }
			]
		}
	],

	// CSS key frame animation syntax
	//@-webkit-keyframes infinite-spinning {
	//	 from {
	//		-webkit-transform: rotate(0deg);
	//	}
	//	to {
	//		-webkit-transform: rotate(360deg);
	//	}
	//}
	[
		{
			line: '@-webkit-keyframes infinite-spinning {',
			tokens: [
				{ startIndex: 0, type: 'keyword.css' },
				{ startIndex: 18, type: '' },
				{ startIndex: 19, type: 'attribute.value.css' },
				{ startIndex: 36, type: '' },
				{ startIndex: 37, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  from {',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.value.css' },
				{ startIndex: 6, type: '' },
				{ startIndex: 7, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  -webkit-transform: rotate(0deg);',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 20, type: '' },
				{ startIndex: 21, type: 'attribute.value.css' },
				{ startIndex: 28, type: 'attribute.value.number.css' },
				{ startIndex: 29, type: 'attribute.value.unit.css' },
				{ startIndex: 32, type: 'attribute.value.css' },
				{ startIndex: 33, type: 'delimiter.css' }
			]
		},
		{
			line: '	 }',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  to {',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.value.css' },
				{ startIndex: 4, type: '' },
				{ startIndex: 5, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '  -webkit-transform: rotate(360deg);',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'attribute.name.css' },
				{ startIndex: 20, type: '' },
				{ startIndex: 21, type: 'attribute.value.css' },
				{ startIndex: 28, type: 'attribute.value.number.css' },
				{ startIndex: 31, type: 'attribute.value.unit.css' },
				{ startIndex: 34, type: 'attribute.value.css' },
				{ startIndex: 35, type: 'delimiter.css' }
			]
		},
		{
			line: '	 }',
			tokens: [
				{ startIndex: 0, type: '' },
				{ startIndex: 2, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '}',
			tokens: [{ startIndex: 0, type: 'delimiter.bracket.css' }]
		}
	],

	// CSS @import related coloring bug 9553
	//		 @import url('something.css');
	//		.rule1{}
	//		.rule2{}
	[
		{
			line: '@import url("something.css");',
			tokens: [
				{ startIndex: 0, type: 'keyword.css' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'attribute.value.css' },
				{ startIndex: 11, type: 'delimiter.parenthesis.css' },
				{ startIndex: 12, type: 'string.css' },
				{ startIndex: 27, type: 'delimiter.parenthesis.css' },
				{ startIndex: 28, type: 'delimiter.css' }
			]
		},
		{
			line: '.rule1{}',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 6, type: 'delimiter.bracket.css' }
			]
		},
		{
			line: '.rule2{}',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 6, type: 'delimiter.bracket.css' }
			]
		}
	],

	// Triple quotes - bug #9870
	[
		{
			line: '"""',
			tokens: [{ startIndex: 0, type: 'string.css' }]
		}
	],

	[
		{
			line: '""""',
			tokens: [{ startIndex: 0, type: 'string.css' }]
		}
	],

	[
		{
			line: '"""""',
			tokens: [{ startIndex: 0, type: 'string.css' }]
		}
	],

	// import statement - bug #10308
	//	@import url('something.css');@import url('something.css');
	[
		{
			line: '@import url("something.css");@import url("something.css");',
			tokens: [
				{ startIndex: 0, type: 'keyword.css' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'attribute.value.css' },
				{ startIndex: 11, type: 'delimiter.parenthesis.css' },
				{ startIndex: 12, type: 'string.css' },
				{ startIndex: 27, type: 'delimiter.parenthesis.css' },
				{ startIndex: 28, type: 'delimiter.css' },
				{ startIndex: 29, type: 'keyword.css' },
				{ startIndex: 36, type: '' },
				{ startIndex: 37, type: 'attribute.value.css' },
				{ startIndex: 40, type: 'delimiter.parenthesis.css' },
				{ startIndex: 41, type: 'string.css' },
				{ startIndex: 56, type: 'delimiter.parenthesis.css' },
				{ startIndex: 57, type: 'delimiter.css' }
			]
		}
	],

	// !important - bug #9578
	// .a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}
	[
		{
			line:
				'.a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 2, type: 'delimiter.bracket.css' },
				{ startIndex: 3, type: 'attribute.name.css' },
				{ startIndex: 14, type: 'attribute.value.hex.css' },
				{ startIndex: 21, type: '' },
				{ startIndex: 22, type: 'keyword.css' },
				{ startIndex: 32, type: 'delimiter.bracket.css' },
				{ startIndex: 33, type: 'tag.css' },
				{ startIndex: 35, type: 'delimiter.bracket.css' },
				{ startIndex: 36, type: 'attribute.name.css' },
				{ startIndex: 48, type: 'string.css' },
				{ startIndex: 64, type: 'delimiter.css' },
				{ startIndex: 65, type: '' },
				{ startIndex: 66, type: 'attribute.value.css' },
				{ startIndex: 75, type: 'delimiter.css' },
				{ startIndex: 76, type: 'attribute.name.css' },
				{ startIndex: 83, type: 'attribute.value.number.css' },
				{ startIndex: 85, type: 'attribute.value.unit.css' },
				{ startIndex: 87, type: 'delimiter.css' },
				{ startIndex: 88, type: 'delimiter.bracket.css' }
			]
		}
	],

	// base64-encoded data uris - bug #9580
	//.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}
	[
		{
			line:
				'.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 5, type: '' },
				{ startIndex: 6, type: 'delimiter.bracket.css' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'attribute.name.css' },
				{ startIndex: 19, type: '' },
				{ startIndex: 20, type: 'attribute.value.hex.css' },
				{ startIndex: 24, type: '' },
				{ startIndex: 25, type: 'attribute.value.css' },
				{ startIndex: 28, type: 'delimiter.parenthesis.css' },
				{ startIndex: 29, type: 'string.css' },
				{ startIndex: 215, type: 'delimiter.parenthesis.css' },
				{ startIndex: 216, type: '' },
				{ startIndex: 217, type: 'attribute.value.css' },
				{ startIndex: 225, type: '' },
				{ startIndex: 226, type: 'attribute.value.css' },
				{ startIndex: 232, type: 'delimiter.bracket.css' }
			]
		}
	],

	// /a colorization is incorrect in url - bug #9581
	//.a{background:url(/a.jpg)}
	[
		{
			line: '.a{background:url(/a.jpg)}',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 2, type: 'delimiter.bracket.css' },
				{ startIndex: 3, type: 'attribute.name.css' },
				{ startIndex: 14, type: 'attribute.value.css' },
				{ startIndex: 17, type: 'delimiter.parenthesis.css' },
				{ startIndex: 18, type: 'string.css' },
				{ startIndex: 24, type: 'delimiter.parenthesis.css' },
				{ startIndex: 25, type: 'delimiter.bracket.css' }
			]
		}
	],

	// Bracket Matching
	[
		{
			line: 'p{}',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 1, type: 'delimiter.bracket.css' }
			]
		}
	],

	[
		{
			line: 'p:nth() {}',
			tokens: [
				{ startIndex: 0, type: 'tag.css' },
				{ startIndex: 5, type: '' },
				{ startIndex: 8, type: 'delimiter.bracket.css' }
			]
		}
	],

	[
		{
			line: "@import 'https://example.com/test.css';",
			tokens: [
				{ startIndex: 0, type: 'keyword.css' },
				{ startIndex: 7, type: '' },
				{ startIndex: 8, type: 'string.css' },
				{ startIndex: 38, type: 'delimiter.css' }
			]
		}
	]
]);


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { registerLanguage } from '../_.contribution';

registerLanguage({
	id: 'kotlin',
	extensions: ['.kt'],
	aliases: ['Kotlin', 'kotlin'],
	mimetypes: ['text/x-kotlin-source', 'text/x-kotlin'],
	loader: () => import('./kotlin')
});


[{ token: 'regexp', bracket: '@close', next: '@pop' }, 'keyword.other']


/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import type { languages } from '../fillers/monaco-editor-core';

export const conf: languages.LanguageConfiguration = {
	comments: {
		lineComment: '#'
	},
	brackets: [
		['{', '}'],
		['[', ']'],
		['(', ')']
	],
	autoClosingPairs: [
		{ open: '{', close: '}' },
		{ open: '[', close: ']' },
		{ open: '(', close: ')' },
		{ open: '"', close: '"' },
		{ open: "'", close: "'" },
		{ open: '`', close: '`' }
	],
	surroundingPairs: [
		{ open: '{', close: '}' },
		{ open: '[', close: ']' },
		{ open: '(', close: ')' },
		{ open: '"', close: '"' },
		{ open: "'", close: "'" },
		{ open: '`', close: '`' }
	]
};

export const language = <languages.IMonarchLanguage>{
	defaultToken: '',
	tokenPostfix: '.perl',

	brackets: [
		{ token: 'delimiter.bracket', open: '{', close: '}' },
		{ token: 'delimiter.parenthesis', open: '(', close: ')' },
		{ token: 'delimiter.square', open: '[', close: ']' }
	],

	// https://learn.perl.org/docs/keywords.html

	// Perl syntax
	keywords: [
		'__DATA__',
		'else',
		'lock',
		'__END__',
		'elsif',
		'lt',
		'__FILE__',
		'eq',
		'__LINE__',
		'exp',
		'ne',
		'sub',
		'__PACKAGE__',
		'for',
		'no',
		'and',
		'foreach',
		'or',
		'unless',
		'cmp',
		'ge',
		'package',
		'until',
		'continue',
		'gt',
		'while',
		'CORE',
		'if',
		'xor',
		'do',
		'le',

		'__DIE__',
		'__WARN__'
	],

	// Perl functions
	builtinFunctions: [
		'-A',
		'END',
		'length',
		'setpgrp',
		'-B',
		'endgrent',
		'link',
		'setpriority',
		'-b',
		'endhostent',
		'listen',
		'setprotoent',
		'-C',
		'endnetent',
		'local',
		'setpwent',
		'-c',
		'endprotoent',
		'localtime',
		'setservent',
		'-d',
		'endpwent',
		'log',
		'setsockopt',
		'-e',
		'endservent',
		'lstat',
		'shift',
		'-f',
		'eof',
		'map',
		'shmctl',
		'-g',
		'eval',
		'mkdir',
		'shmget',
		'-k',
		'exec',
		'msgctl',
		'shmread',
		'-l',
		'exists',
		'msgget',
		'shmwrite',
		'-M',
		'exit',
		'msgrcv',
		'shutdown',
		'-O',
		'fcntl',
		'msgsnd',
		'sin',
		'-o',
		'fileno',
		'my',
		'sleep',
		'-p',
		'flock',
		'next',
		'socket',
		'-r',
		'fork',
		'not',
		'socketpair',
		'-R',
		'format',
		'oct',
		'sort',
		'-S',
		'formline',
		'open',
		'splice',
		'-s',
		'getc',
		'opendir',
		'split',
		'-T',
		'getgrent',
		'ord',
		'sprintf',
		'-t',
		'getgrgid',
		'our',
		'sqrt',
		'-u',
		'getgrnam',
		'pack',
		'srand',
		'-w',
		'gethostbyaddr',
		'pipe',
		'stat',
		'-W',
		'gethostbyname',
		'pop',
		'state',
		'-X',
		'gethostent',
		'pos',
		'study',
		'-x',
		'getlogin',
		'print',
		'substr',
		'-z',
		'getnetbyaddr',
		'printf',
		'symlink',
		'abs',
		'getnetbyname',
		'prototype',
		'syscall',
		'accept',
		'getnetent',
		'push',
		'sysopen',
		'alarm',
		'getpeername',
		'quotemeta',
		'sysread',
		'atan2',
		'getpgrp',
		'rand',
		'sysseek',
		'AUTOLOAD',
		'getppid',
		'read',
		'system',
		'BEGIN',
		'getpriority',
		'readdir',
		'syswrite',
		'bind',
		'getprotobyname',
		'readline',
		'tell',
		'binmode',
		'getprotobynumber',
		'readlink',
		'telldir',
		'bless',
		'getprotoent',
		'readpipe',
		'tie',
		'break',
		'getpwent',
		'recv',
		'tied',
		'caller',
		'getpwnam',
		'redo',
		'time',
		'chdir',
		'getpwuid',
		'ref',
		'times',
		'CHECK',
		'getservbyname',
		'rename',
		'truncate',
		'chmod',
		'getservbyport',
		'require',
		'uc',
		'chomp',
		'getservent',
		'reset',
		'ucfirst',
		'chop',
		'getsockname',
		'return',
		'umask',
		'chown',
		'getsockopt',
		'reverse',
		'undef',
		'chr',
		'glob',
		'rewinddir',
		'UNITCHECK',
		'chroot',
		'gmtime',
		'rindex',
		'unlink',
		'close',
		'goto',
		'rmdir',
		'unpack',
		'closedir',
		'grep',
		'say',
		'unshift',
		'connect',
		'hex',
		'scalar',
		'untie',
		'cos',
		'index',
		'seek',
		'use',
		'crypt',
		'INIT',
		'seekdir',
		'utime',
		'dbmclose',
		'int',
		'select',
		'values',
		'dbmopen',
		'ioctl',
		'semctl',
		'vec',
		'defined',
		'join',
		'semget',
		'wait',
		'delete',
		'keys',
		'semop',
		'waitpid',
		'DESTROY',
		'kill',
		'send',
		'wantarray',
		'die',
		'last',
		'setgrent',
		'warn',
		'dump',
		'lc',
		'sethostent',
		'write',
		'each',
		'lcfirst',
		'setnetent'
	],

	// File handlers
	builtinFileHandlers: ['ARGV', 'STDERR', 'STDOUT', 'ARGVOUT', 'STDIN', 'ENV'],

	// Perl variables
	builtinVariables: [
		'$!',
		'$^RE_TRIE_MAXBUF',
		'$LAST_REGEXP_CODE_RESULT',
		'$"',
		'$^S',
		'$LIST_SEPARATOR',
		'$#',
		'$^T',
		'$MATCH',
		'$$',
		'$^TAINT',
		'$MULTILINE_MATCHING',
		'$%',
		'$^UNICODE',
		'$NR',
		'$&',
		'$^UTF8LOCALE',
		'$OFMT',
		"$'",
		'$^V',
		'$OFS',
		'$(',
		'$^W',
		'$ORS',
		'$)',
		'$^WARNING_BITS',
		'$OS_ERROR',
		'$*',
		'$^WIDE_SYSTEM_CALLS',
		'$OSNAME',
		'$+',
		'$^X',
		'$OUTPUT_AUTO_FLUSH',
		'$,',
		'$_',
		'$OUTPUT_FIELD_SEPARATOR',
		'$-',
		'$`',
		'$OUTPUT_RECORD_SEPARATOR',
		'$.',
		'$a',
		'$PERL_VERSION',
		'$/',
		'$ACCUMULATOR',
		'$PERLDB',
		'$0',
		'$ARG',
		'$PID',
		'$:',
		'$ARGV',
		'$POSTMATCH',
		'$;',
		'$b',
		'$PREMATCH',
		'$<',
		'$BASETIME',
		'$PROCESS_ID',
		'$=',
		'$CHILD_ERROR',
		'$PROGRAM_NAME',
		'$>',
		'$COMPILING',
		'$REAL_GROUP_ID',
		'$?',
		'$DEBUGGING',
		'$REAL_USER_ID',
		'$@',
		'$EFFECTIVE_GROUP_ID',
		'$RS',
		'$[',
		'$EFFECTIVE_USER_ID',
		'$SUBSCRIPT_SEPARATOR',
		'$\\',
		'$EGID',
		'$SUBSEP',
		'$]',
		'$ERRNO',
		'$SYSTEM_FD_MAX',
		'$^',
		'$EUID',
		'$UID',
		'$^A',
		'$EVAL_ERROR',
		'$WARNING',
		'$^C',
		'$EXCEPTIONS_BEING_CAUGHT',
		'$|',
		'$^CHILD_ERROR_NATIVE',
		'$EXECUTABLE_NAME',
		'$~',
		'$^D',
		'$EXTENDED_OS_ERROR',
		'%!',
		'$^E',
		'$FORMAT_FORMFEED',
		'%^H',
		'$^ENCODING',
		'$FORMAT_LINE_BREAK_CHARACTERS',
		'%ENV',
		'$^F',
		'$FORMAT_LINES_LEFT',
		'%INC',
		'$^H',
		'$FORMAT_LINES_PER_PAGE',
		'%OVERLOAD',
		'$^I',
		'$FORMAT_NAME',
		'%SIG',
		'$^L',
		'$FORMAT_PAGE_NUMBER',
		'@+',
		'$^M',
		'$FORMAT_TOP_NAME',
		'@-',
		'$^N',
		'$GID',
		'@_',
		'$^O',
		'$INPLACE_EDIT',
		'@ARGV',
		'$^OPEN',
		'$INPUT_LINE_NUMBER',
		'@INC',
		'$^P',
		'$INPUT_RECORD_SEPARATOR',
		'@LAST_MATCH_START',
		'$^R',
		'$LAST_MATCH_END',
		'$^RE_DEBUG_FLAGS',
		'$LAST_PAREN_MATCH'
	],

	// operators
	symbols: /[:+\-\^*$&%@=<>!?|\/~\.]/,
	quoteLikeOps: ['qr', 'm', 's', 'q', 'qq', 'qx', 'qw', 'tr', 'y'],

	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,

	// The main tokenizer for our languages
	tokenizer: {
		root: [
			{ include: '@whitespace' },

			[
				/[a-zA-Z\-_][\w\-_]*/,
				{
					cases: {
						'@keywords': 'keyword',
						'@builtinFunctions': 'type.identifier',
						'@builtinFileHandlers': 'variable.predefined',
						'@quoteLikeOps': {
							token: '@rematch',
							next: 'quotedConstructs'
						},
						'@default': ''
					}
				}
			],

			// Perl variables
			[
				/[\$@%][*@#?\+\-\$!\w\\\^><~:;\.]+/,
				{
					cases: {
						'@builtinVariables': 'variable.predefined',
						'@default': 'variable'
					}
				}
			],

			{ include: '@strings' },
			{ include: '@dblStrings' },

			// Perl Doc
			{ include: '@perldoc' },

			// Here Doc
			{ include: '@heredoc' },

			[/[{}\[\]()]/, '@brackets'],

			// RegExp
			[/[\/](?:(?:\[(?:\\]|[^\]])+\])|(?:\\\/|[^\]\/]))*[\/]\w*\s*(?=[).,;]|$)/, 'regexp'],

			[/@symbols/, 'operators'],

			{ include: '@numbers' },

			[/[,;]/, 'delimiter']
		],

		whitespace: [
			[/\s+/, 'white'],
			[/(^#!.*$)/, 'metatag'],
			[/(^#.*$)/, 'comment']
		],

		numbers: [
			[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
			[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/, 'number.hex'],
			[/\d+/, 'number']
		],

		// Single quote string
		strings: [[/'/, 'string', '@stringBody']],

		stringBody: [
			[/'/, 'string', '@popall'],
			[/\\'/, 'string.escape'],
			[/./, 'string']
		],

		// Double quote string
		dblStrings: [[/"/, 'string', '@dblStringBody']],

		dblStringBody: [
			[/"/, 'string', '@popall'],
			[/@escapes/, 'string.escape'],
			[/\\./, 'string.escape.invalid'],
			{ include: '@variables' },
			[/./, 'string']
		],

		// Quoted constructs
		// Percent strings in Ruby are similar to quote-like operators in Perl.
		// This is adapted from pstrings in ../ruby/ruby.ts.
		quotedConstructs: [
			[/(q|qw|tr|y)\s*\(/, { token: 'string.delim', switchTo: '@qstring.(.)' }],
			[/(q|qw|tr|y)\s*\[/, { token: 'string.delim', switchTo: '@qstring.[.]' }],
			[/(q|qw|tr|y)\s*\{/, { token: 'string.delim', switchTo: '@qstring.{.}' }],
			[/(q|qw|tr|y)\s*</, { token: 'string.delim', switchTo: '@qstring.<.>' }],
			[/(q|qw|tr|y)#/, { token: 'string.delim', switchTo: '@qstring.#.#' }],
			[
				/(q|qw|tr|y)\s*([^A-Za-z0-9#\s])/,
				{ token: 'string.delim', switchTo: '@qstring.$2.$2' }
			],
			[/(q|qw|tr|y)\s+(\w)/, { token: 'string.delim', switchTo: '@qstring.$2.$2' }],

			[/(qr|m|s)\s*\(/, { token: 'regexp.delim', switchTo: '@qregexp.(.)' }],
			[/(qr|m|s)\s*\[/, { token: 'regexp.delim', switchTo: '@qregexp.[.]' }],
			[/(qr|m|s)\s*\{/, { token: 'regexp.delim', switchTo: '@qregexp.{.}' }],
			[/(qr|m|s)\s*</, { token: 'regexp.delim', switchTo: '@qregexp.<.>' }],
			[/(qr|m|s)#/, { token: 'regexp.delim', switchTo: '@qregexp.#.#' }],
			[
				/(qr|m|s)\s*([^A-Za-z0-9_#\s])/,
				{ token: 'regexp.delim', switchTo: '@qregexp.$2.$2' }
			],
			[/(qr|m|s)\s+(\w)/, { token: 'regexp.delim', switchTo: '@qregexp.$2.$2' }],

			[/(qq|qx)\s*\(/, { token: 'string.delim', switchTo: '@qqstring.(.)' }],
			[/(qq|qx)\s*\[/, { token: 'string.delim', switchTo: '@qqstring.[.]' }],
			[/(qq|qx)\s*\{/, { token: 'string.delim', switchTo: '@qqstring.{.}' }],
			[/(qq|qx)\s*</, { token: 'string.delim', switchTo: '@qqstring.<.>' }],
			[/(qq|qx)#/, { token: 'string.delim', switchTo: '@qqstring.#.#' }],
			[/(qq|qx)\s*([^A-Za-z0-9#\s])/, { token: 'string.delim', switchTo: '@qqstring.$2.$2' }],
			[/(qq|qx)\s+(\w)/, { token: 'string.delim', switchTo: '@qqstring.$2.$2' }]
		],

		// Non-expanded quoted string
		// qstring<open>.<close>
		//  open = open delimiter
		//  close = close delimiter
		qstring: [
			[/\\./, 'string.escape'],
			[
				/./,
				{
					cases: {
						'$#==$S3': { token: 'string.delim', next: '@pop' },
						'$#==$S2': { token: 'string.delim', next: '@push' }, // nested delimiters
						'@default': 'string'
					}
				}
			]
		],

		// Quoted regexp
		// qregexp.<open>.<close>
		//  open = open delimiter
		//  close = close delimiter
		qregexp: [
			{ include: '@variables' },
			[/\\./, 'regexp.escape'],
			[
				/./,
				{
					cases: {
						'$#==$S3': {
							token: 'regexp.delim',
							next: '@regexpModifiers'
						},
						'$#==$S2': { token: 'regexp.delim', next: '@push' }, // nested delimiters
						'@default': 'regexp'
					}
				}
			]
		],

		regexpModifiers: [[/[msixpodualngcer]+/, { token: 'regexp.modifier', next: '@popall' }]],

		// Expanded quoted string
		// qqstring.<open>.<close>
		//  open = open delimiter
		//  close = close delimiter
		qqstring: [{ include: '@variables' }, { include: '@qstring' }],

		heredoc: [
			[
				/<<\s*['"`]?([\w\-]+)['"`]?/,
				{ token: 'string.heredoc.delimiter', next: '@heredocBody.$1' }
			]
		],

		heredocBody: [
			[
				/^([\w\-]+)$/,
				{
					cases: {
						'$1==$S2': [
							{
								token: 'string.heredoc.delimiter',
								next: '@popall'
							}
						],
						'@default': 'string.heredoc'
					}
				}
			],
			[/./, 'string.heredoc']
		],

		perldoc: [[/^=\w/, 'comment.doc', '@perldocBody']],

		perldocBody: [
			[/^=cut\b/, 'type.identifier', '@popall'],
			[/./, 'comment.doc']
		],

		variables: [
			[/\$\w+/, 'variable'], // scalar
			[/@\w+/, 'variable'], // array
			[/%\w+/, 'variable'] // key/value
		]
	}
};