| /* |
| * Copyright 2020 The Bazel Authors. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.google.devtools.build.android.desugar.testing.junit; |
| |
| import static com.google.common.base.Preconditions.checkNotNull; |
| import static com.google.common.collect.ImmutableList.toImmutableList; |
| |
| import com.google.common.base.Splitter; |
| import com.google.common.collect.ImmutableList; |
| import com.google.devtools.build.android.desugar.langmodel.ClassName; |
| import com.google.devtools.build.android.desugar.langmodel.MemberUseKind; |
| import com.google.devtools.build.android.desugar.langmodel.MethodInvocationSite; |
| import com.google.devtools.build.android.desugar.langmodel.MethodKey; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Arrays; |
| import java.util.function.Predicate; |
| import java.util.regex.Pattern; |
| import org.objectweb.asm.tree.AbstractInsnNode; |
| import org.objectweb.asm.tree.MethodInsnNode; |
| import org.objectweb.asm.tree.MethodNode; |
| |
| /** Static utilities that facilities desugar testing. */ |
| public class DesugarTestHelpers { |
| |
| private DesugarTestHelpers() {} |
| |
| /** |
| * A helper method that reads file paths into an array from the JVM flag value associated with |
| * {@param jvmFlagKey}. |
| */ |
| public static Path[] getRuntimePathsFromJvmFlag(String jvmFlagKey) { |
| String jvmPropertyValue = |
| checkNotNull( |
| System.getProperty(jvmFlagKey), |
| "Expected JVM Option to be specified: -D<%s>=<YourValue>", |
| jvmFlagKey); |
| return Splitter.on(" ").trimResults().splitToList(jvmPropertyValue).stream() |
| .map(Paths::get) |
| .toArray(Path[]::new); |
| } |
| |
| /** Find all matched method invocation instructions in the given method. */ |
| public static ImmutableList<MethodInvocationSite> findMethodInvocationSites( |
| MethodNode enclosingMethod, |
| String methodOwnerRegex, |
| String methodNameRegex, |
| String methodDescRegex) { |
| Predicate<String> methodOwnerPredicate = Pattern.compile(methodOwnerRegex).asPredicate(); |
| Predicate<String> methodNamePredicate = Pattern.compile(methodNameRegex).asPredicate(); |
| Predicate<String> methodDescPredicate = Pattern.compile(methodDescRegex).asPredicate(); |
| return filterInstructions(enclosingMethod, AbstractInsnNode.METHOD_INSN).stream() |
| .map(node -> (MethodInsnNode) node) |
| .filter(node -> methodOwnerPredicate.test(node.owner)) |
| .filter(node -> methodNamePredicate.test(node.name)) |
| .filter(node -> methodDescPredicate.test(node.desc)) |
| .map( |
| node -> |
| MethodInvocationSite.builder() |
| .setInvocationKind(MemberUseKind.fromValue(node.getOpcode())) |
| .setMethod(MethodKey.create(ClassName.create(node.owner), node.name, node.desc)) |
| .setIsInterface(node.itf) |
| .build()) |
| .collect(toImmutableList()); |
| } |
| |
| public static ImmutableList<AbstractInsnNode> filterInstructions( |
| MethodNode enclosingMethod, int instructionType) { |
| return Arrays.stream(enclosingMethod.instructions.toArray()) |
| .filter(node -> node.getType() == instructionType) |
| .collect(toImmutableList()); |
| } |
| } |