Created
January 29, 2018 13:13
-
-
Save ryanqy/d8fc845be327eefcc3be1ebd3a8dbcea to your computer and use it in GitHub Desktop.
analyze gradle project dependencies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.maven.shared.dependency.analyzer.ClassAnalyzer | |
import org.apache.maven.shared.dependency.analyzer.DefaultClassAnalyzer | |
import org.apache.maven.shared.dependency.analyzer.DependencyAnalyzer | |
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis | |
import org.apache.maven.shared.dependency.analyzer.asm.ASMDependencyAnalyzer | |
buildscript { | |
repositories { | |
mavenCentral() | |
} | |
dependencies { | |
classpath 'org.apache.maven.shared:maven-dependency-analyzer:1.7' | |
} | |
} | |
task analyze { | |
doLast { | |
//单工程项目 | |
if (childProjects.size() == 0) { | |
printAnalyze(project) | |
} else { | |
for (Project childrenProject : childProjects.values()) { | |
printAnalyze(childrenProject) | |
} | |
} | |
} | |
} | |
void printAnalyze(Project project) { | |
ProjectDependencyAnalysis analysis = new ProjectDependencyResolver().analyzeDependencies(project) | |
StringBuffer buffer = new StringBuffer() | |
buffer.append("project:" + project.name + "\n") | |
['usedDeclaredArtifacts', 'usedUndeclaredArtifacts', 'unusedDeclaredArtifacts'].each { section -> | |
def violations = analysis."$section" | |
buffer.append("$section: \n") | |
violations*.moduleVersion*.id.each { | |
buffer.append(" - $it.group:$it.name:$it.version\n") | |
} | |
} | |
logger.warn(buffer.toString()) | |
} | |
class ProjectDependencyResolver { | |
private ClassAnalyzer classAnalyzer = new DefaultClassAnalyzer(); | |
private DependencyAnalyzer dependencyAnalyzer = new ASMDependencyAnalyzer(); | |
/** | |
* | |
* @param project | |
* @return | |
*/ | |
ProjectDependencyAnalysis analyzeDependencies(Project project) { | |
if (!project.plugins.hasPlugin('java')) { | |
throw new IllegalStateException("Project does not have the java plugin applied.") | |
} | |
Set<ResolvedDependency> firstLevelDeps = getFirstLevelDependencies(project, 'compile') | |
Set<File> dependencyArtifacts = findModuleArtifactFiles(firstLevelDeps) | |
Map<File, Set<String>> fileClassMap = buildArtifactClassMap(dependencyArtifacts) | |
project.logger.info "fileClassMap = $fileClassMap" | |
Set<String> dependencyClasses = analyzeClassDependencies(project) | |
project.logger.info "dependencyClasses = $dependencyClasses" | |
Set<File> usedArtifacts = buildUsedArtifacts(fileClassMap, dependencyClasses) | |
project.logger.info "usedArtifacts = $usedArtifacts" | |
Set<File> usedDeclaredArtifacts = new LinkedHashSet<File>(dependencyArtifacts) | |
usedDeclaredArtifacts.retainAll(usedArtifacts) | |
project.logger.info "usedDeclaredArtifacts = $usedDeclaredArtifacts" | |
Set<File> usedUndeclaredArtifacts = new LinkedHashSet<File>(usedArtifacts) | |
usedUndeclaredArtifacts.removeAll(dependencyArtifacts) | |
project.logger.info "usedUndeclaredArtifacts = $usedUndeclaredArtifacts" | |
Set<File> unusedDeclaredArtifacts = new LinkedHashSet<File>(dependencyArtifacts) | |
unusedDeclaredArtifacts.removeAll(usedArtifacts) | |
project.logger.info "unusedDeclaredArtifacts = $unusedDeclaredArtifacts" | |
//Now work back from the files to the artifact information | |
ConfigurationContainer configurations = project.configurations | |
def nonTestConfigurations = configurations.findAll { !it.name.contains('test') } | |
List<ResolvedArtifact> artifacts = nonTestConfigurations*.resolvedConfiguration*.resolvedArtifacts.unique { | |
it | |
}.flatten() | |
return new ProjectDependencyAnalysis( | |
artifacts.findAll { ResolvedArtifact artifact -> artifact.file in usedDeclaredArtifacts }.unique { | |
it.file | |
} as Set<org.apache.maven.artifact.Artifact>, | |
artifacts.findAll { ResolvedArtifact artifact -> artifact.file in usedUndeclaredArtifacts }.unique { | |
it.file | |
} as Set<org.apache.maven.artifact.Artifact>, | |
artifacts.findAll { ResolvedArtifact artifact -> artifact.file in unusedDeclaredArtifacts }.unique { | |
it.file | |
} as Set<org.apache.maven.artifact.Artifact>) | |
} | |
private Set<ResolvedDependency> getFirstLevelDependencies(Project project, String configurationName) { | |
project.configurations."$configurationName".resolvedConfiguration.firstLevelModuleDependencies | |
} | |
private Map<File, Set<String>> buildArtifactClassMap(Set<File> dependencyArtifacts) throws IOException { | |
Map<File, Set<String>> artifactClassMap = [:] | |
dependencyArtifacts.each { File file -> | |
if (file.name.endsWith('jar')) { | |
artifactClassMap.put(file, classAnalyzer.analyze(file.toURL())) | |
} else { | |
project.logger.info "Skipping analysis of file for classes: $file" | |
} | |
} | |
return artifactClassMap | |
} | |
private Set<File> findModuleArtifactFiles(Set<ResolvedDependency> dependencies) { | |
dependencies*.moduleArtifacts*.collect { it.file }.unique().flatten() | |
} | |
private Collection analyzeClassDependencies(Project project) { | |
return project.sourceSets*.output.classesDir?.collect { File file -> | |
dependencyAnalyzer.analyze(file.toURI().toURL()) | |
}?.flatten()?.unique() | |
} | |
private Set<File> buildUsedArtifacts(Map<File, Set<String>> artifactClassMap, Set<String> dependencyClasses) { | |
Set<File> usedArtifacts = new HashSet() | |
dependencyClasses.each { String className -> | |
File artifact = artifactClassMap.find { it.value.contains(className) }?.key | |
if (artifact) { | |
usedArtifacts << artifact | |
} | |
} | |
return usedArtifacts | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment