tree-indenter-spec.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. const fs = require('fs');
  2. const path = require('path');
  3. const TreeSitterGrammar = require('../src/tree-sitter-grammar');
  4. const TreeSitterLanguageMode = require('../src/tree-sitter-language-mode');
  5. const TreeIndenter = require('../src/tree-indenter');
  6. const jsGrammarPath = require.resolve(
  7. 'language-javascript/grammars/tree-sitter-javascript.cson'
  8. );
  9. const TAB_LENGTH = 2;
  10. const jsScopes = {
  11. indent: {
  12. array: true,
  13. object: true,
  14. arguments: true,
  15. statement_block: true,
  16. class_body: true,
  17. parenthesized_expression: true,
  18. jsx_element: true,
  19. jsx_opening_element: true,
  20. jsx_expression: true,
  21. switch_body: true,
  22. comment: true
  23. },
  24. indentExceptFirst: {
  25. member_expression: true,
  26. assignment_expression: true,
  27. expression_statement: true,
  28. variable_declarator: true,
  29. lexical_declaration: true,
  30. binary_expression: true,
  31. jsx_self_closing_element: true
  32. },
  33. indentExceptFirstOrBlock: {
  34. if_statement: true,
  35. while_statement: true
  36. },
  37. types: {
  38. indent: {},
  39. outdent: {
  40. else: true
  41. }
  42. }
  43. };
  44. describe('TreeIndenter', () => {
  45. let editor, buffer, grammar;
  46. let languageMode, treeIndenter;
  47. beforeEach(async () => {
  48. editor = await atom.workspace.open('');
  49. buffer = editor.getBuffer();
  50. editor.displayLayer.reset({ foldCharacter: '…' });
  51. grammar = new TreeSitterGrammar(atom.grammars, jsGrammarPath, {
  52. parser: 'tree-sitter-javascript'
  53. });
  54. });
  55. /** load a file from disk and verify that our proposed indentation
  56. is the same as it is in the file */
  57. function compareFile(filename) {
  58. const text = fs.readFileSync(filename);
  59. buffer.setText(text);
  60. languageMode = new TreeSitterLanguageMode({ buffer, grammar });
  61. treeIndenter = new TreeIndenter(languageMode, jsScopes);
  62. for (let row = 0; row < buffer.getLineCount(); row++) {
  63. // get current (correct) indentation
  64. const line = buffer.lineForRow(row);
  65. const currentIndentation = languageMode.indentLevelForLine(
  66. line,
  67. TAB_LENGTH
  68. );
  69. // get suggested indentation
  70. const indent = treeIndenter.suggestedIndentForBufferRow(
  71. row,
  72. TAB_LENGTH,
  73. {}
  74. );
  75. // verify
  76. if (indent !== currentIndentation) {
  77. throw Error(
  78. `failure in file row ${row +
  79. 1}: suggested ${indent} but ${currentIndentation} is correct (${line})`
  80. );
  81. } else {
  82. expect(indent).toEqual(currentIndentation);
  83. }
  84. }
  85. }
  86. describe('indentation', () => {
  87. it('indents wrongly indented lines', () => {
  88. buffer.setText(`if (true) {
  89. a = {a: [
  90. 1,
  91. 'something'
  92. ],
  93. b: 2}
  94. }`);
  95. const correct = [0, 1, 3, 3, 2, 2, 0];
  96. languageMode = new TreeSitterLanguageMode({ buffer, grammar });
  97. treeIndenter = new TreeIndenter(languageMode, jsScopes);
  98. for (let row = 0; row < buffer.getLineCount(); row++) {
  99. // get suggested indentation
  100. const indent = treeIndenter.suggestedIndentForBufferRow(
  101. row,
  102. TAB_LENGTH,
  103. {}
  104. );
  105. // verify
  106. if (indent !== correct[row]) {
  107. const line = buffer.lineForRow(row).trim();
  108. throw Error(
  109. `failure in row ${row}: suggested ${indent} but ${
  110. correct[row]
  111. } is correct (${line})`
  112. );
  113. } else {
  114. expect(indent).toEqual(correct[row]);
  115. }
  116. }
  117. });
  118. const fixtures = fs.readdirSync(
  119. path.join(__dirname, 'fixtures', 'indentation')
  120. );
  121. fixtures.forEach(filename => {
  122. /**
  123. * TODO: FAILING TEST - This test fails with the following output:
  124. * it suggests correct indentations for if_then_else.js
  125. * Error: failure in file row 5: suggested 1 but 0 is correct (else)
  126. */
  127. xit(`suggests correct indentations for ${filename}`, () => {
  128. compareFile(path.join(__dirname, 'fixtures', 'indentation', filename));
  129. });
  130. });
  131. });
  132. });