Skip to content

Commit

Permalink
Merge branch 'main' into analysis-options
Browse files Browse the repository at this point in the history
# Conflicts:
#	lib/src/language_version_cache.dart
  • Loading branch information
munificent committed Oct 7, 2024
2 parents 23637d1 + fb00aab commit 2e37ca3
Show file tree
Hide file tree
Showing 69 changed files with 418 additions and 110 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
matrix:
sdk: [3.4.0, dev]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938
- uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672
with:
sdk: ${{ matrix.sdk }}
Expand Down Expand Up @@ -52,7 +52,7 @@ jobs:
os: [ubuntu-latest]
sdk: [3.4.0, dev]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938
- uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672
with:
sdk: ${{ matrix.sdk }}
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@
If `--stdin-name` and `--language-version` are both omitted, then parses
stdin using the latest supported language version.

* **Apply class modifiers to API classes.** The dart_style package exposes only
a few classes in its public API: `DartFormatter`, `SourceCode`,
`FormatterException`, and `UnexpectedOutputException`. None were ever
intended to be extended or implemented. They are now all marked `final` to
make that intention explicit.

## 2.3.7

* Allow passing a language version to `DartFomatter()`. Formatted code will be
Expand Down
2 changes: 1 addition & 1 deletion lib/src/analysis_options/analysis_options_file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ Future<AnalysisOptions> readAnalysisOptions(

/// Exception thrown when an analysis options file contains a "package:" URI in
/// an include and resolving the URI to a file path failed.
class PackageResolutionException implements Exception {
final class PackageResolutionException implements Exception {
final String _message;

PackageResolutionException(this._message);
Expand Down
4 changes: 2 additions & 2 deletions lib/src/analysis_options/io_file_system.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:path/path.dart' as p;
import 'file_system.dart';

/// An implementation of [FileSystem] using `dart:io`.
class IOFileSystem implements FileSystem {
final class IOFileSystem implements FileSystem {
Future<IOFileSystemPath> makePath(String path) async =>
IOFileSystemPath._(path);

Expand Down Expand Up @@ -42,7 +42,7 @@ class IOFileSystem implements FileSystem {
/// An abstraction over a file path string, used by [IOFileSystem].
///
/// To create an instance of this, use [IOFileSystem.makePath()].
class IOFileSystemPath implements FileSystemPath {
final class IOFileSystemPath implements FileSystemPath {
/// The underlying physical file system path.
final String path;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/back_end/code.dart
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ enum _Marker { start, end }

/// Traverses a [Code] tree and produces the final string of output code and
/// the selection markers, if any.
class _StringBuilder {
final class _StringBuilder {
/// Pre-calculated whitespace strings for various common levels of
/// indentation.
///
Expand Down
4 changes: 2 additions & 2 deletions lib/src/back_end/code_writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import 'solution_cache.dart';
/// an instance of this class. It has methods that the piece can call to add
/// output text to the resulting code, recursively format child pieces, insert
/// whitespace, etc.
class CodeWriter {
final class CodeWriter {
final int _pageWidth;

/// Previously cached formatted subtrees.
Expand Down Expand Up @@ -415,7 +415,7 @@ enum Whitespace {
}

/// A level of indentation in the indentation stack.
class _Indent {
final class _Indent {
/// The total number of spaces of indentation.
final int indent;

Expand Down
2 changes: 1 addition & 1 deletion lib/src/back_end/solution.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import 'solution_cache.dart';
/// of the pieces in the tree so they can format themselves. That in turn
/// yields a total number of overflow characters, cost, and formatted output,
/// which are all stored here.
class Solution implements Comparable<Solution> {
final class Solution implements Comparable<Solution> {
/// The states that pieces have been bound to.
///
/// Note that order that keys are inserted into this map is significant. When
Expand Down
2 changes: 1 addition & 1 deletion lib/src/back_end/solution_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import 'solver.dart';
/// the same child Piece and wanting to format it separately with the same
/// indentation. When that happens, sharing this cache allows us to reuse that
/// cached subtree Solution.
class SolutionCache {
final class SolutionCache {
final _cache = <_Key, Solution>{};

/// Returns a previously cached solution for formatting [root] with leading
Expand Down
2 changes: 1 addition & 1 deletion lib/src/back_end/solver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const _maxAttempts = 10000;
/// use it across different Solutions. This enables us to both divide and
/// conquer the Piece tree and solve portions separately, while also
/// reusing work across different solutions.
class Solver {
final class Solver {
final SolutionCache _cache;

final int _pageWidth;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/cli/format_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import 'output.dart';
import 'show.dart';
import 'summary.dart';

class FormatCommand extends Command<int> {
final class FormatCommand extends Command<int> {
@override
String get name => 'format';

Expand Down
2 changes: 1 addition & 1 deletion lib/src/cli/formatter_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'summary.dart';
const dartStyleVersion = '2.3.7';

/// Global options that affect how the formatter produces and uses its outputs.
class FormatterOptions {
final class FormatterOptions {
/// The language version formatted code should be parsed at or `null` if not
/// specified.
final Version? languageVersion;
Expand Down
6 changes: 3 additions & 3 deletions lib/src/cli/summary.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import '../source_code.dart';
import 'formatter_options.dart';

/// The kind of summary shown after all formatting is complete.
class Summary {
final class Summary {
static const Summary none = Summary._();

/// Creates a Summary that tracks how many files were formatted and the total
Expand Down Expand Up @@ -41,7 +41,7 @@ class Summary {
}

/// Tracks how many files were formatted and the total time.
class _LineSummary extends Summary {
final class _LineSummary extends Summary {
final DateTime _start = DateTime.now();

/// The number of processed files.
Expand Down Expand Up @@ -81,7 +81,7 @@ class _LineSummary extends Summary {
}

/// Reports how long it took for format each file.
class _ProfileSummary implements Summary {
final class _ProfileSummary implements Summary {
/// The files that have been started but have not completed yet.
///
/// Maps a file label to the time that it started being formatted.
Expand Down
2 changes: 1 addition & 1 deletion lib/src/config_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import 'profile.dart';
///
/// This class also directly caches the language versions and page widths that
/// are then inferred from the package config and analysis_options.yaml files.
class ConfigCache {
final class ConfigCache {
/// The previously cached package config for all files immediately within a
/// given directory.
final Map<String, PackageConfig?> _directoryConfigs = {};
Expand Down
4 changes: 2 additions & 2 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const tallStyleExperimentFlag = 'tall-style';

/// Constants for the cost heuristics used to determine which set of splits is
/// most desirable.
class Cost {
final class Cost {
/// The cost of splitting after the `=>` in a lambda or arrow-bodied member.
///
/// We make this zero because there is already a span around the entire body
Expand Down Expand Up @@ -64,7 +64,7 @@ class Cost {
}

/// Constants for the number of spaces for various kinds of indentation.
class Indent {
final class Indent {
/// Reset back to no indentation.
static const none = 0;

Expand Down
22 changes: 20 additions & 2 deletions lib/src/dart_formatter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ import 'short/source_visitor.dart';
import 'source_code.dart';
import 'string_compare.dart' as string_compare;

/// Regular expression that matches a format width comment like:
///
/// // dart format width=123
final RegExp _widthCommentPattern = RegExp(r'^// dart format width=(\d+)$');

/// Dart source code formatter.
class DartFormatter {
final class DartFormatter {
/// The latest Dart language version that can be parsed and formatted by this
/// version of the formatter.
static final latestLanguageVersion = Version(3, 3, 0);
Expand Down Expand Up @@ -182,8 +187,21 @@ class DartFormatter {

SourceCode output;
if (experimentFlags.contains(tallStyleExperimentFlag)) {
// Look for a page width comment before the code.
int? pageWidthFromComment;
for (Token? comment = node.beginToken.precedingComments;
comment != null;
comment = comment.next) {
if (_widthCommentPattern.firstMatch(comment.lexeme) case var match?) {
// If integer parsing fails for some reason, the returned `null`
// means we correctly ignore the comment.
pageWidthFromComment = int.tryParse(match[1]!);
break;
}
}

var visitor = AstNodeVisitor(this, lineInfo, unitSourceCode);
output = visitor.run(unitSourceCode, node);
output = visitor.run(unitSourceCode, node, pageWidthFromComment);
} else {
var visitor = SourceVisitor(this, lineInfo, unitSourceCode);
output = visitor.run(node);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/debug.dart
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ String pieceTree(Piece piece) {
}

/// A stringified representation of a tree of pieces for debug output.
class _PieceDebugTree {
final class _PieceDebugTree {
final String label;
final List<_PieceDebugTree> children = [];

Expand Down
4 changes: 2 additions & 2 deletions lib/src/exceptions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:source_span/source_span.dart';

/// Thrown when one or more errors occurs while parsing the code to be
/// formatted.
class FormatterException implements Exception {
final class FormatterException implements Exception {
/// The [AnalysisError]s that occurred.
final List<AnalysisError> errors;

Expand Down Expand Up @@ -53,7 +53,7 @@ class FormatterException implements Exception {

/// Exception thrown when the internal sanity check that only whitespace
/// changes are made fails.
class UnexpectedOutputException implements Exception {
final class UnexpectedOutputException implements Exception {
/// The source being formatted.
final String _input;

Expand Down
9 changes: 6 additions & 3 deletions lib/src/front_end/ast_node_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import 'sequence_builder.dart';
/// To avoid this class becoming a monolith, functionality is divided into a
/// couple of mixins, one for each area of functionality. This class then
/// contains only shared state and the visitor methods for the AST.
class AstNodeVisitor extends ThrowingAstVisitor<void> with PieceFactory {
final class AstNodeVisitor extends ThrowingAstVisitor<void> with PieceFactory {
@override
final PieceWriter pieces;

Expand Down Expand Up @@ -66,7 +66,10 @@ class AstNodeVisitor extends ThrowingAstVisitor<void> with PieceFactory {
///
/// This is the only method that should be called externally. Everything else
/// is effectively private.
SourceCode run(SourceCode source, AstNode node) {
///
/// If there is a `// dart format width=123` comment before the formatted
/// code, then [pageWidthFromComment] is that width.
SourceCode run(SourceCode source, AstNode node, [int? pageWidthFromComment]) {
Profile.begin('AstNodeVisitor.run()');

Profile.begin('AstNodeVisitor build Piece tree');
Expand Down Expand Up @@ -123,7 +126,7 @@ class AstNodeVisitor extends ThrowingAstVisitor<void> with PieceFactory {
Profile.end('AstNodeVisitor build Piece tree');

// Finish writing and return the complete result.
var result = pieces.finish(source, unitPiece);
var result = pieces.finish(source, unitPiece, pageWidthFromComment);

Profile.end('AstNodeVisitor.run()');

Expand Down
2 changes: 1 addition & 1 deletion lib/src/front_end/chain_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import 'piece_factory.dart';
///
/// This lets us create a single [ChainPiece] for the entire series of dotted
/// operations, so that we can control splitting them or not as a unit.
class ChainBuilder {
final class ChainBuilder {
final PieceFactory _visitor;

/// The outermost expression being converted to a chain.
Expand Down
6 changes: 3 additions & 3 deletions lib/src/front_end/comment_writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import '../comment_type.dart';
/// construct. These get directly embedded in the [TextPiece] of the code being
/// written. When that [TextPiece] is output later, it will include the comments
/// as well.
class CommentWriter {
final class CommentWriter {
final LineInfo _lineInfo;

/// The tokens whose preceding comments have already been taken by calls to
Expand Down Expand Up @@ -147,7 +147,7 @@ class CommentWriter {

/// A comment in the source, with a bit of information about the surrounding
/// whitespace.
class SourceComment {
final class SourceComment {
/// The text of the comment, including `//`, `/*`, and `*/`.
final String text;

Expand Down Expand Up @@ -210,7 +210,7 @@ class SourceComment {
/// * 2 newlines between `/* c2 */` and `/* c3 */`
/// * Comment `/* c3 */`
/// * 3 newlines between `/* c3 */` and `b`
class CommentSequence extends ListBase<SourceComment> {
final class CommentSequence extends ListBase<SourceComment> {
static const CommentSequence empty = CommentSequence._([0], []);

/// The number of newlines between a pair of comments or the preceding or
Expand Down
2 changes: 1 addition & 1 deletion lib/src/front_end/delimited_list_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import 'piece_factory.dart';
/// delimiter token. Then call [add()] for each [AstNode] that is inside the
/// delimiters. The [rightBracket()] with the closing delimiter and finally
/// [build()] to get the resulting [ListPiece].
class DelimitedListBuilder {
final class DelimitedListBuilder {
final PieceFactory _visitor;

/// The opening bracket before the elements, if any.
Expand Down
3 changes: 2 additions & 1 deletion lib/src/front_end/piece_factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,8 @@ mixin PieceFactory {
pieces.token(catchKeyword);
pieces.space();

var parameters = DelimitedListBuilder(this);
var parameters = DelimitedListBuilder(
this, const ListStyle(commas: Commas.nonTrailing));
parameters.leftBracket(catchClause.leftParenthesis!);
if (catchClause.exceptionParameter case var exceptionParameter?) {
parameters.visit(exceptionParameter);
Expand Down
11 changes: 8 additions & 3 deletions lib/src/front_end/piece_writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import 'sequence_builder.dart';
///
/// Handles updating selection markers and attaching comments to the tokens
/// before and after the comments.
class PieceWriter {
final class PieceWriter {
final DartFormatter _formatter;

final SourceCode _source;
Expand Down Expand Up @@ -390,7 +390,11 @@ class PieceWriter {

/// Finishes writing and returns a [SourceCode] containing the final output
/// and updated selection, if any.
SourceCode finish(SourceCode source, Piece rootPiece) {
///
/// If there is a `// dart format width=123` comment before the formatted
/// code, then [pageWidthFromComment] is that width.
SourceCode finish(
SourceCode source, Piece rootPiece, int? pageWidthFromComment) {
if (debug.tracePieceBuilder) {
debug.log(debug.pieceTree(rootPiece));
}
Expand All @@ -399,7 +403,8 @@ class PieceWriter {

var cache = SolutionCache();
var solver = Solver(cache,
pageWidth: _formatter.pageWidth, leadingIndent: _formatter.indent);
pageWidth: pageWidthFromComment ?? _formatter.pageWidth,
leadingIndent: _formatter.indent);
var solution = solver.format(rootPiece);
var output = solution.code.build(source, _formatter.lineEnding);

Expand Down
2 changes: 1 addition & 1 deletion lib/src/front_end/sequence_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import 'piece_factory.dart';
/// separate statements inside the sequence. This lets us gracefully handle
/// indenting them and supporting blank lines around them the same way we handle
/// other statements or members in a sequence.
class SequenceBuilder {
final class SequenceBuilder {
final PieceFactory _visitor;

/// The opening bracket before the elements, if any.
Expand Down
2 changes: 1 addition & 1 deletion lib/src/piece/adjacent.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import '../back_end/code_writer.dart';
import 'piece.dart';

/// A simple piece that just writes its child pieces one after the other.
class AdjacentPiece extends Piece {
final class AdjacentPiece extends Piece {
final List<Piece> pieces;

AdjacentPiece(this.pieces);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/piece/assign.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ import 'piece.dart';
/// var [unsplitBlock] =
/// longOperand +
/// anotherOperand;
class AssignPiece extends Piece {
final class AssignPiece extends Piece {
/// Force the block left-hand side to split and allow the right-hand side to
/// split.
static const State _blockSplitLeft = State(1);
Expand Down
Loading

0 comments on commit 2e37ca3

Please sign in to comment.