write method

void write(
  1. String code, {
  2. Map<String, void Function()> args = const {},
})

Interpolates the given code, gracefully printing types and adding type prefixes if necessary.

This works by interpolating #{{uri|type}} into the code. A typical usage would be:

codeBuffer.write('''
  void main() {
    final controller = #{{dart:async|StreamController}}<int>();
  }
''');

The buffer will then interpolate the #{{uri|type}} and use relevant imports to write the code.

As such, the generated code may look like:

import 'dart:async' as _i1;

void main() {
  final controller = _i1.StreamController<int>();
}

Note: Some syntax sugar for package URIs are supported. You can write:

  • #{{example|Name}}(same as #{{package:example/example.dart|Name}})
  • #{{example/foo|Name}} (same as #{{package:example/foo.dart|Name}})

args can optionally be provided to insert custom 'write' operations at specific places in the code. It relies by inserting #{{name}} in the code, and then looking up corresponding keys within args. It is commonly used in conjunction with other write calls to write code conditionally or on a loop:

codeBuffer.write(args: {
  'properties': () {
     for (final property in [...]) {
       codeBuffer.write('final ${property.name} = ${property.code};');
     }
  },
}, '''
class Generated extends #{{package:flutter/widgets|StatelessWidget}} {
  #{{properties}}
}
''');

See also:

Implementation

void write(String code, {Map<String, void Function()> args = const {}}) {
  final prevLookup = _lookupArg;
  final lookup = _lookupArg = (name) {
    return args[name] ?? prevLookup?.call(name);
  };

  try {
    final reg = RegExp('#{{(.+?)}}');

    var previousIndex = 0;
    for (final match in reg.allMatches(code)) {
      _buffer.write(code.substring(previousIndex, match.start));
      previousIndex = match.end;

      final matchedString = match.group(1)!;
      _parseCode(
        matchedString,
        generatedFile: _generatedFile,
        onArg: (argName) {
          final arg = lookup(argName);
          if (arg == null) {
            throw ArgumentError('No argument found for $argName');
          }
          arg();
        },
        onUri: (uri, symbol) {
          final prefix = _upsertImport(uri, symbol).prefix;
          if (prefix != null) {
            _buffer.write(prefix);
            _buffer.write('.');
          }
          _buffer.write(symbol);
        },
      );
    }

    _buffer.write(code.substring(previousIndex));
  } finally {
    _lookupArg = prevLookup;
  }
}