Use parseString() API instead of internal Parser.
diff --git a/lib/src/dart_formatter.dart b/lib/src/dart_formatter.dart
index c602874..da00e20 100644
--- a/lib/src/dart_formatter.dart
+++ b/lib/src/dart_formatter.dart
@@ -7,16 +7,14 @@
import 'dart:math' as math;
import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/string_source.dart';
-import 'error_listener.dart';
import 'exceptions.dart';
import 'source_code.dart';
import 'source_visitor.dart';
@@ -87,8 +85,6 @@
/// Returns a new [SourceCode] containing the formatted code and the resulting
/// selection, if any.
SourceCode formatSource(SourceCode source) {
- var errorListener = ErrorListener();
-
// Enable all features that are enabled by default in the current analyzer
// version.
// TODO(paulberry): consider plumbing in experiment enable flags from the
@@ -98,46 +94,69 @@
'non-nullable',
]);
- // Tokenize the source.
- var reader = CharSequenceReader(source.text);
- var stringSource = StringSource(source.text, source.uri);
- var scanner = Scanner(stringSource, reader, errorListener);
- scanner.configureFeatures(featureSet);
- var startToken = scanner.tokenize();
- var lineInfo = LineInfo(scanner.lineStarts);
+ var inputOffset = 0;
+ var text = source.text;
+ var unitSourceCode = source;
+ if (!source.isCompilationUnit) {
+ var prefix = 'void foo() { ';
+ inputOffset = prefix.length;
+ text = '$prefix$text }';
+ unitSourceCode = SourceCode(
+ text,
+ uri: source.uri,
+ isCompilationUnit: false,
+ selectionStart: source.selectionStart != null
+ ? source.selectionStart + inputOffset
+ : null,
+ selectionLength: source.selectionLength,
+ );
+ }
+
+ // Parse it.
+ var parseResult = parseString(
+ content: text,
+ featureSet: featureSet,
+ path: source.uri,
+ throwIfDiagnostics: false,
+ );
// Infer the line ending if not given one. Do it here since now we know
// where the lines start.
if (lineEnding == null) {
// If the first newline is "\r\n", use that. Otherwise, use "\n".
- if (scanner.lineStarts.length > 1 &&
- scanner.lineStarts[1] >= 2 &&
- source.text[scanner.lineStarts[1] - 2] == '\r') {
+ var lineStarts = parseResult.lineInfo.lineStarts;
+ if (lineStarts.length > 1 &&
+ lineStarts[1] >= 2 &&
+ text[lineStarts[1] - 2] == '\r') {
lineEnding = '\r\n';
} else {
lineEnding = '\n';
}
}
- errorListener.throwIfErrors();
-
- // Parse it.
- var parser = Parser(stringSource, errorListener, featureSet: featureSet);
- parser.enableOptionalNewAndConst = true;
- parser.enableSetLiterals = true;
+ // Throw if there are syntactic errors.
+ var syntacticErrors = parseResult.errors.where((error) {
+ return error.errorCode.type == ErrorType.SYNTACTIC_ERROR;
+ }).toList();
+ if (syntacticErrors.isNotEmpty) {
+ throw FormatterException(syntacticErrors);
+ }
AstNode node;
if (source.isCompilationUnit) {
- node = parser.parseCompilationUnit(startToken);
+ node = parseResult.unit;
} else {
- node = parser.parseStatement(startToken);
+ var function = parseResult.unit.declarations[0] as FunctionDeclaration;
+ var body = function.functionExpression.body as BlockFunctionBody;
+ node = body.block.statements[0];
// Make sure we consumed all of the source.
var token = node.endToken.next;
- if (token.type != TokenType.EOF) {
+ if (token.type != TokenType.CLOSE_CURLY_BRACKET) {
+ var stringSource = StringSource(text, source.uri);
var error = AnalysisError(
stringSource,
- token.offset,
+ token.offset - inputOffset,
math.max(token.length, 1),
ParserErrorCode.UNEXPECTED_TOKEN,
[token.lexeme]);
@@ -146,10 +165,9 @@
}
}
- errorListener.throwIfErrors();
-
// Format it.
- var visitor = SourceVisitor(this, lineInfo, source);
+ var lineInfo = parseResult.lineInfo;
+ var visitor = SourceVisitor(this, lineInfo, unitSourceCode);
var output = visitor.run(node);
// Sanity check that only whitespace was changed if that's all we expect.
diff --git a/lib/src/error_listener.dart b/lib/src/error_listener.dart
deleted file mode 100644
index a1df699..0000000
--- a/lib/src/error_listener.dart
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2014, 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.src.error_listener;
-
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-
-import 'exceptions.dart';
-
-/// A simple [AnalysisErrorListener] that just collects the reported errors.
-class ErrorListener implements AnalysisErrorListener {
- final _errors = <AnalysisError>[];
-
- @override
- void onError(AnalysisError error) {
- // Fasta produces some semantic errors, which we want to ignore so that
- // users can format code containing static errors.
- if (error.errorCode.type != ErrorType.SYNTACTIC_ERROR) return;
-
- _errors.add(error);
- }
-
- /// Throws a [FormatterException] if any errors have been reported.
- void throwIfErrors() {
- if (_errors.isEmpty) return;
-
- throw FormatterException(_errors);
- }
-}