ruby-spec.js 86 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. describe("TextMate Ruby grammar", function() {
  2. let grammar = null;
  3. beforeEach(function() {
  4. atom.config.set('core.useTreeSitterParsers', false);
  5. waitsForPromise(() => atom.packages.activatePackage("language-ruby"));
  6. runs(() => grammar = atom.grammars.grammarForScopeName("source.ruby"));
  7. });
  8. it("parses the grammar", function() {
  9. expect(grammar).toBeTruthy();
  10. expect(grammar.scopeName).toBe("source.ruby");
  11. });
  12. it("tokenizes self", function() {
  13. const {tokens} = grammar.tokenizeLine('self');
  14. expect(tokens[0]).toEqual({value: 'self', scopes: ['source.ruby', 'variable.language.self.ruby']});
  15. });
  16. it("tokenizes special functions", function() {
  17. let {tokens} = grammar.tokenizeLine('require "."');
  18. expect(tokens[0]).toEqual({value: 'require', scopes: ['source.ruby', 'meta.require.ruby', 'keyword.other.special-method.ruby']});
  19. ({tokens} = grammar.tokenizeLine('Kernel.require "."'));
  20. expect(tokens[1]).toEqual({value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  21. expect(tokens[2]).toEqual({value: 'require ', scopes: ['source.ruby']});
  22. ({tokens} = grammar.tokenizeLine('Kernel::require "."'));
  23. expect(tokens[1]).toEqual({value: '::', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  24. expect(tokens[2]).toEqual({value: 'require ', scopes: ['source.ruby']});
  25. ({tokens} = grammar.tokenizeLine('thing&.call'));
  26. expect(tokens[1]).toEqual({value: '&.', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  27. expect(tokens[2]).toEqual({value: 'call', scopes: ['source.ruby']});
  28. });
  29. it("tokenizes variable constants", function() {
  30. let {tokens} = grammar.tokenizeLine('VAR1 = 100');
  31. expect(tokens[0]).toEqual({value: 'VAR1', scopes: ['source.ruby', 'variable.other.constant.ruby']});
  32. ({tokens} = grammar.tokenizeLine('_VAR2 = 200'));
  33. expect(tokens[0]).toEqual({value: '_VAR2', scopes: ['source.ruby', 'variable.other.constant.ruby']});
  34. });
  35. it("tokenizes decimal numbers", function() {
  36. let {tokens} = grammar.tokenizeLine('100_000');
  37. expect(tokens[0]).toEqual({value: '100_000', scopes: ['source.ruby', 'constant.numeric.ruby']});
  38. ({tokens} = grammar.tokenizeLine('0'));
  39. expect(tokens[0]).toEqual({value: '0', scopes: ['source.ruby', 'constant.numeric.ruby']});
  40. ({tokens} = grammar.tokenizeLine('1.23'));
  41. expect(tokens[0]).toEqual({value: '1.23', scopes: ['source.ruby', 'constant.numeric.ruby']});
  42. ({tokens} = grammar.tokenizeLine('1.23e-4'));
  43. expect(tokens[0]).toEqual({value: '1.23e-4', scopes: ['source.ruby', 'constant.numeric.ruby']});
  44. ({tokens} = grammar.tokenizeLine('0d100_000'));
  45. expect(tokens[0]).toEqual({value: '0d100_000', scopes: ['source.ruby', 'constant.numeric.ruby']});
  46. });
  47. it("tokenizes hexadecimal numbers", function() {
  48. let {tokens} = grammar.tokenizeLine('0xAFFF');
  49. expect(tokens[0]).toEqual({value: '0xAFFF', scopes: ['source.ruby', 'constant.numeric.ruby']});
  50. ({tokens} = grammar.tokenizeLine('0XA_FFF'));
  51. expect(tokens[0]).toEqual({value: '0XA_FFF', scopes: ['source.ruby', 'constant.numeric.ruby']});
  52. });
  53. it("tokenizes octal numbers", function() {
  54. let {tokens} = grammar.tokenizeLine('01_777');
  55. expect(tokens[0]).toEqual({value: '01_777', scopes: ['source.ruby', 'constant.numeric.ruby']});
  56. ({tokens} = grammar.tokenizeLine('0o1_777'));
  57. expect(tokens[0]).toEqual({value: '0o1_777', scopes: ['source.ruby', 'constant.numeric.ruby']});
  58. });
  59. it("tokenizes binary numbers", function() {
  60. let {tokens} = grammar.tokenizeLine('0b100_000');
  61. expect(tokens[0]).toEqual({value: '0b100_000', scopes: ['source.ruby', 'constant.numeric.ruby']});
  62. ({tokens} = grammar.tokenizeLine('0B00100'));
  63. expect(tokens[0]).toEqual({value: '0B00100', scopes: ['source.ruby', 'constant.numeric.ruby']});
  64. });
  65. it("tokenizes symbols", function() {
  66. let {tokens} = grammar.tokenizeLine(':test');
  67. expect(tokens[0]).toEqual({value: ':', scopes: ['source.ruby', 'constant.other.symbol.ruby', 'punctuation.definition.constant.ruby']});
  68. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'constant.other.symbol.ruby']});
  69. ({tokens} = grammar.tokenizeLine(':$symbol'));
  70. expect(tokens[0]).toEqual({value: ':', scopes: ['source.ruby', 'constant.other.symbol.ruby', 'punctuation.definition.constant.ruby']});
  71. expect(tokens[1]).toEqual({value: '$symbol', scopes: ['source.ruby', 'constant.other.symbol.ruby']});
  72. ({tokens} = grammar.tokenizeLine(':<=>'));
  73. expect(tokens[0]).toEqual({value: ':', scopes: ['source.ruby', 'constant.other.symbol.ruby', 'punctuation.definition.constant.ruby']});
  74. expect(tokens[1]).toEqual({value: '<=>', scopes: ['source.ruby', 'constant.other.symbol.ruby']});
  75. });
  76. it("tokenizes symbol as hash key (1.9 syntax)", function() {
  77. const {tokens} = grammar.tokenizeLine('foo: 1');
  78. expect(tokens[0]).toEqual({value: 'foo', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby']});
  79. expect(tokens[1]).toEqual({value: ':', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby', 'punctuation.definition.constant.hashkey.ruby']});
  80. expect(tokens[2]).toEqual({value: ' ', scopes: ['source.ruby']});
  81. expect(tokens[3]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  82. });
  83. it("tokenizes symbol as hash key (1.8 syntax)", function() {
  84. const {tokens} = grammar.tokenizeLine(':foo => 1');
  85. expect(tokens[0]).toEqual({value: ':', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby', 'punctuation.definition.constant.ruby']});
  86. expect(tokens[1]).toEqual({value: 'foo', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby']});
  87. expect(tokens[2]).toEqual({value: ' ', scopes: ['source.ruby']});
  88. expect(tokens[3]).toEqual({value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby']});
  89. expect(tokens[4]).toEqual({value: ' ', scopes: ['source.ruby']});
  90. expect(tokens[5]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  91. });
  92. it("tokenizes :: separators", function() {
  93. let {tokens} = grammar.tokenizeLine('File::read "test"');
  94. expect(tokens[0]).toEqual({value: 'File', scopes: ['source.ruby', 'support.class.ruby']});
  95. expect(tokens[1]).toEqual({value: '::', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  96. expect(tokens[2]).toEqual({value: 'read ', scopes: ['source.ruby']});
  97. ({tokens} = grammar.tokenizeLine('File:: read "test"'));
  98. expect(tokens[0]).toEqual({value: 'File', scopes: ['source.ruby', 'variable.other.constant.ruby']});
  99. expect(tokens[1]).toEqual({value: '::', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  100. expect(tokens[2]).toEqual({value: ' read ', scopes: ['source.ruby']});
  101. ({tokens} = grammar.tokenizeLine('RbConfig::CONFIG'));
  102. expect(tokens[0]).toEqual({value: 'RbConfig', scopes: ['source.ruby', 'support.class.ruby']});
  103. expect(tokens[1]).toEqual({value: '::', scopes: ['source.ruby', 'punctuation.separator.namespace.ruby']});
  104. expect(tokens[2]).toEqual({value: 'CONFIG', scopes: ['source.ruby', 'variable.other.constant.ruby']});
  105. ({tokens} = grammar.tokenizeLine('RbConfig:: CONFIG'));
  106. expect(tokens[0]).toEqual({value: 'RbConfig', scopes: ['source.ruby', 'variable.other.constant.ruby']});
  107. expect(tokens[1]).toEqual({value: '::', scopes: ['source.ruby', 'punctuation.separator.namespace.ruby']});
  108. expect(tokens[2]).toEqual({value: ' ', scopes: ['source.ruby']});
  109. expect(tokens[3]).toEqual({value: 'CONFIG', scopes: ['source.ruby', 'variable.other.constant.ruby']});
  110. ({tokens} = grammar.tokenizeLine('class A::B::C < ::D::E'));
  111. expect(tokens[0]).toEqual({value: 'class', scopes: ['source.ruby', 'meta.class.ruby', 'keyword.control.class.ruby']});
  112. expect(tokens[2]).toEqual({value: 'A', scopes: ['source.ruby', 'meta.class.ruby', 'entity.name.type.class.ruby']});
  113. expect(tokens[3]).toEqual({value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.separator.namespace.ruby']});
  114. expect(tokens[4]).toEqual({value: 'B', scopes: ['source.ruby', 'meta.class.ruby', 'entity.name.type.class.ruby']});
  115. expect(tokens[5]).toEqual({value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.separator.namespace.ruby']});
  116. expect(tokens[6]).toEqual({value: 'C', scopes: ['source.ruby', 'meta.class.ruby', 'entity.name.type.class.ruby']});
  117. expect(tokens[8]).toEqual({value: '<', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.separator.inheritance.ruby']});
  118. expect(tokens[10]).toEqual({value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'punctuation.separator.namespace.ruby']});
  119. expect(tokens[11]).toEqual({value: 'D', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'entity.name.type.class.ruby']});
  120. expect(tokens[12]).toEqual({value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'punctuation.separator.namespace.ruby']});
  121. expect(tokens[13]).toEqual({value: 'E', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'entity.name.type.class.ruby']});
  122. ({tokens} = grammar.tokenizeLine('class << A::B'));
  123. expect(tokens[0]).toEqual({value: 'class', scopes: ['source.ruby', 'meta.class.ruby', 'keyword.control.class.ruby']});
  124. expect(tokens[2]).toEqual({value: '<<', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.definition.variable.ruby']});
  125. expect(tokens[4]).toEqual({value: 'A', scopes: ['source.ruby', 'meta.class.ruby', 'variable.other.object.ruby', 'entity.name.type.class.ruby']});
  126. expect(tokens[5]).toEqual({value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'variable.other.object.ruby', 'punctuation.separator.namespace.ruby']});
  127. expect(tokens[6]).toEqual({value: 'B', scopes: ['source.ruby', 'meta.class.ruby', 'variable.other.object.ruby', 'entity.name.type.class.ruby']});
  128. ({tokens} = grammar.tokenizeLine('module A::B::C'));
  129. expect(tokens[0]).toEqual({value: 'module', scopes: ['source.ruby', 'meta.module.ruby', 'keyword.control.module.ruby']});
  130. expect(tokens[2]).toEqual({value: 'A', scopes: ['source.ruby', 'meta.module.ruby', 'entity.other.inherited-class.module.ruby']});
  131. expect(tokens[3]).toEqual({value: '::', scopes: ['source.ruby', 'meta.module.ruby', 'punctuation.separator.namespace.ruby']});
  132. expect(tokens[4]).toEqual({value: 'B', scopes: ['source.ruby', 'meta.module.ruby', 'entity.other.inherited-class.module.ruby']});
  133. expect(tokens[5]).toEqual({value: '::', scopes: ['source.ruby', 'meta.module.ruby', 'punctuation.separator.namespace.ruby']});
  134. expect(tokens[6]).toEqual({value: 'C', scopes: ['source.ruby', 'meta.module.ruby', 'entity.name.type.module.ruby']});
  135. });
  136. it("tokenizes . separator", function() {
  137. let {tokens} = grammar.tokenizeLine('File.read "test"');
  138. expect(tokens[0]).toEqual({value: 'File', scopes: ['source.ruby', 'support.class.ruby']});
  139. expect(tokens[1]).toEqual({value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  140. expect(tokens[2]).toEqual({value: 'read ', scopes: ['source.ruby']});
  141. ({tokens} = grammar.tokenizeLine('File. read "test"'));
  142. expect(tokens[0]).toEqual({value: 'File', scopes: ['source.ruby', 'variable.other.constant.ruby']});
  143. expect(tokens[1]).toEqual({value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  144. expect(tokens[2]).toEqual({value: ' read ', scopes: ['source.ruby']});
  145. ({tokens} = grammar.tokenizeLine('def a.b(*args)'));
  146. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  147. expect(tokens[2]).toEqual({value: 'a', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  148. expect(tokens[3]).toEqual({value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby']});
  149. expect(tokens[4]).toEqual({value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  150. expect(tokens[5]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  151. expect(tokens[6]).toEqual({value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby']});
  152. expect(tokens[7]).toEqual({value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby']});
  153. expect(tokens[8]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  154. ({tokens} = grammar.tokenizeLine('def a.b *args'));
  155. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  156. expect(tokens[2]).toEqual({value: 'a', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  157. expect(tokens[3]).toEqual({value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby']});
  158. expect(tokens[4]).toEqual({value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  159. expect(tokens[6]).toEqual({value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby']});
  160. expect(tokens[7]).toEqual({value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby']});
  161. ({tokens} = grammar.tokenizeLine('def a.b'));
  162. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'keyword.control.def.ruby']});
  163. expect(tokens[2]).toEqual({value: 'a', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby']});
  164. expect(tokens[3]).toEqual({value: '.', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby']});
  165. expect(tokens[4]).toEqual({value: 'b', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby']});
  166. ({tokens} = grammar.tokenizeLine('def self.b(*args)'));
  167. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  168. expect(tokens[2]).toEqual({value: 'self', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'variable.language.self.ruby']});
  169. expect(tokens[3]).toEqual({value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby']});
  170. expect(tokens[4]).toEqual({value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  171. expect(tokens[5]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  172. expect(tokens[6]).toEqual({value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby']});
  173. expect(tokens[7]).toEqual({value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby']});
  174. expect(tokens[8]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  175. ({tokens} = grammar.tokenizeLine('def self.b *args'));
  176. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  177. expect(tokens[2]).toEqual({value: 'self', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'variable.language.self.ruby']});
  178. expect(tokens[3]).toEqual({value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby']});
  179. expect(tokens[4]).toEqual({value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  180. expect(tokens[6]).toEqual({value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby']});
  181. expect(tokens[7]).toEqual({value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby']});
  182. ({tokens} = grammar.tokenizeLine('def self.b'));
  183. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'keyword.control.def.ruby']});
  184. expect(tokens[2]).toEqual({value: 'self', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby', 'variable.language.self.ruby']});
  185. expect(tokens[3]).toEqual({value: '.', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby']});
  186. expect(tokens[4]).toEqual({value: 'b', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby']});
  187. });
  188. it("tokenizes , separator", function() {
  189. let {tokens} = grammar.tokenizeLine('hash = {1 => \'one\', 2 => \'two\'}');
  190. expect(tokens[0]).toEqual({value: 'hash ', scopes: ['source.ruby']});
  191. expect(tokens[1]).toEqual({value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby']});
  192. expect(tokens[3]).toEqual({value: '{', scopes: ['source.ruby', 'punctuation.section.scope.begin.ruby']});
  193. expect(tokens[4]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  194. expect(tokens[6]).toEqual({value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby']});
  195. expect(tokens[8]).toEqual({value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.begin.ruby']});
  196. expect(tokens[9]).toEqual({value: 'one', scopes: ['source.ruby', 'string.quoted.single.ruby']});
  197. expect(tokens[10]).toEqual({value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.end.ruby']});
  198. expect(tokens[11]).toEqual({value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby']});
  199. expect(tokens[13]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  200. expect(tokens[15]).toEqual({value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby']});
  201. expect(tokens[17]).toEqual({value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.begin.ruby']});
  202. expect(tokens[18]).toEqual({value: 'two', scopes: ['source.ruby', 'string.quoted.single.ruby']});
  203. expect(tokens[19]).toEqual({value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.end.ruby']});
  204. expect(tokens[20]).toEqual({value: '}', scopes: ['source.ruby', 'punctuation.section.scope.end.ruby']});
  205. ({tokens} = grammar.tokenizeLine('method(a,b)'));
  206. expect(tokens[0]).toEqual({value: 'method', scopes: ['source.ruby']});
  207. expect(tokens[1]).toEqual({value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  208. expect(tokens[2]).toEqual({value: 'a', scopes: ['source.ruby']});
  209. expect(tokens[3]).toEqual({value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby']});
  210. expect(tokens[4]).toEqual({value: 'b', scopes: ['source.ruby']});
  211. expect(tokens[5]).toEqual({value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  212. });
  213. it("tokenizes %() style strings", function() {
  214. const {tokens} = grammar.tokenizeLine('%(te(s)t)');
  215. expect(tokens[0]).toEqual({value: '%(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby']});
  216. expect(tokens[1]).toEqual({value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  217. expect(tokens[2]).toEqual({value: '(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  218. expect(tokens[3]).toEqual({value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  219. expect(tokens[4]).toEqual({value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  220. expect(tokens[5]).toEqual({value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  221. expect(tokens[6]).toEqual({value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby']});
  222. });
  223. it("tokenizes %[] style strings", function() {
  224. const {tokens} = grammar.tokenizeLine('%[te[s]t]');
  225. expect(tokens[0]).toEqual({value: '%[', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby']});
  226. expect(tokens[1]).toEqual({value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  227. expect(tokens[2]).toEqual({value: '[', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  228. expect(tokens[3]).toEqual({value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  229. expect(tokens[4]).toEqual({value: ']', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  230. expect(tokens[5]).toEqual({value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  231. expect(tokens[6]).toEqual({value: ']', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby']});
  232. });
  233. it("tokenizes %{} style strings", function() {
  234. const {tokens} = grammar.tokenizeLine('%{te{s}t}');
  235. expect(tokens[0]).toEqual({value: '%{', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby']});
  236. expect(tokens[1]).toEqual({value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  237. expect(tokens[2]).toEqual({value: '{', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  238. expect(tokens[3]).toEqual({value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  239. expect(tokens[4]).toEqual({value: '}', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  240. expect(tokens[5]).toEqual({value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  241. expect(tokens[6]).toEqual({value: '}', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby']});
  242. });
  243. it("tokenizes %<> style strings", function() {
  244. const {tokens} = grammar.tokenizeLine('%<te<s>t>');
  245. expect(tokens[0]).toEqual({value: '%<', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby']});
  246. expect(tokens[1]).toEqual({value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  247. expect(tokens[2]).toEqual({value: '<', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  248. expect(tokens[3]).toEqual({value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  249. expect(tokens[4]).toEqual({value: '>', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  250. expect(tokens[5]).toEqual({value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  251. expect(tokens[6]).toEqual({value: '>', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby']});
  252. });
  253. it("tokenizes %~~ style strings", function() {
  254. const {tokens} = grammar.tokenizeLine('%~te\\~s\\~t~');
  255. expect(tokens[0]).toEqual({value: '%~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby']});
  256. expect(tokens[1]).toEqual({value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  257. expect(tokens[2]).toEqual({value: '\\~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'constant.character.escape.ruby']});
  258. expect(tokens[3]).toEqual({value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  259. expect(tokens[4]).toEqual({value: '\\~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'constant.character.escape.ruby']});
  260. expect(tokens[5]).toEqual({value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  261. expect(tokens[6]).toEqual({value: '~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby']});
  262. });
  263. it("tokenizes %Q() style strings", function() {
  264. const {tokens} = grammar.tokenizeLine('%Q(te(s)t)');
  265. expect(tokens[0]).toEqual({value: '%Q(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby']});
  266. expect(tokens[1]).toEqual({value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  267. expect(tokens[2]).toEqual({value: '(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  268. expect(tokens[3]).toEqual({value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  269. expect(tokens[4]).toEqual({value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby']});
  270. expect(tokens[5]).toEqual({value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby']});
  271. expect(tokens[6]).toEqual({value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby']});
  272. });
  273. it("tokenizes %x!! style strings", function() {
  274. const {tokens} = grammar.tokenizeLine('%x!\#\{"l" + "s"\}!');
  275. expect(tokens[0]).toEqual({value: '%x!', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby']});
  276. expect(tokens[1]).toEqual({value: '#{', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'meta.embedded.line.ruby', 'punctuation.section.embedded.begin.ruby']});
  277. expect(tokens[11]).toEqual({value: '}', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'meta.embedded.line.ruby', 'punctuation.section.embedded.end.ruby']});
  278. expect(tokens[12]).toEqual({value: '!', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby']});
  279. });
  280. it("tokenizes regular expressions", function() {
  281. let {tokens} = grammar.tokenizeLine('/test/');
  282. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  283. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  284. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  285. ({tokens} = grammar.tokenizeLine('/{w}/'));
  286. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  287. expect(tokens[1]).toEqual({value: '{w}', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  288. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  289. ({tokens} = grammar.tokenizeLine('a_method /test/'));
  290. expect(tokens[0]).toEqual({value: 'a_method ', scopes: ['source.ruby']});
  291. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  292. expect(tokens[2]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  293. expect(tokens[3]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  294. ({tokens} = grammar.tokenizeLine('a_method(/test/)'));
  295. expect(tokens[0]).toEqual({value: 'a_method', scopes: ['source.ruby']});
  296. expect(tokens[1]).toEqual({value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  297. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  298. expect(tokens[3]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  299. expect(tokens[4]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  300. expect(tokens[5]).toEqual({value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  301. ({tokens} = grammar.tokenizeLine('/test/.match("test")'));
  302. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  303. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  304. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  305. expect(tokens[3]).toEqual({value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  306. ({tokens} = grammar.tokenizeLine('foo(4 / 2).split(/c/)'));
  307. expect(tokens[0]).toEqual({value: 'foo', scopes: ['source.ruby']});
  308. expect(tokens[1]).toEqual({value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  309. expect(tokens[2]).toEqual({value: '4', scopes: ['source.ruby', 'constant.numeric.ruby']});
  310. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  311. expect(tokens[4]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  312. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  313. expect(tokens[6]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  314. expect(tokens[7]).toEqual({value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  315. expect(tokens[8]).toEqual({value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby']});
  316. expect(tokens[9]).toEqual({value: 'split', scopes: ['source.ruby']});
  317. expect(tokens[10]).toEqual({value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  318. expect(tokens[11]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  319. expect(tokens[12]).toEqual({value: 'c', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  320. expect(tokens[13]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  321. expect(tokens[14]).toEqual({value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  322. ({tokens} = grammar.tokenizeLine('[/test/,3]'));
  323. expect(tokens[0]).toEqual({value: '[', scopes: ['source.ruby', 'punctuation.section.array.begin.ruby']});
  324. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  325. expect(tokens[2]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  326. expect(tokens[3]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  327. expect(tokens[4]).toEqual({value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby']});
  328. ({tokens} = grammar.tokenizeLine('[/test/]'));
  329. expect(tokens[0]).toEqual({value: '[', scopes: ['source.ruby', 'punctuation.section.array.begin.ruby']});
  330. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  331. expect(tokens[2]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  332. expect(tokens[3]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  333. ({tokens} = grammar.tokenizeLine('/test/ && 4'));
  334. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  335. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  336. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  337. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  338. ({tokens} = grammar.tokenizeLine('/test/ || 4'));
  339. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  340. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  341. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  342. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  343. ({tokens} = grammar.tokenizeLine('/test/ ? 4 : 3'));
  344. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  345. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  346. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  347. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  348. ({tokens} = grammar.tokenizeLine('/test/ : foo'));
  349. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  350. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  351. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  352. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  353. ({tokens} = grammar.tokenizeLine('{a: /test/}'));
  354. expect(tokens[4]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  355. expect(tokens[5]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  356. expect(tokens[6]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  357. ({tokens} = grammar.tokenizeLine('if "test" =~ /test/ then 4 end'));
  358. expect(tokens[8]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  359. expect(tokens[9]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  360. expect(tokens[10]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  361. expect(tokens[11]).toEqual({value: ' ', scopes: ['source.ruby']});
  362. expect(tokens[12]).toEqual({value: 'then', scopes: ['source.ruby', 'keyword.control.ruby']});
  363. ({tokens} = grammar.tokenizeLine('if "test" =~ /test/; 4 end'));
  364. expect(tokens[8]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  365. expect(tokens[9]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  366. expect(tokens[10]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  367. expect(tokens[11]).toEqual({value: ';', scopes: ['source.ruby', 'punctuation.terminator.statement.ruby']});
  368. ({tokens} = grammar.tokenizeLine('/test/ =~ "test"'));
  369. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  370. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  371. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  372. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  373. expect(tokens[4]).toEqual({value: '=~', scopes: ['source.ruby', 'keyword.operator.comparison.ruby']});
  374. ({tokens} = grammar.tokenizeLine('/test/ !~ "test"'));
  375. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  376. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  377. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  378. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  379. expect(tokens[4]).toEqual({value: '!~', scopes: ['source.ruby', 'keyword.operator.comparison.ruby']});
  380. ({tokens} = grammar.tokenizeLine('/test/ != "test"'));
  381. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  382. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  383. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  384. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  385. expect(tokens[4]).toEqual({value: '!=', scopes: ['source.ruby', 'keyword.operator.comparison.ruby']});
  386. ({tokens} = grammar.tokenizeLine('/test/ == /test/'));
  387. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  388. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  389. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  390. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  391. expect(tokens[4]).toEqual({value: '==', scopes: ['source.ruby', 'keyword.operator.comparison.ruby']});
  392. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  393. expect(tokens[6]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  394. expect(tokens[7]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  395. expect(tokens[8]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  396. ({tokens} = grammar.tokenizeLine('/test/ === /test/'));
  397. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  398. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  399. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  400. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  401. expect(tokens[4]).toEqual({value: '===', scopes: ['source.ruby', 'keyword.operator.comparison.ruby']});
  402. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  403. expect(tokens[6]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  404. expect(tokens[7]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  405. expect(tokens[8]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  406. ({tokens} = grammar.tokenizeLine('if false then /test/ else 4 end'));
  407. expect(tokens[4]).toEqual({value: 'then', scopes: ['source.ruby', 'keyword.control.ruby']});
  408. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  409. expect(tokens[6]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  410. expect(tokens[7]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  411. expect(tokens[8]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  412. expect(tokens[9]).toEqual({value: ' ', scopes: ['source.ruby']});
  413. expect(tokens[10]).toEqual({value: 'else', scopes: ['source.ruby', 'keyword.control.ruby']});
  414. ({tokens} = grammar.tokenizeLine('if false then 4 else /test/ end'));
  415. expect(tokens[8]).toEqual({value: 'else', scopes: ['source.ruby', 'keyword.control.ruby']});
  416. expect(tokens[9]).toEqual({value: ' ', scopes: ['source.ruby']});
  417. expect(tokens[10]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  418. expect(tokens[11]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  419. expect(tokens[12]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  420. expect(tokens[13]).toEqual({value: ' ', scopes: ['source.ruby']});
  421. expect(tokens[14]).toEqual({value: 'end', scopes: ['source.ruby', 'keyword.control.ruby']});
  422. ({tokens} = grammar.tokenizeLine('if true then /test/ elsif false then 4 end'));
  423. expect(tokens[4]).toEqual({value: 'then', scopes: ['source.ruby', 'keyword.control.ruby']});
  424. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  425. expect(tokens[6]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  426. expect(tokens[7]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  427. expect(tokens[8]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  428. expect(tokens[9]).toEqual({value: ' ', scopes: ['source.ruby']});
  429. expect(tokens[10]).toEqual({value: 'elsif', scopes: ['source.ruby', 'keyword.control.ruby']});
  430. ({tokens} = grammar.tokenizeLine('method /test/ do; end'));
  431. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  432. expect(tokens[2]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  433. expect(tokens[3]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  434. expect(tokens[4]).toEqual({value: ' ', scopes: ['source.ruby']});
  435. expect(tokens[5]).toEqual({value: 'do', scopes: ['source.ruby', 'keyword.control.start-block.ruby']});
  436. ({tokens} = grammar.tokenizeLine('/test/ if true'));
  437. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  438. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  439. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  440. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  441. expect(tokens[4]).toEqual({value: 'if', scopes: ['source.ruby', 'keyword.control.ruby']});
  442. ({tokens} = grammar.tokenizeLine('/test/ unless true'));
  443. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  444. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  445. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  446. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  447. expect(tokens[4]).toEqual({value: 'unless', scopes: ['source.ruby', 'keyword.control.ruby']});
  448. ({tokens} = grammar.tokenizeLine('/test/ while true'));
  449. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  450. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  451. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  452. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  453. expect(tokens[4]).toEqual({value: 'while', scopes: ['source.ruby', 'keyword.control.ruby']});
  454. ({tokens} = grammar.tokenizeLine('/test/ until true'));
  455. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  456. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  457. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  458. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  459. expect(tokens[4]).toEqual({value: 'until', scopes: ['source.ruby', 'keyword.control.ruby']});
  460. ({tokens} = grammar.tokenizeLine('/test/ or return'));
  461. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  462. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  463. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  464. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  465. expect(tokens[4]).toEqual({value: 'or', scopes: ['source.ruby', 'keyword.operator.logical.ruby']});
  466. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  467. expect(tokens[6]).toEqual({value: 'return', scopes: ['source.ruby', 'keyword.control.pseudo-method.ruby']});
  468. ({tokens} = grammar.tokenizeLine('/test/ and return'));
  469. expect(tokens[0]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  470. expect(tokens[1]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  471. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  472. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  473. expect(tokens[4]).toEqual({value: 'and', scopes: ['source.ruby', 'keyword.operator.logical.ruby']});
  474. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  475. expect(tokens[6]).toEqual({value: 'return', scopes: ['source.ruby', 'keyword.control.pseudo-method.ruby']});
  476. ({tokens} = grammar.tokenizeLine('{/test/ => 1}'));
  477. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  478. expect(tokens[2]).toEqual({value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  479. expect(tokens[3]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  480. expect(tokens[4]).toEqual({value: ' ', scopes: ['source.ruby']});
  481. expect(tokens[5]).toEqual({value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby']});
  482. expect(tokens[6]).toEqual({value: ' ', scopes: ['source.ruby']});
  483. expect(tokens[7]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  484. });
  485. it("tokenizes multiline regular expressions", function() {
  486. const tokens = grammar.tokenizeLines(`\
  487. regexp = /
  488. foo|
  489. bar
  490. /ix\
  491. `
  492. );
  493. expect(tokens[0][0]).toEqual({value: 'regexp ', scopes: ['source.ruby']});
  494. expect(tokens[0][1]).toEqual({value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby']});
  495. expect(tokens[0][2]).toEqual({value: ' ', scopes: ['source.ruby']});
  496. expect(tokens[0][3]).toEqual({value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  497. expect(tokens[1][0]).toEqual({value: ' foo|', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  498. expect(tokens[2][0]).toEqual({value: ' bar', scopes: ['source.ruby', 'string.regexp.interpolated.ruby']});
  499. expect(tokens[3][0]).toEqual({value: '/ix', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby']});
  500. });
  501. it("tokenizes the / arithmetic operator", function() {
  502. let {tokens} = grammar.tokenizeLine('call/me/maybe');
  503. expect(tokens[0]).toEqual({value: 'call', scopes: ['source.ruby']});
  504. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  505. expect(tokens[2]).toEqual({value: 'me', scopes: ['source.ruby']});
  506. expect(tokens[3]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  507. expect(tokens[4]).toEqual({value: 'maybe', scopes: ['source.ruby']});
  508. ({tokens} = grammar.tokenizeLine('(1+2)/3/4'));
  509. expect(tokens[0]).toEqual({value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  510. expect(tokens[1]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  511. expect(tokens[2]).toEqual({value: '+', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  512. expect(tokens[3]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  513. expect(tokens[4]).toEqual({value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  514. expect(tokens[5]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  515. expect(tokens[6]).toEqual({value: '3', scopes: ['source.ruby', 'constant.numeric.ruby']});
  516. expect(tokens[7]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  517. expect(tokens[8]).toEqual({value: '4', scopes: ['source.ruby', 'constant.numeric.ruby']});
  518. ({tokens} = grammar.tokenizeLine('1 / 2 / 3'));
  519. expect(tokens[0]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  520. expect(tokens[1]).toEqual({value: ' ', scopes: ['source.ruby']});
  521. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  522. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  523. expect(tokens[4]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  524. expect(tokens[5]).toEqual({value: ' ', scopes: ['source.ruby']});
  525. expect(tokens[6]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  526. expect(tokens[7]).toEqual({value: ' ', scopes: ['source.ruby']});
  527. expect(tokens[8]).toEqual({value: '3', scopes: ['source.ruby', 'constant.numeric.ruby']});
  528. ({tokens} = grammar.tokenizeLine('1/ 2 / 3'));
  529. expect(tokens[0]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  530. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  531. expect(tokens[2]).toEqual({value: ' ', scopes: ['source.ruby']});
  532. expect(tokens[3]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  533. expect(tokens[4]).toEqual({value: ' ', scopes: ['source.ruby']});
  534. expect(tokens[5]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  535. expect(tokens[6]).toEqual({value: ' ', scopes: ['source.ruby']});
  536. expect(tokens[7]).toEqual({value: '3', scopes: ['source.ruby', 'constant.numeric.ruby']});
  537. ({tokens} = grammar.tokenizeLine('1 / 2/ 3'));
  538. expect(tokens[0]).toEqual({value: '1', scopes: ['source.ruby', 'constant.numeric.ruby']});
  539. expect(tokens[1]).toEqual({value: ' ', scopes: ['source.ruby']});
  540. expect(tokens[2]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  541. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby']});
  542. expect(tokens[4]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  543. expect(tokens[5]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  544. expect(tokens[6]).toEqual({value: ' ', scopes: ['source.ruby']});
  545. expect(tokens[7]).toEqual({value: '3', scopes: ['source.ruby', 'constant.numeric.ruby']});
  546. ({tokens} = grammar.tokenizeLine('x / 2; x /= 2'));
  547. expect(tokens[1]).toEqual({value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby']});
  548. expect(tokens[2]).toEqual({value: ' ', scopes: ['source.ruby']});
  549. expect(tokens[3]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  550. expect(tokens[4]).toEqual({value: ';', scopes: ['source.ruby', 'punctuation.terminator.statement.ruby']});
  551. expect(tokens[6]).toEqual({value: '/=', scopes: ['source.ruby', 'keyword.operator.assignment.augmented.ruby']});
  552. expect(tokens[7]).toEqual({value: ' ', scopes: ['source.ruby']});
  553. expect(tokens[8]).toEqual({value: '2', scopes: ['source.ruby', 'constant.numeric.ruby']});
  554. });
  555. it("tokenizes 'not' when used as method name", function() {
  556. let {tokens} = grammar.tokenizeLine('foo.not(bar)');
  557. expect(tokens[2]).toEqual({value: 'not', scopes: ['source.ruby']});
  558. ({tokens} = grammar.tokenizeLine('not?(Array)'));
  559. expect(tokens[0]).toEqual({value: 'not?', scopes: ['source.ruby']});
  560. });
  561. it("tokenizes 'not' as logical operator", function() {
  562. const {tokens} = grammar.tokenizeLine('not true');
  563. expect(tokens[0]).toEqual({value: 'not', scopes: ['source.ruby', 'keyword.operator.logical.ruby']});
  564. });
  565. it("tokenizes ! when used in method name", function() {
  566. const {tokens} = grammar.tokenizeLine('sort!');
  567. expect(tokens[0]).toEqual({value: 'sort!', scopes: ['source.ruby']});
  568. });
  569. it("tokenizes ! as logical operator", function() {
  570. const {tokens} = grammar.tokenizeLine('!foo');
  571. expect(tokens[0]).toEqual({value: '!', scopes: ['source.ruby', 'keyword.operator.logical.ruby']});
  572. });
  573. it("tokenizes != as comparison operator", function() {
  574. const {tokens} = grammar.tokenizeLine('foo != bar');
  575. expect(tokens[1]).toEqual({value: '!=', scopes: ['source.ruby', 'keyword.operator.comparison.ruby']});
  576. });
  577. it("tokenizes yard documentation comments", function() {
  578. let {tokens} = grammar.tokenizeLine('# @private');
  579. expect(tokens[0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  580. expect(tokens[1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  581. expect(tokens[2]).toEqual({value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  582. expect(tokens[3]).toEqual({value: 'private', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  583. tokens = grammar.tokenizeLines(`\
  584. # @deprecated Because I said so,
  585. # end of discussion\
  586. `
  587. );
  588. expect(tokens[0][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  589. expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  590. expect(tokens[0][2]).toEqual({value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  591. expect(tokens[0][3]).toEqual({value: 'deprecated', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  592. expect(tokens[0][4]).toEqual({value: ' Because I said so,', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  593. expect(tokens[1][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']});
  594. expect(tokens[1][1]).toEqual({value: ' end of discussion', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  595. tokens = grammar.tokenizeLines(`\
  596. # @raise [AccountBalanceError] if the account does not have
  597. # sufficient funds to perform the transaction\
  598. `
  599. );
  600. expect(tokens[0][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  601. expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  602. expect(tokens[0][2]).toEqual({value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  603. expect(tokens[0][3]).toEqual({value: 'raise', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  604. expect(tokens[0][4]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']});
  605. expect(tokens[0][5]).toEqual({value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  606. expect(tokens[0][6]).toEqual({value: 'AccountBalanceError', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']});
  607. expect(tokens[0][7]).toEqual({value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  608. expect(tokens[0][8]).toEqual({value: ' if the account does not have', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  609. expect(tokens[1][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']});
  610. expect(tokens[1][1]).toEqual({value: ' sufficient funds to perform the transaction', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  611. tokens = grammar.tokenizeLines(`\
  612. # @param value [Object] describe value param in a long way which
  613. # makes it multiline\
  614. `
  615. );
  616. expect(tokens[0][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  617. expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  618. expect(tokens[0][2]).toEqual({value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  619. expect(tokens[0][3]).toEqual({value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  620. expect(tokens[0][4]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']});
  621. expect(tokens[0][5]).toEqual({value: 'value', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.parameter.yard.ruby']});
  622. expect(tokens[0][6]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']});
  623. expect(tokens[0][7]).toEqual({value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  624. expect(tokens[0][8]).toEqual({value: 'Object', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']});
  625. expect(tokens[0][9]).toEqual({value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  626. expect(tokens[0][10]).toEqual({value: ' describe value param in a long way which', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  627. expect(tokens[1][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']});
  628. expect(tokens[1][1]).toEqual({value: ' makes it multiline', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  629. ({tokens} = grammar.tokenizeLine('# @param [Bar] Baz'));
  630. expect(tokens[0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  631. expect(tokens[1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  632. expect(tokens[2]).toEqual({value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  633. expect(tokens[3]).toEqual({value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  634. expect(tokens[4]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']});
  635. expect(tokens[5]).toEqual({value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  636. expect(tokens[6]).toEqual({value: 'Bar', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']});
  637. expect(tokens[7]).toEqual({value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  638. expect(tokens[8]).toEqual({value: ' Baz', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  639. ({tokens} = grammar.tokenizeLine('# @return [Array#[](0), Array] comment'));
  640. expect(tokens[0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  641. expect(tokens[1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  642. expect(tokens[2]).toEqual({value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  643. expect(tokens[3]).toEqual({value: 'return', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  644. expect(tokens[4]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']});
  645. expect(tokens[5]).toEqual({value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  646. expect(tokens[6]).toEqual({value: 'Array#[](0), Array', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']});
  647. expect(tokens[7]).toEqual({value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  648. expect(tokens[8]).toEqual({value: ' comment', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  649. ({tokens} = grammar.tokenizeLine('# @param [Array#[](0), Array] comment'));
  650. expect(tokens[0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  651. expect(tokens[1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  652. expect(tokens[2]).toEqual({value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  653. expect(tokens[3]).toEqual({value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  654. expect(tokens[4]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']});
  655. expect(tokens[5]).toEqual({value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  656. expect(tokens[6]).toEqual({value: 'Array#[](0), Array', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']});
  657. expect(tokens[7]).toEqual({value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  658. expect(tokens[8]).toEqual({value: ' comment', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  659. tokens = grammar.tokenizeLines(`\
  660. # @!attribute [r] count the number of items
  661. # present in the list\
  662. `
  663. );
  664. expect(tokens[0][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']});
  665. expect(tokens[0][1]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']});
  666. expect(tokens[0][2]).toEqual({value: '@!', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']});
  667. expect(tokens[0][3]).toEqual({value: 'attribute', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']});
  668. expect(tokens[0][4]).toEqual({value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']});
  669. expect(tokens[0][5]).toEqual({value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  670. expect(tokens[0][6]).toEqual({value: 'r', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']});
  671. expect(tokens[0][7]).toEqual({value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']});
  672. expect(tokens[0][8]).toEqual({value: ' count the number of items', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  673. expect(tokens[1][0]).toEqual({value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']});
  674. expect(tokens[1][1]).toEqual({value: ' present in the list', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']});
  675. });
  676. it("tokenizes a method with *args properly", function() {
  677. let {tokens} = grammar.tokenizeLine('def method(*args)');
  678. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  679. expect(tokens[2]).toEqual({value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  680. expect(tokens[3]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  681. expect(tokens[4]).toEqual({value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby']});
  682. expect(tokens[5]).toEqual({value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby']});
  683. expect(tokens[6]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  684. ({tokens} = grammar.tokenizeLine('def method(args)'));
  685. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  686. expect(tokens[2]).toEqual({value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  687. expect(tokens[3]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  688. expect(tokens[4]).toEqual({value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby']});
  689. expect(tokens[5]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  690. ({tokens} = grammar.tokenizeLine('def method *args'));
  691. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  692. expect(tokens[2]).toEqual({value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  693. expect(tokens[3]).toEqual({value: ' ', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby']});
  694. expect(tokens[4]).toEqual({value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby']});
  695. expect(tokens[5]).toEqual({value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby']});
  696. });
  697. it("tokenizes a method with (symbol: arg) properly", function() {
  698. const {tokens} = grammar.tokenizeLine('def method(red: 2)');
  699. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  700. expect(tokens[2]).toEqual({value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  701. expect(tokens[3]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  702. expect(tokens[4]).toEqual({value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  703. expect(tokens[7]).toEqual({value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  704. });
  705. it("tokenizes a method with symbol: arg (no paren) properly", function() {
  706. const {tokens} = grammar.tokenizeLine('def method red: 2');
  707. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  708. expect(tokens[2]).toEqual({value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  709. expect(tokens[4]).toEqual({value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  710. expect(tokens[7]).toEqual({value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  711. });
  712. it("tokenizes a method with (symbol: arg(paren), symbol: arg2(paren)...) properly", function() {
  713. const {tokens} = grammar.tokenizeLine('def method(red: rand(2), green: rand(3), blue: rand(4))');
  714. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  715. expect(tokens[2]).toEqual({value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  716. expect(tokens[3]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby']});
  717. expect(tokens[4]).toEqual({value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  718. expect(tokens[7]).toEqual({value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby']});
  719. expect(tokens[8]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  720. expect(tokens[9]).toEqual({value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  721. expect(tokens[10]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  722. expect(tokens[11]).toEqual({value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby']});
  723. expect(tokens[13]).toEqual({value: 'green', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  724. expect(tokens[16]).toEqual({value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby']});
  725. expect(tokens[17]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  726. expect(tokens[18]).toEqual({value: '3', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  727. expect(tokens[19]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  728. expect(tokens[20]).toEqual({value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby']});
  729. expect(tokens[22]).toEqual({value: 'blue', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  730. expect(tokens[25]).toEqual({value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby']});
  731. expect(tokens[26]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  732. expect(tokens[27]).toEqual({value: '4', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  733. expect(tokens[28]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  734. });
  735. it("tokenizes a method with symbol: arg(paren), symbol: arg2(paren)... (no outer parens) properly", function() {
  736. const {tokens} = grammar.tokenizeLine('def method red: rand(2), green: rand(3), blue: rand(4)');
  737. expect(tokens[0]).toEqual({value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby']});
  738. expect(tokens[2]).toEqual({value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby']});
  739. expect(tokens[4]).toEqual({value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  740. expect(tokens[7]).toEqual({value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby']});
  741. expect(tokens[8]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  742. expect(tokens[9]).toEqual({value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  743. expect(tokens[10]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  744. expect(tokens[11]).toEqual({value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby']});
  745. expect(tokens[13]).toEqual({value: 'green', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  746. expect(tokens[16]).toEqual({value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby']});
  747. expect(tokens[17]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  748. expect(tokens[18]).toEqual({value: '3', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  749. expect(tokens[19]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  750. expect(tokens[20]).toEqual({value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby']});
  751. expect(tokens[22]).toEqual({value: 'blue', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby']});
  752. expect(tokens[25]).toEqual({value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby']});
  753. expect(tokens[26]).toEqual({value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  754. expect(tokens[27]).toEqual({value: '4', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby']});
  755. expect(tokens[28]).toEqual({value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby']});
  756. });
  757. it("tokenizes a stabby lambda properly", function() {
  758. const {tokens} = grammar.tokenizeLine('method_name -> { puts "A message"} do');
  759. expect(tokens[1]).toEqual({value: '->', scopes: ['source.ruby', 'support.function.kernel.arrow.ruby']});
  760. });
  761. it("tokenizes a simple do block properly", function() {
  762. const {tokens} = grammar.tokenizeLine('do |foo| ');
  763. expect(tokens[0]).toEqual({value: 'do', scopes: ['source.ruby', 'keyword.control.start-block.ruby']});
  764. expect(tokens[2]).toEqual({value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby']});
  765. expect(tokens[3]).toEqual({value: 'foo', scopes: ['source.ruby', 'variable.other.block.ruby']});
  766. expect(tokens[4]).toEqual({value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby']});
  767. });
  768. it("tokenizes a complex do block properly", function() {
  769. const {tokens} = grammar.tokenizeLine('do |key = (a || b), hash = config, create: false|');
  770. expect(tokens[0]).toEqual({value: 'do', scopes: ['source.ruby', 'keyword.control.start-block.ruby']});
  771. expect(tokens[2]).toEqual({value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby']});
  772. expect(tokens[3]).toEqual({value: 'key', scopes: ['source.ruby', 'variable.other.block.ruby']});
  773. expect(tokens[5]).toEqual({value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby']});
  774. expect(tokens[7]).toEqual({value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  775. expect(tokens[8]).toEqual({value: 'a', scopes: ['source.ruby', 'variable.other.block.ruby']});
  776. expect(tokens[10]).toEqual({value: '||', scopes: ['source.ruby', 'keyword.operator.logical.ruby']});
  777. expect(tokens[12]).toEqual({value: 'b', scopes: ['source.ruby', 'variable.other.block.ruby']});
  778. expect(tokens[13]).toEqual({value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby']});
  779. expect(tokens[14]).toEqual({value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby']});
  780. expect(tokens[16]).toEqual({value: 'hash', scopes: ['source.ruby', 'variable.other.block.ruby']});
  781. expect(tokens[18]).toEqual({value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby']});
  782. expect(tokens[20]).toEqual({value: 'config', scopes: ['source.ruby', 'variable.other.block.ruby']});
  783. expect(tokens[21]).toEqual({value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby']});
  784. expect(tokens[23]).toEqual({value: 'create', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby']});
  785. expect(tokens[24]).toEqual({value: ':', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby', 'punctuation.definition.constant.hashkey.ruby']});
  786. expect(tokens[26]).toEqual({value: 'false', scopes: ['source.ruby', 'constant.language.boolean.ruby']});
  787. expect(tokens[27]).toEqual({value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby']});
  788. });
  789. it("does not erroneously tokenize a variable ending in `do` followed by a pipe as a block", function() {
  790. const {tokens} = grammar.tokenizeLine('sudo ||= true');
  791. expect(tokens[0]).toEqual({value: 'sudo ', scopes: ['source.ruby']});
  792. expect(tokens[1]).toEqual({value: '||=', scopes: ['source.ruby', 'keyword.operator.assignment.augmented.ruby']});
  793. expect(tokens[3]).toEqual({value: 'true', scopes: ['source.ruby', 'constant.language.boolean.ruby']});
  794. });
  795. it("tokenizes <<- heredoc", function() {
  796. const lines = grammar.tokenizeLines('<<-EOS\nThis is text\nEOS');
  797. expect(lines[0][0]).toEqual({value: '<<-EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby']});
  798. expect(lines[2][0]).toEqual({value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby']});
  799. });
  800. it("tokenizes <<~ Ruby 2.3.0 squiggly heredoc", function() {
  801. const lines = grammar.tokenizeLines('<<~EOS\nThis is text\nEOS');
  802. expect(lines[0][0]).toEqual({value: '<<~EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby']});
  803. expect(lines[2][0]).toEqual({value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby']});
  804. });
  805. it("tokenizes quoted heredoc", function() {
  806. // Double-quoted heredoc:
  807. let lines = grammar.tokenizeLines('<<~"EOS"\nThis is text\nEOS');
  808. expect(lines[0][0]).toEqual({value: '<<~"EOS"', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby']});
  809. expect(lines[2][0]).toEqual({value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby']});
  810. // Single-quoted heredoc:
  811. lines = grammar.tokenizeLines('<<~\'EOS\'\nThis is text\nEOS');
  812. expect(lines[0][0]).toEqual({value: '<<~\'EOS\'', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby']});
  813. expect(lines[2][0]).toEqual({value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby']});
  814. // Backtick-quoted heredoc:
  815. lines = grammar.tokenizeLines('<<~`EOS`\nThis is text\nEOS');
  816. expect(lines[0][0]).toEqual({value: '<<~`EOS`', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby']});
  817. expect(lines[2][0]).toEqual({value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby']});
  818. });
  819. it("tokenizes heredoc which includes identifier in end of a line", function() {
  820. const lines = grammar.tokenizeLines('<<-EOS\nThis is text\nThis is Not EOS\nEOS');
  821. expect(lines[0][0]).toEqual({value: '<<-EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby']});
  822. expect(lines[3][0]).toEqual({value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby']});
  823. });
  824. it("tokenizes Kernel support functions autoload? and exit!", function() {
  825. const lines = grammar.tokenizeLines('p autoload?(:test)\nexit!\nat_exit!');
  826. expect(lines[0][2]).toEqual({value: 'autoload?', scopes: ['source.ruby', 'support.function.kernel.ruby']});
  827. expect(lines[1][0]).toEqual({value: 'exit!', scopes: ['source.ruby', 'support.function.kernel.ruby']});
  828. expect(lines[2][0]).toEqual({value: 'at_exit!', scopes: ['source.ruby']});
  829. });
  830. it("tokenizes iterator? the same way as block_given?", function() {
  831. const lines = grammar.tokenizeLines('p iterator?\np block_given?');
  832. expect(lines[0][2].value).toEqual('iterator?');
  833. expect(lines[1][2].value).toEqual('block_given?');
  834. expect(lines[0][2].scopes).toEqual(lines[1][2].scopes);
  835. });
  836. describe("firstLineMatch", function() {
  837. it("recognises interpreter directives", function() {
  838. let line;
  839. const valid = `\
  840. #!/usr/sbin/ruby foo
  841. #!/usr/bin/rake foo=bar/
  842. #!/usr/sbin/jruby
  843. #!/usr/sbin/rbx foo bar baz
  844. #!/usr/bin/rake perl
  845. #!/usr/bin/macruby bin/perl
  846. #!/usr/bin/rbx
  847. #!/bin/rbx
  848. #!/bin/env ruby_executable_hooks
  849. #!/usr/bin/ruby --script=usr/bin
  850. #! /usr/bin/env A=003 B=149 C=150 D=xzd E=base64 F=tar G=gz H=head I=tail rbx
  851. #!\t/usr/bin/env --foo=bar ruby --quu=quux
  852. #! /usr/bin/ruby
  853. #!/usr/bin/env ruby\
  854. `;
  855. for (line of Array.from(valid.split(/\n/))) {
  856. expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull();
  857. }
  858. const invalid = `\
  859. \x20#!/usr/sbin/ruby
  860. \t#!/usr/sbin/rake
  861. #!/usr/bin/env-ruby/node-env/
  862. #!/usr/bin/env-ruby
  863. #! /usr/binrake
  864. #!\t/usr/bin/env --ruby=bar\
  865. `;
  866. return (() => {
  867. const result = [];
  868. for (line of Array.from(invalid.split(/\n/))) {
  869. result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull());
  870. }
  871. return result;
  872. })();
  873. });
  874. it("recognises Emacs modelines", function() {
  875. let line;
  876. const valid = `\
  877. #-*- Ruby -*-
  878. #-*- mode: Ruby -*-
  879. /* -*-ruby-*- */
  880. // -*- RUBY -*-
  881. /* -*- mode:RUBY -*- */
  882. // -*- font:bar;mode:Ruby -*-
  883. // -*- font:bar;mode:ruby;foo:bar; -*-
  884. // -*-font:mode;mode:Ruby-*-
  885. // -*- foo:bar mode: ruby bar:baz -*-
  886. " -*-foo:bar;mode:ruby;bar:foo-*- ";
  887. " -*-font-mode:foo;mode:ruby;foo-bar:quux-*-"
  888. "-*-font:x;foo:bar; mode : ruby; bar:foo;foooooo:baaaaar;fo:ba;-*-";
  889. "-*- font:x;foo : bar ; mode : RUBY ; bar : foo ; foooooo:baaaaar;fo:ba-*-";\
  890. `;
  891. for (line of Array.from(valid.split(/\n/))) {
  892. expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull();
  893. }
  894. const invalid = `\
  895. /* --*ruby-*- */
  896. /* -*-- ruby -*-
  897. /* -*- -- RUBY -*-
  898. /* -*- RUBY -;- -*-
  899. // -*- iRUBY -*-
  900. // -*- ruby; -*-
  901. // -*- ruby-stuff -*-
  902. /* -*- model:ruby -*-
  903. /* -*- indent-mode:ruby -*-
  904. // -*- font:mode;Ruby -*-
  905. // -*- mode: -*- Ruby
  906. // -*- mode: i-named-my-dog-ruby -*-
  907. // -*-font:mode;mode:ruby--*-\
  908. `;
  909. return (() => {
  910. const result = [];
  911. for (line of Array.from(invalid.split(/\n/))) {
  912. result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull());
  913. }
  914. return result;
  915. })();
  916. });
  917. it("recognises Vim modelines", function() {
  918. let line;
  919. const valid = `\
  920. vim: se filetype=ruby:
  921. # vim: se ft=ruby:
  922. # vim: set ft=Ruby:
  923. # vim: set filetype=RUBY:
  924. # vim: ft=RUBY
  925. # vim: syntax=Ruby
  926. # vim: se syntax=ruBy:
  927. # ex: syntax=rUBy
  928. # vim:ft=RubY
  929. # vim600: ft=ruby
  930. # vim>600: set ft=ruby:
  931. # vi:noai:sw=3 ts=6 ft=ruby
  932. # vi::::::::::noai:::::::::::: ft=ruby
  933. # vim:ts=4:sts=4:sw=4:noexpandtab:ft=ruby
  934. # vi:: noai : : : : sw =3 ts =6 ft =ruby
  935. # vim: ts=4: pi sts=4: ft=ruby: noexpandtab: sw=4:
  936. # vim: ts=4 sts=4: ft=ruby noexpandtab:
  937. # vim:noexpandtab sts=4 ft=ruby ts=4
  938. # vim:noexpandtab:ft=RUBY
  939. # vim:ts=4:sts=4 ft=ruby:noexpandtab:\x20
  940. # vim:noexpandtab titlestring=hi\|there\\\\ ft=ruby ts=4\
  941. `;
  942. for (line of Array.from(valid.split(/\n/))) {
  943. expect(grammar.firstLineRegex.findNextMatchSync(line)).not.toBeNull();
  944. }
  945. const invalid = `\
  946. ex: se filetype=ruby:
  947. _vi: se filetype=ruby:
  948. vi: se filetype=ruby
  949. # vim set ft=rubyy
  950. # vim: soft=ruby
  951. # vim: clean-syntax=ruby:
  952. # vim set ft=ruby:
  953. # vim: setft=ruby:
  954. # vim: se ft=ruby backupdir=tmp
  955. # vim: set ft=ruby set cmdheight=1
  956. # vim:noexpandtab sts:4 ft:ruby ts:4
  957. # vim:noexpandtab titlestring=hi\\|there\\ ft=ruby ts=4
  958. # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=ruby ts=4\
  959. `;
  960. return (() => {
  961. const result = [];
  962. for (line of Array.from(invalid.split(/\n/))) {
  963. result.push(expect(grammar.firstLineRegex.findNextMatchSync(line)).toBeNull());
  964. }
  965. return result;
  966. })();
  967. });
  968. });
  969. });