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.jet.lang.resolve.calls.autocasts;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.jet.lang.resolve.BindingContext;
021 import org.jetbrains.jet.lang.resolve.BindingTrace;
022 import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
023 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
024 import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
025 import org.jetbrains.jet.lang.types.JetType;
026
027 import java.util.ArrayList;
028 import java.util.Collections;
029 import java.util.List;
030 import java.util.Set;
031
032 import static org.jetbrains.jet.lang.diagnostics.Errors.AUTOCAST_IMPOSSIBLE;
033 import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
034 import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE;
035
036 public class AutoCastUtils {
037
038 private AutoCastUtils() {}
039
040 /**
041 * @return variants @param receiverToCast may be cast to according to @param dataFlowInfo, @param receiverToCast itself is NOT included
042 */
043 @NotNull
044 public static List<ReceiverValue> getAutoCastVariants(
045 @NotNull BindingContext bindingContext,
046 @NotNull DataFlowInfo dataFlowInfo,
047 @NotNull ReceiverValue receiverToCast
048 ) {
049 if (receiverToCast instanceof ThisReceiver) {
050 ThisReceiver receiver = (ThisReceiver) receiverToCast;
051 assert receiver.exists();
052 DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(receiver);
053 return collectAutoCastReceiverValues(dataFlowInfo, receiver, dataFlowValue);
054 }
055 else if (receiverToCast instanceof ExpressionReceiver) {
056 ExpressionReceiver receiver = (ExpressionReceiver) receiverToCast;
057 DataFlowValue dataFlowValue =
058 DataFlowValueFactory.createDataFlowValue(receiver.getExpression(), receiver.getType(), bindingContext);
059 return collectAutoCastReceiverValues(dataFlowInfo, receiver, dataFlowValue);
060 }
061 else if (receiverToCast instanceof AutoCastReceiver) {
062 return getAutoCastVariants(bindingContext, dataFlowInfo, ((AutoCastReceiver) receiverToCast).getOriginal());
063 }
064 return Collections.emptyList();
065 }
066
067 @NotNull
068 private static List<ReceiverValue> collectAutoCastReceiverValues(
069 @NotNull DataFlowInfo dataFlowInfo,
070 @NotNull ReceiverValue receiver,
071 @NotNull DataFlowValue dataFlowValue
072 ) {
073 Set<JetType> possibleTypes = dataFlowInfo.getPossibleTypes(dataFlowValue);
074 List<ReceiverValue> result = new ArrayList<ReceiverValue>(possibleTypes.size());
075 for (JetType possibleType : possibleTypes) {
076 result.add(new AutoCastReceiver(receiver, possibleType, dataFlowValue.isStableIdentifier()));
077 }
078 return result;
079 }
080
081 public static void recordAutoCastIfNecessary(ReceiverValue receiver, @NotNull BindingTrace trace) {
082 if (receiver instanceof AutoCastReceiver) {
083 AutoCastReceiver autoCastReceiver = (AutoCastReceiver) receiver;
084 ReceiverValue original = autoCastReceiver.getOriginal();
085 if (original instanceof ExpressionReceiver) {
086 ExpressionReceiver expressionReceiver = (ExpressionReceiver) original;
087 if (autoCastReceiver.canCast()) {
088 trace.record(AUTOCAST, expressionReceiver.getExpression(), autoCastReceiver.getType());
089 trace.record(EXPRESSION_TYPE, expressionReceiver.getExpression(), autoCastReceiver.getType());
090 }
091 else {
092 trace.report(AUTOCAST_IMPOSSIBLE.on(expressionReceiver.getExpression(), autoCastReceiver.getType(), expressionReceiver.getExpression().getText()));
093 }
094 }
095 else {
096 assert autoCastReceiver.canCast() : "A non-expression receiver must always be autocastabe: " + original;
097 }
098 }
099 }
100 }