diff --git a/src/apex/apex.test.ts b/src/apex/apex.test.ts index 9c6c9b8f..5f9f6c8f 100644 --- a/src/apex/apex.test.ts +++ b/src/apex/apex.test.ts @@ -251,6 +251,41 @@ testTokenization('apex', [ ] }], + // Keywords with case variations + [{ + line: 'Package test; CLASS Program { Static void main(String[] args) {} } }', + tokens: [ + { startIndex: 0, type: 'keyword.Package.apex' }, + { startIndex: 7, type: '' }, + { startIndex: 8, type: 'identifier.apex' }, + { startIndex: 12, type: 'delimiter.apex' }, + { startIndex: 13, type: '' }, + { startIndex: 14, type: 'keyword.CLASS.apex' }, + { startIndex: 19, type: '' }, + { startIndex: 20, type: 'type.identifier.apex' }, + { startIndex: 27, type: '' }, + { startIndex: 28, type: 'delimiter.curly.apex' }, + { startIndex: 29, type: '' }, + { startIndex: 30, type: 'keyword.Static.apex' }, + { startIndex: 36, type: '' }, + { startIndex: 37, type: 'keyword.void.apex' }, + { startIndex: 41, type: '' }, + { startIndex: 42, type: 'identifier.apex' }, + { startIndex: 46, type: 'delimiter.parenthesis.apex' }, + { startIndex: 47, type: 'type.identifier.apex' }, + { startIndex: 53, type: 'delimiter.square.apex' }, + { startIndex: 55, type: '' }, + { startIndex: 56, type: 'identifier.apex' }, + { startIndex: 60, type: 'delimiter.parenthesis.apex' }, + { startIndex: 61, type: '' }, + { startIndex: 62, type: 'delimiter.curly.apex' }, + { startIndex: 64, type: '' }, + { startIndex: 65, type: 'delimiter.curly.apex' }, + { startIndex: 66, type: '' }, + { startIndex: 67, type: 'delimiter.curly.apex' } + ] + }], + // Numbers [{ line: '0', diff --git a/src/apex/apex.ts b/src/apex/apex.ts index b22fd9b4..c02eddd9 100644 --- a/src/apex/apex.ts +++ b/src/apex/apex.ts @@ -43,153 +43,166 @@ export const conf: IRichLanguageConfiguration = { } }; +const keywords = [ + 'abstract', + 'activate', + 'and', + 'any', + 'array', + 'as', + 'asc', + 'assert', + 'autonomous', + 'begin', + 'bigdecimal', + 'blob', + 'boolean', + 'break', + 'bulk', + 'by', + 'case', + 'cast', + 'catch', + 'char', + 'class', + 'collect', + 'commit', + 'const', + 'continue', + 'convertcurrency', + 'decimal', + 'default', + 'delete', + 'desc', + 'do', + 'double', + 'else', + 'end', + 'enum', + 'exception', + 'exit', + 'export', + 'extends', + 'false', + 'final', + 'finally', + 'float', + 'for', + 'from', + 'future', + 'get', + 'global', + 'goto', + 'group', + 'having', + 'hint', + 'if', + 'implements', + 'import', + 'in', + 'inner', + 'insert', + 'instanceof', + 'int', + 'interface', + 'into', + 'join', + 'last_90_days', + 'last_month', + 'last_n_days', + 'last_week', + 'like', + 'limit', + 'list', + 'long', + 'loop', + 'map', + 'merge', + 'native', + 'new', + 'next_90_days', + 'next_month', + 'next_n_days', + 'next_week', + 'not', + 'null', + 'nulls', + 'number', + 'object', + 'of', + 'on', + 'or', + 'outer', + 'override', + 'package', + 'parallel', + 'pragma', + 'private', + 'protected', + 'public', + 'retrieve', + 'return', + 'returning', + 'rollback', + 'savepoint', + 'search', + 'select', + 'set', + 'short', + 'sort', + 'stat', + 'static', + 'strictfp', + 'super', + 'switch', + 'synchronized', + 'system', + 'testmethod', + 'then', + 'this', + 'this_month', + 'this_week', + 'throw', + 'throws', + 'today', + 'tolabel', + 'tomorrow', + 'transaction', + 'transient', + 'trigger', + 'true', + 'try', + 'type', + 'undelete', + 'update', + 'upsert', + 'using', + 'virtual', + 'void', + 'volatile', + 'webservice', + 'when', + 'where', + 'while', + 'yesterday' +]; + +// create case variations of the keywords - apex is case insensitive, but we can't make the highlighter case insensitive +// because we use a heuristic to assume that identifiers starting with an upper case letter are types. +const uppercaseFirstLetter = (lowercase) => lowercase.charAt(0).toUpperCase() + lowercase.substr(1); + +let keywordsWithCaseVariations = []; +keywords.forEach(lowercase => { + keywordsWithCaseVariations.push(lowercase); + keywordsWithCaseVariations.push(lowercase.toUpperCase()); + keywordsWithCaseVariations.push(uppercaseFirstLetter(lowercase)); +}) + export const language = { defaultToken: '', tokenPostfix: '.apex', - keywords: [ - 'abstract', - 'activate', - 'and', - 'any', - 'array', - 'as', - 'asc', - 'assert', - 'autonomous', - 'begin', - 'bigdecimal', - 'blob', - 'boolean', - 'break', - 'bulk', - 'by', - 'case', - 'cast', - 'catch', - 'char', - 'class', - 'collect', - 'commit', - 'const', - 'continue', - 'convertcurrency', - 'decimal', - 'default', - 'delete', - 'desc', - 'do', - 'double', - 'else', - 'end', - 'enum', - 'exception', - 'exit', - 'export', - 'extends', - 'false', - 'final', - 'finally', - 'float', - 'for', - 'from', - 'future', - 'get', - 'global', - 'goto', - 'group', - 'having', - 'hint', - 'if', - 'implements', - 'import', - 'in', - 'inner', - 'insert', - 'instanceof', - 'int', - 'interface', - 'into', - 'join', - 'last_90_days', - 'last_month', - 'last_n_days', - 'last_week', - 'like', - 'limit', - 'list', - 'long', - 'loop', - 'map', - 'merge', - 'native', - 'new', - 'next_90_days', - 'next_month', - 'next_n_days', - 'next_week', - 'not', - 'null', - 'nulls', - 'number', - 'object', - 'of', - 'on', - 'or', - 'outer', - 'override', - 'package', - 'parallel', - 'pragma', - 'private', - 'protected', - 'public', - 'retrieve', - 'return', - 'returning', - 'rollback', - 'savepoint', - 'search', - 'select', - 'set', - 'short', - 'sort', - 'stat', - 'static', - 'strictfp', - 'super', - 'switch', - 'synchronized', - 'system', - 'testmethod', - 'then', - 'this', - 'this_month', - 'this_week', - 'throw', - 'throws', - 'today', - 'tolabel', - 'tomorrow', - 'transaction', - 'transient', - 'trigger', - 'true', - 'try', - 'type', - 'undelete', - 'update', - 'upsert', - 'using', - 'virtual', - 'void', - 'volatile', - 'webservice', - 'when', - 'where', - 'while', - 'yesterday' - ], + keywords: keywordsWithCaseVariations, operators: [ '=', '>', '<', '!', '~', '?', ':',