Introduce KmFunction subject to inspect (extension) function.
Bug: 70169921
Change-Id: Ida7b85097c32eaf5bc245f83740091cfd37c0d2f
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java
index d6300f3..ab702b1 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInClasspathTypeTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.kotlin.metadata;
import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isExtension;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.not;
@@ -18,6 +19,8 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.KmClassSubject;
+import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
+import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@@ -77,10 +80,21 @@
.compile();
String pkg = getClass().getPackage().getName();
final String implClassName = pkg + ".classpath_lib_ext.Impl";
+ final String implKtClassName = pkg + ".classpath_lib_ext.ImplKt";
final String extraClassName = pkg + ".classpath_lib_ext.Extra";
compileResult.inspect(inspector -> {
assertThat(inspector.clazz(implClassName), not(isPresent()));
+ ClassSubject implKt = inspector.clazz(implKtClassName);
+ assertThat(implKt, isPresent());
+ assertThat(implKt, not(isRenamed()));
+ // API entry is kept, hence the presence of Metadata.
+ KmPackageSubject kmPackage = implKt.getKmPackage();
+ assertThat(kmPackage, isPresent());
+
+ KmFunctionSubject kmFunction = kmPackage.kmFunctionExtensionWithUniqueName("fooExt");
+ assertThat(kmFunction, isPresent());
+
ClassSubject extra = inspector.clazz(extraClassName);
assertThat(extra, isPresent());
assertThat(extra, not(isRenamed()));
@@ -132,11 +146,22 @@
.compile();
String pkg = getClass().getPackage().getName();
final String implClassName = pkg + ".classpath_lib_ext.Impl";
+ final String implKtClassName = pkg + ".classpath_lib_ext.ImplKt";
final String extraClassName = pkg + ".classpath_lib_ext.Extra";
compileResult.inspect(inspector -> {
ClassSubject impl = inspector.clazz(implClassName);
assertThat(impl, isRenamed());
+ ClassSubject implKt = inspector.clazz(implKtClassName);
+ assertThat(implKt, isPresent());
+ assertThat(implKt, not(isRenamed()));
+ // API entry is kept, hence the presence of Metadata.
+ KmPackageSubject kmPackage = implKt.getKmPackage();
+ assertThat(kmPackage, isPresent());
+
+ KmFunctionSubject kmFunction = kmPackage.kmFunctionExtensionWithUniqueName("fooExt");
+ assertThat(kmFunction, isExtension());
+
ClassSubject extra = inspector.clazz(extraClassName);
assertThat(extra, isPresent());
assertThat(extra, not(isRenamed()));
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java
index 665414a..6f9dd7f 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInExtensionTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.kotlin.metadata;
import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isExtension;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.not;
@@ -18,6 +19,8 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.KmClassSubject;
+import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
+import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@@ -71,6 +74,7 @@
String pkg = getClass().getPackage().getName();
final String superClassName = pkg + ".extension_lib.Super";
final String bClassName = pkg + ".extension_lib.B";
+ final String bKtClassName = pkg + ".extension_lib.BKt";
compileResult.inspect(inspector -> {
assertThat(inspector.clazz(superClassName), not(isPresent()));
@@ -83,7 +87,16 @@
List<ClassSubject> superTypes = kmClass.getSuperTypes();
assertTrue(superTypes.stream().noneMatch(
supertype -> supertype.getFinalDescriptor().contains("Super")));
- // TODO(b/70169921): introduce KmFunction subject and make sure extension exists.
+
+ ClassSubject bKt = inspector.clazz(bKtClassName);
+ assertThat(bKt, isPresent());
+ assertThat(bKt, not(isRenamed()));
+ // API entry is kept, hence the presence of Metadata.
+ KmPackageSubject kmPackage = bKt.getKmPackage();
+ assertThat(kmPackage, isPresent());
+
+ KmFunctionSubject kmFunction = kmPackage.kmFunctionExtensionWithUniqueName("extension");
+ assertThat(kmFunction, isExtension());
});
Path libJar = compileResult.writeToZip();
@@ -122,6 +135,7 @@
String pkg = getClass().getPackage().getName();
final String superClassName = pkg + ".extension_lib.Super";
final String bClassName = pkg + ".extension_lib.B";
+ final String bKtClassName = pkg + ".extension_lib.BKt";
compileResult.inspect(inspector -> {
ClassSubject sup = inspector.clazz(superClassName);
assertThat(sup, isPresent());
@@ -138,7 +152,16 @@
supertype -> supertype.getFinalDescriptor().contains("Super")));
assertTrue(superTypes.stream().anyMatch(
supertype -> supertype.getFinalDescriptor().equals(sup.getFinalDescriptor())));
- // TODO(b/70169921): introduce KmFunction subject and make sure extension exists.
+
+ ClassSubject bKt = inspector.clazz(bKtClassName);
+ assertThat(bKt, isPresent());
+ assertThat(bKt, not(isRenamed()));
+ // API entry is kept, hence the presence of Metadata.
+ KmPackageSubject kmPackage = bKt.getKmPackage();
+ assertThat(kmPackage, isPresent());
+
+ KmFunctionSubject kmFunction = kmPackage.kmFunctionExtensionWithUniqueName("extension");
+ assertThat(kmFunction, isExtension());
});
Path libJar = compileResult.writeToZip();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInFunctionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInFunctionTest.java
index b11d4ee..c7e5db4 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInFunctionTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRenameInFunctionTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.kotlin.metadata;
import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isExtension;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.not;
@@ -18,6 +19,8 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.KmClassSubject;
+import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
+import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@@ -70,6 +73,7 @@
String pkg = getClass().getPackage().getName();
final String superClassName = pkg + ".function_lib.Super";
final String bClassName = pkg + ".function_lib.B";
+ final String bKtClassName = pkg + ".function_lib.BKt";
compileResult.inspect(inspector -> {
assertThat(inspector.clazz(superClassName), not(isPresent()));
@@ -82,7 +86,17 @@
List<ClassSubject> superTypes = kmClass.getSuperTypes();
assertTrue(superTypes.stream().noneMatch(
supertype -> supertype.getFinalDescriptor().contains("Super")));
- // TODO(b/70169921): introduce KmFunction subject and make sure function exists.
+
+ ClassSubject bKt = inspector.clazz(bKtClassName);
+ assertThat(bKt, isPresent());
+ assertThat(bKt, not(isRenamed()));
+ // API entry is kept, hence the presence of Metadata.
+ KmPackageSubject kmPackage = bKt.getKmPackage();
+ assertThat(kmPackage, isPresent());
+
+ KmFunctionSubject kmFunction = kmPackage.kmFunctionWithUniqueName("fun");
+ assertThat(kmFunction, isPresent());
+ assertThat(kmFunction, not(isExtension()));
});
Path libJar = compileResult.writeToZip();
@@ -120,6 +134,7 @@
String pkg = getClass().getPackage().getName();
final String superClassName = pkg + ".function_lib.Super";
final String bClassName = pkg + ".function_lib.B";
+ final String bKtClassName = pkg + ".function_lib.BKt";
compileResult.inspect(inspector -> {
ClassSubject sup = inspector.clazz(superClassName);
assertThat(sup, isRenamed());
@@ -135,7 +150,17 @@
supertype -> supertype.getFinalDescriptor().contains("Super")));
assertTrue(superTypes.stream().anyMatch(
supertype -> supertype.getFinalDescriptor().equals(sup.getFinalDescriptor())));
- // TODO(b/70169921): introduce KmFunction subject and make sure function exists.
+
+ ClassSubject bKt = inspector.clazz(bKtClassName);
+ assertThat(bKt, isPresent());
+ assertThat(bKt, not(isRenamed()));
+ // API entry is kept, hence the presence of Metadata.
+ KmPackageSubject kmPackage = bKt.getKmPackage();
+ assertThat(kmPackage, isPresent());
+
+ KmFunctionSubject kmFunction = kmPackage.kmFunctionWithUniqueName("fun");
+ assertThat(kmFunction, isPresent());
+ assertThat(kmFunction, not(isExtension()));
});
Path libJar = compileResult.writeToZip();
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java
index 2704774..212dd9f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmClassSubject.java
@@ -44,6 +44,21 @@
}
@Override
+ public KmFunctionSubject kmFunctionWithUniqueName(String name) {
+ return null;
+ }
+
+ @Override
+ public KmFunctionSubject kmFunctionExtensionWithUniqueName(String name) {
+ return null;
+ }
+
+ @Override
+ public List<KmFunctionSubject> getFunctions() {
+ return null;
+ }
+
+ @Override
public List<ClassSubject> getParameterTypesInFunctions() {
return null;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
new file mode 100644
index 0000000..fb7466b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils.codeinspector;
+
+public class AbsentKmFunctionSubject extends KmFunctionSubject {
+
+ @Override
+ public boolean isPresent() {
+ return false;
+ }
+
+ @Override
+ public boolean isRenamed() {
+ return false;
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ return false;
+ }
+
+ @Override
+ public boolean isExtension() {
+ return false;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPackageSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPackageSubject.java
index 6ea407a..1fd6506 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPackageSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPackageSubject.java
@@ -3,11 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils.codeinspector;
+import com.android.tools.r8.graph.DexClass;
import java.util.List;
public class AbsentKmPackageSubject extends KmPackageSubject {
@Override
+ public DexClass getDexClass() {
+ return null;
+ }
+
+ @Override
public boolean isPresent() {
return false;
}
@@ -38,6 +44,21 @@
}
@Override
+ public KmFunctionSubject kmFunctionWithUniqueName(String name) {
+ return null;
+ }
+
+ @Override
+ public KmFunctionSubject kmFunctionExtensionWithUniqueName(String name) {
+ return null;
+ }
+
+ @Override
+ public List<KmFunctionSubject> getFunctions() {
+ return null;
+ }
+
+ @Override
public List<ClassSubject> getParameterTypesInFunctions() {
return null;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java
index 45607ed..f30a0e5 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmDeclarationContainerSubject.java
@@ -11,8 +11,14 @@
import java.util.Objects;
import java.util.stream.Collectors;
import kotlinx.metadata.KmDeclarationContainer;
+import kotlinx.metadata.KmExtensionType;
+import kotlinx.metadata.KmFunction;
+import kotlinx.metadata.KmFunctionExtensionVisitor;
+import kotlinx.metadata.KmFunctionVisitor;
import kotlinx.metadata.KmType;
import kotlinx.metadata.KmTypeVisitor;
+import kotlinx.metadata.jvm.JvmFunctionExtensionVisitor;
+import kotlinx.metadata.jvm.JvmMethodSignature;
public interface FoundKmDeclarationContainerSubject extends KmDeclarationContainerSubject {
@@ -65,6 +71,68 @@
.collect(Collectors.toList());
}
+ // TODO(b/145824437): This is a dup of KotlinMetadataJvmExtensionUtils$KmFunctionProcessor
+ class KmFunctionProcessor {
+ // Custom name via @JvmName("..."). Otherwise, null.
+ private JvmMethodSignature signature = null;
+
+ KmFunctionProcessor(KmFunction kmFunction) {
+ kmFunction.accept(new KmFunctionVisitor() {
+ @Override
+ public KmFunctionExtensionVisitor visitExtensions(KmExtensionType type) {
+ if (type != JvmFunctionExtensionVisitor.TYPE) {
+ return null;
+ }
+ return new JvmFunctionExtensionVisitor() {
+ @Override
+ public void visit(JvmMethodSignature desc) {
+ assert signature == null : signature.asString();
+ signature = desc;
+ }
+ };
+ }
+ });
+ }
+
+ JvmMethodSignature signature() {
+ return signature;
+ }
+ }
+
+ default KmFunctionSubject kmFunctionOrExtensionWithUniqueName(String name, boolean isExtension) {
+ for (KmFunction kmFunction : getKmDeclarationContainer().getFunctions()) {
+ if (KmFunctionSubject.isExtension(kmFunction) != isExtension) {
+ continue;
+ }
+ if (kmFunction.getName().equals(name)) {
+ return new FoundKmFunctionSubject(codeInspector(), kmFunction);
+ }
+ KmFunctionProcessor kmFunctionProcessor = new KmFunctionProcessor(kmFunction);
+ if (kmFunctionProcessor.signature() != null
+ && kmFunctionProcessor.signature().getName().equals(name)) {
+ return new FoundKmFunctionSubject(codeInspector(), kmFunction);
+ }
+ }
+ return new AbsentKmFunctionSubject();
+ }
+
+ @Override
+ default KmFunctionSubject kmFunctionWithUniqueName(String name) {
+ return kmFunctionOrExtensionWithUniqueName(name, false);
+ }
+
+ @Override
+ default KmFunctionSubject kmFunctionExtensionWithUniqueName(String name) {
+ return kmFunctionOrExtensionWithUniqueName(name, true);
+ }
+
+ @Override
+ default List<KmFunctionSubject> getFunctions() {
+ return getKmDeclarationContainer().getFunctions().stream()
+ .map(kmFunction -> new FoundKmFunctionSubject(codeInspector(), kmFunction))
+ .collect(Collectors.toList());
+ }
+
default ClassSubject getClassSubjectFromKmType(KmType kmType) {
String descriptor = getDescriptorFromKmType(kmType);
if (descriptor == null) {
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
new file mode 100644
index 0000000..4ee0f82
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils.codeinspector;
+
+import kotlinx.metadata.KmFunction;
+
+public class FoundKmFunctionSubject extends KmFunctionSubject {
+ private final CodeInspector codeInspector;
+ private final KmFunction kmFunction;
+
+ FoundKmFunctionSubject(CodeInspector codeInspector, KmFunction kmFunction) {
+ this.codeInspector = codeInspector;
+ this.kmFunction = kmFunction;
+ }
+
+ @Override
+ public boolean isPresent() {
+ return true;
+ }
+
+ @Override
+ public boolean isRenamed() {
+ // TODO(b/70169921): need to know the corresponding DexEncodedMethod.
+ return false;
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ // TODO(b/70169921): This should return `true` conditionally if we start synthesizing @Metadata
+ // from scratch.
+ return false;
+ }
+
+ @Override
+ public boolean isExtension() {
+ return isExtension(kmFunction);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPackageSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPackageSubject.java
index 8bc9459..b4e796c 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPackageSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPackageSubject.java
@@ -20,6 +20,11 @@
}
@Override
+ public DexClass getDexClass() {
+ return clazz;
+ }
+
+ @Override
public CodeInspector codeInspector() {
return codeInspector;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmDeclarationContainerSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmDeclarationContainerSubject.java
index d553228..677ad3d 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KmDeclarationContainerSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmDeclarationContainerSubject.java
@@ -12,6 +12,12 @@
List<String> getReturnTypeDescriptorsInProperties();
+ KmFunctionSubject kmFunctionWithUniqueName(String name);
+
+ KmFunctionSubject kmFunctionExtensionWithUniqueName(String name);
+
+ List<KmFunctionSubject> getFunctions();
+
List<ClassSubject> getParameterTypesInFunctions();
List<ClassSubject> getReturnTypesInFunctions();
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
new file mode 100644
index 0000000..ca91912
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils.codeinspector;
+
+import kotlinx.metadata.KmFunction;
+
+public abstract class KmFunctionSubject extends Subject {
+ // TODO(b/145824437): This is a dup of KotlinMetadataSynthesizer#isExtension
+ static boolean isExtension(KmFunction kmFunction) {
+ return kmFunction.getReceiverParameterType() != null;
+ }
+
+ public abstract boolean isExtension();
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmPackageSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPackageSubject.java
index 8e00ce3..af44e1f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KmPackageSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPackageSubject.java
@@ -3,5 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils.codeinspector;
+import com.android.tools.r8.graph.DexClass;
+
public abstract class KmPackageSubject extends Subject implements KmDeclarationContainerSubject {
+ public abstract DexClass getDexClass();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
index d9f11d6..b1c6958 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
@@ -61,6 +61,10 @@
type = "annotation";
} else if (subject instanceof KmClassSubject) {
type = "@Metadata.KmClass";
+ } else if (subject instanceof KmPackageSubject) {
+ type = "@Metadata.KmPackage";
+ } else if (subject instanceof KmFunctionSubject) {
+ type = "@Metadata.KmFunction";
}
return type;
}
@@ -77,6 +81,10 @@
name = ((AnnotationSubject) subject).getAnnotation().type.toSourceString();
} else if (subject instanceof KmClassSubject) {
name = ((KmClassSubject) subject).getDexClass().toSourceString();
+ } else if (subject instanceof KmPackageSubject) {
+ name = ((KmPackageSubject) subject).getDexClass().toSourceString();
+ } else if (subject instanceof KmFunctionSubject) {
+ name = ((KmFunctionSubject) subject).toString();
}
return name;
}
@@ -357,6 +365,29 @@
};
}
+ public static Matcher<KmFunctionSubject> isExtension() {
+ return new TypeSafeMatcher<KmFunctionSubject>() {
+ @Override
+ protected boolean matchesSafely(KmFunctionSubject kmFunction) {
+ return kmFunction.isPresent() && kmFunction.isExtension();
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("is extension function");
+ }
+
+ @Override
+ public void describeMismatchSafely(
+ final KmFunctionSubject kmFunction, Description description) {
+ description
+ .appendText("kmFunction ")
+ .appendValue(kmFunction)
+ .appendText(" was not");
+ }
+ };
+ }
+
public static Matcher<RetraceMethodResult> isInlineFrame() {
return new TypeSafeMatcher<RetraceMethodResult>() {
@Override