Skip to content

Commit

Permalink
Support a fix to add a setter, both in extensions and elsewhere
Browse files Browse the repository at this point in the history
Change-Id: I94d7ec13a2bcf73b120be18facf473a4710a6e28
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/116053
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
  • Loading branch information
bwilkerson authored and commit-bot@chromium.org committed Sep 6, 2019
1 parent e227ffa commit eb60f05
Show file tree
Hide file tree
Showing 7 changed files with 619 additions and 2 deletions.
2 changes: 2 additions & 0 deletions pkg/analysis_server/lib/src/services/correction/fix.dart
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ class DartFixKind {
const FixKind('CREATE_MIXIN', 50, "Create mixin '{0}'");
static const CREATE_NO_SUCH_METHOD = const FixKind(
'CREATE_NO_SUCH_METHOD', 49, "Create 'noSuchMethod' method");
static const CREATE_SETTER =
const FixKind('CREATE_SETTER', 50, "Create setter '{0}'");
static const EXTEND_CLASS_FOR_MIXIN =
const FixKind('EXTEND_CLASS_FOR_MIXIN', 50, "Extend the class '{0}'");
static const IMPORT_ASYNC =
Expand Down
88 changes: 88 additions & 0 deletions pkg/analysis_server/lib/src/services/correction/fix_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ class FixProcessor extends BaseProcessor {
await _addFix_createGetter();
await _addFix_createFunction_forFunctionType();
await _addFix_createMixin();
await _addFix_createSetter();
await _addFix_importLibrary_withType();
await _addFix_importLibrary_withExtension();
await _addFix_importLibrary_withFunction();
Expand Down Expand Up @@ -532,9 +533,11 @@ class FixProcessor extends BaseProcessor {
if (errorCode == StaticTypeWarningCode.UNDEFINED_SETTER) {
await _addFix_undefinedClassAccessor_useSimilar();
await _addFix_createField();
await _addFix_createSetter();
}
if (errorCode == CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER) {
await _addFix_undefinedClassAccessor_useSimilar();
await _addFix_createSetter();
}
if (errorCode == CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER) {
await _addFix_convertFlutterChild();
Expand Down Expand Up @@ -2441,6 +2444,91 @@ class FixProcessor extends BaseProcessor {
}
}

Future<void> _addFix_createSetter() async {
if (node is! SimpleIdentifier) {
return;
}
SimpleIdentifier nameNode = node;
if (!nameNode.inSetterContext()) {
return;
}
// prepare target
Expression target;
{
AstNode nameParent = nameNode.parent;
if (nameParent is PrefixedIdentifier) {
target = nameParent.prefix;
} else if (nameParent is PropertyAccess) {
target = nameParent.realTarget;
}
}
// prepare target element
bool staticModifier = false;
Element targetElement;
if (target is ExtensionOverride) {
targetElement = target.staticElement;
} else if (target is Identifier &&
target.staticElement is ExtensionElement) {
targetElement = target.staticElement;
staticModifier = true;
} else if (target != null) {
// prepare target interface type
DartType targetType = target.staticType;
if (targetType is! InterfaceType) {
return;
}
targetElement = targetType.element;
// maybe static
if (target is Identifier) {
Identifier targetIdentifier = target;
Element targetElement = targetIdentifier.staticElement;
staticModifier = targetElement?.kind == ElementKind.CLASS;
}
} else {
targetElement =
getEnclosingClassElement(node) ?? getEnclosingExtensionElement(node);
if (targetElement == null) {
return;
}
staticModifier = _inStaticContext();
}
if (targetElement.librarySource.isInSystemLibrary) {
return;
}
// prepare target declaration
var targetDeclarationResult =
await sessionHelper.getElementDeclaration(targetElement);
if (targetDeclarationResult.node is! ClassOrMixinDeclaration &&
targetDeclarationResult.node is! ExtensionDeclaration) {
return;
}
CompilationUnitMember targetNode = targetDeclarationResult.node;
// prepare location
ClassMemberLocation targetLocation = CorrectionUtils(
targetDeclarationResult.resolvedUnit)
.prepareNewGetterLocation(targetNode); // Rename to "AccessorLocation"
// build method source
Source targetSource = targetElement.source;
String targetFile = targetSource.fullName;
String name = nameNode.name;
var changeBuilder = _newDartChangeBuilder();
await changeBuilder.addFileEdit(targetFile, (DartFileEditBuilder builder) {
builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) {
Expression parameterTypeNode = climbPropertyAccess(nameNode);
DartType parameterType =
_inferUndefinedExpressionType(parameterTypeNode);
builder.write(targetLocation.prefix);
builder.writeSetterDeclaration(name,
isStatic: staticModifier,
nameGroupName: 'NAME',
parameterType: parameterType,
parameterTypeGroupName: 'TYPE');
builder.write(targetLocation.suffix);
});
});
_addFixFromBuilder(changeBuilder, DartFixKind.CREATE_SETTER, args: [name]);
}

Future<void> _addFix_extendClassForMixin() async {
ClassDeclaration declaration =
node.thisOrAncestorOfType<ClassDeclaration>();
Expand Down
Loading

0 comments on commit eb60f05

Please sign in to comment.