From 324ffe835e863380ff617f0d1d47080a2ef65903 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 23 Apr 2018 14:58:44 +0300 Subject: [PATCH] icons.gant: check that all fallback icons are replaced with stub.png --- .../build/images/ImageSanityChecker.kt | 36 +++++++++++++++---- .../jetbrains/intellij/build/images/util.kt | 9 +++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/ImageSanityChecker.kt b/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/ImageSanityChecker.kt index 8ab81559f3ba..801736f09f75 100644 --- a/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/ImageSanityChecker.kt +++ b/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/ImageSanityChecker.kt @@ -24,6 +24,8 @@ import java.io.File import java.util.* abstract class ImageSanityCheckerBase(val projectHome: File, val ignoreSkipTag: Boolean) { + private val STUB_PNG_MD5 = "5a87124746c39b00aad480e92672eca0" // /actions/stub.svg - 16x16 + fun check(module: JpsModule) { val allImages = ImageCollector(projectHome, false, ignoreSkipTag).collect(module) @@ -34,7 +36,8 @@ abstract class ImageSanityCheckerBase(val projectHome: File, val ignoreSkipTag: checkHaveCompleteIconSet(images, module) checkHaveValidSize(images, module) checkAreNotAmbiguous(images, module) - checkSvgIconsFallbackVersions(images, module) + checkSvgFallbackVersionsAreStubIcons(images, module) + checkOverridingFallbackVersionsAreStubIcons(images, module) } private fun checkHaveRetinaVersion(images: List, module: JpsModule) { @@ -83,14 +86,35 @@ abstract class ImageSanityCheckerBase(val projectHome: File, val ignoreSkipTag: } } - private fun checkSvgIconsFallbackVersions(images: List, module: JpsModule) { - process(images, WARNING, "svg image with non-fallback legacy version", module) { image -> - val extensions = image.files.map { ImageExtension.fromFile(it) } - if (SVG !in extensions) return@process true - return@process image.files.filter { ImageExtension.fromFile(it) != SVG }.filter { ImageType.fromFile(it) != BASIC }.isEmpty() + private fun checkSvgFallbackVersionsAreStubIcons(images: List, module: JpsModule) { + process(images, WARNING, "SVG icons should use stub.png as fallback", module) { image -> + if (image.files.none { ImageExtension.fromFile(it) == SVG }) return@process true + + val legacyFiles = image.files.filter { ImageExtension.fromFile(it) != SVG } + return@process isStubFallbackVersion(legacyFiles) } } + private fun checkOverridingFallbackVersionsAreStubIcons(images: List, module: JpsModule) { + process(images, WARNING, "Overridden icons should be replaced with stub.png as fallback", module) { image -> + if (image.deprecationReplacement == null) return@process true + + return@process isStubFallbackVersion(image.files) + } + } + + private fun isStubFallbackVersion(files: List): Boolean { + if (files.isEmpty()) return true + if (files.size > 1) return false + + val file = files.single() + if (ImageType.fromFile(file) != BASIC) return false + + val md5 = md5(file) + return md5 == STUB_PNG_MD5 + } + + private fun process(images: List, severity: Severity, message: String, module: JpsModule, processor: (ImagePaths) -> Boolean) { val result = ArrayList() diff --git a/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt b/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt index de07674838a0..f93e3f8c3cdb 100644 --- a/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt +++ b/platform/build-scripts/icons/src/org/jetbrains/intellij/build/images/util.kt @@ -20,6 +20,8 @@ import com.intellij.util.SVGLoader import java.awt.Dimension import java.awt.Image import java.io.File +import java.math.BigInteger +import java.security.MessageDigest import javax.imageio.ImageIO internal val File.children: List get() = if (isDirectory) listFiles().toList() else emptyList() @@ -63,6 +65,13 @@ internal fun loadImage(file: File): Image? { } } +internal fun md5(file: File): String { + val md5 = MessageDigest.getInstance("MD5") + val bytes = file.inputStream().readBytes() + val hash = md5.digest(bytes) + return BigInteger(hash).abs().toString(16) +} + internal enum class ImageType(private val suffix: String) { BASIC(""), RETINA("@2x"), DARCULA("_dark"), RETINA_DARCULA("@2x_dark");