blob: b785df3802fcbfdb5e8e5e0c9c47ce40edf588d7 [file] [log] [blame]
// Copyright (c) 2014, 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.
/// The models used to represent Dart code.
library dartdoc.element_type;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'model.dart';
class ElementType {
final DartType _type;
final ModelElement element;
String _linkedName;
ElementType(this._type, this.element);
bool get isDynamic => _type.isDynamic;
bool get isFunctionType => (_type is FunctionType);
bool get isParameterizedType {
if (_type is FunctionType) {
return typeArguments.isNotEmpty;
} else if (_type is ParameterizedType) {
return (_type as ParameterizedType).typeArguments.isNotEmpty;
}
return false;
}
bool get isParameterType => (_type is TypeParameterType);
String get linkedName {
if (_linkedName != null) return _linkedName;
StringBuffer buf = new StringBuffer();
if (isParameterType) {
buf.write(name);
} else {
buf.write(element.linkedName);
}
// not TypeParameterType or Void or Union type
if (isParameterizedType) {
if (typeArguments.every((t) => t.linkedName == 'dynamic')) {
_linkedName = buf.toString();
return _linkedName;
}
if (typeArguments.isNotEmpty) {
buf.write('<');
buf.writeAll(typeArguments.map((t) => t.linkedName), ', ');
buf.write('>');
}
}
_linkedName = buf.toString();
return _linkedName;
}
String get name => _type.name;
ModelElement get returnElement {
Element e = _returnTypeCore.element;
if (e == null || e.library == null) {
return null;
}
Library lib = element.package.findLibraryFor(e);
if (lib == null) {
lib = new Library(e.library, element.package);
}
return (new ModelElement.from(e, lib));
}
List<ElementType> get typeArguments {
var type = _type;
if (type is FunctionType) {
Iterable<DartType> typeArguments;
if (type.element is FunctionTypeAliasElement &&
type.typeFormals.isEmpty) {
// TODO(jmesserly): simplify check above; we should have a way
// to find instantiated typedefs without consulting the element.
// Also, it will not work if we support typedefs declared inside classes.
typeArguments = type.typeArguments;
} else {
typeArguments = type.typeFormals.map((f) => f.type);
}
return typeArguments.map(_getElementTypeFrom).toList();
} else {
return (_type as ParameterizedType)
.typeArguments
.map((f) => _getElementTypeFrom(f))
.toList();
}
}
ElementType get _returnType {
var rt = _returnTypeCore;
Library lib = element.package.findLibraryFor(rt.element);
if (lib == null) {
lib = new Library(rt.element.library, element.package);
}
return new ElementType(rt, new ModelElement.from(rt.element, lib));
}
DartType get _returnTypeCore => (_type as FunctionType).returnType;
String get _returnTypeName => _returnTypeCore.name;
String createLinkedReturnTypeName() {
if (_returnTypeCore.element == null ||
_returnTypeCore.element.library == null) {
if (_returnTypeName != null) {
if (_returnTypeName == 'dynamic' && element.isAsynchronous) {
// TODO(keertip): for SDK docs it should be a link
return 'Future';
}
return _returnTypeName;
} else {
return '';
}
} else {
return _returnType.linkedName;
}
}
@override
String toString() => "$_type";
ElementType _getElementTypeFrom(DartType f) {
Library lib;
// can happen if element is dynamic
lib = element.package.findLibraryFor(f.element);
if (lib == null && f.element.library != null) {
lib = new Library(f.element.library, element.package);
}
return new ElementType(f, new ModelElement.from(f.element, lib));
}
}