parse method

DefinedOperation parse ()


DefinedOperation parse() {
  final annotation = method.metadata.single.computeConstantValue();

  final annotationName = annotation.type.displayName;
  StatementType type;
  switch (annotationName) {
    case "Update":
    case "Delete":
      type = StatementType.update;
    case "Insert":
      type = StatementType.insert;
    case "Query":
      type =;

  String sql = annotation.getField("(super)").getField("sql").toStringValue();

  if (!method.returnType.isDartAsyncFuture) {
    error("Database methods must return an async future", method);
  if (method.isStatic) {
    error("Database methods may not be static", method);
  if (method.typeParameters.isNotEmpty) {
    error("Database methods may not be generic", method);
  if (!(method.computeNode().body is EmptyFunctionBody)) {
    error("Database methods may not have an implementation", method);
  if (method.parameters.any((param) => param.isOptional)) {
    error("Parameters of database methods may not be optional or positional",

  final sqlWithVars = SqlVariableAnalyzer(sql).sqlWithVars;

  final operation = DefinedOperation(type, sqlWithVars, method);

  final equality = SetEquality();
  final varsInSql = sqlWithVars.foundVariables;
  final parameters = operation.parameters.keys.toSet();

  if (!equality.equals(varsInSql, parameters)) {
        "The variables in your SQL do not match the parameters defined "
        "in your method. All method parameters need to show up in SQL, and "
        "These variables were found in your SQL: $varsInSql\n"
        "And these varaibles were in your method: $parameters",

  final returnType = operation.returnTypeNoFutureOrList;
  if (type == &&
      !types.typeNativelySupported(returnType)) {
    // Parse & validate the return type if this didn't happen yet.

  return operation;