I'm experimenting with possibly validating the plain data class against JsonSchema. First I tried to read the declared arguments of a given class constructor. Such as argument name, type, nullability, or required.
The dart analyzer package seems promising. But I can't find a way to determine the argument type.
This is the example code I created. This code gives me correct argument names and required or not. But I can't find the type of information.
import 'dart:io';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:flutter/cupertino.dart';
class Data {
const Data({
required this.id,
required this.name,
this.codename,
this.value = 0,
});
final int id;
final String name;
final String? codename;
final int value;
}
class PropertyAnalyzer extends RecursiveAstVisitor<void> {
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
debugPrint("constructor: ${node.name}");
final parameters = node.parameters.parameters;
for (final parameter in parameters) {
final paramName = parameter.name;
final paramType = parameter.declaredElement;
final required = parameter.isRequired;
final defaultValue = parameter is DefaultFormalParameter ? parameter.defaultValue : null;
debugPrint("$paramName\t$paramType\t$required\t$defaultValue");
}
}
}
String getSdkPath() {
final exePath = Platform.resolvedExecutable;
final i = exePath.indexOf("/flutter/bin");
return "${exePath.substring(0, i)}/flutter/bin/cache/dart-sdk";
}
void main() {
const filePath = "path/to/data.dart";
final collection = AnalysisContextCollection(includedPaths: [filePath], sdkPath: getSdkPath());
for (final c in collection.contexts) {
final currentSession = c.currentSession;
final result = currentSession.getParsedUnit(filePath);
if (result is ParsedUnitResult) {
result.unit.accept(PropertyAnalyzer());
}
}
}
My question is Am I going in the right direction? If this is the right direction then how to I determine the type information?
You can use
mirrorsto inspect and read the constructor argument types of a class at runtime:Output:
Note that
mirrorsis not supported inFlutterbecause it relies onruntime reflection, which Flutter'stree shakingandAOT (Ahead-Of-Time)compilation do not allow.