use of org.jetbrains.kotlin.resolve.BindingContext in project kotlin by JetBrains.
the class ControlStructureTypingVisitor method visitIfExpression.
public KotlinTypeInfo visitIfExpression(KtIfExpression ifExpression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
components.dataFlowAnalyzer.recordExpectedType(contextWithExpectedType.trace, ifExpression, contextWithExpectedType.expectedType);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
KtExpression condition = ifExpression.getCondition();
DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);
boolean loopBreakContinuePossibleInCondition = condition != null && containsJumpOutOfLoop(condition, context);
KtExpression elseBranch = ifExpression.getElse();
KtExpression thenBranch = ifExpression.getThen();
LexicalWritableScope thenScope = newWritableScopeImpl(context, LexicalScopeKind.THEN, components.overloadChecker);
LexicalWritableScope elseScope = newWritableScopeImpl(context, LexicalScopeKind.ELSE, components.overloadChecker);
DataFlowInfo thenInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, true, context).and(conditionDataFlowInfo);
DataFlowInfo elseInfo = components.dataFlowAnalyzer.extractDataFlowInfoFromCondition(condition, false, context).and(conditionDataFlowInfo);
if (elseBranch == null) {
if (thenBranch != null) {
KotlinTypeInfo result = getTypeInfoWhenOnlyOneBranchIsPresent(thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression);
// If jump was possible, take condition check info as the jump info
return result.getJumpOutPossible() ? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo) : result;
}
return TypeInfoFactoryKt.createTypeInfo(components.builtIns.getUnitType(), thenInfo.or(elseInfo));
}
if (thenBranch == null) {
return getTypeInfoWhenOnlyOneBranchIsPresent(elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
}
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
KtBlockExpression elseBlock = psiFactory.wrapInABlockWrapper(elseBranch);
Call callForIf = createCallForSpecialConstruction(ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock));
MutableDataFlowInfoForArguments dataFlowInfoForArguments = createDataFlowInfoForArgumentsForIfCall(callForIf, conditionDataFlowInfo, thenInfo, elseInfo);
ResolvedCall<FunctionDescriptor> resolvedCall = components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(callForIf, ResolveConstruct.IF, Lists.newArrayList("thenBranch", "elseBranch"), Lists.newArrayList(false, false), contextWithExpectedType, dataFlowInfoForArguments);
BindingContext bindingContext = context.trace.getBindingContext();
KotlinTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
KotlinTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
assert thenTypeInfo != null || elseTypeInfo != null : "Both branches of if expression were not processed: " + ifExpression.getText();
KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition;
DataFlowInfo resultDataFlowInfo;
if (elseTypeInfo == null) {
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible();
resultDataFlowInfo = thenTypeInfo.getDataFlowInfo();
} else if (thenTypeInfo == null) {
loopBreakContinuePossible |= elseTypeInfo.getJumpOutPossible();
resultDataFlowInfo = elseTypeInfo.getDataFlowInfo();
} else {
KotlinType thenType = thenTypeInfo.getType();
KotlinType elseType = elseTypeInfo.getType();
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
if (resultType != null && thenType != null && elseType != null) {
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue, components.languageVersionSettings);
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue, components.languageVersionSettings);
}
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
if (thenType == null && elseType == null) {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
} else if (thenType == null || (jumpInThen && !jumpInElse)) {
resultDataFlowInfo = elseDataFlowInfo;
} else if (elseType == null || (jumpInElse && !jumpInThen)) {
resultDataFlowInfo = thenDataFlowInfo;
} else {
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
}
if (thenType == null && jumpInElse || elseType == null && jumpInThen) {
return TypeInfoFactoryKt.noTypeInfo(resultDataFlowInfo);
}
}
// If break or continue was possible, take condition check info as the jump info
return TypeInfoFactoryKt.createTypeInfo(components.dataFlowAnalyzer.checkType(resultType, ifExpression, contextWithExpectedType), resultDataFlowInfo, loopBreakContinuePossible, loopBreakContinuePossibleInCondition ? context.dataFlowInfo : conditionDataFlowInfo);
}
use of org.jetbrains.kotlin.resolve.BindingContext in project kotlin by JetBrains.
the class KotlinCallerMethodsTreeStructure method buildChildren.
@NotNull
@Override
protected Object[] buildChildren(@NotNull HierarchyNodeDescriptor descriptor) {
final PsiElement element = getTargetElement(descriptor);
KtElement codeBlockForLocalDeclaration = getEnclosingElementForLocalDeclaration(element);
if (codeBlockForLocalDeclaration != null) {
BindingContext bindingContext = ResolutionUtils.analyze((KtElement) element, BodyResolveMode.FULL);
final Map<PsiReference, PsiElement> referencesToElements = new HashMap<PsiReference, PsiElement>();
codeBlockForLocalDeclaration.accept(new CalleeReferenceVisitorBase(bindingContext, true) {
@Override
protected void processDeclaration(KtSimpleNameExpression reference, PsiElement declaration) {
if (!declaration.equals(element))
return;
//noinspection unchecked
PsiElement container = PsiTreeUtil.getParentOfType(reference, KtNamedFunction.class, KtPropertyAccessor.class, KtClassOrObject.class);
if (container instanceof KtPropertyAccessor) {
container = PsiTreeUtil.getParentOfType(container, KtProperty.class);
}
if (container != null) {
referencesToElements.put(ReferenceUtilKt.getMainReference(reference), container);
}
}
});
return collectNodeDescriptors(descriptor, referencesToElements, null);
}
SearchScope searchScope = getSearchScope(scopeType, basePsiClass);
Map<PsiElement, HierarchyNodeDescriptor> methodToDescriptorMap = Maps.newHashMap();
Object[] javaCallers = null;
if (element instanceof PsiMethod) {
javaCallers = javaTreeStructure.getChildElements(getJavaNodeDescriptor(descriptor));
processPsiMethodCallers(Collections.singleton((PsiMethod) element), descriptor, methodToDescriptorMap, searchScope, true);
}
if (element instanceof KtNamedFunction || element instanceof KtSecondaryConstructor) {
Collection<PsiMethod> lightMethods = LightClassUtil.INSTANCE.getLightClassMethods((KtFunction) element);
processPsiMethodCallers(lightMethods, descriptor, methodToDescriptorMap, searchScope, false);
}
if (element instanceof KtProperty) {
LightClassUtil.PropertyAccessorsPsiMethods propertyMethods = LightClassUtil.INSTANCE.getLightClassPropertyMethods((KtProperty) element);
processPsiMethodCallers(propertyMethods, descriptor, methodToDescriptorMap, searchScope, false);
}
if (element instanceof KtClassOrObject) {
KtPrimaryConstructor constructor = ((KtClassOrObject) element).getPrimaryConstructor();
if (constructor != null) {
PsiMethod lightMethod = LightClassUtil.INSTANCE.getLightClassMethod(constructor);
processPsiMethodCallers(Collections.singleton(lightMethod), descriptor, methodToDescriptorMap, searchScope, false);
} else {
processKtClassOrObjectCallers((KtClassOrObject) element, descriptor, methodToDescriptorMap, searchScope);
}
}
Object[] callers = methodToDescriptorMap.values().toArray(new Object[methodToDescriptorMap.size()]);
return (javaCallers != null) ? ArrayUtil.mergeArrays(javaCallers, callers) : callers;
}
use of org.jetbrains.kotlin.resolve.BindingContext in project kotlin by JetBrains.
the class AbstractLoadJavaTest method doTestCompiledJava.
private void doTestCompiledJava(@NotNull String javaFileName, Configuration configuration) throws Exception {
final File srcDir = new File(tmpdir, "src");
File compiledDir = new File(tmpdir, "compiled");
assertTrue(srcDir.mkdir());
assertTrue(compiledDir.mkdir());
List<File> srcFiles = KotlinTestUtils.createTestFiles(new File(javaFileName).getName(), FileUtil.loadFile(new File(javaFileName), true), new TestFileFactoryNoModules<File>() {
@NotNull
@Override
public File create(@NotNull String fileName, @NotNull String text, @NotNull Map<String, String> directives) {
File targetFile = new File(srcDir, fileName);
try {
FileUtil.writeToFile(targetFile, text);
} catch (IOException e) {
throw new AssertionError(e);
}
return targetFile;
}
});
Pair<PackageViewDescriptor, BindingContext> javaPackageAndContext = compileJavaAndLoadTestPackageAndBindingContextFromBinary(srcFiles, compiledDir, ConfigurationKind.ALL);
checkJavaPackage(getTxtFile(javaFileName), javaPackageAndContext.first, javaPackageAndContext.second, configuration);
}
use of org.jetbrains.kotlin.resolve.BindingContext in project kotlin by JetBrains.
the class ExpressionCodegen method visitSimpleNameExpression.
@Override
public StackValue visitSimpleNameExpression(@NotNull KtSimpleNameExpression expression, @NotNull StackValue receiver) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
DeclarationDescriptor descriptor;
if (resolvedCall == null) {
descriptor = bindingContext.get(REFERENCE_TARGET, expression);
} else {
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall;
resolvedCall = call.getVariableCall();
}
descriptor = resolvedCall.getResultingDescriptor();
//Check early if KCallableNameProperty is applicable to prevent closure generation
StackValue intrinsicResult = applyIntrinsic(descriptor, KCallableNameProperty.class, resolvedCall, receiver);
if (intrinsicResult != null)
return intrinsicResult;
receiver = StackValue.receiver(resolvedCall, receiver, this, null);
if (descriptor instanceof FakeCallableDescriptorForObject) {
descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor();
}
}
assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'";
descriptor = descriptor.getOriginal();
boolean isSyntheticField = descriptor instanceof SyntheticFieldDescriptor;
if (isSyntheticField) {
descriptor = ((SyntheticFieldDescriptor) descriptor).getPropertyDescriptor();
}
StackValue intrinsicResult = applyIntrinsic(descriptor, IntrinsicPropertyGetter.class, resolvedCall, receiver);
if (intrinsicResult != null)
return intrinsicResult;
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.Companion.getInstances(state.getProject());
if (!codegenExtensions.isEmpty() && resolvedCall != null) {
ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v);
KotlinType returnType = propertyDescriptor.getReturnType();
for (ExpressionCodegenExtension extension : codegenExtensions) {
if (returnType != null) {
StackValue value = extension.applyProperty(receiver, resolvedCall, context);
if (value != null)
return value;
}
}
}
boolean directToField = isSyntheticField && contextKind() != OwnerKind.DEFAULT_IMPLS;
ClassDescriptor superCallTarget = resolvedCall == null ? null : getSuperCallTarget(resolvedCall.getCall());
if (directToField) {
receiver = StackValue.receiverWithoutReceiverArgument(receiver);
}
return intermediateValueForProperty(propertyDescriptor, directToField, directToField, superCallTarget, false, receiver, resolvedCall);
}
if (descriptor instanceof TypeAliasDescriptor) {
ClassDescriptor classDescriptor = ((TypeAliasDescriptor) descriptor).getClassDescriptor();
if (classDescriptor == null) {
throw new IllegalStateException("Type alias " + descriptor + " static member refernece should be rejected by type checker, " + "since there is no class corresponding to this type alias.");
}
descriptor = classDescriptor;
}
if (descriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
if (isObject(classDescriptor)) {
return StackValue.singleton(classDescriptor, typeMapper);
}
if (isEnumEntry(classDescriptor)) {
return StackValue.enumEntry(classDescriptor, typeMapper);
}
ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor();
if (companionObjectDescriptor != null) {
return StackValue.singleton(companionObjectDescriptor, typeMapper);
}
return StackValue.none();
}
StackValue localOrCaptured = findLocalOrCapturedValue(descriptor);
if (localOrCaptured != null) {
return localOrCaptured;
}
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
}
use of org.jetbrains.kotlin.resolve.BindingContext in project kotlin by JetBrains.
the class CheckerTestUtil method getDiagnosticsIncludingSyntaxErrors.
@NotNull
public static List<ActualDiagnostic> getDiagnosticsIncludingSyntaxErrors(@NotNull BindingContext bindingContext, @NotNull List<Pair<MultiTargetPlatform, BindingContext>> implementingModulesBindings, @NotNull PsiElement root, boolean markDynamicCalls, @Nullable List<DeclarationDescriptor> dynamicCallDescriptors) {
List<ActualDiagnostic> result = getDiagnosticsIncludingSyntaxErrors(bindingContext, root, markDynamicCalls, dynamicCallDescriptors, null);
List<Pair<MultiTargetPlatform, BindingContext>> sortedBindings = CollectionsKt.sortedWith(implementingModulesBindings, new Comparator<Pair<MultiTargetPlatform, BindingContext>>() {
@Override
public int compare(Pair<MultiTargetPlatform, BindingContext> o1, Pair<MultiTargetPlatform, BindingContext> o2) {
return o1.getFirst().compareTo(o2.getFirst());
}
});
for (Pair<MultiTargetPlatform, BindingContext> binding : sortedBindings) {
MultiTargetPlatform platform = binding.getFirst();
assert platform instanceof MultiTargetPlatform.Specific : "Implementing module must have a specific platform: " + platform;
result.addAll(getDiagnosticsIncludingSyntaxErrors(binding.getSecond(), root, markDynamicCalls, dynamicCallDescriptors, ((MultiTargetPlatform.Specific) platform).getPlatform()));
}
return result;
}
Aggregations