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