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
017package org.jetbrains.k2js.translate.context;
018
019import com.google.dart.compiler.backend.js.ast.*;
020import org.jetbrains.annotations.NotNull;
021import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
022import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
023import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
024import org.jetbrains.jet.lang.resolve.DescriptorUtils;
025
026/**
027 * Encapuslates different types of constants and naming conventions.
028 */
029public final class Namer {
030    public static final String CALLEE_NAME = "$fun";
031
032    private static final String INITIALIZE_METHOD_NAME = "initialize";
033    private static final String CLASS_OBJECT_NAME = "createClass";
034    private static final String TRAIT_OBJECT_NAME = "createTrait";
035    private static final String OBJECT_OBJECT_NAME = "createObject";
036    private static final String SETTER_PREFIX = "set_";
037    private static final String GETTER_PREFIX = "get_";
038    private static final String BACKING_FIELD_PREFIX = "$";
039    private static final String SUPER_METHOD_NAME = "super_init";
040    private static final String KOTLIN_OBJECT_NAME = "Kotlin";
041    private static final String ROOT_NAMESPACE = "_";
042    private static final String RECEIVER_PARAMETER_NAME = "receiver";
043    private static final String CLASSES_OBJECT_NAME = "classes";
044    private static final String THROW_NPE_FUN_NAME = "throwNPE";
045
046    @NotNull
047    public static String getReceiverParameterName() {
048        return RECEIVER_PARAMETER_NAME;
049    }
050
051    @NotNull
052    public static String getRootNamespaceName() {
053        return ROOT_NAMESPACE;
054    }
055
056    @NotNull
057    public static JsNameRef initializeMethodReference() {
058        return new JsNameRef(INITIALIZE_METHOD_NAME);
059    }
060
061    @NotNull
062    public static String superMethodName() {
063        return SUPER_METHOD_NAME;
064    }
065
066    @NotNull
067    public static String nameForClassesVariable() {
068        return CLASSES_OBJECT_NAME;
069    }
070
071    @NotNull
072    public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter, boolean useNativeAccessor) {
073        if (useNativeAccessor) {
074            return propertyName;
075        }
076
077        if (isGetter) {
078            return getNameForGetter(propertyName);
079        }
080        else {
081            return getNameForSetter(propertyName);
082        }
083    }
084
085    @NotNull
086    public static String getKotlinBackingFieldName(@NotNull String propertyName) {
087        return getNameWithPrefix(propertyName, BACKING_FIELD_PREFIX);
088    }
089
090    @NotNull
091    private static String getNameForGetter(@NotNull String propertyName) {
092        return getNameWithPrefix(propertyName, GETTER_PREFIX);
093    }
094
095    @NotNull
096    private static String getNameForSetter(@NotNull String propertyName) {
097        return getNameWithPrefix(propertyName, SETTER_PREFIX);
098    }
099
100    @NotNull
101    private static String getNameWithPrefix(@NotNull String name, @NotNull String prefix) {
102        return prefix + name;
103    }
104
105    public static Namer newInstance(@NotNull JsScope rootScope) {
106        return new Namer(rootScope);
107    }
108
109    @NotNull
110    private final JsName kotlinName;
111    @NotNull
112    private final JsScope kotlinScope;
113    @NotNull
114    private final JsName className;
115    @NotNull
116    private final JsName traitName;
117    @NotNull
118    private final JsExpression definePackage;
119    @NotNull
120    private final JsName objectName;
121
122    @NotNull
123    private final JsName isTypeName;
124
125    private Namer(@NotNull JsScope rootScope) {
126        kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME);
127        kotlinScope = new JsScope(rootScope, "Kotlin standard object");
128        traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
129
130        definePackage = kotlin("definePackage");
131
132        className = kotlinScope.declareName(CLASS_OBJECT_NAME);
133        objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
134
135        isTypeName = kotlinScope.declareName("isType");
136    }
137
138    @NotNull
139    public JsExpression classCreationMethodReference() {
140        return kotlin(className);
141    }
142
143    @NotNull
144    public JsExpression traitCreationMethodReference() {
145        return kotlin(traitName);
146    }
147
148    @NotNull
149    public JsExpression packageDefinitionMethodReference() {
150        return definePackage;
151    }
152
153    @NotNull
154    public JsExpression objectCreationMethodReference() {
155        return kotlin(objectName);
156    }
157
158    @NotNull
159    public JsExpression throwNPEFunctionCall() {
160        return new JsInvocation(new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject()));
161    }
162
163    @NotNull
164    private JsNameRef kotlin(@NotNull JsName name) {
165        return new JsNameRef(name, kotlinObject());
166    }
167
168    @NotNull
169    public JsExpression kotlin(@NotNull String name) {
170        return kotlin(kotlinScope.declareName(name));
171    }
172
173    @NotNull
174    public JsNameRef kotlinObject() {
175        return kotlinName.makeRef();
176    }
177
178    @NotNull
179    public JsExpression isOperationReference() {
180        return kotlin(isTypeName);
181    }
182
183    @NotNull
184        /*package*/ JsScope getKotlinScope() {
185        return kotlinScope;
186    }
187
188    @NotNull
189    static String generateNamespaceName(DeclarationDescriptor descriptor) {
190        if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
191            return getRootNamespaceName();
192        }
193        else {
194            return descriptor.getName().asString();
195        }
196    }
197
198    @NotNull
199    public JsInvocation classCreateInvocation(@NotNull ClassDescriptor descriptor) {
200        switch (descriptor.getKind()) {
201            case TRAIT:
202                return new JsInvocation(traitCreationMethodReference());
203            case OBJECT:
204                return new JsInvocation(objectCreationMethodReference());
205
206            default:
207                return new JsInvocation(classCreationMethodReference());
208        }
209    }
210}