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.context;
018    
019    import com.google.dart.compiler.backend.js.ast.*;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
022    import org.jetbrains.jet.lang.descriptors.ClassKind;
023    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
024    import org.jetbrains.jet.lang.resolve.name.FqName;
025    import org.jetbrains.jet.plugin.JetLanguage;
026    
027    import static org.jetbrains.jet.lang.descriptors.ClassKind.TRAIT;
028    
029    /**
030     * Encapuslates different types of constants and naming conventions.
031     */
032    public final class Namer {
033        public static final String KOTLIN_NAME = JetLanguage.NAME;
034        public static final String KOTLIN_LOWER_NAME = KOTLIN_NAME.toLowerCase();
035        public static final JsNameRef KOTLIN_OBJECT_REF = new JsNameRef(KOTLIN_NAME);
036    
037        public static final String CALLEE_NAME = "$fun";
038    
039        private static final String CALL_FUNCTION = "call";
040        private static final String APPLY_FUNCTION = "apply";
041    
042        private static final String CLASS_OBJECT_NAME = "createClass";
043        private static final String TRAIT_OBJECT_NAME = "createTrait";
044        private static final String OBJECT_OBJECT_NAME = "createObject";
045        private static final String ENUM_ENTRIES_NAME = "createEnumEntries";
046        private static final String CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME = "getCallableRefForMemberFunction";
047        private static final String CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME = "getCallableRefForExtensionFunction";
048        private static final String CALLABLE_REF_FOR_CONSTRUCTOR_NAME = "getCallableRefForConstructor";
049        private static final String CALLABLE_REF_FOR_TOP_LEVEL_PROPERTY = "getCallableRefForTopLevelProperty";
050        private static final String CALLABLE_REF_FOR_MEMBER_PROPERTY = "getCallableRefForMemberProperty";
051        private static final String CALLABLE_REF_FOR_EXTENSION_PROPERTY = "getCallableRefForExtensionProperty";
052    
053        private static final String SETTER_PREFIX = "set_";
054        private static final String GETTER_PREFIX = "get_";
055        private static final String BACKING_FIELD_PREFIX = "$";
056        private static final String DELEGATE_POSTFIX = "$delegate";
057    
058        private static final String SUPER_METHOD_NAME = "baseInitializer";
059    
060        private static final String ROOT_PACKAGE = "_";
061    
062        private static final String RECEIVER_PARAMETER_NAME = "$receiver";
063    
064        private static final String THROW_NPE_FUN_NAME = "throwNPE";
065        private static final String CLASS_OBJECT_GETTER = "object";
066        private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$";
067        private static final String PROTOTYPE_NAME = "prototype";
068        public static final String CAPTURED_VAR_FIELD = "v";
069    
070        @NotNull
071        public static String getReceiverParameterName() {
072            return RECEIVER_PARAMETER_NAME;
073        }
074    
075        @NotNull
076        public static String getRootPackageName() {
077            return ROOT_PACKAGE;
078        }
079    
080        @NotNull
081        public static JsNameRef superMethodNameRef(@NotNull JsName superClassJsName) {
082            return new JsNameRef(SUPER_METHOD_NAME, superClassJsName.makeRef());
083        }
084    
085        @NotNull
086        public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter, boolean useNativeAccessor) {
087            if (useNativeAccessor) {
088                return propertyName;
089            }
090    
091            if (isGetter) {
092                return getNameForGetter(propertyName);
093            }
094            else {
095                return getNameForSetter(propertyName);
096            }
097        }
098    
099        @NotNull
100        public static String getKotlinBackingFieldName(@NotNull String propertyName) {
101            return getNameWithPrefix(propertyName, BACKING_FIELD_PREFIX);
102        }
103    
104        @NotNull
105        private static String getNameForGetter(@NotNull String propertyName) {
106            return getNameWithPrefix(propertyName, GETTER_PREFIX);
107        }
108    
109        @NotNull
110        private static String getNameForSetter(@NotNull String propertyName) {
111            return getNameWithPrefix(propertyName, SETTER_PREFIX);
112        }
113    
114        @NotNull
115        public static JsExpression getClassObjectAccessor(@NotNull JsExpression referenceToClass) {
116            return new JsNameRef(CLASS_OBJECT_GETTER, referenceToClass);
117        }
118    
119        @NotNull
120        public static String getNameForClassObjectInitializer() {
121            return CLASS_OBJECT_INITIALIZER;
122        }
123    
124        @NotNull
125        public static String getPrototypeName() {
126            return PROTOTYPE_NAME;
127        }
128    
129        @NotNull
130        public static JsNameRef getRefToPrototype(@NotNull JsExpression classOrTraitExpression) {
131            return new JsNameRef(getPrototypeName(), classOrTraitExpression);
132        }
133    
134        @NotNull
135        public static String getDelegateName(@NotNull String propertyName) {
136            return propertyName + DELEGATE_POSTFIX;
137        }
138    
139        @NotNull
140        public static JsNameRef getDelegateNameRef(String propertyName) {
141            return new JsNameRef(getDelegateName(propertyName), JsLiteral.THIS);
142        }
143    
144        @NotNull
145        private static String getNameWithPrefix(@NotNull String name, @NotNull String prefix) {
146            return prefix + name;
147        }
148    
149        @NotNull
150        public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
151            return new JsNameRef(CALL_FUNCTION, functionExpression);
152        }
153    
154        @NotNull
155        public static JsNameRef getFunctionApplyRef(@NotNull JsExpression functionExpression) {
156            return new JsNameRef(APPLY_FUNCTION, functionExpression);
157        }
158    
159        @NotNull
160        public static JsNameRef getCapturedVarAccessor(@NotNull JsExpression ref) {
161            return new JsNameRef(CAPTURED_VAR_FIELD, ref);
162        }
163    
164        @NotNull
165        public static Namer newInstance(@NotNull JsScope rootScope) {
166            return new Namer(rootScope);
167        }
168    
169        @NotNull
170        private final JsName kotlinName;
171        @NotNull
172        private final JsScope kotlinScope;
173        @NotNull
174        private final JsName className;
175        @NotNull
176        private final JsName traitName;
177        @NotNull
178        private final JsExpression definePackage;
179        @NotNull
180        private final JsExpression defineRootPackage;
181        @NotNull
182        private final JsName objectName;
183        @NotNull
184        private final JsName enumEntriesName;
185        @NotNull
186        private final JsName callableRefForMemberFunctionName;
187        @NotNull
188        private final JsName callableRefForExtensionFunctionName;
189        @NotNull
190        private final JsName callableRefForConstructorName;
191        @NotNull
192        private final JsName callableRefForTopLevelProperty;
193        @NotNull
194        private final JsName callableRefForMemberProperty;
195        @NotNull
196        private final JsName callableRefForExtensionProperty;
197        @NotNull
198        private final JsExpression undefinedExpression;
199        @NotNull
200        private final JsExpression callGetProperty;
201        @NotNull
202        private final JsExpression callSetProperty;
203    
204        @NotNull
205        private final JsName isTypeName;
206    
207        private Namer(@NotNull JsScope rootScope) {
208            kotlinName = rootScope.declareName(KOTLIN_NAME);
209            kotlinScope = new JsScope(rootScope, "Kotlin standard object");
210            traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
211    
212            definePackage = kotlin("definePackage");
213            defineRootPackage = kotlin("defineRootPackage");
214    
215            callGetProperty = kotlin("callGetter");
216            callSetProperty = kotlin("callSetter");
217    
218            className = kotlinScope.declareName(CLASS_OBJECT_NAME);
219            enumEntriesName = kotlinScope.declareName(ENUM_ENTRIES_NAME);
220            objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
221            callableRefForMemberFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_MEMBER_FUNCTION_NAME);
222            callableRefForExtensionFunctionName = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_FUNCTION_NAME);
223            callableRefForConstructorName = kotlinScope.declareName(CALLABLE_REF_FOR_CONSTRUCTOR_NAME);
224            callableRefForTopLevelProperty = kotlinScope.declareName(CALLABLE_REF_FOR_TOP_LEVEL_PROPERTY);
225            callableRefForMemberProperty = kotlinScope.declareName(CALLABLE_REF_FOR_MEMBER_PROPERTY);
226            callableRefForExtensionProperty = kotlinScope.declareName(CALLABLE_REF_FOR_EXTENSION_PROPERTY);
227    
228            isTypeName = kotlinScope.declareName("isType");
229    
230            undefinedExpression = new JsPrefixOperation(JsUnaryOperator.VOID, rootScope.getProgram().getNumberLiteral(0));
231        }
232    
233        @NotNull
234        public JsExpression classCreationMethodReference() {
235            return kotlin(className);
236        }
237    
238        @NotNull
239        public JsExpression enumEntriesCreationMethodReference() {
240            return kotlin(enumEntriesName);
241        }
242    
243        @NotNull
244        public JsExpression traitCreationMethodReference() {
245            return kotlin(traitName);
246        }
247    
248        @NotNull
249        public JsExpression packageDefinitionMethodReference() {
250            return definePackage;
251        }
252    
253        @NotNull
254        public JsExpression rootPackageDefinitionMethodReference() {
255            return defineRootPackage;
256        }
257    
258        @NotNull
259        public JsExpression objectCreationMethodReference() {
260            return kotlin(objectName);
261        }
262    
263        @NotNull
264        public JsExpression callableRefForMemberFunctionReference() {
265            return kotlin(callableRefForMemberFunctionName);
266        }
267    
268        @NotNull
269        public JsExpression callableRefForExtensionFunctionReference() {
270            return kotlin(callableRefForExtensionFunctionName);
271        }
272    
273        @NotNull
274        public JsExpression callableRefForConstructorReference() {
275            return kotlin(callableRefForConstructorName);
276        }
277    
278        @NotNull
279        public JsExpression callableRefForTopLevelPropertyReference() {
280            return kotlin(callableRefForTopLevelProperty);
281        }
282    
283        @NotNull
284        public JsExpression callableRefForMemberPropertyReference() {
285            return kotlin(callableRefForMemberProperty);
286        }
287    
288        @NotNull
289        public JsExpression callableRefForExtensionPropertyReference() {
290            return kotlin(callableRefForExtensionProperty);
291        }
292    
293        @NotNull
294        public JsExpression throwNPEFunctionRef() {
295            return new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject());
296        }
297    
298        @NotNull
299        private JsNameRef kotlin(@NotNull JsName name) {
300            return new JsNameRef(name, kotlinObject());
301        }
302    
303        @NotNull
304        public JsExpression kotlin(@NotNull String name) {
305            return kotlin(kotlinScope.declareName(name));
306        }
307    
308        @NotNull
309        public JsNameRef kotlinObject() {
310            return kotlinName.makeRef();
311        }
312    
313        @NotNull
314        public JsExpression isOperationReference() {
315            return kotlin(isTypeName);
316        }
317    
318        @NotNull
319            /*package*/ JsScope getKotlinScope() {
320            return kotlinScope;
321        }
322    
323        @NotNull
324        static String generatePackageName(@NotNull FqName packageFqName) {
325            return packageFqName.isRoot() ? getRootPackageName() : packageFqName.shortName().asString();
326        }
327    
328        @NotNull
329        public JsExpression classCreateInvocation(@NotNull ClassDescriptor descriptor) {
330            ClassKind kind = descriptor.getKind();
331            if (kind == TRAIT) {
332                return traitCreationMethodReference();
333            }
334    
335            if (kind.isSingleton() || DescriptorUtils.isAnonymousObject(descriptor)) {
336                return objectCreationMethodReference();
337            }
338    
339            return classCreationMethodReference();
340        }
341    
342        @NotNull
343        public JsInvocation enumEntriesObjectCreateInvocation() {
344            return new JsInvocation(enumEntriesCreationMethodReference());
345        }
346    
347        @NotNull
348        public JsExpression getUndefinedExpression() {
349            return undefinedExpression;
350        }
351    
352        @NotNull
353        public JsExpression getCallGetProperty() {
354            return callGetProperty;
355        }
356    
357        @NotNull
358        public JsExpression getCallSetProperty() {
359            return callSetProperty;
360        }
361    }