Skip to content

Commit e8190bf

Browse files
authored
Remove uses of internal analyzer implementation. (#1787)
In the very rare case that a user called formatStatement() and gave the formatter something longer than a single statement, we need to throw a FormatException but don't actually have a diagnostic from the analyzer to use. To deal with that, it used to import some internal implementation libraries in order to conjure up a diagnostic. Instead, this has a local implementation of the necessary public analyzer classes. This will avoid dart_style being broken with analyzer 9.0.0 when that internal code changes.
1 parent de7e726 commit e8190bf

File tree

4 files changed

+71
-11
lines changed

4 files changed

+71
-11
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 3.1.4-wip
2+
3+
* Remove dependencies on analyzer internal implementation.
4+
15
## 3.1.3
26

37
* No longer format imports with configurations and a prefix in the wrong order.

lib/src/cli/formatter_options.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import 'show.dart';
1313
import 'summary.dart';
1414

1515
// Note: The following line of code is modified by tool/grind.dart.
16-
const dartStyleVersion = '3.1.3';
16+
const dartStyleVersion = '3.1.4';
1717

1818
/// Global options parsed from the command line that affect how the formatter
1919
/// produces and uses its outputs.

lib/src/dart_formatter.dart

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import 'package:analyzer/dart/ast/ast.dart';
99
import 'package:analyzer/dart/ast/token.dart';
1010
import 'package:analyzer/diagnostic/diagnostic.dart';
1111
import 'package:analyzer/error/error.dart';
12-
// ignore: implementation_imports
13-
import 'package:analyzer/src/dart/scanner/scanner.dart';
14-
// ignore: implementation_imports
15-
import 'package:analyzer/src/string_source.dart';
12+
import 'package:analyzer/source/source.dart';
13+
import 'package:analyzer/source/timestamped_data.dart';
14+
import 'package:path/path.dart' as p;
1615
import 'package:pub_semver/pub_semver.dart';
1716

1817
import 'exceptions.dart';
@@ -193,13 +192,16 @@ final class DartFormatter {
193192
// Make sure we consumed all of the source.
194193
var token = node.endToken.next!;
195194
if (token.type != TokenType.CLOSE_CURLY_BRACKET) {
196-
var stringSource = StringSource(text, source.uri);
197-
var error = Diagnostic.tmp(
198-
source: stringSource,
195+
var error = Diagnostic.forValues(
196+
source: _StringSource(text, source.uri ?? ''),
199197
offset: token.offset - inputOffset,
200198
length: math.max(token.length, 1),
201-
diagnosticCode: ParserErrorCode.unexpectedToken,
202-
arguments: [token.lexeme],
199+
diagnosticCode: _FormatterDiagnosticCode(
200+
name: 'UnexpectedToken',
201+
problemMessage: "Unexpected token '${token.lexeme}'.",
202+
uniqueName: 'ParserErrorCode.UNEXPECTED_TOKEN',
203+
),
204+
message: "Unexpected token '${token.lexeme}'.",
203205
);
204206
throw FormatterException([error]);
205207
}
@@ -273,3 +275,57 @@ enum TrailingCommas {
273275
/// trailing comma is preserved.
274276
preserve,
275277
}
278+
279+
/// A custom [DiagnosticCode] implementation to avoid depending on internal
280+
/// analyzer implementation.
281+
class _FormatterDiagnosticCode extends DiagnosticCode {
282+
_FormatterDiagnosticCode({
283+
required super.name,
284+
required super.problemMessage,
285+
required super.uniqueName,
286+
});
287+
288+
@override
289+
DiagnosticSeverity get severity => DiagnosticSeverity.ERROR;
290+
291+
@override
292+
DiagnosticType get type => DiagnosticType.SYNTACTIC_ERROR;
293+
}
294+
295+
/// An implementation of [Source] for an in-memory Dart string.
296+
///
297+
/// Mostly copied from `package:analyzer/lib/src/string_source.dart`. Copied
298+
/// here to avoid depending on internal implementation.
299+
class _StringSource extends Source {
300+
/// The content of the source.
301+
final String _contents;
302+
303+
@override
304+
final String fullName;
305+
306+
@override
307+
Uri get uri => p.toUri(fullName);
308+
309+
_StringSource(this._contents, this.fullName);
310+
311+
@override
312+
TimestampedData<String> get contents => TimestampedData(0, _contents);
313+
314+
@override
315+
int get hashCode => _contents.hashCode ^ fullName.hashCode;
316+
317+
@override
318+
String get shortName => fullName;
319+
320+
/// Return `true` if the given [object] is a string source that is equal to
321+
/// this source.
322+
@override
323+
bool operator ==(Object object) {
324+
return object is _StringSource &&
325+
object._contents == _contents &&
326+
object.fullName == fullName;
327+
}
328+
329+
@override
330+
bool exists() => true;
331+
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: dart_style
22
# Note: See tool/grind.dart for how to bump the version.
3-
version: 3.1.3
3+
version: 3.1.4-wip
44
description: >-
55
Opinionated, automatic Dart source code formatter.
66
Provides an API and a CLI tool.

0 commit comments

Comments
 (0)