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