generateForAnnotatedElement method

  1. @override
dynamic generateForAnnotatedElement(
  1. Element element,
  2. ConstantReader annotation,
  3. BuildStep buildStep
)
override

Implement to return source code to generate for element.

This method is invoked based on finding elements annotated with an instance of T. The annotation is provided as a ConstantReader.

Supported return values include a single String or multiple String instances within an Iterable or Stream. It is also valid to return a Future of String, Iterable, or Stream.

Implementations should return null when no content is generated. Empty or whitespace-only String instances are also ignored.

Implementation

@override
generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) {
  if (element is! ClassElement) {
    throw InvalidGenerationSourceError("Lexer annotation is only valid for classes.");
  }
  int startState = annotation.read(_startStateField).intValue;
  String classname = element.name;
  List<MethodElement> children = element.methods;
  List<(MethodElement, Rule)> rules = [];

  for (var child in children) {
    var rule = _ruleChecker.firstAnnotationOfExact(child);
    if (rule != null) {
      rules.add((child, Rule(rule.getField(_patternField)!.toStringValue()!, rule.getField(_priorityField)!.toIntValue()!,
          state: rule.getField(_stateField)!.toIntValue())));
    }
  }

  {
    for (var r in rules) {
      if (r.$2.pattern.isEmpty) {
        throw InvalidGenerationSourceError("Rule has empty pattern: ${r.$1.name}");
      }
    }
  }
  var ruleLists = rules.groupListsBy((e) => e.$2.priority);
  List<int> priorities = ruleLists.keys.sorted((a, b) => b - a).toList();

  String rulesString = "";


  for (int k in priorities) {
    rulesString +=
    "[${ruleLists[k]!.map((e) => _ruleToString(e.$2, e.$1.name)).reduce((value,
        element) => "$value, $element")}],";
  }
  rulesString = "[$rulesString]";


  String classCode = "abstract class _$classname<T extends Token> extends LexerBase<T> {\n";
  for (var r in rules) {
    classCode += "TokenResponse<T> ${r.$1.name}(String token, int line, int char, int index);\n";
  }

  classCode += "_$classname() : super($startState) {rules = $rulesString;}\n";


  classCode += "}";
  return classCode;
}