@@ -3,14 +3,14 @@ package datadog.gradle.plugin.config
33import com.github.javaparser.ParserConfiguration
44import com.github.javaparser.StaticJavaParser
55import com.github.javaparser.ast.CompilationUnit
6- import com.github.javaparser.ast.expr.StringLiteralExpr
7- import com.github.javaparser.ast.nodeTypes.NodeWithModifiers
86import com.github.javaparser.ast.Modifier
97import com.github.javaparser.ast.body.FieldDeclaration
108import com.github.javaparser.ast.body.VariableDeclarator
9+ import com.github.javaparser.ast.expr.StringLiteralExpr
10+ import com.github.javaparser.ast.nodeTypes.NodeWithModifiers
11+ import org.gradle.api.GradleException
1112import org.gradle.api.Plugin
1213import org.gradle.api.Project
13- import org.gradle.api.GradleException
1414import org.gradle.api.tasks.SourceSet
1515import org.gradle.api.tasks.SourceSetContainer
1616import org.gradle.kotlin.dsl.getByType
@@ -39,29 +39,37 @@ private var cachedConfigFields: LoadedConfigFields? = null
3939private fun loadConfigFields (
4040 mainSourceSetOutput : org.gradle.api.file.FileCollection ,
4141 generatedClassName : String
42- ): LoadedConfigFields {
43- return cachedConfigFields ? : run {
44- val urls = mainSourceSetOutput.files.map { it.toURI().toURL() }.toTypedArray( )
45- URLClassLoader (urls, LoadedConfigFields :: class .java.classLoader) .use { cl ->
42+ ): LoadedConfigFields = cachedConfigFields ? : run {
43+ val urls = mainSourceSetOutput.files.map { it.toURI().toURL() }.toTypedArray()
44+ URLClassLoader ( urls, LoadedConfigFields :: class .java.classLoader )
45+ .use { cl ->
4646 val clazz = Class .forName(generatedClassName, true , cl)
4747
4848 val supportedField = clazz.getField(" SUPPORTED" ).get(null )
49+
4950 @Suppress(" UNCHECKED_CAST" )
50- val supportedSet = when (supportedField) {
51- is Set <* > -> supportedField as Set <String >
52- is Map <* , * > -> supportedField.keys as Set <String >
53- else -> throw IllegalStateException (" SUPPORTED field must be either Set<String> or Map<String, Any>, but was ${supportedField?.javaClass} " )
54- }
51+ val supportedSet =
52+ when (supportedField) {
53+ is Set <* > -> supportedField as Set <String >
54+
55+ is Map <* , * > -> supportedField.keys as Set <String >
56+
57+ else -> throw IllegalStateException (
58+ " SUPPORTED field must be either Set<String> or Map<String, Any>, but was ${supportedField?.javaClass} " ,
59+ )
60+ }
5561
5662 @Suppress(" UNCHECKED_CAST" )
5763 val aliasMappingMap = clazz.getField(" ALIAS_MAPPING" ).get(null ) as Map <String , String >
5864 LoadedConfigFields (supportedSet, aliasMappingMap)
5965 }.also { cachedConfigFields = it }
60- }
6166}
6267
6368/* * Registers `logEnvVarUsages` (scan for DD_/OTEL_ tokens and fail if unsupported). */
64- private fun registerLogEnvVarUsages (target : Project , extension : SupportedTracerConfigurations ) {
69+ private fun registerLogEnvVarUsages (
70+ target : Project ,
71+ extension : SupportedTracerConfigurations
72+ ) {
6573 val ownerPath = extension.configOwnerPath
6674 val generatedFile = extension.className
6775
@@ -70,19 +78,23 @@ private fun registerLogEnvVarUsages(target: Project, extension: SupportedTracerC
7078 group = " verification"
7179 description = " Scan Java files for DD_/OTEL_ tokens and fail if unsupported (using generated constants)"
7280
73- val mainSourceSetOutput = ownerPath.map {
74- target.project(it)
75- .extensions.getByType<SourceSetContainer >()
76- .named(SourceSet .MAIN_SOURCE_SET_NAME )
77- .map { main -> main.output }
78- }
81+ val mainSourceSetOutput =
82+ ownerPath.map {
83+ target
84+ .project(it)
85+ .extensions
86+ .getByType<SourceSetContainer >()
87+ .named(SourceSet .MAIN_SOURCE_SET_NAME )
88+ .map { main -> main.output }
89+ }
7990 inputs.files(mainSourceSetOutput)
8091
8192 // inputs for incrementality (your own source files, not the owner’s)
82- val javaFiles = target.fileTree(target.projectDir) {
83- include(" **/src/main/java/**/*.java" )
84- exclude(" **/build/**" , " **/dd-smoke-tests/**" )
85- }
93+ val javaFiles =
94+ target.fileTree(target.projectDir) {
95+ include(" **/src/main/java/**/*.java" )
96+ exclude(" **/build/**" , " **/dd-smoke-tests/**" )
97+ }
8698 inputs.files(javaFiles)
8799 outputs.upToDateWhen { true }
88100 doLast {
@@ -94,25 +106,26 @@ private fun registerLogEnvVarUsages(target: Project, extension: SupportedTracerC
94106 val repoRoot = target.projectDir.toPath()
95107 val tokenRegex = Regex (" \" (?:DD_|OTEL_)[A-Za-z0-9_]+\" " )
96108
97- val violations = buildList {
98- javaFiles.files.forEach { f ->
99- val rel = repoRoot.relativize(f.toPath()).toString()
100- var inBlock = false
101- f.readLines().forEachIndexed { i, raw ->
102- val trimmed = raw.trim()
103- if (trimmed.startsWith(" //" )) return @forEachIndexed
104- if (! inBlock && trimmed.contains(" /*" )) inBlock = true
105- if (inBlock) {
106- if (trimmed.contains(" */" )) inBlock = false
107- return @forEachIndexed
108- }
109- tokenRegex.findAll(raw).forEach { m ->
110- val token = m.value.trim(' "' )
111- if (token !in supported) add(" $rel :${i + 1 } -> Unsupported token '$token '" )
109+ val violations =
110+ buildList {
111+ javaFiles.files.forEach { f ->
112+ val rel = repoRoot.relativize(f.toPath()).toString()
113+ var inBlock = false
114+ f.readLines().forEachIndexed { i, raw ->
115+ val trimmed = raw.trim()
116+ if (trimmed.startsWith(" //" )) return @forEachIndexed
117+ if (! inBlock && trimmed.contains(" /*" )) inBlock = true
118+ if (inBlock) {
119+ if (trimmed.contains(" */" )) inBlock = false
120+ return @forEachIndexed
121+ }
122+ tokenRegex.findAll(raw).forEach { m ->
123+ val token = m.value.trim(' "' )
124+ if (token !in supported) add(" $rel :${i + 1 } -> Unsupported token '$token '" )
125+ }
112126 }
113127 }
114128 }
115- }
116129
117130 if (violations.isNotEmpty()) {
118131 violations.forEach { target.logger.error(it) }
@@ -132,25 +145,27 @@ private fun registerCheckEnvironmentVariablesUsage(project: Project) {
132145
133146 doLast {
134147 val repoRoot: Path = project.projectDir.toPath()
135- val javaFiles = project.fileTree(project.projectDir) {
136- include(" **/src/main/java/**/*.java" )
137- exclude(" **/build/**" )
138- exclude(" utils/config-utils/src/main/java/datadog/trace/config/inversion/ConfigHelper.java" )
139- exclude(" dd-java-agent/agent-bootstrap/**" )
140- exclude(" dd-java-agent/src/main/java/datadog/trace/bootstrap/**" )
141- }
148+ val javaFiles =
149+ project.fileTree(project.projectDir) {
150+ include(" **/src/main/java/**/*.java" )
151+ exclude(" **/build/**" )
152+ exclude(" utils/config-utils/src/main/java/datadog/trace/config/inversion/ConfigHelper.java" )
153+ exclude(" dd-java-agent/agent-bootstrap/**" )
154+ exclude(" dd-java-agent/src/main/java/datadog/trace/bootstrap/**" )
155+ }
142156
143157 val pattern = Regex (""" EnvironmentVariables\.get\s*\(""" )
144- val matches = buildList {
145- javaFiles.forEach { f ->
146- val relative = repoRoot.relativize(f.toPath())
147- f.readLines().forEachIndexed { idx, line ->
148- if (pattern.containsMatchIn(line)) {
149- add(" $relative :${idx + 1 } -> ${line.trim()} " )
158+ val matches =
159+ buildList {
160+ javaFiles.forEach { f ->
161+ val relative = repoRoot.relativize(f.toPath())
162+ f.readLines().forEachIndexed { idx, line ->
163+ if (pattern.containsMatchIn(line)) {
164+ add(" $relative :${idx + 1 } -> ${line.trim()} " )
165+ }
150166 }
151167 }
152168 }
153- }
154169
155170 if (matches.isNotEmpty()) {
156171 project.logger.lifecycle(" \n Found forbidden usages of EnvironmentVariables.get(...):" )
@@ -164,28 +179,33 @@ private fun registerCheckEnvironmentVariablesUsage(project: Project) {
164179}
165180
166181// Helper functions for checking Config Strings
167- private fun normalize (configValue : String ) =
168- " DD_" + configValue.uppercase().replace(" -" , " _" ).replace(" ." , " _" )
182+ private fun normalize (configValue : String ) = " DD_" + configValue.uppercase().replace(" -" , " _" ).replace(" ." , " _" )
169183
170184// Checking "public" "static" "final"
171- private fun NodeWithModifiers <* >.hasModifiers (vararg mods : Modifier .Keyword ) =
172- mods.all { hasModifier(it) }
185+ private fun NodeWithModifiers <* >.hasModifiers (vararg mods : Modifier .Keyword ) = mods.all { hasModifier(it) }
173186
174187/* * Registers `checkConfigStrings` to validate config definitions against documented supported configurations. */
175- private fun registerCheckConfigStringsTask (project : Project , extension : SupportedTracerConfigurations ) {
188+ private fun registerCheckConfigStringsTask (
189+ project : Project ,
190+ extension : SupportedTracerConfigurations
191+ ) {
176192 val ownerPath = extension.configOwnerPath
177193 val generatedFile = extension.className
178194
179195 project.tasks.register(" checkConfigStrings" ) {
180196 group = " verification"
181- description = " Validates that all config definitions in `dd-trace-api/src/main/java/datadog/trace/api/config` exist in `metadata/supported-configurations.json`"
182-
183- val mainSourceSetOutput = ownerPath.map {
184- project.project(it)
185- .extensions.getByType<SourceSetContainer >()
186- .named(SourceSet .MAIN_SOURCE_SET_NAME )
187- .map { main -> main.output }
188- }
197+ description =
198+ " Validates that all config definitions in `dd-trace-api/src/main/java/datadog/trace/api/config` exist in `metadata/supported-configurations.json`"
199+
200+ val mainSourceSetOutput =
201+ ownerPath.map {
202+ project
203+ .project(it)
204+ .extensions
205+ .getByType<SourceSetContainer >()
206+ .named(SourceSet .MAIN_SOURCE_SET_NAME )
207+ .map { main -> main.output }
208+ }
189209 inputs.files(mainSourceSetOutput)
190210
191211 doLast {
@@ -205,41 +225,46 @@ private fun registerCheckConfigStringsTask(project: Project, extension: Supporte
205225
206226 StaticJavaParser .setConfiguration(parserConfig)
207227
208- val violations = buildList {
209- configDir.listFiles()?.forEach { file ->
210- val fileName = file.name
211- val cu: CompilationUnit = StaticJavaParser .parse(file)
212-
213- cu.findAll(VariableDeclarator ::class .java).forEach { varDecl ->
214- varDecl.parentNode
215- .map { it as ? FieldDeclaration }
216- .ifPresent { field ->
217- if (field.hasModifiers(Modifier .Keyword .PUBLIC , Modifier .Keyword .STATIC , Modifier .Keyword .FINAL ) &&
218- varDecl.typeAsString == " String" ) {
219-
220- val fieldName = varDecl.nameAsString
221- if (fieldName.endsWith(" _DEFAULT" )) return @ifPresent
222- val init = varDecl.initializer.orElse(null ) ? : return @ifPresent
223-
224- if (init !is StringLiteralExpr ) return @ifPresent
225- val rawValue = init .value
226-
227- val normalized = normalize(rawValue)
228- if (normalized !in supported && normalized !in aliasMapping) {
229- val line = varDecl.range.map { it.begin.line }.orElse(1 )
230- add(" $fileName :$line -> Config '$rawValue ' normalizes to '$normalized ' " +
231- " which is missing from '${extension.jsonFile.get()} '" )
228+ val violations =
229+ buildList {
230+ configDir.listFiles()?.forEach { file ->
231+ val fileName = file.name
232+ val cu: CompilationUnit = StaticJavaParser .parse(file)
233+
234+ cu.findAll(VariableDeclarator ::class .java).forEach { varDecl ->
235+ varDecl.parentNode
236+ .map { it as ? FieldDeclaration }
237+ .ifPresent { field ->
238+ if (field.hasModifiers(Modifier .Keyword .PUBLIC , Modifier .Keyword .STATIC , Modifier .Keyword .FINAL ) &&
239+ varDecl.typeAsString == " String"
240+ ) {
241+ val fieldName = varDecl.nameAsString
242+ if (fieldName.endsWith(" _DEFAULT" )) return @ifPresent
243+ val init = varDecl.initializer.orElse(null ) ? : return @ifPresent
244+
245+ if (init !is StringLiteralExpr ) return @ifPresent
246+ val rawValue = init .value
247+
248+ val normalized = normalize(rawValue)
249+ if (normalized !in supported && normalized !in aliasMapping) {
250+ val line = varDecl.range.map { it.begin.line }.orElse(1 )
251+ add(
252+ " $fileName :$line -> Config '$rawValue ' normalizes to '$normalized ' " +
253+ " which is missing from '${extension.jsonFile.get()} '" ,
254+ )
255+ }
232256 }
233257 }
234- }
258+ }
235259 }
236260 }
237- }
238261
239262 if (violations.isNotEmpty()) {
240263 logger.error(" \n Found config definitions not in '${extension.jsonFile.get()} ':" )
241264 violations.forEach { logger.lifecycle(it) }
242- throw GradleException (" Undocumented Environment Variables found. Please add the above Environment Variables to '${extension.jsonFile.get()} '." )
265+ throw GradleException (
266+ " Undocumented Environment Variables found. Please add the above Environment Variables to '${extension.jsonFile.get()} '." ,
267+ )
243268 } else {
244269 logger.info(" All config strings are present in '${extension.jsonFile.get()} '." )
245270 }
0 commit comments