[JS BE] Support contracts in JS Fix KT-27946

This commit is contained in:
Roman Artemev
2018-11-07 20:56:10 +03:00
committed by romanart
parent b010d9eef8
commit 8f2117685f
5 changed files with 35 additions and 10 deletions
@@ -198,10 +198,14 @@ public class BindingContextUtils {
return expression instanceof KtReferenceExpression;
}
public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
public static boolean isCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar();
return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null;
}
public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) {
return isCapturedInClosure(bindingContext, descriptor) && ((VariableDescriptor) descriptor).isVar();
}
@NotNull
@@ -86,7 +86,7 @@ internal fun VariableDescriptor.variableKind(
}
private fun hasNoWritersInClosures(
fun hasNoWritersInClosures(
variableContainingDeclaration: DeclarationDescriptor,
writers: Set<AssignedVariablesSearcher.Writer>,
bindingContext: BindingContext
@@ -16,23 +16,22 @@
package org.jetbrains.kotlin.js.translate.callTranslator
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.SideEffectKind
import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
import org.jetbrains.kotlin.js.translate.declaration.contextWithPropertyMetadataCreationIntrinsified
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.reference.buildReifiedTypeArgs
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import java.util.*
@@ -87,7 +86,7 @@ object DefaultVariableAccessCase : VariableAccessCase() {
}
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
val ref = if (isVarCapturedInClosure(context.bindingContext(), callableDescriptor)) {
val ref = if (context.isBoxedLocalCapturedInClosure(callableDescriptor)) {
getCapturedVarAccessor(functionRef)
}
else {
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.kotlin.serialization.js.ModuleKind;
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
import java.util.*;
@@ -50,6 +52,8 @@ import static org.jetbrains.kotlin.js.translate.context.UsageTrackerKt.getNameFo
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForElement;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isCapturedInClosure;
import static org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueKindUtilsKt.hasNoWritersInClosures;
/**
* All the info about the state of the translation process.
@@ -793,6 +797,25 @@ public class TranslationContext {
return staticContext.getDeferredCallSites().containsKey(classDescriptor);
}
private boolean isValWithWriterInDifferentScope(VariableDescriptor descriptor) {
//TODO: Simplify this code once KT-17694 is fixed
if (!(descriptor instanceof LocalVariableDescriptor)) {
return false;
}
PreliminaryDeclarationVisitor preliminaryVisitor =
PreliminaryDeclarationVisitor.Companion.getVisitorByVariable(descriptor, bindingContext());
return (preliminaryVisitor == null ||
!hasNoWritersInClosures(descriptor.getContainingDeclaration(), preliminaryVisitor.writers(descriptor), bindingContext()));
}
public boolean isBoxedLocalCapturedInClosure(CallableDescriptor descriptor) {
if (isCapturedInClosure(bindingContext(), descriptor)) {
VariableDescriptor localVariable = (VariableDescriptor) descriptor;
return localVariable.isVar() || isValWithWriterInDifferentScope(localVariable);
}
return false;
}
public void deferConstructorCall(@NotNull ClassConstructorDescriptor constructor, @NotNull List<JsExpression> invocationArgs) {
ClassDescriptor classDescriptor = constructor.getContainingDeclaration();
List<DeferredCallSite> callSites = staticContext.getDeferredCallSites().get(classDescriptor);
@@ -74,7 +74,6 @@ import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*;
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForDeclaration;
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateInitializerForProperty;
import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt.getResolvedCallWithAssert;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getAnnotationClass;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
@@ -244,7 +243,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
initializer = PropertyTranslatorKt.translateDelegateOrInitializerExpression(context, expression);
assert initializer != null : "Initializer must be non-null for property with delegate";
}
else if (isVarCapturedInClosure(context.bindingContext(), descriptor)) {
else if (context.isBoxedLocalCapturedInClosure(descriptor)) {
JsNameRef alias = getCapturedVarAccessor(name.makeRef());
initializer = JsAstUtils.wrapValue(alias, initializer == null ? new JsNullLiteral() : initializer);
}