001 /*
002 * Copyright 2010-2013 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.k2js.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 org.jetbrains.annotations.NotNull;
024 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
025 import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
026 import org.jetbrains.jet.lang.descriptors.Modality;
027 import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
028 import org.jetbrains.jet.lang.psi.*;
029 import org.jetbrains.jet.lang.types.JetType;
030 import org.jetbrains.k2js.translate.context.TranslationContext;
031 import org.jetbrains.k2js.translate.general.Translation;
032 import org.jetbrains.k2js.translate.general.TranslatorVisitor;
033 import org.jetbrains.k2js.translate.initializer.ClassInitializerTranslator;
034 import org.jetbrains.k2js.translate.utils.BindingUtils;
035 import org.jetbrains.k2js.translate.utils.TranslationUtils;
036
037 import java.util.Collection;
038 import java.util.List;
039
040 import static org.jetbrains.k2js.translate.initializer.InitializerUtils.createClassObjectInitializer;
041 import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
042 import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
043
044 public class DeclarationBodyVisitor extends TranslatorVisitor<Void> {
045 protected final List<JsPropertyInitializer> result;
046 protected final List<JsPropertyInitializer> staticResult;
047 protected final List<JsPropertyInitializer> enumEntryList = new SmartList<JsPropertyInitializer>();
048
049 public DeclarationBodyVisitor() {
050 this(new SmartList<JsPropertyInitializer>(), new SmartList<JsPropertyInitializer>());
051 }
052
053 public DeclarationBodyVisitor(@NotNull List<JsPropertyInitializer> result, @NotNull List<JsPropertyInitializer> staticResult) {
054 this.result = result;
055 this.staticResult = staticResult;
056 }
057
058 @NotNull
059 public List<JsPropertyInitializer> getResult() {
060 return result;
061 }
062
063 public List<JsPropertyInitializer> getEnumEntryList() {
064 return enumEntryList;
065 }
066
067 @Override
068 public Void visitClass(@NotNull JetClass expression, @NotNull TranslationContext context) {
069 return null;
070 }
071
072 @Override
073 public Void visitEnumEntry(@NotNull JetEnumEntry enumEntry, TranslationContext data) {
074 JsExpression jsEnumEntryCreation;
075 ClassDescriptor descriptor = getClassDescriptor(data.bindingContext(), enumEntry);
076 Collection<JetType> supertypes = descriptor.getTypeConstructor().getSupertypes();
077 if (enumEntry.getBody() != null || supertypes.size() > 1) {
078 jsEnumEntryCreation = ClassTranslator.generateClassCreation(enumEntry, descriptor, data);
079 } else {
080 assert supertypes.size() == 1 : "Simple Enum entry must have one supertype";
081 jsEnumEntryCreation = new ClassInitializerTranslator(enumEntry, data).generateEnumEntryInstanceCreation(supertypes.iterator().next());
082 }
083 enumEntryList.add(new JsPropertyInitializer(data.getNameForDescriptor(descriptor).makeRef(), jsEnumEntryCreation));
084 return null;
085 }
086
087 @Override
088 public Void visitClassObject(
089 @NotNull JetClassObject classObject, TranslationContext context
090 ) {
091 JetObjectDeclaration declaration = classObject.getObjectDeclaration();
092 assert declaration != null : "Declaration for class object must be not null";
093 ClassDescriptor descriptor = getClassDescriptor(context.bindingContext(), declaration);
094 JsExpression value = ClassTranslator.generateClassCreation(declaration, descriptor, context);
095
096 JsFunction fun = TranslationUtils.simpleReturnFunction(context.getScopeForDescriptor(descriptor), value);
097 staticResult.add(createClassObjectInitializer(fun, context));
098 return null;
099 }
100
101 @Override
102 public Void visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, @NotNull TranslationContext context) {
103 // parsed it in initializer visitor => no additional actions are needed
104 return null;
105 }
106
107 @Override
108 public Void visitNamedFunction(@NotNull JetNamedFunction expression, @NotNull TranslationContext context) {
109 FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
110 if (descriptor.getModality() == Modality.ABSTRACT) {
111 return null;
112 }
113
114 JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
115 result.add(methodAsPropertyInitializer);
116 return null;
117 }
118
119 @Override
120 public Void visitProperty(@NotNull JetProperty expression, @NotNull TranslationContext context) {
121 PropertyDescriptor propertyDescriptor = BindingUtils.getPropertyDescriptor(context.bindingContext(), expression);
122 PropertyTranslator.translateAccessors(propertyDescriptor, expression, result, context);
123 return null;
124 }
125
126 @Override
127 public Void visitAnonymousInitializer(@NotNull JetClassInitializer expression, @NotNull TranslationContext context) {
128 // parsed it in initializer visitor => no additional actions are needed
129 return null;
130 }
131 }