Skip to content

Commit 54ba049

Browse files
committed
feat: a script to find obsolete code
1 parent 41484e3 commit 54ba049

1 file changed

Lines changed: 246 additions & 0 deletions

File tree

src/Get-Obsoletions.ps1

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
<#
2+
.SYNOPSIS
3+
Lists obsoletions, deprecations, and outdated dependencies for a Maven project.
4+
5+
.DESCRIPTION
6+
This script runs various Maven plugins to gather information about:
7+
1. Code deprecations (calls to @Deprecated methods/classes).
8+
2. Outdated dependencies (using versions-maven-plugin).
9+
3. Outdated plugins (using versions-maven-plugin).
10+
4. Unused declared dependencies (using maven-dependency-plugin).
11+
12+
.PARAMETER IncludeTransitive
13+
If set, includes transitive dependencies in the outdated dependencies report.
14+
15+
.PARAMETER OnlyDeprecations
16+
If set, only checks for code deprecations and skips dependency/plugin checks.
17+
18+
.PARAMETER PomFile
19+
Path to the pom.xml file. Defaults to "pom.xml" in the script's directory.
20+
#>
21+
param(
22+
[switch]$IncludeTransitive,
23+
[switch]$OnlyDeprecations,
24+
[string]$PomFile
25+
)
26+
27+
$ErrorActionPreference = "Continue"
28+
29+
if ($PomFile) {
30+
$pomPath = Resolve-Path $PomFile
31+
} else {
32+
$pomPath = Join-Path $PSScriptRoot "pom.xml"
33+
}
34+
35+
# Check Java version mismatch
36+
try {
37+
$javaExe = (Get-Command java -ErrorAction Stop).Source
38+
# Resolve symlinks if possible or just take the path
39+
$javaItem = Get-Item $javaExe
40+
if ($javaItem.LinkType -eq "SymbolicLink") {
41+
$javaExe = $javaItem.Target
42+
}
43+
$javaExePath = Split-Path (Split-Path $javaExe)
44+
45+
if ($env:JAVA_HOME) {
46+
$envJavaHome = (Get-Item $env:JAVA_HOME).FullName.TrimEnd('\/')
47+
$exeJavaHome = (Get-Item $javaExePath).FullName.TrimEnd('\/')
48+
49+
if ($envJavaHome -ne $exeJavaHome) {
50+
Write-Warning "JAVA_HOME ($env:JAVA_HOME) differs from 'java' in PATH ($javaExePath). Maven might use an unexpected version."
51+
}
52+
}
53+
} catch {
54+
# Ignore
55+
}
56+
57+
function Get-MavenOutput {
58+
param(
59+
[string[]]$Goals,
60+
[string[]]$Params
61+
)
62+
$mvnCmd = "mvn"
63+
if ($IsWindows) { $mvnCmd = "mvn.cmd" }
64+
65+
# -B for batch mode (less noise in logs)
66+
$cmdArgs = @("-B", "-f", $pomPath) + $Goals + $Params
67+
68+
# Capture all output (stdout and stderr)
69+
$output = & $mvnCmd $cmdArgs 2>&1
70+
return $output
71+
}
72+
73+
function Parse-VersionsOutput {
74+
param(
75+
[string[]]$OutputLines,
76+
[switch]$IncludeTransitive
77+
)
78+
79+
$results = @()
80+
$bufferedArtifact = ""
81+
$currentSection = "None"
82+
83+
foreach ($line in $OutputLines) {
84+
# Detect section headers
85+
if ($line -match "The following dependencies in Dependencies have newer versions:") {
86+
$currentSection = "Direct"
87+
$bufferedArtifact = ""
88+
continue
89+
}
90+
if ($line -match "The following dependencies in Dependency Management have newer versions:") {
91+
$currentSection = "Transitive"
92+
$bufferedArtifact = ""
93+
continue
94+
}
95+
if ($line -match "The following plugin updates are available:") {
96+
$currentSection = "Direct" # Plugins are treated as direct/always show
97+
$bufferedArtifact = ""
98+
continue
99+
}
100+
101+
# Determine if we should capture this section
102+
$capture = $false
103+
if ($currentSection -eq "Direct") { $capture = $true }
104+
if ($currentSection -eq "Transitive" -and $IncludeTransitive) { $capture = $true }
105+
106+
if (-not $capture) {
107+
continue
108+
}
109+
110+
$cleanLine = $line -replace "^\[INFO\]\s*", ""
111+
112+
# Check for update line (contains "->")
113+
if ($cleanLine -match "\s->\s") {
114+
# Check if this line also contains the artifact name (group:artifact)
115+
# Regex: start of line, non-spaces, colon, non-spaces
116+
if ($cleanLine -match "^[^: ]+:[^: ]+") {
117+
# Full line
118+
$results += $cleanLine
119+
$bufferedArtifact = ""
120+
} elseif ($bufferedArtifact) {
121+
# Continuation line
122+
# Remove trailing dots from buffer
123+
$prefix = $bufferedArtifact -replace "\.+$", ""
124+
# Remove trailing spaces from prefix
125+
$prefix = $prefix.Trim()
126+
$results += "$prefix " + $cleanLine.Trim()
127+
$bufferedArtifact = ""
128+
} else {
129+
# Orphan update line (shouldn't happen if logic is correct, but just in case)
130+
$results += $cleanLine
131+
}
132+
}
133+
# Check for artifact line (group:artifact, no "->")
134+
# We look for lines starting with group:artifact
135+
elseif ($cleanLine -match "^(?<name>[^: ]+:[^: ]+)") {
136+
$bufferedArtifact = $cleanLine
137+
}
138+
}
139+
return $results | Select-Object -Unique
140+
}
141+
142+
Write-Host "Gathering information... (this may take a minute)" -ForegroundColor Gray
143+
144+
# 1. Code Deprecations
145+
Write-Host "`n1. Code Deprecations (Calls to @Deprecated)" -ForegroundColor Cyan
146+
Write-Host "------------------------------------------" -ForegroundColor DarkCyan
147+
# We need clean compile to ensure we see warnings for all files
148+
$compileOut = Get-MavenOutput -Goals @("clean", "compile") -Params @("-Dmaven.compiler.showDeprecation=true", "-Dmaven.compiler.showWarnings=true")
149+
# Check for build failure
150+
if ($compileOut -match "BUILD FAILURE") {
151+
Write-Host "Build failed! Some results may be missing." -ForegroundColor Red
152+
}
153+
154+
# Filter for [deprecation] tag or "has been deprecated" message
155+
$deprecations = $compileOut | Where-Object { $_ -match "\[deprecation\]" -or $_ -match "has been deprecated" } | Select-Object -Unique
156+
157+
if ($deprecations) {
158+
foreach ($line in $deprecations) {
159+
# Format: [WARNING] /path/to/file.java:[12,34] [deprecation] ...
160+
# Strip [WARNING] for cleaner output
161+
Write-Host ($line -replace "^\[WARNING\]\s*", "")
162+
}
163+
} else {
164+
Write-Host "None found." -ForegroundColor Green
165+
}
166+
167+
if (-not $OnlyDeprecations) {
168+
# 2. Outdated Dependencies
169+
$depTitle = "2. Outdated Dependencies (Direct)"
170+
if ($IncludeTransitive) { $depTitle = "2. Outdated Dependencies (Direct & Transitive)" }
171+
Write-Host "`n$depTitle" -ForegroundColor Cyan
172+
Write-Host "------------------------" -ForegroundColor DarkCyan
173+
$verDepsOut = Get-MavenOutput -Goals @("versions:display-dependency-updates")
174+
175+
if ($verDepsOut -match "BUILD FAILURE") {
176+
Write-Host "Build failed! Some results may be missing." -ForegroundColor Red
177+
}
178+
179+
$outdatedDeps = Parse-VersionsOutput -OutputLines $verDepsOut -IncludeTransitive $IncludeTransitive
180+
181+
if ($outdatedDeps) {
182+
foreach ($line in $outdatedDeps) {
183+
Write-Host $line
184+
}
185+
} else {
186+
Write-Host "None found." -ForegroundColor Green
187+
}
188+
189+
# 3. Outdated Plugins
190+
Write-Host "`n3. Outdated Plugins" -ForegroundColor Cyan
191+
Write-Host "-------------------" -ForegroundColor DarkCyan
192+
$verPluginsOut = Get-MavenOutput -Goals @("versions:display-plugin-updates")
193+
194+
if ($verPluginsOut -match "BUILD FAILURE") {
195+
Write-Host "Build failed! Some results may be missing." -ForegroundColor Red
196+
}
197+
198+
$outdatedPlugins = Parse-VersionsOutput -OutputLines $verPluginsOut -IncludeTransitive $true # Always show plugins
199+
200+
if ($outdatedPlugins) {
201+
foreach ($line in $outdatedPlugins) {
202+
Write-Host $line
203+
}
204+
} else {
205+
Write-Host "None found." -ForegroundColor Green
206+
}
207+
208+
# 4. Unused Dependencies
209+
Write-Host "`n4. Unused Declared Dependencies" -ForegroundColor Cyan
210+
Write-Host "-------------------------------" -ForegroundColor DarkCyan
211+
$analyzeOut = Get-MavenOutput -Goals @("dependency:analyze") -Params @("-DignoreNonCompile=true")
212+
213+
if ($analyzeOut -match "BUILD FAILURE") {
214+
Write-Host "Build failed! Some results may be missing." -ForegroundColor Red
215+
}
216+
217+
$capturing = $false
218+
$unusedDeps = @()
219+
foreach ($line in $analyzeOut) {
220+
if ($line -match "Unused declared dependencies found") {
221+
$capturing = $true
222+
continue
223+
}
224+
225+
if ($capturing) {
226+
# Stop capturing if we hit another section or INFO log that isn't an artifact
227+
# Artifact lines in this section usually start with [WARNING] and contain colons like group:artifact:ver
228+
if ($line -match "^\[WARNING\]\s+.*:.*:.*") {
229+
$unusedDeps += ($line -replace "^\[WARNING\]\s*", "")
230+
} elseif ($line -match "^\[INFO\]" -or ($line -match "^\[WARNING\]" -and $line -notmatch "dependencies found")) {
231+
# If we hit a new warning header or info, stop
232+
$capturing = $false
233+
}
234+
}
235+
}
236+
237+
$unusedDeps = $unusedDeps | Select-Object -Unique
238+
if ($unusedDeps) {
239+
foreach ($item in $unusedDeps) {
240+
Write-Host $item.Trim()
241+
}
242+
} else {
243+
Write-Host "None found." -ForegroundColor Green
244+
}
245+
}
246+

0 commit comments

Comments
 (0)