| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'package:unittest/unittest.dart'; | 5 import 'package:unittest/unittest.dart'; |
| 6 | 6 |
| 7 import 'package:analyzer_experimental/src/generated/ast.dart'; | 7 import 'package:analyzer_experimental/src/generated/ast.dart'; |
| 8 import 'package:analyzer_experimental/src/generated/scanner.dart'; | 8 import 'package:analyzer_experimental/src/generated/scanner.dart'; |
| 9 import 'package:analyzer_experimental/src/services/formatter.dart'; | 9 import 'package:analyzer_experimental/src/services/formatter.dart'; |
| 10 import 'package:analyzer_experimental/src/services/formatter_impl.dart'; | 10 import 'package:analyzer_experimental/src/services/formatter_impl.dart'; |
| 11 import 'package:analyzer_experimental/src/services/writer.dart'; |
| 11 | 12 |
| 12 main() { | 13 main() { |
| 13 | 14 |
| 14 /// Edit recorder tests | |
| 15 group('edit recorder', () { | |
| 16 | |
| 17 test('countWhitespace', (){ | |
| 18 expect(newRecorder(' ').countWhitespace(), equals(3)); | |
| 19 expect(newRecorder('').countWhitespace(), equals(0)); | |
| 20 expect(newRecorder(' foo').countWhitespace(), equals(2)); | |
| 21 }); | |
| 22 | |
| 23 test('isNewlineAt', (){ | |
| 24 expect(newRecorder('012\n').isNewlineAt(3), isTrue); | |
| 25 expect(newRecorder('012\n3456').isNewlineAt(3), isTrue); | |
| 26 expect(newRecorder('\n').isNewlineAt(0), isTrue); | |
| 27 }); | |
| 28 | |
| 29 test('space advances 1', (){ | |
| 30 var recorder = newRecorder(' foo'); | |
| 31 var startColumn = recorder.column; | |
| 32 recorder.space(); | |
| 33 expect(recorder.column, equals(startColumn + 1)); | |
| 34 }); | |
| 35 | |
| 36 test('space eats WS (1)', (){ | |
| 37 var recorder = newRecorder(' class') | |
| 38 ..currentToken = new KeywordToken(Keyword.CLASS, 3) | |
| 39 ..space() | |
| 40 ..advanceToken('class'); | |
| 41 expect(doFormat(recorder), equals(' class')); | |
| 42 }); | |
| 43 | |
| 44 test('space eats WS (2)', (){ | |
| 45 var src = 'class A'; | |
| 46 var recorder = newRecorder(src); | |
| 47 recorder..currentToken = (classKeyword(0)..setNext(identifier('A', 7))) | |
| 48 ..advanceToken('class') | |
| 49 ..space() | |
| 50 ..advanceToken('A'); | |
| 51 | |
| 52 expect(doFormat(recorder), equals('class A')); | |
| 53 }); | |
| 54 | |
| 55 test('advance string token', (){ | |
| 56 var recorder = newRecorder('class A')..currentToken = classKeyword(0); | |
| 57 expect(recorder.column, equals(0)); | |
| 58 recorder.advanceToken('class'); | |
| 59 expect(recorder.column, equals(5)); | |
| 60 }); | |
| 61 | |
| 62 test('advance string token (failure)', (){ | |
| 63 var recorder = newRecorder('class A')..currentToken = classKeyword(0); | |
| 64 expect(() => recorder.advanceToken('static'), | |
| 65 throwsA(new isInstanceOf<FormatterException>())); | |
| 66 }); | |
| 67 | |
| 68 test('advance indent', (){ | |
| 69 var recorder = newRecorder(' class A')..currentToken = classKeyword(0); | |
| 70 recorder.advanceIndent(); | |
| 71 expect(doFormat(recorder), equals('class A')); | |
| 72 }); | |
| 73 | |
| 74 test('indent string', (){ | |
| 75 var recorder = newRecorder(''); | |
| 76 expect(recorder.getIndentString(0).length, equals(0)); | |
| 77 expect(recorder.getIndentString(5).length, equals(5)); | |
| 78 expect(recorder.getIndentString(50).length, equals(50)); | |
| 79 }); | |
| 80 | |
| 81 | |
| 82 test('newline', (){ | |
| 83 var recorder = newRecorder('class A { }'); | |
| 84 recorder..currentToken = chain([classKeyword(0), | |
| 85 identifier('A', 6), | |
| 86 openParen(8), | |
| 87 closeParen(10)]) | |
| 88 ..advanceToken('class') | |
| 89 ..space() | |
| 90 ..advanceToken('A') | |
| 91 ..space() | |
| 92 ..advanceToken('{') | |
| 93 ..newline(); | |
| 94 | |
| 95 expect(doFormat(recorder)[9], equals(NEW_LINE)); | |
| 96 }); | |
| 97 | |
| 98 test('newline eats trailing WS', (){ | |
| 99 var src = 'class A {'; | |
| 100 var recorder = newRecorder(src + ' '); | |
| 101 recorder..currentToken = chain([classKeyword(0), | |
| 102 identifier('A', 6), | |
| 103 openParen(8)]) | |
| 104 ..advanceToken('class') | |
| 105 ..space() | |
| 106 ..advanceToken('A') | |
| 107 ..space() | |
| 108 ..advanceToken('{') | |
| 109 ..newline(); | |
| 110 | |
| 111 expect(doFormat(recorder).length, equals((src + NEW_LINE).length)); | |
| 112 }); | |
| 113 | |
| 114 | |
| 115 }); | |
| 116 | |
| 117 | |
| 118 /// Edit operations | |
| 119 group('edit operations', () { | |
| 120 | |
| 121 test('replace same length', () { | |
| 122 var edits = [new Edit(1, 2, 'oo'), | |
| 123 new Edit(4, 5, 'bar')]; | |
| 124 expect(new EditOperation().apply(edits, 'fun house'), equals('foo bar')); | |
| 125 }); | |
| 126 | |
| 127 test('replace shorten', () { | |
| 128 var edits = [new Edit(0, 2, 'a'), | |
| 129 new Edit(2, 2, 'b'), | |
| 130 new Edit(4, 2, 'c')]; | |
| 131 expect(new EditOperation().apply(edits, 'AaBbCc'), equals('abc')); | |
| 132 }); | |
| 133 | |
| 134 | |
| 135 }); | |
| 136 | |
| 137 | |
| 138 /// Formatter tests | 15 /// Formatter tests |
| 139 group('formatter', () { | 16 group('formatter', () { |
| 140 | 17 |
| 141 test('failed parse', () { | 18 test('failed parse', () { |
| 142 var formatter = new CodeFormatter(); | 19 var formatter = new CodeFormatter(); |
| 143 expect(() => formatter.format(CodeKind.COMPILATION_UNIT, '~'), | 20 expect(() => formatter.format(CodeKind.COMPILATION_UNIT, '~'), |
| 144 throwsA(new isInstanceOf<FormatterException>())); | 21 throwsA(new isInstanceOf<FormatterException>())); |
| 145 }); | 22 }); |
| 146 | 23 |
| 147 test('CU (1)', () { | 24 test('CU (1)', () { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 'class A {\n' | 62 'class A {\n' |
| 186 'void x(){\n' | 63 'void x(){\n' |
| 187 '}\n' | 64 '}\n' |
| 188 '}', | 65 '}', |
| 189 'class A {\n' | 66 'class A {\n' |
| 190 ' void x() {\n' | 67 ' void x() {\n' |
| 191 ' }\n' | 68 ' }\n' |
| 192 '}' | 69 '}' |
| 193 ); | 70 ); |
| 194 }); | 71 }); |
| 195 | 72 // |
| 196 test('CU (method indent - 2)', () { | 73 // test('CU (method indent - 2)', () { |
| 197 expectCUFormatsTo( | 74 // expectCUFormatsTo( |
| 198 'class A {\n' | 75 // 'class A {\n' |
| 199 ' static void x(){}\n' | 76 // ' static bool x(){ return true; }\n' |
| 200 ' }', | 77 // ' }', |
| 201 'class A {\n' | 78 // 'class A {\n' |
| 202 ' static void x() {\n' | 79 // ' static bool x() {\n' |
| 203 ' }\n' | 80 // ' return true;\n' |
| 204 '}' | 81 // ' }\n' |
| 205 ); | 82 // '}' |
| 206 }); | 83 // ); |
| 207 | 84 // }); |
| 85 // |
| 86 // test('CU (method indent - 3)', () { |
| 87 // expectCUFormatsTo( |
| 88 // 'class A {\n' |
| 89 // ' int x() => 42 + 3 ; \n' |
| 90 // ' }', |
| 91 // 'class A {\n' |
| 92 // ' int x() => 42 + 3;\n' |
| 93 // '}' |
| 94 // ); |
| 95 // }); |
| 96 // |
| 97 // test('CU (method indent - 4)', () { |
| 98 // expectCUFormatsTo( |
| 99 // 'class A {\n' |
| 100 // ' int x() { \n' |
| 101 // 'if (true) {return 42;\n' |
| 102 // '} else { return false; }\n' |
| 103 // ' }' |
| 104 // '}', |
| 105 // 'class A {\n' |
| 106 // ' int x() {\n' |
| 107 // ' if (true) {\n' |
| 108 // ' return 42;\n' |
| 109 // ' } else {\n' |
| 110 // ' return false;\n' |
| 111 // ' }\n' |
| 112 // '}' |
| 113 // ); |
| 114 // }); |
| 208 | 115 |
| 209 | 116 |
| 210 // test('initialIndent', () { | 117 // test('initialIndent', () { |
| 211 // var formatter = new CodeFormatter( | 118 // var formatter = new CodeFormatter( |
| 212 // new FormatterOptions(initialIndentationLevel:2)); | 119 // new FormatterOptions(initialIndentationLevel: 2)); |
| 213 // var formattedSource = formatter.format(CodeKind.STATEMENT, 'var x;'); | 120 // var formattedSource = formatter.format(CodeKind.STATEMENT, 'var x;'); |
| 214 // expect(formattedSource, startsWith(' ')); | 121 // expect(formattedSource, startsWith(' ')); |
| 215 // }); | 122 // }); |
| 216 | 123 |
| 217 }); | 124 }); |
| 218 | 125 |
| 126 |
| 127 /// Line tests |
| 128 group('line', () { |
| 129 |
| 130 test('space', () { |
| 131 var line = new Line(indent: 0); |
| 132 line.addSpaces(2); |
| 133 expect(line.toString(), equals(' ')); |
| 134 }); |
| 135 |
| 136 test('initial indent', () { |
| 137 var line = new Line(indent: 2); |
| 138 expect(line.toString(), equals(' ')); |
| 139 }); |
| 140 |
| 141 test('initial indent (tabbed)', () { |
| 142 var line = new Line(indent:1, useTabs: true); |
| 143 expect(line.toString(), equals('\t')); |
| 144 }); |
| 145 |
| 146 test('addToken', () { |
| 147 var line = new Line(); |
| 148 line.addToken(new LineToken('foo')); |
| 149 expect(line.toString(), equals('foo')); |
| 150 }); |
| 151 |
| 152 test('addToken (2)', () { |
| 153 var line = new Line(indent: 1); |
| 154 line.addToken(new LineToken('foo')); |
| 155 expect(line.toString(), equals(' foo')); |
| 156 }); |
| 157 |
| 158 }); |
| 159 |
| 160 |
| 161 /// Writer tests |
| 162 group('writer', () { |
| 163 |
| 164 test('basic print', () { |
| 165 var writer = new SourceWriter(); |
| 166 writer.print('foo'); |
| 167 writer.print(' '); |
| 168 writer.print('bar'); |
| 169 expect(writer.toString(), equals('foo bar')); |
| 170 }); |
| 171 |
| 172 test('newline', () { |
| 173 var writer = new SourceWriter(); |
| 174 writer.print('foo'); |
| 175 writer.newline(); |
| 176 expect(writer.toString(), equals('foo\n')); |
| 177 }); |
| 178 |
| 179 test('basic print (with indents)', () { |
| 180 var writer = new SourceWriter(); |
| 181 writer.print('foo'); |
| 182 writer.indent(); |
| 183 writer.newline(); |
| 184 writer.print('bar'); |
| 185 writer.unindent(); |
| 186 writer.newline(); |
| 187 writer.print('baz'); |
| 188 expect(writer.toString(), equals('foo\n bar\nbaz')); |
| 189 }); |
| 190 |
| 191 }); |
| 192 |
| 193 |
| 194 /// Helper method tests |
| 195 group('helpers', () { |
| 196 |
| 197 test('indentString', () { |
| 198 expect(getIndentString(0), ''); |
| 199 expect(getIndentString(1), ' '); |
| 200 expect(getIndentString(4), ' '); |
| 201 }); |
| 202 |
| 203 test('indentString (tabbed)', () { |
| 204 expect(getIndentString(0, useTabs: true), ''); |
| 205 expect(getIndentString(1, useTabs: true), '\t'); |
| 206 expect(getIndentString(3, useTabs: true), '\t\t\t'); |
| 207 }); |
| 208 |
| 209 test('repeat', () { |
| 210 expect(repeat('x', 0), ''); |
| 211 expect(repeat('x', 1), 'x'); |
| 212 expect(repeat('x', 4), 'xxxx'); |
| 213 }); |
| 214 |
| 215 }); |
| 216 |
| 219 } | 217 } |
| 220 | 218 |
| 221 Token classKeyword(int offset) => | 219 Token classKeyword(int offset) => |
| 222 new KeywordToken(Keyword.CLASS, offset); | 220 new KeywordToken(Keyword.CLASS, offset); |
| 223 | 221 |
| 224 Token identifier(String value, int offset) => | 222 Token identifier(String value, int offset) => |
| 225 new StringToken(TokenType.IDENTIFIER, value, offset); | 223 new StringToken(TokenType.IDENTIFIER, value, offset); |
| 226 | 224 |
| 227 Token openParen(int offset) => | 225 Token openParen(int offset) => |
| 228 new StringToken(TokenType.OPEN_PAREN, '{', offset); | 226 new StringToken(TokenType.OPEN_PAREN, '{', offset); |
| 229 | 227 |
| 230 Token closeParen(int offset) => | 228 Token closeParen(int offset) => |
| 231 new StringToken(TokenType.CLOSE_PAREN, '}', offset); | 229 new StringToken(TokenType.CLOSE_PAREN, '}', offset); |
| 232 | 230 |
| 233 Token chain(List<Token> tokens) { | 231 Token chain(List<Token> tokens) { |
| 234 for (var i = 0; i < tokens.length - 1; ++i) { | 232 for (var i = 0; i < tokens.length - 1; ++i) { |
| 235 tokens[i].setNext(tokens[i + 1]); | 233 tokens[i].setNext(tokens[i + 1]); |
| 236 } | 234 } |
| 237 return tokens[0]; | 235 return tokens[0]; |
| 238 } | 236 } |
| 239 | 237 |
| 240 EditRecorder newRecorder(source) => | |
| 241 new EditRecorder(new FormatterOptions())..source = source; | |
| 242 | |
| 243 String doFormat(recorder) => | |
| 244 new EditOperation().apply(recorder.editStore.edits, recorder.source); | |
| 245 | |
| 246 String formatCU(src, {options: const FormatterOptions()}) => | 238 String formatCU(src, {options: const FormatterOptions()}) => |
| 247 new CodeFormatter(options).format(CodeKind.COMPILATION_UNIT, src); | 239 new CodeFormatter(options).format(CodeKind.COMPILATION_UNIT, src); |
| 248 | 240 |
| 249 expectCUFormatsTo(src, expected) => expect(formatCU(src), equals(expected)); | 241 expectCUFormatsTo(src, expected) => expect(formatCU(src), equals(expected)); |
| OLD | NEW |