KT-2631 Check multiple assignment - in progress

check multiple declaration without specified type annotation
This commit is contained in:
Svetlana Isakova
2012-08-17 18:58:40 +04:00
committed by Andrey Breslav
parent 68ebdabf8f
commit a0da232ed3
6 changed files with 103 additions and 0 deletions
@@ -24,7 +24,9 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetTokens;
@@ -97,6 +99,9 @@ public interface Errors {
SimpleDiagnosticFactory<JetExpression> MANY_FUNCTION_LITERAL_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR);
SimpleDiagnosticFactory<JetProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, NAMED_ELEMENT);
SimpleDiagnosticFactory<JetMultiDeclaration> INITIALIZER_REQUIRED_FOR_MULTIDECLARATION = SimpleDiagnosticFactory.create(ERROR, DEFAULT);
DiagnosticFactory1<JetExpression, Name> COMPONENT_FUNCTION_MISSING = DiagnosticFactory1.create(ERROR, DEFAULT);
DiagnosticFactory2<JetExpression, Name, Collection<? extends ResolvedCall<? extends CallableDescriptor>>> COMPONENT_FUNCTION_AMBIGUITY = DiagnosticFactory2.create(ERROR, DEFAULT);
SimpleDiagnosticFactory<JetModifierListOwner> ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER);
SimpleDiagnosticFactory<JetProperty> ABSTRACT_PROPERTY_NOT_IN_CLASS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER);
@@ -112,6 +112,9 @@ public class DefaultErrorMessages {
MAP.put(MANY_FUNCTION_LITERAL_ARGUMENTS, "Only one function literal is allowed outside a parenthesized argument list");
MAP.put(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER, "This property must either have a type annotation or be initialized");
MAP.put(INITIALIZER_REQUIRED_FOR_MULTIDECLARATION, "Initializer required for multi-declaration");
MAP.put(COMPONENT_FUNCTION_MISSING, "Multi-declaration initializer must have a ''{0}()'' function", TO_STRING);
MAP.put(COMPONENT_FUNCTION_AMBIGUITY, "Method ''{0}'' is ambiguous for this expression: {1}", TO_STRING, AMBIGUOUS_CALLS);
MAP.put(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, "This property cannot be declared abstract");
MAP.put(ABSTRACT_PROPERTY_NOT_IN_CLASS, "A property may be abstract only when defined in a class or trait");
@@ -32,6 +32,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetTypeInfo;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
@@ -127,6 +128,45 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
return DataFlowUtils.checkStatementType(property, context, context.dataFlowInfo);
}
@Override
public JetTypeInfo visitMultiDeclaration(JetMultiDeclaration multiDeclaration, final ExpressionTypingContext context) {
final JetExpression initializer = multiDeclaration.getInitializer();
if (initializer == null) {
context.trace.report(INITIALIZER_REQUIRED_FOR_MULTIDECLARATION.on(multiDeclaration));
return JetTypeInfo.create(null, context.dataFlowInfo);
}
final ExpressionReceiver expressionReceiver = ExpressionTypingUtils.getExpressionReceiver(facade, initializer, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE));
if (expressionReceiver == null) {
return JetTypeInfo.create(null, context.dataFlowInfo);
}
int componentIndex = 0;
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
final Name componentName = Name.identifier("component" + componentIndex);
componentIndex++;
JetType componentType = null;
OverloadResolutionResults<FunctionDescriptor> results =
ExpressionTypingUtils.resolveFakeCall(expressionReceiver, context, componentName);
if (results.isSuccess()) {
componentType = results.getResultingDescriptor().getReturnType();
}
else if (results.isAmbiguity()) {
context.trace.report(COMPONENT_FUNCTION_AMBIGUITY.on(initializer, componentName, results.getResultingCalls()));
}
else {
context.trace.report(COMPONENT_FUNCTION_MISSING.on(initializer, componentName));
}
if (componentType == null) {
componentType = ErrorUtils.createErrorType(componentName + "() return type");
}
VariableDescriptor variableDescriptor = context.expressionTypingServices.getDescriptorResolver().
resolveLocalVariableDescriptorWithType(scope.getContainingDeclaration(), entry, componentType, context.trace);
scope.addVariableDescriptor(variableDescriptor);
}
return DataFlowUtils.checkStatementType(multiDeclaration, context, context.dataFlowInfo);
}
@Override
public JetTypeInfo visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
SimpleFunctionDescriptor functionDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function, context.trace);
@@ -0,0 +1,20 @@
package a
class MyClass {
fun component0(<!UNUSED_PARAMETER!>i<!>: Int) {}
}
class MyClass2 {}
<!CONFLICTING_OVERLOADS!>fun MyClass2.component0()<!> = 1.2
<!CONFLICTING_OVERLOADS!>fun MyClass2.component0()<!> = 1.3
fun test(<!UNUSED_PARAMETER!>mc1<!>: MyClass, <!UNUSED_PARAMETER!>mc2<!>: MyClass2) {
val (a, b) = <!COMPONENT_FUNCTION_MISSING, COMPONENT_FUNCTION_MISSING!>mc1<!>
val (c) = <!COMPONENT_FUNCTION_AMBIGUITY!>mc2<!>
//a,b,c are error types
a : Boolean
b : Boolean
c : Boolean
}
@@ -0,0 +1,25 @@
//KT-2631 Check multiple assignment
package a
class MyClass {
fun component0() = 1
fun component1() = "a"
}
class MyClass2 {}
fun MyClass2.component0() = 1.2
fun test(<!UNUSED_PARAMETER!>mc1<!>: MyClass, <!UNUSED_PARAMETER!>mc2<!>: MyClass2) {
val (a, b) = mc1
a : Int
b : String
val (c) = mc2
c : Double
//check no error types
<!TYPE_MISMATCH!>a<!> : Boolean
<!TYPE_MISMATCH!>b<!> : Boolean
<!TYPE_MISMATCH!>c<!> : Boolean
}
@@ -1073,11 +1073,21 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt2142.kt");
}
@TestMetadata("kt2631_MultipleDeclaration.kt")
public void testKt2631_MultipleDeclaration() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt2631_MultipleDeclaration.kt");
}
@TestMetadata("kt559.kt")
public void testKt559() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt559.kt");
}
@TestMetadata("MultiDeclarationErrors.kt")
public void testMultiDeclarationErrors() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/MultiDeclarationErrors.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/tests/extensions")