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