Skip to content

Commit 4439618

Browse files
authored
Merge pull request #18 from PatilShreyas/v1.0.0-alpha03
Release v1.0.0 alpha03
2 parents 1b13fbd + 1c8de5c commit 4439618

File tree

17 files changed

+255
-92
lines changed

17 files changed

+255
-92
lines changed

README.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,14 @@ composeReport2Html -h
7575
Once you run, here's how it looks.
7676

7777
```shell
78-
Usage: Compose Compiler Report to HTML Generator options_list
78+
Usage: Compose Compiler Report to HTML Generator ~ v1.0.0-alpha03 options_list
7979
Options:
8080
--applicationName, -app -> Application name (To be displayed in the report) (always required) { String }
81-
--overallStatsFile, -overallStatsReport -> Overall Statistics Metrics JSON file (always required) { String }
82-
--detailedStatsFile, -detailedStatsMetrics -> Detailed Statistics Metrics CSV file (always required) { String }
83-
--composableMetricsFile, -composableMetrics -> Composable Metrics TXT file (always required) { String }
84-
--classMetricsFile, -classMetrics -> Class Metrics TXT file (always required) { String }
81+
--inputDirectory, -i -> Input directory where composable report and metrics are available { String }
82+
--overallStatsFile, -overallStatsReport -> Overall Statistics Metrics JSON files (separated by commas) { String }
83+
--detailedStatsFile, -detailedStatsMetrics -> Detailed Statistics Metrics CSV files (separated by commas) { String }
84+
--composableMetricsFile, -composableMetrics -> Composable Metrics TXT files (separated by commas) { String }
85+
--classMetricsFile, -classMetrics -> Class Metrics TXT files (separated by commas) { String }
8586
--outputDirectory, -o -> Output directory name (always required) { String }
8687
--help, -h -> Usage info
8788
```
@@ -95,32 +96,35 @@ this CLI utility to feed the data.
9596
9697
To generate the report, provide details related to app, metric and report files and output directory.
9798
99+
#### 3.1 When all metric and report files are available in the same directory
100+
101+
Assuming report and metrics generated by Compose Compiler are available in one directory then you can specify path to
102+
that directory only and utility will automatically pick files.
103+
98104
```shell
99105
java -jar composeReport2Html.jar \
100-
-app <YOUR_APP_NAME> \
101-
-overallStatsReport <PATH TO *-module.json FILE> \
102-
-detailedStatsMetrics <PATH TO *-composables.csv FILE> \
103-
-composableMetrics <PATH TO *-composables.txt FILE> \
104-
-classMetrics <PATH TO *-classes.txt FILE> \
105-
-o <OUTPUT DIRECTORY PATH FOR REPORT>
106+
-app MyAppName \
107+
-i composable_report \
108+
-o htmlReportDir
106109
```
107110
108-
OR, directly use `composeReport2Html` (_if using NPM package_).
111+
#### 3.2 Provide path to individual report and metric files
109112
110-
***Example Usage:***
113+
You can provide each metric/report file individually using separate parameters.
111114
112115
```shell
113116
java -jar composeReport2Html.jar \
114-
-app NotyKT \
117+
-app MyAppName \
115118
-overallStatsReport app_release-module.json \
116119
-detailedStatsMetrics app_release-composables.csv \
117120
-composableMetrics app_release-composables.txt \
118121
-classMetrics app_release-classes.txt \
119-
-o notyReport
122+
-o htmlReportDir
120123
```
121124
122-
In the above example, it will create report with name **"NotyKT"** with specified metric and report files and finally
123-
report will be generated in the specified path i.e. `notyReport/index.html`.
125+
_(Multiple files can be provided to the single parameter by separating path with commas)_
126+
127+
***If you're using NPM package, directly use command: `composeReport2Html`***.
124128
125129
## Utility as a library
126130

cli/src/main/kotlin/dev/shreyaspatil/composeCompilerMetricsGenerator/cli/Main.kt

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,33 +23,39 @@
2323
*/
2424
package dev.shreyaspatil.composeCompilerMetricsGenerator.cli
2525

26+
import dev.shreyaspatil.composeCompilerMetricsGenerator.cli.file.ReportAndMetricsFileFinder
2627
import dev.shreyaspatil.composeCompilerMetricsGenerator.core.ComposeCompilerMetricsProvider
28+
import dev.shreyaspatil.composeCompilerMetricsGenerator.core.ComposeCompilerReportFiles
2729
import dev.shreyaspatil.composeCompilerMetricsGenerator.generator.HtmlReportGenerator
2830
import dev.shreyaspatil.composeCompilerMetricsGenerator.generator.ReportSpec
2931
import kotlinx.cli.ArgParser
3032
import kotlinx.cli.ArgType
3133
import kotlinx.cli.required
3234
import java.io.File
3335
import java.io.FileNotFoundException
36+
import java.nio.file.Path
3437
import java.nio.file.Paths
3538

