JS: support enumValues<E>() and enumValueOf<E>("name") intrinsics.
This commit is contained in:
@@ -587,4 +587,17 @@ public class DescriptorUtils {
|
||||
ClassDescriptor containingClass = getContainingClass(descriptor);
|
||||
return containingClass != null && isEffectivelyExternal(containingClass);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FunctionDescriptor getFunctionByName(@NotNull MemberScope scope, @NotNull Name name) {
|
||||
Collection<DeclarationDescriptor> functions = scope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS,
|
||||
MemberScope.Companion.getALL_NAME_FILTER());
|
||||
for (DeclarationDescriptor d : functions) {
|
||||
if (d instanceof FunctionDescriptor && name.equals(d.getOriginal().getName())) {
|
||||
return (FunctionDescriptor) d;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Function not found");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1258,6 +1258,10 @@ fun main(args: Array<String>) {
|
||||
testClass<AbstractCallableReferenceInlineTests> {
|
||||
model("codegen/boxInline/callableReference/", targetBackend = TargetBackend.JS)
|
||||
}
|
||||
|
||||
testClass<AbstractEnumValuesInlineTests> {
|
||||
model("codegen/boxInline/enum/", targetBackend = TargetBackend.JS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.js.test.semantics;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/enum")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class EnumValuesInlineTestsGenerated extends AbstractEnumValuesInlineTests {
|
||||
public void testAllFilesPresentInEnum() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/enum"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("kt10569.kt")
|
||||
public void testKt10569() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/kt10569.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valueOf.kt")
|
||||
public void testValueOf() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOf.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valueOfCapturedType.kt")
|
||||
public void testValueOfCapturedType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfCapturedType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valueOfChain.kt")
|
||||
public void testValueOfChain() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfChain.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valueOfChainCapturedType.kt")
|
||||
public void testValueOfChainCapturedType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfChainCapturedType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valueOfNonReified.kt")
|
||||
public void testValueOfNonReified() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfNonReified.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("values.kt")
|
||||
public void testValues() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/values.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesAsArray.kt")
|
||||
public void testValuesAsArray() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesAsArray.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesCapturedType.kt")
|
||||
public void testValuesCapturedType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesCapturedType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesChain.kt")
|
||||
public void testValuesChain() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesChain.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesChainCapturedType.kt")
|
||||
public void testValuesChainCapturedType() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesChainCapturedType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("valuesNonReified.kt")
|
||||
public void testValuesNonReified() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesNonReified.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
+2
@@ -35,6 +35,8 @@ abstract class AbstractNoInlineTests : BorrowedInlineTest("noInline/")
|
||||
|
||||
abstract class AbstractCallableReferenceInlineTests : BorrowedInlineTest("callableReference/")
|
||||
|
||||
abstract class AbstractEnumValuesInlineTests : BorrowedInlineTest("enum/")
|
||||
|
||||
abstract class AbstractBoxJsTest() : BasicBoxTest(
|
||||
BasicBoxTest.TEST_DATA_DIR_PATH + "box/",
|
||||
BasicBoxTest.TEST_DATA_DIR_PATH + "out/box/"
|
||||
|
||||
+2
-11
@@ -22,9 +22,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
|
||||
class EnumTranslator(
|
||||
context: TranslationContext,
|
||||
@@ -37,14 +35,14 @@ class EnumTranslator(
|
||||
}
|
||||
|
||||
private fun generateValuesFunction() {
|
||||
val function = createFunction(getEnumFunction(DescriptorUtils.ENUM_VALUES))
|
||||
val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, DescriptorUtils.ENUM_VALUES))
|
||||
|
||||
val values = entries.map { JsInvocation(JsAstUtils.pureFqn(context().getNameForObjectInstance(it), null)) }
|
||||
function.body.statements += JsReturn(JsArrayLiteral(values))
|
||||
}
|
||||
|
||||
private fun generateValueOfFunction() {
|
||||
val function = createFunction(getEnumFunction(DescriptorUtils.ENUM_VALUE_OF))
|
||||
val function = createFunction(DescriptorUtils.getFunctionByName(descriptor.staticScope, DescriptorUtils.ENUM_VALUE_OF))
|
||||
|
||||
val nameParam = function.scope.declareTemporaryName("name")
|
||||
function.parameters += JsParameter(nameParam)
|
||||
@@ -74,11 +72,4 @@ class EnumTranslator(
|
||||
|
||||
return function
|
||||
}
|
||||
|
||||
private fun getEnumFunction(name: Name): FunctionDescriptor {
|
||||
val functions = descriptor.staticScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||
return functions
|
||||
.mapNotNull { (it as? FunctionDescriptor)?.original }
|
||||
.first { it.name == name }
|
||||
}
|
||||
}
|
||||
+52
-11
@@ -18,12 +18,10 @@ package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories;
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.js.patterns.DescriptorPredicate;
|
||||
import org.jetbrains.kotlin.js.patterns.NamePredicate;
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform;
|
||||
@@ -38,6 +36,7 @@ import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.KtQualifiedExpression;
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
@@ -140,19 +139,25 @@ public final class TopLevelFIF extends CompositeFIF {
|
||||
}
|
||||
};
|
||||
|
||||
private static final JsExpression getReferenceToOnlyTypeParameter(
|
||||
@NotNull CallInfo callInfo, @NotNull TranslationContext context
|
||||
) {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = callInfo.getResolvedCall();
|
||||
Map<TypeParameterDescriptor, KotlinType> typeArguments = resolvedCall.getTypeArguments();
|
||||
|
||||
assert typeArguments.size() == 1;
|
||||
KotlinType type = typeArguments.values().iterator().next();
|
||||
|
||||
return UtilsKt.getReferenceToJsClass(type, context);
|
||||
}
|
||||
|
||||
private static final FunctionIntrinsic JS_CLASS_FUN_INTRINSIC = new FunctionIntrinsic() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(
|
||||
@NotNull CallInfo callInfo, @NotNull List<JsExpression> arguments, @NotNull TranslationContext context
|
||||
) {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = callInfo.getResolvedCall();
|
||||
Map<TypeParameterDescriptor, KotlinType> typeArguments = resolvedCall.getTypeArguments();
|
||||
|
||||
assert typeArguments.size() == 1;
|
||||
KotlinType type = typeArguments.values().iterator().next();
|
||||
|
||||
return UtilsKt.getReferenceToJsClass(type, context);
|
||||
return getReferenceToOnlyTypeParameter(callInfo, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -164,6 +169,39 @@ public final class TopLevelFIF extends CompositeFIF {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static final FunctionIntrinsic ENUM_VALUES_INTRINSIC = new CallParametersAwareFunctionIntrinsic() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(
|
||||
@NotNull CallInfo callInfo, @NotNull List<JsExpression> arguments, @NotNull TranslationContext context
|
||||
) {
|
||||
JsExpression enumClassRef = getReferenceToOnlyTypeParameter(callInfo, context);
|
||||
|
||||
FunctionDescriptor fd = DescriptorFactory.createEnumValuesMethod(context.getCurrentModule().getBuiltIns().getEnum());
|
||||
|
||||
return new JsInvocation(new JsNameRef(context.getNameForDescriptor(fd), enumClassRef));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static final FunctionIntrinsic ENUM_VALUE_OF_INTRINSIC = new CallParametersAwareFunctionIntrinsic() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JsExpression apply(
|
||||
@NotNull CallInfo callInfo, @NotNull List<JsExpression> arguments, @NotNull TranslationContext context
|
||||
) {
|
||||
JsExpression arg = arguments.get(2); // The first two are reified parameters
|
||||
|
||||
JsExpression enumClassRef = getReferenceToOnlyTypeParameter(callInfo, context);
|
||||
|
||||
FunctionDescriptor fd = DescriptorFactory.createEnumValueOfMethod(context.getCurrentModule().getBuiltIns().getEnum());
|
||||
|
||||
return new JsInvocation(new JsNameRef(context.getNameForDescriptor(fd), enumClassRef), arg);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@NotNull
|
||||
public static final KotlinFunctionIntrinsic TO_STRING = new KotlinFunctionIntrinsic("toString");
|
||||
|
||||
@@ -187,6 +225,9 @@ public final class TopLevelFIF extends CompositeFIF {
|
||||
add(pattern("kotlin.js", "Json", "set"), ArrayFIF.SET_INTRINSIC);
|
||||
|
||||
add(pattern("kotlin.js", "jsClass"), JS_CLASS_FUN_INTRINSIC);
|
||||
|
||||
add(pattern("kotlin", "enumValues"), ENUM_VALUES_INTRINSIC);
|
||||
add(pattern("kotlin", "enumValueOf"), ENUM_VALUE_OF_INTRINSIC);
|
||||
}
|
||||
|
||||
private abstract static class NativeMapGetSet extends CallParametersAwareFunctionIntrinsic {
|
||||
|
||||
Reference in New Issue
Block a user