@@ -17,6 +17,7 @@ import { buildPackageId } from './utility';
1717import metadataManager from './metadataManager' ;
1818import { sendInfo } from 'vscode-extension-telemetry-wrapper' ;
1919import { batchGetCVEIssues } from './cve' ;
20+ import { ContainerPath } from '../views/containerNode' ;
2021
2122function packageNodeToDescription ( node : INodeData ) : PackageDescription | null {
2223 const version = node . metaData ?. [ "maven.version" ] ;
@@ -152,12 +153,17 @@ async function getDependencyIssues(dependencies: PackageDescription[]): Promise<
152153async function getProjectIssues ( projectNode : INodeData ) : Promise < UpgradeIssue [ ] > {
153154 const issues : UpgradeIssue [ ] = [ ] ;
154155 const dependencies = await getDirectDependencies ( projectNode ) ;
156+ if ( dependencies . length === 0 ) {
157+ sendInfo ( "" , {
158+ operationName : "java.dependency.assessmentManager.getProjectIssues.noDirectDependencies"
159+ } ) ;
160+ return issues ;
161+ }
155162 issues . push ( ...await getCVEIssues ( dependencies ) ) ;
156163 issues . push ( ...getJavaIssues ( projectNode ) ) ;
157164 issues . push ( ...await getDependencyIssues ( dependencies ) ) ;
158165
159166 return issues ;
160-
161167}
162168
163169async function getWorkspaceIssues ( workspaceFolderUri : string ) : Promise < UpgradeIssue [ ] > {
@@ -181,9 +187,6 @@ async function getWorkspaceIssues(workspaceFolderUri: string): Promise<UpgradeIs
181187 return workspaceIssues ;
182188}
183189
184- const MAVEN_CONTAINER_PATH = "org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER" ;
185- const GRADLE_CONTAINER_PATH = "org.eclipse.buildship.core.gradleclasspathcontainer" ;
186-
187190/**
188191 * Find all pom.xml files in a directory using glob
189192 */
@@ -207,21 +210,22 @@ function parseDependenciesFromSinglePom(pomPath: string): Set<string> {
207210 const directDeps = new Set < string > ( ) ;
208211 try {
209212 const pomContent = fs . readFileSync ( pomPath , 'utf-8' ) ;
210-
213+
211214 // Extract dependencies from <dependencies> section (not inside <dependencyManagement>)
212215 // First, remove dependencyManagement sections to avoid including managed deps
213216 const withoutDepMgmt = pomContent . replace ( / < d e p e n d e n c y M a n a g e m e n t > [ \s \S ] * ?< \/ d e p e n d e n c y M a n a g e m e n t > / g, '' ) ;
214-
217+
215218 // Match <dependency> blocks and extract groupId and artifactId
216219 const dependencyRegex = / < d e p e n d e n c y > \s * < g r o u p I d > ( [ ^ < ] + ) < \/ g r o u p I d > \s * < a r t i f a c t I d > ( [ ^ < ] + ) < \/ a r t i f a c t I d > / g;
217- let match ;
218- while ( ( match = dependencyRegex . exec ( withoutDepMgmt ) ) !== null ) {
220+ let match = dependencyRegex . exec ( withoutDepMgmt ) ;
221+ while ( match !== null ) {
219222 const groupId = match [ 1 ] . trim ( ) ;
220223 const artifactId = match [ 2 ] . trim ( ) ;
221224 // Skip property references like ${project.groupId}
222225 if ( ! groupId . includes ( '${' ) && ! artifactId . includes ( '${' ) ) {
223226 directDeps . add ( `${ groupId } :${ artifactId } ` ) ;
224227 }
228+ match = dependencyRegex . exec ( withoutDepMgmt ) ;
225229 }
226230 } catch {
227231 // If we can't read the pom, return empty set
@@ -235,16 +239,16 @@ function parseDependenciesFromSinglePom(pomPath: string): Set<string> {
235239 */
236240async function parseDirectDependenciesFromPom ( projectPath : string ) : Promise < Set < string > > {
237241 const directDeps = new Set < string > ( ) ;
238-
242+
239243 // Find all pom.xml files in the project starting from the project root
240244 const allPomFiles = await findAllPomFiles ( projectPath ) ;
241-
245+
242246 // Parse each pom.xml and collect dependencies
243247 for ( const pom of allPomFiles ) {
244248 const deps = parseDependenciesFromSinglePom ( pom ) ;
245249 deps . forEach ( dep => directDeps . add ( dep ) ) ;
246250 }
247-
251+
248252 return directDeps ;
249253}
250254
@@ -271,30 +275,33 @@ function parseDependenciesFromSingleGradle(gradlePath: string): Set<string> {
271275 const directDeps = new Set < string > ( ) ;
272276 try {
273277 const gradleContent = fs . readFileSync ( gradlePath , 'utf-8' ) ;
274-
278+
275279 // Match common dependency configurations:
276280 // implementation 'group:artifact:version'
277281 // implementation "group:artifact:version"
278282 // api 'group:artifact:version'
279283 // compileOnly, runtimeOnly, testImplementation, etc.
280284 const shortFormRegex = / (?: i m p l e m e n t a t i o n | a p i | c o m p i l e | c o m p i l e O n l y | r u n t i m e O n l y | t e s t I m p l e m e n t a t i o n | t e s t C o m p i l e O n l y | t e s t R u n t i m e O n l y ) \s * \( ? [ ' " ] ( [ ^ : ' " ] + ) : ( [ ^ : ' " ] + ) (?: : [ ^ ' " ] * ) ? [ ' " ] \) ? / g;
281- let match ;
282- while ( ( match = shortFormRegex . exec ( gradleContent ) ) !== null ) {
285+ let match = shortFormRegex . exec ( gradleContent ) ;
286+ while ( match !== null ) {
283287 const groupId = match [ 1 ] . trim ( ) ;
284288 const artifactId = match [ 2 ] . trim ( ) ;
285289 if ( ! groupId . includes ( '$' ) && ! artifactId . includes ( '$' ) ) {
286290 directDeps . add ( `${ groupId } :${ artifactId } ` ) ;
287291 }
292+ match = shortFormRegex . exec ( gradleContent ) ;
288293 }
289294
290295 // Match map notation: implementation group: 'x', name: 'y', version: 'z'
291296 const mapFormRegex = / (?: i m p l e m e n t a t i o n | a p i | c o m p i l e | c o m p i l e O n l y | r u n t i m e O n l y | t e s t I m p l e m e n t a t i o n | t e s t C o m p i l e O n l y | t e s t R u n t i m e O n l y ) \s * \( ? g r o u p : \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] \s * , \s * n a m e : \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / g;
292- while ( ( match = mapFormRegex . exec ( gradleContent ) ) !== null ) {
297+ match = mapFormRegex . exec ( gradleContent ) ;
298+ while ( match !== null ) {
293299 const groupId = match [ 1 ] . trim ( ) ;
294300 const artifactId = match [ 2 ] . trim ( ) ;
295301 if ( ! groupId . includes ( '$' ) && ! artifactId . includes ( '$' ) ) {
296302 directDeps . add ( `${ groupId } :${ artifactId } ` ) ;
297303 }
304+ match = mapFormRegex . exec ( gradleContent ) ;
298305 }
299306 } catch {
300307 // If we can't read the gradle file, return empty set
@@ -308,16 +315,16 @@ function parseDependenciesFromSingleGradle(gradlePath: string): Set<string> {
308315 */
309316async function parseDirectDependenciesFromGradle ( projectPath : string ) : Promise < Set < string > > {
310317 const directDeps = new Set < string > ( ) ;
311-
318+
312319 // Find all Gradle build files in the project
313320 const allGradleFiles = await findAllGradleFiles ( projectPath ) ;
314-
321+
315322 // Parse each gradle file and collect dependencies
316323 for ( const gradleFile of allGradleFiles ) {
317324 const deps = parseDependenciesFromSingleGradle ( gradleFile ) ;
318325 deps . forEach ( dep => directDeps . add ( dep ) ) ;
319326 }
320-
327+
321328 return directDeps ;
322329}
323330
@@ -326,15 +333,14 @@ async function getDirectDependencies(projectNode: INodeData): Promise<PackageDes
326333 // Only include Maven or Gradle containers (not JRE or other containers)
327334 const dependencyContainers = projectStructureData . filter ( x =>
328335 x . kind === NodeKind . Container &&
329- ( x . path ?. startsWith ( MAVEN_CONTAINER_PATH ) || x . path ?. startsWith ( GRADLE_CONTAINER_PATH ) )
336+ ( x . path ?. startsWith ( ContainerPath . Maven ) || x . path ?. startsWith ( ContainerPath . Gradle ) )
330337 ) ;
331338
332339 if ( dependencyContainers . length === 0 ) {
333340 return [ ] ;
334341 }
335342 // Determine build type from dependency containers
336- const isMaven = dependencyContainers . some ( x => x . path ?. startsWith ( MAVEN_CONTAINER_PATH ) ) ;
337-
343+ const isMaven = dependencyContainers . some ( x => x . path ?. startsWith ( ContainerPath . Maven ) ) ;
338344
339345 const allPackages = await Promise . allSettled (
340346 dependencyContainers . map ( async ( packageContainer ) => {
@@ -391,7 +397,7 @@ async function getDirectDependencies(projectNode: INodeData): Promise<PackageDes
391397 }
392398 // Filter to only direct dependencies if we have build file info
393399 if ( directDependencyIds && directDependencyIds . size > 0 ) {
394- dependencies = dependencies . filter ( pkg =>
400+ dependencies = dependencies . filter ( pkg =>
395401 directDependencyIds ! . has ( `${ pkg . groupId } :${ pkg . artifactId } ` )
396402 ) ;
397403 }
0 commit comments