Skip to content

Commit

Permalink
feat: improve support for parsing Kotlin DSL, using KotlinEditor.
Browse files Browse the repository at this point in the history
  • Loading branch information
autonomousapps committed Aug 6, 2024
1 parent 563b5e2 commit 50e329e
Show file tree
Hide file tree
Showing 23 changed files with 1,645 additions and 540 deletions.
21 changes: 17 additions & 4 deletions app/src/main/kotlin/com/squareup/sort/SortCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.squareup.parse.BuildScriptParseException
import com.squareup.sort.Status.NOT_SORTED
import com.squareup.sort.Status.PARSE_ERROR
import com.squareup.sort.Status.SUCCESS
import com.squareup.sort.groovy.GroovySorter
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.nio.file.FileSystem
Expand All @@ -39,7 +40,15 @@ class SortCommand(
) {

init {
context { helpFormatter = { context -> MordantHelpFormatter(context = context, showDefaultValues = true, showRequiredTag = true) } }
context {
helpFormatter = { context ->
MordantHelpFormatter(
context = context,
showDefaultValues = true,
showRequiredTag = true,
)
}
}
}

private val verbose by option("-v", "--verbose", help = "Verbose mode. All logs are printed.")
Expand All @@ -50,7 +59,11 @@ class SortCommand(
help = "Flag to control whether file tree walking looks in build and hidden directories. True by default.",
).flag("--no-skip-hidden-and-build-dirs", default = true)

val mode by option("-m", "--mode", help = "Mode: [sort, check]. Defaults to 'sort'. Check will report if a file is already sorted")
val mode by option(
"-m",
"--mode",
help = "Mode: [sort, check]. Defaults to 'sort'. Check will report if a file is already sorted"
)
.enum<Mode>().default(Mode.SORT)

val paths: List<Path> by argument(help = "Path(s) to sort. Required.")
Expand Down Expand Up @@ -102,7 +115,7 @@ class SortCommand(
var alreadySortedCount = 0
filesToSort.parallelStream().forEach { file ->
try {
val newContent = Sorter.sorterFor(file).rewritten()
val newContent = Sorter.of(file).rewritten()
file.writeText(newContent, Charsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING)
logger.trace("Successfully sorted: ${file.pathString} ")
successCount++
Expand Down Expand Up @@ -144,7 +157,7 @@ class SortCommand(

filesToSort.parallelStream().forEach { file ->
try {
val sorter = Sorter.sorterFor(file)
val sorter = Sorter.of(file)
if (!sorter.isSorted() && !sorter.hasParseErrors()) {
logger.trace("Not ordered: ${file.pathString} ")
notSorted.add(file)
Expand Down
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dagp = "1.30.0"
java = "11"
junit5 = "5.7.2"
kotlin = "1.9.24"
kotlinEditor = "0.4"
mavenPublish = "0.28.0"
moshi = "1.14.0"
retrofit = "2.9.0"
Expand All @@ -14,6 +15,8 @@ antlr-core = { module = "org.antlr:antlr4", version.ref = "antlr" }
antlr-runtime = { module = "org.antlr:antlr4-runtime", version.ref = "antlr" }
clikt = "com.github.ajalt.clikt:clikt:4.2.2"
grammar = "com.autonomousapps:gradle-script-grammar:0.3"
kotlinEditor-core = { module = "app.cash.kotlin-editor:core", version.ref = "kotlinEditor" }
kotlinEditor-grammar = { module = "app.cash.kotlin-editor:grammar", version.ref = "kotlinEditor" }
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin"}
okhttp3 = "com.squareup.okhttp3:okhttp:4.9.0"
moshi-core = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
Expand Down
22 changes: 0 additions & 22 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pluginManagement {

plugins {
id 'com.gradle.develocity' version '3.17.1'
id 'me.champeau.includegit' version '0.1.6'
}

dependencyResolutionManagement {
Expand All @@ -13,27 +12,6 @@ dependencyResolutionManagement {
}
}

// Configure 'me.champeau.includegit' plugin to enable concurrent development on the gradle-script-grammar project.
// See also https://github.com/melix/includegit-gradle-plugin and
// https://melix.github.io/includegit-gradle-plugin/latest/index.html.
if (grammarAsSource()) {
gitRepositories {
include('gradleScriptGrammar') {
uri = 'git@github.com:autonomousapps/gradle-script-grammar.git'
// optional, set what branch to use
branch = 'main'
}
}
}

// Run build with `-PincludeGrammar=true`,
// or add `-PincludeGrammar=true` to gradle.properties or ~/.gradle/gradle.properties
boolean grammarAsSource() {
return providers.gradleProperty('includeGrammar')
.map { it.toBoolean() }
.getOrElse(false)
}

rootProject.name = 'gradle-dependencies-sorter'

develocity {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ final class FunctionalSpec extends Specification {
Files.writeString(buildScript, BUILD_SCRIPT)

when: 'We sort dependencies'
build(dir, 'sortDependencies')
build(dir, 'sortDependencies', '--verbose')

then: 'Dependencies are sorted'
buildScript.text == """\
Expand Down
1 change: 1 addition & 0 deletions sort/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ kotlin {

dependencies {
api libs.grammar
api libs.kotlinEditor.core

testImplementation libs.spock
}
89 changes: 89 additions & 0 deletions sort/src/main/kotlin/com/squareup/sort/Configuration.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.squareup.sort

internal class Configuration(
private val configuration: String,
val level: Int,
/**
* Android support. A "variant" configuration looks like "debugApi", "releaseImplementation", etc.
* The variant will be "debug", "release", etc.
*/
var variant: String? = null
) {

companion object {
val values = listOf(
"api" to { Configuration("api", 0) },
"implementation" to { Configuration("implementation", 1) },
"compileOnlyApi" to { Configuration("compileOnlyApi", 2) },
"compileOnly" to { Configuration("compileOnly", 3) },
"runtimeOnly" to { Configuration("runtimeOnly", 4) },
"annotationProcessor" to { Configuration("annotationProcessor", 5) },
"kapt" to { Configuration("kapt", 6) },
"testImplementation" to { Configuration("testImplementation", 7) },
"testCompileOnly" to { Configuration("testCompileOnly", 8) },
"testRuntimeOnly" to { Configuration("testRuntimeOnly", 9) },
"androidTestImplementation" to { Configuration("androidTestImplementation", 10) },
)

fun of(configuration: String): Configuration? {
fun findConfiguration(
predicate: (Pair<String, () -> Configuration>) -> Boolean
): Configuration? {
return values.find(predicate)?.second?.invoke()
}

// Try to find an exact match
var matchingConfiguration = findConfiguration { it.first == configuration }

// If that failed, look for a variant
if (matchingConfiguration == null) {
matchingConfiguration = findConfiguration { configuration.endsWith(it.first, true) }
if (matchingConfiguration != null) {
matchingConfiguration.variant = configuration.substring(
0,
configuration.length - matchingConfiguration.configuration.length
)
}
}

// Look for a variant again
if (matchingConfiguration == null) {
matchingConfiguration = findConfiguration { configuration.startsWith(it.first, true) }
if (matchingConfiguration != null) {
matchingConfiguration.variant = configuration.substring(
configuration.length - matchingConfiguration.configuration.length,
configuration.length
)
}
}

return matchingConfiguration
}

@JvmStatic
fun stringCompare(
left: String,
right: String
): Int {
val leftC = of(left)
val rightC = of(right)

// Null means they don't map to a known configuration. So, compare by String natural order.
if (leftC == null && rightC == null) return left.compareTo(right)
// Unknown configuration is "higher than" known
if (rightC == null) return 1
if (leftC == null) return -1

val c = leftC.level.compareTo(rightC.level)

// If each maps to a known configuration, and they're different, we can return that value
if (c != 0) return c
// If each maps to the same configuration, we now differentiate based on whether variants are
// involved. Non-variants are "higher than" variants.
if (leftC.variant != null && rightC.variant != null) {
return rightC.variant!!.compareTo(leftC.variant!!)
}
return if (rightC.variant != null) return -1 else 1
}
}
}
99 changes: 0 additions & 99 deletions sort/src/main/kotlin/com/squareup/sort/ConfigurationComparator.kt

This file was deleted.

Loading

0 comments on commit 50e329e

Please sign in to comment.