Analyze local variable declarations in expression position

Fixes exception on invalid code "val c = 1 < val Int.f: Int = 3"
This commit is contained in:
Pavel V. Talanov
2016-01-12 14:12:30 +03:00
parent 060864f7af
commit 9bfa90dc0e
7 changed files with 29 additions and 9 deletions
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.expressions.* import org.jetbrains.kotlin.types.expressions.*
@@ -47,9 +46,9 @@ class LocalVariableResolver(
fun process( fun process(
property: KtProperty, property: KtProperty,
typingContext: ExpressionTypingContext, typingContext: ExpressionTypingContext,
scope: LexicalWritableScope, scope: LexicalScope,
facade: ExpressionTypingFacade facade: ExpressionTypingFacade
): KotlinTypeInfo { ): Pair<KotlinTypeInfo, VariableDescriptor> {
val context = typingContext.replaceContextDependency(ContextDependency.INDEPENDENT).replaceScope(scope) val context = typingContext.replaceContextDependency(ContextDependency.INDEPENDENT).replaceScope(scope)
val receiverTypeRef = property.receiverTypeReference val receiverTypeRef = property.receiverTypeReference
if (receiverTypeRef != null) { if (receiverTypeRef != null) {
@@ -99,11 +98,10 @@ class LocalVariableResolver(
ExpressionTypingUtils.checkVariableShadowing(context.scope, context.trace, propertyDescriptor) ExpressionTypingUtils.checkVariableShadowing(context.scope, context.trace, propertyDescriptor)
scope.addVariableDescriptor(propertyDescriptor)
property.checkTypeReferences(context.trace) property.checkTypeReferences(context.trace)
modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(property, propertyDescriptor) modifiersChecker.withTrace(context.trace).checkModifiersForLocalDeclaration(property, propertyDescriptor)
identifierChecker.checkDeclaration(property, context.trace) identifierChecker.checkDeclaration(property, context.trace)
return typeInfo.replaceType(dataFlowAnalyzer.checkStatementType(property, context)) return Pair(typeInfo.replaceType(dataFlowAnalyzer.checkStatementType(property, context)), propertyDescriptor)
} }
private fun resolveLocalVariableDescriptor( private fun resolveLocalVariableDescriptor(
@@ -1461,13 +1461,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@NotNull @NotNull
private static KotlinTypeInfo declarationInIllegalContext( private static KotlinTypeInfo declarationInIllegalContext(
@NotNull KtDeclaration declaration, @NotNull KtDeclaration declaration,
@NotNull ExpressionTypingContext context @NotNull ExpressionTypingContext context
) { ) {
context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(declaration)); context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(declaration));
return TypeInfoFactoryKt.noTypeInfo(context); return TypeInfoFactoryKt.noTypeInfo(context);
} }
@Override
public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext context) {
components.localVariableResolver.process(property, context, context.scope, facade);
return declarationInIllegalContext(property, context);
}
@NotNull @NotNull
public KotlinTypeInfo getTypeInfoForBinaryCall( public KotlinTypeInfo getTypeInfoForBinaryCall(
@NotNull Name name, @NotNull Name name,
@@ -389,6 +389,11 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin
return basic.visitClass(klass, data); return basic.visitClass(klass, data);
} }
@Override
public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext data) {
return basic.visitProperty(property, data);
}
@Override @Override
public KotlinTypeInfo visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, ExpressionTypingContext data) { public KotlinTypeInfo visitStringTemplateExpression(@NotNull KtStringTemplateExpression expression, ExpressionTypingContext data) {
return basic.visitStringTemplateExpression(expression, data); return basic.visitStringTemplateExpression(expression, data);
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.types.expressions;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import kotlin.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
@@ -103,7 +104,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
@Override @Override
public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext typingContext) { public KotlinTypeInfo visitProperty(@NotNull KtProperty property, ExpressionTypingContext typingContext) {
return components.localVariableResolver.process(property, typingContext, scope, facade); Pair<KotlinTypeInfo, VariableDescriptor> typeInfoAndVariableDescriptor = components.localVariableResolver.process(property, typingContext, scope, facade);
scope.addVariableDescriptor(typeInfoAndVariableDescriptor.getSecond());
return typeInfoAndVariableDescriptor.getFirst();
} }
@Override @Override
@@ -1,3 +1,3 @@
fun test() { fun test() {
(d@ <!DECLARATION_IN_ILLEGAL_CONTEXT!>val bar = 2<!>) (d@ <!DECLARATION_IN_ILLEGAL_CONTEXT!>val <!UNUSED_VARIABLE!>bar<!> = 2<!>)
} }
@@ -0,0 +1,2 @@
val f = 1 >
<error descr="[DECLARATION_IN_ILLEGAL_CONTEXT] Declarations are not allowed in this position">val g: Int = 3</error>
@@ -562,6 +562,12 @@ public class PsiCheckerTestGenerated extends AbstractPsiCheckerTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("PropertyDeclarationAsExpression.kt")
public void testPropertyDeclarationAsExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/PropertyDeclarationAsExpression.kt");
doTest(fileName);
}
@TestMetadata("ScopeForSecondaryConstructors.kt") @TestMetadata("ScopeForSecondaryConstructors.kt")
public void testScopeForSecondaryConstructors() throws Exception { public void testScopeForSecondaryConstructors() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/ScopeForSecondaryConstructors.kt"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/ScopeForSecondaryConstructors.kt");