JS backend: drop old property access translator

This commit is contained in:
Erokhin Stanislav
2013-12-27 17:33:24 +04:00
parent 402a9f6c81
commit 31668406cd
6 changed files with 38 additions and 435 deletions
@@ -1,73 +0,0 @@
/*
* Copyright 2010-2013 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.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.translate.context.TemporaryVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.singletonList;
public final class CachedPropertyAccessTranslator implements CachedAccessTranslator {
@NotNull
private final PropertyAccessTranslator baseTranslator;
@Nullable
private final TemporaryVariable cachedReceiver;
/*package*/ CachedPropertyAccessTranslator(@Nullable JsExpression receiverExpression,
@NotNull PropertyAccessTranslator baseTranslator,
@NotNull TranslationContext context) {
this.cachedReceiver = receiverExpression != null ? context.declareTemporary(receiverExpression) : null;
this.baseTranslator = baseTranslator;
}
@NotNull
@Override
public JsExpression translateAsGet() {
return baseTranslator.translateAsGet(receiverOrNull());
}
@NotNull
@Override
public JsExpression translateAsSet(@NotNull JsExpression toSetTo) {
return baseTranslator.translateAsSet(receiverOrNull(), toSetTo);
}
@Nullable
private JsNameRef receiverOrNull() {
return cachedReceiver != null ? cachedReceiver.reference() : null;
}
@NotNull
@Override
public CachedAccessTranslator getCached() {
return this;
}
@NotNull
@Override
public List<TemporaryVariable> declaredTemporaries() {
return cachedReceiver != null ? singletonList(cachedReceiver) : Collections.<TemporaryVariable>emptyList();
}
}
@@ -1,115 +0,0 @@
/*
* Copyright 2010-2013 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.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.PropertyGetterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.DescriptorFactory;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.assignmentToBackingField;
/**
* For properies /w accessors.
*/
public final class KotlinPropertyAccessTranslator extends PropertyAccessTranslator {
@Nullable
private final JsExpression receiver;
@NotNull
private final PropertyDescriptor propertyDescriptor;
@NotNull
private final ResolvedCall<?> resolvedCall;
//TODO: too many params in constructor
/*package*/ KotlinPropertyAccessTranslator(@NotNull PropertyDescriptor descriptor,
@Nullable JsExpression receiver,
@NotNull ResolvedCall<?> resolvedCall,
@NotNull TranslationContext context) {
super(context);
this.receiver = receiver;
this.propertyDescriptor = descriptor.getOriginal();
this.resolvedCall = resolvedCall;
}
@NotNull
@Override
public JsExpression translateAsGet() {
return translateAsGet(receiver);
}
@Override
@NotNull
public JsExpression translateAsGet(@Nullable JsExpression receiver) {
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
if (getter == null) {
//TODO: Temporary hack!!! Rewrite codegen!
//Now for consistency we don't create default getter for object declaration property descriptor
PropertyGetterDescriptorImpl getterImpl = DescriptorFactory.createDefaultGetter(propertyDescriptor);
getterImpl.initialize(propertyDescriptor.getType());
((PropertyDescriptorImpl)propertyDescriptor).initialize(getterImpl, null);
getter = getterImpl;
}
assert getter != null : "Getter for kotlin properties should bot be null.";
return callBuilderForAccessor(receiver)
.descriptor(getter)
.translate();
}
@NotNull
@Override
public JsExpression translateAsSet(@NotNull JsExpression toSetTo) {
if (propertyDescriptor.isVar()) {
return translateAsSet(receiver, toSetTo);
} else {
return assignmentToBackingField(context(), propertyDescriptor, toSetTo);
}
}
@Override
@NotNull
public JsExpression translateAsSet(@Nullable JsExpression receiver, @NotNull JsExpression toSetTo) {
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
assert setter != null : "Setter for kotlin properties should not be null.";
return callBuilderForAccessor(receiver)
.args(toSetTo)
.descriptor(setter)
.translate();
}
@NotNull
private CallBuilder callBuilderForAccessor(@Nullable JsExpression qualifier) {
return CallBuilder.build(context())
.receiver(qualifier)
.resolvedCall(resolvedCall)
.type(getCallType());
}
@NotNull
@Override
public CachedAccessTranslator getCached() {
return new CachedPropertyAccessTranslator(receiver, this, context());
}
}
@@ -1,116 +0,0 @@
/*
* Copyright 2010-2013 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.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.assignment;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedThisDescriptor;
/**
* For native apis that use .property notation for access.
*/
public final class NativePropertyAccessTranslator extends PropertyAccessTranslator {
@Nullable
private final JsExpression receiver;
@NotNull
private final PropertyDescriptor propertyDescriptor;
/*package*/
NativePropertyAccessTranslator(@NotNull PropertyDescriptor descriptor,
@Nullable JsExpression receiver,
@NotNull TranslationContext context) {
super(context);
this.receiver = receiver;
this.propertyDescriptor = descriptor.getOriginal();
}
@Override
@NotNull
public JsExpression translateAsGet() {
return translateAsGet(getReceiver());
}
@NotNull
@Override
protected JsExpression translateAsGet(@Nullable JsExpression receiver) {
return getCallType().constructCall(receiver, new CallType.CallConstructor() {
@NotNull
@Override
public JsExpression construct(@Nullable JsExpression receiver) {
return doTranslateAsGet(receiver);
}
}, context());
}
@NotNull
private JsExpression doTranslateAsGet(JsExpression receiver) {
JsName nativePropertyName = context().getNameForDescriptor(propertyDescriptor);
if (receiver != null) {
return new JsNameRef(nativePropertyName, receiver);
}
else {
return nativePropertyName.makeRef();
}
}
@Override
@NotNull
protected JsExpression translateAsSet(@Nullable JsExpression receiver, @NotNull final JsExpression setTo) {
assert receiver != null;
return getCallType().constructCall(receiver, new CallType.CallConstructor() {
@NotNull
@Override
public JsExpression construct(@Nullable JsExpression receiver) {
return assignment(translateAsGet(receiver), setTo);
}
}, context());
}
@NotNull
@Override
public JsExpression translateAsSet(@NotNull JsExpression setTo) {
return translateAsSet(getReceiver(), setTo);
}
@Nullable
private JsExpression getReceiver() {
if (receiver != null) {
return receiver;
}
assert propertyDescriptor.getReceiverParameter() == null : "Can't have native extension properties.";
DeclarationDescriptor expectedThisDescriptor = getExpectedThisDescriptor(propertyDescriptor);
if (expectedThisDescriptor == null) {
return null;
}
return context().getThisObject(expectedThisDescriptor);
}
@NotNull
@Override
public CachedAccessTranslator getCached() {
return new CachedPropertyAccessTranslator(getReceiver(), this, context());
}
}
@@ -1,129 +0,0 @@
/*
* Copyright 2010-2013 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.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import static org.jetbrains.k2js.translate.utils.AnnotationsUtils.isNativeObject;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCallForProperty;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelectorAsSimpleName;
import static org.jetbrains.jet.lang.psi.JetPsiUtil.isBackingFieldReference;
public abstract class PropertyAccessTranslator extends AbstractTranslator implements AccessTranslator {
@NotNull
public static PropertyAccessTranslator newInstance(@NotNull JetSimpleNameExpression expression,
@Nullable JsExpression qualifier,
@NotNull CallType callType,
@NotNull TranslationContext context) {
PropertyAccessTranslator result;
PropertyDescriptor propertyDescriptor = getPropertyDescriptor(expression, context);
if (isNativeObject(propertyDescriptor) || isBackingFieldReference(expression)) {
result = new NativePropertyAccessTranslator(propertyDescriptor, qualifier, context);
}
else {
ResolvedCall<?> resolvedCall = getResolvedCallForProperty(context.bindingContext(), expression);
result = new KotlinPropertyAccessTranslator(propertyDescriptor, qualifier, resolvedCall, context);
}
result.setCallType(callType);
return result;
}
@NotNull
private static PropertyDescriptor getPropertyDescriptor(@NotNull JetSimpleNameExpression expression,
@NotNull TranslationContext context) {
DeclarationDescriptor descriptor =
getDescriptorForReferenceExpression(context.bindingContext(), expression);
assert descriptor instanceof PropertyDescriptor : "Must be a property descriptor.";
return (PropertyDescriptor) descriptor;
}
@NotNull
public static JsExpression translateAsPropertyGetterCall(@NotNull JetSimpleNameExpression expression,
@Nullable JsExpression qualifier,
@NotNull CallType callType,
@NotNull TranslationContext context) {
return (newInstance(expression, qualifier, callType, context))
.translateAsGet();
}
private static boolean canBePropertyGetterCall(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
JetSimpleNameExpression selector = getSelectorAsSimpleName(expression);
assert selector != null : "Only names are allowed after the dot";
return canBePropertyGetterCall(selector, context);
}
private static boolean canBePropertyGetterCall(@NotNull JetSimpleNameExpression expression,
@NotNull TranslationContext context) {
return (getDescriptorForReferenceExpression
(context.bindingContext(), expression) instanceof PropertyDescriptor);
}
public static boolean canBePropertyGetterCall(@NotNull JetExpression expression,
@NotNull TranslationContext context) {
if (expression instanceof JetQualifiedExpression) {
return canBePropertyGetterCall((JetQualifiedExpression) expression, context);
}
if (expression instanceof JetSimpleNameExpression) {
return canBePropertyGetterCall((JetSimpleNameExpression) expression, context);
}
return false;
}
public static boolean canBePropertyAccess(@NotNull JetExpression expression,
@NotNull TranslationContext context) {
return canBePropertyGetterCall(expression, context);
}
//TODO: we use normal by default but may cause bugs
//TODO: inspect
private /*var*/ CallType callType = CallType.NORMAL;
protected PropertyAccessTranslator(@NotNull TranslationContext context) {
super(context);
}
public void setCallType(@NotNull CallType callType) {
this.callType = callType;
}
@NotNull
protected CallType getCallType() {
assert callType != null : "CallType not set";
return callType;
}
@NotNull
protected abstract JsExpression translateAsGet(@Nullable JsExpression receiver);
@NotNull
protected abstract JsExpression translateAsSet(@Nullable JsExpression receiver, @NotNull JsExpression setTo);
}
@@ -59,7 +59,7 @@ public final class QualifiedExpressionTranslator {
@NotNull CallType callType,
@NotNull TranslationContext context
) {
if (PropertyAccessTranslator.canBePropertyGetterCall(selector, context)) {
if (ReferenceTranslator.canBePropertyGetterCall(selector, context)) {
assert selector instanceof JetSimpleNameExpression : "Selectors for properties must be simple names.";
return new SimpleWrappedVariableAccessTranslator(context, (JetSimpleNameExpression)selector, receiver).translateAsGet();
}
@@ -21,11 +21,16 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static org.jetbrains.jet.lang.psi.JetPsiUtil.isBackingFieldReference;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelectorAsSimpleName;
public final class ReferenceTranslator {
@@ -70,7 +75,7 @@ public final class ReferenceTranslator {
if (isBackingFieldReference(referenceExpression)) {
return BackingFieldAccessTranslator.newInstance(referenceExpression, context);
}
if (PropertyAccessTranslator.canBePropertyAccess(referenceExpression, context)) {
if (canBePropertyAccess(referenceExpression, context)) {
return new SimpleWrappedVariableAccessTranslator(context, referenceExpression, receiver);
}
if (ClassObjectAccessTranslator.isClassObjectReference(referenceExpression, context)) {
@@ -78,4 +83,35 @@ public final class ReferenceTranslator {
}
return ReferenceAccessTranslator.newInstance(referenceExpression, context);
}
// TODO: drop this
private static boolean canBePropertyGetterCall(@NotNull JetQualifiedExpression expression,
@NotNull TranslationContext context) {
JetSimpleNameExpression selector = getSelectorAsSimpleName(expression);
assert selector != null : "Only names are allowed after the dot";
return canBePropertyGetterCall(selector, context);
}
private static boolean canBePropertyGetterCall(@NotNull JetSimpleNameExpression expression,
@NotNull TranslationContext context) {
return (getDescriptorForReferenceExpression
(context.bindingContext(), expression) instanceof PropertyDescriptor);
}
public static boolean canBePropertyGetterCall(@NotNull JetExpression expression,
@NotNull TranslationContext context) {
if (expression instanceof JetQualifiedExpression) {
return canBePropertyGetterCall((JetQualifiedExpression) expression, context);
}
if (expression instanceof JetSimpleNameExpression) {
return canBePropertyGetterCall((JetSimpleNameExpression) expression, context);
}
return false;
}
public static boolean canBePropertyAccess(@NotNull JetExpression expression,
@NotNull TranslationContext context) {
return canBePropertyGetterCall(expression, context);
}
}