blob: c284ee8a493e680851abc502b97a7d1bb7d32d68 [file] [log] [blame]
// Copyright (c) 2015, 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.
library domains.analysis.implemented_dart;
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/element/element.dart';
class ImplementedComputer {
final SearchEngine searchEngine;
final CompilationUnitElement unitElement;
List<protocol.ImplementedClass> classes = <protocol.ImplementedClass>[];
List<protocol.ImplementedMember> members = <protocol.ImplementedMember>[];
Set<ClassElement> subtypes;
ImplementedComputer(this.searchEngine, this.unitElement);
compute() async {
for (ClassElement type in unitElement.types) {
// always include Object and its members
if (type.supertype == null) {
_addImplementedClass(type);
type.accessors.forEach(_addImplementedMember);
type.fields.forEach(_addImplementedMember);
type.methods.forEach(_addImplementedMember);
continue;
}
// analyze ancestors
subtypes = await searchEngine.searchAllSubtypes(type);
if (subtypes.isNotEmpty) {
_addImplementedClass(type);
}
type.accessors.forEach(_addMemberIfImplemented);
type.fields.forEach(_addMemberIfImplemented);
type.methods.forEach(_addMemberIfImplemented);
}
}
void _addImplementedClass(ClassElement type) {
int offset = type.nameOffset;
int length = type.nameLength;
classes.add(new protocol.ImplementedClass(offset, length));
}
void _addImplementedMember(Element member) {
int offset = member.nameOffset;
int length = member.nameLength;
members.add(new protocol.ImplementedMember(offset, length));
}
void _addMemberIfImplemented(Element element) {
if (element.isSynthetic || _isStatic(element)) {
return;
}
if (_hasOverride(element)) {
_addImplementedMember(element);
}
}
bool _hasOverride(Element element) {
String name = element.displayName;
LibraryElement library = element.library;
for (ClassElement subtype in subtypes) {
ClassMemberElement subElement = subtype.getMethod(name);
if (subElement == null) {
subElement = subtype.getField(name);
}
if (subElement != null &&
!subElement.isStatic &&
subElement.isAccessibleIn(library)) {
return true;
}
}
return false;
}
/**
* Return `true` if the given [element] is a static element.
*/
static bool _isStatic(Element element) {
if (element is ExecutableElement) {
return element.isStatic;
} else if (element is PropertyInducingElement) {
return element.isStatic;
}
return false;
}
}