mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 08:44:27 +00:00
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:
parent
ae7bf9e999
commit
5d6bab4ed2
24 changed files with 1988 additions and 252 deletions
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
533
pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
Normal file
533
pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
Normal 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;
|
||||
}
|
|
@ -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>();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
1230
pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
Normal file
1230
pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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');
|
||||
}
|
||||
|
|
|
@ -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(' {');
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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),
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue