| Index: pkg/analyzer/lib/src/dart/element/element.dart
|
| diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
|
| index 9677e893fea33b68fae76034c98569be2a5fee91..4b031464d10b1cabaeda8af3d800bd811258c55a 100644
|
| --- a/pkg/analyzer/lib/src/dart/element/element.dart
|
| +++ b/pkg/analyzer/lib/src/dart/element/element.dart
|
| @@ -1789,11 +1789,12 @@ abstract class ElementImpl implements Element {
|
|
|
| /**
|
| * Set the enclosing element of this element to the given [element].
|
| + *
|
| + * Throws [FrozenHashCodeException] if the hashCode can't be changed.
|
| */
|
| void set enclosingElement(Element element) {
|
| _enclosingElement = element as ElementImpl;
|
| - _cachedLocation = null;
|
| - _cachedHashCode = null;
|
| + _updateCaches();
|
| }
|
|
|
| @override
|
| @@ -1865,10 +1866,15 @@ abstract class ElementImpl implements Element {
|
| @override
|
| String get name => _name;
|
|
|
| +
|
| + /**
|
| + * Changes the name of this element.
|
| + *
|
| + * Throws [FrozenHashCodeException] if the hashCode can't be changed.
|
| + */
|
| void set name(String name) {
|
| this._name = name;
|
| - _cachedLocation = null;
|
| - _cachedHashCode = null;
|
| + _updateCaches();
|
| }
|
|
|
| @override
|
| @@ -1880,11 +1886,12 @@ abstract class ElementImpl implements Element {
|
| /**
|
| * Sets the offset of the name of this element in the file that contains the
|
| * declaration of this element.
|
| + *
|
| + * Throws [FrozenHashCodeException] if the hashCode can't be changed.
|
| */
|
| void set nameOffset(int offset) {
|
| _nameOffset = offset;
|
| - _cachedHashCode = null;
|
| - _cachedLocation = null;
|
| + _updateCaches();
|
| }
|
|
|
| @override
|
| @@ -2045,6 +2052,35 @@ abstract class ElementImpl implements Element {
|
| void visitChildren(ElementVisitor visitor) {
|
| // There are no children to visit
|
| }
|
| +
|
| + /**
|
| + * Updates cached values after an input changed.
|
| + *
|
| + * Throws [FrozenHashCodeException] if not allowed.
|
| + */
|
| + void _updateCaches() {
|
| + if (!hasModifier(Modifier.CACHE_KEY)) {
|
| + // Fast path.
|
| + _cachedLocation = null;
|
| + _cachedHashCode = null;
|
| + return;
|
| + }
|
| +
|
| + // Save originals.
|
| + ElementLocation oldLocation = _cachedLocation;
|
| + int oldHashCode = _cachedHashCode;
|
| +
|
| + _cachedLocation = null;
|
| + _cachedHashCode = null;
|
| +
|
| + if (oldHashCode != hashCode) {
|
| + // Prevent cache corruption by restoring originals.
|
| + _cachedLocation = oldLocation;
|
| + _cachedHashCode = oldHashCode;
|
| + throw new FrozenHashCodeException(
|
| + "can't update hashCode for a cache key: $this ($runtimeType)");
|
| + }
|
| + }
|
| }
|
|
|
| /**
|
| @@ -2575,6 +2611,18 @@ class FieldFormalParameterElementImpl extends ParameterElementImpl
|
| }
|
|
|
| /**
|
| + * Indicates that an ElementImpl's hashCode cannot currently be changed.
|
| + */
|
| +class FrozenHashCodeException implements Exception {
|
| + final String _message;
|
| +
|
| + FrozenHashCodeException(this._message);
|
| +
|
| + @override
|
| + String toString() => "FrozenHashCodeException($_message)";
|
| +}
|
| +
|
| +/**
|
| * A concrete implementation of a [FunctionElement].
|
| */
|
| class FunctionElementImpl extends ExecutableElementImpl
|
| @@ -3815,7 +3863,12 @@ class Modifier extends Enum<Modifier> {
|
| */
|
| static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 18);
|
|
|
| - static const List<Modifier> values = const [
|
| + /**
|
| + * Indicates that this element is being used as an analyzer cache key.
|
| + */
|
| + static const Modifier CACHE_KEY = const Modifier('CACHE_KEY', 19);
|
| +
|
| + static const List<Modifier> persistedValues = const [
|
| ABSTRACT,
|
| ASYNCHRONOUS,
|
| CONST,
|
| @@ -3837,6 +3890,11 @@ class Modifier extends Enum<Modifier> {
|
| SYNTHETIC
|
| ];
|
|
|
| + static const List<Modifier> transientValues = const [CACHE_KEY];
|
| +
|
| + static final values = new List.unmodifiable(
|
| + []..addAll(persistedValues)..addAll(transientValues));
|
| +
|
| const Modifier(String name, int ordinal) : super(name, ordinal);
|
| }
|
|
|
|
|