JS DCE: disable logging by default
Based on Vladislav Saifulin's PR #4031
This commit is contained in:
@@ -76,16 +76,23 @@ class K2JSDce : CLITool<K2JSDceArguments>() {
|
|||||||
messageCollector.report(severity, message)
|
messageCollector.report(severity, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dceResult = DeadCodeElimination.run(files, includedDeclarations, logConsumer)
|
val dceResult = DeadCodeElimination.run(
|
||||||
|
files,
|
||||||
|
includedDeclarations,
|
||||||
|
arguments.printReachabilityInfo,
|
||||||
|
logConsumer
|
||||||
|
)
|
||||||
if (dceResult.status == DeadCodeEliminationStatus.FAILED) return ExitCode.COMPILATION_ERROR
|
if (dceResult.status == DeadCodeEliminationStatus.FAILED) return ExitCode.COMPILATION_ERROR
|
||||||
|
|
||||||
val reachabilitySeverity = if (arguments.printReachabilityInfo) CompilerMessageSeverity.INFO else CompilerMessageSeverity.LOGGING
|
if (arguments.printReachabilityInfo) {
|
||||||
messageCollector.report(reachabilitySeverity, "")
|
val reachabilitySeverity = CompilerMessageSeverity.INFO
|
||||||
for (node in dceResult.reachableNodes.extractReachableRoots(dceResult.context!!)) {
|
messageCollector.report(reachabilitySeverity, "")
|
||||||
printTree(
|
for (node in dceResult.reachableNodes.extractReachableRoots(dceResult.context!!)) {
|
||||||
node, { messageCollector.report(reachabilitySeverity, it) },
|
printTree(
|
||||||
printNestedMembers = false, showLocations = true
|
node, { messageCollector.report(reachabilitySeverity, it) },
|
||||||
)
|
printNestedMembers = false, showLocations = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExitCode.OK
|
return ExitCode.OK
|
||||||
|
|||||||
@@ -38,7 +38,10 @@ import org.jetbrains.kotlin.js.util.TextOutputImpl
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
|
|
||||||
class DeadCodeElimination(private val logConsumer: (DCELogLevel, String) -> Unit) {
|
class DeadCodeElimination(
|
||||||
|
private val printReachabilityInfo: Boolean,
|
||||||
|
private val logConsumer: (DCELogLevel, String) -> Unit
|
||||||
|
) {
|
||||||
val moduleMapping = mutableMapOf<JsBlock, String>()
|
val moduleMapping = mutableMapOf<JsBlock, String>()
|
||||||
private val reachableNames = mutableSetOf<String>()
|
private val reachableNames = mutableSetOf<String>()
|
||||||
|
|
||||||
@@ -61,7 +64,7 @@ class DeadCodeElimination(private val logConsumer: (DCELogLevel, String) -> Unit
|
|||||||
analyzer.moduleMapping += moduleMapping
|
analyzer.moduleMapping += moduleMapping
|
||||||
root.accept(analyzer)
|
root.accept(analyzer)
|
||||||
|
|
||||||
val usageFinder = ReachabilityTracker(context, analyzer.analysisResult, logConsumer)
|
val usageFinder = ReachabilityTracker(context, analyzer.analysisResult, logConsumer.takeIf { printReachabilityInfo })
|
||||||
root.accept(usageFinder)
|
root.accept(usageFinder)
|
||||||
|
|
||||||
for (reachableName in reachableNames) {
|
for (reachableName in reachableNames) {
|
||||||
@@ -78,10 +81,11 @@ class DeadCodeElimination(private val logConsumer: (DCELogLevel, String) -> Unit
|
|||||||
fun run(
|
fun run(
|
||||||
inputFiles: Collection<InputFile>,
|
inputFiles: Collection<InputFile>,
|
||||||
rootReachableNames: Set<String>,
|
rootReachableNames: Set<String>,
|
||||||
|
printReachabilityInfo: Boolean,
|
||||||
logConsumer: (DCELogLevel, String) -> Unit
|
logConsumer: (DCELogLevel, String) -> Unit
|
||||||
): DeadCodeEliminationResult {
|
): DeadCodeEliminationResult {
|
||||||
val program = JsProgram()
|
val program = JsProgram()
|
||||||
val dce = DeadCodeElimination(logConsumer)
|
val dce = DeadCodeElimination(printReachabilityInfo, logConsumer)
|
||||||
|
|
||||||
var hasErrors = false
|
var hasErrors = false
|
||||||
val blocks = inputFiles.map { file ->
|
val blocks = inputFiles.map { file ->
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
|
|||||||
class ReachabilityTracker(
|
class ReachabilityTracker(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val analysisResult: AnalysisResult,
|
private val analysisResult: AnalysisResult,
|
||||||
private val logConsumer: (DCELogLevel, String) -> Unit
|
private val logConsumer: ((DCELogLevel, String) -> Unit)?
|
||||||
) : RecursiveJsVisitor() {
|
) : RecursiveJsVisitor() {
|
||||||
companion object {
|
companion object {
|
||||||
private val CALL_FUNCTIONS = setOf("call", "apply")
|
private val CALL_FUNCTIONS = setOf("call", "apply")
|
||||||
@@ -237,14 +237,15 @@ class ReachabilityTracker(
|
|||||||
currentNodeWithLocation = old
|
currentNodeWithLocation = old
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun report(message: String) {
|
|
||||||
logConsumer(DCELogLevel.INFO, " ".repeat(depth) + message)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reportAndNest(message: String, dueTo: JsNode?, action: () -> Unit) {
|
private fun reportAndNest(message: String, dueTo: JsNode?, action: () -> Unit) {
|
||||||
val location = dueTo?.extractLocation()
|
if (logConsumer != null) {
|
||||||
val fullMessage = if (location != null) "$message (due to ${location.asString()})" else message
|
val indent = " ".repeat(depth)
|
||||||
report(fullMessage)
|
val fullMessage = when (val location = dueTo?.extractLocation()) {
|
||||||
|
null -> "$indent$message"
|
||||||
|
else -> "$indent$message (due to ${location.asString()})"
|
||||||
|
}
|
||||||
|
logConsumer.invoke(DCELogLevel.INFO, fullMessage)
|
||||||
|
}
|
||||||
nested(action)
|
nested(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ abstract class AbstractDceTest : TestCase() {
|
|||||||
val fileContents = file.readText()
|
val fileContents = file.readText()
|
||||||
val inputFile = InputFile(InputResource.file(filePath), null,
|
val inputFile = InputFile(InputResource.file(filePath), null,
|
||||||
File(pathToOutputDir, file.relativeTo(File(pathToTestDir)).path).path, "main")
|
File(pathToOutputDir, file.relativeTo(File(pathToTestDir)).path).path, "main")
|
||||||
val dceResult = DeadCodeElimination.run(setOf(inputFile), extractDeclarations(REQUEST_REACHABLE_PATTERN, fileContents)) { _, _ -> }
|
val dceResult = DeadCodeElimination.run(setOf(inputFile), extractDeclarations(REQUEST_REACHABLE_PATTERN, fileContents), true) { _, _ -> }
|
||||||
val reachableNodeStrings = dceResult.reachableNodes.map { it.toString().removePrefix("<unknown>.") }.toSet()
|
val reachableNodeStrings = dceResult.reachableNodes.map { it.toString().removePrefix("<unknown>.") }.toSet()
|
||||||
|
|
||||||
for (assertedDeclaration in extractDeclarations(ASSERT_REACHABLE_PATTERN, fileContents)) {
|
for (assertedDeclaration in extractDeclarations(ASSERT_REACHABLE_PATTERN, fileContents)) {
|
||||||
|
|||||||
@@ -928,7 +928,7 @@ abstract class BasicBoxTest(
|
|||||||
"kotlin-test.kotlin.test.DefaultAsserter"
|
"kotlin-test.kotlin.test.DefaultAsserter"
|
||||||
)
|
)
|
||||||
val allFilesToMinify = filesToMinify.values + kotlinJsInputFile + kotlinTestJsInputFile
|
val allFilesToMinify = filesToMinify.values + kotlinJsInputFile + kotlinTestJsInputFile
|
||||||
val dceResult = DeadCodeElimination.run(allFilesToMinify, additionalReachableNodes) { _, _ -> }
|
val dceResult = DeadCodeElimination.run(allFilesToMinify, additionalReachableNodes, true) { _, _ -> }
|
||||||
|
|
||||||
val reachableNodes = dceResult.reachableNodes
|
val reachableNodes = dceResult.reachableNodes
|
||||||
minificationThresholdChecker(reachableNodes.count { it.reachable })
|
minificationThresholdChecker(reachableNodes.count { it.reachable })
|
||||||
|
|||||||
Reference in New Issue
Block a user