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 19982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlisimport com.android.tools.build.jetifier.processor.cartesianProduct 20ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlisimport com.android.tools.build.jetifier.processor.transform.proguard.patterns.GroupsReplacer 21ba381a314edcd57963ed1ac5910595e04faf29ccFilip Pavlisimport com.android.tools.build.jetifier.processor.transform.proguard.patterns.PatternHelper 225d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 235d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis/** 245d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * Parses and rewrites ProGuard rules that contain class specification. See ProGuard documentation 255d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis * https://www.guardsquare.com/en/proguard/manual/usage#classspecification 265d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis */ 274a360e3a3af230badc847867c117f605367170aaFilip Pavlisclass ProGuardClassSpecParser(private val mapper: ProGuardTypesMapper) { 285d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 295d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis companion object { 305d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val RULES = "(keep[a-z]*|whyareyoukeeping|assumenosideeffects)" 315d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val RULES_MODIFIERS = 325d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "(includedescriptorclasses|allowshrinking|allowoptimization|allowobfuscation)" 335d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 345d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val CLASS_NAME = "[\\w.$?*_%]+" 355d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val CLASS_MODIFIERS = "[!]?(public|final|abstract)" 365d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val CLASS_TYPES = "[!]?(interface|class|enum)" 375d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 385d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val ANNOTATION_TYPE = CLASS_NAME 395d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 405d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val FIELD_NAME = "[\\w?*_%]+" 415d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val FIELD_TYPE = CLASS_NAME 425d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val FIELD_MODIFIERS = 435d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "[!]?(public|private|protected|static|volatile|transient)" 445d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 455d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val METHOD_MODIFIERS = 465d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "[!]?(public|private|protected|static|synchronized|native|abstract|strictfp)" 475d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val RETURN_TYPE_NAME = CLASS_NAME 485d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val METHOD_NAME = "[\\w?*_]+" 495d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private const val ARGS = "[^)]*" 505d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis } 515d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 525d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis val replacer = GroupsReplacer( 535d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis pattern = PatternHelper.build( 545d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "-$RULES ($RULES_MODIFIERS )*(@⦅$ANNOTATION_TYPE⦆ )?($CLASS_MODIFIERS )*$CLASS_TYPES " + 555d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "⦅$CLASS_NAME⦆( (extends|implements) ⦅$CLASS_NAME⦆)?+ *( *\\{⦅[^}]*⦆\\} *)?+"), 565d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis groupsMap = listOf( 574a360e3a3af230badc847867c117f605367170aaFilip Pavlis { annotation: String -> mapper.replaceType(annotation) }, 584a360e3a3af230badc847867c117f605367170aaFilip Pavlis { className: String -> mapper.replaceType(className) }, 594a360e3a3af230badc847867c117f605367170aaFilip Pavlis { className2: String -> mapper.replaceType(className2) }, 604a360e3a3af230badc847867c117f605367170aaFilip Pavlis { bodyGroup: String -> rewriteBodyGroup(bodyGroup) } 615d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis ) 625d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis ) 635d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 645d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis private val bodyReplacers = listOf( 655d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis // [@annotation] [[!]public|private|etc...] <fields>; 665d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis GroupsReplacer( 675d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis pattern = PatternHelper.build( 685d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "^ *(@⦅$ANNOTATION_TYPE⦆ )?($FIELD_MODIFIERS )*<fields> *$"), 695d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis groupsMap = listOf( 704a360e3a3af230badc847867c117f605367170aaFilip Pavlis { annotation: String -> mapper.replaceType(annotation) } 715d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis )), 725d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 735d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis // [@annotation] [[!]public|private|etc...] fieldType fieldName; 745d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis GroupsReplacer( 755d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis pattern = PatternHelper.build( 765d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "^ *(@⦅$ANNOTATION_TYPE⦆ )?($FIELD_MODIFIERS )*(⦅$FIELD_TYPE⦆ $FIELD_NAME) *$"), 775d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis groupsMap = listOf( 784a360e3a3af230badc847867c117f605367170aaFilip Pavlis { annotation: String -> mapper.replaceType(annotation) }, 794a360e3a3af230badc847867c117f605367170aaFilip Pavlis { fieldType: String -> mapper.replaceType(fieldType) } 805d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis )), 815d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 825d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis // [@annotation] [[!]public|private|etc...] <methods>; 835d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis GroupsReplacer( 845d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis pattern = PatternHelper.build( 855d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*<methods> *$"), 865d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis groupsMap = listOf( 874a360e3a3af230badc847867c117f605367170aaFilip Pavlis { annotation: String -> mapper.replaceType(annotation) } 885d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis )), 895d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 905d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis // [@annotation] [[!]public|private|etc...] className(argumentType,...)); 915d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis GroupsReplacer( 925d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis pattern = PatternHelper.build( 935d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*⦅$CLASS_NAME⦆ *\\(⦅$ARGS⦆\\) *$"), 945d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis groupsMap = listOf( 954a360e3a3af230badc847867c117f605367170aaFilip Pavlis { annotation: String -> mapper.replaceType(annotation) }, 964a360e3a3af230badc847867c117f605367170aaFilip Pavlis { className: String -> mapper.replaceType(className) }, 974a360e3a3af230badc847867c117f605367170aaFilip Pavlis { argsType: String -> mapper.replaceMethodArgs(argsType) } 984a360e3a3af230badc847867c117f605367170aaFilip Pavlis )), 995d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 1005d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis // [@annotation] [[!]public|private|etc...] <init>(argumentType,...)); 1015d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis GroupsReplacer( 1025d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis pattern = PatternHelper.build( 1035d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*<init> *\\(⦅$ARGS⦆\\) *$"), 1045d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis groupsMap = listOf( 1054a360e3a3af230badc847867c117f605367170aaFilip Pavlis { annotation: String -> mapper.replaceType(annotation) }, 1064a360e3a3af230badc847867c117f605367170aaFilip Pavlis { argsType: String -> mapper.replaceMethodArgs(argsType) } 1075d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis )), 1085d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 1095d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis // [@annotation] [[!]public|private|etc...] returnType methodName(argumentType,...)); 1105d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis GroupsReplacer( 1114a360e3a3af230badc847867c117f605367170aaFilip Pavlis pattern = PatternHelper.build( 1124a360e3a3af230badc847867c117f605367170aaFilip Pavlis "^ *(@⦅$ANNOTATION_TYPE⦆ )?($METHOD_MODIFIERS )*" + 1135d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis "⦅$RETURN_TYPE_NAME⦆ $METHOD_NAME *\\(⦅$ARGS⦆\\) *$"), 1145d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis groupsMap = listOf( 1154a360e3a3af230badc847867c117f605367170aaFilip Pavlis { annotation: String -> mapper.replaceType(annotation) }, 1164a360e3a3af230badc847867c117f605367170aaFilip Pavlis { returnType: String -> mapper.replaceType(returnType) }, 1174a360e3a3af230badc847867c117f605367170aaFilip Pavlis { argsType: String -> mapper.replaceMethodArgs(argsType) } 1185d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis )) 1195d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis ) 1205d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 121982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis private fun rewriteBodyGroup(bodyGroup: String): List<String> { 1225d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis if (bodyGroup == "*" || bodyGroup == "**") { 123982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis return listOf(bodyGroup) 1245d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis } 1255d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis 1265d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis return bodyGroup 1275d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis .split(';') 1285d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis .map { 1295d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis for (replacer in bodyReplacers) { 1305d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis val matcher = replacer.pattern.matcher(it) 1315d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis if (matcher.matches()) { 1325d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis return@map replacer.runReplacements(matcher) 1335d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis } 1345d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis } 135982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis return@map listOf(it) 1365d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis } 137982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis .cartesianProduct() 138982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis .map { it.joinToString(separator = ";") } 139982679c45ee20f39c5da072ff6a80519ee262ef4Filip Pavlis .toList() 1405d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis } 1415d7619f3c22d5d40ff099ae5599bdbb47453d2ccFilip Pavlis}