String checkValidity()

in lib/src/intl_message.dart [133:230]


  String checkValidity(MethodInvocation node, List arguments, String outerName,
      FormalParameterList outerArgs,
      {bool nameAndArgsGenerated: false, bool examplesRequired: false}) {
    // If we have parameters, we must specify args and name.
    NamedExpression args = arguments.firstWhere(
        (each) => each is NamedExpression && each.name.label.name == 'args',
        orElse: () => null);
    var parameterNames =
        outerArgs.parameters.map((x) => x.identifier.name).toList();
    var hasArgs = args != null;
    var hasParameters = !outerArgs.parameters.isEmpty;
    if (!nameAndArgsGenerated && !hasArgs && hasParameters) {
      return "The 'args' argument for Intl.message must be specified for "
          "messages with parameters. Consider using rewrite_intl_messages.dart";
    }
    if (!checkArgs(args, parameterNames)) {
      return "The 'args' argument must match the message arguments,"
          " e.g. args: ${parameterNames}";
    }
    var messageNameArgument = arguments.firstWhere(
        (eachArg) =>
            eachArg is NamedExpression && eachArg.name.label.name == 'name',
        orElse: () => null);
    var nameExpression = messageNameArgument?.expression;
    String messageName;
    String givenName;

    //TODO(alanknight): If we generalize this to messages with parameters
    // this check will need to change.
    if (nameExpression == null) {
      if (!hasParameters) {
        // No name supplied, no parameters. Use the message as the name.
        messageName = _evaluateAsString(arguments[0]);
        outerName = messageName;
      } else {
        // We have no name and parameters, but the transformer generates the
        // name.
        if (nameAndArgsGenerated) {
          givenName = outerName;
          messageName = givenName;
        } else {
          return "The 'name' argument for Intl.message must be supplied for "
              "messages with parameters. Consider using "
              "rewrite_intl_messages.dart";
        }
      }
    } else {
      // Name argument is supplied, use it.
      givenName = _evaluateAsString(nameExpression);
      messageName = givenName;
    }

    if (messageName == null) {
      return "The 'name' argument for Intl.message must be a string literal";
    }

    var hasOuterName = outerName != null;
    var simpleMatch = outerName == givenName || givenName == null;

    var classPlusMethod = Message.classPlusMethodName(node, outerName);
    var classMatch = classPlusMethod != null && (givenName == classPlusMethod);
    if (!(hasOuterName && (simpleMatch || classMatch))) {
      return "The 'name' argument for Intl.message must match either "
          "the name of the containing function or <ClassName>_<methodName> ("
          "was '$givenName' but must be '$outerName'  or '$classPlusMethod')";
    }

    var simpleArguments = arguments.where((each) =>
        each is NamedExpression &&
        ["desc", "name"].contains(each.name.label.name));
    var values = simpleArguments.map((each) => each.expression).toList();
    for (var arg in values) {
      if (_evaluateAsString(arg) == null) {
        return ("Intl.message arguments must be string literals: $arg");
      }
    }

    if (hasParameters) {
      var exampleArg = arguments.where((each) =>
          each is NamedExpression && each.name.label.name == "examples");
      var examples = exampleArg.map((each) => each.expression).toList();
      if (examples.isEmpty && examplesRequired) {
        return "Examples must be provided for messages with parameters";
      }
      if (examples.isNotEmpty) {
        var example = examples.first;
        var map = _evaluateAsMap(example);
        if (map == null) {
          return "Examples must be a const Map literal.";
        }
        if (example.constKeyword == null) {
          return "Examples must be const.";
        }
      }
    }

    return null;
  }