diff --git a/invert-models/src/commonMain/kotlin/com/squareup/invert/models/DiContribution.kt b/invert-models/src/commonMain/kotlin/com/squareup/invert/models/DiContribution.kt deleted file mode 100644 index 33072c0..0000000 --- a/invert-models/src/commonMain/kotlin/com/squareup/invert/models/DiContribution.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.squareup.invert.models - diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/InvertReport.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/InvertReport.kt index 1939731..68d0f75 100644 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/InvertReport.kt +++ b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/InvertReport.kt @@ -15,12 +15,10 @@ import com.squareup.invert.common.pages.CodeReferencesReportPage import com.squareup.invert.common.pages.ConfigurationDetailReportPage import com.squareup.invert.common.pages.ConfigurationsReportPage import com.squareup.invert.common.pages.DependencyDiffReportPage -import com.squareup.invert.common.pages.DependencyInjectionReportPage import com.squareup.invert.common.pages.GitHubMarkdownReportPage import com.squareup.invert.common.pages.GradlePluginsReportPage import com.squareup.invert.common.pages.GradleRepositoriesReportPage import com.squareup.invert.common.pages.HomeReportPage -import com.squareup.invert.common.pages.HotwireReportPage import com.squareup.invert.common.pages.InvertedDependenciesReportPage import com.squareup.invert.common.pages.KotlinCompilerPluginsReportPage import com.squareup.invert.common.pages.LeafModulesReportPage @@ -114,11 +112,9 @@ class InvertReport( CodeReferencesReportPage, ConfigurationDetailReportPage, ConfigurationsReportPage, - DependencyInjectionReportPage, DependencyDiffReportPage, ModuleDependencyGraphReportPage, HomeReportPage, - HotwireReportPage, KotlinCompilerPluginsReportPage, LeafModulesReportPage, ModuleDetailReportPage, diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/ReportDataRepo.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/ReportDataRepo.kt index e219b43..50d48b2 100644 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/ReportDataRepo.kt +++ b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/ReportDataRepo.kt @@ -42,80 +42,6 @@ class ReportDataRepo( val statsData: Flow = collectedDataRepo.statsData - val diProvidesAndInjects: Flow> = - statsData.mapLatest { statsData: StatsJsReportModel? -> - val STAT_KEY = "DiProvidesAndInjects" - val diRowDataRows = mutableListOf() - val statsByModule: Map>? = statsData?.statsByModule - statsByModule?.forEach { (moduleGradlePath, statsDataForModule) -> - val stat = statsDataForModule[STAT_KEY] - if (stat is Stat.DiProvidesAndInjectsStat) { - stat.value.forEach { providesAndInjects -> - if (providesAndInjects.contributions.isNotEmpty()) { - providesAndInjects.contributions.forEach { contribution -> - diRowDataRows.add( - DiProvidesAndInjectsItem.Provides( - module = moduleGradlePath, - filePath = providesAndInjects.filePath, - startLine = providesAndInjects.startLine, - endLine = providesAndInjects.endLine, - type = contribution.boundType, - implementationType = contribution.boundImplementation, - scope = null, - qualifiers = listOf() - ) - ) - } - } - - if (providesAndInjects.consumptions.isNotEmpty()) { - providesAndInjects.consumptions.forEach { consumption -> - diRowDataRows.add( - DiProvidesAndInjectsItem.Injects( - module = moduleGradlePath, - filePath = providesAndInjects.filePath, - startLine = consumption.startLine, - endLine = consumption.endLine, - type = consumption.type, - qualifiers = consumption.qualifierAnnotations, - ) - ) - } - } - } - } - } - diRowDataRows - } - - - fun diProvidesAndInjects( - moduleModulePaths: List? = null, - ): Flow> = - diProvidesAndInjects.mapLatest { diProvidesAndInjects: List -> - diProvidesAndInjects.filter { - when (it) { - is DiProvidesAndInjectsItem.Injects -> moduleModulePaths?.contains(it.module) ?: true - is DiProvidesAndInjectsItem.Provides -> moduleModulePaths?.contains(it.module) ?: true - } - } - } - - fun diInjects(moduleModulePaths: List): Flow> = - diProvidesAndInjects(moduleModulePaths).mapLatest { - it.filterIsInstance().sortedBy { it.type } - } - - fun diProvides(): Flow> = - diProvidesAndInjects.mapLatest { - it.filterIsInstance().sortedBy { it.type } - } - - - fun diProvides(diKey: DiKey): Flow> = diProvides().mapLatest { providesList -> - providesList.filter { it.key == diKey } - } - val statInfos: Flow?> = collectedDataRepo.statsData.mapLatest { it?.statInfos?.values } val statTotals: Flow = collectedDataRepo.statTotals diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavGroupsRepo.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavGroupsRepo.kt index 1344aa9..726af6e 100644 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavGroupsRepo.kt +++ b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/navigation/NavGroupsRepo.kt @@ -12,9 +12,6 @@ import com.squareup.invert.common.pages.CodeReferencesReportPage import com.squareup.invert.common.pages.ConfigurationDetailNavRoute import com.squareup.invert.common.pages.ConfigurationsNavRoute import com.squareup.invert.common.pages.DependencyDiffReportPage -import com.squareup.invert.common.pages.DependencyInjectionReportPage -import com.squareup.invert.common.pages.GitHubMarkdownReportPage -import com.squareup.invert.common.pages.GithubReadMeNavRoute import com.squareup.invert.common.pages.GradlePluginsNavRoute import com.squareup.invert.common.pages.GradlePluginsReportPage import com.squareup.invert.common.pages.GradleRepositoriesReportPage @@ -54,16 +51,6 @@ class NavGroupsRepo(additionalGroups: Set) { object DefaultNavItems { - private fun gitHubContentNavItem(title: String, destinationNavRoute: NavRoute): NavItem { - return NavItem( - navPage = GitHubMarkdownReportPage.navPage, - itemTitle = title, - navIconSlug = "github", - destinationNavRoute = destinationNavRoute, - matchesCurrentNavRoute = { it == destinationNavRoute } - ) - } - val ROOT_NAV_ITEMS get() = listOf( NavPageGroup( @@ -120,29 +107,10 @@ object DefaultNavItems { NavPageGroup( "Explore", setOf( InvertedDependenciesReportPage.navPage.toNavItem(), - DependencyInjectionReportPage.navPage.toNavItem(), DependencyDiffReportPage.navPage.toNavItem(), ModuleDependencyGraphReportPage.navPage.toNavItem(), ) - ), -// NavPageGroup( -// "GitHub", setOf( -// gitHubContentNavItem( -// title = "README.md", -// destinationNavRoute = GithubReadMeNavRoute( -// "square/okhttp", -// "README.md" -// ) -// ), -// gitHubContentNavItem( -// title = "OkHttp.kt", -// destinationNavRoute = GithubReadMeNavRoute( -// "square/okhttp", -// "okhttp/src/main/kotlin/okhttp3/OkHttp.kt" -// ) -// ), -// ) -// ) + ) ) } diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/DependencyInjectionReportPage.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/DependencyInjectionReportPage.kt deleted file mode 100644 index 6a2b494..0000000 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/DependencyInjectionReportPage.kt +++ /dev/null @@ -1,202 +0,0 @@ -package com.squareup.invert.common.pages - - -import PagingConstants.MAX_RESULTS -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import com.squareup.invert.common.DependencyGraph -import com.squareup.invert.common.DiProvidesAndInjectsItem -import com.squareup.invert.common.InvertReportPage -import com.squareup.invert.common.ReportDataRepo -import com.squareup.invert.common.httpsUrlForCommit -import com.squareup.invert.common.navigation.NavPage -import com.squareup.invert.common.navigation.NavRouteRepo -import com.squareup.invert.common.navigation.routes.BaseNavRoute -import com.squareup.invert.common.pages.DependencyInjectionNavRoute.Companion.parser -import kotlinx.browser.window -import kotlinx.html.ATarget -import org.jetbrains.compose.web.dom.Br -import org.jetbrains.compose.web.dom.Datalist -import org.jetbrains.compose.web.dom.H1 -import org.jetbrains.compose.web.dom.H4 -import org.jetbrains.compose.web.dom.Option -import org.jetbrains.compose.web.dom.Text -import ui.BootstrapColumn -import ui.BootstrapLoadingMessageWithSpinner -import ui.BootstrapLoadingSpinner -import ui.BootstrapRow -import ui.BootstrapSearchBox -import ui.BootstrapTable -import ui.MarkdownCellContent -import kotlin.reflect.KClass - -data class DependencyInjectionNavRoute( - val typeQuery: String? = null, - val moduleQuery: String? = null, -) : BaseNavRoute(DependencyInjectionReportPage.navPage) { - - override fun toSearchParams(): Map = toParamsWithOnlyPageId(this) - .also { params -> - moduleQuery?.let { - params[MODULE_QUERY_PARAM] = it - } - typeQuery?.let { - params[TYPE_QUERY_PARAM] = it - } - } - - companion object { - - private const val MODULE_QUERY_PARAM = "modulequery" - private const val TYPE_QUERY_PARAM = "providedquery" - - fun parser(params: Map): DependencyInjectionNavRoute { - val moduleQuery = params[MODULE_QUERY_PARAM] - val typeQuery = params[TYPE_QUERY_PARAM] - return DependencyInjectionNavRoute( - typeQuery = typeQuery, - moduleQuery = moduleQuery, - ) - } - } -} - -object DependencyInjectionReportPage : InvertReportPage { - override val navPage: NavPage = NavPage( - pageId = "dependency_injection", - displayName = "Dependency Injection", - navRouteParser = { parser(it) } - ) - - override val navRouteKClass: KClass = DependencyInjectionNavRoute::class - - override val composableContent: @Composable (DependencyInjectionNavRoute) -> Unit = { navRoute -> - DependencyInjectionComposable(navRoute) - } -} - - -@Composable -fun DependencyInjectionComposable( - diNavRoute: DependencyInjectionNavRoute, - reportDataRepo: ReportDataRepo = DependencyGraph.reportDataRepo, - navRouteRepo: NavRouteRepo = DependencyGraph.navRouteRepo, -) { - val statsData by reportDataRepo.statsData.collectAsState(null) - val allModulesOrig by reportDataRepo.allModules.collectAsState(null) - val moduleToOwnerMapFlowValue by reportDataRepo.moduleToOwnerMap.collectAsState(null) - - H1 { Text("Dependency Injection") } - - if (moduleToOwnerMapFlowValue == null) { - BootstrapLoadingSpinner() - return - } - - val moduleQuery = diNavRoute.moduleQuery ?: "" - val typeQuery = diNavRoute.typeQuery ?: "" - - if (allModulesOrig == null) { - BootstrapLoadingMessageWithSpinner("Loading Modules") - return - } - - val allModules = allModulesOrig!! - - val modulesMatchingQuery = if (moduleQuery != null && moduleQuery != ":" && moduleQuery.isNotEmpty()) { - allModules.filter { it.contains(moduleQuery) } - } else { - allModules - } - - val ALL_MODULES_DATALIST_ID = "available_modules" - Datalist({ id(ALL_MODULES_DATALIST_ID) }) { - allModules.map { Option(it) } - } - - BootstrapRow { - BootstrapColumn(12) { - BootstrapSearchBox( - query = typeQuery, - placeholderText = "Class/Interface Type Search...", - ) { - navRouteRepo.updateNavRoute(diNavRoute.copy(typeQuery = it)) - } - } - } - Br() - - val metadata by reportDataRepo.reportMetadata.collectAsState(null) - if (statsData == null || metadata == null) { - BootstrapLoadingMessageWithSpinner("Loading...") - return - } - - val gitRepoHttpsUrlForBranch = metadata!!.httpsUrlForCommit() - - val diRowDataRows by reportDataRepo.diProvidesAndInjects.collectAsState(null) - if (diRowDataRows == null) { - BootstrapLoadingMessageWithSpinner() - return - } - val columnsHeaders = mutableListOf( - "Module", - "Type", - "Qualifiers", - "File", - ) - H4 { Text("Provides") } - BootstrapTable( - rows = diRowDataRows!! - .filterIsInstance() - .filter { rowData -> - rowData.module.contains(moduleQuery) - && ( - rowData.type.contains(typeQuery, true) - || rowData.implementationType.contains(typeQuery, true) - ) - } - .map { - listOf( - it.module, - it.type + " -> " + it.implementationType, - it.qualifiers.joinToString(" "), - "${it.filePath}#L${it.startLine}-L${it.endLine}", - ) - }, - types = columnsHeaders.map { String::class }.dropLast(1).toMutableList>() - .apply { add(MarkdownCellContent::class) }, - headers = columnsHeaders, - maxResultsLimitConstant = MAX_RESULTS, - onItemClickCallback = { - val filePath = it[3] - window.open("${gitRepoHttpsUrlForBranch}/$filePath", ATarget.blank) - } - ) - H4 { Text("Injects") } - BootstrapTable( - rows = diRowDataRows!! - .filterIsInstance() - .filter { rowData -> - - rowData.module.contains(moduleQuery, true) - && rowData.type.contains(typeQuery, true) - } - .map { - listOf( - it.module, - it.type, - it.qualifiers.joinToString(" "), - "${it.filePath}#L${it.startLine}-L${it.endLine}", - ) - }, - types = columnsHeaders.map { String::class }, - headers = columnsHeaders, - maxResultsLimitConstant = MAX_RESULTS, - onItemClickCallback = { - val filePath = it[3] - window.open("${gitRepoHttpsUrlForBranch}/$filePath", ATarget.blank) - } - ) -} diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/GitHubMarkdownReportPage.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/GitHubMarkdownReportPage.kt index 5021989..624e1ee 100644 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/GitHubMarkdownReportPage.kt +++ b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/GitHubMarkdownReportPage.kt @@ -5,6 +5,8 @@ import androidx.compose.runtime.SideEffect import androidx.compose.runtime.key import com.squareup.invert.common.InvertReportPage import com.squareup.invert.common.navigation.NavPage +import com.squareup.invert.common.navigation.NavPage.NavItem +import com.squareup.invert.common.navigation.NavRoute import com.squareup.invert.common.navigation.routes.BaseNavRoute import com.squareup.invert.common.pages.GitHubMarkdownReportPage.navPage import com.squareup.invert.common.pages.GithubReadMeNavRoute.Companion.FILE_KEY @@ -37,6 +39,17 @@ data class GithubReadMeNavRoute( } object GitHubMarkdownReportPage : InvertReportPage { + + fun gitHubContentNavItem(title: String, destinationNavRoute: NavRoute): NavItem { + return NavItem( + navPage = GitHubMarkdownReportPage.navPage, + itemTitle = title, + navIconSlug = "github", + destinationNavRoute = destinationNavRoute, + matchesCurrentNavRoute = { it == destinationNavRoute } + ) + } + override val navPage: NavPage = NavPage( pageId = "github_readme", displayName = "ReadMe on GitHub", diff --git a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/HotwireReportPage.kt b/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/HotwireReportPage.kt deleted file mode 100644 index a96867c..0000000 --- a/invert-report/src/jsMain/kotlin/com/squareup/invert/common/pages/HotwireReportPage.kt +++ /dev/null @@ -1,206 +0,0 @@ -package com.squareup.invert.common.pages - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import com.squareup.invert.common.CollectedDataRepo -import com.squareup.invert.common.DependencyGraph -import com.squareup.invert.common.DiProvidesAndInjectsItem -import com.squareup.invert.common.InvertReportPage -import com.squareup.invert.common.ReportDataRepo -import com.squareup.invert.common.navigation.NavPage -import com.squareup.invert.common.navigation.NavRoute -import com.squareup.invert.common.navigation.NavRouteRepo -import com.squareup.invert.common.navigation.routes.BaseNavRoute -import com.squareup.invert.models.ModulePath -import highlightJsHighlightAll -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.launch -import org.jetbrains.compose.web.dom.Code -import org.jetbrains.compose.web.dom.Datalist -import org.jetbrains.compose.web.dom.H2 -import org.jetbrains.compose.web.dom.Hr -import org.jetbrains.compose.web.dom.Li -import org.jetbrains.compose.web.dom.Option -import org.jetbrains.compose.web.dom.Pre -import org.jetbrains.compose.web.dom.Text -import org.jetbrains.compose.web.dom.Ul -import ui.BootstrapLoadingMessageWithSpinner -import ui.BootstrapSearchBox -import kotlin.reflect.KClass - - -data class HotwireNavRoute( - val path: ModulePath? = null, -) : BaseNavRoute(HotwireReportPage.navPage) { - override fun toSearchParams() = toParamsWithOnlyPageId(this) - .also { map -> - path?.let { - map[PATH_PARAM] = path - } - } - - companion object { - private const val PATH_PARAM = "path" - - fun parser(params: Map): NavRoute { - println("PARSE ${params}") - return HotwireNavRoute( - path = params[PATH_PARAM], - ) - } - } -} - -object HotwireReportPage : InvertReportPage { - override val navPage: NavPage = NavPage( - pageId = "hotwire", - displayName = "Hotwire", - navIconSlug = "car-front-fill", - navRouteParser = { HotwireNavRoute.parser(it) } - ) - override val navRouteKClass: KClass = HotwireNavRoute::class - - override val composableContent: @Composable (HotwireNavRoute) -> Unit = { navRoute -> - HotwireComposable(navRoute) - } - -} - -// :impl (Selected Module) -// Injects com.android.Application with MyApplication from :app-provider -// Injects com.Metrics with com.MetricsImpl from :impl-metrics -// -// :app-provider -// Injects com.Logger with com.LoggerImpl from :logger-impl -// Injects com.Metrics with com.MetricsImpl from :impl-metrics -// -// :impl-metrics - -@OptIn(ExperimentalCoroutinesApi::class) -class HotwireRepo( - private val reportDataRepo: ReportDataRepo, - private val requestedModules: List -) { - - val code = MutableStateFlow("") - private val requiredModules = MutableStateFlow(requestedModules.distinct()) - private val requiredInjectsByModule = - MutableStateFlow>>(mapOf()) - - init { - CoroutineScope(Dispatchers.Default).launch { - requiredModules.collect { requiredModules -> - val injectsForRequiredModules = reportDataRepo.diInjects(requiredModules).first().distinctBy { it.key } - code.value = buildString { - requiredModules.forEach { requiredModule -> - appendLine("// $requiredModule (Selected Module)") - } - injectsForRequiredModules.onEach { - appendLine("// Injects ${it.key} as ____ from ___") - reportDataRepo.diProvides(it.key).first().forEach { provideOption -> - appendLine("// OPTION ${provideOption.implementationType} in ${provideOption.module}") - } - } - -// """ -//// :impl (Selected Module) -//// Injects com.android.Application with MyApplication from :app-provider -//// Injects com.Metrics with com.MetricsImpl from :impl-metrics -//// -//// :app-provider -//// Injects com.Logger with com.LoggerImpl from :logger-impl -//// Injects com.Metrics with com.MetricsImpl from :impl-metrics -//// -//// :impl-metrics -// """.trimIndent() - } - } - } - - - } -} - -@Composable -fun HotwireComposable( - navRoute: HotwireNavRoute, - reportDataRepo: ReportDataRepo = DependencyGraph.reportDataRepo, - navRouteRepo: NavRouteRepo = DependencyGraph.navRouteRepo, - collectRepo: CollectedDataRepo = DependencyGraph.collectedDataRepo, -) { - val allModules: List? by reportDataRepo.allModules.collectAsState(null) - - if (allModules == null) { - BootstrapLoadingMessageWithSpinner() - return - } - - H2 { Text("Hotwire") } - - val ALL_MODULES_DATALIST_ID = "all_modules_datalist" - - Datalist({ id(ALL_MODULES_DATALIST_ID) }) { allModules?.sorted()?.forEach { Option(it) } } - BootstrapSearchBox( - query = navRoute.path, - placeholderText = "", - dataListId = ALL_MODULES_DATALIST_ID, - textUpdated = { - navRouteRepo.updateNavRoute( - HotwireNavRoute( - path = it - ) - ) - } - ) - - val diInjectsForModule by reportDataRepo.diInjects(listOfNotNull(navRoute.path)).collectAsState(null) - - if (diInjectsForModule == null) { - BootstrapLoadingMessageWithSpinner() - return - } - - val gradlePath = navRoute.path - println("gradlePath: $gradlePath") - - - Hr { } - - val realCode by HotwireRepo(reportDataRepo, listOfNotNull(navRoute.path)).code.collectAsState("") - Pre({ - classes("pre-scrollable") - }) { - Code { - Text(realCode) - } - } - - -// HighlightedCodeBlock(code, "kotlin") - - Ul { - diInjectsForModule!!.filterIsInstance().forEach { - Li { Text("Requires ${it.type}") } - } - } - -} - - -@Composable -fun HighlightedCodeBlock(content: String, language: String) { - Pre { - Code({ classes(("language-$language")) }) { - Text(content) - SideEffect { - highlightJsHighlightAll() - } - } - } -} \ No newline at end of file