15d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis/*
24a360e3a3af230badc847867c117f605367170aaFilip Pavlis * Copyright 2017 The Android Open Source Project
35d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis *
45d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * Licensed under the Apache License, Version 2.0 (the "License");
55d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * you may not use this file except in compliance with the License.
65d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * You may obtain a copy of the License at
75d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis *
84a360e3a3af230badc847867c117f605367170aaFilip Pavlis *      http://www.apache.org/licenses/LICENSE-2.0
95d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis *
105d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * Unless required by applicable law or agreed to in writing, software
115d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * distributed under the License is distributed on an "AS IS" BASIS,
125d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * See the License for the specific language governing permissions and
144a360e3a3af230badc847867c117f605367170aaFilip Pavlis * limitations under the License.
155d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis */
165d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
17ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlispackage com.android.tools.build.jetifier.processor.transform.proguard
185d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
19ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlisimport com.android.tools.build.jetifier.processor.transform.proguard.patterns.GroupsReplacer
20ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlisimport com.android.tools.build.jetifier.processor.transform.proguard.patterns.PatternHelper
215d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlisimport java.util.regex.Pattern
225d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
235d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis/**
245d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * Parses and rewrites ProGuard rules that contain class filters. See ProGuard documentation
255d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * https://www.guardsquare.com/en/proguard/manual/usage#filters
265d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis */
274a360e3a3af230badc847867c117f605367170aaFilip Pavlisclass ProGuardClassFilterParser(private val mapper: ProGuardTypesMapper) {
285d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
295d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis    companion object {
305d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        private const val RULES = "(adaptclassstrings|dontnote|dontwarn)"
315d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis    }
325d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
335d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis    val replacer = GroupsReplacer(
345d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        pattern = PatternHelper.build("^ *-$RULES ⦅[^-]+⦆ *$", Pattern.MULTILINE),
355d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        groupsMap = listOf(
36982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis            { filter: String -> listOf(rewriteClassFilter(filter)) }
375d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        )
385d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis    )
395d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
404a360e3a3af230badc847867c117f605367170aaFilip Pavlis    private fun rewriteClassFilter(classFilter: String): String {
415d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        return classFilter
425d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis            .splitToSequence(",")
435d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis            .filterNotNull()
445d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis            .map { it.trim() }
455d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis            .filter { it.isNotEmpty() }
465d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis            .map { replaceTypeInClassFilter(it) }
47982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis            .flatten()
48982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis            .distinct()
495d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis            .joinToString(separator = ", ")
505d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis    }
515d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
52982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis    /**
53982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis     * Given a package name matcher that matches several pre-renamed class names, returns several
54982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis     * package name matches that collectively match all of the possible pos-renamed names of those
55982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis     * classes.
56982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis     */
57982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis    private fun replaceTypeInClassFilter(type: String): List<String> {
585d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        if (!type.startsWith('!')) {
595d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis            return mapper.replaceType(type)
605d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        }
615d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis
625d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis        val withoutNegation = type.substring(1, type.length)
63982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis        return mapper.replaceType(withoutNegation)
64982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis            .map { '!' + it }
65982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis            .toList()
665d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis    }
675d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis}