| // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library dart_style.example.format; |
| |
| import 'dart:io'; |
| import 'dart:mirrors'; |
| |
| import 'package:path/path.dart' as p; |
| |
| import 'package:dart_style/dart_style.dart'; |
| import 'package:dart_style/src/debug.dart' as debug; |
| |
| void main(List<String> args) { |
| // Enable debugging so you can see some of the formatter's internal state. |
| // Normal users do not do this. |
| debug.traceChunkBuilder = true; |
| debug.traceLineWriter = true; |
| debug.traceSplitter = true; |
| debug.useAnsiColors = true; |
| |
| runTest("regression/0000/0068.stmt", 14); |
| |
| formatStmt("hello(world);"); |
| } |
| |
| void formatStmt(String source, [int pageWidth = 80]) { |
| runFormatter(source, pageWidth, isCompilationUnit: false); |
| } |
| |
| void formatUnit(String source, [int pageWidth = 80]) { |
| runFormatter(source, pageWidth, isCompilationUnit: true); |
| } |
| |
| void runFormatter(String source, int pageWidth, {bool isCompilationUnit}) { |
| try { |
| var formatter = new DartFormatter(pageWidth: pageWidth); |
| |
| var result; |
| if (isCompilationUnit) { |
| result = formatter.format(source); |
| } else { |
| result = formatter.formatStatement(source); |
| } |
| |
| drawRuler("before", pageWidth); |
| print(source); |
| drawRuler("after", pageWidth); |
| print(result); |
| } on FormatterException catch (error) { |
| print(error.message()); |
| } |
| } |
| |
| void drawRuler(String label, int width) { |
| var padding = " " * (width - label.length - 1); |
| print("$label:$padding|"); |
| } |
| |
| /// Runs the formatter test starting on [line] at [path] inside the "test" |
| /// directory. |
| void runTest(String path, int line) { |
| var indentPattern = new RegExp(r"^\(indent (\d+)\)\s*"); |
| |
| // Locate the "test" directory. Use mirrors so that this works with the test |
| // package, which loads this suite into an isolate. |
| var testDir = p.join( |
| p.dirname(currentMirrorSystem() |
| .findLibrary(#dart_style.example.format) |
| .uri |
| .path), |
| "../test"); |
| |
| var lines = new File(p.join(testDir, path)).readAsLinesSync(); |
| |
| // The first line may have a "|" to indicate the page width. |
| var pageWidth = 80; |
| if (lines[0].endsWith("|")) { |
| pageWidth = lines[0].indexOf("|"); |
| lines = lines.skip(1).toList(); |
| } |
| |
| var i = 0; |
| while (i < lines.length) { |
| var description = lines[i++].replaceAll(">>>", "").trim(); |
| |
| // Let the test specify a leading indentation. This is handy for |
| // regression tests which often come from a chunk of nested code. |
| var leadingIndent = 0; |
| var indentMatch = indentPattern.firstMatch(description); |
| if (indentMatch != null) { |
| leadingIndent = int.parse(indentMatch[1]); |
| description = description.substring(indentMatch.end); |
| } |
| |
| if (description == "") { |
| description = "line ${i + 1}"; |
| } else { |
| description = "line ${i + 1}: $description"; |
| } |
| var startLine = i + 1; |
| |
| var input = ""; |
| while (!lines[i].startsWith("<<<")) { |
| input += lines[i++] + "\n"; |
| } |
| |
| var expectedOutput = ""; |
| while (++i < lines.length && !lines[i].startsWith(">>>")) { |
| expectedOutput += lines[i] + "\n"; |
| } |
| |
| if (line != startLine) continue; |
| |
| var isCompilationUnit = p.extension(path) == ".unit"; |
| |
| var inputCode = |
| _extractSelection(input, isCompilationUnit: isCompilationUnit); |
| |
| var expected = |
| _extractSelection(expectedOutput, isCompilationUnit: isCompilationUnit); |
| |
| var formatter = |
| new DartFormatter(pageWidth: pageWidth, indent: leadingIndent); |
| |
| var actual = formatter.formatSource(inputCode); |
| |
| // The test files always put a newline at the end of the expectation. |
| // Statements from the formatter (correctly) don't have that, so add |
| // one to line up with the expected result. |
| var actualText = actual.text; |
| if (!isCompilationUnit) actualText += "\n"; |
| |
| print("$path $description"); |
| drawRuler("before", pageWidth); |
| print(input); |
| if (actualText == expected.text) { |
| drawRuler("result", pageWidth); |
| print(actualText); |
| } else { |
| print("FAIL"); |
| drawRuler("expected", pageWidth); |
| print(expected.text); |
| drawRuler("actual", pageWidth); |
| print(actualText); |
| } |
| } |
| } |
| |
| /// Given a source string that contains ‹ and › to indicate a selection, returns |
| /// a [SourceCode] with the text (with the selection markers removed) and the |
| /// correct selection range. |
| SourceCode _extractSelection(String source, {bool isCompilationUnit: false}) { |
| var start = source.indexOf("‹"); |
| source = source.replaceAll("‹", ""); |
| |
| var end = source.indexOf("›"); |
| source = source.replaceAll("›", ""); |
| |
| return new SourceCode(source, |
| isCompilationUnit: isCompilationUnit, |
| selectionStart: start == -1 ? null : start, |
| selectionLength: end == -1 ? null : end - start); |
| } |