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