Skip to content
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

Merged
merged 35 commits into from
Apr 26, 2018

Conversation

JorgeCastilloPrz
Copy link
Member

@JorgeCastilloPrz JorgeCastilloPrz commented Apr 22, 2018

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.

  • Added processor tests using compile-testing.
  • Added relations between typeclasses and instances. Now it generates UML with a form similar to the following (but much more extense, ofc):
#font: Menlo
#fontSize: 15
#arrowSize: 1
#bendSize: 0.3
#lineWidth: 2
#padding: 8
#zoom: 1
#fill: #64B5F6
#.typeclass: fill=#64B5F6 visual=database bold
#.instances: fill=#B9F6CA visual=class italic bold dashed
[<typeclass>Semigroup]<-[<instances>Semigroup Instances|OptionMonoidInstance|OptionSemigroupInstance]
[<typeclass>Semigroup]<-[<typeclass>Monoid]
[<typeclass>Monoid]<-[<instances>Monoid Instances|OptionMonoidInstance]

Which renders to:
captura de pantalla 2018-04-24 a las 10 50 58

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

@codecov
Copy link

codecov bot commented Apr 22, 2018

Codecov Report

Merging #812 into master will increase coverage by 0.78%.
The diff coverage is 67.79%.

Impacted file tree graph

@@             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
Impacted Files Coverage Δ Complexity Δ
...ava/arrow/ap/objects/renzu/OptionMonoidInstance.kt 0% <0%> (ø) 0 <0> (?)
...src/main/java/arrow/instances/AnnotatedInstance.kt 80% <0%> (+80%) 4 <0> (+4) ⬆️
.../arrow/ap/objects/renzu/OptionSemigroupInstance.kt 0% <0%> (ø) 0 <0> (?)
...src/main/java/arrow/common/utils/ProcessorUtils.kt 42.04% <20%> (+23.97%) 0 <0> (ø) ⬇️
...rocessor/src/main/java/arrow/renzu/ModuleStyles.kt 60% <60%> (ø) 0 <0> (?)
...cessor/src/main/java/arrow/renzu/RenzuGenerator.kt 74.02% <74.02%> (ø) 17 <17> (?)
...cessor/src/main/java/arrow/renzu/RenzuProcessor.kt 79.16% <79.16%> (ø) 12 <12> (?)
... and 5 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3237249...f51048b. Read the comment docs.

@JorgeCastilloPrz
Copy link
Member Author

JorgeCastilloPrz commented Apr 24, 2018

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:

#font: Menlo
#fontSize: 15
#arrowSize: 1
#bendSize: 0.3
#lineWidth: 2
#padding: 8
#zoom: 1
#fill: #64B5F6
#.typeclass: fill=#64B5F6 visual=database bold
#.instances: fill=#B9F6CA visual=class italic bold dashed
[<typeclass>Semigroup]<-[<instances>Semigroup Instances|OptionMonoidInstance|OptionSemigroupInstance]
[<typeclass>Semigroup]<-[<typeclass>Monoid]
[<typeclass>Monoid]<-[<instances>Monoid Instances|OptionMonoidInstance]

Which renders to:
captura de pantalla 2018-04-24 a las 10 50 58

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

@JorgeCastilloPrz
Copy link
Member Author

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>> {
Copy link
Member

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?

Copy link
Member Author

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")) {
Copy link
Member

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?

Copy link
Member Author

@JorgeCastilloPrz JorgeCastilloPrz Apr 26, 2018

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 ->
Copy link
Member

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") +
Copy link
Member

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>()
Copy link
Member

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

@raulraja
Copy link
Member

AwesomeSauce!

@JorgeCastilloPrz
Copy link
Member Author

All the stuff has been fixed @raulraja , I'll merge whenever CI has the will to let me.

@JorgeCastilloPrz JorgeCastilloPrz merged commit 40baca8 into master Apr 26, 2018
@JorgeCastilloPrz JorgeCastilloPrz deleted the renzu branch April 26, 2018 18:33
RawToast pushed a commit to RawToast/kategory that referenced this pull request Jul 18, 2018
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants