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.descriptors.CallableDescriptor; 025 import org.jetbrains.kotlin.descriptors.ClassDescriptor; 026 import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; 027 import org.jetbrains.kotlin.idea.KotlinLanguage; 028 import org.jetbrains.kotlin.js.resolve.JsPlatform; 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 = KotlinLanguage.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(JsPlatform.INSTANCE.getBuiltIns().getAny(), "equals"); 050 public static final String COMPARE_TO_METHOD_NAME = getStableMangledNameForDescriptor(JsPlatform.INSTANCE.getBuiltIns().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 }