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.DeclarationDescriptor;
023 import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
024 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
025 import org.jetbrains.jet.plugin.JetLanguage;
026
027 import java.util.List;
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 CLASS_OBJECT_NAME = "createClass";
041 private static final String TRAIT_OBJECT_NAME = "createTrait";
042 private static final String OBJECT_OBJECT_NAME = "createObject";
043 private static final String ENUM_ENTRIES_NAME = "createEnumEntries";
044 private static final String SETTER_PREFIX = "set_";
045 private static final String GETTER_PREFIX = "get_";
046 private static final String BACKING_FIELD_PREFIX = "$";
047 private static final String SUPER_METHOD_NAME = "baseInitializer";
048 private static final String ROOT_NAMESPACE = "_";
049 private static final String RECEIVER_PARAMETER_NAME = "$receiver";
050 private static final String THROW_NPE_FUN_NAME = "throwNPE";
051 private static final String CLASS_OBJECT_GETTER = "object";
052 private static final String CLASS_OBJECT_INITIALIZER = "object_initializer$";
053 private static final String PROTOTYPE_NAME = "prototype";
054
055
056 private static final String DELEGATE_POSTFIX = "$delegate";
057 private static final String PROPERTY_METADATA = "PropertyMetadata";
058
059 @NotNull
060 public static String getReceiverParameterName() {
061 return RECEIVER_PARAMETER_NAME;
062 }
063
064 @NotNull
065 public static String getRootNamespaceName() {
066 return ROOT_NAMESPACE;
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
143 @NotNull
144 public static Namer newInstance(@NotNull JsScope rootScope) {
145 return new Namer(rootScope);
146 }
147
148 @NotNull
149 private final JsName kotlinName;
150 @NotNull
151 private final JsScope kotlinScope;
152 @NotNull
153 private final JsName className;
154 @NotNull
155 private final JsName traitName;
156 @NotNull
157 private final JsExpression definePackage;
158 @NotNull
159 private final JsExpression defineRootPackage;
160 @NotNull
161 private final JsName objectName;
162 @NotNull
163 private final JsName enumEntriesName;
164 @NotNull
165 private final JsExpression undefinedExpression;
166 @NotNull
167 private final JsExpression callGetProperty;
168 @NotNull
169 private final JsExpression callSetProperty;
170
171 @NotNull
172 private final JsName isTypeName;
173
174 private Namer(@NotNull JsScope rootScope) {
175 kotlinName = rootScope.declareName(KOTLIN_NAME);
176 kotlinScope = new JsScope(rootScope, "Kotlin standard object");
177 traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
178
179 definePackage = kotlin("definePackage");
180 defineRootPackage = kotlin("defineRootPackage");
181
182 callGetProperty = kotlin("callGetter");
183 callSetProperty = kotlin("callSetter");
184
185 className = kotlinScope.declareName(CLASS_OBJECT_NAME);
186 enumEntriesName = kotlinScope.declareName(ENUM_ENTRIES_NAME);
187 objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
188
189 isTypeName = kotlinScope.declareName("isType");
190
191 undefinedExpression = new JsPrefixOperation(JsUnaryOperator.VOID, rootScope.getProgram().getNumberLiteral(0));
192 }
193
194 @NotNull
195 public JsExpression classCreationMethodReference() {
196 return kotlin(className);
197 }
198
199 @NotNull
200 public JsExpression enumEntriesCreationMethodReference() {
201 return kotlin(enumEntriesName);
202 }
203
204 @NotNull
205 public JsExpression traitCreationMethodReference() {
206 return kotlin(traitName);
207 }
208
209 @NotNull
210 public JsExpression packageDefinitionMethodReference() {
211 return definePackage;
212 }
213
214 @NotNull
215 public JsExpression rootPackageDefinitionMethodReference() {
216 return defineRootPackage;
217 }
218
219 @NotNull
220 public JsExpression objectCreationMethodReference() {
221 return kotlin(objectName);
222 }
223
224 @NotNull
225 public JsExpression throwNPEFunctionRef() {
226 return new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject());
227 }
228
229 @NotNull
230 public JsNameRef propertyMetadataRef() {
231 return new JsNameRef(PROPERTY_METADATA, kotlinObject());
232 }
233
234 @NotNull
235 private JsNameRef kotlin(@NotNull JsName name) {
236 return new JsNameRef(name, kotlinObject());
237 }
238
239 @NotNull
240 public JsExpression kotlin(@NotNull String name) {
241 return kotlin(kotlinScope.declareName(name));
242 }
243
244 @NotNull
245 public JsNameRef kotlinObject() {
246 return kotlinName.makeRef();
247 }
248
249 @NotNull
250 public JsExpression isOperationReference() {
251 return kotlin(isTypeName);
252 }
253
254 @NotNull
255 /*package*/ JsScope getKotlinScope() {
256 return kotlinScope;
257 }
258
259 @NotNull
260 static String generateNamespaceName(@NotNull DeclarationDescriptor descriptor) {
261 if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
262 return getRootNamespaceName();
263 }
264 else {
265 return descriptor.getName().asString();
266 }
267 }
268
269 @NotNull
270 public JsInvocation classCreateInvocation(@NotNull ClassDescriptor descriptor, @NotNull List<JsExpression> arguments) {
271 switch (descriptor.getKind()) {
272 case TRAIT:
273 return new JsInvocation(traitCreationMethodReference(), arguments);
274
275 case OBJECT:
276 case CLASS_OBJECT:
277 case ENUM_ENTRY:
278 return new JsInvocation(objectCreationMethodReference(), arguments);
279
280 default:
281 return new JsInvocation(classCreationMethodReference(), arguments);
282 }
283 }
284
285 @NotNull
286 public JsInvocation enumEntriesObjectCreateInvocation() {
287 return new JsInvocation(enumEntriesCreationMethodReference());
288 }
289
290 @NotNull
291 public JsExpression getUndefinedExpression() {
292 return undefinedExpression;
293 }
294
295 @NotNull
296 public JsExpression getCallGetProperty() {
297 return callGetProperty;
298 }
299
300 @NotNull
301 public JsExpression getCallSetProperty() {
302 return callSetProperty;
303 }
304 }