Expression _expressionFromDartObject()

in lib/src/builder.dart [1268:1350]


  Expression _expressionFromDartObject(DartObject object,
      [ParameterElement? parameter]) {
    final constant = ConstantReader(object);
    if (constant.isNull) {
      return literalNull;
    } else if (constant.isBool) {
      return literalBool(constant.boolValue);
    } else if (constant.isDouble) {
      return literalNum(constant.doubleValue);
    } else if (constant.isInt) {
      return literalNum(constant.intValue);
    } else if (constant.isString) {
      return literalString(constant.stringValue, raw: true);
    } else if (constant.isList) {
      return literalConstList([
        for (var element in constant.listValue)
          _expressionFromDartObject(element)
      ]);
    } else if (constant.isMap) {
      return literalConstMap({
        for (var pair in constant.mapValue.entries)
          _expressionFromDartObject(pair.key!):
              _expressionFromDartObject(pair.value!)
      });
    } else if (constant.isSet) {
      return literalConstSet({
        for (var element in constant.setValue)
          _expressionFromDartObject(element)
      });
    } else if (constant.isType) {
      // TODO(srawlins): It seems like this might be revivable, but Angular
      // does not revive Types; we should investigate this if users request it.
      var type = object.toTypeValue()!;
      var typeStr = type.getDisplayString(withNullability: false);
      throw _ReviveException('default value is a Type: $typeStr.');
    } else {
      // If [constant] is not null, a literal, or a type, then it must be an
      // object constructed with `const`. Revive it.
      var revivable = constant.revive();
      if (revivable.isPrivate) {
        final privateReference = revivable.accessor.isNotEmpty
            ? '${revivable.source}::${revivable.accessor}'
            : '${revivable.source}';
        throw _ReviveException(
            'default value has a private type: $privateReference.');
      }
      if (object.toFunctionValue() != null) {
        // A top-level function, like `void f() {}` must be referenced by its
        // identifier, rather than a revived value.
        var element = object.toFunctionValue();
        return referImported(revivable.accessor, _typeImport(element));
      } else if (revivable.source.fragment.isEmpty) {
        // We can create this invocation by referring to a const field or
        // top-level variable.
        return referImported(
            revivable.accessor, _typeImport(object.type!.element));
      }

      final name = revivable.source.fragment;
      final positionalArgs = [
        for (var argument in revivable.positionalArguments)
          _expressionFromDartObject(argument)
      ];
      final namedArgs = {
        for (var pair in revivable.namedArguments.entries)
          pair.key: _expressionFromDartObject(pair.value)
      };
      final element = parameter != null && name != object.type!.element!.name
          ? parameter.type.element
          : object.type!.element;
      final type = referImported(name, _typeImport(element));
      if (revivable.accessor.isNotEmpty) {
        return type.constInstanceNamed(
          revivable.accessor,
          positionalArgs,
          namedArgs,
          // No type arguments. See
          // https://github.com/dart-lang/source_gen/issues/478.
        );
      }
      return type.constInstance(positionalArgs, namedArgs);
    }
  }