Skip to content

Commit 5f9b01d

Browse files
committed
Detect and prohibit new Guava classes
1 parent bac784b commit 5f9b01d

2 files changed

Lines changed: 80 additions & 0 deletions

File tree

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ dependencies {
125125
testAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
126126
jmh 'org.openjdk.jmh:jmh-core:1.37'
127127
jmh 'org.openjdk.jmh:jmh-generator-annprocess:1.37'
128+
129+
testImplementation "com.tngtech.archunit:archunit-junit5:1.2.0"
128130
}
129131

130132
shadowJar {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package graphql
2+
3+
import com.tngtech.archunit.core.domain.JavaClasses
4+
import com.tngtech.archunit.core.importer.ClassFileImporter
5+
import com.tngtech.archunit.core.importer.ImportOption
6+
import spock.lang.Specification
7+
8+
/*
9+
* We selectively shade in a few classes of Guava, however we want to minimise dependencies so we want to keep this list small.
10+
* This check ensures no new Guava classes are added
11+
*/
12+
class GuavaLimitCheck extends Specification {
13+
14+
static final String GUAVA_PACKAGE_PREFIX = "com.google.common"
15+
16+
static final Set<String> ALLOWED_GUAVA_CLASSES = [
17+
"com.google.common.collect.ImmutableMap",
18+
"com.google.common.collect.ImmutableSet",
19+
"com.google.common.collect.ImmutableList",
20+
"com.google.common.base.Strings",
21+
"com.google.common.collect.BiMap",
22+
"com.google.common.collect.HashBiMap",
23+
"com.google.common.collect.ImmutableCollection",
24+
"com.google.common.collect.LinkedHashMultimap",
25+
"com.google.common.collect.Multimap",
26+
"com.google.common.collect.Table",
27+
"com.google.common.collect.Sets",
28+
"com.google.common.collect.Multimaps",
29+
"com.google.common.collect.Iterables",
30+
"com.google.common.collect.HashBasedTable",
31+
"com.google.common.collect.HashMultimap",
32+
"com.google.common.collect.Interner",
33+
"com.google.common.collect.Interners"
34+
]
35+
36+
def "should identify which classes use prohibited Guava dependencies"() {
37+
given:
38+
JavaClasses importedClasses = new ClassFileImporter()
39+
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
40+
.importPackages("graphql")
41+
42+
when:
43+
Map<String, Set<String>> violationsByClass = [:]
44+
45+
importedClasses.each { javaClass ->
46+
def className = javaClass.name
47+
def guavaUsages = javaClass.getAccessesFromSelf()
48+
.collect { it.targetOwner }
49+
.findAll { it.packageName.startsWith(GUAVA_PACKAGE_PREFIX) && !ALLOWED_GUAVA_CLASSES.contains(it) }
50+
.toSet()
51+
52+
if (!guavaUsages.isEmpty()) {
53+
violationsByClass[className] = guavaUsages
54+
}
55+
}
56+
57+
then:
58+
violationsByClass.isEmpty()
59+
60+
cleanup: "if the test fails, provide detailed information about which classes have violations"
61+
if (!violationsByClass.isEmpty()) {
62+
def errorMessage = new StringBuilder("Prohibited Guava class usage found:\n")
63+
64+
violationsByClass.each { className, guavaClasses ->
65+
errorMessage.append("\nClass: ${className} uses these prohibited Guava classes:\n")
66+
guavaClasses.each { guavaClass ->
67+
errorMessage.append(" - ${guavaClass}\n")
68+
}
69+
}
70+
71+
errorMessage.append("\nEither:\n")
72+
errorMessage.append("1. Preferred option: Replace them with alternatives that don't depend on Guava\n")
73+
errorMessage.append("2. If absolutely necessary: Add these Guava classes to the shade configuration in the build.gradle file\n")
74+
75+
println errorMessage.toString()
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)