3639
/**
3740
* Entry point of a CLI application
3841
*/
3942
fun main(args: Array<String>) {
40-
val arguments = CliArguments(args)
43+
val arguments = CliArguments(args, Paths.get("").toAbsolutePath())
4144

4245
val reportSpec = ReportSpec(arguments.applicationName)
46+
val inputFiles = arguments.getRequiredFiles()
4347

4448
printHeader("Generating Composable HTML Report")
4549

4650
val html = HtmlReportGenerator(
4751
reportSpec = reportSpec,
4852
metricsProvider = ComposeCompilerMetricsProvider(
49-
briefStatisticsJsonFilePath = arguments.overallStatsFile,
50-
detailedStatisticsJsonFilePath = arguments.detailedStatsFile,
51-
composableReportFilePath = arguments.composableMetricsFile,
52-
classesReportFilePath = arguments.classMetricsFile
53+
ComposeCompilerReportFiles(
54+
briefStatisticsJsonFiles = inputFiles.briefStatisticsJsonFilePath,
55+
detailedStatisticsCsvFiles = inputFiles.detailedStatisticsJsonFilePath,
56+
composableReportFiles = inputFiles.composableReportFilePath,
57+
classesReportFiles = inputFiles.classesReportFilePath
58+
)
5359
)
5460
).generateHtml()
5561

@@ -83,7 +89,7 @@ fun saveReportAsHtml(htmlContent: String, outputDirectory: String): String {
8389
/**
8490
* Parses and validates CLI arguments
8591
*/
86-
class CliArguments(args: Array<String>) {
92+
class CliArguments(args: Array<String>, private val path: Path) {
8793
private val parser = ArgParser("Compose Compiler Report to HTML Generator ~ ${Constants.VERSION}")
8894

8995
val applicationName by parser.option(
@@ -92,29 +98,35 @@ class CliArguments(args: Array<String>) {
9298
description = "Application name (To be displayed in the report)"
9399
).required()
94100

101+
val inputDirectory by parser.option(
102+
ArgType.String,
103+
shortName = "i",
104+
description = "Input directory where composable report and metrics are available"
105+
)
106+
95107
val overallStatsFile by parser.option(
96108
ArgType.String,
97109
shortName = "overallStatsReport",
98-
description = "Overall Statistics Metrics JSON file"
99-
).required()
110+
description = "Overall Statistics Metrics JSON files (separated by commas)"
111+
)
100112

101113
val detailedStatsFile by parser.option(
102114
ArgType.String,
103115
shortName = "detailedStatsMetrics",
104-
description = "Detailed Statistics Metrics CSV file"
105-
).required()
116+
description = "Detailed Statistics Metrics CSV files (separated by commas)"
117+
)
106118

107119
val composableMetricsFile by parser.option(
108120
ArgType.String,
109121
shortName = "composableMetrics",
110-
description = "Composable Metrics TXT file"
111-
).required()
122+
description = "Composable Metrics TXT files (separated by commas)"
123+
)
112124

113125
val classMetricsFile by parser.option(
114126
ArgType.String,
115127
shortName = "classMetrics",
116-
description = "Class Metrics TXT file"
117-
).required()
128+
description = "Class Metrics TXT files (separated by commas)"
129+
)
118130

119131
val outputDirectory by parser.option(
120132
ArgType.String,
@@ -129,28 +141,85 @@ class CliArguments(args: Array<String>) {
129141

130142
require(applicationName.isNotBlank()) { "Application name should not be blank" }
131143
require(outputDirectory.isNotBlank()) { "Output directory path should not be blank" }
144+
}
145+
146+
fun getRequiredFiles(): InputFiles {
147+
val directory = inputDirectory
132148

133-
printHeader("Checking files")
134-
listOf(overallStatsFile, detailedStatsFile, composableMetricsFile, classMetricsFile).forEach { filename ->
135-
ensureFileExists(filename) { fileNotExistMessage(filename) }
149+
val files = arrayOf(
150+
overallStatsFile,
151+
detailedStatsFile,
152+
composableMetricsFile,
153+
classMetricsFile
154+
)
155+
156+
if (directory != null) {
157+
ensureDirectory(directory) { "Directory '$directory' not exists" }
158+
return findRequiredFilesInDirectory(directory)
159+
} else if (files.all { !it.isNullOrBlank() }) {
160+
return InputFiles(
161+
briefStatisticsJsonFilePath = files(overallStatsFile!!),
162+
detailedStatisticsJsonFilePath = files(detailedStatsFile!!),
163+
composableReportFilePath = files(composableMetricsFile!!),
164+
classesReportFilePath = files(classMetricsFile!!)
165+
)
166+
} else {
167+
// Assume report and metric files available in the current working directory as specified in the `path`
168+
val defaultDirectory = path.toAbsolutePath().toString()
169+
return findRequiredFilesInDirectory(defaultDirectory)
136170
}
137171
}
138172

139-
companion object {
140-
fun fileNotExistMessage(filename: String) = "File not exists with name '$filename'"
173+
private fun findRequiredFilesInDirectory(directory: String): InputFiles {
174+
val finder = ReportAndMetricsFileFinder(File(Paths.get(directory).toAbsolutePath().toString()))
175+
176+
return InputFiles(
177+
briefStatisticsJsonFilePath = finder.findBriefStatisticsJsonFile(),
178+
detailedStatisticsJsonFilePath = finder.findDetailsStatisticsCsvFile(),
179+
composableReportFilePath = finder.findComposablesReportTxtFile(),
180+
classesReportFilePath = finder.findClassesReportTxtFile()
181+
)
182+
}
183+
184+
private fun files(filenames: String): List<File> {
185+
return filenames.split(",").map { ensureFileExists(it) { "File not exist: $it" } }
141186
}
187+
188+
/**
189+
*
190+
*/
191+
class InputFiles(
192+
val briefStatisticsJsonFilePath: List<File>,
193+
val detailedStatisticsJsonFilePath: List<File>,
194+
val composableReportFilePath: List<File>,
195+
val classesReportFilePath: List<File>
196+
)
142197
}
143198

144199
/**
145200
* Checks whether file with [filename] exists or not. Else throws [FileNotFoundException].
146201
*/
147-
inline fun ensureFileExists(filename: String, lazyMessage: () -> Any) {
202+
inline fun ensureFileExists(filename: String, lazyMessage: () -> Any): File {
148203
val file = File(Paths.get(filename).toAbsolutePath().toString())
149204
println("Checking file '${file.absolutePath}'")
150205
if (!file.exists()) {
151206
val message = lazyMessage()
152207
throw FileNotFoundException(message.toString())
153208
}
209+
return file
210+
}
211+
212+
/**
213+
* Checks whether directory with [name] exists or not.
214+
* Else throws [FileNotFoundException].
215+
*/
216+
inline fun ensureDirectory(name: String, lazyMessage: () -> Any) {
217+
val file = File(Paths.get(name).toAbsolutePath().toString())
218+
println("Checking directory '${file.absolutePath}'")
219+
if (!file.isDirectory) {
220+
val message = lazyMessage()
221+
throw FileNotFoundException(message.toString())
222+
}
154223
}
155224

156225
fun printHeader(header: String) = println(
@@ -161,5 +230,5 @@ fun printHeader(header: String) = println(
161230
)
162231

163232
object Constants {
164-
const val VERSION = "v1.0.0-alpha02"
233+
const val VERSION = "v1.0.0-alpha03"
165234
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2022 Shreyas Patil
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package dev.shreyaspatil.composeCompilerMetricsGenerator.cli.file
25+
26+
import java.io.File
27+
28+
/**
29+
* Finds reports and metrics files generated by Compose compiler
30+
*
31+
* @param directory The directory in which files will be searched
32+
*/
33+
class ReportAndMetricsFileFinder(directory: File) {
34+
private val allFiles = directory
35+
.listFiles()
36+
.filterNotNull()
37+
38+
fun findBriefStatisticsJsonFile(): List<File> {
39+
return allFiles.filter { it.name.endsWith(FileSuffixes.MODULE_REPORT_JSON) }
40+
}
41+
42+
fun findDetailsStatisticsCsvFile(): List<File> {
43+
return allFiles.filter { it.name.endsWith(FileSuffixes.COMPOSABLES_STATS_METRICS_CSV) }
44+
}
45+
46+
fun findComposablesReportTxtFile(): List<File> {
47+
return allFiles.filter { it.name.endsWith(FileSuffixes.COMPOSABLES_REPORT_TXT) }
48+
}
49+
50+
fun findClassesReportTxtFile(): List<File> {
51+
return allFiles.filter { it.name.endsWith(FileSuffixes.CLASSES_REPORT_TXT) }
52+
}
53+
54+
object FileSuffixes {
55+
const val CLASSES_REPORT_TXT = "-classes.txt"
56+
const val COMPOSABLES_REPORT_TXT = "-composables.txt"
57+
const val COMPOSABLES_STATS_METRICS_CSV = "-composables.csv"
58+
const val MODULE_REPORT_JSON = "-module.json"
59+
}
60+
}

0 commit comments

Comments
 (0)