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.resolve.DescriptorUtils;
023 import org.jetbrains.jet.lang.resolve.name.FqName;
024 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
025 import org.jetbrains.jet.plugin.JetLanguage;
026
027 import static com.google.dart.compiler.backend.js.ast.AstPackage.JsObjectScope;
028 import static org.jetbrains.k2js.translate.utils.ManglingUtils.getStableMangledNameForDescriptor;
029
030 /**
031 * Encapuslates 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 CLASS_OBJECT_GETTER = "object";
082 private static final String CLASS_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 getClassObjectAccessor(@NotNull JsExpression referenceToClass) {
145 return new JsNameRef(CLASS_OBJECT_GETTER, referenceToClass);
146 }
147
148 @NotNull
149 public static String getNameForClassObjectInitializer() {
150 return CLASS_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 case CLASS_OBJECT:
368 return objectCreationMethodReference();
369 case ANNOTATION_CLASS:
370 case CLASS:
371 return DescriptorUtils.isAnonymousObject(descriptor)
372 ? objectCreationMethodReference()
373 : classCreationMethodReference();
374 default:
375 throw new UnsupportedOperationException("Unsupported class kind: " + descriptor);
376 }
377 }
378
379 @NotNull
380 public JsExpression getUndefinedExpression() {
381 return UNDEFINED_EXPRESSION;
382 }
383
384 @NotNull
385 public JsExpression getCallGetProperty() {
386 return callGetProperty;
387 }
388
389 @NotNull
390 public JsExpression getCallSetProperty() {
391 return callSetProperty;
392 }
393 }