001 /* 002 * Copyright 2010-2015 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.resolve; 018 019 import com.google.common.collect.Lists; 020 import com.intellij.openapi.util.Pair; 021 import com.intellij.psi.PsiElement; 022 import com.intellij.psi.util.PsiTreeUtil; 023 import kotlin.jvm.functions.Function3; 024 import org.jetbrains.annotations.NotNull; 025 import org.jetbrains.annotations.Nullable; 026 import org.jetbrains.kotlin.descriptors.*; 027 import org.jetbrains.kotlin.diagnostics.Diagnostic; 028 import org.jetbrains.kotlin.diagnostics.Severity; 029 import org.jetbrains.kotlin.psi.*; 030 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt; 031 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; 032 import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall; 033 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory; 034 import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression; 035 import org.jetbrains.kotlin.types.KotlinType; 036 import org.jetbrains.kotlin.types.TypeUtils; 037 import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo; 038 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt; 039 import org.jetbrains.kotlin.util.slicedMap.*; 040 041 import java.util.Collection; 042 import java.util.EnumMap; 043 import java.util.Map; 044 045 import static org.jetbrains.kotlin.diagnostics.Errors.AMBIGUOUS_LABEL; 046 import static org.jetbrains.kotlin.resolve.BindingContext.*; 047 048 public class BindingContextUtils { 049 private BindingContextUtils() { 050 } 051 052 @Nullable 053 public static VariableDescriptor extractVariableFromResolvedCall( 054 @NotNull BindingContext bindingContext, 055 @Nullable KtElement callElement 056 ) { 057 ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt.getResolvedCall(callElement, bindingContext); 058 if (resolvedCall == null || !(resolvedCall.getResultingDescriptor() instanceof VariableDescriptor)) return null; 059 return (VariableDescriptor) resolvedCall.getResultingDescriptor(); 060 } 061 062 @Nullable 063 public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable KtElement element, boolean onlyReference) { 064 DeclarationDescriptor descriptor = null; 065 if (!onlyReference && (element instanceof KtVariableDeclaration || element instanceof KtParameter)) { 066 descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); 067 } 068 else if (element instanceof KtSimpleNameExpression) { 069 descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (KtSimpleNameExpression) element); 070 } 071 else if (element instanceof KtQualifiedExpression) { 072 descriptor = extractVariableDescriptorIfAny(bindingContext, ((KtQualifiedExpression) element).getSelectorExpression(), onlyReference); 073 } 074 if (descriptor instanceof VariableDescriptor) { 075 return (VariableDescriptor) descriptor; 076 } 077 return null; 078 } 079 080 public static void recordFunctionDeclarationToDescriptor(@NotNull BindingTrace trace, 081 @NotNull PsiElement psiElement, @NotNull SimpleFunctionDescriptor function) { 082 trace.record(BindingContext.FUNCTION, psiElement, function); 083 } 084 085 @NotNull 086 public static <K, V> V getNotNull( 087 @NotNull BindingContext bindingContext, 088 @NotNull ReadOnlySlice<K, V> slice, 089 @NotNull K key 090 ) { 091 return getNotNull(bindingContext, slice, key, "Value at " + slice + " must not be null for " + key); 092 } 093 094 @NotNull 095 public static KotlinType getTypeNotNull( 096 @NotNull BindingContext bindingContext, 097 @NotNull KtExpression expression 098 ) { 099 KotlinType result = bindingContext.getType(expression); 100 if (result == null) { 101 throw new IllegalStateException("Type must be not null for " + expression); 102 } 103 return result; 104 } 105 106 @NotNull 107 public static <K, V> V getNotNull( 108 @NotNull BindingContext bindingContext, 109 @NotNull ReadOnlySlice<K, V> slice, 110 @NotNull K key, 111 @NotNull String messageIfNull 112 ) { 113 V value = bindingContext.get(slice, key); 114 if (value == null) { 115 throw new IllegalStateException(messageIfNull); 116 } 117 return value; 118 } 119 120 @NotNull 121 public static DeclarationDescriptor getEnclosingDescriptor(@NotNull BindingContext context, @NotNull KtElement element) { 122 KtNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, KtNamedDeclaration.class); 123 if (declaration instanceof KtFunctionLiteral) { 124 return getEnclosingDescriptor(context, declaration); 125 } 126 DeclarationDescriptor descriptor = context.get(DECLARATION_TO_DESCRIPTOR, declaration); 127 assert descriptor != null : "No descriptor for named declaration: " + declaration.getText() + "\n(of type " + declaration.getClass() + ")"; 128 return descriptor; 129 } 130 131 public static FunctionDescriptor getEnclosingFunctionDescriptor(@NotNull BindingContext context, @NotNull KtElement element) { 132 KtFunction function = PsiTreeUtil.getParentOfType(element, KtFunction.class); 133 return (FunctionDescriptor)context.get(DECLARATION_TO_DESCRIPTOR, function); 134 } 135 136 public static void reportAmbiguousLabel( 137 @NotNull BindingTrace trace, 138 @NotNull KtSimpleNameExpression targetLabel, 139 @NotNull Collection<DeclarationDescriptor> declarationsByLabel 140 ) { 141 Collection<PsiElement> targets = Lists.newArrayList(); 142 for (DeclarationDescriptor descriptor : declarationsByLabel) { 143 PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(descriptor); 144 assert element != null : "Label can only point to something in the same lexical scope"; 145 targets.add(element); 146 } 147 if (!targets.isEmpty()) { 148 trace.record(AMBIGUOUS_LABEL_TARGET, targetLabel, targets); 149 } 150 trace.report(AMBIGUOUS_LABEL.on(targetLabel)); 151 } 152 153 @Nullable 154 public static KotlinType updateRecordedType( 155 @Nullable KotlinType type, 156 @NotNull KtExpression expression, 157 @NotNull BindingTrace trace, 158 boolean shouldBeMadeNullable 159 ) { 160 if (type == null) return null; 161 if (shouldBeMadeNullable) { 162 type = TypeUtils.makeNullable(type); 163 } 164 trace.recordType(expression, type); 165 return type; 166 } 167 168 @Nullable 169 public static KotlinTypeInfo getRecordedTypeInfo(@NotNull KtExpression expression, @NotNull BindingContext context) { 170 // noinspection ConstantConditions 171 if (!context.get(BindingContext.PROCESSED, expression)) return null; 172 // NB: should never return null if expression is already processed 173 KotlinTypeInfo result = context.get(BindingContext.EXPRESSION_TYPE_INFO, expression); 174 return result != null ? result : TypeInfoFactoryKt.noTypeInfo(DataFlowInfoFactory.EMPTY); 175 } 176 177 public static boolean isExpressionWithValidReference( 178 @NotNull KtExpression expression, 179 @NotNull BindingContext context 180 ) { 181 if (expression instanceof KtCallExpression) { 182 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, context); 183 return resolvedCall instanceof VariableAsFunctionResolvedCall; 184 } 185 return expression instanceof KtReferenceExpression; 186 } 187 188 public static boolean isVarCapturedInClosure(BindingContext bindingContext, DeclarationDescriptor descriptor) { 189 if (!(descriptor instanceof VariableDescriptor) || descriptor instanceof PropertyDescriptor) return false; 190 VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; 191 return bindingContext.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null && variableDescriptor.isVar(); 192 } 193 194 @NotNull 195 public static Pair<FunctionDescriptor, PsiElement> getContainingFunctionSkipFunctionLiterals( 196 @Nullable DeclarationDescriptor startDescriptor, 197 boolean strict 198 ) { 199 FunctionDescriptor containingFunctionDescriptor = DescriptorUtils.getParentOfType(startDescriptor, FunctionDescriptor.class, strict); 200 PsiElement containingFunction = 201 containingFunctionDescriptor != null ? DescriptorToSourceUtils.getSourceFromDescriptor(containingFunctionDescriptor) : null; 202 while (containingFunction instanceof KtFunctionLiteral) { 203 containingFunctionDescriptor = DescriptorUtils.getParentOfType(containingFunctionDescriptor, FunctionDescriptor.class); 204 containingFunction = containingFunctionDescriptor != null ? DescriptorToSourceUtils 205 .getSourceFromDescriptor(containingFunctionDescriptor) : null; 206 } 207 208 return new Pair<FunctionDescriptor, PsiElement>(containingFunctionDescriptor, containingFunction); 209 } 210 211 @Nullable 212 public static ResolvedCall<ConstructorDescriptor> getDelegationConstructorCall( 213 @NotNull BindingContext bindingContext, 214 @NotNull ConstructorDescriptor constructorDescriptor 215 ) { 216 return bindingContext.get(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructorDescriptor); 217 } 218 219 static void addOwnDataTo( 220 @NotNull final BindingTrace trace, @Nullable final TraceEntryFilter filter, boolean commitDiagnostics, 221 @NotNull MutableSlicedMap map, MutableDiagnosticsWithSuppression diagnostics 222 ) { 223 map.forEach(new Function3<WritableSlice, Object, Object, Void>() { 224 @Override 225 public Void invoke(WritableSlice slice, Object key, Object value) { 226 if (filter == null || filter.accept(slice, null, key)) { 227 trace.record(slice, key, value); 228 } 229 230 return null; 231 } 232 }); 233 234 if (!commitDiagnostics) return; 235 236 for (Diagnostic diagnostic : diagnostics.getOwnDiagnostics()) { 237 if (filter == null || filter.accept(null, diagnostic, diagnostic.getPsiElement())) { 238 trace.report(diagnostic); 239 } 240 } 241 242 } 243 }