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
036 public static final String CALLEE_NAME = "$fun";
037
038 private static final String CALL_FUNCTION = "call";
039 private static final String APPLY_FUNCTION = "apply";
040
041 private static final String CLASS_OBJECT_NAME = "createClass";
042 private static final String TRAIT_OBJECT_NAME = "createTrait";
043 private static final String OBJECT_OBJECT_NAME = "createObject";
044 private static final String ENUM_ENTRIES_NAME = "createEnumEntries";
045
046 private static final String SETTER_PREFIX = "set_";
047 private static final String GETTER_PREFIX = "get_";
048 private static final String BACKING_FIELD_PREFIX = "$";
049 private static final String DELEGATE_POSTFIX = "$delegate";
050
051 private static final String SUPER_METHOD_NAME = "baseInitializer";
052
053 private static final String ROOT_PACKAGE = "_";
054
055 private static final String RECEIVER_PARAMETER_NAME = "$receiver";
056
057 private static final String THROW_NPE_FUN_NAME = "throwNPE";
058 private static final String CLASS_OBJECT_GETTER = "object";
059 private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$";
060 private static final String PROTOTYPE_NAME = "prototype";
061 public static final String CAPTURED_VAR_FIELD = "v";
062
063 @NotNull
064 public static String getReceiverParameterName() {
065 return RECEIVER_PARAMETER_NAME;
066 }
067
068 @NotNull
069 public static String getRootPackageName() {
070 return ROOT_PACKAGE;
071 }
072
073 @NotNull
074 public static JsNameRef superMethodNameRef(@NotNull JsName superClassJsName) {
075 return new JsNameRef(SUPER_METHOD_NAME, superClassJsName.makeRef());
076 }
077
078 @NotNull
079 public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter, boolean useNativeAccessor) {
080 if (useNativeAccessor) {
081 return propertyName;
082 }
083
084 if (isGetter) {
085 return getNameForGetter(propertyName);
086 }
087 else {
088 return getNameForSetter(propertyName);
089 }
090 }
091
092 @NotNull
093 public static String getKotlinBackingFieldName(@NotNull String propertyName) {
094 return getNameWithPrefix(propertyName, BACKING_FIELD_PREFIX);
095 }
096
097 @NotNull
098 private static String getNameForGetter(@NotNull String propertyName) {
099 return getNameWithPrefix(propertyName, GETTER_PREFIX);
100 }
101
102 @NotNull
103 private static String getNameForSetter(@NotNull String propertyName) {
104 return getNameWithPrefix(propertyName, SETTER_PREFIX);
105 }
106
107 @NotNull
108 public static JsExpression getClassObjectAccessor(@NotNull JsExpression referenceToClass) {
109 return new JsNameRef(CLASS_OBJECT_GETTER, referenceToClass);
110 }
111
112 @NotNull
113 public static String getNameForClassObjectInitializer() {
114 return CLASS_OBJECT_INITIALIZER;
115 }
116
117 @NotNull
118 public static String getPrototypeName() {
119 return PROTOTYPE_NAME;
120 }
121
122 @NotNull
123 public static JsNameRef getRefToPrototype(@NotNull JsExpression classOrTraitExpression) {
124 return new JsNameRef(getPrototypeName(), classOrTraitExpression);
125 }
126
127 @NotNull
128 public static String getDelegateName(@NotNull String propertyName) {
129 return propertyName + DELEGATE_POSTFIX;
130 }
131
132 @NotNull
133 public static JsNameRef getDelegateNameRef(String propertyName) {
134 return new JsNameRef(getDelegateName(propertyName), JsLiteral.THIS);
135 }
136
137 @NotNull
138 private static String getNameWithPrefix(@NotNull String name, @NotNull String prefix) {
139 return prefix + name;
140 }
141
142 @NotNull
143 public static JsNameRef getFunctionCallRef(@NotNull JsExpression functionExpression) {
144 return new JsNameRef(CALL_FUNCTION, functionExpression);
145 }
146
147 @NotNull
148 public static JsNameRef getFunctionApplyRef(@NotNull JsExpression functionExpression) {
149 return new JsNameRef(APPLY_FUNCTION, functionExpression);
150 }
151
152 @NotNull
153 public static JsNameRef getCapturedVarAccessor(@NotNull JsExpression ref) {
154 return new JsNameRef(CAPTURED_VAR_FIELD, ref);
155 }
156
157 @NotNull
158 public static Namer newInstance(@NotNull JsScope rootScope) {
159 return new Namer(rootScope);
160 }
161
162 @NotNull
163 private final JsName kotlinName;
164 @NotNull
165 private final JsScope kotlinScope;
166 @NotNull
167 private final JsName className;
168 @NotNull
169 private final JsName traitName;
170 @NotNull
171 private final JsExpression definePackage;
172 @NotNull
173 private final JsExpression defineRootPackage;
174 @NotNull
175 private final JsName objectName;
176 @NotNull
177 private final JsName enumEntriesName;
178 @NotNull
179 private final JsExpression undefinedExpression;
180 @NotNull
181 private final JsExpression callGetProperty;
182 @NotNull
183 private final JsExpression callSetProperty;
184
185 @NotNull
186 private final JsName isTypeName;
187
188 private Namer(@NotNull JsScope rootScope) {
189 kotlinName = rootScope.declareName(KOTLIN_NAME);
190 kotlinScope = new JsScope(rootScope, "Kotlin standard object");
191 traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
192
193 definePackage = kotlin("definePackage");
194 defineRootPackage = kotlin("defineRootPackage");
195
196 callGetProperty = kotlin("callGetter");
197 callSetProperty = kotlin("callSetter");
198
199 className = kotlinScope.declareName(CLASS_OBJECT_NAME);
200 enumEntriesName = kotlinScope.declareName(ENUM_ENTRIES_NAME);
201 objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
202
203 isTypeName = kotlinScope.declareName("isType");
204
205 undefinedExpression = new JsPrefixOperation(JsUnaryOperator.VOID, rootScope.getProgram().getNumberLiteral(0));
206 }
207
208 @NotNull
209 public JsExpression classCreationMethodReference() {
210 return kotlin(className);
211 }
212
213 @NotNull
214 public JsExpression enumEntriesCreationMethodReference() {
215 return kotlin(enumEntriesName);
216 }
217
218 @NotNull
219 public JsExpression traitCreationMethodReference() {
220 return kotlin(traitName);
221 }
222
223 @NotNull
224 public JsExpression packageDefinitionMethodReference() {
225 return definePackage;
226 }
227
228 @NotNull
229 public JsExpression rootPackageDefinitionMethodReference() {
230 return defineRootPackage;
231 }
232
233 @NotNull
234 public JsExpression objectCreationMethodReference() {
235 return kotlin(objectName);
236 }
237
238 @NotNull
239 public JsExpression throwNPEFunctionRef() {
240 return new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject());
241 }
242
243 @NotNull
244 private JsNameRef kotlin(@NotNull JsName name) {
245 return new JsNameRef(name, kotlinObject());
246 }
247
248 @NotNull
249 public JsExpression kotlin(@NotNull String name) {
250 return kotlin(kotlinScope.declareName(name));
251 }
252
253 @NotNull
254 public JsNameRef kotlinObject() {
255 return kotlinName.makeRef();
256 }
257
258 @NotNull
259 public JsExpression isOperationReference() {
260 return kotlin(isTypeName);
261 }
262
263 @NotNull
264 /*package*/ JsScope getKotlinScope() {
265 return kotlinScope;
266 }
267
268 @NotNull
269 static String generatePackageName(@NotNull FqName packageFqName) {
270 return packageFqName.isRoot() ? getRootPackageName() : packageFqName.shortName().asString();
271 }
272
273 @NotNull
274 public JsExpression classCreateInvocation(@NotNull ClassDescriptor descriptor) {
275 ClassKind kind = descriptor.getKind();
276 if (kind == TRAIT) {
277 return traitCreationMethodReference();
278 }
279
280 if (kind.isSingleton() || DescriptorUtils.isAnonymousObject(descriptor)) {
281 return objectCreationMethodReference();
282 }
283
284 return classCreationMethodReference();
285 }
286
287 @NotNull
288 public JsInvocation enumEntriesObjectCreateInvocation() {
289 return new JsInvocation(enumEntriesCreationMethodReference());
290 }
291
292 @NotNull
293 public JsExpression getUndefinedExpression() {
294 return undefinedExpression;
295 }
296
297 @NotNull
298 public JsExpression getCallGetProperty() {
299 return callGetProperty;
300 }
301
302 @NotNull
303 public JsExpression getCallSetProperty() {
304 return callSetProperty;
305 }
306 }