Give private parameters public names for constructor.

R=brianwilkerson@google.com

Bug: https://github.com/flutter/flutter-intellij/issues/2284
Change-Id: I091c1f557266aa2442ad0fd047ca745996332f4d
Reviewed-on: https://dart-review.googlesource.com/57040
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2018-05-29 19:34:36 +00:00 committed by commit-bot@chromium.org
parent 7b33203f8e
commit 17afa8ef56
2 changed files with 141 additions and 4 deletions

View file

@ -266,6 +266,29 @@ class ExtractWidgetRefactoringImpl extends RefactoringImpl
}
}
// Collect used public names.
var usedNames = new Set<String>();
for (var parameter in _parameters) {
if (!parameter.name.startsWith('_')) {
usedNames.add(parameter.name);
}
}
// Give each private parameter a public name for the constructor.
for (var parameter in _parameters) {
var name = parameter.name;
if (name.startsWith('_')) {
var baseName = name.substring(1);
for (var i = 1;; i++) {
name = i == 1 ? baseName : '$baseName$i';
if (usedNames.add(name)) {
break;
}
}
}
parameter.constructorName = name;
}
return collector.status;
}
@ -334,18 +357,33 @@ class ExtractWidgetRefactoringImpl extends RefactoringImpl
builder.writeln(',');
// Add parameters for fields, local, and method parameters.
for (int i = 0; i < _parameters.length; i++) {
for (var parameter in _parameters) {
builder.write(' ');
builder.write('@');
builder.writeReference(accessorRequired);
builder.write(' this.');
builder.write(_parameters[i].name);
builder.write(' ');
if (parameter.constructorName != parameter.name) {
builder.writeType(parameter.type);
builder.write(' ');
builder.write(parameter.constructorName);
} else {
builder.write('this.');
builder.write(parameter.name);
}
builder.writeln(',');
}
builder.write(' }');
},
initializerWriter: () {
for (var parameter in _parameters) {
if (parameter.constructorName != parameter.name) {
builder.write(parameter.name);
builder.write(' = ');
builder.write(parameter.constructorName);
builder.write(', ');
}
}
builder.write('super(key: key)');
},
);
@ -407,7 +445,7 @@ class ExtractWidgetRefactoringImpl extends RefactoringImpl
if (parameter != _parameters.first) {
builder.write(', ');
}
builder.write(parameter.name);
builder.write(parameter.constructorName);
builder.write(': ');
builder.write(parameter.name);
}
@ -433,12 +471,19 @@ class _MethodInvocationsCollector extends RecursiveAstVisitor<void> {
}
class _Parameter {
/// The name which is used to reference this parameter in the expression
/// being extracted, and also the name of the field in the new widget.
final String name;
final DartType type;
/// Whether the parameter is a parameter of the method being extracted.
final bool isMethodParameter;
/// If the [name] is private, the public name to use in the new widget
/// constructor. If the [name] is already public, then the [name].
String constructorName;
_Parameter(this.name, this.type, {this.isMethodParameter: false});
}

View file

@ -915,6 +915,98 @@ class MyWidget extends StatelessWidget {
assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
}
test_parameters_private() async {
addFlutterPackage();
await indexTestUnit(r'''
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
String _field;
@override
Widget build(BuildContext context) {
return new Text(_field);
}
}
''');
_createRefactoringForStringOffset('new Text');
await _assertSuccessfulRefactoring('''
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
String _field;
@override
Widget build(BuildContext context) {
return new Test(field: _field);
}
}
class Test extends StatelessWidget {
const Test({
Key key,
@required String field,
}) : _field = field, super(key: key);
final String _field;
@override
Widget build(BuildContext context) {
return new Text(_field);
}
}
''');
}
test_parameters_private_conflictWithPublic() async {
addFlutterPackage();
await indexTestUnit(r'''
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
int field;
String _field;
@override
Widget build(BuildContext context) {
return new Text('$field $_field');
}
}
''');
_createRefactoringForStringOffset('new Text');
await _assertSuccessfulRefactoring(r'''
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
int field;
String _field;
@override
Widget build(BuildContext context) {
return new Test(field: field, field2: _field);
}
}
class Test extends StatelessWidget {
const Test({
Key key,
@required this.field,
@required String field2,
}) : _field = field2, super(key: key);
final int field;
final String _field;
@override
Widget build(BuildContext context) {
return new Text('$field $_field');
}
}
''');
}
test_parameters_readField_readLocal() async {
addFlutterPackage();
await indexTestUnit(r'''