How to get function body as string using build_runner and source_gen?

369 views Asked by At

My goal is to make my unit tests easy to understand. Currently, they are hard to understand because they have so many nested functions.

I want to use build_runner to generate the code of the unit with all functions unwrapped.

So here is an example of my current test:

test.dart

import 'package:example_usage/src/unwrap.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

class Cat {
  String sound() => "Meow";
  int walk() => 4;
}

class Dog {
  final Cat cat;

  Dog(this.cat);

  String sayHi() {
    return this.cat.sound();
  }

  int jump() {
    return this.cat.walk();
  }
}

class MockCat extends Mock implements Cat {}

void main() {
  MockCat cat;
  Dog dog;

  @UnWrap()
  void setupCatSoundStub() {
    when(cat.sound()).thenReturn("Woof");
  }

  @UnWrap()
  void setupCatWalkstub() {
    when(cat.walk()).thenReturn(2);
  }

  @UnWrap()
  void expectCatCalled() {
    verify(cat.sound());
  }

  @UnWrap()
  void testDogWoof() {
    setupCatSoundStub();
    dog = Dog(cat);
    final sound = dog.sayHi();
    expect(sound, "Woof");
    expectCatCalled();
  }

  void expectCatWalked() {
    verify(cat.walk());
  }

  group('Dog Cat Play', () {
    setUp(() {
      cat = MockCat();
    });

    test('Dog woof', () {
      testDogWoof();
    });

    test('Dog woof then jump', () {
      testDogWoof();
      setupCatWalkstub();
      final steps = dog.jump();
      expect(steps, 2);
      expectCatWalked();
    });
  });
}

I want to generate a code like this

_$test.dart

void _$main() {
  MockCat cat;
  Dog dog;
  void expectCatWalked() {
    verify(cat.walk());
  }

  group('Dog Cat Play', () {
    setUp(() {
      cat = MockCat();
    });

    test('Dog woof', () {
      // testDogWoof();
      // setupCatSoundStub();
      when(cat.sound()).thenReturn("Woof");
      dog = Dog(cat);
      final sound = dog.sayHi();
      expect(sound, "Woof");
      // expectCatCalled();
      verify(cat.sound());
    });

    test('Dog woof then jump', () {
      // testDogWoof();
      // setupCatSoundStub();
      when(cat.sound()).thenReturn("Woof");
      dog = Dog(cat);
      final sound = dog.sayHi();
      expect(sound, "Woof");
      // expectCatCalled();
      verify(cat.sound());
      // setupCatWalkstub();
      when(cat.walk()).thenReturn(2);
      final steps = dog.jump();
      expect(steps, 2);
      expectCatWalked();
    });
  });
}

I found some tutorial online but I could find documentations about getting the function body into string ( some like JavaScript's Function.prototype.toString() method ) I am new to code generation so I tried to print all fields but I can't find anything like that.

import 'dart:async';

import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';

class InfoGenerator extends Generator {
  @override
  FutureOr<String> generate(LibraryReader library, BuildStep buildStep) {
    var buffer = StringBuffer();

    // library.allElements.forEach((element) {
    //   buffer.writeln(
    //       '// ${element.displayName} - ${element.source.fullName} - ${element.declaration}');
    // });
    library.allElements.whereType<TopLevelVariableElement>().forEach((element) {
      buffer.writeln('/*');
      buffer.writeln(element.toString());
      buffer.writeln('*/');
      buffer.writeln(
          '// ${element.name} - ${element.kind.displayName} - ${element.declaration}');
    });

    return buffer.toString();
  }
}

I am also new to annotations so I just made this up

/// What to do here ?
class UnWrap {
  const UnWrap();
}

Is what I am trying to do even possible ?

0

There are 0 answers