Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support compact strings in the report #14

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 57 additions & 32 deletions src/jsMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ external interface JsModel {
val documentationLink: String
val totalProblemCount: Int
val diagnostics: Array<JsDiagnostic>
val dictionary: Array<String>?
}


Expand Down Expand Up @@ -152,9 +153,33 @@ data class ImportedProblem(
)


private
interface StringDictionary {
fun get(key: String): String
}


private
object NoopStringDictionary : StringDictionary {
override fun get(key: String): String = key
}


private
class DefaultStringDictionary(
private val dict: Array<String>
) : StringDictionary {

override fun get(key: String): String {
return dict[key.toInt()]
}
}


private
fun reportPageModelFromJsModel(jsModel: JsModel): ConfigurationCacheReportPage.Model {
val diagnostics = importDiagnostics(jsModel.diagnostics)
val dict = jsModel.dictionary?.let(::DefaultStringDictionary) ?: NoopStringDictionary
val diagnostics = importDiagnostics(jsModel.diagnostics, dict)
return ConfigurationCacheReportPage.Model(
cacheAction = jsModel.cacheAction,
requestedTasks = jsModel.requestedTasks,
Expand All @@ -163,16 +188,16 @@ fun reportPageModelFromJsModel(jsModel: JsModel): ConfigurationCacheReportPage.M
reportedProblems = diagnostics.problems.size,
messageTree = treeModelFor(
ProblemNode.Label("Problems grouped by message"),
problemNodesByMessage(diagnostics.problems)
problemNodesByMessage(diagnostics.problems, dict)
),
locationTree = treeModelFor(
ProblemNode.Label("Problems grouped by location"),
problemNodesByLocation(diagnostics.problems)
problemNodesByLocation(diagnostics.problems, dict)
),
reportedInputs = diagnostics.inputs.size,
inputTree = treeModelFor(
ProblemNode.Label("Inputs"),
inputNodes(diagnostics.inputs)
inputNodes(diagnostics.inputs, dict)
)
)
}
Expand All @@ -186,30 +211,30 @@ class ImportedDiagnostics(


private
fun importDiagnostics(jsDiagnostics: Array<JsDiagnostic>): ImportedDiagnostics {
fun importDiagnostics(jsDiagnostics: Array<JsDiagnostic>, dict: StringDictionary): ImportedDiagnostics {
val importedProblems = mutableListOf<ImportedProblem>()
val importedInputs = mutableListOf<ImportedProblem>()
for (diagnostic in jsDiagnostics) {
diagnostic.input?.let {
importedInputs.add(toImportedProblem(it, diagnostic))
importedInputs.add(toImportedProblem(it, diagnostic, dict))
} ?: diagnostic.problem!!.let {
importedProblems.add(toImportedProblem(it, diagnostic))
importedProblems.add(toImportedProblem(it, diagnostic, dict))
}
}
return ImportedDiagnostics(importedProblems, importedInputs)
}


private
fun toImportedProblem(label: Array<JsMessageFragment>, jsProblem: JsDiagnostic) = ImportedProblem(
fun toImportedProblem(label: Array<JsMessageFragment>, jsProblem: JsDiagnostic, dict: StringDictionary) = ImportedProblem(
jsProblem,
label.let(::toPrettyText),
toPrettyText(label, dict),
jsProblem.trace.map(::toProblemNode)
)


private
fun inputNodes(inputs: List<ImportedProblem>): Sequence<List<ProblemNode>> =
fun inputNodes(inputs: List<ImportedProblem>, dict: StringDictionary): Sequence<List<ProblemNode>> =
inputs.asSequence().map { input ->
buildList {
val message = input.message
Expand All @@ -218,7 +243,7 @@ fun inputNodes(inputs: List<ImportedProblem>): Sequence<List<ProblemNode>> =
add(
ProblemNode.Info(
ProblemNode.Label(inputType),
docLinkFor(input.problem)
docLinkFor(input.problem, dict)
)
)
add(ProblemNode.Message(inputDescription))
Expand All @@ -228,48 +253,48 @@ fun inputNodes(inputs: List<ImportedProblem>): Sequence<List<ProblemNode>> =


private
fun problemNodesByMessage(problems: List<ImportedProblem>): Sequence<List<ProblemNode>> =
fun problemNodesByMessage(problems: List<ImportedProblem>, dict: StringDictionary): Sequence<List<ProblemNode>> =
problems.asSequence().map { problem ->
buildList {
add(problemNodeFor(problem))
add(problemNodeFor(problem, dict))
addAll(problem.trace)
addExceptionNode(problem)
addExceptionNode(problem, dict)
}
}


private
fun problemNodesByLocation(problems: List<ImportedProblem>): Sequence<List<ProblemNode>> =
fun problemNodesByLocation(problems: List<ImportedProblem>, dict: StringDictionary): Sequence<List<ProblemNode>> =
problems.asSequence().map { problem ->
buildList {
addAll(problem.trace.asReversed())
add(problemNodeFor(problem))
addExceptionNode(problem)
add(problemNodeFor(problem, dict))
addExceptionNode(problem, dict)
}
}


private
fun MutableList<ProblemNode>.addExceptionNode(problem: ImportedProblem) {
exceptionNodeFor(problem.problem)?.let {
fun MutableList<ProblemNode>.addExceptionNode(problem: ImportedProblem, dict: StringDictionary) {
exceptionNodeFor(problem.problem, dict)?.let {
add(it)
}
}


private
fun problemNodeFor(problem: ImportedProblem) = errorOrWarningNodeFor(
fun problemNodeFor(problem: ImportedProblem, dict: StringDictionary) = errorOrWarningNodeFor(
problem.problem,
messageNodeFor(problem),
docLinkFor(problem.problem)
docLinkFor(problem.problem, dict)
)


private
fun toPrettyText(message: Array<JsMessageFragment>) = PrettyText(
fun toPrettyText(message: Array<JsMessageFragment>, dict: StringDictionary) = PrettyText(
message.map {
it.text?.let(PrettyText.Fragment::Text)
?: it.name?.let(PrettyText.Fragment::Reference)
it.text?.let(dict::get)?.let(PrettyText.Fragment::Text)
?: it.name?.let(dict::get)?.let(PrettyText.Fragment::Reference)
?: PrettyText.Fragment.Text("Unrecognised message fragment: ${stringify(it)}")
}
)
Expand Down Expand Up @@ -334,22 +359,22 @@ fun messageNodeFor(importedProblem: ImportedProblem) =


private
fun exceptionNodeFor(diagnostic: JsDiagnostic): ProblemNode? {
fun exceptionNodeFor(diagnostic: JsDiagnostic, dict: StringDictionary): ProblemNode? {
val error = diagnostic.error ?: return null

return ProblemNode.Exception(
summary = error.summary?.let { toPrettyText(it) },
fullText = error.parts.mapNotNull { it.textContent }.joinToString("\n"),
summary = error.summary?.let { toPrettyText(it, dict) },
fullText = error.parts.mapNotNull { it.textContent?.let(dict::get) }.joinToString("\n"),
parts = error.parts.mapNotNull { part ->
stackTracePartFor(part)
stackTracePartFor(part, dict)
}
)
}


private
fun stackTracePartFor(part: JsStackTracePart): ProblemNode.StackTracePart? {
val partText = part.textContent ?: return null
fun stackTracePartFor(part: JsStackTracePart, dict: StringDictionary): ProblemNode.StackTracePart? {
val partText = part.textContent?.let(dict::get) ?: return null
val lines = partText.lineSequence().filter { it.isNotEmpty() }.toList()
val isInternal = part.internalText != null
return ProblemNode.StackTracePart(lines, defaultViewStateFor(isInternal, lines.size))
Expand All @@ -368,8 +393,8 @@ fun defaultViewStateFor(isInternal: Boolean, linesCount: Int): Tree.ViewState? {


private
fun docLinkFor(it: JsDiagnostic): ProblemNode? =
it.documentationLink?.let { ProblemNode.Link(it, " ?") }
fun docLinkFor(it: JsDiagnostic, dict: StringDictionary): ProblemNode? =
it.documentationLink?.let(dict::get)?.let { ProblemNode.Link(it, " ?") }


private
Expand Down