blob: 8b6fb5086c73232250b548159bd85fdbb97ed9db [file] [log] [blame]
// Copyright (c) 2022, 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.
import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:collection/collection.dart';
class AddCallSuper extends CorrectionProducer {
var _addition = '';
@override
// Adding as the first statement is not predictably the correct action.
bool get canBeAppliedInBulk => false;
@override
// Adding as the first statement is not predictably the correct action.
bool get canBeAppliedToFile => false;
@override
List<Object> get fixArguments => [_addition];
@override
FixKind get fixKind => DartFixKind.ADD_CALL_SUPER;
@override
Future<void> compute(ChangeBuilder builder) async {
var node = this.node;
if (node is! SimpleIdentifier) return;
var methodDeclaration = node.thisOrAncestorOfType<MethodDeclaration>();
if (methodDeclaration == null) return;
var classElement = methodDeclaration
.thisOrAncestorOfType<ClassDeclaration>()
?.declaredElement;
if (classElement == null) return;
var name = Name(classElement.library.source.uri, node.name);
var overridden = InheritanceManager3().getInherited2(classElement, name);
if (overridden == null) return;
var overriddenParameters = overridden.parameters.map((p) => p.name);
var body = methodDeclaration.body;
var parameters = methodDeclaration.parameters?.parameters;
var argumentList = parameters
?.map((p) {
var name = p.identifier?.name;
if (overriddenParameters.contains(name)) {
return p.isNamed ? '$name: $name' : name;
}
return null;
})
.whereNotNull()
.join(', ') ??
'';
_addition = '${node.name}($argumentList)';
if (body is BlockFunctionBody) {
await _block(builder, body);
} else if (body is ExpressionFunctionBody) {
await _expression(builder, body);
}
}
Future<void> _block(ChangeBuilder builder, BlockFunctionBody body) async {
var location = utils.prepareNewStatementLocation(body.block, true);
await builder.addDartFileEdit(file, (builder) {
builder.addInsertion(location.offset, (builder) {
builder.write(location.prefix);
builder.write('super.$_addition;');
builder.write(location.suffix);
});
});
}
Future<void> _expression(
ChangeBuilder builder, ExpressionFunctionBody body) async {
var expression = body.expression;
var semicolon = body.semicolon;
var prefix = utils.getLinePrefix(expression.offset);
var prefixWithLine = eol + prefix + utils.getIndent(1);
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleReplacement(
range.startStart(body.functionDefinition, expression),
'{${prefixWithLine}super.$_addition;${prefixWithLine}return ');
builder.addSimpleReplacement(
range.endEnd(expression, semicolon ?? expression), ';$eol$prefix}');
});
}
}