11package org.gradle.dependencygraph.extractor
22
33import org.gradle.api.GradleException
4+ import org.gradle.api.artifacts.component.ProjectComponentIdentifier
45import org.gradle.api.artifacts.result.ResolvedComponentResult
56import org.gradle.api.artifacts.result.ResolvedDependencyResult
67import org.gradle.api.internal.artifacts.DefaultProjectComponentIdentifier
@@ -144,8 +145,9 @@ abstract class DependencyExtractor :
144145 }
145146 val projectIdentityPath = (rootComponent.id as ? DefaultProjectComponentIdentifier )?.identityPath?.path
146147
147- // TODO: At this point, any resolution not bound to a particular project will be assigned to the root "build :"
148+ // At this point, any resolution not bound to a particular project will be assigned to the root "build :"
148149 // This is because `details.buildPath` is always ':', which isn't correct in a composite build.
150+ // This is inconsequential for GitHub Dependency Graph, since all dependencies are mapped to a single manifest.
149151 // It is possible to do better. By tracking the current build operation context, we can assign more precisely.
150152 // See the Gradle Enterprise Build Scan Plugin: `ConfigurationResolutionCapturer_5_0`
151153 val rootPath = projectIdentityPath ? : details.buildPath
@@ -159,17 +161,17 @@ abstract class DependencyExtractor :
159161 val rootSource = DependencySource (rootId, rootPath)
160162 val resolvedConfiguration = ResolvedConfiguration (rootSource, details.configurationName)
161163
162- for (directDependency in getResolvedDependencies(rootComponent)) {
164+ for (dependencyComponent in getResolvedDependencies(rootComponent)) {
163165 val directDep = createComponentNode(
164- componentId(directDependency ),
166+ componentId(dependencyComponent ),
165167 rootSource,
166168 true ,
167- directDependency ,
169+ dependencyComponent ,
168170 repositoryLookup
169171 )
170172 resolvedConfiguration.addDependency(directDep)
171173
172- walkComponentDependencies(directDependency , directDep.source, repositoryLookup, resolvedConfiguration)
174+ walkComponentDependencies(dependencyComponent , directDep.source, repositoryLookup, resolvedConfiguration)
173175 }
174176
175177 resolvedConfigurations.add(resolvedConfiguration)
@@ -184,11 +186,11 @@ abstract class DependencyExtractor :
184186 val componentSource = getSource(component, parentSource)
185187 val direct = componentSource != parentSource
186188
187- val dependencyComponents = getResolvedDependencies(component)
188- for (dependencyComponent in dependencyComponents) {
189+ for (dependencyComponent in getResolvedDependencies(component)) {
189190 val dependencyId = componentId(dependencyComponent)
190191 if (! resolvedConfiguration.hasDependency(dependencyId)) {
191- val dependencyNode = createComponentNode(dependencyId, componentSource, direct, dependencyComponent, repositoryLookup)
192+ val dependencyNode =
193+ createComponentNode(dependencyId, componentSource, direct, dependencyComponent, repositoryLookup)
192194 resolvedConfiguration.addDependency(dependencyNode)
193195
194196 walkComponentDependencies(dependencyComponent, componentSource, repositoryLookup, resolvedConfiguration)
@@ -208,13 +210,15 @@ abstract class DependencyExtractor :
208210 return component.dependencies.filterIsInstance<ResolvedDependencyResult >().map { it.selected }.filter { it != component }
209211 }
210212
211- private fun createComponentNode (componentId : String , source : DependencySource , direct : Boolean , component : ResolvedComponentResult , repositoryLookup : RepositoryUrlLookup ): ResolvedDependency {
213+ private fun createComponentNode (componentId : String , source : DependencySource , isDirectDependency : Boolean , component : ResolvedComponentResult , repositoryLookup : RepositoryUrlLookup ): ResolvedDependency {
212214 val componentDependencies = component.dependencies.filterIsInstance<ResolvedDependencyResult >().map { componentId(it.selected) }
213215 val repositoryUrl = repositoryLookup.doLookup(component)
216+ val isProjectDependency = component.id is ProjectComponentIdentifier
214217 return ResolvedDependency (
215218 componentId,
216219 source,
217- direct,
220+ isDirectDependency,
221+ isProjectDependency,
218222 coordinates(component),
219223 repositoryUrl,
220224 componentDependencies
@@ -226,13 +230,12 @@ abstract class DependencyExtractor :
226230 }
227231
228232 private fun coordinates (component : ResolvedComponentResult ): DependencyCoordinates {
229- // TODO: Consider and handle null moduleVersion
230- val moduleVersionIdentifier = component.moduleVersion!!
231- return DependencyCoordinates (
232- moduleVersionIdentifier.group,
233- moduleVersionIdentifier.name,
234- moduleVersionIdentifier.version
235- )
233+ val mv = component.moduleVersion
234+ return if (mv != null ) {
235+ DependencyCoordinates (mv.group, mv.name, mv.version)
236+ } else {
237+ DependencyCoordinates (" unknown" , " unknown" , " unknown" )
238+ }
236239 }
237240
238241 private class RepositoryUrlLookup (
0 commit comments