All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.nebula.lint.rule.dependency.DuplicateDependencyService.kt Maven / Gradle / Ivy

Go to download

Pluggable and configurable linter tool for identifying and reporting on patterns of misuse or deprecations in Gradle scripts

There is a newer version: 20.2.2
Show newest version
package com.netflix.nebula.lint.rule.dependency

import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.util.*

class DuplicateDependencyService(val project: Project) {
    companion object {
        val BLACKLISTED_CLASSES = setOf(
                "package-info",
                "module-info"
        )
    }

    val logger: Logger = LoggerFactory.getLogger(DuplicateDependencyService::class.java)

    fun violationsForModules(moduleIds: List, conf: Configuration, ignoredDependencies: Set): List =
            moduleIds.flatMap { violationsForModule(it, conf.name, ignoredDependencies) }

    fun violationsForModule(mvid: ModuleVersionIdentifier, conf: String, ignoredDependencies: Set): List {
        val dependencyService = DependencyService.forProject(project)
        if (ignoredDependencies.contains(mvid)) {
            return emptyList()
        }

        val dependencyClasses = dependencyService.jarContents(mvid.module)?.classes ?: return emptyList()
        val dupeDependencyClasses = dependencyService.artifactsByClass(conf)
                .filter {
                    var allowable = true
                    BLACKLISTED_CLASSES.forEach { bc ->
                        if (it.key.contains(bc)) {
                            allowable = false
                        }
                    }
                    allowable
                }
                .filter {
                    // don't count artifacts that have the same ModuleIdentifier, which are different versions of the same
                    // module coming from extended configurations that are ultimately conflict resolved away anyway
                    val artifacts = it.value
                    dependencyClasses.contains(it.key) && artifacts.any {
                        !ignoredDependencies.contains(it.moduleVersion.id) && it.moduleVersion.id.module != mvid.module
                    }
                }

        val dupeClassesByDependency = TreeMap>(DependencyService.DEPENDENCY_COMPARATOR)
        dupeDependencyClasses.forEach { (className, resolvedArtifacts) ->
            resolvedArtifacts.forEach { artifact ->
                val moduleId = artifact.moduleVersion.id
                if (!dupeClassesByDependency.containsKey(moduleId)) {
                    dupeClassesByDependency.put(moduleId, mutableSetOf())
                }
                dupeClassesByDependency[artifact.moduleVersion.id]!!.add(className)
            }
        }

        val violations = mutableListOf()
        val configuration = project.configurations.getByName(conf)
        if (!dupeClassesByDependency.isEmpty() && mvid == dupeClassesByDependency.keys.first()) {
            dupeClassesByDependency.forEach { (resolvedMvid, classes) ->
                if (mvid != resolvedMvid) {
                    val message = "$mvid in $configuration has ${classes.size} classes duplicated by $resolvedMvid"
                    logger.info("$message. Duplicate classes: $classes")
                    violations.add("$message (use --info for detailed class list)")
                }
            }
        }
        return violations
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy