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 017package org.jetbrains.k2js.translate.reference; 018 019import com.google.dart.compiler.backend.js.ast.JsExpression; 020import org.jetbrains.annotations.NotNull; 021import org.jetbrains.annotations.Nullable; 022import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; 023import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; 024import org.jetbrains.jet.lang.psi.*; 025import org.jetbrains.k2js.translate.context.TranslationContext; 026import org.jetbrains.k2js.translate.utils.ErrorReportingUtils; 027 028import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression; 029import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression; 030import static org.jetbrains.k2js.translate.utils.PsiUtils.getNotNullSimpleNameSelector; 031import static org.jetbrains.k2js.translate.utils.PsiUtils.getSelector; 032 033public final class QualifiedExpressionTranslator { 034 035 private QualifiedExpressionTranslator() { 036 } 037 038 @NotNull 039 public static AccessTranslator getAccessTranslator(@NotNull JetQualifiedExpression expression, 040 @NotNull TranslationContext context) { 041 JsExpression receiver = translateReceiver(expression, context); 042 PropertyAccessTranslator result = 043 PropertyAccessTranslator.newInstance(getNotNullSimpleNameSelector(expression), receiver, 044 CallType.getCallTypeForQualifiedExpression(expression), context); 045 result.setCallType(CallType.getCallTypeForQualifiedExpression(expression)); 046 return result; 047 } 048 049 @NotNull 050 public static JsExpression translateQualifiedExpression(@NotNull JetQualifiedExpression expression, 051 @NotNull TranslationContext context) { 052 JsExpression receiver = translateReceiver(expression, context); 053 JetExpression selector = getSelector(expression); 054 CallType callType = CallType.getCallTypeForQualifiedExpression(expression); 055 return dispatchToCorrectTranslator(receiver, selector, callType, context); 056 } 057 058 @NotNull 059 private static JsExpression dispatchToCorrectTranslator(@Nullable JsExpression receiver, 060 @NotNull JetExpression selector, 061 @NotNull CallType callType, 062 @NotNull TranslationContext context) { 063 if (PropertyAccessTranslator.canBePropertyGetterCall(selector, context)) { 064 assert selector instanceof JetSimpleNameExpression : "Selectors for properties must be simple names."; 065 return PropertyAccessTranslator.translateAsPropertyGetterCall 066 ((JetSimpleNameExpression)selector, receiver, callType, context); 067 } 068 if (selector instanceof JetCallExpression) { 069 return invokeCallExpressionTranslator(receiver, selector, callType, context); 070 } 071 //TODO: never get there 072 if (selector instanceof JetSimpleNameExpression) { 073 return ReferenceTranslator.translateSimpleName((JetSimpleNameExpression)selector, context); 074 } 075 throw new AssertionError("Unexpected qualified expression: " + selector.getText()); 076 } 077 078 @NotNull 079 private static JsExpression invokeCallExpressionTranslator(@Nullable JsExpression receiver, 080 @NotNull JetExpression selector, 081 @NotNull CallType callType, 082 @NotNull TranslationContext context) { 083 try { 084 return CallExpressionTranslator.translate((JetCallExpression) selector, receiver, callType, context); 085 } catch (RuntimeException e) { 086 throw ErrorReportingUtils.reportErrorWithLocation(selector, e); 087 } 088 } 089 090 @Nullable 091 private static JsExpression translateReceiver(@NotNull JetQualifiedExpression expression, 092 @NotNull TranslationContext context) { 093 JetExpression receiverExpression = expression.getReceiverExpression(); 094 if (isFullQualifierForExpression(receiverExpression, context)) { 095 return null; 096 } 097 return translateAsExpression(receiverExpression, context); 098 } 099 100 //TODO: prove correctness 101 private static boolean isFullQualifierForExpression(@Nullable JetExpression receiverExpression, @NotNull TranslationContext context) { 102 if (receiverExpression == null) { 103 return false; 104 } 105 if (receiverExpression instanceof JetReferenceExpression) { 106 DeclarationDescriptor descriptorForReferenceExpression = 107 getDescriptorForReferenceExpression(context.bindingContext(), (JetReferenceExpression)receiverExpression); 108 if (descriptorForReferenceExpression instanceof NamespaceDescriptor) { 109 return true; 110 } 111 } 112 if (receiverExpression instanceof JetQualifiedExpression) { 113 return isFullQualifierForExpression(((JetQualifiedExpression)receiverExpression).getSelectorExpression(), context); 114 } 115 return false; 116 } 117}