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