blob: fe87f3d2192f887e5b7b8d5896f81820eb5fc5e1 [file] [log] [blame]
// 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/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:meta/meta.dart';
mixin ElementsTypesMixin {
DynamicTypeImpl get dynamicType => typeProvider.dynamicType;
TypeProvider get typeProvider;
ClassElementImpl class_({
@required String name,
bool isAbstract = false,
InterfaceType superType,
List<TypeParameterElement> typeParameters = const [],
List<InterfaceType> interfaces = const [],
List<InterfaceType> mixins = const [],
List<MethodElement> methods = const [],
}) {
var element = ClassElementImpl(name, 0);
element.typeParameters = typeParameters;
element.supertype = superType ?? typeProvider.objectType;
element.interfaces = interfaces;
element.mixins = mixins;
element.methods = methods;
return element;
}
FunctionType functionType({
List<TypeParameterElement> typeFormals,
List<DartType> required,
List<DartType> optional,
Map<String, DartType> named,
DartType returns,
NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
}) {
if (optional != null && named != null) {
throw ArgumentError(
'Cannot have both optional positional and named parameters.',
);
}
var parameters = <ParameterElement>[];
if (required != null) {
for (var i = 0; i < required.length; ++i) {
parameters.add(
ParameterElementImpl.synthetic(
'r$i',
required[i],
ParameterKind.REQUIRED,
),
);
}
}
if (optional != null) {
for (var i = 0; i < optional.length; ++i) {
parameters.add(
ParameterElementImpl.synthetic(
'p$i',
optional[i],
ParameterKind.POSITIONAL,
),
);
}
}
if (named != null) {
for (var namedEntry in named.entries) {
parameters.add(
ParameterElementImpl.synthetic(
namedEntry.key,
namedEntry.value,
ParameterKind.NAMED,
),
);
}
}
return FunctionTypeImpl.synthetic(
returns ?? typeProvider.voidType,
typeFormals ?? const <TypeParameterElement>[],
parameters,
nullabilitySuffix: nullabilitySuffix,
);
}
FunctionType functionTypeAliasType(
FunctionTypeAliasElement element, {
List<DartType> typeArguments = const [],
NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
}) {
return element.instantiate2(
typeArguments: typeArguments,
nullabilitySuffix: nullabilitySuffix,
);
}
DartType futureType(DartType T) {
var futureElement = typeProvider.futureElement;
return interfaceType(futureElement, typeArguments: [T]);
}
GenericFunctionTypeElementImpl genericFunctionType({
List<TypeParameterElement> typeParameters,
List<ParameterElement> parameters,
DartType returnType,
}) {
var result = GenericFunctionTypeElementImpl.forOffset(0);
result.typeParameters = typeParameters;
result.parameters = parameters;
result.returnType = returnType ?? typeProvider.voidType;
return result;
}
GenericTypeAliasElementImpl genericTypeAlias({
@required String name,
List<TypeParameterElement> typeParameters = const [],
@required GenericFunctionTypeElement function,
}) {
return GenericTypeAliasElementImpl(name, 0)
..typeParameters = typeParameters
..function = function;
}
InterfaceType interfaceType(
ClassElement element, {
List<DartType> typeArguments = const [],
NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
}) {
return InterfaceTypeImpl.explicit(
element,
typeArguments,
nullabilitySuffix: nullabilitySuffix,
);
}
MethodElement method(
String name,
DartType returnType, {
bool isStatic = false,
List<TypeParameterElement> typeFormals = const [],
List<ParameterElement> parameters = const [],
}) {
var element = MethodElementImpl(name, 0)
..isStatic = isStatic
..parameters = parameters
..returnType = returnType
..typeParameters = typeFormals;
element.type = _typeOfExecutableElement(element);
return element;
}
ParameterElement namedParameter(String name, {@required DartType type}) {
var parameter = ParameterElementImpl(name, 0);
parameter.parameterKind = ParameterKind.NAMED;
parameter.type = type;
return parameter;
}
ParameterElement positionalParameter(String name, {@required DartType type}) {
var parameter = ParameterElementImpl(name, 0);
parameter.parameterKind = ParameterKind.POSITIONAL;
parameter.type = type;
return parameter;
}
ParameterElement requiredParameter(String name, {@required DartType type}) {
var parameter = ParameterElementImpl(name, 0);
parameter.parameterKind = ParameterKind.REQUIRED;
parameter.type = type;
return parameter;
}
TypeParameterElementImpl typeParameter(String name, {DartType bound}) {
var element = TypeParameterElementImpl.synthetic(name);
element.bound = bound;
return element;
}
TypeParameterTypeImpl typeParameterType(
TypeParameterElement element, {
NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
}) {
return TypeParameterTypeImpl(
element,
nullabilitySuffix: nullabilitySuffix,
);
}
/// TODO(scheglov) We should do the opposite - build type in the element.
/// But build a similar synthetic / structured type.
FunctionType _typeOfExecutableElement(ExecutableElement element) {
return FunctionTypeImpl.synthetic(
element.returnType,
element.typeParameters,
element.parameters,
);
}
}