Comments (2)
Yes, as you noticed .init
breaks needle's understand of the graph and that causes runtime issues. As you noted, it's really hard to know the type of the class being constructed because the AST has no form of type-inference. In a simple one line function, maybe the return type can tell us the type but in the case you give above, we have to walk back to the let secondComponent: SecondComponent
property and that would be quite hard and difficult to generalize for all cases.
When we initially came up with the API, we thought about using comments so that the you could just tell us who the children of a particular components were. We decided that comments were prone to typos and such, so we decide to go with the current pattern where a parent component must instantiate it's children somewhere in the body to let needle know about parent -> child relationships.
from needle.
Yeah, I wasn't sure how easy it would be to use the AST to figure it all out properly.
I did have an interesting thought for a way to resolve the issue with .init
and remove the required child component bolierplate code.
Instead of trying to detect child parent relationships by searching the parent for instantiations of its child components. It might be possible to instead use convenience initializers in in the child for each of it's possible parents.
ie:
final class BaseComponent: BootstrapComponent {}
final class A1Component: Component<EmptyDependency> {
var name: String { return "A1" }
private override init(parent: Scope) {
super.init(parent: parent)
}
convenience init(parentComponent: BaseComponent) {
self.init(parent: parentComponent)
}
}
final class A2Component: Component<EmptyDependency> {
var name: String { return "A2" }
private override init(parent: Scope) {
super.init(parent: parent)
}
convenience init(parentComponent: BaseComponent) {
self.init(parent: parentComponent)
}
}
protocol BDependency: Dependency {
var name: String { get }
}
final class BComponent: Component<BDependency> {
private override init(parent: Scope) {
super.init(parent: parent)
}
convenience init(parentComponent: A1Component) {
self.init(parent: parentComponent)
}
convenience init(parentComponent: A2Component) {
self.init(parent: parentComponent)
}
}
This replaces the boilerplate declaring child components in their parents with declaring parent components in their children. But in the majority of cases it is more likely a component has more children than parents, so the boilerplate should be reduced.
The generator can then create the dependency graph by identifiying the convenience initializers that match the expected pattern and using the parentComponent
type names to link the component with its parents.
The private override init(parent: Scope)
is there to prevent potential runtime errors that might happen if someone were to try using the component's designated initializer with a parent that the graph doesn't know about. the generator could enforce that the component override this init as private (as well as ensure that super.init isn't called anywhere else in the component) or produce an error at compile time. This would resolve the issue with .init
because the generator no longer needs to try to detect component instantiations because the only available initializers are ones that require the components exact parent types as defined in the dependency graph.
from needle.
Related Issues (20)
- Proper usage of shared to avoid memory cycles HOT 5
- Generated Code doesn't work with package specification
- Getting double results HOT 4
- How to resolve dependency cycle? HOT 2
- Failed to read source paths from list file at iOS HOT 1
- Very high compile times in release mode for our largest app
- How to pass values in Views in SwiftUI HOT 2
- Needle's parsing of Component's properties is going "too deep"
- Improve Optional Dependencies HOT 3
- Internal properties of Components should be ignored
- Needle Cocoapods spec is outdated
- Needle Usage for Integration testing
- SPM product 'NeedleFoundation' required by package 'xxx' target 'xxx' not found. HOT 1
- public properties HOT 3
- Apple M1: "Some dependencies are missing" HOT 2
- Sample MVVM project is not compiling HOT 1
- The property is not passed from the parent to the child HOT 1
- Showing Recent Issues 💩 Some dependencies are missing, please look at the warnings above for the list.
- needle generate malfunctioning HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from needle.