Skip to content

Commit

Permalink
Augment. Store 'augmentationTargetAny', check type in 'augmentationTa…
Browse files Browse the repository at this point in the history
…rget'.

So, we can distinguish "no target" from "invalid target".

If we augment a setter, and there is no target, we also probe getters
(and methods, constructors). Which theoretically is not the same as
augmenting e.g. a class with a mixin - they live in different names.
Not sure. Maybe don't look for `name` when `name=`?
The difference is that we will report "No augmentation target" vs
"It is wrong when a setter augments a method".

Change-Id: Ibee84b2d039cf16824cb367fefdcda72b99f54bf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364603
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
  • Loading branch information
scheglov authored and Commit Queue committed Apr 26, 2024
1 parent 307d739 commit 4432585
Show file tree
Hide file tree
Showing 10 changed files with 1,104 additions and 124 deletions.
2 changes: 1 addition & 1 deletion pkg/analyzer/lib/src/dart/analysis/driver.dart
Expand Up @@ -95,7 +95,7 @@ import 'package:meta/meta.dart';
// TODO(scheglov): Clean up the list of implicitly analyzed files.
class AnalysisDriver {
/// The version of data format, should be incremented on every format change.
static const int DATA_VERSION = 359;
static const int DATA_VERSION = 360;

/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
Expand Down
23 changes: 19 additions & 4 deletions pkg/analyzer/lib/src/dart/element/element.dart
Expand Up @@ -56,14 +56,15 @@ import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/inference_error.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/utilities/extensions/collection.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';

/// Shared implementation of `augmentation` and `augmentationTarget`.
mixin AugmentableElement<T extends ElementImpl> on ElementImpl {
T? _augmentation;
T? _augmentationTarget;
ElementImpl? _augmentationTargetAny;

T? get augmentation {
linkedData?.read(this);
Expand All @@ -75,12 +76,16 @@ mixin AugmentableElement<T extends ElementImpl> on ElementImpl {
}

T? get augmentationTarget {
return augmentationTargetAny.ifTypeOrNull();
}

ElementImpl? get augmentationTargetAny {
linkedData?.read(this);
return _augmentationTarget;
return _augmentationTargetAny;
}

set augmentationTarget(T? value) {
_augmentationTarget = value;
set augmentationTargetAny(ElementImpl? value) {
_augmentationTargetAny = value;
}

bool get isAugmentation {
Expand Down Expand Up @@ -6332,6 +6337,16 @@ class PropertyAccessorElementImpl extends ExecutableElementImpl
isSynthetic = true;
}

@override
PropertyAccessorElementImpl? get augmentationTarget {
if (super.augmentationTarget case var target?) {
if (target.kind == kind) {
return target;
}
}
return null;
}

@override
PropertyAccessorElement? get correspondingGetter {
if (isGetter) {
Expand Down
88 changes: 68 additions & 20 deletions pkg/analyzer/lib/src/summary2/augmentation.dart
Expand Up @@ -7,6 +7,7 @@ import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';

class AugmentedClassDeclarationBuilder
extends AugmentedInstanceDeclarationBuilder {
Expand Down Expand Up @@ -97,21 +98,38 @@ class AugmentedExtensionTypeDeclarationBuilder
abstract class AugmentedInstanceDeclarationBuilder {
final Map<String, FieldElementImpl> fields = {};
final Map<String, ConstructorElementImpl> constructors = {};
final Map<String, PropertyAccessorElementImpl> accessors = {};
final Map<String, PropertyAccessorElementImpl> getters = {};
final Map<String, PropertyAccessorElementImpl> setters = {};
final Map<String, MethodElementImpl> methods = {};

void addAccessors(List<PropertyAccessorElementImpl> elements) {
for (var element in elements) {
var name = element.name;
if (element.isAugmentation) {
var existing = accessors[name];
if (existing != null) {
existing.augmentation = element;
element.augmentationTarget = existing;
element.variable2 = existing.variable2;
if (element.isGetter) {
if (element.isAugmentation) {
if (getters[name] case var target?) {
target.augmentation = element;
element.augmentationTargetAny = target;
element.variable2 = target.variable2;
} else {
var target = _recoveryAugmentationTarget(name);
element.augmentationTargetAny = target;
}
}
getters[name] = element;
} else {
if (element.isAugmentation) {
if (setters[name] case var target?) {
target.augmentation = element;
element.augmentationTargetAny = target;
element.variable2 = target.variable2;
} else {
var target = _recoveryAugmentationTarget(name);
element.augmentationTargetAny = target;
}
}
setters[name] = element;
}
accessors[name] = element;
}
}

Expand All @@ -122,7 +140,7 @@ abstract class AugmentedInstanceDeclarationBuilder {
var existing = constructors[name];
if (existing != null) {
existing.augmentation = element;
element.augmentationTarget = existing;
element.augmentationTargetAny = existing;
}
}
constructors[name] = element;
Expand All @@ -136,7 +154,7 @@ abstract class AugmentedInstanceDeclarationBuilder {
var existing = fields[name];
if (existing != null) {
existing.augmentation = element;
element.augmentationTarget = existing;
element.augmentationTargetAny = existing;
}
}
fields[name] = element;
Expand All @@ -147,10 +165,12 @@ abstract class AugmentedInstanceDeclarationBuilder {
for (var element in elements) {
var name = element.name;
if (element.isAugmentation) {
var existing = methods[name];
if (existing != null) {
existing.augmentation = element;
element.augmentationTarget = existing;
if (methods[name] case var target?) {
target.augmentation = element;
element.augmentationTargetAny = target;
} else {
var target = _recoveryAugmentationTarget(name);
element.augmentationTargetAny = target;
}
}
methods[name] = element;
Expand Down Expand Up @@ -192,6 +212,17 @@ abstract class AugmentedInstanceDeclarationBuilder {
return augmented;
}

ElementImpl? _recoveryAugmentationTarget(String name) {
name = name.removeSuffix('=') ?? name;

ElementImpl? target;
target ??= getters[name];
target ??= setters['$name='];
target ??= constructors[name];
target ??= methods[name];
return target;
}

void _updatedAugmented(InstanceElementImpl augmentation) {
assert(augmentation.augmentationTarget != null);
var augmented = _ensureAugmented(augmentation);
Expand Down Expand Up @@ -284,17 +315,34 @@ class AugmentedMixinDeclarationBuilder
}

class AugmentedTopVariablesBuilder {
final Map<String, ElementImpl> augmentationTargets;
final Map<String, TopLevelVariableElementImpl> variables = {};
final Map<String, PropertyAccessorElementImpl> accessors = {};

AugmentedTopVariablesBuilder(this.augmentationTargets);

void addAccessor(PropertyAccessorElementImpl element) {
var name = element.name;
if (element.isAugmentation) {
var existing = accessors[name];
if (existing != null) {
existing.augmentation = element;
element.augmentationTarget = existing;
element.variable2 = existing.variable2;
ElementImpl? target = accessors[name];
// Recovery.
if (target == null) {
if (name.removeSuffix('=') case var getterName?) {
target ??= accessors[getterName];
target ??= augmentationTargets[getterName];
} else {
target ??= accessors['$name='];
target ??= augmentationTargets[name];
}
}

if (target is PropertyAccessorElementImpl &&
target.isGetter == element.isGetter) {
target.augmentation = element;
element.augmentationTargetAny = target;
element.variable2 = target.variable2;
} else {
element.augmentationTargetAny = target;
}
}
accessors[name] = element;
Expand All @@ -306,7 +354,7 @@ class AugmentedTopVariablesBuilder {
var existing = variables[name];
if (existing != null) {
existing.augmentation = element;
element.augmentationTarget = existing;
element.augmentationTargetAny = existing;
}
}
variables[name] = element;
Expand Down
36 changes: 18 additions & 18 deletions pkg/analyzer/lib/src/summary2/bundle_reader.dart
Expand Up @@ -147,7 +147,7 @@ class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
element.supertype = reader._readOptionalInterfaceType();
element.mixins = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
element.augmentationTarget = reader.readElement() as ClassElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
element.augmentation = reader.readElement() as ClassElementImpl?;

if (element.augmentationTarget == null) {
Expand Down Expand Up @@ -215,8 +215,7 @@ class ConstructorElementLinkedData
element.redirectedConstructor = reader.readElement() as ConstructorElement?;
element.constantInitializers = reader._readNodeList();
element.augmentation = reader.readElement() as ConstructorElementImpl?;
element.augmentationTarget =
reader.readElement() as ConstructorElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
applyConstantOffsets?.perform();
}
}
Expand Down Expand Up @@ -351,7 +350,7 @@ class EnumElementLinkedData extends ElementLinkedData<EnumElementImpl> {
element.supertype = reader._readOptionalInterfaceType();
element.mixins = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
element.augmentationTarget = reader.readElement() as EnumElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
element.augmentation = reader.readElement() as EnumElementImpl?;
if (element.augmentationTarget == null) {
if (reader.readBool()) {
Expand Down Expand Up @@ -391,7 +390,7 @@ class ExtensionElementLinkedData
unitElement: element.enclosingElement,
);
_readTypeParameters(reader, element.typeParameters);
element.augmentationTarget = reader.readElement() as ExtensionElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
element.augmentation = reader.readElement() as ExtensionElementImpl?;
if (element.augmentationTarget == null) {
var extendedType = reader.readRequiredType();
Expand Down Expand Up @@ -432,8 +431,7 @@ class ExtensionTypeElementLinkedData
);
_readTypeParameters(reader, element.typeParameters);
element.interfaces = reader._readInterfaceTypeList();
element.augmentationTarget =
reader.readElement() as ExtensionTypeElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
element.augmentation = reader.readElement() as ExtensionTypeElementImpl?;
if (element.augmentationTarget == null) {
if (reader.readBool()) {
Expand Down Expand Up @@ -478,10 +476,10 @@ class FieldElementLinkedData extends ElementLinkedData<FieldElementImpl> {
element.macroDiagnostics = reader.readMacroDiagnostics();
element.type = reader.readRequiredType();

var augmentationTarget = reader.readElement();
var augmentationTarget = reader.readElement() as ElementImpl?;
element.augmentationTargetAny = augmentationTarget;
if (augmentationTarget is FieldElementImpl) {
augmentationTarget.augmentation = element;
element.augmentationTarget = augmentationTarget;
}

if (element is ConstFieldElementImpl) {
Expand Down Expand Up @@ -520,7 +518,7 @@ class FunctionElementLinkedData extends ElementLinkedData<FunctionElementImpl> {
element.returnType = reader.readRequiredType();
_readFormalParameters(reader, element.parameters);
element.augmentation = reader.readElement() as FunctionElementImpl?;
element.augmentationTarget = reader.readElement() as FunctionElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
applyConstantOffsets?.perform();
}
}
Expand Down Expand Up @@ -1879,7 +1877,7 @@ class MethodElementLinkedData extends ElementLinkedData<MethodElementImpl> {
_readFormalParameters(reader, element.parameters);
element.returnType = reader.readRequiredType();
element.augmentation = reader.readElement() as MethodElementImpl?;
element.augmentationTarget = reader.readElement() as MethodElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
applyConstantOffsets?.perform();
}
}
Expand Down Expand Up @@ -1908,7 +1906,7 @@ class MixinElementLinkedData extends ElementLinkedData<MixinElementImpl> {
_readTypeParameters(reader, element.typeParameters);
element.superclassConstraints = reader._readInterfaceTypeList();
element.interfaces = reader._readInterfaceTypeList();
element.augmentationTarget = reader.readElement() as MixinElementImpl?;
element.augmentationTargetAny = reader.readElement() as ElementImpl?;
element.augmentation = reader.readElement() as MixinElementImpl?;

if (element.augmentationTarget == null) {
Expand Down Expand Up @@ -1954,11 +1952,13 @@ class PropertyAccessorElementLinkedData
element.returnType = reader.readRequiredType();
_readFormalParameters(reader, element.parameters);

var augmentationTarget = reader.readElement();
var augmentationTarget = reader.readElement() as ElementImpl?;
element.augmentationTargetAny = augmentationTarget;
if (augmentationTarget is PropertyAccessorElementImpl) {
augmentationTarget.augmentation = element;
element.augmentationTarget = augmentationTarget;
element.variable2 = augmentationTarget.variable2;
if (augmentationTarget.kind == element.kind) {
augmentationTarget.augmentation = element;
element.variable2 = augmentationTarget.variable2;
}
}

applyConstantOffsets?.perform();
Expand Down Expand Up @@ -2615,10 +2615,10 @@ class TopLevelVariableElementLinkedData
element.macroDiagnostics = reader.readMacroDiagnostics();
element.type = reader.readRequiredType();

var augmentationTarget = reader.readElement();
var augmentationTarget = reader.readElement() as ElementImpl?;
element.augmentationTargetAny = augmentationTarget;
if (augmentationTarget is TopLevelVariableElementImpl) {
augmentationTarget.augmentation = element;
element.augmentationTarget = augmentationTarget;
}

if (element is ConstTopLevelVariableElementImpl) {
Expand Down

0 comments on commit 4432585

Please sign in to comment.