.kotlin.kotlin-compiler.1.3.11.source-code.InitializerVisitor Maven / Gradle / Ivy
/*
* Copyright 2010-2017 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.translate.initializer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.js.backend.ast.*;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt;
import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.types.KotlinType;
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsStatementAndMergeInBlockIfNeeded;
import static org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForDelegate;
import static org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.generateInitializerForProperty;
public final class InitializerVisitor extends TranslatorVisitor {
@Override
protected Void emptyResult(@NotNull TranslationContext context) {
return null;
}
@Override
public final Void visitProperty(@NotNull KtProperty property, @NotNull TranslationContext context) {
PropertyDescriptor descriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), property);
JsExpression value = PropertyTranslatorKt.translateDelegateOrInitializerExpression(context, property);
JsStatement statement = null;
KtExpression initializer = property.getInitializer();
KtExpression delegate = property.getDelegateExpression();
if (initializer != null) {
assert value != null;
KotlinType type = TranslationUtils.isReferenceToSyntheticBackingField(descriptor) ?
descriptor.getType() :
TranslationUtils.getReturnTypeForCoercion(descriptor);
value = TranslationUtils.coerce(context, value, type);
statement = generateInitializerForProperty(context, descriptor, value);
}
else if (delegate != null) {
assert value != null;
statement = generateInitializerForDelegate(context, descriptor, value);
}
else if (Boolean.TRUE.equals(context.bindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
JsNameRef backingFieldReference = TranslationUtils.backingFieldReference(context, descriptor);
JsExpression defaultValue = generateDefaultValue(descriptor, backingFieldReference);
statement = TranslationUtils.assignmentToBackingField(context, descriptor, defaultValue).source(property).makeStmt();
}
else if (JsDescriptorUtils.isSimpleFinalProperty(descriptor)) {
JsNameRef propRef = new JsNameRef(context.getNameForDescriptor(descriptor), new JsThisRef());
JsExpression defaultValue = generateDefaultValue(descriptor, propRef);
statement = JsAstUtils.assignment(propRef, defaultValue).source(property).makeStmt();
}
if (statement != null && !JsAstUtils.isEmptyStatement(statement)) {
context.addStatementsToCurrentBlock(JsAstUtils.flattenStatement(statement));
}
return null;
}
@NotNull
private static JsExpression generateDefaultValue(
@NotNull PropertyDescriptor property,
@NotNull JsExpression lateInitDefault
) {
if (property.isLateInit()) return lateInitDefault.deepCopy();
KotlinType type = property.getType();
if (KotlinBuiltIns.isInt(type) || KotlinBuiltIns.isFloat(type) || KotlinBuiltIns.isDouble(type) ||
KotlinBuiltIns.isByte(type) || KotlinBuiltIns.isShort(type)
) {
return new JsIntLiteral(0);
}
else if (KotlinBuiltIns.isBoolean(type)) {
return new JsBooleanLiteral(false);
}
else {
return new JsNullLiteral();
}
}
@Override
public Void visitAnonymousInitializer(@NotNull KtAnonymousInitializer initializer, @NotNull TranslationContext context) {
KtExpression initializerBody = initializer.getBody();
if (initializerBody != null) {
context.addStatementsToCurrentBlock(JsAstUtils.flattenStatement(
translateAsStatementAndMergeInBlockIfNeeded(initializerBody, context)));
}
return null;
}
@Override
// Not interested in other types of declarations, they do not contain initializers.
public Void visitDeclaration(@NotNull KtDeclaration expression, @NotNull TranslationContext context) {
return null;
}
@Override
public Void visitSecondaryConstructor(@NotNull KtSecondaryConstructor constructor, TranslationContext data) {
return null;
}
}