Skip to content

Commit

Permalink
Merge pull request #612 from Workiva/CPLAT-11722-add-uiForwardRef
Browse files Browse the repository at this point in the history
CPLAT-11722 Add uiForwardRef
  • Loading branch information
rmconsole2-wf authored Aug 7, 2020
2 parents 1c56416 + d12bca5 commit 4ff4b37
Show file tree
Hide file tree
Showing 49 changed files with 2,606 additions and 814 deletions.
4 changes: 2 additions & 2 deletions doc/new_boilerplate_migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ UiFactory<UiProps> Foo = uiFunction(
(props) {
return 'id: ${props.id}';
},
FunctionComponentConfig(
UiFactoryConfig(
displayName: 'Foo',
),
);
Expand Down Expand Up @@ -823,7 +823,7 @@ UiFactory<FooProps> createFooHoc(UiFactory otherFactory) {
Dom.div()('prop foo: ${props.foo}'),
);
},
FunctionComponentConfig(
UiFactoryConfig(
displayName: 'FooHoc',
propsFactory: PropsFactory.fromUiFactory(Foo),
),
Expand Down
4 changes: 2 additions & 2 deletions example/builder/src/function_component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ ReactElement functionComponentContent() {

final genericFactory = uiFunction<UiProps>(
GenericFactory,
FunctionComponentConfig(),
UiFactoryConfig(),
);

final basicFactory = uiFunction<BasicProps>(
Expand All @@ -88,7 +88,7 @@ ReactElement functionComponentContent() {
Dom.div()('prop basic1: ${props.basic1}'),
);
},
FunctionComponentConfig(
UiFactoryConfig(
propsFactory: PropsFactory.fromUiFactory(Basic),
displayName: 'basicFactory',
)
Expand Down
28 changes: 13 additions & 15 deletions example/builder/src/function_component.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/hooks/use_callback_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions example/hooks/use_context_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions example/hooks/use_debug_value_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions example/hooks/use_imperative_handle_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,14 @@ class FancyInputApi {
FancyInputApi(this.focus);
}

UiFactory<FancyInputProps> FancyInput =
forwardRef<FancyInputProps>((props, ref) {
return (_FancyInput()
..forwardedRef = ref
..addProps(props)
)();
})(_FancyInput);
UiFactory<FancyInputProps> FancyInput = uiForwardRef((props, ref) {
return (_FancyInput()
..forwardedRef = ref
..addProps(props)
)();
},
_FancyInput.asForwardRefConfig(displayName: 'FancyInputForwardRef')
);

UiFactory<FancyInputProps> _FancyInput = uiFunction(
(props) {
Expand Down
17 changes: 8 additions & 9 deletions example/hooks/use_imperative_handle_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/hooks/use_layout_effect_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/hooks/use_memo_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/hooks/use_reducer_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/hooks/use_ref_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions example/hooks/use_state_example.over_react.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/over_react.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export 'src/component_declaration/component_base_2.dart'
UiStatefulMixin2;
export 'src/component_declaration/built_redux_component.dart';
export 'src/component_declaration/flux_component.dart';
export 'src/component_declaration/function_component.dart';
export 'src/component_declaration/function_component.dart' hide getFunctionName, GenericUiProps;
export 'src/util/character_constants.dart';
export 'src/util/class_names.dart';
export 'src/util/constants_base.dart';
Expand Down
10 changes: 5 additions & 5 deletions lib/src/builder/codegen/typed_map_impl_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -371,15 +371,15 @@ class _TypedMapImplGenerator extends TypedMapImplGenerator {
member = declaration.props.either,
isProps = true,
componentFactoryName = 'null',
isFunctionComponentDeclaration = declaration.factories.first.isFunctionComponentFactory,
isFunctionComponentDeclaration = declaration.factories.first.shouldGenerateConfig,
version = declaration.version;

@override
bool get isComponent2 => true;

String _generateFunctionComponentConfig(FactoryNames factoryName) {
return 'final FunctionComponentConfig<${names.implName}> '
'${factoryName.configName} = FunctionComponentConfig(\n'
String _generateUiFactoryConfig(FactoryNames factoryName) {
return 'final UiFactoryConfig<${names.implName}> '
'${factoryName.configName} = UiFactoryConfig(\n'
'propsFactory: PropsFactory(\n'
'map: (map) => ${names.implName}(map),\n'
'jsMap: (map) => ${names.jsMapImplName}(map),),\n'
Expand All @@ -390,7 +390,7 @@ class _TypedMapImplGenerator extends TypedMapImplGenerator {
void _generateFactory() {
if (isFunctionComponentDeclaration) {
for (final factoryName in factoryNames) {
outputContentsBuffer.write(_generateFunctionComponentConfig(factoryName));
outputContentsBuffer.write(_generateUiFactoryConfig(factoryName));
}
} else {
super._generateFactory();
Expand Down
14 changes: 5 additions & 9 deletions lib/src/builder/parsing/ast_util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,11 @@ extension InitializerHelperTopLevel on TopLevelVariableDeclaration {
/// The first variable in this list.
VariableDeclaration get firstVariable => variables.firstVariable;

/// Returns whether or not the config argument of `uiFunction` is generated.
bool get hasGeneratedConfigArg {
/// Returns whether or not there is a generated config being used.
bool get usesAGeneratedConfig {
return firstInitializer != null &&
anyDescendantIdentifiers(firstInitializer, (identifier) {
if (identifier.name == 'uiFunction') {
final args =
identifier.thisOrAncestorOfType<MethodInvocation>()?.argumentList?.arguments;
if (args == null || args.length < 2) return false;
return args[1].toString().startsWith(RegExp(r'\$'));
}
return false;
return identifier.nameWithoutPrefix == '\$${firstVariable.name.name}Config';
});
}
}
Expand All @@ -79,6 +73,8 @@ extension NameHelper on Identifier {
final self = this;
return self is PrefixedIdentifier ? self.identifier.name : self.name;
}

bool get isFunctionType => ['uiFunction', 'uiForwardRef', 'uiJsComponent'].contains(this.name);
}

/// Utilities related to detecting a super class on a [MixinDeclaration]
Expand Down
3 changes: 1 addition & 2 deletions lib/src/builder/parsing/declarations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,7 @@ class FactoryGroup {
return factoriesInitializedToIdentifier.first;
}

final functionComponentFactories =
factories.where((factory) => factory.isFunctionComponentFactory);
final functionComponentFactories = factories.where((factory) => factory.shouldGenerateConfig);
if (functionComponentFactories.isNotEmpty) {
return functionComponentFactories.first;
}
Expand Down
8 changes: 3 additions & 5 deletions lib/src/builder/parsing/declarations_from_members.dart
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,10 @@ Iterable<BoilerplateDeclaration> getBoilerplateDeclarations(
}
}

if (factory.isFunctionComponentFactory) {
if (factory.shouldGenerateConfig) {
final factories = factoryGroups.firstWhere((group) => group.bestFactory == factory);
final generatedFactories = factories.factories.where((factory) =>
factory.node.hasGeneratedConfigArg &&
factory.isFunctionComponentFactory &&
factory.versionConfidences.maxConfidence.shouldGenerate);
final generatedFactories = factories.factories
.where((factory) => factory.versionConfidences.maxConfidence.shouldGenerate);
final associatedProps =
getPropsForFunctionComponent(members.props, members.propsMixins, factory);
if (generatedFactories.isNotEmpty &&
Expand Down
11 changes: 4 additions & 7 deletions lib/src/builder/parsing/members/factory.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class BoilerplateFactory extends BoilerplateMember {
}
}

if (isFunctionComponentFactory) {
if (shouldGenerateConfig) {
final uiFunctionInvocation = getDescendantIdentifier(
node.variables.firstInitializer, (identifier) => identifier.name == 'uiFunction');
node.variables.firstInitializer, (identifier) => identifier.isFunctionType);
final methodInvocation = uiFunctionInvocation.thisOrAncestorOfType<MethodInvocation>();
final typeArgs = methodInvocation?.typeArguments?.arguments?.first;
return typeArgs;
Expand All @@ -53,10 +53,7 @@ class BoilerplateFactory extends BoilerplateMember {

bool get hasFactoryAnnotation => node.hasAnnotationWithName('Factory');

bool get isFunctionComponentFactory =>
node.variables.firstInitializer != null &&
anyDescendantIdentifiers(
node.variables.firstInitializer, (identifier) => identifier.name == 'uiFunction');
bool get shouldGenerateConfig => node.usesAGeneratedConfig;

/// Verifies the correct implementation of a boilerplate factory
///
Expand Down Expand Up @@ -94,7 +91,7 @@ class BoilerplateFactory extends BoilerplateMember {
anyDescendantIdentifiers(
initializer, (identifier) => identifier.name == generatedFactoryName);

if (!referencesGeneratedFactory && !isFunctionComponentFactory) {
if (!referencesGeneratedFactory && !shouldGenerateConfig) {
errorCollector.addError(
'Factory variables are stubs for the generated factories, and must '
'be initialized with or otherwise reference the generated factory. Should be: `$factoryName = $generatedFactoryName`',
Expand Down
5 changes: 2 additions & 3 deletions lib/src/builder/parsing/members_from_ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,11 @@ class _BoilerplateMemberDetector {
}

final rightHandSide = node.variables.firstInitializer;
if (rightHandSide != null &&
anyDescendantIdentifiers(rightHandSide, (identifier) => identifier.name == 'uiFunction')) {
if (rightHandSide != null && node.usesAGeneratedConfig) {
onFactory(BoilerplateFactory(
node,
VersionConfidences(
v4_mixinBased: node.hasGeneratedConfigArg ? Confidence.likely : Confidence.neutral,
v4_mixinBased: Confidence.likely,
v3_legacyDart2Only: Confidence.none,
v2_legacyBackwardsCompat: Confidence.none,
)));
Expand Down
Loading

0 comments on commit 4ff4b37

Please sign in to comment.