blob: 15d86ef7169c3815c03b201b5826e91b343652ed [file] [log] [blame]
// Copyright (c) 2017, Google Inc. 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:built_collection/built_collection.dart';
import 'package:built_value_generator/src/value_source_class.dart';
BuiltSet<String> _builtCollectionNames = BuiltSet<String>([
'BuiltList',
'BuiltListMultimap',
'BuiltMap',
'BuiltSet',
'BuiltSetMultimap',
]);
class DartTypes {
static bool needsNestedBuilder(DartType type) {
return isInstantiableBuiltValue(type) || isBuiltCollection(type);
}
static bool isInstantiableBuiltValue(DartType type) {
return isBuiltValue(type) &&
ValueSourceClass(type.element as ClassElement).settings.instantiable;
}
static bool isBuiltValue(DartType type) {
if (type.element is! ClassElement) return false;
return (type.element as ClassElement)
.allSupertypes
.any((interfaceType) => interfaceType.name == 'Built');
}
static bool isBuiltCollection(DartType type) {
return _builtCollectionNames
.any((name) => getName(type).startsWith('$name<'));
}
static bool isBuilt(DartType type) =>
isBuiltValue(type) || isBuiltCollection(type);
static bool isBuiltCollectionTypeName(String name) =>
_builtCollectionNames.contains(name);
/// Gets the name of a `DartType`. Supports `Function` types, which will
/// be returned using the `Function()` syntax.
static String getName(DartType dartType) {
if (dartType == null) {
return null;
} else if (dartType.isDynamic) {
return 'dynamic';
} else if (dartType is FunctionType) {
return getName(dartType.returnType) +
' Function(' +
dartType.parameters.map((p) => getName(p.type)).join(', ') +
')';
} else if (dartType is InterfaceType) {
var typeArguments = dartType.typeArguments;
if (typeArguments.isEmpty || typeArguments.every((t) => t.isDynamic)) {
return dartType.element.name;
} else {
final typeArgumentsStr = typeArguments.map(getName).join(', ');
return '${dartType.element.name}<$typeArgumentsStr>';
}
} else if (dartType is TypeParameterType) {
return dartType.element.name;
} else if (dartType.isVoid) {
return 'void';
} else {
throw UnimplementedError('(${dartType.runtimeType}) $dartType');
}
}
/// Turns a type name, optionally with generics, into just the type name.
static String stripGenerics(String name) {
var genericsStart = name.indexOf('<');
return genericsStart == -1 ? name : name.substring(0, genericsStart);
}
}