001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.js.translate.declaration;
018
019 import com.google.dart.compiler.backend.js.ast.JsExpression;
020 import com.google.dart.compiler.backend.js.ast.JsFunction;
021 import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
022 import com.intellij.util.SmartList;
023 import jet.runtime.typeinfo.KotlinSignature;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.kotlin.descriptors.ClassDescriptor;
026 import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
027 import org.jetbrains.kotlin.descriptors.Modality;
028 import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
029 import org.jetbrains.kotlin.js.translate.context.TranslationContext;
030 import org.jetbrains.kotlin.js.translate.declaration.propertyTranslator.PropertyTranslatorKt;
031 import org.jetbrains.kotlin.js.translate.general.Translation;
032 import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
033 import org.jetbrains.kotlin.js.translate.initializer.ClassInitializerTranslator;
034 import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
035 import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
036 import org.jetbrains.kotlin.psi.*;
037 import org.jetbrains.kotlin.types.JetType;
038
039 import java.util.List;
040
041 import static org.jetbrains.kotlin.js.translate.initializer.InitializerUtils.createCompanionObjectInitializer;
042 import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getClassDescriptor;
043 import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getFunctionDescriptor;
044 import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSupertypesWithoutFakes;
045
046 public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
047 @KotlinSignature("val result: MutableList<JsPropertyInitializer>")
048 protected final List<JsPropertyInitializer> result;
049 protected final List<JsPropertyInitializer> staticResult;
050 protected final List<JsPropertyInitializer> enumEntryList = new SmartList<JsPropertyInitializer>();
051
052 public DeclarationBodyVisitor(@NotNull List<JsPropertyInitializer> result, @NotNull List<JsPropertyInitializer> staticResult) {
053 this.result = result;
054 this.staticResult = staticResult;
055 }
056
057 @NotNull
058 public List<JsPropertyInitializer> getResult() {
059 return result;
060 }
061
062 public List<JsPropertyInitializer> getEnumEntryList() {
063 return enumEntryList;
064 }
065
066 @Override
067 protected Void emptyResult(@NotNull TranslationContext context) {
068 return null;
069 }
070
071 @Override
072 public Void visitClass(@NotNull JetClass expression, TranslationContext context) {
073 return null;
074 }
075
076 @Override
077 public Void visitEnumEntry(@NotNull JetEnumEntry enumEntry, TranslationContext data) {
078 JsExpression jsEnumEntryCreation;
079 ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
080 List<JetType> supertypes = getSupertypesWithoutFakes(descriptor);
081 if (enumEntry.getBody() != null || supertypes.size() > 1) {
082 jsEnumEntryCreation = ClassTranslator.generateClassCreation(enumEntry, data);
083 } else {
084 assert supertypes.size() == 1 : "Simple Enum entry must have one supertype";
085 jsEnumEntryCreation = new ClassInitializerTranslator(enumEntry, data).generateEnumEntryInstanceCreation(supertypes.get(0));
086 }
087 enumEntryList.add(new JsPropertyInitializer(data.getNameForDescriptor(descriptor).makeRef(), jsEnumEntryCreation));
088 return null;
089 }
090
091 @Override
092 public Void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, TranslationContext context) {
093 if (!declaration.isCompanion()) {
094 // parsed it in initializer visitor => no additional actions are needed
095 return null;
096 }
097 JsExpression value = ClassTranslator.generateClassCreation(declaration, context);
098
099 ClassDescriptor descriptor = getClassDescriptor(context.bindingContext(), declaration);
100 JsFunction fun = TranslationUtils.simpleReturnFunction(context.getScopeForDescriptor(descriptor), value);
101 staticResult.add(createCompanionObjectInitializer(fun, context));
102 return null;
103 }
104
105 @Override
106 public Void visitNamedFunction(@NotNull JetNamedFunction expression, TranslationContext context) {
107 FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
108 if (descriptor.getModality() == Modality.ABSTRACT) {
109 return null;
110 }
111
112 JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
113 result.add(methodAsPropertyInitializer);
114 return null;
115 }
116
117 @Override
118 public Void visitProperty(@NotNull JetProperty expression, TranslationContext context) {
119 PropertyDescriptor propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression);
120 PropertyTranslatorKt.translateAccessors(propertyDescriptor, expression, result, context);
121 return null;
122 }
123
124 @Override
125 public Void visitAnonymousInitializer(@NotNull JetClassInitializer expression, TranslationContext context) {
126 // parsed it in initializer visitor => no additional actions are needed
127 return null;
128 }
129
130 @Override
131 public Void visitSecondaryConstructor(@NotNull JetSecondaryConstructor constructor, TranslationContext data) {
132 return null;
133 }
134 }