Add ExecutableElement(s) based InheritanceManager3, and switch analyzer to it.

Change-Id: I9d87619e05ae769f4df6a6ba26cd7901c7c98510
Reviewed-on: https://dart-review.googlesource.com/c/93141
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2019-02-14 18:11:18 +00:00 committed by commit-bot@chromium.org
parent ae7bf9e999
commit 5d6bab4ed2
24 changed files with 1988 additions and 252 deletions

View file

@ -15,7 +15,7 @@ import 'package:analysis_server/src/plugin/result_merger.dart';
import 'package:analysis_server/src/services/kythe/kythe_visitors.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
@ -66,7 +66,7 @@ class KytheDomainHandler extends AbstractRequestHandler {
server.resourceProvider,
entries,
file,
new InheritanceManager2(typeSystem),
new InheritanceManager3(typeSystem),
result.content));
allResults.add(new KytheGetKytheEntriesResult(entries, files));
}

View file

@ -10,8 +10,8 @@ import 'package:analysis_server/src/protocol_server.dart' as protocol
hide CompletionSuggestion, CompletionSuggestionKind;
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
@ -36,7 +36,7 @@ class OverrideContributor implements DartCompletionContributor {
return const <CompletionSuggestion>[];
}
var inheritance = new InheritanceManager2(request.result.typeSystem);
var inheritance = new InheritanceManager3(request.result.typeSystem);
// Generate a collection of inherited members
var classElem = classDecl.declaredElement;
@ -48,12 +48,12 @@ class OverrideContributor implements DartCompletionContributor {
// Build suggestions
List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
for (Name name in namesToOverride) {
FunctionType signature = interfaceMap[name];
ExecutableElement element = interfaceMap[name];
// Gracefully degrade if the overridden element has not been resolved.
if (signature.returnType != null) {
if (element.returnType != null) {
var invokeSuper = interface.isSuperImplemented(name);
var suggestion =
await _buildSuggestion(request, targetId, signature, invokeSuper);
await _buildSuggestion(request, targetId, element, invokeSuper);
if (suggestion != null) {
suggestions.add(suggestion);
}
@ -64,19 +64,19 @@ class OverrideContributor implements DartCompletionContributor {
/**
* Build a suggestion to replace [targetId] in the given [request] with an
* override of the given [signature].
* override of the given [element].
*/
Future<CompletionSuggestion> _buildSuggestion(
DartCompletionRequest request,
SimpleIdentifier targetId,
FunctionType signature,
ExecutableElement element,
bool invokeSuper) async {
var displayTextBuffer = new StringBuffer();
var builder = new DartChangeBuilder(request.result.session);
await builder.addFileEdit(request.result.path, (builder) {
builder.addReplacement(range.node(targetId), (builder) {
builder.writeOverride(
signature,
element,
displayTextBuffer: displayTextBuffer,
invokeSuper: invokeSuper,
);
@ -113,11 +113,11 @@ class OverrideContributor implements DartCompletionContributor {
completion,
selectionRange.offset - offsetDelta,
selectionRange.length,
signature.element.hasDeprecated,
element.hasDeprecated,
false,
displayText: displayText);
suggestion.element = protocol.convertElement(signature.element);
suggestion.elementUri = signature.element.source.toString();
suggestion.element = protocol.convertElement(element);
suggestion.elementUri = element.source.toString();
return suggestion;
}

View file

@ -1971,15 +1971,15 @@ class FixProcessor {
ClassDeclaration targetClass = node.parent as ClassDeclaration;
ClassElement targetClassElement = targetClass.declaredElement;
utils.targetClassElement = targetClassElement;
List<FunctionType> signatures =
List<ExecutableElement> signatures =
InheritanceOverrideVerifier.missingOverrides(targetClass).toList();
// sort by name, getters before setters
signatures.sort((FunctionType a, FunctionType b) {
int names = compareStrings(a.element.displayName, b.element.displayName);
signatures.sort((ExecutableElement a, ExecutableElement b) {
int names = compareStrings(a.displayName, b.displayName);
if (names != 0) {
return names;
}
if (a.element.kind == ElementKind.GETTER) {
if (a.kind == ElementKind.GETTER) {
return -1;
}
return 1;
@ -2008,10 +2008,9 @@ class FixProcessor {
// merge getter/setter pairs into fields
for (int i = 0; i < signatures.length; i++) {
FunctionType signature = signatures[i];
ExecutableElement element = signature.element;
ExecutableElement element = signatures[i];
if (element.kind == ElementKind.GETTER && i + 1 < signatures.length) {
ExecutableElement nextElement = signatures[i + 1].element;
ExecutableElement nextElement = signatures[i + 1];
if (nextElement.kind == ElementKind.SETTER) {
// remove this and the next elements, adjust iterator
signatures.removeAt(i + 1);
@ -2025,7 +2024,7 @@ class FixProcessor {
builder.write(eol);
// add field
builder.write(prefix);
builder.writeType(signature.returnType, required: true);
builder.writeType(element.returnType, required: true);
builder.write(' ');
builder.write(element.name);
builder.write(';');
@ -2033,9 +2032,9 @@ class FixProcessor {
}
}
// add elements
for (FunctionType signature in signatures) {
for (ExecutableElement element in signatures) {
addSeparatorBetweenDeclarations();
builder.writeOverride(signature);
builder.writeOverride(element);
}
builder.write(location.suffix);
});

View file

@ -13,7 +13,7 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/workspace/bazel.dart';
import 'package:analyzer/src/workspace/gn.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
@ -94,7 +94,7 @@ class KytheDartVisitor extends GeneralizingAstVisitor with OutputUtils {
final ResourceProvider resourceProvider;
final List<KytheEntry> entries;
final String corpus;
final InheritanceManager2 _inheritanceManager;
final InheritanceManager3 _inheritanceManager;
final String _contents;
String _enclosingFilePath = '';
@ -695,18 +695,18 @@ class KytheDartVisitor extends GeneralizingAstVisitor with OutputUtils {
returnNode: node.returnType);
// override edges
var overriddenSignatures = _inheritanceManager.getOverridden(
var overriddenList = _inheritanceManager.getOverridden(
_enclosingClassElement.type,
new Name(
_enclosingClassElement.library.source.uri,
node.declaredElement.name,
),
);
for (FunctionType signature in overriddenSignatures) {
for (ExecutableElement overridden in overriddenList) {
addEdge(
methodVName,
schema.OVERRIDES_EDGE,
_vNameFromElement(signature.element, schema.FUNCTION_KIND),
_vNameFromElement(overridden, schema.FUNCTION_KIND),
);
}

View file

@ -17,7 +17,7 @@ import 'package:analyzer/src/dart/constant/constant_verifier.dart';
import 'package:analyzer/src/dart/constant/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/inheritance_override.dart';
import 'package:analyzer/src/error/pending_error.dart';
@ -48,7 +48,7 @@ class LibraryAnalyzer {
final FileState _library;
final ResourceProvider _resourceProvider;
final InheritanceManager2 _inheritance;
final InheritanceManager3 _inheritance;
final bool Function(Uri) _isLibraryUri;
final AnalysisContext _context;
final ElementResynthesizer _resynthesizer;

View file

@ -13,7 +13,7 @@ import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisOptions;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
@ -45,7 +45,7 @@ class LibraryContext {
AnalysisContextImpl analysisContext;
SummaryResynthesizer resynthesizer;
InheritanceManager2 inheritanceManager;
InheritanceManager3 inheritanceManager;
LibraryContext({
@required AnalysisSession session,
@ -76,7 +76,7 @@ class LibraryContext {
session: session);
resynthesizer = provider.resynthesizer;
inheritanceManager = new InheritanceManager2(analysisContext.typeSystem);
inheritanceManager = new InheritanceManager3(analysisContext.typeSystem);
}
/**

View file

@ -0,0 +1,533 @@
// Copyright (c) 2019, 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:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
/// Description of a failure to find a valid override from superinterfaces.
class Conflict {
/// The name of an instance member for which we failed to find a valid
/// override.
final Name name;
/// The list of candidates for a valid override for a member [name]. It has
/// at least two items, because otherwise the only candidate is always valid.
final List<ExecutableElement> candidates;
/// The getter that conflicts with the [method], or `null`, if the conflict
/// is inconsistent inheritance.
final ExecutableElement getter;
/// The method tha conflicts with the [getter], or `null`, if the conflict
/// is inconsistent inheritance.
final ExecutableElement method;
Conflict(this.name, this.candidates, [this.getter, this.method]);
}
/// Manages knowledge about interface types and their members.
class InheritanceManager3 {
static final _noSuchMethodName = Name(null, 'noSuchMethod');
final TypeSystem _typeSystem;
/// Cached instance interfaces for [InterfaceType].
final Map<InterfaceType, Interface> _interfaces = {};
/// The set of classes that are currently being processed, used to detect
/// self-referencing cycles.
final Set<ClassElement> _processingClasses = new Set<ClassElement>();
InheritanceManager3(this._typeSystem);
/// Return the most specific signature of the member with the given [name]
/// that the [type] inherits from the mixins, superclasses, or interfaces;
/// or `null` if no member is inherited because the member is not declared
/// at all, or because there is no the most specific signature.
///
/// This is equivalent to `getInheritedMap(type)[name]`.
ExecutableElement getInherited(InterfaceType type, Name name) {
return getInheritedMap(type)[name];
}
/// Return signatures of all concrete members that the given [type] inherits
/// from the superclasses and mixins.
Map<Name, ExecutableElement> getInheritedConcreteMap(InterfaceType type) {
var interface = getInterface(type);
return interface._superImplemented.last;
}
/// Return the mapping from names to most specific signatures of members
/// inherited from the super-interfaces (superclasses, mixins, and
/// interfaces). If there is no most specific signature for a name, the
/// corresponding name will not be included.
Map<Name, ExecutableElement> getInheritedMap(InterfaceType type) {
var interface = getInterface(type);
if (interface._inheritedMap == null) {
interface._inheritedMap = {};
_findMostSpecificFromNamedCandidates(
interface._inheritedMap,
interface._overridden,
);
}
return interface._inheritedMap;
}
/// Return the interface of the given [type]. It might include private
/// members, not necessary accessible in all libraries.
Interface getInterface(InterfaceType type) {
if (type == null) {
return Interface._empty;
}
var result = _interfaces[type];
if (result != null) {
return result;
}
_interfaces[type] = Interface._empty;
var classElement = type.element;
if (!_processingClasses.add(classElement)) {
return Interface._empty;
}
Map<Name, List<ExecutableElement>> namedCandidates = {};
List<Map<Name, ExecutableElement>> superImplemented = [];
Map<Name, ExecutableElement> declared;
Interface superInterface;
Map<Name, ExecutableElement> implemented;
Map<Name, ExecutableElement> implementedForMixing;
try {
// If a class declaration has a member declaration, the signature of that
// member declaration becomes the signature in the interface.
declared = _getTypeMembers(type);
for (var interface in type.interfaces) {
var interfaceObj = getInterface(interface);
_addCandidates(namedCandidates, interfaceObj);
}
if (classElement.isMixin) {
var superClassCandidates = <Name, List<ExecutableElement>>{};
for (var constraint in type.superclassConstraints) {
var interfaceObj = getInterface(constraint);
_addCandidates(superClassCandidates, interfaceObj);
_addCandidates(namedCandidates, interfaceObj);
}
implemented = {};
// `mixin M on S1, S2 {}` can call using `super` any instance member
// from its superclass constraints, whether it is abstract or concrete.
var superClass = <Name, ExecutableElement>{};
_findMostSpecificFromNamedCandidates(superClass, superClassCandidates);
superImplemented.add(superClass);
} else {
if (type.superclass != null) {
superInterface = getInterface(type.superclass);
_addCandidates(namedCandidates, superInterface);
implemented = superInterface.implemented;
superImplemented.add(implemented);
} else {
implemented = {};
}
implementedForMixing = {};
for (var mixin in type.mixins) {
var interfaceObj = getInterface(mixin);
_addCandidates(namedCandidates, interfaceObj);
implemented = <Name, ExecutableElement>{}
..addAll(implemented)
..addAll(interfaceObj._implementedForMixing);
superImplemented.add(implemented);
implementedForMixing.addAll(interfaceObj._implementedForMixing);
}
}
} finally {
_processingClasses.remove(classElement);
}
var thisImplemented = <Name, ExecutableElement>{};
_addImplemented(thisImplemented, type);
if (classElement.isMixin) {
implementedForMixing = thisImplemented;
} else {
implementedForMixing.addAll(thisImplemented);
}
implemented = <Name, ExecutableElement>{}..addAll(implemented);
_addImplemented(implemented, type);
// If a class declaration does not have a member declaration with a
// particular name, but some super-interfaces do have a member with that
// name, it's a compile-time error if there is no signature among the
// super-interfaces that is a valid override of all the other
// super-interface signatures with the same name. That "most specific"
// signature becomes the signature of the class's interface.
Map<Name, ExecutableElement> map = new Map.of(declared);
List<Conflict> conflicts = _findMostSpecificFromNamedCandidates(
map,
namedCandidates,
);
var noSuchMethodForwarders = Set<Name>();
if (classElement.isAbstract) {
if (superInterface != null) {
noSuchMethodForwarders = superInterface._noSuchMethodForwarders;
}
} else {
var noSuchMethod = implemented[_noSuchMethodName];
if (noSuchMethod != null && !_isDeclaredInObject(noSuchMethod)) {
var superForwarders = superInterface?._noSuchMethodForwarders;
for (var name in map.keys) {
if (!implemented.containsKey(name) ||
superForwarders != null && superForwarders.contains(name)) {
implemented[name] = map[name];
noSuchMethodForwarders.add(name);
}
}
}
}
var interface = new Interface._(
map,
declared,
implemented,
noSuchMethodForwarders,
implementedForMixing,
namedCandidates,
superImplemented,
conflicts ?? const [],
);
_interfaces[type] = interface;
return interface;
}
/// Return the member with the given [name].
///
/// If [concrete] is `true`, the the concrete implementation is returned,
/// from the given [type], or its superclass.
///
/// If [forSuper] is `true`, then [concrete] is implied, and only concrete
/// members from the superclass are considered.
///
/// If [forMixinIndex] is specified, only the nominal superclass, and the
/// given number of mixins after it are considered. For example for `1` in
/// `class C extends S with M1, M2, M3`, only `S` and `M1` are considered.
ExecutableElement getMember(
InterfaceType type,
Name name, {
bool concrete: false,
int forMixinIndex: -1,
bool forSuper: false,
}) {
var interface = getInterface(type);
if (forSuper) {
var superImplemented = interface._superImplemented;
if (forMixinIndex >= 0) {
return superImplemented[forMixinIndex][name];
}
return superImplemented.last[name];
}
if (concrete) {
return interface.implemented[name];
}
return interface.map[name];
}
/// Return all members of mixins, superclasses, and interfaces that a member
/// with the given [name], defined in the [type], would override; or `null`
/// if no members would be overridden.
List<ExecutableElement> getOverridden(InterfaceType type, Name name) {
var interface = getInterface(type);
return interface._overridden[name];
}
void _addCandidate(Map<Name, List<ExecutableElement>> namedCandidates,
Name name, ExecutableElement candidate) {
var candidates = namedCandidates[name];
if (candidates == null) {
candidates = <ExecutableElement>[];
namedCandidates[name] = candidates;
}
candidates.add(candidate);
}
void _addCandidates(
Map<Name, List<ExecutableElement>> namedCandidates, Interface interface) {
var map = interface.map;
for (var name in map.keys) {
var candidate = map[name];
_addCandidate(namedCandidates, name, candidate);
}
}
void _addImplemented(
Map<Name, ExecutableElement> implemented, InterfaceType type) {
var libraryUri = type.element.librarySource.uri;
void addMember(ExecutableElement member) {
if (!member.isAbstract && !member.isStatic) {
var name = new Name(libraryUri, member.name);
implemented[name] = member;
}
}
void addMembers(InterfaceType type) {
type.methods.forEach(addMember);
type.accessors.forEach(addMember);
}
addMembers(type);
}
/// Check that all [candidates] for the given [name] have the same kind, all
/// getters, all methods, or all setter. If a conflict found, return the
/// new [Conflict] instance that describes it.
Conflict _checkForGetterMethodConflict(
Name name, List<ExecutableElement> candidates) {
assert(candidates.length > 1);
bool allGetters = true;
bool allMethods = true;
bool allSetters = true;
for (var candidate in candidates) {
var kind = candidate.kind;
if (kind != ElementKind.GETTER) {
allGetters = false;
}
if (kind != ElementKind.METHOD) {
allMethods = false;
}
if (kind != ElementKind.SETTER) {
allSetters = false;
}
}
if (allGetters || allMethods || allSetters) {
return null;
}
ExecutableElement getter;
ExecutableElement method;
for (var candidate in candidates) {
var kind = candidate.kind;
if (kind == ElementKind.GETTER) {
getter ??= candidate;
}
if (kind == ElementKind.METHOD) {
method ??= candidate;
}
}
return new Conflict(name, candidates, getter, method);
}
/// The given [namedCandidates] maps names to candidates from direct
/// superinterfaces. Find the most specific signature, and put it into the
/// [map], if there is no one yet (from the class itself). If there is no
/// such single most specific signature (i.e. no valid override), then add a
/// new conflict description.
List<Conflict> _findMostSpecificFromNamedCandidates(
Map<Name, ExecutableElement> map,
Map<Name, List<ExecutableElement>> namedCandidates) {
List<Conflict> conflicts = null;
for (var name in namedCandidates.keys) {
if (map.containsKey(name)) {
continue;
}
var candidates = namedCandidates[name];
// If just one candidate, it is always valid.
if (candidates.length == 1) {
map[name] = candidates[0];
continue;
}
// Check for a getter/method conflict.
var conflict = _checkForGetterMethodConflict(name, candidates);
if (conflict != null) {
conflicts ??= <Conflict>[];
conflicts.add(conflict);
}
// Candidates are recorded in forward order, so
// `class X extends S with M1, M2 implements I1, I2 {}` will record
// candidates from [I1, I2, S, M1, M2]. But during method lookup
// candidates should be considered in backward order, i.e. from `M2`,
// then from `M1`, then from `S`.
ExecutableElement validOverride;
for (var i = candidates.length - 1; i >= 0; i--) {
validOverride = candidates[i];
for (var j = 0; j < candidates.length; j++) {
var candidate = candidates[j];
if (!_typeSystem.isOverrideSubtypeOf(
validOverride.type, candidate.type)) {
validOverride = null;
break;
}
}
if (validOverride != null) {
break;
}
}
if (validOverride != null) {
map[name] = validOverride;
} else {
conflicts ??= <Conflict>[];
conflicts.add(new Conflict(name, candidates));
}
}
return conflicts;
}
Map<Name, ExecutableElement> _getTypeMembers(InterfaceType type) {
var declared = <Name, ExecutableElement>{};
var libraryUri = type.element.librarySource.uri;
var methods = type.methods;
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
if (!method.isStatic) {
var name = new Name(libraryUri, method.name);
declared[name] = method;
}
}
var accessors = type.accessors;
for (var i = 0; i < accessors.length; i++) {
var accessor = accessors[i];
if (!accessor.isStatic) {
var name = new Name(libraryUri, accessor.name);
declared[name] = accessor;
}
}
return declared;
}
static bool _isDeclaredInObject(ExecutableElement element) {
var enclosing = element.enclosingElement;
return enclosing is ClassElement &&
enclosing.supertype == null &&
!enclosing.isMixin;
}
}
/// The instance interface of an [InterfaceType].
class Interface {
static final _empty = Interface._(
const {},
const {},
const {},
Set<Name>(),
const {},
const {},
const [{}],
const [],
);
/// The map of names to their signature in the interface.
final Map<Name, ExecutableElement> map;
/// The map of declared names to their signatures.
final Map<Name, ExecutableElement> declared;
/// The map of names to their concrete implementations.
final Map<Name, ExecutableElement> implemented;
/// The set of names that are `noSuchMethod` forwarders in [implemented].
final Set<Name> _noSuchMethodForwarders;
/// The map of names to their concrete implementations that can be mixed
/// when this type is used as a mixin.
final Map<Name, ExecutableElement> _implementedForMixing;
/// The map of names to their signatures from the mixins, superclasses,
/// or interfaces.
final Map<Name, List<ExecutableElement>> _overridden;
/// Each item of this list maps names to their concrete implementations.
/// The first item of the list is the nominal superclass, next the nominal
/// superclass plus the first mixin, etc. So, for the class like
/// `class C extends S with M1, M2`, we get `[S, S&M1, S&M1&M2]`.
final List<Map<Name, ExecutableElement>> _superImplemented;
/// The list of conflicts between superinterfaces - the nominal superclass,
/// mixins, and interfaces. Does not include conflicts with the declared
/// members of the class.
final List<Conflict> conflicts;
/// The map of names to the most specific signatures from the mixins,
/// superclasses, or interfaces.
Map<Name, ExecutableElement> _inheritedMap;
Interface._(
this.map,
this.declared,
this.implemented,
this._noSuchMethodForwarders,
this._implementedForMixing,
this._overridden,
this._superImplemented,
this.conflicts,
);
/// Return `true` if the [name] is implemented in the supertype.
bool isSuperImplemented(Name name) {
return _superImplemented.last.containsKey(name);
}
}
/// A public name, or a private name qualified by a library URI.
class Name {
/// If the name is private, the URI of the defining library.
/// Otherwise, it is `null`.
final Uri libraryUri;
/// The name of this name object.
/// If the name starts with `_`, then the name is private.
/// Names of setters end with `=`.
final String name;
/// Precomputed
final bool isPublic;
/// The cached, pre-computed hash code.
final int hashCode;
factory Name(Uri libraryUri, String name) {
if (name.startsWith('_')) {
var hashCode = JenkinsSmiHash.hash2(libraryUri.hashCode, name.hashCode);
return new Name._internal(libraryUri, name, false, hashCode);
} else {
return new Name._internal(null, name, true, name.hashCode);
}
}
Name._internal(this.libraryUri, this.name, this.isPublic, this.hashCode);
@override
bool operator ==(other) {
return other is Name &&
name == other.name &&
libraryUri == other.libraryUri;
}
bool isAccessibleFor(Uri libraryUri) {
return isPublic || this.libraryUri == libraryUri;
}
@override
String toString() => libraryUri != null ? '$libraryUri::$name' : name;
}

View file

@ -21,7 +21,7 @@ import 'package:analyzer/src/generated/utilities_dart.dart';
* Instances of the class `InheritanceManager` manage the knowledge of where class members
* (methods, getters & setters) are inherited from.
*/
@Deprecated('Use InheritanceManager2 instead.')
@Deprecated('Use InheritanceManager3 instead.')
class InheritanceManager {
/**
* The [LibraryElement] that is managed by this manager.
@ -77,7 +77,7 @@ class InheritanceManager {
* @return a mapping between the set of all members inherited from the passed [ClassElement]
* superclass hierarchy, and the associated [ExecutableElement]
*/
@Deprecated('Use InheritanceManager2.getInheritedConcreteMap() instead.')
@Deprecated('Use InheritanceManager3.getInheritedConcreteMap() instead.')
MemberMap getMapOfMembersInheritedFromClasses(ClassElement classElt) =>
new MemberMap.fromMap(
_computeClassChainLookupMap(classElt, new HashSet<ClassElement>()));
@ -90,7 +90,7 @@ class InheritanceManager {
* @return a mapping between the set of all string names of the members inherited from the passed
* [ClassElement] interface hierarchy, and the associated [ExecutableElement].
*/
@Deprecated('Use InheritanceManager2.getInheritedMap() instead.')
@Deprecated('Use InheritanceManager3.getInheritedMap() instead.')
MemberMap getMapOfMembersInheritedFromInterfaces(ClassElement classElt) =>
new MemberMap.fromMap(
_computeInterfaceLookupMap(classElt, new HashSet<ClassElement>()));
@ -126,7 +126,7 @@ class InheritanceManager {
* @return the inherited executable element with the member name, or `null` if no such
* member exists
*/
@Deprecated('Use InheritanceManager2.getInherited() instead.')
@Deprecated('Use InheritanceManager3.getInherited() instead.')
ExecutableElement lookupInheritance(
ClassElement classElt, String memberName) {
if (memberName == null || memberName.isEmpty) {
@ -151,7 +151,7 @@ class InheritanceManager {
* @return the inherited executable element with the member name, or `null` if no such
* member exists
*/
@Deprecated('Use InheritanceManager2.getMember() instead.')
@Deprecated('Use InheritanceManager3.getMember() instead.')
ExecutableElement lookupMember(ClassElement classElt, String memberName) {
ExecutableElement element = _lookupMemberInClass(classElt, memberName);
if (element != null) {
@ -170,7 +170,7 @@ class InheritanceManager {
* @param memberName the name of the class member to query
* @return a list of overridden methods
*/
@Deprecated('Use InheritanceManager2.getOverridden() instead.')
@Deprecated('Use InheritanceManager3.getOverridden() instead.')
List<ExecutableElement> lookupOverrides(
ClassElement classElt, String memberName) {
List<ExecutableElement> result = new List<ExecutableElement>();

View file

@ -7,8 +7,7 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
@ -27,7 +26,7 @@ class MethodInvocationResolver {
final InterfaceType _typeType;
/// The manager for the inheritance mappings.
final InheritanceManager2 _inheritance;
final InheritanceManager3 _inheritance;
/// The element for the library containing the compilation unit being visited.
final LibraryElement _definingLibrary;
@ -138,18 +137,17 @@ class MethodInvocationResolver {
return null;
}
/// If the element of the invoked [targetType] is a getter, then actually
/// the return type of the [targetType] is invoked. So, remember the
/// [targetType] into [MethodInvocationImpl.methodNameType] and return the
/// actual invoked type.
DartType _getCalleeType(MethodInvocation node, FunctionType targetType) {
if (targetType.element.kind == ElementKind.GETTER) {
(node as MethodInvocationImpl).methodNameType = targetType;
var calleeType = targetType.returnType;
/// If the invoked [target] is a getter, then actually the return type of
/// the [target] is invoked. So, remember the [target] into
/// [MethodInvocationImpl.methodNameType] and return the actual invoked type.
DartType _getCalleeType(MethodInvocation node, ExecutableElement target) {
if (target.kind == ElementKind.GETTER) {
(node as MethodInvocationImpl).methodNameType = target.type;
var calleeType = target.returnType;
calleeType = _resolveTypeParameter(calleeType);
return calleeType;
}
return targetType;
return target.type;
}
/// Check for a generic type, and apply type arguments.
@ -306,13 +304,13 @@ class MethodInvocationResolver {
}
// We can invoke Object methods on Function.
var type = _inheritance.getMember(
var member = _inheritance.getMember(
_resolver.typeProvider.objectType,
new Name(null, name),
);
if (type != null) {
nameNode.staticElement = type.element;
return _setResolution(node, type);
if (member != null) {
nameNode.staticElement = member;
return _setResolution(node, member.type);
}
_reportUndefinedMethod(
@ -330,21 +328,10 @@ class MethodInvocationResolver {
return;
}
var targetType = _inheritance.getMember(receiverType, _currentName);
if (targetType != null) {
var calleeType = _getCalleeType(node, targetType);
// TODO(scheglov) This is bad, we have to create members here.
// Find a way to avoid this.
Element element;
var baseElement = targetType.element;
if (baseElement is MethodElement) {
element = MethodMember.from(baseElement, receiverType);
} else if (baseElement is PropertyAccessorElement) {
element = PropertyAccessorMember.from(baseElement, receiverType);
}
nameNode.staticElement = element;
var target = _inheritance.getMember(receiverType, _currentName);
if (target != null) {
nameNode.staticElement = target;
var calleeType = _getCalleeType(node, target);
return _setResolution(node, calleeType);
}
@ -384,7 +371,7 @@ class MethodInvocationResolver {
element = multiply.conflictingElements[0];
}
if (element is ExecutableElement) {
var calleeType = _getCalleeType(node, element.type);
var calleeType = _getCalleeType(node, element);
return _setResolution(node, calleeType);
}
if (element is VariableElement) {
@ -405,11 +392,11 @@ class MethodInvocationResolver {
}
var receiverType = enclosingClass.type;
var targetType = _inheritance.getMember(receiverType, _currentName);
var target = _inheritance.getMember(receiverType, _currentName);
if (targetType != null) {
nameNode.staticElement = targetType.element;
var calleeType = _getCalleeType(node, targetType);
if (target != null) {
nameNode.staticElement = target;
var calleeType = _getCalleeType(node, target);
return _setResolution(node, calleeType);
}
@ -458,7 +445,7 @@ class MethodInvocationResolver {
}
if (element is ExecutableElement) {
var calleeType = _getCalleeType(node, element.type);
var calleeType = _getCalleeType(node, element);
return _setResolution(node, calleeType);
}
@ -472,16 +459,16 @@ class MethodInvocationResolver {
}
var receiverType = _resolver.enclosingClass.type;
var targetType = _inheritance.getMember(
var target = _inheritance.getMember(
receiverType,
_currentName,
forSuper: true,
);
// If there is that concrete dispatch target, then we are done.
if (targetType != null) {
nameNode.staticElement = targetType.element;
var calleeType = _getCalleeType(node, targetType);
if (target != null) {
nameNode.staticElement = target;
var calleeType = _getCalleeType(node, target);
_setResolution(node, calleeType);
return;
}
@ -489,16 +476,16 @@ class MethodInvocationResolver {
// Otherwise, this is an error.
// But we would like to give the user at least some resolution.
// So, we try to find the interface target.
targetType = _inheritance.getInherited(receiverType, _currentName);
if (targetType != null) {
nameNode.staticElement = targetType.element;
var calleeType = _getCalleeType(node, targetType);
target = _inheritance.getInherited(receiverType, _currentName);
if (target != null) {
nameNode.staticElement = target;
var calleeType = _getCalleeType(node, target);
_setResolution(node, calleeType);
_resolver.errorReporter.reportErrorForNode(
CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
nameNode,
[targetType.element.kind.displayName, name]);
[target.kind.displayName, name]);
return;
}
@ -520,7 +507,7 @@ class MethodInvocationResolver {
if (element != null) {
if (element is ExecutableElement) {
nameNode.staticElement = element;
var calleeType = _getCalleeType(node, element.type);
var calleeType = _getCalleeType(node, element);
_setResolution(node, calleeType);
} else {
_reportInvocationOfNonFunction(node);
@ -561,8 +548,8 @@ class MethodInvocationResolver {
if (type is InterfaceType) {
var call = _inheritance.getMember(type, _nameCall);
if (call != null && call.element.kind == ElementKind.METHOD) {
type = call;
if (call != null && call.kind == ElementKind.METHOD) {
type = call.type;
}
}

View file

@ -8,7 +8,8 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@ -19,7 +20,7 @@ class InheritanceOverrideVerifier {
final TypeSystem _typeSystem;
final TypeProvider _typeProvider;
final InheritanceManager2 _inheritance;
final InheritanceManager3 _inheritance;
final ErrorReporter _reporter;
InheritanceOverrideVerifier(
@ -70,9 +71,9 @@ class InheritanceOverrideVerifier {
}
}
/// Returns [FunctionType]s of members that are in the interface of the
/// Returns [ExecutableElement] members that are in the interface of the
/// given class, but don't have concrete implementations.
static List<FunctionType> missingOverrides(ClassDeclaration node) {
static List<ExecutableElement> missingOverrides(ClassDeclaration node) {
return node.name.getProperty(_missingOverridesKey) ?? const [];
}
}
@ -80,7 +81,7 @@ class InheritanceOverrideVerifier {
class _ClassVerifier {
final TypeSystem typeSystem;
final TypeProvider typeProvider;
final InheritanceManager2 inheritance;
final InheritanceManager3 inheritance;
final ErrorReporter reporter;
final LibraryElement library;
@ -180,27 +181,27 @@ class _ClassVerifier {
_checkForMismatchedAccessorTypes(interface);
if (!classElement.isAbstract) {
List<FunctionType> inheritedAbstract = null;
List<ExecutableElement> inheritedAbstract = null;
for (var name in interface.map.keys) {
if (!name.isAccessibleFor(libraryUri)) {
continue;
}
var interfaceType = interface.map[name];
var concreteType = interface.implemented[name];
var interfaceElement = interface.map[name];
var concreteElement = interface.implemented[name];
// No concrete implementation of the name.
if (concreteType == null) {
if (concreteElement == null) {
if (!_reportConcreteClassWithAbstractMember(name.name)) {
inheritedAbstract ??= [];
inheritedAbstract.add(interfaceType);
inheritedAbstract.add(interfaceElement);
}
continue;
}
// The case when members have different kinds is reported in verifier.
if (concreteType.element.kind != interfaceType.element.kind) {
if (concreteElement.kind != interfaceElement.kind) {
continue;
}
@ -212,16 +213,17 @@ class _ClassVerifier {
// 2. if the class contains no member named `m`, and the class member
// for `noSuchMethod` is the one declared in `Object`, then it's a
// compile-time error.
if (!typeSystem.isOverrideSubtypeOf(concreteType, interfaceType)) {
if (!typeSystem.isOverrideSubtypeOf(
concreteElement.type, interfaceElement.type)) {
reporter.reportErrorForNode(
CompileTimeErrorCode.INVALID_OVERRIDE,
classNameNode,
[
name.name,
concreteType.element.enclosingElement.name,
concreteType.displayName,
interfaceType.element.enclosingElement.name,
interfaceType.displayName,
concreteElement.enclosingElement.name,
concreteElement.displayName,
interfaceElement.enclosingElement.name,
interfaceElement.displayName,
],
);
}
@ -257,15 +259,15 @@ class _ClassVerifier {
var name = new Name(libraryUri, member.name);
for (var superInterface in allSuperinterfaces) {
var superMemberType = superInterface.declared[name];
if (superMemberType != null) {
var superMember = superInterface.declared[name];
if (superMember != null) {
// The case when members have different kinds is reported in verifier.
// TODO(scheglov) Do it here?
if (member.kind != superMemberType.element.kind) {
if (member.kind != superMember.kind) {
continue;
}
if (!typeSystem.isOverrideSubtypeOf(member.type, superMemberType)) {
if (!typeSystem.isOverrideSubtypeOf(member.type, superMember.type)) {
reporter.reportErrorForNode(
CompileTimeErrorCode.INVALID_OVERRIDE,
node,
@ -273,14 +275,14 @@ class _ClassVerifier {
name.name,
member.enclosingElement.name,
member.type.displayName,
superMemberType.element.enclosingElement.name,
superMemberType.displayName
superMember.enclosingElement.name,
superMember.displayName
],
);
}
if (methodParameterNodes != null) {
_checkForOptionalParametersDifferentDefaultValues(
superMemberType.element,
superMember,
member,
methodParameterNodes,
);
@ -374,34 +376,31 @@ class _ClassVerifier {
if (!name.isAccessibleFor(libraryUri)) continue;
var getter = interface.map[name];
if (getter.element.kind == ElementKind.GETTER) {
if (getter.kind == ElementKind.GETTER) {
// TODO(scheglov) We should separate getters and setters.
var setter = interface.map[new Name(libraryUri, '${name.name}=')];
if (setter != null && setter.parameters.length == 1) {
var getterType = getter.returnType;
var setterType = setter.parameters[0].type;
if (!typeSystem.isAssignableTo(getterType, setterType)) {
var getterElement = getter.element;
var setterElement = setter.element;
Element errorElement;
if (getterElement.enclosingElement == classElement) {
errorElement = getterElement;
} else if (setterElement.enclosingElement == classElement) {
errorElement = setterElement;
if (getter.enclosingElement == classElement) {
errorElement = getter;
} else if (setter.enclosingElement == classElement) {
errorElement = setter;
} else {
errorElement = classElement;
}
String getterName = getterElement.displayName;
if (getterElement.enclosingElement != classElement) {
var getterClassName = getterElement.enclosingElement.displayName;
String getterName = getter.displayName;
if (getter.enclosingElement != classElement) {
var getterClassName = getter.enclosingElement.displayName;
getterName = '$getterClassName.$getterName';
}
String setterName = setterElement.displayName;
if (setterElement.enclosingElement != classElement) {
var setterClassName = setterElement.enclosingElement.displayName;
String setterName = setter.displayName;
if (setter.enclosingElement != classElement) {
var setterClassName = setter.enclosingElement.displayName;
setterName = '$setterClassName.$setterName';
}
@ -436,6 +435,9 @@ class _ClassVerifier {
for (var i = 0; i < baseParameterElements.length; ++i) {
var baseParameter = baseParameterElements[i];
if (baseParameter.isOptional) {
if (baseParameter is ParameterMember) {
baseParameter = (baseParameter as ParameterMember).baseElement;
}
baseOptionalElements.add(baseParameter);
}
}
@ -625,13 +627,13 @@ class _ClassVerifier {
node,
[
name.name,
conflict.getter.element.enclosingElement.name,
conflict.method.element.enclosingElement.name
conflict.getter.enclosingElement.name,
conflict.method.enclosingElement.name
],
);
} else {
var candidatesStr = conflict.candidates.map((candidate) {
var className = candidate.element.enclosingElement.name;
var className = candidate.enclosingElement.name;
return '$className.${name.name} (${candidate.displayName})';
}).join(', ');
@ -643,20 +645,18 @@ class _ClassVerifier {
}
}
void _reportInheritedAbstractMembers(List<FunctionType> types) {
if (types == null) {
void _reportInheritedAbstractMembers(List<ExecutableElement> elements) {
if (elements == null) {
return;
}
classNameNode.setProperty(
InheritanceOverrideVerifier._missingOverridesKey,
types,
elements,
);
var descriptions = <String>[];
for (FunctionType type in types) {
ExecutableElement element = type.element;
for (ExecutableElement element in elements) {
String prefix = '';
if (element is PropertyAccessorElement) {
if (element.isGetter) {

View file

@ -17,7 +17,7 @@ import 'package:analyzer/src/dart/ast/ast.dart'
SimpleIdentifierImpl;
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
@ -87,7 +87,7 @@ class ElementResolver extends SimpleAstVisitor<void> {
/**
* The manager for the inheritance mappings.
*/
final InheritanceManager2 _inheritance;
final InheritanceManager3 _inheritance;
/**
* The resolver driving this participant.
@ -1153,25 +1153,6 @@ class ElementResolver extends SimpleAstVisitor<void> {
return null;
}
/**
* Look up the [FunctionType] of a getter or a method with the given [name]
* in the given [targetType].
*/
FunctionType _lookUpGetterType(DartType targetType, String name,
{bool concrete: false, bool forSuper: false}) {
targetType = _resolveTypeParameter(targetType);
if (targetType is InterfaceType) {
var nameObject = new Name(_definingLibrary.source.uri, name);
return _inheritance.getMember(
targetType,
nameObject,
concrete: concrete,
forSuper: forSuper,
);
}
return null;
}
/**
* Look up the method with the given [methodName] in the given [type]. Return
* the element representing the method that was found, or `null` if there is
@ -1431,11 +1412,18 @@ class ElementResolver extends SimpleAstVisitor<void> {
if (leftOperand != null) {
DartType leftType = _getStaticType(leftOperand);
var isSuper = leftOperand is SuperExpression;
var invokeType = _lookUpGetterType(leftType, methodName,
concrete: isSuper, forSuper: isSuper);
var invokeElement = invokeType?.element;
ExecutableElement invokeElement;
if (leftType is InterfaceType) {
invokeElement = _inheritance.getMember(
leftType,
new Name(_definingLibrary.source.uri, methodName),
forSuper: isSuper,
);
}
node.staticElement = invokeElement;
node.staticInvokeType = invokeType;
node.staticInvokeType = invokeElement?.type;
if (_shouldReportInvalidMember(leftType, invokeElement)) {
if (isSuper) {
_recordUndefinedToken(

View file

@ -16,7 +16,7 @@ import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
@ -73,7 +73,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
/**
* The manager for the inheritance mappings.
*/
final InheritanceManager2 _inheritanceManager;
final InheritanceManager3 _inheritanceManager;
/**
* A flag indicating whether the visitor is currently within a constructor
@ -2601,12 +2601,10 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
String name = method.name;
// find inherited property accessor
ExecutableElement inherited = _inheritanceManager
.getInherited(enclosingType, new Name(libraryUri, name))
?.element;
inherited ??= _inheritanceManager
.getInherited(enclosingType, new Name(libraryUri, '$name='))
?.element;
ExecutableElement inherited = _inheritanceManager.getInherited(
enclosingType, new Name(libraryUri, name));
inherited ??= _inheritanceManager.getInherited(
enclosingType, new Name(libraryUri, '$name='));
if (method.isStatic && inherited != null) {
_errorReporter.reportErrorForElement(
@ -2630,12 +2628,10 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
String name = accessor.displayName;
// find inherited method or property accessor
ExecutableElement inherited = _inheritanceManager
.getInherited(enclosingType, new Name(libraryUri, name))
?.element;
inherited ??= _inheritanceManager
.getInherited(enclosingType, new Name(libraryUri, '$name='))
?.element;
ExecutableElement inherited = _inheritanceManager.getInherited(
enclosingType, new Name(libraryUri, name));
inherited ??= _inheritanceManager.getInherited(
enclosingType, new Name(libraryUri, '$name='));
if (accessor.isStatic && inherited != null) {
_errorReporter.reportErrorForElement(
@ -4506,11 +4502,10 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
for (var name in mixinElementImpl.superInvokedNames) {
var nameObject = new Name(mixinLibraryUri, name);
var superMemberType = _inheritanceManager.getMember(
enclosingType, nameObject,
var superMember = _inheritanceManager.getMember(enclosingType, nameObject,
forMixinIndex: mixinIndex, concrete: true, forSuper: true);
if (superMemberType == null) {
if (superMember == null) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode
.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
@ -4519,16 +4514,17 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
return true;
}
FunctionType mixinMemberType =
ExecutableElement mixinMember =
_inheritanceManager.getMember(mixinType, nameObject, forSuper: true);
if (mixinMemberType != null &&
!_typeSystem.isOverrideSubtypeOf(superMemberType, mixinMemberType)) {
if (mixinMember != null &&
!_typeSystem.isOverrideSubtypeOf(
superMember.type, mixinMember.type)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode
.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
mixinName.name,
[name, mixinMemberType.displayName, superMemberType.displayName]);
[name, mixinMember.type.displayName, superMember.type.displayName]);
return true;
}
}

View file

@ -21,7 +21,7 @@ import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart';
@ -3300,7 +3300,7 @@ class InstanceFieldResolverVisitor extends ResolverVisitor {
/// the node that will first be visited. If `null` or unspecified, a new
/// [LibraryScope] will be created based on the [definingLibrary].
InstanceFieldResolverVisitor(
InheritanceManager2 inheritance,
InheritanceManager3 inheritance,
LibraryElement definingLibrary,
Source source,
TypeProvider typeProvider,
@ -3376,7 +3376,7 @@ class InstanceFieldResolverVisitor extends ResolverVisitor {
/// being used correctly.
class OverrideVerifier extends RecursiveAstVisitor {
/// The inheritance manager used to find overridden methods.
final InheritanceManager2 _inheritance;
final InheritanceManager3 _inheritance;
/// The URI of the library being verified.
final Uri _libraryUri;
@ -3478,7 +3478,7 @@ class PartialResolverVisitor extends ResolverVisitor {
/// [LibraryScope] will be created based on [definingLibrary] and
/// [typeProvider].
PartialResolverVisitor(
InheritanceManager2 inheritance,
InheritanceManager3 inheritance,
LibraryElement definingLibrary,
Source source,
TypeProvider typeProvider,
@ -3640,7 +3640,7 @@ class ResolverVisitor extends ScopedVisitor {
/**
* The manager for the inheritance mappings.
*/
final InheritanceManager2 inheritance;
final InheritanceManager3 inheritance;
/// The object used to resolve the element associated with the current node.
ElementResolver elementResolver;

View file

@ -67,7 +67,7 @@ import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
@ -2463,7 +2463,7 @@ class ExprTypeComputer {
nameScope = new ClassScope(
new TypeParameterScope(nameScope, enclosingClass), enclosingClass);
}
var inheritance = new InheritanceManager2(linker.typeSystem);
var inheritance = new InheritanceManager3(linker.typeSystem);
var resolverVisitor = new ResolverVisitor(
inheritance, library, source, typeProvider, errorListener,
nameScope: nameScope,
@ -3938,7 +3938,7 @@ class Linker {
SpecialTypeElementForLink _voidElement;
SpecialTypeElementForLink _dynamicElement;
SpecialTypeElementForLink _bottomElement;
InheritanceManager2 _inheritanceManager;
InheritanceManager3 _inheritanceManager;
ContextForLink _context;
AnalysisOptionsForLink _analysisOptions;
@ -3978,9 +3978,9 @@ class Linker {
SpecialTypeElementForLink get dynamicElement => _dynamicElement ??=
new SpecialTypeElementForLink(this, DynamicTypeImpl.instance);
/// Get an instance of [InheritanceManager2] for use during linking.
InheritanceManager2 get inheritanceManager =>
_inheritanceManager ??= new InheritanceManager2(typeSystem);
/// Get an instance of [InheritanceManager3] for use during linking.
InheritanceManager3 get inheritanceManager =>
_inheritanceManager ??= new InheritanceManager3(typeSystem);
/// Indicates whether type inference should use strong mode rules.
@deprecated

View file

@ -23,7 +23,7 @@ import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/constant_verifier.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/dart/sdk/patch.dart';
@ -2861,7 +2861,7 @@ class GenerateHintsTask extends SourceBasedAnalysisTask {
unit.accept(new Dart2JSVerifier(errorReporter));
}
// Dart best practices.
var inheritanceManager2 = new InheritanceManager2(context.typeSystem);
var inheritanceManager3 = new InheritanceManager3(context.typeSystem);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
@ -2871,7 +2871,7 @@ class GenerateHintsTask extends SourceBasedAnalysisTask {
resourceProvider: resourceProvider,
analysisOptions: context.analysisOptions));
unit.accept(new OverrideVerifier(
inheritanceManager2,
inheritanceManager3,
libraryElement,
errorReporter,
));
@ -3162,7 +3162,7 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask {
//
// Infer instance members.
//
var inheritance = new InheritanceManager2(context.typeSystem);
var inheritance = new InheritanceManager3(context.typeSystem);
InstanceMemberInferrer inferrer =
new InstanceMemberInferrer(typeProvider, inheritance);
inferrer.inferCompilationUnit(unit.declaredElement);
@ -3411,7 +3411,7 @@ class InferStaticVariableTypeTask extends InferStaticVariableTask {
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
var inheritance = new InheritanceManager2(context.typeSystem);
var inheritance = new InheritanceManager3(context.typeSystem);
// If we're not in a dependency cycle, and we have no type annotation,
// re-resolve the right hand side and do inference.
@ -4030,7 +4030,7 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
CompilationUnitElement unitElement = unit.declaredElement;
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
var inheritance = new InheritanceManager2(context.typeSystem);
var inheritance = new InheritanceManager3(context.typeSystem);
//
// Resolve references and record outputs.
//
@ -4567,7 +4567,7 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
var inheritance = new InheritanceManager2(context.typeSystem);
var inheritance = new InheritanceManager3(context.typeSystem);
CompilationUnitElement unitElement = unit.declaredElement;
//
@ -5011,7 +5011,7 @@ class ResolveUnitTask extends SourceBasedAnalysisTask {
LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
var inheritance = new InheritanceManager2(context.typeSystem);
var inheritance = new InheritanceManager3(context.typeSystem);
//
// Resolve everything.
//
@ -5576,7 +5576,7 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
// Compute inheritance and override errors.
//
var typeSystem = libraryElement.context.typeSystem;
var inheritanceManager = new InheritanceManager2(typeSystem);
var inheritanceManager = new InheritanceManager3(typeSystem);
var inheritanceOverrideVerifier = new InheritanceOverrideVerifier(
typeSystem, inheritanceManager, errorReporter);
inheritanceOverrideVerifier.verifyUnit(unit);

View file

@ -9,7 +9,7 @@ import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/summary/format.dart';
@ -36,7 +36,7 @@ typedef bool VariableFilter(VariableElement element);
*/
class InstanceMemberInferrer {
final TypeProvider typeProvider;
final InheritanceManager2 inheritance;
final InheritanceManager3 inheritance;
final Set<ClassElement> elementsBeingInferred = new HashSet<ClassElement>();
InterfaceType interfaceType;
@ -56,14 +56,14 @@ class InstanceMemberInferrer {
}
/**
* Return `true` if the elements corresponding to the [types] have the same
* Return `true` if the elements corresponding to the [elements] have the same
* kind as the [element].
*/
bool _allSameElementKind(
ExecutableElement element, List<FunctionType> types) {
ExecutableElement element, List<ExecutableElement> elements) {
var elementKind = element.kind;
for (int i = 0; i < types.length; i++) {
if (types[i].element.kind != elementKind) {
for (int i = 0; i < elements.length; i++) {
if (elements[i].kind != elementKind) {
return false;
}
}
@ -83,7 +83,7 @@ class InstanceMemberInferrer {
new Name(accessor.library.source.uri, name),
);
List<FunctionType> overriddenSetters;
List<ExecutableElement> overriddenSetters;
if (overriddenGetters == null || !accessor.variable.isFinal) {
overriddenSetters = inheritance.getOverridden(
interfaceType,
@ -91,34 +91,34 @@ class InstanceMemberInferrer {
);
}
// Choose overridden types from getters or/and setters.
List<FunctionType> overriddenTypes = <FunctionType>[];
// Choose overridden members from getters or/and setters.
List<ExecutableElement> overriddenElements = <ExecutableElement>[];
if (overriddenGetters == null && overriddenSetters == null) {
overriddenTypes = const <FunctionType>[];
overriddenElements = const <ExecutableElement>[];
} else if (overriddenGetters == null && overriddenSetters != null) {
overriddenTypes = overriddenSetters;
overriddenElements = overriddenSetters;
} else if (overriddenGetters != null && overriddenSetters == null) {
overriddenTypes = overriddenGetters;
overriddenElements = overriddenGetters;
} else {
overriddenTypes = <FunctionType>[]
overriddenElements = <ExecutableElement>[]
..addAll(overriddenGetters)
..addAll(overriddenSetters);
}
bool isCovariant = false;
DartType impliedType;
for (FunctionType overriddenType in overriddenTypes) {
var overriddenElementKind = overriddenType.element.kind;
if (overriddenType == null) {
for (ExecutableElement overriddenElement in overriddenElements) {
var overriddenElementKind = overriddenElement.kind;
if (overriddenElement == null) {
return new _FieldOverrideInferenceResult(false, null, true);
}
DartType type;
if (overriddenElementKind == ElementKind.GETTER) {
type = overriddenType.returnType;
type = overriddenElement.returnType;
} else if (overriddenElementKind == ElementKind.SETTER) {
if (overriddenType.parameters.length == 1) {
ParameterElement parameter = overriddenType.parameters[0];
if (overriddenElement.parameters.length == 1) {
ParameterElement parameter = overriddenElement.parameters[0];
type = parameter.type;
isCovariant = isCovariant || parameter.isCovariant;
}
@ -355,15 +355,17 @@ class InstanceMemberInferrer {
// TODO(scheglov) If no implicit types, don't ask inherited.
List<FunctionType> overriddenTypes = inheritance.getOverridden(
List<ExecutableElement> overriddenElements = inheritance.getOverridden(
interfaceType,
new Name(element.library.source.uri, element.name),
);
if (overriddenTypes == null ||
!_allSameElementKind(element, overriddenTypes)) {
if (overriddenElements == null ||
!_allSameElementKind(element, overriddenElements)) {
return;
}
overriddenTypes = _toOverriddenFunctionTypes(element, overriddenTypes);
List<FunctionType> overriddenTypes =
_toOverriddenFunctionTypes(element, overriddenElements);
if (overriddenTypes.isEmpty) {
return;
}
@ -461,11 +463,8 @@ class InstanceMemberInferrer {
}
/**
* If the [element] has formal type parameters, then the [overriddenType]
* must have it as well, but they are different. Replace type parameters
* of the [overriddenType] with type formals of the [element].
*
* Return `null`, in case of type parameters inconsistency.
* Return the [FunctionType] of the [overriddenElement] that [element]
* overrides. Return `null`, in case of type parameters inconsistency.
*
* The overridden element must have the same number of generic type
* parameters as the target element, or none.
@ -476,9 +475,10 @@ class InstanceMemberInferrer {
* should infer this as `m<T>(T t)`.
*/
FunctionType _toOverriddenFunctionType(
ExecutableElement element, FunctionType overriddenType) {
ExecutableElement element, ExecutableElement overriddenElement) {
List<DartType> typeFormals =
TypeParameterTypeImpl.getTypes(element.type.typeFormals);
FunctionType overriddenType = overriddenElement.type;
if (overriddenType.typeFormals.isNotEmpty) {
if (overriddenType.typeFormals.length != typeFormals.length) {
return null;
@ -489,20 +489,21 @@ class InstanceMemberInferrer {
}
/**
* Return [overriddenTypes] that override [element].
* Return [FunctionType]s of [overriddenElements] that override [element].
* Return the empty list, in case of type parameters inconsistency.
*/
List<FunctionType> _toOverriddenFunctionTypes(
ExecutableElement element, List<FunctionType> overriddenTypes) {
var result = <FunctionType>[];
for (var overriddenType in overriddenTypes) {
overriddenType = _toOverriddenFunctionType(element, overriddenType);
ExecutableElement element, List<ExecutableElement> overriddenElements) {
var overriddenTypes = <FunctionType>[];
for (ExecutableElement overriddenElement in overriddenElements) {
FunctionType overriddenType =
_toOverriddenFunctionType(element, overriddenElement);
if (overriddenType == null) {
return const <FunctionType>[];
}
result.add(overriddenType);
overriddenTypes.add(overriddenType);
}
return result;
return overriddenTypes;
}
/**

View file

@ -11,7 +11,7 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/element_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
@ -1111,7 +1111,7 @@ class ElementResolverTest extends EngineTestCase with ResourceProviderMixin {
resourceProvider: resourceProvider);
_typeProvider = context.typeProvider;
var inheritance = new InheritanceManager2(context.typeSystem);
var inheritance = new InheritanceManager3(context.typeSystem);
Source source = new FileSource(getFile("/test.dart"));
CompilationUnitElementImpl unit = new CompilationUnitElementImpl();
unit.librarySource = unit.source = source;

View file

@ -11,7 +11,7 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/error/codes.dart';
@ -1527,7 +1527,7 @@ class StaticTypeAnalyzerTest extends EngineTestCase with ResourceProviderMixin {
context = AnalysisContextFactory.contextWithCore(
resourceProvider: resourceProvider);
}
var inheritance = new InheritanceManager2(context.typeSystem);
var inheritance = new InheritanceManager3(context.typeSystem);
Source source = new FileSource(getFile("/lib.dart"));
CompilationUnitElementImpl definingCompilationUnit =
new CompilationUnitElementImpl();

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'element_test.dart' as element;
import 'function_type_test.dart' as function_type;
import 'inheritance_manager2_test.dart' as inheritance_manager2;
import 'inheritance_manager3_test.dart' as inheritance_manager3;
/// Utility for manually running all tests.
main() {
@ -14,5 +15,6 @@ main() {
element.main();
function_type.main();
inheritance_manager2.main();
inheritance_manager3.main();
}, name: 'element');
}

View file

@ -400,7 +400,7 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
@override
void writeOverride(
FunctionType signature, {
ExecutableElement element, {
StringBuffer displayTextBuffer,
String returnTypeGroupName,
bool invokeSuper: false,
@ -414,7 +414,6 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
}
ExecutableElement element = signature.element as ExecutableElement;
String prefix = getIndent(1);
String prefix2 = getIndent(2);
ElementKind elementKind = element.kind;
@ -435,7 +434,7 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
// return type
DartType returnType = signature.returnType;
DartType returnType = element.returnType;
bool typeWritten = writeType(returnType,
groupName: returnTypeGroupName, methodBeingCopied: element);
if (typeWritten) {
@ -475,9 +474,10 @@ class DartEditBuilderImpl extends EditBuilderImpl implements DartEditBuilder {
}
displayTextBuffer?.write(' => …');
} else {
List<ParameterElement> parameters = signature.parameters;
List<ParameterElement> parameters = element.parameters;
withCarbonCopyBuffer(() {
writeTypeParameters(signature.typeFormals, methodBeingCopied: element);
writeTypeParameters(element.type.typeFormals,
methodBeingCopied: element);
writeParameters(parameters, methodBeingCopied: element);
});
writeln(' {');

View file

@ -208,13 +208,13 @@ abstract class DartEditBuilder implements EditBuilder {
/**
* Append a placeholder for an override of the specified inherited
* [signature]. If provided, write a string value suitable for display
* [element]. If provided, write a string value suitable for display
* (e.g., in a completion popup) in the given [displayTextBuffer].
* If [invokeSuper] is `true`, then the corresponding `super.name()` will be
* added in the body.
*/
void writeOverride(
FunctionType signature, {
ExecutableElement element, {
StringBuffer displayTextBuffer,
bool invokeSuper: false,
});

View file

@ -9,7 +9,7 @@ import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
@ -2586,7 +2586,7 @@ class B extends A {
}
TypeSystem typeSystem = await session.typeSystem;
var inherited = new InheritanceManager2(typeSystem).getInherited(
var inherited = new InheritanceManager3(typeSystem).getInherited(
targetElement.type,
new Name(null, nameToOverride),
);

View file

@ -15,7 +15,7 @@ import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/sdk.dart';
@ -336,7 +336,7 @@ class LinkedAnalysisDriver {
(uri) => _isLibraryUri('$uri'),
resynthesizer.context,
resynthesizer,
InheritanceManager2(resynthesizer.typeSystem),
InheritanceManager3(resynthesizer.typeSystem),
libraryFile,
_resourceProvider);
// TODO(jmesserly): ideally we'd use the existing public `analyze()` method,