-
Notifications
You must be signed in to change notification settings - Fork 450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Renzu processor] UML generation for Typeclass + Instances info graph #812
Conversation
Codecov Report
@@ Coverage Diff @@
## master #812 +/- ##
============================================
+ Coverage 43.5% 44.29% +0.78%
- Complexity 584 617 +33
============================================
Files 284 289 +5
Lines 7259 7376 +117
Branches 804 828 +24
============================================
+ Hits 3158 3267 +109
+ Misses 3819 3810 -9
- Partials 282 299 +17
Continue to review full report at Codecov.
|
Ok, this is starting to look better. Processor tests are now passing, and I've added relations between typeclasses. Now it generates UML with the form:
I've decided to group instances for the same typeclass in a single box for the time being given the way nomnoml aligns childs horizontally on 1 -> N relations (it would grow sooo much horizontally). I keep iterating on it. Now I'll try to colorize them differently depending on the package they belong to, like here |
Can you take a look @raulraja ? I'd need a green here in order to let you test it. It requires the frontend side to be deployed also, which is included here. No worries, this does not break any compilation / CI or anything, so should be safe to merge. Take a rapid look if you rather, though. When this gets merged I have a plan to make not merged PRs provide a link on the CI console so you can visualize their current graph state. |
import arrow.typeclasses.Monoid | ||
|
||
@instance(Option::class) | ||
interface OptionMonoidInstance<A> : OptionSemigroupInstance<A>, Monoid<Option<A>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these for testing purposes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, these are just clones of real instances inside the processor models module for testing
val className = i.removeBackticks().substringBefore("<") | ||
val typeClassElement = processor.elementUtils.getTypeElement(className) | ||
val parentInterface = processor.getClassOrPackageDataWrapper(typeClassElement) as ClassOrPackageDataWrapper.Class | ||
if (i.removeBackticks().contains("typeclass")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this fail if the type class extends an interface in the same package that is not a type class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The supertypes are extracted from the typetable and here we're just adding them to the typeclass collection if they are actually typeclasses, so this shouldn't fail IMO
|
||
private fun normalizeTypeclassTree(instances: List<Instance>) | ||
: MutableMap<TypeClass, Tuple2<Instances, Set<ParentTypeClass>>> = | ||
instances.fold(mutableMapOf()) { acc, instance -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be implemented in terms of an immutable map instead?
val file = File(generatedDir, "arrow-infographic.txt") | ||
if (!file.exists()) { | ||
val globalStyles = | ||
listOf("#font: Menlo") + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be probably expressed as a string template:
val globalStyles =
"""
|#font: Menlo
|...
""".trimMarging()
*/ | ||
private fun genDiagramRelations(typeclassTree: MutableMap<TypeClass, Tuple2<Instances, Set<ParentTypeClass>>>) | ||
: List<String> { | ||
val relations = mutableListOf<String>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can encode this entire method without mutability just flatMapping over typeclassTree
AwesomeSauce! |
All the stuff has been fixed @raulraja , I'll merge whenever CI has the will to let me. |
…arrow-kt#812) * Added Renzu annotation processor to generate UML renderable by the docs site. * Added tests to ensure integrity. * Added isolated infograph UML version for tests. * Added new section for the website (/graph) to browse the typeclasses and instances graph.
Renzu is just the codename for now, it stands for "lens" in Japanese. Not directly related to FP prisms / lenses but also to the concept of looking to something through a lens to discover a new perspective over it. That's kind of what this diagrams are. Name is open for discussion.
This processor generates UML text recognized by nomnoml frontend lib to render UML diagrams.
compile-testing
.Which renders to:
I've decided to group instances for the same typeclass in a single box for the time being given the way nomnoml aligns childs horizontally on 1 -> N relations (it would grow sooo much horizontally).
To generate test stubs if you get problems on those:
./gradlew clean :arrow-annotations-processor-test-models:assemble :arrow-annotations-processor:test