diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/AndroidResourceDeclaredNames.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/AndroidResourceDeclaredNames.kt index 8abc2c98d7..341621a59b 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/AndroidResourceDeclaredNames.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/AndroidResourceDeclaredNames.kt @@ -27,6 +27,7 @@ import modulecheck.parsing.source.AndroidResourceDeclaredName import modulecheck.project.McProject import modulecheck.project.ProjectContext import modulecheck.project.isAndroid +import modulecheck.project.project import modulecheck.utils.LazySet import modulecheck.utils.SafeCache import modulecheck.utils.dataSource @@ -75,7 +76,7 @@ data class AndroidResourceDeclaredNames( val transitiveSourceSetName = tpd.source.declaringSourceSetName() - tpd.contributed.project + tpd.contributed.project(project.projectCache) .androidUnqualifiedDeclarationNamesForSourceSetName(transitiveSourceSetName) } else flowOf() diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilGraph.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilGraph.kt index 87ccbe53b7..8cfb95a8b2 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilGraph.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilGraph.kt @@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.mapNotNull +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.source.AnvilScopeName import modulecheck.parsing.source.AnvilScopeNameEntry @@ -28,9 +29,9 @@ import modulecheck.parsing.source.JvmFile import modulecheck.parsing.source.KotlinFile import modulecheck.parsing.source.RawAnvilAnnotatedType import modulecheck.parsing.source.asExplicitKotlinReference -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.SafeCache import org.jetbrains.kotlin.name.FqName @@ -163,7 +164,7 @@ data class AnvilGraph( .orEmpty() .asFlow() .mapNotNull { cpd -> - cpd.project + cpd.project(project.projectCache) .declarations() .get(SourceSetName.MAIN, includeUpstream = true) .filter { maybeExtraReferences.contains(it) } diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilScopeDependencies.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilScopeDependencies.kt index 2a27ea5ffc..57daefacb5 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilScopeDependencies.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/AnvilScopeDependencies.kt @@ -15,10 +15,11 @@ package modulecheck.api.context +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.SourceSetName -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.SafeCache data class AnvilScopeDependencies( @@ -43,7 +44,7 @@ data class AnvilScopeDependencies( .filter { cpd -> val contributed = cpd - .project + .project(project.projectCache) .anvilScopeContributionsForSourceSetName(cpd.configurationName.toSourceSetName()) contributed.any { (scopeName, _) -> diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/ClasspathDependencies.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/ClasspathDependencies.kt index eeb31dfae6..af0660deb4 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/ClasspathDependencies.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/ClasspathDependencies.kt @@ -17,9 +17,9 @@ package modulecheck.api.context import modulecheck.parsing.gradle.model.ConfigurationName import modulecheck.parsing.gradle.model.SourceSetName +import modulecheck.parsing.gradle.model.TransitiveProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext -import modulecheck.project.TransitiveProjectDependency import modulecheck.utils.SafeCache import modulecheck.utils.mapToSet @@ -57,20 +57,20 @@ data class ClasspathDependencies( ) val directDependencies = projectDependencies[sourceSetName] - .filterNot { it.project == project } + .filterNot { it.project() == project } - val directDependencyPaths = directDependencies.mapToSet { it.project.path } + val directDependencyPaths = directDependencies.mapToSet { it.path } val inherited = directDependencies.flatMap { sourceCpd -> sourceApiConfigs(sourceSetName, sourceCpd.isTestFixture) .flatMap { apiConfig -> - sourceCpd.project + sourceCpd.project() .classpathDependencies() .get(apiConfig.toSourceSetName()) .asSequence() .filter { it.contributed.configurationName.isApi() } - .filterNot { it.contributed.project.path in directDependencyPaths } + .filterNot { it.contributed.path in directDependencyPaths } .map { transitiveCpd -> TransitiveProjectDependency(sourceCpd, transitiveCpd.contributed) } diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/Declarations.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/Declarations.kt index 1c4524c79b..d1ad9c0727 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/Declarations.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/Declarations.kt @@ -19,10 +19,11 @@ import kotlinx.coroutines.flow.toList import modulecheck.api.context.Declarations.DeclarationsKey.ALL import modulecheck.api.context.Declarations.DeclarationsKey.WithUpstream import modulecheck.api.context.Declarations.DeclarationsKey.WithoutUpstream +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.source.DeclaredName -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject +import modulecheck.project.ProjectCache import modulecheck.project.ProjectContext import modulecheck.project.isAndroid import modulecheck.utils.LazySet @@ -113,7 +114,10 @@ data class Declarations private constructor( suspend fun ProjectContext.declarations(): Declarations = get(Declarations) -suspend fun ConfiguredProjectDependency.declarations(): LazySet { +suspend fun ConfiguredProjectDependency.declarations( + projectCache: ProjectCache +): LazySet { + val project = projectCache.getValue(path) if (isTestFixture) { return project.declarations().get(SourceSetName.TEST_FIXTURES, false) } diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/DependencySources.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/DependencySources.kt index b53455f26e..1169507d72 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/DependencySources.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/DependencySources.kt @@ -17,9 +17,9 @@ package modulecheck.api.context import modulecheck.api.context.DependencySources.SourceResult.Found import modulecheck.api.context.DependencySources.SourceResult.NOT_PRESENT -import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ProjectPath import modulecheck.parsing.gradle.model.SourceSetName -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext import modulecheck.utils.SafeCache @@ -31,7 +31,7 @@ data class DependencySources( data class SourceKey( val sourceSetName: SourceSetName, - val dependencyProjectPath: StringProjectPath, + val dependencyProjectPath: ProjectPath, val isTestFixture: Boolean ) @@ -44,7 +44,7 @@ data class DependencySources( get() = DependencySources suspend fun sourceOfOrNull( - dependencyProjectPath: StringProjectPath, + dependencyProjectPath: ProjectPath, sourceSetName: SourceSetName, isTestFixture: Boolean ): ConfiguredProjectDependency? { @@ -60,7 +60,7 @@ data class DependencySources( val sourceOrNull = project.classpathDependencies() .get(sourceSetName) .firstOrNull { transitive -> - transitive.contributed.project.path == dependencyProjectPath && + transitive.contributed.path == dependencyProjectPath && transitive.contributed.isTestFixture == isTestFixture } ?.source diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/Depths.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/Depths.kt index d55646b5cf..f37f5a6e62 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/Depths.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/Depths.kt @@ -21,6 +21,7 @@ import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.SafeCache data class Depths( @@ -43,7 +44,7 @@ data class Depths( private suspend fun fetchForSourceSet(sourceSetName: SourceSetName): ProjectDepth { val (childDepth, children) = project.projectDependencies[sourceSetName] - .map { it.project } + .map { it.project(project.projectCache) } .distinct() .map { it.depthForSourceSetName(SourceSetName.MAIN) } .groupBy { it.depth } @@ -99,7 +100,8 @@ data class ProjectDepth( val children = dependentProject .projectDependencies[sourceSetName] .flatMap { - it.project.depthForSourceSetName(SourceSetName.MAIN) + it.project(dependentProject.projectCache) + .depthForSourceSetName(SourceSetName.MAIN) .fullTree(SourceSetName.MAIN) } children.toSet() + this diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/DownstreamProjects.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/DownstreamProjects.kt index 3a94ab4d2c..c2b4142623 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/DownstreamProjects.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/DownstreamProjects.kt @@ -15,9 +15,10 @@ package modulecheck.api.context -import modulecheck.project.DownstreamDependency +import modulecheck.parsing.gradle.model.DownstreamDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.flatMapToSet data class DownstreamProjects( @@ -37,10 +38,10 @@ data class DownstreamProjects( otherProject .classpathDependencies() .all() - .filter { it.contributed.project == project } + .filter { it.contributed.project(project.projectCache) == project } .map { transitive -> DownstreamDependency( - dependentProject = otherProject, + dependentProjectPath = otherProject.path, configuredProjectDependency = transitive.withContributedConfiguration().contributed ) } diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/KaptDependencies.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/KaptDependencies.kt index a1e2465377..40cb4e74fd 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/KaptDependencies.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/KaptDependencies.kt @@ -16,8 +16,8 @@ package modulecheck.api.context import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredDependency import modulecheck.parsing.gradle.model.all -import modulecheck.project.ConfiguredDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext import modulecheck.project.ProjectContext.Element diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/PublicDependencies.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/PublicDependencies.kt index 6858e8fc58..8eca373bf6 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/PublicDependencies.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/PublicDependencies.kt @@ -16,8 +16,8 @@ package modulecheck.api.context import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.all -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext @@ -51,7 +51,7 @@ data class PublicDependencies( val inherited = combined .flatMap { cpd -> cpd - .project + .project() .allPublicClassPathDependencyDeclarations(false) } diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/ResolvedDeclaredNames.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/ResolvedDeclaredNames.kt index 1e0f3f41d3..cdec38f005 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/ResolvedDeclaredNames.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/ResolvedDeclaredNames.kt @@ -21,6 +21,7 @@ import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.source.DeclaredName import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.SafeCache data class ResolvedDeclaredNames internal constructor( @@ -72,7 +73,7 @@ data class ResolvedDeclaredNames internal constructor( .get(sourceSetName) .asSequence() .map { it.contributed } - .distinctBy { it.project to it.isTestFixture } + .distinctBy { it.project(project.projectCache) to it.isTestFixture } .firstNotNullOfOrNull { sourceCpd -> listOfNotNull( @@ -80,7 +81,8 @@ data class ResolvedDeclaredNames internal constructor( SourceSetName.TEST_FIXTURES.takeIf { sourceCpd.isTestFixture } ) .firstNotNullOfOrNull { dependencySourceSetName -> - sourceCpd.project.resolvedDeclaredNames() + sourceCpd.project(project.projectCache) + .resolvedDeclaredNames() .getSource(declaredName, dependencySourceSetName) } } diff --git a/modulecheck-api/src/main/kotlin/modulecheck/api/context/SourceSetDependencies.kt b/modulecheck-api/src/main/kotlin/modulecheck/api/context/SourceSetDependencies.kt index fa0e970325..f8b9cc6900 100644 --- a/modulecheck-api/src/main/kotlin/modulecheck/api/context/SourceSetDependencies.kt +++ b/modulecheck-api/src/main/kotlin/modulecheck/api/context/SourceSetDependencies.kt @@ -16,9 +16,9 @@ package modulecheck.api.context import modulecheck.parsing.gradle.model.SourceSetName +import modulecheck.parsing.gradle.model.TransitiveProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext -import modulecheck.project.TransitiveProjectDependency import modulecheck.utils.SafeCache data class SourceSetDependencies( @@ -45,19 +45,19 @@ data class SourceSetDependencies( ) val directDependencies = projectDependencies[sourceSetName] - .filterNot { it.project == project } + .filterNot { it.path == project.path } .toSet() - val directDependencyPaths = directDependencies.map { it.project.path }.toSet() + val directDependencyPaths = directDependencies.map { it.path }.toSet() val inherited = directDependencies.flatMap { sourceCpd -> sourceConfigs(sourceCpd.isTestFixture) .flatMap { dependencySourceSetName -> - sourceCpd.project + sourceCpd.project() .sourceSetDependencies() .get(dependencySourceSetName) - .filterNot { it.contributed.project.path in directDependencyPaths } + .filterNot { it.contributed.path in directDependencyPaths } .map { transitiveCpd -> TransitiveProjectDependency(sourceCpd, transitiveCpd.contributed) } diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/InheritedDependencyFinding.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/InheritedDependencyFinding.kt index 1fadf19f15..98421cb0c0 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/InheritedDependencyFinding.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/InheritedDependencyFinding.kt @@ -21,7 +21,7 @@ import modulecheck.finding.FindingName import modulecheck.finding.internal.positionIn import modulecheck.finding.internal.statementOrNullIn import modulecheck.parsing.gradle.dsl.BuildFileStatement -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.utils.LazyDeferred import modulecheck.utils.lazyDeferred @@ -51,10 +51,10 @@ data class InheritedDependencyFinding( } override fun fromStringOrEmpty(): String { - return if (dependency.path == source.project.path) { + return if (dependency.path == source.path) { "" } else { - source.project.path.value + source.path.value } } diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/MustBeApiFinding.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/MustBeApiFinding.kt index 82befadb6f..67f6f7b621 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/MustBeApiFinding.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/MustBeApiFinding.kt @@ -22,7 +22,7 @@ import modulecheck.finding.RemovesDependency import modulecheck.finding.internal.statementOrNullIn import modulecheck.parsing.gradle.dsl.BuildFileStatement import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.utils.LazyDeferred import modulecheck.utils.lazyDeferred @@ -53,10 +53,10 @@ data class MustBeApiFinding( } override fun fromStringOrEmpty(): String { - return if (dependency.path == source?.project?.path) { + return if (dependency.path == source?.path) { "" } else { - "${source?.project?.path?.value}" + "${source?.path?.value}" } } diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/OverShotDependencyFinding.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/OverShotDependencyFinding.kt index 9c1a311a75..1aa2de7048 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/OverShotDependencyFinding.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/OverShotDependencyFinding.kt @@ -22,7 +22,7 @@ import modulecheck.finding.internal.positionOfStatement import modulecheck.finding.internal.statementOrNullIn import modulecheck.parsing.gradle.dsl.BuildFileStatement import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.utils.LazyDeferred import modulecheck.utils.lazyDeferred diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/RedundantDependencyFinding.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/RedundantDependencyFinding.kt index fa0830f348..16aafdaeb9 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/RedundantDependencyFinding.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/RedundantDependencyFinding.kt @@ -19,7 +19,7 @@ import modulecheck.finding.Deletable import modulecheck.finding.FindingName import modulecheck.finding.RemovesDependency import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.project.McProject data class RedundantDependency( @@ -54,14 +54,14 @@ data class RedundantDependencyFinding( "declared in the current module. This is technically unnecessary if a \"minimalist\" build " + "file is desired." - override val dependencyIdentifier = oldDependency.project.path.value + fromStringOrEmpty() + override val dependencyIdentifier = oldDependency.path.value + fromStringOrEmpty() override fun fromStringOrEmpty(): String { - return if (from.all { dependency.path == it.project.path }) { + return if (from.all { dependency.path == it.path }) { "" } else { - from.joinToString { it.project.path.value } + from.joinToString { it.path.value } } } } diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedDependency.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedDependency.kt index bfcdcbd86e..da34afb895 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedDependency.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedDependency.kt @@ -19,7 +19,7 @@ import modulecheck.finding.Deletable import modulecheck.finding.FindingName import modulecheck.finding.RemovesDependency import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.project.McProject data class UnusedDependency( diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedPluginFinding.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedPluginFinding.kt index f10a926d67..f02aa24edf 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedPluginFinding.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/UnusedPluginFinding.kt @@ -26,10 +26,10 @@ import modulecheck.finding.getSuppressions import modulecheck.finding.internal.removeDependencyWithComment import modulecheck.finding.internal.removeDependencyWithDelete import modulecheck.parsing.gradle.dsl.BuildFileStatement +import modulecheck.parsing.gradle.model.PluginDefinition +import modulecheck.parsing.gradle.model.PluginDependency import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath import modulecheck.project.McProject -import modulecheck.project.PluginDefinition -import modulecheck.project.PluginDependency import modulecheck.utils.LazyDeferred import modulecheck.utils.lazyDeferred import java.io.File diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/context/MustBeApi.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/context/MustBeApi.kt index bed84f322a..e382169b48 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/context/MustBeApi.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/context/MustBeApi.kt @@ -28,14 +28,15 @@ import modulecheck.api.context.declarations import modulecheck.api.context.dependencySources import modulecheck.api.context.jvmFilesForSourceSetName import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.source.DeclaredName import modulecheck.parsing.source.NamedSymbol import modulecheck.parsing.source.Reference import modulecheck.parsing.source.UnqualifiedAndroidResourceReference -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.LazyDeferred import modulecheck.utils.LazySet import modulecheck.utils.any @@ -70,10 +71,11 @@ data class MustBeApi( // projects with a @Contributes(...) annotation somewhere val scopeContributingProjects = mainDependencies - .filter { (_, projectDependency) -> + .filter { (_, projectDependencyPath) -> - val contributions = - projectDependency.anvilScopeContributionsForSourceSetName(sourceSetName) + val contributions = project.projectCache + .getValue(projectDependencyPath) + .anvilScopeContributionsForSourceSetName(sourceSetName) mergedScopeNames.any { contributions.containsKey(it) } } @@ -86,7 +88,7 @@ data class MustBeApi( .toSet() val directMainDependencies by lazy { - project.projectDependencies[sourceSetName].map { it.project } + project.projectDependencies[sourceSetName].map { it.project(project.projectCache) } } mainDependencies @@ -95,19 +97,20 @@ data class MustBeApi( // and will be handled by the InheritedDependencyRule. .filterNot { it.configurationName.isApi() } .plus(scopeContributingProjects) - .distinctBy { it.project } + .distinctBy { it.path } .filterNot { cpd -> // exclude anything which is inherited but already included in local `api` deps cpd in directApiProjects } .filterAsync { - !sourceSetName.isTestingOnly() && it.project.mustBeApiIn( - dependentProject = project, - referencesFromDependencies = importsFromDependencies, - sourceSetName = it.configurationName.toSourceSetName(), - isTestFixtures = it.isTestFixture, - directMainDependencies = directMainDependencies - ) + !sourceSetName.isTestingOnly() && it.project(project.projectCache) + .mustBeApiIn( + dependentProject = project, + referencesFromDependencies = importsFromDependencies, + sourceSetName = it.configurationName.toSourceSetName(), + isTestFixtures = it.isTestFixture, + directMainDependencies = directMainDependencies + ) } .map { cpd -> val source = project @@ -117,17 +120,18 @@ data class MustBeApi( // First try to find a normal "implementation" version of the dependency. dependencies .firstOrNull { declared -> - declared.project == cpd.project && declared.isTestFixture == cpd.isTestFixture + declared.path == cpd.path && declared.isTestFixture == cpd.isTestFixture } // If that didn't work, look for something where the project matches // (which means it's testFixtures) - ?: dependencies.firstOrNull { it.project == cpd.project } + ?: dependencies.firstOrNull { it.path == cpd.path } } - ?: project.dependencySources().sourceOfOrNull( - dependencyProjectPath = cpd.project.path, - sourceSetName = sourceSetName, - isTestFixture = cpd.isTestFixture - ) + ?: project.dependencySources() + .sourceOfOrNull( + dependencyProjectPath = cpd.path, + sourceSetName = sourceSetName, + isTestFixture = cpd.isTestFixture + ) InheritedDependencyWithSource(cpd, source) } .toList() @@ -170,7 +174,7 @@ suspend fun McProject.mustBeApiIn( val directDependencies = sourceSetName.withUpstream(dependentProject) .flatMap { sourceSetOrUpstream -> dependentProject.projectDependencies[sourceSetOrUpstream] - .map { it.project } + .map { it.project() } } return mustBeApiIn( dependentProject = dependentProject, @@ -233,11 +237,12 @@ private suspend fun McProject.mustBeApiIn( suspend fun ConfiguredProjectDependency.asApiOrImplementation( dependentProject: McProject ): ConfiguredProjectDependency { - val mustBeApi = project.mustBeApiIn( - dependentProject = dependentProject, - sourceSetName = configurationName.toSourceSetName(), - isTestFixtures = isTestFixture - ) + val mustBeApi = project(dependentProject.projectCache) + .mustBeApiIn( + dependentProject = dependentProject, + sourceSetName = configurationName.toSourceSetName(), + isTestFixtures = isTestFixture + ) val newConfig = if (mustBeApi) { configurationName.apiVariant() diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/context/OverShotDependencies.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/context/OverShotDependencies.kt index 0e84eecf6e..97ac6001ee 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/context/OverShotDependencies.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/context/OverShotDependencies.kt @@ -18,10 +18,10 @@ package modulecheck.core.context import modulecheck.core.OverShotDependency import modulecheck.core.internal.uses import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.toSourceSetDependency import modulecheck.project.McProject import modulecheck.project.ProjectContext -import modulecheck.project.toSourceSetDependency import modulecheck.utils.SafeCache import modulecheck.utils.mapToSet import modulecheck.utils.unsafeLazy @@ -74,7 +74,7 @@ data class OverShotDependencies( .map { (configName, isTestFixture) -> ConfiguredProjectDependency( configurationName = configName, - project = unused.dependency.project, + path = unused.dependency.path, isTestFixture = isTestFixture ) } @@ -120,8 +120,8 @@ data class OverShotDependencies( configurationName = newCpd.configurationName ) } - .sortedBy { it.newDependency.project } - .distinctBy { it.newDependency.project } + .sortedBy { it.newDependency.path } + .distinctBy { it.newDependency.path } } } diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/context/RedundantDependencies.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/context/RedundantDependencies.kt index d9bd56a0c7..3af24e353a 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/context/RedundantDependencies.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/context/RedundantDependencies.kt @@ -21,6 +21,7 @@ import modulecheck.core.RedundantDependency import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.SafeCache import modulecheck.utils.mapAsync @@ -51,12 +52,12 @@ data class RedundantDependencies( val inheritedDependencyProjects = project .classpathDependencies() .get(sourceSetName) - .groupBy { it.contributed.project } + .groupBy { it.contributed.path } allDirect .mapNotNull { direct -> - val fromCpd = inheritedDependencyProjects[direct.project] + val fromCpd = inheritedDependencyProjects[direct.path] ?.map { it.source } ?: return@mapNotNull null diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/context/UnusedDependencies.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/context/UnusedDependencies.kt index c973d54400..8f92cd537a 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/context/UnusedDependencies.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/context/UnusedDependencies.kt @@ -24,6 +24,7 @@ import modulecheck.core.internal.uses import modulecheck.parsing.gradle.model.ConfigurationName import modulecheck.project.McProject import modulecheck.project.ProjectContext +import modulecheck.project.project import modulecheck.utils.SafeCache import modulecheck.utils.filterAsync import modulecheck.utils.lazyDeferred @@ -54,22 +55,22 @@ data class UnusedDependencies( val neededForScopes = lazyDeferred { project.anvilScopeDependenciesForSourceSetName(configurationName.toSourceSetName()) - .map { it.project } + .map { it.project(project.projectCache) } .toSet() } dependencies // test configurations have the main source project as a dependency. // without this, every project will report itself as unused. - .filterNot { cpd -> cpd.project.path == project.path } + .filterNot { cpd -> cpd.path == project.path } .filterAsync { cpd -> - !project.uses(cpd) && !neededForScopes.await().contains(cpd.project) + !project.uses(cpd) && !neededForScopes.await().contains(cpd.project(project.projectCache)) } .map { cpd -> UnusedDependency( dependentProject = project, dependency = cpd, - dependencyIdentifier = cpd.project.path.value, + dependencyIdentifier = cpd.path.value, configurationName = cpd.configurationName ) } diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/internal/uses.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/internal/uses.kt index 7b535cb46a..66f61f6ed9 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/internal/uses.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/internal/uses.kt @@ -23,9 +23,9 @@ import modulecheck.api.context.anvilScopeContributionsForSourceSetName import modulecheck.api.context.declarations import modulecheck.api.context.dependents import modulecheck.api.context.referencesForSourceSetName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.source.Generated -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.utils.any import modulecheck.utils.containsAny @@ -34,7 +34,7 @@ import modulecheck.utils.lazySet suspend fun McProject.uses(dependency: ConfiguredProjectDependency): Boolean { - val dependencyDeclarations = dependency.declarations() + val dependencyDeclarations = dependency.declarations(projectCache) val referencesSourceSetName = dependency.configurationName.toSourceSetName() @@ -67,7 +67,7 @@ suspend fun McProject.uses(dependency: ConfiguredProjectDependency): Boolean { val downstreamSourceSet = downstreamDependency.configuredProjectDependency .declaringSourceSetName() - downstreamDependency.dependentProject + projectCache.getValue(downstreamDependency.dependentProjectPath) .referencesForSourceSetName(downstreamSourceSet) .containsAny(generatedFromThisDependency) } @@ -75,7 +75,7 @@ suspend fun McProject.uses(dependency: ConfiguredProjectDependency): Boolean { if (usedUpstream) return true // If there are no references is manually/human written static code, then parse the Anvil graph. - val anvilContributions = dependency.project + val anvilContributions = dependency.project() .anvilScopeContributionsForSourceSetName(SourceSetName.MAIN) return anvilGraph() diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/kapt/UnusedKaptProcessorFinding.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/kapt/UnusedKaptProcessorFinding.kt index b9b82fbc98..cf52bc4716 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/kapt/UnusedKaptProcessorFinding.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/kapt/UnusedKaptProcessorFinding.kt @@ -27,10 +27,10 @@ import modulecheck.finding.internal.positionOfStatement import modulecheck.finding.internal.statementOrNullIn import modulecheck.parsing.gradle.dsl.BuildFileStatement import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ExternalDependency import modulecheck.parsing.gradle.model.ProjectPath -import modulecheck.project.ConfiguredDependency -import modulecheck.project.ConfiguredProjectDependency -import modulecheck.project.ExternalDependency import modulecheck.project.McProject import modulecheck.utils.LazyDeferred import modulecheck.utils.lazyDeferred diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableAndroidResourcesRule.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableAndroidResourcesRule.kt index 4a3f278365..682d436ac5 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableAndroidResourcesRule.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableAndroidResourcesRule.kt @@ -26,6 +26,7 @@ import modulecheck.core.rule.android.UnusedResourcesGenerationFinding import modulecheck.finding.FindingName import modulecheck.parsing.gradle.model.AndroidPlatformPlugin.AndroidLibraryPlugin import modulecheck.project.McProject +import modulecheck.project.project import modulecheck.utils.containsAny class DisableAndroidResourcesRule : DocumentedRule() { @@ -69,13 +70,16 @@ class DisableAndroidResourcesRule : DocumentedRule - downstream.dependentProject.sourceSets.keys + downstream.project(project.projectCache) + .sourceSets + .keys .any any2@{ sourceSetName -> val rName = project.androidRDeclaredNameForSourceSetName(sourceSetName) ?: return@any2 false - val refsForSourceSet = downstream.dependentProject + val refsForSourceSet = project.projectCache + .getValue(downstream.dependentProjectPath) .androidResourceReferencesForSourceSetName(sourceSetName) val resourceDeclarations = project diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableViewBindingRule.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableViewBindingRule.kt index 686406656c..c6d06c3e6c 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableViewBindingRule.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/DisableViewBindingRule.kt @@ -22,6 +22,7 @@ import modulecheck.config.ChecksSettings import modulecheck.core.rule.android.DisableViewBindingGenerationFinding import modulecheck.finding.FindingName import modulecheck.project.McProject +import modulecheck.project.project import modulecheck.utils.any import modulecheck.utils.lazyDeferred @@ -71,7 +72,7 @@ class DisableViewBindingRule : DocumentedRule diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/InheritedDependencyRule.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/InheritedDependencyRule.kt index 600d4e8f65..d61de24fac 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/InheritedDependencyRule.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/InheritedDependencyRule.kt @@ -22,13 +22,13 @@ import modulecheck.core.InheritedDependencyFinding import modulecheck.core.context.asApiOrImplementation import modulecheck.core.internal.uses import modulecheck.finding.FindingName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.SourceSetDependency import modulecheck.parsing.gradle.model.SourceSetName +import modulecheck.parsing.gradle.model.TransitiveProjectDependency import modulecheck.parsing.gradle.model.sortedByInheritance -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.toSourceSetDependency import modulecheck.project.McProject -import modulecheck.project.SourceSetDependency -import modulecheck.project.TransitiveProjectDependency -import modulecheck.project.toSourceSetDependency import modulecheck.utils.flatMapToSet import modulecheck.utils.mapAsync @@ -76,7 +76,7 @@ class InheritedDependencyRule : DocumentedRule() { // Projects shouldn't inherit themselves. This false-positive can happen if a test // fixture/utilities module depends upon a module, and that module uses the test module in // testImplementation. - .filterNot { transitive -> transitive.contributed.project == project } + .filterNot { transitive -> transitive.contributed.path == project.path } .flatMap { transitive -> /* @@ -139,7 +139,7 @@ class InheritedDependencyRule : DocumentedRule() { return@any false } - upstreamCpd.project == contributed.project && + upstreamCpd.path == contributed.path && contributed.isTestFixture == upstreamCpd.isTestFixture } diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/MultiRuleFindingFactory.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/MultiRuleFindingFactory.kt index cb5510125f..0d5e25ad24 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/MultiRuleFindingFactory.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/MultiRuleFindingFactory.kt @@ -22,8 +22,8 @@ import modulecheck.core.OverShotDependencyFinding import modulecheck.finding.AddsDependency import modulecheck.finding.Finding import modulecheck.finding.ModifiesProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredDependency import modulecheck.parsing.gradle.model.SourceSetName -import modulecheck.project.ConfiguredDependency import modulecheck.project.McProject import modulecheck.rule.FindingFactory import modulecheck.rule.ModuleCheckRule diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKaptPluginRule.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKaptPluginRule.kt index 0599df6561..45d7dc1df9 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKaptPluginRule.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKaptPluginRule.kt @@ -25,8 +25,8 @@ import modulecheck.core.context.unusedKaptProcessors import modulecheck.core.kapt.defaultKaptMatchers import modulecheck.finding.Finding import modulecheck.finding.FindingName +import modulecheck.parsing.gradle.model.PluginDefinition import modulecheck.project.McProject -import modulecheck.project.PluginDefinition class UnusedKaptPluginRule( private val settings: ModuleCheckSettings diff --git a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKotlinAndroidExtensionsRule.kt b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKotlinAndroidExtensionsRule.kt index d74de5060b..d5ee408e08 100644 --- a/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKotlinAndroidExtensionsRule.kt +++ b/modulecheck-core/src/main/kotlin/modulecheck/core/rule/UnusedKotlinAndroidExtensionsRule.kt @@ -19,9 +19,9 @@ import modulecheck.api.context.referencesForSourceSetName import modulecheck.config.ChecksSettings import modulecheck.core.UnusedPluginFinding import modulecheck.finding.FindingName +import modulecheck.parsing.gradle.model.PluginDefinition import modulecheck.parsing.source.asExplicitKotlinReference import modulecheck.project.McProject -import modulecheck.project.PluginDefinition import modulecheck.utils.any const val KOTLIN_ANDROID_EXTENSIONS_PLUGIN_ID = "org.jetbrains.kotlin.android.extensions" diff --git a/modulecheck-core/src/test/kotlin/modulecheck/core/InheritedDependenciesTest.kt b/modulecheck-core/src/test/kotlin/modulecheck/core/InheritedDependenciesTest.kt index bf23d4b10c..6ed8c782a9 100644 --- a/modulecheck-core/src/test/kotlin/modulecheck/core/InheritedDependenciesTest.kt +++ b/modulecheck-core/src/test/kotlin/modulecheck/core/InheritedDependenciesTest.kt @@ -364,6 +364,432 @@ class InheritedDependenciesTest : RunnerTest() { ) } + // https://github.com/RBusarow/ModuleCheck/issues/569 + @Test + fun `inherited with same-config token with type-safe accessor should also use type-safe accessor`() { + + val lib1 = kotlinProject(":lib1") { + addKotlinSource( + """ + package com.modulecheck.lib1 + + open class Lib1Class + """.trimIndent() + ) + } + + val lib2 = kotlinProject(":lib2") { + addDependency(ConfigurationName.api, lib1) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + api(project(path = ":lib1")) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib2 + + import com.modulecheck.lib1.Lib1Class + + open class Lib2Class : Lib1Class() + """.trimIndent() + ) + } + + val lib3 = kotlinProject(":lib3") { + addDependency(ConfigurationName.api, lib2) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + api(projects.lib2) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib3 + + import com.modulecheck.lib1.Lib1Class + import com.modulecheck.lib2.Lib2Class + + val clazz = Lib1Class() + val clazz2 = Lib2Class() + """.trimIndent() + ) + } + + run().isSuccess shouldBe true + + lib3.buildFile shouldHaveText """ + plugins { + kotlin("jvm") + } + + dependencies { + api(projects.lib1) + api(projects.lib2) + } + """ + + logger.parsedReport() shouldBe listOf( + ":lib3" to listOf( + inheritedDependency( + fixed = true, + configuration = "api", + dependency = ":lib1", + source = ":lib2", + position = "6, 3" + ) + ) + ) + } + + // https://github.com/RBusarow/ModuleCheck/issues/569 + @Test + fun `inherited with different-config token with type-safe accessor should also use type-safe accessor`() { + + val lib1 = kotlinProject(":lib1") { + addKotlinSource( + """ + package com.modulecheck.lib1 + + open class Lib1Class + """.trimIndent() + ) + } + + val lib2 = kotlinProject(":lib2") { + addDependency(ConfigurationName.api, lib1) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + api(project(path = ":lib1")) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib2 + + import com.modulecheck.lib1.Lib1Class + + open class Lib2Class : Lib1Class() + """.trimIndent() + ) + } + + val lib3 = kotlinProject(":lib3") { + addDependency(ConfigurationName.implementation, lib2) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + implementation(projects.lib2) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib3 + + import com.modulecheck.lib1.Lib1Class + import com.modulecheck.lib2.Lib2Class + + val clazz = Lib1Class() + private val clazz2 = Lib2Class() + """.trimIndent() + ) + } + + run().isSuccess shouldBe true + + lib3.buildFile shouldHaveText """ + plugins { + kotlin("jvm") + } + + dependencies { + api(projects.lib1) + implementation(projects.lib2) + } + """ + + logger.parsedReport() shouldBe listOf( + ":lib3" to listOf( + inheritedDependency( + fixed = true, + configuration = "api", + dependency = ":lib1", + source = ":lib2", + position = "6, 3" + ) + ) + ) + } + + @Test + fun `inherited with different-config tokens with mixed accessor types but type-safe source should use type-safe`() { + + val lib1 = kotlinProject(":lib1") { + addKotlinSource( + """ + package com.modulecheck.lib1 + + open class Lib1Class + """.trimIndent() + ) + } + + val lib2 = kotlinProject(":lib2") { + addDependency(ConfigurationName.api, lib1) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + api(project(path = ":lib1")) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib2 + + import com.modulecheck.lib1.Lib1Class + + open class Lib2Class : Lib1Class() + """.trimIndent() + ) + } + + val lib3 = kotlinProject(":lib3") { + addDependency(ConfigurationName.api, lib1) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + api(project(path = ":lib1")) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib3 + + import com.modulecheck.lib1.Lib1Class + + open class Lib3Class : Lib1Class() + """.trimIndent() + ) + } + + val lib4 = kotlinProject(":lib4") { + addDependency(ConfigurationName.implementation, lib2) + addDependency(ConfigurationName.implementation, lib3) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + implementation(projects.lib2) + implementation(project(path = ":lib3")) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib4 + + import com.modulecheck.lib1.Lib1Class + import com.modulecheck.lib2.Lib2Class + import com.modulecheck.lib3.Lib3Class + + val clazz = Lib1Class() + private val clazz2 = Lib2Class() + private val clazz3 = Lib3Class() + """.trimIndent() + ) + } + + run().isSuccess shouldBe true + + lib4.buildFile shouldHaveText """ + plugins { + kotlin("jvm") + } + + dependencies { + api(projects.lib1) + implementation(projects.lib2) + implementation(project(path = ":lib3")) + } + """ + + logger.parsedReport() shouldBe listOf( + ":lib4" to listOf( + inheritedDependency( + fixed = true, + configuration = "api", + dependency = ":lib1", + source = ":lib2", + position = "6, 3" + ) + ) + ) + } + + @Test + fun `inherited with different-config tokens with mixed accessor types but path source should use path`() { + + val lib1 = kotlinProject(":lib1") { + addKotlinSource( + """ + package com.modulecheck.lib1 + + open class Lib1Class + """.trimIndent() + ) + } + + val lib2 = kotlinProject(":lib2") { + addDependency(ConfigurationName.api, lib1) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + api(project(path = ":lib1")) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib2 + + import com.modulecheck.lib1.Lib1Class + + open class Lib2Class : Lib1Class() + """.trimIndent() + ) + } + + val lib3 = kotlinProject(":lib3") { + addDependency(ConfigurationName.api, lib1) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + api(project(path = ":lib1")) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib3 + + import com.modulecheck.lib1.Lib1Class + + open class Lib3Class : Lib1Class() + """.trimIndent() + ) + } + + val lib4 = kotlinProject(":lib4") { + addDependency(ConfigurationName.implementation, lib2) + addDependency(ConfigurationName.implementation, lib3) + + buildFile { + """ + plugins { + kotlin("jvm") + } + + dependencies { + implementation(project(path = ":lib2")) + implementation(projects.lib3) + } + """ + } + addKotlinSource( + """ + package com.modulecheck.lib4 + + import com.modulecheck.lib1.Lib1Class + import com.modulecheck.lib2.Lib2Class + import com.modulecheck.lib3.Lib3Class + + val clazz = Lib1Class() + private val clazz2 = Lib2Class() + private val clazz3 = Lib3Class() + """.trimIndent() + ) + } + + run().isSuccess shouldBe true + + lib4.buildFile shouldHaveText """ + plugins { + kotlin("jvm") + } + + dependencies { + api(project(path = ":lib1")) + implementation(project(path = ":lib2")) + implementation(projects.lib3) + } + """ + + logger.parsedReport() shouldBe listOf( + ":lib4" to listOf( + inheritedDependency( + fixed = true, + configuration = "api", + dependency = ":lib1", + source = ":lib2", + position = "6, 3" + ) + ) + ) + } + @Test fun `inherited as api from invisible dependency with a visible unrelated api project dependency`() { diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/AddsDependency.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/AddsDependency.kt new file mode 100644 index 0000000000..8de3ef3ab9 --- /dev/null +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/AddsDependency.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021-2022 Rick Busarow + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package modulecheck.finding + +import modulecheck.finding.internal.addDependency +import modulecheck.finding.internal.closestDeclarationOrNull +import modulecheck.parsing.gradle.dsl.ModuleDependencyDeclaration +import modulecheck.parsing.gradle.dsl.createProjectDependencyDeclaration +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency + +interface AddsDependency : Fixable { + + val newDependency: ConfiguredProjectDependency + + suspend fun addDependency(): Boolean { + val token = dependentProject + .closestDeclarationOrNull( + newDependency, + matchPathFirst = false + ) as? ModuleDependencyDeclaration + + val newDeclaration = token?.copy( + newConfigName = newDependency.configurationName, + newModulePath = newDependency.path, + testFixtures = newDependency.isTestFixture + ) + ?: dependentProject.createProjectDependencyDeclaration( + configurationName = newDependency.configurationName, + projectPath = newDependency.path, + isTestFixtures = newDependency.isTestFixture + ) + + dependentProject.addDependency(newDependency, newDeclaration, token) + + return true + } +} diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Finding.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Finding.kt index f9d6264ed4..8660fd1d52 100644 --- a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Finding.kt +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Finding.kt @@ -17,8 +17,8 @@ package modulecheck.finding import modulecheck.parsing.gradle.dsl.BuildFileStatement import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.utils.LazyDeferred import java.io.File diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Fixable.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Fixable.kt index b3a6f8d395..62d296e03f 100644 --- a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Fixable.kt +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Fixable.kt @@ -15,112 +15,10 @@ package modulecheck.finding -import modulecheck.finding.Finding.FindingResult import modulecheck.finding.RemovesDependency.RemovalStrategy -import modulecheck.finding.RemovesDependency.RemovalStrategy.COMMENT -import modulecheck.finding.RemovesDependency.RemovalStrategy.DELETE -import modulecheck.finding.internal.addDependency -import modulecheck.finding.internal.closestDeclarationOrNull -import modulecheck.finding.internal.removeDependencyWithComment -import modulecheck.finding.internal.removeDependencyWithDelete -import modulecheck.finding.internal.statementOrNullIn -import modulecheck.parsing.gradle.dsl.ModuleDependencyDeclaration -import modulecheck.parsing.gradle.dsl.createProjectDependencyDeclaration -import modulecheck.project.ConfiguredDependency -import modulecheck.project.ConfiguredProjectDependency -import modulecheck.utils.LazyDeferred -import modulecheck.utils.lazyDeferred -import modulecheck.utils.safeAs - -interface Problem : - Finding, - DependencyFinding { - - val isSuppressed: LazyDeferred - get() = lazyDeferred { - statementOrNull.await()?.suppressed - ?.contains(findingName.id) - ?: false - } - - override suspend fun toResult(fixed: Boolean): FindingResult { - return FindingResult( - dependentPath = dependentPath, - findingName = findingName, - sourceOrNull = null, - configurationName = safeAs()?.configurationName?.value ?: "", - dependencyIdentifier = dependencyIdentifier, - positionOrNull = positionOrNull.await(), - buildFile = buildFile, - message = message, - fixed = fixed - ) - } -} - -interface RemovesDependency : Fixable { - - val oldDependency: ConfiguredDependency - - suspend fun removeDependency(removalStrategy: RemovalStrategy): Boolean { - - val oldDeclaration = (oldDependency as? ConfiguredProjectDependency) - ?.statementOrNullIn(dependentProject) - ?: statementOrNull.await() - ?: return false - - when (removalStrategy) { - DELETE -> dependentProject.removeDependencyWithDelete(oldDeclaration, oldDependency) - COMMENT -> dependentProject.removeDependencyWithComment( - statement = oldDeclaration, - fixLabel = fixLabel(), - configuredDependency = oldDependency - ) - } - return true - } - - enum class RemovalStrategy { - DELETE, - COMMENT - } -} - -interface AddsDependency : Fixable { - - val newDependency: ConfiguredProjectDependency - - suspend fun addDependency(): Boolean { - val token = dependentProject - .closestDeclarationOrNull( - newDependency, - matchPathFirst = false - ) as? ModuleDependencyDeclaration - - val newDeclaration = token?.copy( - newConfigName = newDependency.configurationName, - newModulePath = newDependency.path, - testFixtures = newDependency.isTestFixture - ) - ?: dependentProject.createProjectDependencyDeclaration( - configurationName = newDependency.configurationName, - projectPath = newDependency.path, - isTestFixtures = newDependency.isTestFixture - ) - - dependentProject.addDependency(newDependency, newDeclaration, token) - - return true - } -} interface ModifiesProjectDependency : RemovesDependency, AddsDependency -interface HasSource : Finding { - - val source: ConfiguredProjectDependency -} - interface Fixable : Finding, Problem { suspend fun fix(removalStrategy: RemovalStrategy): Boolean { diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Problem.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Problem.kt new file mode 100644 index 0000000000..e1dd1ef612 --- /dev/null +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Problem.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021-2022 Rick Busarow + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package modulecheck.finding + +import modulecheck.finding.Finding.FindingResult +import modulecheck.utils.LazyDeferred +import modulecheck.utils.lazyDeferred +import modulecheck.utils.safeAs + +interface Problem : + Finding, + DependencyFinding { + + val isSuppressed: LazyDeferred + get() = lazyDeferred { + statementOrNull.await()?.suppressed + ?.contains(findingName.id) + ?: false + } + + override suspend fun toResult(fixed: Boolean): FindingResult { + return FindingResult( + dependentPath = dependentPath, + findingName = findingName, + sourceOrNull = null, + configurationName = safeAs()?.configurationName?.value ?: "", + dependencyIdentifier = dependencyIdentifier, + positionOrNull = positionOrNull.await(), + buildFile = buildFile, + message = message, + fixed = fixed + ) + } +} diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/RemovesDependency.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/RemovesDependency.kt new file mode 100644 index 0000000000..352616530e --- /dev/null +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/RemovesDependency.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021-2022 Rick Busarow + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package modulecheck.finding + +import modulecheck.finding.RemovesDependency.RemovalStrategy.COMMENT +import modulecheck.finding.RemovesDependency.RemovalStrategy.DELETE +import modulecheck.finding.internal.removeDependencyWithComment +import modulecheck.finding.internal.removeDependencyWithDelete +import modulecheck.finding.internal.statementOrNullIn +import modulecheck.parsing.gradle.model.ConfiguredDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency + +interface RemovesDependency : Fixable { + + val oldDependency: ConfiguredDependency + + suspend fun removeDependency(removalStrategy: RemovalStrategy): Boolean { + + val oldDeclaration = (oldDependency as? ConfiguredProjectDependency) + ?.statementOrNullIn(dependentProject) + ?: statementOrNull.await() + ?: return false + + when (removalStrategy) { + DELETE -> dependentProject.removeDependencyWithDelete(oldDeclaration, oldDependency) + COMMENT -> dependentProject.removeDependencyWithComment( + statement = oldDeclaration, + fixLabel = fixLabel(), + configuredDependency = oldDependency + ) + } + return true + } + + enum class RemovalStrategy { + DELETE, + COMMENT + } +} diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Suppressions.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Suppressions.kt index 838030b11b..761e0d7eb1 100644 --- a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Suppressions.kt +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/Suppressions.kt @@ -16,10 +16,10 @@ package modulecheck.finding import modulecheck.parsing.gradle.dsl.HasBuildFile -import modulecheck.project.ConfiguredProjectDependency -import modulecheck.project.Dependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.Dependency +import modulecheck.parsing.gradle.model.PluginDependency import modulecheck.project.HasProjectCache -import modulecheck.project.PluginDependency class Suppressions( private val delegate: Map> @@ -56,10 +56,9 @@ suspend fun T.getSuppressions(): Suppressions block.forEach { (configuredModule, newNames) -> - val dependencyProject = projectCache.getValue(configuredModule.projectPath) val cpd = ConfiguredProjectDependency( configuredModule.configName, - dependencyProject, + configuredModule.projectPath, configuredModule.testFixtures ) diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/dependencies.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/dependencies.kt index 1ab925a030..80b064a895 100644 --- a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/dependencies.kt +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/dependencies.kt @@ -16,13 +16,13 @@ package modulecheck.finding.internal import kotlinx.coroutines.runBlocking -import modulecheck.finding.Fixable.Companion +import modulecheck.finding.Fixable import modulecheck.parsing.gradle.dsl.BuildFileStatement import modulecheck.parsing.gradle.dsl.DependencyDeclaration import modulecheck.parsing.gradle.dsl.ModuleDependencyDeclaration +import modulecheck.parsing.gradle.model.ConfiguredDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.ProjectPath -import modulecheck.project.ConfiguredDependency -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.utils.isGreaterThan import modulecheck.utils.prefixIfNot @@ -70,7 +70,17 @@ suspend fun McProject.closestDeclarationOrNull( else it.configName != newDependency.configurationName }, { it !is ModuleDependencyDeclaration }, - { (it as? ModuleDependencyDeclaration)?.projectPath?.value ?: "" } + { + // sort by module paths, but normalize between String paths and type-safe accessors. + // String paths will start with ":", so remove that prefix. + // Type-safe accessors will have "." separators, so replace those with ":". + // After that, everything should read like `foo:bar:baz`. + (it as? ModuleDependencyDeclaration) + ?.projectPath + ?.value + ?.removePrefix(":") + ?.replace(".", ":") ?: "" + } ) .let { sorted -> @@ -177,7 +187,7 @@ fun McProject.removeDependencyWithComment( val commented = str.replace("""(\s*)(\S.*)""".toRegex()) { mr -> val (whitespace, code) = mr.destructured - "$whitespace${Companion.INLINE_COMMENT}$code" + "$whitespace${Fixable.INLINE_COMMENT}$code" } if (index == lastIndex) { diff --git a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/mcProject.kt b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/mcProject.kt index de0dfcf299..f481744821 100644 --- a/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/mcProject.kt +++ b/modulecheck-finding/api/src/main/kotlin/modulecheck/finding/internal/mcProject.kt @@ -19,8 +19,8 @@ import modulecheck.finding.Finding.Position import modulecheck.parsing.gradle.dsl.ExternalDependencyDeclaration import modulecheck.parsing.gradle.dsl.ModuleDependencyDeclaration import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.project.ConfiguredProjectDependency -import modulecheck.project.ExternalDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ExternalDependency import modulecheck.project.McProject suspend fun ConfiguredProjectDependency.statementOrNullIn( diff --git a/modulecheck-gradle/plugin/src/main/kotlin/modulecheck/gradle/internal/GradleProjectProvider.kt b/modulecheck-gradle/plugin/src/main/kotlin/modulecheck/gradle/internal/GradleProjectProvider.kt index 1b2332faae..1cb32fd19a 100644 --- a/modulecheck-gradle/plugin/src/main/kotlin/modulecheck/gradle/internal/GradleProjectProvider.kt +++ b/modulecheck-gradle/plugin/src/main/kotlin/modulecheck/gradle/internal/GradleProjectProvider.kt @@ -28,6 +28,9 @@ import modulecheck.gradle.platforms.AndroidPlatformPluginFactory import modulecheck.gradle.platforms.JvmPlatformPluginFactory import modulecheck.gradle.platforms.internal.toJavaVersion import modulecheck.parsing.gradle.dsl.BuildFileParser +import modulecheck.parsing.gradle.model.AllProjectPathsProvider +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ExternalDependency import modulecheck.parsing.gradle.model.ProjectPath import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath import modulecheck.parsing.gradle.model.ProjectPath.TypeSafeProjectPath @@ -36,9 +39,7 @@ import modulecheck.parsing.gradle.model.asConfigurationName import modulecheck.parsing.source.AnvilGradlePlugin import modulecheck.parsing.source.JavaVersion import modulecheck.parsing.wiring.RealJvmFileProvider -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.ExternalDependencies -import modulecheck.project.ExternalDependency import modulecheck.project.McProject import modulecheck.project.ProjectCache import modulecheck.project.ProjectDependencies @@ -53,7 +54,7 @@ import javax.inject.Inject import org.gradle.api.Project as GradleProject @Suppress("LongParameterList") -@ContributesBinding(AppScope::class) +@ContributesBinding(AppScope::class, ProjectProvider::class) class GradleProjectProvider @Inject constructor( @RootGradleProject private val rootGradleProject: GradleProject, @@ -64,8 +65,9 @@ class GradleProjectProvider @Inject constructor( private val jvmFileProviderFactory: RealJvmFileProvider.Factory, private val androidPlatformPluginFactory: AndroidPlatformPluginFactory, private val jvmPlatformPluginFactory: JvmPlatformPluginFactory, - private val typeSafeProjectPathResolver: TypeSafeProjectPathResolver -) : ProjectProvider { + private val typeSafeProjectPathResolver: TypeSafeProjectPathResolver, + private val allProjectPathsProviderDelegate: AllProjectPathsProvider +) : ProjectProvider, AllProjectPathsProvider by allProjectPathsProviderDelegate { private val gradleProjects = rootGradleProject.allprojects .associateBy { StringProjectPath(it.path) } @@ -89,6 +91,10 @@ class GradleProjectProvider @Inject constructor( .map { get(StringProjectPath(it.path)) } } + override fun getAllPaths(): List { + return allProjectPathsProviderDelegate.getAllPaths() + } + override fun clearCaches() { projectCache.clearContexts() } @@ -182,7 +188,7 @@ class GradleProjectProvider @Inject constructor( ConfiguredProjectDependency( configurationName = config.name.asConfigurationName(), - project = get(StringProjectPath(it.dependencyProject.path)), + path = StringProjectPath(it.dependencyProject.path), isTestFixture = isTestFixture ) } diff --git a/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependenciesBlock.kt b/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependenciesBlock.kt index 70c551ae0d..d6bf017bec 100644 --- a/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependenciesBlock.kt +++ b/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependenciesBlock.kt @@ -20,7 +20,6 @@ import modulecheck.parsing.gradle.dsl.DependenciesBlock.ConfiguredModule import modulecheck.parsing.gradle.model.ConfigurationName import modulecheck.parsing.gradle.model.MavenCoordinates import modulecheck.parsing.gradle.model.ProjectPath -import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath interface DependenciesBlock : Block, @@ -33,7 +32,7 @@ interface DependenciesBlock : ): List fun getOrEmpty( - moduleRef: StringProjectPath, + moduleRef: ProjectPath, configName: ConfigurationName, testFixtures: Boolean ): List diff --git a/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependencyDeclaration.kt b/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependencyDeclaration.kt index 9174b2c589..9e924b3d92 100644 --- a/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependencyDeclaration.kt +++ b/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/DependencyDeclaration.kt @@ -18,6 +18,8 @@ package modulecheck.parsing.gradle.dsl import modulecheck.parsing.gradle.dsl.DependencyDeclaration.ConfigurationNameTransform import modulecheck.parsing.gradle.model.ConfigurationName import modulecheck.parsing.gradle.model.ProjectPath +import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath +import modulecheck.parsing.gradle.model.ProjectPath.TypeSafeProjectPath import modulecheck.utils.letIf import modulecheck.utils.prefixIfNot import modulecheck.utils.remove @@ -108,6 +110,11 @@ data class ModuleDependencyDeclaration( val precedingWhitespace = "^\\s*".toRegex() .find(statementWithSurroundingText)?.value ?: "" + val newProjectPathRef = when (projectPath) { + is StringProjectPath -> newModulePath.value + is TypeSafeProjectPath -> newModulePath.typeSafeValue + } + val newDeclaration = declarationText .letIf(newModule) { // strip out any config block @@ -115,7 +122,7 @@ data class ModuleDependencyDeclaration( } .addOrRemoveTestFixtures(testFixtures) .replaceFirst(configToReplace, newConfigText) - .replaceFirst(projectPath.value, newModulePath.value) + .replaceFirst(projectPath.value, newProjectPathRef) .maybeFixExtraQuotes() val newStatement = when { diff --git a/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/InvokesConfigurationNames.kt b/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/InvokesConfigurationNames.kt index 2ccc46f4f6..44b6023a27 100644 --- a/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/InvokesConfigurationNames.kt +++ b/modulecheck-parsing/gradle/dsl/api/src/main/kotlin/modulecheck/parsing/gradle/dsl/InvokesConfigurationNames.kt @@ -17,7 +17,6 @@ package modulecheck.parsing.gradle.dsl import modulecheck.parsing.gradle.model.HasConfigurations import modulecheck.parsing.gradle.model.PluginAware -import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath import java.io.File interface InvokesConfigurationNames : @@ -36,7 +35,3 @@ interface HasDependencyDeclarations : HasBuildFile, HasConfigurations { suspend fun getConfigurationInvocations(): Set } - -interface HasPath { - val path: StringProjectPath -} diff --git a/modulecheck-parsing/gradle/dsl/internal/src/main/kotlin/modulecheck/parsing/gradle/dsl/internal/AbstractDependenciesBlock.kt b/modulecheck-parsing/gradle/dsl/internal/src/main/kotlin/modulecheck/parsing/gradle/dsl/internal/AbstractDependenciesBlock.kt index 92afa090f3..928bd41067 100644 --- a/modulecheck-parsing/gradle/dsl/internal/src/main/kotlin/modulecheck/parsing/gradle/dsl/internal/AbstractDependenciesBlock.kt +++ b/modulecheck-parsing/gradle/dsl/internal/src/main/kotlin/modulecheck/parsing/gradle/dsl/internal/AbstractDependenciesBlock.kt @@ -180,7 +180,7 @@ abstract class AbstractDependenciesBlock( } override fun getOrEmpty( - moduleRef: StringProjectPath, + moduleRef: ProjectPath, configName: ConfigurationName, testFixtures: Boolean ): List { diff --git a/modulecheck-parsing/gradle/dsl/precompiled/src/main/kotlin/modulecheck/parsing/gradle/dsl/precompiled.kt b/modulecheck-parsing/gradle/dsl/precompiled/src/main/kotlin/modulecheck/parsing/gradle/dsl/precompiled.kt index 66f952b127..23aaedee58 100644 --- a/modulecheck-parsing/gradle/dsl/precompiled/src/main/kotlin/modulecheck/parsing/gradle/dsl/precompiled.kt +++ b/modulecheck-parsing/gradle/dsl/precompiled/src/main/kotlin/modulecheck/parsing/gradle/dsl/precompiled.kt @@ -18,7 +18,7 @@ package modulecheck.parsing.gradle.dsl import modulecheck.parsing.gradle.dsl.ProjectAccessor.TypeSafeProjectAccessor import modulecheck.parsing.gradle.model.ConfigurationName import modulecheck.parsing.gradle.model.PluginAware -import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath +import modulecheck.parsing.gradle.model.ProjectPath import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.gradle.model.SourceSetName.Companion import modulecheck.parsing.gradle.model.hasPrefix @@ -57,7 +57,7 @@ suspend fun ConfigurationName.isDefinitelyPrecompiledForProject(project: T): suspend fun T.createProjectDependencyDeclaration( configurationName: ConfigurationName, - projectPath: StringProjectPath, + projectPath: ProjectPath, isTestFixtures: Boolean ): ModuleDependencyDeclaration where T : PluginAware, @@ -75,6 +75,7 @@ suspend fun T.createProjectDependencyDeclaration( val projectAccessorText = projectAccessors() .any { it is TypeSafeProjectAccessor } .let { useTypeSafe -> + if (useTypeSafe) { "projects.${projectPath.typeSafeValue}" } else if (isKotlin) { diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ConfiguredDependency.kt b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ConfiguredDependency.kt similarity index 85% rename from modulecheck-project/api/src/main/kotlin/modulecheck/project/ConfiguredDependency.kt rename to modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ConfiguredDependency.kt index 33fe4a38bc..0037a19182 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ConfiguredDependency.kt +++ b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ConfiguredDependency.kt @@ -13,11 +13,21 @@ * limitations under the License. */ -package modulecheck.project +package modulecheck.parsing.gradle.model -import modulecheck.parsing.gradle.model.ConfigurationName import modulecheck.utils.mapToSet +data class ExternalDependency( + override val configurationName: ConfigurationName, + val group: String?, + val moduleName: String, + val version: String? +) : ConfiguredDependency { + val coords = MavenCoordinates(group, moduleName, version) + override val name = "${group ?: ""}:$moduleName" + val nameWithVersion = "${group ?: ""}:$moduleName:${version ?: ""}" +} + sealed interface ConfiguredDependency : Dependency { val configurationName: ConfigurationName val name: String @@ -51,8 +61,8 @@ data class PluginDependency( * @param legacyIdOrNull An older, "legacy" ID for the plugin like `kotlin-kapt` * @param precompiledAccessorOrNull A special accessor invoked like a property, with or without * backticks, like `base`. - * @param kotlinFunctionArgumentOrNull The `kotlin(...)` function used for official libraries in Kotlin DSL - * files, like `kotlin("kapt")`. + * @param kotlinFunctionArgumentOrNull The `kotlin(...)` function used for official libraries in + * Kotlin DSL files, like `kotlin("kapt")`. */ data class PluginDefinition( val name: String, diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ConfiguredProjectDependency.kt b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ConfiguredProjectDependency.kt similarity index 86% rename from modulecheck-project/api/src/main/kotlin/modulecheck/project/ConfiguredProjectDependency.kt rename to modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ConfiguredProjectDependency.kt index a95d9b29f3..c6e893178d 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ConfiguredProjectDependency.kt +++ b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ConfiguredProjectDependency.kt @@ -13,21 +13,17 @@ * limitations under the License. */ -package modulecheck.project +package modulecheck.parsing.gradle.model -import modulecheck.parsing.gradle.model.ConfigurationName import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath -import modulecheck.parsing.gradle.model.SourceSetName data class ConfiguredProjectDependency( override val configurationName: ConfigurationName, - val project: McProject, + override val path: ProjectPath, val isTestFixture: Boolean -) : ConfiguredDependency { +) : ConfiguredDependency, HasPath { - val path = project.path - - override val name = project.path.value + override val name = path.value fun declaringSourceSetName() = when { isTestFixture -> { @@ -75,19 +71,19 @@ data class TransitiveProjectDependency( } data class DownstreamDependency( - val dependentProject: McProject, + val dependentProjectPath: StringProjectPath, val configuredProjectDependency: ConfiguredProjectDependency ) data class SourceSetDependency( val sourceSetName: SourceSetName, - val path: StringProjectPath, + override val path: ProjectPath, val isTestFixture: Boolean -) +) : HasPath fun ConfiguredProjectDependency.toSourceSetDependency( sourceSetName: SourceSetName = configurationName.toSourceSetName(), - path: StringProjectPath = this@toSourceSetDependency.path, + path: ProjectPath = this@toSourceSetDependency.path, isTestFixture: Boolean = this@toSourceSetDependency.isTestFixture ) = SourceSetDependency( sourceSetName = sourceSetName, diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ExternalDependency.kt b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/HasPath.kt similarity index 54% rename from modulecheck-project/api/src/main/kotlin/modulecheck/project/ExternalDependency.kt rename to modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/HasPath.kt index d7b37bd20b..cef555e4a0 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ExternalDependency.kt +++ b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/HasPath.kt @@ -13,18 +13,8 @@ * limitations under the License. */ -package modulecheck.project +package modulecheck.parsing.gradle.model -import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.parsing.gradle.model.MavenCoordinates - -data class ExternalDependency( - override val configurationName: ConfigurationName, - val group: String?, - val moduleName: String, - val version: String? -) : ConfiguredDependency { - val coords = MavenCoordinates(group, moduleName, version) - override val name = "${group ?: ""}:$moduleName" - val nameWithVersion = "${group ?: ""}:$moduleName:${version ?: ""}" +interface HasPath { + val path: ProjectPath } diff --git a/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ProjectPath.kt b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ProjectPath.kt index 593d122b5f..102bb1011b 100644 --- a/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ProjectPath.kt +++ b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/ProjectPath.kt @@ -49,6 +49,8 @@ sealed class ProjectPath : Comparable { override fun toString(): String = value + abstract fun pathValue(typeSafeProjectPathResolver: TypeSafeProjectPathResolver): String + class StringProjectPath(override val value: String) : ProjectPath() { init { require(value.startsWith(':')) { @@ -58,12 +60,25 @@ sealed class ProjectPath : Comparable { } } - fun toTypeSafe(): TypeSafeProjectPath { + override fun toTypeSafe(): TypeSafeProjectPath { return TypeSafeProjectPath(value.typeSafeName()) } + + override fun pathValue( + typeSafeProjectPathResolver: TypeSafeProjectPathResolver + ): String = value } - class TypeSafeProjectPath(override val value: String) : ProjectPath() + class TypeSafeProjectPath(override val value: String) : ProjectPath() { + + override fun toTypeSafe(): TypeSafeProjectPath = this + + override fun pathValue(typeSafeProjectPathResolver: TypeSafeProjectPathResolver): String { + return typeSafeProjectPathResolver + .resolveStringProjectPath(this) + .pathValue(typeSafeProjectPathResolver) + } + } companion object { fun from(rawString: String): ProjectPath = if (rawString.trim().startsWith(':')) { @@ -72,6 +87,8 @@ sealed class ProjectPath : Comparable { TypeSafeProjectPath(rawString) } } + + abstract fun toTypeSafe(): TypeSafeProjectPath } internal val projectSplitRegex = "[.\\-_]".toRegex() diff --git a/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/TypeSafeProjectPathResolver.kt b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/TypeSafeProjectPathResolver.kt index df920cd38f..4015146e05 100644 --- a/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/TypeSafeProjectPathResolver.kt +++ b/modulecheck-parsing/gradle/model/api/src/main/kotlin/modulecheck/parsing/gradle/model/TypeSafeProjectPathResolver.kt @@ -16,6 +16,8 @@ package modulecheck.parsing.gradle.model import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath +import modulecheck.parsing.gradle.model.ProjectPath.TypeSafeProjectPath +import javax.inject.Inject /** * A type-safe name can't always be resolved to a String path, because dashes and pascalCase in a @@ -31,13 +33,20 @@ import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath * So, in order to convert a type-safe name into its original String path, we need the list of * actual paths to compare against. */ -fun interface TypeSafeProjectPathResolver { +class TypeSafeProjectPathResolver @Inject constructor( + private val allProjectPathsProvider: AllProjectPathsProvider +) { - fun resolveStringProjectPath( - typeSafe: ProjectPath.TypeSafeProjectPath - ): ProjectPath.StringProjectPath + private val allPaths: Map by lazy { + allProjectPathsProvider.getAllPaths() + .associateBy { it.toTypeSafe() } + } + + fun resolveStringProjectPath(typeSafe: TypeSafeProjectPath): StringProjectPath { + return allPaths.getValue(typeSafe) + } } fun interface AllProjectPathsProvider { - fun get(): List + fun getAllPaths(): List } diff --git a/modulecheck-parsing/gradle/model/impl-typesafe/src/main/kotlin/modulecheck/parsing/gradle/model/impl/RealAllProjectPathsProvider.kt b/modulecheck-parsing/gradle/model/impl-typesafe/src/main/kotlin/modulecheck/parsing/gradle/model/impl/RealAllProjectPathsProvider.kt index c02c9a2052..6f9be60771 100644 --- a/modulecheck-parsing/gradle/model/impl-typesafe/src/main/kotlin/modulecheck/parsing/gradle/model/impl/RealAllProjectPathsProvider.kt +++ b/modulecheck-parsing/gradle/model/impl-typesafe/src/main/kotlin/modulecheck/parsing/gradle/model/impl/RealAllProjectPathsProvider.kt @@ -28,8 +28,13 @@ class RealAllProjectPathsProvider @Inject constructor( @RootGradleProject private val rootGradleProject: Project ) : AllProjectPathsProvider { - override fun get(): List { - return rootGradleProject.allprojects + + private val _allPaths by lazy { + rootGradleProject.allprojects .map { ProjectPath.StringProjectPath(it.path) } } + + override fun getAllPaths(): List { + return _allPaths + } } diff --git a/modulecheck-parsing/gradle/model/impl-typesafe/src/main/kotlin/modulecheck/parsing/gradle/model/impl/RealTypeSafeProjectPathResolver.kt b/modulecheck-parsing/gradle/model/impl-typesafe/src/main/kotlin/modulecheck/parsing/gradle/model/impl/RealTypeSafeProjectPathResolver.kt deleted file mode 100644 index 304d2f70e2..0000000000 --- a/modulecheck-parsing/gradle/model/impl-typesafe/src/main/kotlin/modulecheck/parsing/gradle/model/impl/RealTypeSafeProjectPathResolver.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2021-2022 Rick Busarow - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package modulecheck.parsing.gradle.model.impl - -import com.squareup.anvil.annotations.ContributesBinding -import modulecheck.dagger.AppScope -import modulecheck.parsing.gradle.model.AllProjectPathsProvider -import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath -import modulecheck.parsing.gradle.model.ProjectPath.TypeSafeProjectPath -import modulecheck.parsing.gradle.model.TypeSafeProjectPathResolver -import javax.inject.Inject - -@ContributesBinding(AppScope::class) -class RealTypeSafeProjectPathResolver @Inject constructor( - private val allProjectPathsProvider: AllProjectPathsProvider -) : TypeSafeProjectPathResolver { - - private val allPaths: Map by lazy { - allProjectPathsProvider.get() - .associateBy { it.toTypeSafe() } - } - - override fun resolveStringProjectPath(typeSafe: TypeSafeProjectPath): StringProjectPath { - return allPaths.getValue(typeSafe) - } -} diff --git a/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidDataBindingNameProvider.kt b/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidDataBindingNameProvider.kt index 40c4268764..b56aafd2ab 100644 --- a/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidDataBindingNameProvider.kt +++ b/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidDataBindingNameProvider.kt @@ -22,6 +22,7 @@ import modulecheck.parsing.source.AndroidDataBindingDeclaredName import modulecheck.parsing.source.internal.AndroidDataBindingNameProvider import modulecheck.project.McProject import modulecheck.project.isAndroid +import modulecheck.project.project import modulecheck.utils.LazySet import modulecheck.utils.emptyLazySet import modulecheck.utils.toLazySet @@ -39,7 +40,7 @@ class RealAndroidDataBindingNameProvider constructor( val transitive = project.classpathDependencies() .get(sourceSetName) .map { tpd -> - tpd.contributed.project + tpd.contributed.project(project.projectCache) .androidDataBindingDeclarationsForSourceSetName(tpd.source.declaringSourceSetName()) } diff --git a/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidRNameProvider.kt b/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidRNameProvider.kt index d75087abd5..48c2ee9e1a 100644 --- a/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidRNameProvider.kt +++ b/modulecheck-parsing/wiring/src/main/kotlin/modulecheck/parsing/wiring/RealAndroidRNameProvider.kt @@ -22,6 +22,7 @@ import modulecheck.parsing.source.AndroidRDeclaredName import modulecheck.parsing.source.internal.AndroidRNameProvider import modulecheck.project.McProject import modulecheck.project.isAndroid +import modulecheck.project.project import modulecheck.utils.LazySet import modulecheck.utils.dataSource import modulecheck.utils.dataSourceOf @@ -53,7 +54,8 @@ class RealAndroidRNameProvider constructor( dataSource { setOfNotNull( - transitiveDependency.contributed.project + transitiveDependency.contributed + .project(project.projectCache) .androidRDeclaredNameForSourceSetName(transitiveSourceSetName) ) } diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ExternalDependencies.kt b/modulecheck-project/api/src/main/kotlin/modulecheck/project/ExternalDependencies.kt index 4d09f68f73..eeb371d12c 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ExternalDependencies.kt +++ b/modulecheck-project/api/src/main/kotlin/modulecheck/project/ExternalDependencies.kt @@ -16,6 +16,7 @@ package modulecheck.project import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ExternalDependency import modulecheck.parsing.gradle.model.SourceSetName class ExternalDependencies( diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/HasProjectCache.kt b/modulecheck-project/api/src/main/kotlin/modulecheck/project/HasProjectCache.kt index 12dcbd3d93..5adb834c88 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/HasProjectCache.kt +++ b/modulecheck-project/api/src/main/kotlin/modulecheck/project/HasProjectCache.kt @@ -15,6 +15,16 @@ package modulecheck.project +import modulecheck.parsing.gradle.model.DownstreamDependency +import modulecheck.parsing.gradle.model.HasPath + interface HasProjectCache { val projectCache: ProjectCache + + fun HasPath.project(): McProject = projectCache.getValue(path) } + +fun HasPath.project(projectCache: ProjectCache): McProject = projectCache.getValue(path) +fun DownstreamDependency.project( + projectCache: ProjectCache +): McProject = projectCache.getValue(dependentProjectPath) diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/McProject.kt b/modulecheck-project/api/src/main/kotlin/modulecheck/project/McProject.kt index 3ee122e8a4..52fff69f84 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/McProject.kt +++ b/modulecheck-project/api/src/main/kotlin/modulecheck/project/McProject.kt @@ -17,11 +17,12 @@ package modulecheck.project import modulecheck.parsing.gradle.dsl.HasBuildFile import modulecheck.parsing.gradle.dsl.HasDependencyDeclarations -import modulecheck.parsing.gradle.dsl.HasPath import modulecheck.parsing.gradle.dsl.InvokesConfigurationNames import modulecheck.parsing.gradle.model.Configurations import modulecheck.parsing.gradle.model.HasConfigurations +import modulecheck.parsing.gradle.model.HasPath import modulecheck.parsing.gradle.model.PluginAware +import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.gradle.model.SourceSets import modulecheck.parsing.gradle.model.isAndroid @@ -43,6 +44,8 @@ interface McProject : InvokesConfigurationNames, PluginAware { + override val path: StringProjectPath + override val configurations: Configurations get() = platformPlugin.configurations diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectDependencies.kt b/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectDependencies.kt index cb3e04566d..ec602d7d2e 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectDependencies.kt +++ b/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectDependencies.kt @@ -16,6 +16,7 @@ package modulecheck.project import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.SourceSetName class ProjectDependencies( diff --git a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectProvider.kt b/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectProvider.kt index fc91cb1a0f..804e084c11 100644 --- a/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectProvider.kt +++ b/modulecheck-project/api/src/main/kotlin/modulecheck/project/ProjectProvider.kt @@ -15,21 +15,27 @@ package modulecheck.project +import modulecheck.parsing.gradle.model.AllProjectPathsProvider import modulecheck.parsing.gradle.model.ProjectPath import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath +import modulecheck.parsing.gradle.model.TypeSafeProjectPathResolver import java.io.File -interface ProjectProvider : HasProjectCache { +interface ProjectProvider : HasProjectCache, AllProjectPathsProvider { fun get(path: ProjectPath): McProject fun getAll(): List - fun getAllPaths(): List = getAll().map { it.path } + override fun getAllPaths(): List = getAll().map { it.path } fun clearCaches() } +fun ProjectProvider.toTypeSafeProjectPathResolver(): TypeSafeProjectPathResolver { + return TypeSafeProjectPathResolver { getAllPaths() } +} + fun interface ProjectRoot { fun get(): File } diff --git a/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/McProjectBuilder.kt b/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/McProjectBuilder.kt index 35bfe5cab6..9d88ba5ce2 100644 --- a/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/McProjectBuilder.kt +++ b/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/McProjectBuilder.kt @@ -16,6 +16,8 @@ package modulecheck.project.test import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ExternalDependency import modulecheck.parsing.gradle.model.MavenCoordinates import modulecheck.parsing.gradle.model.ProjectPath.StringProjectPath import modulecheck.parsing.gradle.model.SourceSetName @@ -23,9 +25,7 @@ import modulecheck.parsing.psi.internal.KtFile import modulecheck.parsing.source.AnvilGradlePlugin import modulecheck.parsing.source.JavaVersion import modulecheck.parsing.source.JavaVersion.VERSION_14 -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.ExternalDependencies -import modulecheck.project.ExternalDependency import modulecheck.project.McProject import modulecheck.project.ProjectCache import modulecheck.project.ProjectDependencies @@ -60,7 +60,7 @@ data class McProjectBuilder

>( val old = projectDependencies[configurationName].orEmpty() - val cpd = ConfiguredProjectDependency(configurationName, project, asTestFixture) + val cpd = ConfiguredProjectDependency(configurationName, project.path, asTestFixture) projectDependencies[configurationName] = old + cpd } diff --git a/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/ProjectTest.kt b/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/ProjectTest.kt index 0a65530203..157b6b5a1b 100644 --- a/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/ProjectTest.kt +++ b/modulecheck-project/testing/src/main/kotlin/modulecheck/project/test/ProjectTest.kt @@ -27,6 +27,7 @@ import modulecheck.parsing.gradle.model.AndroidPlatformPlugin.AndroidDynamicFeat import modulecheck.parsing.gradle.model.AndroidPlatformPlugin.AndroidLibraryPlugin import modulecheck.parsing.gradle.model.AndroidPlatformPlugin.AndroidTestPlugin import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.parsing.gradle.model.JvmPlatformPlugin.JavaLibraryPlugin import modulecheck.parsing.gradle.model.JvmPlatformPlugin.KotlinJvmPlugin import modulecheck.parsing.gradle.model.PlatformPlugin @@ -35,7 +36,6 @@ import modulecheck.parsing.gradle.model.SourceSetName import modulecheck.parsing.source.Reference.ExplicitReference import modulecheck.parsing.source.Reference.InterpretedReference import modulecheck.parsing.source.UnqualifiedAndroidResourceReference -import modulecheck.project.ConfiguredProjectDependency import modulecheck.project.McProject import modulecheck.project.ProjectCache import modulecheck.project.ProjectProvider @@ -229,7 +229,7 @@ abstract class ProjectTest : BaseTest() { ) { val old = projectDependencies[configurationName].orEmpty() - val cpd = ConfiguredProjectDependency(configurationName, project, asTestFixture) + val cpd = ConfiguredProjectDependency(configurationName, project.path, asTestFixture) projectDependencies[configurationName] = old + cpd } @@ -266,7 +266,7 @@ abstract class ProjectTest : BaseTest() { val allDependencies = project.classpathDependencies().all().map { it.contributed } .plus(project.projectDependencies.values.flatten()) - .map { dependency -> dependency.declarations() } + .map { dependency -> dependency.declarations(projectCache) } .plus(thisProjectDeclarations) .let { lazySet(it) } .map { it.name } diff --git a/modulecheck-reporting/graphviz/build.gradle.kts b/modulecheck-reporting/graphviz/build.gradle.kts index 8d8482022d..953f357d0c 100644 --- a/modulecheck-reporting/graphviz/build.gradle.kts +++ b/modulecheck-reporting/graphviz/build.gradle.kts @@ -26,8 +26,8 @@ dependencies { api(project(path = ":modulecheck-api")) api(project(path = ":modulecheck-config:api")) + api(project(path = ":modulecheck-parsing:gradle:model:api")) - implementation(project(path = ":modulecheck-parsing:gradle:model:api")) implementation(project(path = ":modulecheck-project:api")) implementation(project(path = ":modulecheck-utils")) diff --git a/modulecheck-reporting/graphviz/src/main/kotlin/modulecheck/reporting/graphviz/GraphvizFactory.kt b/modulecheck-reporting/graphviz/src/main/kotlin/modulecheck/reporting/graphviz/GraphvizFactory.kt index f65e7af355..86b3397ace 100644 --- a/modulecheck-reporting/graphviz/src/main/kotlin/modulecheck/reporting/graphviz/GraphvizFactory.kt +++ b/modulecheck-reporting/graphviz/src/main/kotlin/modulecheck/reporting/graphviz/GraphvizFactory.kt @@ -22,7 +22,9 @@ import modulecheck.api.context.ProjectDepth import modulecheck.api.context.depthForSourceSetName import modulecheck.api.context.sourceSetDependencies import modulecheck.parsing.gradle.model.ConfigurationName +import modulecheck.parsing.gradle.model.ProjectPath import modulecheck.parsing.gradle.model.SourceSetName +import modulecheck.parsing.gradle.model.TypeSafeProjectPathResolver import modulecheck.project.McProject import modulecheck.project.isAndroid import modulecheck.reporting.graphviz.GraphvizFactory.Color.ANDROID_GREEN @@ -32,7 +34,9 @@ import modulecheck.reporting.graphviz.GraphvizFactory.Color.IMPLEMENTATION_GREEN import modulecheck.reporting.graphviz.GraphvizFactory.Color.JAVA_ORANGE import javax.inject.Inject -class GraphvizFactory @Inject constructor() { +class GraphvizFactory @Inject constructor( + private val typeSafeProjectPathResolver: TypeSafeProjectPathResolver +) { suspend fun create(root: ProjectDepth): String = buildString { @@ -110,7 +114,7 @@ class GraphvizFactory @Inject constructor() { appendLine( "${dependentProject.pathString()} " + "-> " + - "${cpd.project.pathString()} " + + "${cpd.path.pathString(typeSafeProjectPathResolver)} " + "[style = bold; color = \"${lineColor.value}\"];" ) } @@ -145,7 +149,7 @@ class GraphvizFactory @Inject constructor() { return sourceSetDependencies() .get(sourceSetName) .distinct() - .map { it.contributed.project } + .map { it.contributed.project() } .let { deps -> if (includeSelf) { deps + this @@ -156,6 +160,10 @@ class GraphvizFactory @Inject constructor() { .distinct() } + private fun ProjectPath.pathString( + typeSafeProjectPathResolver: TypeSafeProjectPathResolver + ): String = "\"${pathValue(typeSafeProjectPathResolver)}\"" + private fun McProject.pathString(): String = "\"${this.path.value}\"" enum class Color(val value: String) { diff --git a/modulecheck-reporting/sarif/src/test/kotlin/modulecheck/reporting/sarif/SarifReportTest.kt b/modulecheck-reporting/sarif/src/test/kotlin/modulecheck/reporting/sarif/SarifReportTest.kt index 5013258a85..50793d0151 100644 --- a/modulecheck-reporting/sarif/src/test/kotlin/modulecheck/reporting/sarif/SarifReportTest.kt +++ b/modulecheck-reporting/sarif/src/test/kotlin/modulecheck/reporting/sarif/SarifReportTest.kt @@ -25,7 +25,7 @@ import modulecheck.core.rule.ModuleCheckRuleFactory import modulecheck.finding.Finding import modulecheck.finding.FindingName import modulecheck.parsing.gradle.model.ConfigurationName -import modulecheck.project.ConfiguredProjectDependency +import modulecheck.parsing.gradle.model.ConfiguredProjectDependency import modulecheck.rule.ModuleCheckRule import modulecheck.runtime.test.RunnerTest import modulecheck.testing.getPrivateFieldByName @@ -63,7 +63,7 @@ class SarifReportTest : RunnerTest() { val finding = UnusedDependencyFinding( findingName = FindingName("unused-dependency"), dependentProject = p2, - oldDependency = ConfiguredProjectDependency(ConfigurationName.api, p1, false), + oldDependency = ConfiguredProjectDependency(ConfigurationName.api, p1.path, false), dependencyIdentifier = p1.path.value, configurationName = ConfigurationName.api ).toResult(true) diff --git a/modulecheck-runtime/testing/src/main/kotlin/modulecheck/runtime/test/RunnerTest.kt b/modulecheck-runtime/testing/src/main/kotlin/modulecheck/runtime/test/RunnerTest.kt index 0aa929391d..e189398025 100644 --- a/modulecheck-runtime/testing/src/main/kotlin/modulecheck/runtime/test/RunnerTest.kt +++ b/modulecheck-runtime/testing/src/main/kotlin/modulecheck/runtime/test/RunnerTest.kt @@ -27,6 +27,7 @@ import modulecheck.finding.FindingResultFactory import modulecheck.project.McProject import modulecheck.project.ProjectProvider import modulecheck.project.test.ProjectTest +import modulecheck.project.toTypeSafeProjectPathResolver import modulecheck.reporting.checkstyle.CheckstyleReporter import modulecheck.reporting.console.ReportFactory import modulecheck.reporting.graphviz.GraphvizFactory @@ -63,7 +64,10 @@ abstract class RunnerTest : ProjectTest() { findingResultFactory: FindingResultFactory = RealFindingResultFactory(), reportFactory: ReportFactory = ReportFactory(), checkstyleReporter: CheckstyleReporter = CheckstyleReporter(), - graphvizFileWriter: GraphvizFileWriter = GraphvizFileWriter(settings, GraphvizFactory()), + graphvizFileWriter: GraphvizFileWriter = GraphvizFileWriter( + settings = settings, + graphvizFactory = GraphvizFactory(projectProvider.toTypeSafeProjectPathResolver()) + ), dispatcherProvider: DispatcherProvider = DispatcherProvider() ): Result = runBlocking {