001 /*
002 * Copyright 2010-2016 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.kotlin.js.translate.expression;
018
019 import com.google.dart.compiler.backend.js.ast.*;
020 import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.psi.util.PsiTreeUtil;
023 import kotlin.collections.CollectionsKt;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.kotlin.descriptors.*;
027 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
028 import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention;
029 import org.jetbrains.kotlin.js.translate.context.Namer;
030 import org.jetbrains.kotlin.js.translate.context.TranslationContext;
031 import org.jetbrains.kotlin.js.translate.declaration.ClassTranslator;
032 import org.jetbrains.kotlin.js.translate.general.Translation;
033 import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor;
034 import org.jetbrains.kotlin.js.translate.operation.BinaryOperationTranslator;
035 import org.jetbrains.kotlin.js.translate.operation.UnaryOperationTranslator;
036 import org.jetbrains.kotlin.js.translate.reference.*;
037 import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
038 import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
039 import org.jetbrains.kotlin.js.translate.utils.UtilsKt;
040 import org.jetbrains.kotlin.psi.*;
041 import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
042 import org.jetbrains.kotlin.resolve.BindingContext;
043 import org.jetbrains.kotlin.resolve.BindingContextUtils;
044 import org.jetbrains.kotlin.resolve.DescriptorUtils;
045 import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
046 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
047 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
048 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
049 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
050 import org.jetbrains.kotlin.resolve.inline.InlineUtil;
051 import org.jetbrains.kotlin.types.KotlinType;
052
053 import java.util.ArrayList;
054 import java.util.List;
055
056 import static org.jetbrains.kotlin.js.translate.context.Namer.GET_KCLASS;
057 import static org.jetbrains.kotlin.js.translate.context.Namer.GET_KCLASS_FROM_EXPRESSION;
058 import static org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor;
059 import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
060 import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.*;
061 import static org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils.message;
062 import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
063 import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.newVar;
064 import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForDeclaration;
065 import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateInitializerForProperty;
066 import static org.jetbrains.kotlin.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
067 import static org.jetbrains.kotlin.resolve.BindingContext.LABEL_TARGET;
068 import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure;
069 import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt.getResolvedCallWithAssert;
070 import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression;
071 import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
072
073 public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
074 @Override
075 protected JsNode emptyResult(@NotNull TranslationContext context) {
076 return JsLiteral.NULL;
077 }
078
079 @Override
080 @NotNull
081 public JsNode visitConstantExpression(@NotNull KtConstantExpression expression, @NotNull TranslationContext context) {
082 return translateConstantExpression(expression, context).source(expression);
083 }
084
085 @NotNull
086 private static JsNode translateConstantExpression(@NotNull KtConstantExpression expression, @NotNull TranslationContext context) {
087 CompileTimeConstant<?> compileTimeValue = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext());
088 assert compileTimeValue != null : message(expression, "Expression is not compile time value: " + expression.getText() + " ");
089
090 JsNode result = Translation.translateConstant(compileTimeValue, expression, context);
091 if (result == null) {
092 throw new AssertionError(message(expression, "Unsupported constant expression: " + expression.getText() + " "));
093 }
094
095 return result;
096 }
097
098 @Override
099 @NotNull
100 public JsNode visitBlockExpression(@NotNull KtBlockExpression jetBlock, @NotNull TranslationContext context) {
101 List<KtExpression> statements = jetBlock.getStatements();
102 JsBlock jsBlock = new JsBlock();
103 for (KtExpression statement : statements) {
104 JsNode jsNode = Translation.translateExpression(statement, context, jsBlock);
105 JsStatement jsStatement = convertToStatement(jsNode);
106 if (!JsAstUtils.isEmptyStatement(jsStatement)) {
107 jsBlock.getStatements().add(jsStatement);
108 }
109 }
110 return jsBlock;
111 }
112
113 @Override
114 public JsNode visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration multiDeclaration, @NotNull TranslationContext context) {
115 KtExpression jetInitializer = multiDeclaration.getInitializer();
116 assert jetInitializer != null : "Initializer for multi declaration must be not null";
117 JsExpression initializer = Translation.translateAsExpression(jetInitializer, context);
118 return DestructuringDeclarationTranslator.translate(multiDeclaration, context.scope().declareTemporary(), initializer, context);
119 }
120
121 @Override
122 @NotNull
123 public JsNode visitReturnExpression(@NotNull KtReturnExpression jetReturnExpression, @NotNull TranslationContext context) {
124 KtExpression returned = jetReturnExpression.getReturnedExpression();
125
126 // TODO: add related descriptor to context and use it here
127 KtDeclarationWithBody parent = PsiTreeUtil.getParentOfType(jetReturnExpression, KtDeclarationWithBody.class);
128 if (parent instanceof KtSecondaryConstructor) {
129 return new JsReturn(new JsNameRef(Namer.ANOTHER_THIS_PARAMETER_NAME)).source(jetReturnExpression);
130 }
131
132 JsReturn jsReturn;
133 if (returned == null) {
134 jsReturn = new JsReturn(null);
135 }
136 else {
137 JsExpression jsReturnExpression = translateAsExpression(returned, context);
138
139 jsReturn = new JsReturn(jsReturnExpression);
140 }
141
142 MetadataProperties.setReturnTarget(jsReturn, getNonLocalReturnTarget(jetReturnExpression, context));
143
144 return jsReturn.source(jetReturnExpression);
145 }
146
147 @Nullable
148 private static FunctionDescriptor getNonLocalReturnTarget(
149 @NotNull KtReturnExpression expression,
150 @NotNull TranslationContext context
151 ) {
152 DeclarationDescriptor descriptor = context.getDeclarationDescriptor();
153 assert descriptor instanceof CallableMemberDescriptor : "Return expression can only be inside callable declaration: " +
154 PsiUtilsKt.getTextWithLocation(expression);
155 KtSimpleNameExpression target = expression.getTargetLabel();
156
157 //call inside lambda
158 if (isFunctionLiteral(descriptor) || isFunctionExpression(descriptor)) {
159 if (target == null) {
160 if (isFunctionLiteral(descriptor)) {
161 return BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst();
162 }
163 }
164 else {
165 PsiElement element = context.bindingContext().get(LABEL_TARGET, target);
166 descriptor = context.bindingContext().get(DECLARATION_TO_DESCRIPTOR, element);
167 }
168 }
169
170 assert descriptor == null || descriptor instanceof FunctionDescriptor :
171 "Function descriptor expected to be target of return label: " + PsiUtilsKt.getTextWithLocation(expression);
172 return (FunctionDescriptor) descriptor;
173 }
174
175 @Override
176 @NotNull
177 public JsNode visitParenthesizedExpression(@NotNull KtParenthesizedExpression expression,
178 @NotNull TranslationContext context) {
179 KtExpression expressionInside = expression.getExpression();
180 if (expressionInside != null) {
181 return Translation.translateExpression(expressionInside, context);
182 }
183 return JsEmpty.INSTANCE;
184 }
185
186 @Override
187 @NotNull
188 public JsNode visitBinaryExpression(@NotNull KtBinaryExpression expression,
189 @NotNull TranslationContext context) {
190 return BinaryOperationTranslator.translate(expression, context);
191 }
192
193 @Override
194 @NotNull
195 // assume it is a local variable declaration
196 public JsNode visitProperty(@NotNull KtProperty expression, @NotNull TranslationContext context) {
197 VariableDescriptor descriptor = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.VARIABLE, expression);
198 JsExpression initializer = translateInitializerForProperty(expression, context);
199
200 JsName name = context.getNameForDescriptor(descriptor);
201 if (isVarCapturedInClosure(context.bindingContext(), descriptor)) {
202 JsNameRef alias = getCapturedVarAccessor(name.makeRef());
203 initializer = JsAstUtils.wrapValue(alias, initializer == null ? JsLiteral.NULL : initializer);
204 }
205
206 return newVar(name, initializer).source(expression);
207 }
208
209 @Override
210 @NotNull
211 public JsNode visitCallableReferenceExpression(@NotNull KtCallableReferenceExpression expression, @NotNull TranslationContext context) {
212 return CallableReferenceTranslator.INSTANCE.translate(expression, context);
213 }
214
215 @Override
216 public JsNode visitClassLiteralExpression(
217 @NotNull KtClassLiteralExpression expression, TranslationContext context
218 ) {
219 KotlinType expressionType = context.bindingContext().getType(expression);
220 assert expressionType != null;
221
222 ClassifierDescriptor expressionClassifier = expressionType.getConstructor().getDeclarationDescriptor();
223 assert expressionClassifier != null && DescriptorUtils.getFqName(expressionClassifier).asString().equals("kotlin.reflect.KClass")
224 : "::class expression should be type checked to a KClass: " + expressionType;
225
226 KotlinType type = CollectionsKt.single(expressionType.getArguments()).getType();
227 JsNameRef referenceToJsClass = UtilsKt.getReferenceToJsClass(type, context);
228
229 ClassifierDescriptor typeClassifier = type.getConstructor().getDeclarationDescriptor();
230 if (typeClassifier != null && DescriptorUtils.isEnumEntry(typeClassifier)) {
231 return new JsInvocation(context.namer().kotlin(GET_KCLASS_FROM_EXPRESSION), referenceToJsClass);
232 }
233
234 return new JsInvocation(context.namer().kotlin(GET_KCLASS), referenceToJsClass);
235 }
236
237 @Override
238 @NotNull
239 public JsNode visitCallExpression(
240 @NotNull KtCallExpression expression,
241 @NotNull TranslationContext context
242 ) {
243 return CallExpressionTranslator.translate(expression, null, context).source(expression);
244 }
245
246 @Override
247 @NotNull
248 public JsNode visitIfExpression(@NotNull KtIfExpression expression, @NotNull TranslationContext context) {
249 assert expression.getCondition() != null : "condition should not ne null: " + expression.getText();
250 JsExpression testExpression = Translation.translateAsExpression(expression.getCondition(), context);
251
252 boolean isKotlinExpression = BindingContextUtilsKt.isUsedAsExpression(expression, context.bindingContext());
253
254 KtExpression thenExpression = expression.getThen();
255 KtExpression elseExpression = expression.getElse();
256
257 JsStatement thenStatement =
258 thenExpression != null ? Translation.translateAsStatementAndMergeInBlockIfNeeded(thenExpression, context) : null;
259 JsStatement elseStatement =
260 elseExpression != null ? Translation.translateAsStatementAndMergeInBlockIfNeeded(elseExpression, context) : null;
261
262 if (isKotlinExpression) {
263 JsExpression jsThenExpression = JsAstUtils.extractExpressionFromStatement(thenStatement);
264 JsExpression jsElseExpression = JsAstUtils.extractExpressionFromStatement(elseStatement);
265 boolean canBeJsExpression = jsThenExpression != null && jsElseExpression != null;
266 if (canBeJsExpression) {
267 return new JsConditional(testExpression, jsThenExpression, jsElseExpression).source(expression);
268 }
269 }
270 if (thenStatement == null) {
271 thenStatement = JsEmpty.INSTANCE;
272 }
273 JsIf ifStatement = new JsIf(testExpression, thenStatement, elseStatement);
274 return ifStatement.source(expression);
275 }
276
277 @Override
278 @NotNull
279 public JsExpression visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression,
280 @NotNull TranslationContext context) {
281 return ReferenceTranslator.translateSimpleName(expression, context).source(expression);
282 }
283
284 @Override
285 @NotNull
286 public JsNode visitWhileExpression(@NotNull KtWhileExpression expression, @NotNull TranslationContext context) {
287 return LoopTranslator.createWhile(false, expression, context);
288 }
289
290 @Override
291 @NotNull
292 public JsNode visitDoWhileExpression(@NotNull KtDoWhileExpression expression, @NotNull TranslationContext context) {
293 return LoopTranslator.createWhile(true, expression, context);
294 }
295
296 @Override
297 @NotNull
298 public JsNode visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, @NotNull TranslationContext context) {
299 JsStringLiteral stringLiteral = resolveAsStringConstant(expression, context);
300 if (stringLiteral != null) {
301 return stringLiteral;
302 }
303 return resolveAsTemplate(expression, context).source(expression);
304 }
305
306 @NotNull
307 private static JsNode resolveAsTemplate(@NotNull KtStringTemplateExpression expression,
308 @NotNull TranslationContext context) {
309 return StringTemplateTranslator.translate(expression, context);
310 }
311
312 @Nullable
313 private static JsStringLiteral resolveAsStringConstant(@NotNull KtExpression expression,
314 @NotNull TranslationContext context) {
315 Object value = getCompileTimeValue(context.bindingContext(), expression);
316 if (value == null) {
317 return null;
318 }
319 assert value instanceof String : "Compile time constant template should be a String constant.";
320 String constantString = (String) value;
321 return context.program().getStringLiteral(constantString);
322 }
323
324 @Override
325 @NotNull
326 public JsNode visitDotQualifiedExpression(@NotNull KtDotQualifiedExpression expression, @NotNull TranslationContext context) {
327 return QualifiedExpressionTranslator.translateQualifiedExpression(expression, context);
328 }
329
330 @Override
331 public JsNode visitLabeledExpression(@NotNull KtLabeledExpression expression, @NotNull TranslationContext context) {
332 KtExpression baseExpression = expression.getBaseExpression();
333 assert baseExpression != null;
334
335 if (BindingContextUtilsKt.isUsedAsExpression(expression, context.bindingContext())) {
336 return Translation.translateAsExpression(baseExpression, context).source(expression);
337 }
338
339 JsScope scope = context.scope();
340 assert scope instanceof JsFunctionScope: "Labeled statement is unexpected outside of function scope";
341 JsFunctionScope functionScope = (JsFunctionScope) scope;
342
343 String labelIdent = getReferencedName(expression.getTargetLabel());
344
345 JsName labelName = functionScope.enterLabel(labelIdent);
346 JsStatement baseStatement = Translation.translateAsStatement(baseExpression, context);
347 functionScope.exitLabel();
348
349 return new JsLabel(labelName, baseStatement).source(expression);
350 }
351
352 @Override
353 @NotNull
354 public JsNode visitPrefixExpression(
355 @NotNull KtPrefixExpression expression,
356 @NotNull TranslationContext context
357 ) {
358 return UnaryOperationTranslator.translate(expression, context).source(expression);
359 }
360
361 @Override
362 @NotNull
363 public JsNode visitPostfixExpression(@NotNull KtPostfixExpression expression,
364 @NotNull TranslationContext context) {
365 return UnaryOperationTranslator.translate(expression, context).source(expression);
366 }
367
368 @Override
369 @NotNull
370 public JsNode visitIsExpression(@NotNull KtIsExpression expression,
371 @NotNull TranslationContext context) {
372 return Translation.patternTranslator(context).translateIsExpression(expression);
373 }
374
375 @Override
376 @NotNull
377 public JsNode visitSafeQualifiedExpression(@NotNull KtSafeQualifiedExpression expression,
378 @NotNull TranslationContext context) {
379 return QualifiedExpressionTranslator.translateQualifiedExpression(expression, context).source(expression);
380 }
381
382 @Override
383 @Nullable
384 public JsNode visitWhenExpression(@NotNull KtWhenExpression expression,
385 @NotNull TranslationContext context) {
386 return WhenTranslator.translate(expression, context);
387 }
388
389 @Override
390 @NotNull
391 public JsNode visitBinaryWithTypeRHSExpression(
392 @NotNull KtBinaryExpressionWithTypeRHS expression,
393 @NotNull TranslationContext context
394 ) {
395 JsExpression jsExpression;
396
397 if (PatternTranslator.isCastExpression(expression)) {
398 jsExpression = PatternTranslator.newInstance(context).translateCastExpression(expression);
399 }
400 else {
401 jsExpression = Translation.translateAsExpression(expression.getLeft(), context);
402 }
403
404 return jsExpression.source(expression);
405 }
406
407 private static String getReferencedName(KtSimpleNameExpression expression) {
408 return expression.getReferencedName()
409 .replaceAll("^@", "")
410 .replaceAll("(?:^`(.*)`$)", "$1");
411 }
412
413 private static JsNameRef getTargetLabel(KtExpressionWithLabel expression, TranslationContext context) {
414 KtSimpleNameExpression labelElement = expression.getTargetLabel();
415 if (labelElement == null) {
416 return null;
417 }
418
419 String labelIdent = getReferencedName(labelElement);
420 JsScope scope = context.scope();
421 assert scope instanceof JsFunctionScope: "Labeled statement is unexpected outside of function scope";
422 JsName labelName = ((JsFunctionScope) scope).findLabel(labelIdent);
423 assert labelName != null;
424 return labelName.makeRef();
425 }
426
427 @Override
428 @NotNull
429 public JsNode visitBreakExpression(@NotNull KtBreakExpression expression, @NotNull TranslationContext context) {
430 return new JsBreak(getTargetLabel(expression, context)).source(expression);
431 }
432
433 @Override
434 @NotNull
435 public JsNode visitContinueExpression(@NotNull KtContinueExpression expression, @NotNull TranslationContext context) {
436 return new JsContinue(getTargetLabel(expression, context)).source(expression);
437 }
438
439 @Override
440 @NotNull
441 public JsNode visitLambdaExpression(@NotNull KtLambdaExpression expression, @NotNull TranslationContext context) {
442 return new LiteralFunctionTranslator(context).translate(expression.getFunctionLiteral());
443 }
444
445 @Override
446 @NotNull
447 public JsNode visitNamedFunction(@NotNull KtNamedFunction expression, @NotNull TranslationContext context) {
448 JsExpression alias = new LiteralFunctionTranslator(context).translate(expression);
449
450 FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
451 JsName name = context.getNameForDescriptor(descriptor);
452 if (InlineUtil.isInline(descriptor)) {
453 MetadataProperties.setStaticRef(name, alias);
454 }
455
456 boolean isExpression = BindingContextUtilsKt.isUsedAsExpression(expression, context.bindingContext());
457 JsNode result = isExpression ? alias : JsAstUtils.newVar(name, alias);
458
459 return result.source(expression);
460 }
461
462 @Override
463 @NotNull
464 public JsNode visitThisExpression(@NotNull KtThisExpression expression, @NotNull TranslationContext context) {
465 DeclarationDescriptor thisExpression =
466 getDescriptorForReferenceExpression(context.bindingContext(), expression.getInstanceReference());
467 assert thisExpression != null : "This expression must reference a descriptor: " + expression.getText();
468
469 return context.getDispatchReceiver(getReceiverParameterForDeclaration(thisExpression)).source(expression);
470 }
471
472 @Override
473 @NotNull
474 public JsNode visitArrayAccessExpression(@NotNull KtArrayAccessExpression expression,
475 @NotNull TranslationContext context) {
476 return AccessTranslationUtils.translateAsGet(expression, context);
477 }
478
479 @Override
480 @NotNull
481 public JsNode visitSuperExpression(@NotNull KtSuperExpression expression, @NotNull TranslationContext context) {
482 ResolvedCall<? extends CallableDescriptor> resolvedCall = getResolvedCallWithAssert(expression, context.bindingContext());
483 return context.getDispatchReceiver((ReceiverParameterDescriptor) resolvedCall.getResultingDescriptor());
484 }
485
486 @Override
487 @NotNull
488 public JsNode visitForExpression(@NotNull KtForExpression expression,
489 @NotNull TranslationContext context) {
490 return LoopTranslator.translateForExpression(expression, context).source(expression);
491 }
492
493 @Override
494 @NotNull
495 public JsNode visitTryExpression(
496 @NotNull KtTryExpression expression,
497 @NotNull TranslationContext context
498 ) {
499 return new TryTranslator(expression, context).translate();
500 }
501
502 @Override
503 @NotNull
504 public JsNode visitThrowExpression(@NotNull KtThrowExpression expression,
505 @NotNull TranslationContext context) {
506 KtExpression thrownExpression = expression.getThrownExpression();
507 assert thrownExpression != null : "Thrown expression must not be null";
508 return new JsThrow(translateAsExpression(thrownExpression, context)).source(expression);
509 }
510
511 @Override
512 @NotNull
513 public JsNode visitObjectLiteralExpression(@NotNull KtObjectLiteralExpression expression, @NotNull TranslationContext context) {
514 ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), expression.getObjectDeclaration());
515 ClassTranslator.TranslationResult result = translateClassOrObject(expression.getObjectDeclaration(), descriptor, context);
516 List<JsPropertyInitializer> properties = result.getProperties();
517 context.getDefinitionPlace().getProperties().addAll(properties);
518
519 JsExpression constructor = context.getQualifiedReference(descriptor);
520 List<DeclarationDescriptor> closure = context.getClassOrConstructorClosure(descriptor);
521 List<JsExpression> closureArgs = new ArrayList<JsExpression>();
522 if (closure != null) {
523 for (DeclarationDescriptor capturedValue : closure) {
524 closureArgs.add(context.getArgumentForClosureConstructor(capturedValue));
525 }
526 }
527
528 // In case of object expressions like this:
529 // object : SuperClass(A, B, ...)
530 // we may capture local variables in expressions A, B, etc. We don't want to generate local fields for these variables.
531 // Our ClassTranslator is capable of such thing, but case of object expression is a little special.
532 // Consider the following:
533 //
534 // class A(val x: Int) {
535 // fun foo() { object : A(x) }
536 //
537 // By calling A(x) super constructor we capture `this` explicitly. However, we can't tell which `A::this` we are mentioning,
538 // either `this` of an object literal or `this` of enclosing `class A`.
539 // Frontend treats it as `this` of enclosing class declaration, therefore it expects backend to generate
540 // super call in scope of `fun foo()` rather than define inner scope for object's constructor.
541 // Thus we generate this call here rather than relying on ClassTranslator.
542 ResolvedCall<FunctionDescriptor> superCall = BindingUtils.getSuperCall(context.bindingContext(),
543 expression.getObjectDeclaration());
544 if (superCall != null) {
545 assert context.getDeclarationDescriptor() != null : "This expression should be inside declaration: " +
546 PsiUtilsKt.getTextWithLocation(expression);
547 TranslationContext superCallContext = context.newDeclaration(context.getDeclarationDescriptor(), result.getDefinitionPlace());
548 closureArgs.addAll(CallArgumentTranslator.translate(superCall, null, superCallContext).getTranslateArguments());
549 }
550
551 return new JsNew(constructor, closureArgs);
552 }
553
554 @Override
555 public JsNode visitAnnotatedExpression(@NotNull KtAnnotatedExpression expression, TranslationContext context) {
556 for (KtAnnotationEntry entry : expression.getAnnotationEntries()) {
557 AnnotationDescriptor descriptor = context.bindingContext().get(BindingContext.ANNOTATION, entry);
558 if (descriptor == null) continue;
559
560 ClassifierDescriptor classifierDescriptor = descriptor.getType().getConstructor().getDeclarationDescriptor();
561 if (classifierDescriptor == null) continue;
562
563 KotlinRetention retention = DescriptorUtilsKt.getAnnotationRetention(classifierDescriptor);
564
565 if (retention == KotlinRetention.SOURCE) {
566 KtExpression baseExpression = expression.getBaseExpression();
567 if (baseExpression == null) continue;
568
569 return baseExpression.accept(this, context);
570 }
571 }
572
573 return super.visitAnnotatedExpression(expression, context);
574 }
575
576 @Override
577 public JsNode visitClass(@NotNull KtClass klass, TranslationContext context) {
578 ClassDescriptor descriptor = BindingUtils.getClassDescriptor(context.bindingContext(), klass);
579 context.getDefinitionPlace().getProperties().addAll(translateClassOrObject(klass, descriptor, context).getProperties());
580 return JsEmpty.INSTANCE;
581 }
582
583 private static ClassTranslator.TranslationResult translateClassOrObject(
584 @NotNull KtClassOrObject declaration,
585 @NotNull ClassDescriptor descriptor,
586 @NotNull TranslationContext context
587 ) {
588 JsScope scope = context.getScopeForDescriptor(descriptor);
589 TranslationContext classContext = context.innerWithUsageTracker(scope, descriptor);
590 return ClassTranslator.translate(declaration, classContext);
591 }
592 }