Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a29da58
Merge branch 'function-components-wip' of github.com:Workiva/over_rea…
joebingham-wk Jul 29, 2020
53fd919
Initial implementation
joebingham-wk Jul 29, 2020
968de33
Add first go at examples
joebingham-wk Jul 29, 2020
c542033
Add extension method
joebingham-wk Jul 30, 2020
841d102
Add tests
joebingham-wk Aug 3, 2020
117cadb
Format tests
joebingham-wk Aug 3, 2020
68f4700
Merge in base
joebingham-wk Aug 3, 2020
96ba4ff
Clean up
joebingham-wk Aug 3, 2020
de94787
Rename FunctionComponentConfig to UiFactoryConfig
joebingham-wk Aug 3, 2020
ea10a41
Check for generated config
joebingham-wk Aug 3, 2020
d435a1f
Fix parsing
joebingham-wk Aug 4, 2020
d865b24
Fix up example
joebingham-wk Aug 5, 2020
378a58d
Fix CI
joebingham-wk Aug 5, 2020
7d288eb
Fix breakages from analyzer 0.39.16
joebingham-wk Aug 5, 2020
861fda7
Format
joebingham-wk Aug 5, 2020
fa6eb84
Address feedback
joebingham-wk Aug 6, 2020
1de88bb
Revert unintentional change
joebingham-wk Aug 6, 2020
d66db3f
Fix empty name issue
joebingham-wk Aug 6, 2020
0e3f5ef
Revert change to getFunctionName
joebingham-wk Aug 6, 2020
236f344
Fix doc comment
joebingham-wk Aug 6, 2020
ac8a42c
Improve example logging readability
joebingham-wk Aug 6, 2020
9e3f6d3
Improve deprecation doc comment
joebingham-wk Aug 6, 2020
e5001d2
Address parser feedback
joebingham-wk Aug 6, 2020
8189f1c
Fix up example
joebingham-wk Aug 7, 2020
49df84c
Add integration tests
joebingham-wk Aug 7, 2020
acf2582
Format
joebingham-wk Aug 7, 2020
af9e2e4
Update doc comment
joebingham-wk Aug 7, 2020
31b3414
Address more feedback :tada:
joebingham-wk Aug 7, 2020
b0f9877
Add displayName to doc comment
joebingham-wk Aug 7, 2020
d12bca5
Fix example title
joebingham-wk Aug 7, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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