addFieldMethodPart static method
analyse fieldMethodPart if fits compiledMethod
Implementation
static Future<CompiledFieldMethodPart?> addFieldMethodPart(
TypeInfo type,
MethodElement compiledMethod,
MethodElement fieldMethodPart,
FieldElement field,
String thisReplace,
) async {
FormalParameterFragment fieldParameter = fieldMethodPart
.firstFragment
.formalParameters
.where((element) => element.name == 'field')
.first;
if (!type.typeMap.typeSystem.isSubtypeOf(
field.type,
fieldParameter.element.type,
) ||
//dynamic is nullable but returns empty suffix
!(fieldParameter.element.type is DynamicType ||
field.type.nullabilitySuffix ==
fieldParameter.element.type.nullabilitySuffix)) {
return null;
}
String? requireAnnotation;
for (var m in fieldMethodPart.metadata.annotations) {
if (m.toSource().startsWith('@AnnotatedWith(')) {
requireAnnotation =
'@${m.toSource().substring(15, m.toSource().length - 1)}';
}
}
if (requireAnnotation != null) {
bool pass = false;
for (var m in field.metadata.annotations) {
//support for parametrised required annotations
if (m.toSource() == requireAnnotation ||
m.toSource().startsWith('$requireAnnotation('))
pass = true;
}
if (!pass) return null;
}
var enclosingType = (field.enclosingElement is ClassElement)
? type.typeMap.fromDartType(
(field.enclosingElement as ClassElement).thisType,
context: type.typeArgumentsMap(),
)
: (field.enclosingElement is MixinElement)
? type.typeMap.fromDartType(
(field.enclosingElement as MixinElement).thisType,
context: type.typeArgumentsMap(),
)
: null;
if (enclosingType == null) {
return null;
}
CompiledFieldMethodPart compiledPart;
if (!type.typeMap.compiledMethodsByType[compiledMethod]!.containsKey(
enclosingType.uniqueName,
)) {
type.typeMap.compiledMethodsByType[compiledMethod]![enclosingType
.uniqueName] = compiledPart = CompiledFieldMethodPart(
type.typeMap,
compiledMethod,
enclosingType,
);
} else {
compiledPart = type
.typeMap
.compiledMethodsByType[compiledMethod]![enclosingType.uniqueName]!;
}
if (!compiledPart.stubs.containsKey(field) ||
!compiledPart.stubs[field]!.containsKey(fieldMethodPart)) {
//generate stub;
if (!compiledPart.stubs.containsKey(field)) {
compiledPart.stubs[field] = {};
}
List<String> stubLines = compiledPart.stubs[field]![fieldMethodPart] = [];
var compiledFieldType = type.typeMap.fromDartType(
field.type,
context: type.typeArgumentsMap(),
);
stubLines.add('{');
//magic parameter match
for (var methodParameter
in fieldMethodPart.firstFragment.formalParameters) {
if (compiledMethod.firstFragment.formalParameters
.where((element) => element.name == methodParameter.name)
.isNotEmpty) {
//this parameter comes from compiled method
continue;
}
if (methodParameter.name == fieldParameter.name) {
//this is a special param
continue;
}
var methodParameterValue = 'null';
//var methodParameterType = methodParameter.type.toString();
if (methodParameter.name == 'name') {
methodParameterValue = '"${field.name}"';
} else if (methodParameter.name == 'className') {
methodParameterValue = '"${compiledFieldType.uniqueName}"';
} else if (fieldParameter.element.type.isDartCoreEnum &&
methodParameter.name == 'values') {
methodParameterValue = '${compiledFieldType.uniqueName}.values';
} else if (methodParameter.element.isOptional) {
methodParameterValue =
methodParameter.element.defaultValueCode ?? 'null';
var nameParts = methodParameter.name!.split('_');
String annotationName =
'@${nameParts[0][0].toUpperCase()}${nameParts[0].substring(1)}';
if (nameParts.length == 1) {
methodParameterValue = 'false';
for (var fieldMeta in field.metadata.annotations) {
if (fieldMeta.toSource() == annotationName) {
methodParameterValue = 'true';
}
}
} else {
for (var fieldMeta in field.metadata.annotations) {
if (fieldMeta.toSource().startsWith('$annotationName(') ||
fieldMeta.toSource().startsWith('$annotationName.t(')) {
var constantValue = fieldMeta.computeConstantValue();
if (constantValue == null) {
methodParameterValue = '"COMPUTATION ERROR"';
break;
}
DartObject annotationField = constantValue.getField(
nameParts[1],
)!;
var annotationValue = annotationField.type!.getDisplayString();
switch (annotationValue) {
case 'Type':
//allow passing type as annotation
String typeName = fieldMeta.toSource();
typeName = typeName.substring(
typeName.indexOf('(') + 1,
typeName.indexOf(')'),
);
if (compiledPart.typeMap.allTypes.containsKey(typeName)) {
methodParameterValue = compiledPart.typeMap
.generateTypeGetter(
compiledPart.typeMap.allTypes[typeName]!,
);
} else {
methodParameterValue = "null";
}
break;
case 'String':
//todo toDartVariable?
methodParameterValue =
'"${annotationField.toStringValue()!.replaceAll('\$', '\\\$').replaceAll('"', '\\"')}"';
break;
case 'int':
methodParameterValue = annotationField
.toIntValue()
.toString();
break;
default:
methodParameterValue = annotationField.toString();
}
}
}
}
}
if (methodParameterValue.startsWith('\$')) {
stubLines.add('var ${methodParameter.name} = $methodParameterValue;');
} else {
stubLines.add(
'const ${methodParameter.name} = $methodParameterValue;',
);
}
}
String part = await fieldMethodPart.getSourceCode(type.typeMap.step);
if (fieldMethodPart.firstFragment.formalParameters.indexWhere(
(element) => element.name == 'field',
) >
-1) {
part = part.replaceAll(fieldParameter.name!, 'dis.${field.name}');
}
//TODO
part = part.replaceAll('this', thisReplace);
String paramClass = fieldParameter.element.type.getDisplayString();
String fieldClass = compiledFieldType.uniqueName;
part = part.replaceAll('as $paramClass', 'as $fieldClass');
if (paramClass.contains('<') && fieldClass.contains('<')) {
//TODO support many parameters?
String paramGenericParam = paramClass.substring(
paramClass.indexOf('<') + 1,
paramClass.length - 1,
);
String fieldGenericParam = fieldClass.substring(
fieldClass.indexOf('<') + 1,
fieldClass.length - 1,
);
part = part.replaceAll(
'as $paramGenericParam',
'as $fieldGenericParam',
);
}
//part = "// ${paramClass} \n" + part;
//part = "// ${fieldClass} \n" + part;
stubLines.add(part);
stubLines.add('}');
}
return compiledPart;
}