Skip to content

Commit

Permalink
Align naming of helper functions. Put comments before "dynamic". More…
Browse files Browse the repository at this point in the history
… tests.
  • Loading branch information
lrhn committed Oct 1, 2018
1 parent 4de088a commit 06c3636
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 71 deletions.
141 changes: 73 additions & 68 deletions lib/src/source_visitor.dart
Expand Up @@ -1316,14 +1316,14 @@ class SourceVisitor extends ThrowingAstVisitor {
if (_formatter.fixes.contains(StyleFix.typedefs)) {
_simpleStatement(node, () {
// Inlined visitGenericTypeAlias
_writeGenericTypeAliasHeader(node.typedefKeyword, node.name,
_visitGenericTypeAliasHeader(node.typedefKeyword, node.name,
node.typeParameters, null, (node.returnType ?? node.name).offset);

space();

// Recursively convert function-arguments to Function syntax.
_insideNewTypedefFix = true;
_writeGenericFunctionType(
_visitGenericFunctionType(
node.returnType, null, node.name.offset, null, node.parameters);
_insideNewTypedefFix = false;
});
Expand Down Expand Up @@ -1378,40 +1378,14 @@ class SourceVisitor extends ThrowingAstVisitor {
}

visitGenericFunctionType(GenericFunctionType node) {
_writeGenericFunctionType(node.returnType, node.functionKeyword, null,
_visitGenericFunctionType(node.returnType, node.functionKeyword, null,
node.typeParameters, node.parameters);
}

/// Writes a `Function` function type.
///
/// Used also by a fix, so there may not be a [functionKeyword].
/// In that case [functionKeywordPosition] should be the source position
/// used for the inserted "Function" text.
void _writeGenericFunctionType(
AstNode returnType,
Token functionKeyword,
int functionKeywordPosition,
TypeParameterList typeParameters,
FormalParameterList parameters) {
builder.startLazyRule();
builder.nestExpression();

visit(returnType, after: split);
if (functionKeyword != null) {
token(functionKeyword);
} else {
_writeText("Function", functionKeywordPosition);
}

builder.unnest();
builder.endRule();
_visitParameterSignature(typeParameters, parameters);
}

visitGenericTypeAlias(GenericTypeAlias node) {
visitNodes(node.metadata, between: newline, after: newline);
_simpleStatement(node, () {
_writeGenericTypeAliasHeader(node.typedefKeyword, node.name,
_visitGenericTypeAliasHeader(node.typedefKeyword, node.name,
node.typeParameters, node.equals, null);

space();
Expand All @@ -1420,35 +1394,6 @@ class SourceVisitor extends ThrowingAstVisitor {
});
}

/// Writes the header of a new-style typedef.
///
/// Also used by a fix so there may not be an [equals] token.
/// If [equals] is `null`, then [equalsPosition] must be a
/// position to use for the inserted text "=".
void _writeGenericTypeAliasHeader(Token typedefKeyword, AstNode name,
AstNode typeParameters, Token equals, int equalsPosition) {
token(typedefKeyword);
space();

// If the typedef's type parameters split, split after the "=" too,
// mainly to ensure the function's type parameters and parameters get
// end up on successive lines with the same indentation.
builder.startRule();

visit(name);

visit(typeParameters);
split();

if (equals != null) {
token(equals);
} else {
_writeText("=", equalsPosition);
}

builder.endRule();
}

visitHideCombinator(HideCombinator node) {
_visitCombinator(node.keyword, node.hiddenNames);
}
Expand Down Expand Up @@ -1918,19 +1863,24 @@ class SourceVisitor extends ThrowingAstVisitor {
modifier(node.covariantKeyword);
modifier(node.keyword);

visit(node.type);
bool hasType = node.type != null;
if (_insideNewTypedefFix && !hasType) {
_writeText("dynamic", node.identifier.offset);
hasType = true;
}
// In function declarations and the old typedef syntax, you can have a
// parameter name without a type. In the new syntax, you can have a type
// without a name. Add "dynamic" in that case.

// Ensure comments on the identifier comes before the inserted type.
token(node.identifier.token, before: () {
_writeText("dynamic", node.identifier.offset);
split();
});
} else {
visit(node.type);

// In function declarations and the old typedef syntax, you can have a
// parameter name without a type. In the new syntax, you can have a type
// without a name. Handle both cases.
if (hasType && node.identifier != null) split();
if (hasType && node.identifier != null) split();

visit(node.identifier);
visit(node.identifier);
}
builder.unnest();
builder.endRule();
});
Expand Down Expand Up @@ -2672,6 +2622,61 @@ class SourceVisitor extends ThrowingAstVisitor {
}
}

/// Writes a `Function` function type.
///
/// Used also by a fix, so there may not be a [functionKeyword].
/// In that case [functionKeywordPosition] should be the source position
/// used for the inserted "Function" text.
void _visitGenericFunctionType(
AstNode returnType,
Token functionKeyword,
int functionKeywordPosition,
TypeParameterList typeParameters,
FormalParameterList parameters) {
builder.startLazyRule();
builder.nestExpression();

visit(returnType, after: split);
if (functionKeyword != null) {
token(functionKeyword);
} else {
_writeText("Function", functionKeywordPosition);
}

builder.unnest();
builder.endRule();
_visitParameterSignature(typeParameters, parameters);
}

/// Writes the header of a new-style typedef.
///
/// Also used by a fix so there may not be an [equals] token.
/// If [equals] is `null`, then [equalsPosition] must be a
/// position to use for the inserted text "=".
void _visitGenericTypeAliasHeader(Token typedefKeyword, AstNode name,
AstNode typeParameters, Token equals, int equalsPosition) {
token(typedefKeyword);
space();

// If the typedef's type parameters split, split after the "=" too,
// mainly to ensure the function's type parameters and parameters get
// end up on successive lines with the same indentation.
builder.startRule();

visit(name);

visit(typeParameters);
split();

if (equals != null) {
token(equals);
} else {
_writeText("=", equalsPosition);
}

builder.endRule();
}

/// Gets the cost to split at an assignment (or `:` in the case of a named
/// default value) with the given [rightHandSide].
///
Expand Down
3 changes: 2 additions & 1 deletion lib/src/style_fix.dart
@@ -1,4 +1,5 @@
// Copyright (c) 2018, 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.

Expand All @@ -19,7 +20,7 @@ class StyleFix {
"doc-comments", 'Use triple slash for documentation comments.');

static const typedefs =
const StyleFix._("typedefs", "Use new typedef syntax for typedefs");
const StyleFix._("typedefs", 'Use new typedef syntax for typedefs.');

static const all = const [
namedDefaultSeparator,
Expand Down
60 changes: 58 additions & 2 deletions test/fixes/typedefs.unit
Expand Up @@ -155,9 +155,37 @@ typedef S Foo<S extends num>(S x);
typedef Foo<S extends num> = S Function(
S x);
>>> named argument
typedef int Foo(x);
typedef int Foo({x});
<<<
typedef Foo = int Function(dynamic x);
typedef Foo = int Function({dynamic x});
>>> optional positional argument
typedef int Foo([x]);
<<<
typedef Foo = int Function([dynamic x]);
>>> metadata and keywords
typedef int Foo(@meta v1, final v2, var v3, /*c*/ v4);
<<<
typedef Foo = int Function(
@meta dynamic v1,
final dynamic v2,
var dynamic v3,
/*c*/ dynamic v4);
>>> metadata and keywords optional positional
typedef int Foo([@meta v1, final v2, var v3, /*c*/ v4]);
<<<
typedef Foo = int Function(
[@meta dynamic v1,
final dynamic v2,
var dynamic v3,
/*c*/ dynamic v4]);
>>> metadata and keywords named
typedef int Foo({@meta v1, final v2, var v3, /*c*/ v4});
<<<
typedef Foo = int Function(
{@meta dynamic v1,
final dynamic v2,
var dynamic v3,
/*c*/ dynamic v4});
>>> function argument
typedef int Foo(int callback(int x));
<<<
Expand Down Expand Up @@ -193,3 +221,31 @@ typedef Foo(foo(x));
<<<
typedef Foo = Function(
Function(dynamic x) foo);
>>> block comments in typedef
typedef/*0*/void/*1*/Foo/*2*/<T>/*3*/(/*4*/T/*5*/foo(/*6*/x));
<<<
typedef /*1*/ Foo /*2*/ <T>
= /*0*/ void Function /*3*/ (
/*4*/ T Function(
/*6*/ dynamic x) /*5*/ foo);
>>> eol comments in typedef
typedef//0
void//1
Foo//2
<T>//3
(//4
T//5
foo(//6
x));
<<<
typedef //1
Foo //2
<T>
= //0
void Function //3
(
//4
T Function(
//6
dynamic x) //5
foo);

0 comments on commit 06c3636

Please sign in to comment.