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