-
-
Notifications
You must be signed in to change notification settings - Fork 140
Update Kotlin DSL rewriting functionality to use KotlinEditor #1299
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
Update Kotlin DSL rewriting functionality to use KotlinEditor #1299
Conversation
fixDependencies task to use grammar from KotlinEditor for Kotlin Gradle DSL
autonomousapps
left a comment
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 is looking really good! Thanks! <3
src/main/kotlin/com/autonomousapps/internal/parse/KotlinBuildScriptDependenciesRewriter.kt
Show resolved
Hide resolved
src/main/kotlin/com/autonomousapps/internal/parse/KotlinBuildScriptDependenciesRewriter.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/com/autonomousapps/internal/parse/KotlinBuildScriptDependenciesRewriter.kt
Outdated
Show resolved
Hide resolved
src/main/kotlin/com/autonomousapps/internal/parse/KotlinBuildScriptDependenciesRewriter.kt
Outdated
Show resolved
Hide resolved
529e11a to
e71d021
Compare
src/test/kotlin/com/autonomousapps/internal/parse/KotlinBuildScriptDependenciesRewriterTest.kt
Show resolved
Hide resolved
9327c2b to
8778ec0
Compare
8778ec0 to
510c512
Compare
510c512 to
b17b6f3
Compare
src/test/kotlin/com/autonomousapps/internal/parse/KotlinBuildScriptDependenciesRewriterTest.kt
Show resolved
Hide resolved
autonomousapps
left a comment
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.
Looks great! Thank you <3 Left a few comments.
| } | ||
|
|
||
| override fun exitNamedBlock(ctx: NamedBlockContext) { | ||
| dependencyExtractor.onExitBlock() |
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.
I think the (implied) contract of this function is that it should be at the bottom of the exitNamedBlock function.
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.
| advice.filterToOrderedSet { it.isAnyAdd() }.ifNotEmpty { addAdvice -> | ||
| rewriter.insertBefore( | ||
| ctx.stop, | ||
| addAdvice.joinToString(prefix = "\ndependencies {\n", postfix = "\n}\n", separator = "\n") { a -> | ||
| printer.toDeclaration(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.
This block looks basically identical to the block above, with the exception that this one uses filterToOrderedSet and the above one is just filterToSet. I think We should extract this to a function and use the ordered set function.
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.
| } else if (a.isAnyChange()) { | ||
| val configuration = context.primaryExpression() | ||
| rewriter.replace(configuration.start, configuration.stop, a.toConfiguration) | ||
| } |
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.
I think this is being too clever. The DependencyDeclaration data class has all the information we need, and we shouldn't try to re-parse the context object to get the configuration context out of it. We should just rewrite the whole line using printer.toDeclaration(a). That ensures there's just one method responsible for printing declarations.
I think the above ☝️ is true, but I will note one caveat that came to mind as I wrote it. There are cases where there are really complex dependency declarations, and what I said assumes that DAGP is correctly modeling a declaration in its totality. Your approach is more conservative by just rewriting the configuration name.
All that said, I prefer keeping the code simple and using printer.toDeclaration(a) to rewrite the whole line. fixDependencies is an optional task and is allowed to make assumptions that buildHealth can't.
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 should just rewrite the whole line using printer.toDeclaration(a). That ensures there's just one method responsible for printing declarations.
Good point. I will update this
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.
👍 I'm happy to update this to printer.toDeclaration(a) for simplicity. I was just following the existing pattern e.g.
Lines 149 to 150 in d36ba8a
| val c = ctxDependency.configuration | |
| rewriter.replace(c.start, c.stop, a.toConfiguration) |
Note on the test set up
After making the change, the test "update dependencies with dependencyMap" test failed e.g. compileOnly(project(:marvin)) (without "") instead of compileOnly(project(":marvin"))
It's because the AdvicePrinter doesn't print the quote if dependencyMap is presented for the specific advice.
Lines 58 to 66 in 7c7c915
| return if (!mapped.isNullOrBlank()) { | |
| // If the user is mapping, it's bring-your-own-quotes | |
| mapped | |
| } else { | |
| // If there's no map, include quotes | |
| when (dslKind) { | |
| DslKind.KOTLIN -> "\"$gav\"" | |
| DslKind.GROOVY -> "'$gav'" | |
| } |
To get the test passing, I need to avoid providing dependencyMap for the dependency we want to remain the same. See change
Question
Can we assume that the given dependencyMap from users should always include quotes?
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 we assume that the given dependencyMap from users should always include quotes?
Yes. Good catch and fix!
c358cd6 to
cf85b18
Compare
autonomousapps
left a comment
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.
LGTM!
| if (it.statement.leafRule() !is PostfixUnaryExpressionContext) return@forEach | ||
|
|
||
| val context = it.statement.leafRule() as PostfixUnaryExpressionContext |
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 could be simplified a bit into a one-liner:
val context = it.statement.leafRule() as? PostfixUnaryExpressionContext ?: return@forEach| } else if (a.isAnyChange()) { | ||
| val configuration = context.primaryExpression() | ||
| rewriter.replace(configuration.start, configuration.stop, a.toConfiguration) | ||
| } |
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 we assume that the given dependencyMap from users should always include quotes?
Yes. Good catch and fix!
|
The |
2cc86a8 to
f1f9c94
Compare
📝 Description
Updating the
RewritingTaskto use kotlin-editor, which contains an updated grammar for more complex Kotlin Gradle build scripts. The grammar used for parsing Groovy build scripts remains unchanged.Note: this depends on cashapp/kotlin-editor#17