Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.squareup.invert.models.js.DependenciesJsReportModel
import com.squareup.invert.models.js.DirectDependenciesJsReportModel
import com.squareup.invert.models.js.OwnershipJsReportModel
import com.squareup.invert.models.js.PluginsJsReportModel
import com.squareup.invert.models.js.StatJsReportModel
import com.squareup.invert.models.js.StatTotalAndMetadata
import com.squareup.invert.models.js.StatsJsReportModel

Expand Down Expand Up @@ -113,6 +114,21 @@ object InvertJsReportUtils {
return globalTotals
}

fun buildStatJsReportModelList(statsJsReportModel: StatsJsReportModel): Set<StatJsReportModel> {
val map = mutableMapOf<StatKey, Map<ModulePath, Stat>>()
statsJsReportModel.statsByModule.entries.forEach { (modulePath, statMap: Map<StatKey, Stat>) ->
statMap.entries.forEach { (statKey, stat) ->
map[statKey] = map.getOrDefault(statKey, emptyMap()) + (modulePath to stat)
}
}
return statsJsReportModel.statInfos.values.map { statMetadata ->
StatJsReportModel(
statInfo = statMetadata,
statsByModule = map[statMetadata.key] ?: emptyMap()
)
}.toSet()
}

/**
* Takes all [CollectedStatsForProject] collected by Invert, and creates the JS Report Model.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import com.squareup.invert.models.js.JsReportFileKey
import com.squareup.invert.models.js.MetadataJsReportModel
import com.squareup.invert.models.js.OwnershipJsReportModel
import com.squareup.invert.models.js.PluginsJsReportModel
import com.squareup.invert.models.js.StatJsReportModel
import com.squareup.invert.models.js.StatsJsReportModel
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.SetSerializer
import java.io.File

Expand All @@ -43,68 +43,77 @@ class InvertJsReportWriter(
val pluginsReport = InvertJsReportUtils.toCollectedPlugins(allPluginsData)
val modulesList = allProjectsDependencyData.map { it.path }

val statsMapData: Set<StatJsReportModel> = InvertJsReportUtils.buildStatJsReportModelList(allProjectsStatsData)
statsMapData.forEach {
writeJsFileInDir(
fileKey = JsReportFileKey.STAT.key + "_" + it.statInfo.key,
serializer = StatJsReportModel.serializer(),
value = it
)
}

val collectedDependencies = HomeJsReportModel(
modules = modulesList.sorted(),
artifacts = invertedDependencies.getAllArtifactIds().sorted(),
plugins = pluginsReport.plugins.keys.toList().sorted()
)

writeJsFileInDir(
fileKey = JsReportFileKey.METADATA,
fileKey = JsReportFileKey.METADATA.key,
serializer = MetadataJsReportModel.serializer(),
value = reportMetadata
)

writeJsFileInDir(
fileKey = JsReportFileKey.HISTORICAL_DATA,
fileKey = JsReportFileKey.HISTORICAL_DATA.key,
serializer = SetSerializer(HistoricalData.serializer()),
value = historicalData
)

writeJsFileInDir(
fileKey = JsReportFileKey.OWNERS,
fileKey = JsReportFileKey.OWNERS.key,
serializer = OwnershipJsReportModel.serializer(),
value = collectedOwnershipInfo
)

writeJsFileInDir(
fileKey = JsReportFileKey.STAT_TOTALS,
fileKey = JsReportFileKey.STAT_TOTALS.key,
serializer = CollectedStatTotalsJsReportModel.serializer(),
value = globalStatTotals
)

writeJsFileInDir(
fileKey = JsReportFileKey.STATS,
fileKey = JsReportFileKey.STATS.key,
serializer = StatsJsReportModel.serializer(),
value = allProjectsStatsData
)

writeJsFileInDir(
fileKey = JsReportFileKey.CONFIGURATIONS,
fileKey = JsReportFileKey.CONFIGURATIONS.key,
serializer = ConfigurationsJsReportModel.serializer(),
value = InvertJsReportUtils.toCollectedConfigurations(allProjectsConfigurationsData)
)

writeJsFileInDir(
fileKey = JsReportFileKey.PLUGINS,
fileKey = JsReportFileKey.PLUGINS.key,
serializer = PluginsJsReportModel.serializer(),
value = pluginsReport
)

writeJsFileInDir(
fileKey = JsReportFileKey.INVERTED_DEPENDENCIES,
fileKey = JsReportFileKey.INVERTED_DEPENDENCIES.key,
serializer = DependenciesJsReportModel.serializer(),
value = invertedDependencies
)

writeJsFileInDir(
fileKey = JsReportFileKey.DIRECT_DEPENDENCIES,
fileKey = JsReportFileKey.DIRECT_DEPENDENCIES.key,
serializer = DirectDependenciesJsReportModel.serializer(),
value = directDependencies
)

writeJsFileInDir(
fileKey = JsReportFileKey.HOME,
fileKey = JsReportFileKey.HOME.key,
serializer = HomeJsReportModel.serializer(),
value = collectedDependencies
)
Expand All @@ -131,15 +140,31 @@ class InvertJsReportWriter(
}

fun <T> writeJsFileInDir(
fileKey: JsReportFileKey,
fileKey: String,
serializer: KSerializer<T>,
value: T,
) = writeJsFile(
logger = logger,
fileKey = fileKey,
jsOutputFile = InvertFileUtils.outputFile(
directory = rootBuildHtmlReportDir,
filename = "$fileKey.js"
),
serializer = serializer,
value = value
)

fun <T> writeJsFileInDir(
fileKey: String,
jsFilename: String,
serializer: KSerializer<T>,
value: T,
) = writeJsFile(
logger = logger,
fileKey = fileKey,
jsOutputFile = InvertFileUtils.outputFile(
directory = rootBuildHtmlReportDir,
filename = fileKey.jsFilename
filename = jsFilename
),
serializer = serializer,
value = value
Expand All @@ -152,18 +177,18 @@ class InvertJsReportWriter(
* This method of variable assignment is used by the invert web ui to get around Web CORS rules.
*/
private fun invertJsGlobalVariableAssignment(
fileKey: JsReportFileKey,
fileKey: String,
value: String
): String {
return buildString {
appendLine("window.invert_report.${fileKey.key}=")
appendLine("window.invert_report[\"${fileKey}\"]=")
appendLine(value)
}
}

