| Index: pkg/analysis_server/lib/src/services/correction/fix_internal.dart
|
| diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
|
| index 17c7822649c962ded4c1e1a764a52d0303d1e66a..b64f4289f66c8c1fade91fcb0184cd1e52ed53ee 100644
|
| --- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
|
| +++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
|
| @@ -697,14 +697,12 @@ class FixProcessor {
|
| }
|
| }
|
| // prepare location for a new constructor
|
| - _ConstructorLocation targetLocation =
|
| + _ClassMemberLocation targetLocation =
|
| _prepareNewConstructorLocation(classDeclaration);
|
| // build constructor source
|
| SourceBuilder sb = new SourceBuilder(file, targetLocation.offset);
|
| {
|
| - String indent = ' ';
|
| sb.append(targetLocation.prefix);
|
| - sb.append(indent);
|
| sb.append(classDeclaration.name.name);
|
| sb.append('(');
|
| sb.append(fieldNames.map((name) => 'this.$name').join(', '));
|
| @@ -743,19 +741,17 @@ class FixProcessor {
|
| if (targetTypeNode is! ClassDeclaration) {
|
| return;
|
| }
|
| - _ConstructorLocation targetLocation =
|
| + _ClassMemberLocation targetLocation =
|
| _prepareNewConstructorLocation(targetTypeNode);
|
| String targetFile = targetElement.source.fullName;
|
| // build method source
|
| SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset);
|
| {
|
| - String indent = ' ';
|
| sb.append(targetLocation.prefix);
|
| - sb.append(indent);
|
| sb.append(targetElement.name);
|
| _addFix_undefinedMethod_create_parameters(
|
| sb, instanceCreation.argumentList);
|
| - sb.append(') {$eol$indent}');
|
| + sb.append(');');
|
| sb.append(targetLocation.suffix);
|
| }
|
| // insert source
|
| @@ -801,15 +797,13 @@ class FixProcessor {
|
| if (targetTypeNode is! ClassDeclaration) {
|
| return;
|
| }
|
| - _ConstructorLocation targetLocation =
|
| + _ClassMemberLocation targetLocation =
|
| _prepareNewConstructorLocation(targetTypeNode);
|
| String targetFile = targetElement.source.fullName;
|
| // build method source
|
| SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset);
|
| {
|
| - String indent = ' ';
|
| sb.append(targetLocation.prefix);
|
| - sb.append(indent);
|
| sb.append(targetElement.name);
|
| sb.append('.');
|
| // append name
|
| @@ -820,7 +814,7 @@ class FixProcessor {
|
| }
|
| _addFix_undefinedMethod_create_parameters(
|
| sb, instanceCreation.argumentList);
|
| - sb.append(') {$eol$indent}');
|
| + sb.append(');');
|
| sb.append(targetLocation.suffix);
|
| }
|
| // insert source
|
| @@ -941,13 +935,11 @@ class FixProcessor {
|
| argumentsBuffer.append(parameterName);
|
| }
|
| // add proposal
|
| - _ConstructorLocation targetLocation =
|
| + _ClassMemberLocation targetLocation =
|
| _prepareNewConstructorLocation(targetClassNode);
|
| SourceBuilder sb = new SourceBuilder(file, targetLocation.offset);
|
| {
|
| - String indent = utils.getIndent(1);
|
| sb.append(targetLocation.prefix);
|
| - sb.append(indent);
|
| sb.append(targetClassName);
|
| if (!constructorName.isEmpty) {
|
| sb.startPosition('NAME');
|
| @@ -1025,7 +1017,8 @@ class FixProcessor {
|
| }
|
| ClassDeclaration targetClassNode = targetTypeNode;
|
| // prepare location
|
| - _FieldLocation targetLocation = _prepareNewFieldLocation(targetClassNode);
|
| + _ClassMemberLocation targetLocation =
|
| + _prepareNewFieldLocation(targetClassNode);
|
| // build method source
|
| String targetFile = targetClassElement.source.fullName;
|
| SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset);
|
| @@ -1157,7 +1150,8 @@ class FixProcessor {
|
| }
|
| ClassDeclaration targetClassNode = targetTypeNode;
|
| // prepare location
|
| - _FieldLocation targetLocation = _prepareNewGetterLocation(targetClassNode);
|
| + _ClassMemberLocation targetLocation =
|
| + _prepareNewGetterLocation(targetClassNode);
|
| // build method source
|
| String targetFile = targetClassElement.source.fullName;
|
| SourceBuilder sb = new SourceBuilder(targetFile, targetLocation.offset);
|
| @@ -1284,7 +1278,7 @@ class FixProcessor {
|
| // EOL management
|
| bool isFirst = true;
|
| void addEolIfNotFirst() {
|
| - if (!isFirst || !targetClass.members.isEmpty) {
|
| + if (!isFirst || _isClassWithEmptyBody(targetClass)) {
|
| sb.append(eol);
|
| }
|
| isFirst = false;
|
| @@ -2739,74 +2733,62 @@ class FixProcessor {
|
| return node is SimpleIdentifier && node.name == 'await';
|
| }
|
|
|
| - _ConstructorLocation _prepareNewConstructorLocation(
|
| - ClassDeclaration classDeclaration) {
|
| - List<ClassMember> members = classDeclaration.members;
|
| - // find the last field/constructor
|
| - ClassMember lastFieldOrConstructor = null;
|
| - for (ClassMember member in members) {
|
| - if (member is FieldDeclaration || member is ConstructorDeclaration) {
|
| - lastFieldOrConstructor = member;
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - // after the last field/constructor
|
| - if (lastFieldOrConstructor != null) {
|
| - return new _ConstructorLocation(
|
| - eol + eol, lastFieldOrConstructor.end, '');
|
| - }
|
| - // at the beginning of the class
|
| - String suffix = members.isEmpty ? '' : eol;
|
| - return new _ConstructorLocation(
|
| - eol, classDeclaration.leftBracket.end, suffix);
|
| + /**
|
| + * Return `true` if the given [classDeclaration] has open '{' and close '}'
|
| + * at the same line, e.g. `class X {}`.
|
| + */
|
| + bool _isClassWithEmptyBody(ClassDeclaration classDeclaration) {
|
| + return utils.getLineThis(classDeclaration.leftBracket.offset) ==
|
| + utils.getLineThis(classDeclaration.rightBracket.offset);
|
| }
|
|
|
| - _FieldLocation _prepareNewFieldLocation(ClassDeclaration classDeclaration) {
|
| + _ClassMemberLocation _prepareNewClassMemberLocation(
|
| + ClassDeclaration classDeclaration,
|
| + bool shouldSkip(ClassMember existingMember)) {
|
| String indent = utils.getIndent(1);
|
| - // find the last field
|
| - ClassMember lastFieldOrConstructor = null;
|
| + // Find the last target member.
|
| + ClassMember targetMember = null;
|
| List<ClassMember> members = classDeclaration.members;
|
| for (ClassMember member in members) {
|
| - if (member is FieldDeclaration) {
|
| - lastFieldOrConstructor = member;
|
| + if (shouldSkip(member)) {
|
| + targetMember = member;
|
| } else {
|
| break;
|
| }
|
| }
|
| - // after the last field
|
| - if (lastFieldOrConstructor != null) {
|
| - return new _FieldLocation(
|
| - eol + eol + indent, lastFieldOrConstructor.end, '');
|
| + // After the last target member.
|
| + if (targetMember != null) {
|
| + return new _ClassMemberLocation(eol + eol + indent, targetMember.end, '');
|
| }
|
| - // at the beginning of the class
|
| - String suffix = members.isEmpty ? '' : eol;
|
| - return new _FieldLocation(
|
| + // At the beginning of the class.
|
| + String suffix = members.isNotEmpty ||
|
| + _isClassWithEmptyBody(classDeclaration) ? eol : '';
|
| + return new _ClassMemberLocation(
|
| eol + indent, classDeclaration.leftBracket.end, suffix);
|
| }
|
|
|
| - _FieldLocation _prepareNewGetterLocation(ClassDeclaration classDeclaration) {
|
| - String indent = utils.getIndent(1);
|
| - // find an existing target member
|
| - ClassMember prevMember = null;
|
| - List<ClassMember> members = classDeclaration.members;
|
| - for (ClassMember member in members) {
|
| - if (member is FieldDeclaration ||
|
| - member is ConstructorDeclaration ||
|
| - member is MethodDeclaration && member.isGetter) {
|
| - prevMember = member;
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - // after the last field/getter
|
| - if (prevMember != null) {
|
| - return new _FieldLocation(eol + eol + indent, prevMember.end, '');
|
| - }
|
| - // at the beginning of the class
|
| - String suffix = members.isEmpty ? '' : eol;
|
| - return new _FieldLocation(
|
| - eol + indent, classDeclaration.leftBracket.end, suffix);
|
| + _ClassMemberLocation _prepareNewConstructorLocation(
|
| + ClassDeclaration classDeclaration) {
|
| + return _prepareNewClassMemberLocation(
|
| + classDeclaration,
|
| + (member) =>
|
| + member is FieldDeclaration || member is ConstructorDeclaration);
|
| + }
|
| +
|
| + _ClassMemberLocation _prepareNewFieldLocation(
|
| + ClassDeclaration classDeclaration) {
|
| + return _prepareNewClassMemberLocation(
|
| + classDeclaration, (member) => member is FieldDeclaration);
|
| + }
|
| +
|
| + _ClassMemberLocation _prepareNewGetterLocation(
|
| + ClassDeclaration classDeclaration) {
|
| + return _prepareNewClassMemberLocation(
|
| + classDeclaration,
|
| + (member) =>
|
| + member is FieldDeclaration ||
|
| + member is ConstructorDeclaration ||
|
| + member is MethodDeclaration && member.isGetter);
|
| }
|
|
|
| /**
|
| @@ -2928,6 +2910,17 @@ class LintNames {
|
| }
|
|
|
| /**
|
| + * Describes the location for a newly created [ClassMember].
|
| + */
|
| +class _ClassMemberLocation {
|
| + final String prefix;
|
| + final int offset;
|
| + final String suffix;
|
| +
|
| + _ClassMemberLocation(this.prefix, this.offset, this.suffix);
|
| +}
|
| +
|
| +/**
|
| * Helper for finding [Element] with name closest to the given.
|
| */
|
| class _ClosestElementFinder {
|
| @@ -2955,25 +2948,3 @@ class _ClosestElementFinder {
|
| }
|
| }
|
| }
|
| -
|
| -/**
|
| - * Describes the location for a newly created [ConstructorDeclaration].
|
| - */
|
| -class _ConstructorLocation {
|
| - final String prefix;
|
| - final int offset;
|
| - final String suffix;
|
| -
|
| - _ConstructorLocation(this.prefix, this.offset, this.suffix);
|
| -}
|
| -
|
| -/**
|
| - * Describes the location for a newly created [FieldDeclaration].
|
| - */
|
| -class _FieldLocation {
|
| - final String prefix;
|
| - final int offset;
|
| - final String suffix;
|
| -
|
| - _FieldLocation(this.prefix, this.offset, this.suffix);
|
| -}
|
|
|