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.Named;
024 import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
025 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
026 import org.jetbrains.jet.plugin.JetLanguage;
027 import org.jetbrains.jet.lang.resolve.name.Name;
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 INITIALIZE_METHOD_NAME = "initialize";
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 = "super_init";
048 private static final String ROOT_NAMESPACE = "_";
049 private static final String RECEIVER_PARAMETER_NAME = "$receiver";
050 private static final String CLASSES_OBJECT_NAME = "classes";
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
055
056 private static final String DELEGATE_POSTFIX = "$delegate";
057 private static final String PROPERTY_METADATA = "PropertyMetadata";
058
059 private static final Named CLASS_OBJECT_INITIALIZER_NAMED = new Named() {
060 @NotNull
061 @Override
062 public Name getName() {
063 return Name.identifier(CLASS_OBJECT_INITIALIZER);
064 }
065 };
066
067 @NotNull
068 public static String getReceiverParameterName() {
069 return RECEIVER_PARAMETER_NAME;
070 }
071
072 @NotNull
073 public static String getRootNamespaceName() {
074 return ROOT_NAMESPACE;
075 }
076
077 @NotNull
078 public static JsNameRef initializeMethodReference() {
079 return new JsNameRef(INITIALIZE_METHOD_NAME);
080 }
081
082 @NotNull
083 public static String superMethodName() {
084 return SUPER_METHOD_NAME;
085 }
086
087 @NotNull
088 public static String nameForClassesVariable() {
089 return CLASSES_OBJECT_NAME;
090 }
091
092 @NotNull
093 public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter, boolean useNativeAccessor) {
094 if (useNativeAccessor) {
095 return propertyName;
096 }
097
098 if (isGetter) {
099 return getNameForGetter(propertyName);
100 }
101 else {
102 return getNameForSetter(propertyName);
103 }
104 }
105
106 @NotNull
107 public static String getKotlinBackingFieldName(@NotNull String propertyName) {
108 return getNameWithPrefix(propertyName, BACKING_FIELD_PREFIX);
109 }
110
111 @NotNull
112 private static String getNameForGetter(@NotNull String propertyName) {
113 return getNameWithPrefix(propertyName, GETTER_PREFIX);
114 }
115
116 @NotNull
117 private static String getNameForSetter(@NotNull String propertyName) {
118 return getNameWithPrefix(propertyName, SETTER_PREFIX);
119 }
120
121 @NotNull
122 public static JsExpression getClassObjectAccessor(@NotNull JsExpression referenceToClass) {
123 return new JsInvocation(new JsNameRef(CLASS_OBJECT_GETTER, referenceToClass));
124 }
125
126 @NotNull
127 public static Named getNamedForClassObjectInitializer() {
128 return CLASS_OBJECT_INITIALIZER_NAMED;
129 }
130
131 @NotNull
132 public static String getDelegateName(@NotNull String propertyName) {
133 return propertyName + DELEGATE_POSTFIX;
134 }
135
136 @NotNull
137 public static JsNameRef getDelegateNameRef(String propertyName) {
138 return new JsNameRef(getDelegateName(propertyName), JsLiteral.THIS);
139 }
140
141 @NotNull
142 private static String getNameWithPrefix(@NotNull String name, @NotNull String prefix) {
143 return prefix + name;
144 }
145
146 @NotNull
147 public static Namer newInstance(@NotNull JsScope rootScope) {
148 return new Namer(rootScope);
149 }
150
151 @NotNull
152 private final JsName kotlinName;
153 @NotNull
154 private final JsScope kotlinScope;
155 @NotNull
156 private final JsName className;
157 @NotNull
158 private final JsName traitName;
159 @NotNull
160 private final JsExpression definePackage;
161 @NotNull
162 private final JsName objectName;
163 @NotNull
164 private final JsName enumEntriesName;
165
166 @NotNull
167 private final JsName isTypeName;
168
169 private Namer(@NotNull JsScope rootScope) {
170 kotlinName = rootScope.declareName(KOTLIN_NAME);
171 kotlinScope = new JsScope(rootScope, "Kotlin standard object");
172 traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
173
174 definePackage = kotlin("definePackage");
175
176 className = kotlinScope.declareName(CLASS_OBJECT_NAME);
177 enumEntriesName = kotlinScope.declareName(ENUM_ENTRIES_NAME);
178 objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
179
180 isTypeName = kotlinScope.declareName("isType");
181 }
182
183 @NotNull
184 public JsExpression classCreationMethodReference() {
185 return kotlin(className);
186 }
187
188 @NotNull
189 public JsExpression enumEntriesCreationMethodReference() {
190 return kotlin(enumEntriesName);
191 }
192
193 @NotNull
194 public JsExpression traitCreationMethodReference() {
195 return kotlin(traitName);
196 }
197
198 @NotNull
199 public JsExpression packageDefinitionMethodReference() {
200 return definePackage;
201 }
202
203 @NotNull
204 public JsExpression objectCreationMethodReference() {
205 return kotlin(objectName);
206 }
207
208 @NotNull
209 public JsExpression throwNPEFunctionRef() {
210 return new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject());
211 }
212
213 @NotNull
214 public JsNameRef propertyMetadataRef() {
215 return new JsNameRef(PROPERTY_METADATA, kotlinObject());
216 }
217
218 @NotNull
219 private JsNameRef kotlin(@NotNull JsName name) {
220 return new JsNameRef(name, kotlinObject());
221 }
222
223 @NotNull
224 public JsExpression kotlin(@NotNull String name) {
225 return kotlin(kotlinScope.declareName(name));
226 }
227
228 @NotNull
229 public JsNameRef kotlinObject() {
230 return kotlinName.makeRef();
231 }
232
233 @NotNull
234 public JsExpression isOperationReference() {
235 return kotlin(isTypeName);
236 }
237
238 @NotNull
239 /*package*/ JsScope getKotlinScope() {
240 return kotlinScope;
241 }
242
243 @NotNull
244 static String generateNamespaceName(DeclarationDescriptor descriptor) {
245 if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
246 return getRootNamespaceName();
247 }
248 else {
249 return descriptor.getName().asString();
250 }
251 }
252
253 @NotNull
254 public JsInvocation classCreateInvocation(@NotNull ClassDescriptor descriptor) {
255 switch (descriptor.getKind()) {
256 case TRAIT:
257 return new JsInvocation(traitCreationMethodReference());
258
259 case OBJECT:
260 case CLASS_OBJECT:
261 case ENUM_ENTRY:
262 return new JsInvocation(objectCreationMethodReference());
263
264 default:
265 return new JsInvocation(classCreationMethodReference());
266 }
267 }
268
269 @NotNull
270 public JsInvocation enumEntriesObjectCreateInvocation() {
271 return new JsInvocation(enumEntriesCreationMethodReference());
272 }
273 }