fun <T> writeJsFile(
logger: InvertLogger,
fileKey: JsReportFileKey,
fileKey: String,
jsOutputFile: File,
serializer: KSerializer<T>,
value: T,
Expand All @@ -180,7 +205,7 @@ class InvertJsReportWriter(
)
)
)
logger.lifecycle("Writing JavaScript ${fileKey.description} to file://$canonicalPath")
logger.lifecycle("Writing JavaScript $fileKey to file://$canonicalPath")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import com.squareup.invert.models.js.MetadataJsReportModel
import com.squareup.invert.models.js.StatTotalAndMetadata
import com.squareup.invert.models.js.StatsJsReportModel
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.SetSerializer
import java.io.File

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ typealias DependencyId = String
typealias ConfigurationName = String
typealias GradlePluginId = String
typealias ModulePath = String
typealias FileKey = String
typealias OwnerName = String
typealias GitSha = String
typealias GitBranch = String
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.squareup.invert.models.js

import com.squareup.invert.models.ModulePath
import com.squareup.invert.models.OwnerName
import com.squareup.invert.models.StatKey
import com.squareup.invert.models.StatMetadata
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum class JsReportFileKey(
OWNERS("owners", "Owners"),
METADATA("metadata", "Metadata"),
CONFIGURATIONS("configurations", "Configurations"),
STAT("stat", "Stat"),
STATS("stats", "Stats"),
STAT_TOTALS("stat_totals", "Stat Totals");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.squareup.invert.models.js

import com.squareup.invert.models.ModulePath
import com.squareup.invert.models.Stat
import com.squareup.invert.models.StatMetadata
import kotlinx.serialization.Serializable

/**
* Model for [JsReportFileKey.STATS] for Invert Web Report
*/
@Serializable
data class StatJsReportModel(
val statInfo: StatMetadata,
val statsByModule: Map<ModulePath, Stat>,
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.squareup.invert.common

import com.squareup.invert.models.FileKey
import com.squareup.invert.models.StatKey
import com.squareup.invert.models.js.CollectedStatTotalsJsReportModel
import com.squareup.invert.models.js.ConfigurationsJsReportModel
import com.squareup.invert.models.js.DependenciesJsReportModel
Expand All @@ -10,6 +12,7 @@ import com.squareup.invert.models.js.JsReportFileKey
import com.squareup.invert.models.js.MetadataJsReportModel
import com.squareup.invert.models.js.OwnershipJsReportModel
import com.squareup.invert.models.js.PluginsJsReportModel
import com.squareup.invert.models.js.StatJsReportModel
import com.squareup.invert.models.js.StatsJsReportModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
Expand All @@ -25,22 +28,30 @@ import kotlinx.coroutines.withContext
*/
class CollectedDataRepo(
private val coroutineDispatcher: CoroutineDispatcher,
private val loadFileData: suspend (JsReportFileKey, CollectedDataRepo) -> Unit = { _, _ -> },
private val loadFileData: suspend (FileKey, CollectedDataRepo) -> Unit = { _, _ -> },
) {

private val hasLoadedFile = mutableMapOf<JsReportFileKey, Boolean>()
private val hasLoadedFile = mutableMapOf<FileKey, Boolean>()

private suspend fun loadJsOfType(fileKey: JsReportFileKey) = withContext(coroutineDispatcher) {
private suspend fun loadJsOfType(fileKey: FileKey) = withContext(coroutineDispatcher) {
if (!hasLoadedFile.contains(fileKey)) {
hasLoadedFile[fileKey] = true
loadFileData(fileKey, this@CollectedDataRepo)
}
}

private suspend fun loadJsOfType(jsReportFileKey: JsReportFileKey) = withContext(coroutineDispatcher) {
loadJsOfType(jsReportFileKey.key)
}

private val _collectedPluginInfoReport: MutableStateFlow<PluginsJsReportModel?> =
MutableStateFlow(null)
val collectedPluginInfoReport: Flow<PluginsJsReportModel?> = _collectedPluginInfoReport
.onEach { loadJsOfType(JsReportFileKey.PLUGINS) }
.onEach { loadJsOfType(JsReportFileKey.PLUGINS.key) }

private val _statData = MutableStateFlow<Map<StatKey, StatJsReportModel>>(mapOf())
fun statData(statKey: StatKey): Flow<Map<StatKey, StatJsReportModel>?> = _statData
.onEach { loadJsOfType(JsReportFileKey.STAT.key + "_$statKey") }

private val _statsData = MutableStateFlow<StatsJsReportModel?>(null)
val statsData: Flow<StatsJsReportModel?> = _statsData
Expand Down Expand Up @@ -127,6 +138,12 @@ class CollectedDataRepo(
this._historicalData.value = historicalData
}

fun statUpdated(statJsReportModel: StatJsReportModel) {
this._statData.value = this._statData.value.toMutableMap().apply {
put(statJsReportModel.statInfo.key, statJsReportModel)
}
}

fun homeUpdated(data: HomeJsReportModel) {
this._home.value = data
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.squareup.invert.models.js.CollectedStatTotalsJsReportModel
import com.squareup.invert.models.js.HistoricalData
import com.squareup.invert.models.js.MetadataJsReportModel
import com.squareup.invert.models.js.PluginsJsReportModel
import com.squareup.invert.models.js.StatJsReportModel
import com.squareup.invert.models.js.StatsJsReportModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -45,10 +46,10 @@ class ReportDataRepo(

val historicalData: Flow<List<HistoricalData>?> = collectedDataRepo.historicalData.mapLatest { it }

val statInfos: Flow<Collection<StatMetadata>?> = collectedDataRepo.statsData.mapLatest { it?.statInfos?.values }

val statTotals: Flow<CollectedStatTotalsJsReportModel?> = collectedDataRepo.statTotals

val statInfos: Flow<Collection<StatMetadata>?> = statTotals.mapLatest { it?.statTotals?.values?.map { it.metadata } }

val collectedPluginInfoReport: Flow<PluginsJsReportModel?> = collectedDataRepo.collectedPluginInfoReport

val moduleToOwnerMap: Flow<Map<ModulePath, OwnerName>?> = collectedDataRepo.ownersInfo.mapLatest {
Expand Down Expand Up @@ -101,6 +102,9 @@ class ReportDataRepo(
it?.allConfigurationNames
}

fun statForKey(statKey: StatKey): Flow<StatJsReportModel?> =
collectedDataRepo.statData(statKey).mapLatest { it?.get(statKey) }

val pluginIdToAllModulesMap: Flow<Map<GradlePluginId, List<ModulePath>>?> =
collectedDataRepo.collectedPluginInfoReport
.mapLatest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,13 @@ object InvertedDependenciesReportPage : InvertReportPage<InvertedDependenciesNav
override val navRouteKClass: KClass<InvertedDependenciesNavRoute> = InvertedDependenciesNavRoute::class

override val composableContent: @Composable (InvertedDependenciesNavRoute) -> Unit = { navRoute ->
InverteDependenciesComposable(navRoute)
InvertDependenciesComposable(navRoute)
}
}


@Composable
fun InverteDependenciesComposable(
fun InvertDependenciesComposable(
navRoute: InvertedDependenciesNavRoute,
reportDataRepo: ReportDataRepo = DependencyGraph.reportDataRepo,
navRouteRepo: NavRouteRepo = DependencyGraph.navRouteRepo,
Expand All @@ -111,7 +111,6 @@ fun InverteDependenciesComposable(
BootstrapLoadingMessageWithSpinner()
return
}
println("1")
if (allConfigurationNames!!.isEmpty()) {
H1 { Text("No analyzed configurations found.") }
return
Expand All @@ -123,7 +122,6 @@ fun InverteDependenciesComposable(
if (navRoute.pluginGroupByFilter.isEmpty() || navRoute.configurations.isEmpty()) {
BootstrapJumbotron(
headerContent = {
// BootstrapIcon("exclamation-triangle", 48)
Text(" Inverted Dependency Search")
}
) {
Expand Down
Loading