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