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