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