[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; 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; if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false;
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; 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 @NotNull
@@ -86,7 +86,7 @@ internal fun VariableDescriptor.variableKind(
} }
private fun hasNoWritersInClosures( fun hasNoWritersInClosures(
variableContainingDeclaration: DeclarationDescriptor, variableContainingDeclaration: DeclarationDescriptor,
writers: Set<AssignedVariablesSearcher.Writer>, writers: Set<AssignedVariablesSearcher.Writer>,
bindingContext: BindingContext bindingContext: BindingContext
@@ -16,23 +16,22 @@
package org.jetbrains.kotlin.js.translate.callTranslator 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.CallableDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.js.backend.ast.* 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
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
import org.jetbrains.kotlin.js.translate.declaration.contextWithPropertyMetadataCreationIntrinsified import org.jetbrains.kotlin.js.translate.declaration.contextWithPropertyMetadataCreationIntrinsified
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator 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.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.JsAstUtils.pureFqn
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import java.util.* import java.util.*
@@ -87,7 +86,7 @@ object DefaultVariableAccessCase : VariableAccessCase() {
} }
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context) val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
val ref = if (isVarCapturedInClosure(context.bindingContext(), callableDescriptor)) { val ref = if (context.isBoxedLocalCapturedInClosure(callableDescriptor)) {
getCapturedVarAccessor(functionRef) getCapturedVarAccessor(functionRef)
} }
else { else {
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations; 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.TypeAliasConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation; 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.inline.InlineUtil;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.kotlin.serialization.js.ModuleKind; import org.jetbrains.kotlin.serialization.js.ModuleKind;
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
import java.util.*; 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.AnnotationsUtils.isNativeObject;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForElement; 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.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. * All the info about the state of the translation process.
@@ -793,6 +797,25 @@ public class TranslationContext {
return staticContext.getDeferredCallSites().containsKey(classDescriptor); 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) { public void deferConstructorCall(@NotNull ClassConstructorDescriptor constructor, @NotNull List<JsExpression> invocationArgs) {
ClassDescriptor classDescriptor = constructor.getContainingDeclaration(); ClassDescriptor classDescriptor = constructor.getContainingDeclaration();
List<DeferredCallSite> callSites = staticContext.getDeferredCallSites().get(classDescriptor); 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.JsDescriptorUtils.getReceiverParameterForDeclaration;
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateInitializerForProperty; import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateInitializerForProperty;
import static org.jetbrains.kotlin.resolve.BindingContext.*; 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.calls.callUtil.CallUtilKt.getResolvedCallWithAssert;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getAnnotationClass; import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getAnnotationClass;
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression; 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); initializer = PropertyTranslatorKt.translateDelegateOrInitializerExpression(context, expression);
assert initializer != null : "Initializer must be non-null for property with delegate"; 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()); JsNameRef alias = getCapturedVarAccessor(name.makeRef());
initializer = JsAstUtils.wrapValue(alias, initializer == null ? new JsNullLiteral() : initializer); initializer = JsAstUtils.wrapValue(alias, initializer == null ? new JsNullLiteral() : initializer);
} }