Search in sources :

Example 16 with BindingContext

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);
}
Also used : ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall(org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils.createDataFlowInfoForArgumentsForIfCall) KotlinType(org.jetbrains.kotlin.types.KotlinType) MutableDataFlowInfoForArguments(org.jetbrains.kotlin.resolve.calls.model.MutableDataFlowInfoForArguments) BindingContext(org.jetbrains.kotlin.resolve.BindingContext) DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) LexicalWritableScope(org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope) DataFlowInfo(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo)

Example 17 with BindingContext

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;
}
Also used : HashMap(com.intellij.util.containers.HashMap) BindingContext(org.jetbrains.kotlin.resolve.BindingContext) SearchScope(com.intellij.psi.search.SearchScope) LightClassUtil(org.jetbrains.kotlin.asJava.LightClassUtil) HierarchyNodeDescriptor(com.intellij.ide.hierarchy.HierarchyNodeDescriptor) NotNull(org.jetbrains.annotations.NotNull)

Example 18 with BindingContext

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);
}
Also used : IOException(java.io.IOException) BindingContext(org.jetbrains.kotlin.resolve.BindingContext) KtFile(org.jetbrains.kotlin.psi.KtFile) File(java.io.File) NotNull(org.jetbrains.annotations.NotNull)

Example 19 with BindingContext

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);
}
Also used : BindingContext(org.jetbrains.kotlin.resolve.BindingContext) SyntheticFieldDescriptor(org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor) FakeCallableDescriptorForObject(org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject) SyntheticJavaPropertyDescriptor(org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor) KotlinType(org.jetbrains.kotlin.types.KotlinType) ExpressionCodegenExtension(org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension)

Example 20 with BindingContext

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;
}
Also used : MultiTargetPlatform(org.jetbrains.kotlin.resolve.MultiTargetPlatform) BindingContext(org.jetbrains.kotlin.resolve.BindingContext) Pair(kotlin.Pair) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

BindingContext (org.jetbrains.kotlin.resolve.BindingContext)20 KtFile (org.jetbrains.kotlin.psi.KtFile)6 File (java.io.File)5 NotNull (org.jetbrains.annotations.NotNull)5 Nullable (org.jetbrains.annotations.Nullable)3 AnalysisResult (org.jetbrains.kotlin.analyzer.AnalysisResult)3 IOException (java.io.IOException)2 KotlinCoreEnvironment (org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment)2 ResolutionFacade (org.jetbrains.kotlin.idea.resolve.ResolutionFacade)2 KtNamedFunction (org.jetbrains.kotlin.psi.KtNamedFunction)2 KotlinType (org.jetbrains.kotlin.types.KotlinType)2 Type (org.jetbrains.org.objectweb.asm.Type)2 HierarchyNodeDescriptor (com.intellij.ide.hierarchy.HierarchyNodeDescriptor)1 Editor (com.intellij.openapi.editor.Editor)1 ProcessCanceledException (com.intellij.openapi.progress.ProcessCanceledException)1 PsiElement (com.intellij.psi.PsiElement)1 PsiFile (com.intellij.psi.PsiFile)1 PsiMethod (com.intellij.psi.PsiMethod)1 SearchScope (com.intellij.psi.search.SearchScope)1 HashMap (com.intellij.util.containers.HashMap)1