dvHomeWidgetDeclaration top-level property

RegExp dvHomeWidgetDeclaration
final

The declaration a @DVHomeWidget annotation sits above.

One pattern, in core, because two scanners read it: the generator that writes the page and the route, and the build check that decides whether the target being built has anywhere to put one. They held a copy each, and both copies matched the literal @DVHomeWidget() -- empty parentheses included. Giving a widget the shell properties the specification promises therefore deleted it: no entry in the generated list, no route, no provider, no extension, and no message anywhere, with the annotation still in the file saying otherwise.

The specification puts the annotation on "any widget, whether Flutter-native, DVClassWidget, or DVFunctionalWidget", so the class shape is matched as well as the function shape -- and it is matched first, which is the whole of the fix. The function branch's return type is deliberately loose, because a widget-returning function may be written with any of several types, and loose enough to swallow class _StepCounter extends and take StatelessWidget for the declared name. What came of that was a message telling the developer to rename a class in the Flutter SDK, about a widget nothing had read.

Read the pieces out with dvHomeWidgetAnnotationArgs, dvHomeWidgetDeclaredName and dvHomeWidgetIsClass rather than by group number: two scanners share this, and a group index counted by hand in each is a scan that silently reads the wrong capture when the pattern grows another one.

Implementation

final RegExp dvHomeWidgetDeclaration = RegExp(
  r'@DVHomeWidget\(([^)]*)\)\s*(?:@[A-Za-z_][\w.]*\([^)]*\)\s*)*'
  r'(?:class\s+(?:const\s+)?(?<widgetClass>[A-Za-z_][A-Za-z0-9_]*)\b'
  r'|(?:Widget|[A-Za-z_][\w<>, ?]*)\s+(?<widgetFunction>[A-Za-z_][A-Za-z0-9_]*)\s*\()',
);