From a0da232ed32fadd1abe055aa37547150bdf2fc3f Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Fri, 17 Aug 2012 18:58:40 +0400 Subject: [PATCH] KT-2631 Check multiple assignment - in progress check multiple declaration without specified type annotation --- .../jet/lang/diagnostics/Errors.java | 5 +++ .../rendering/DefaultErrorMessages.java | 3 ++ .../ExpressionTypingVisitorForStatements.java | 40 +++++++++++++++++++ .../MultiDeclarationErrors.kt | 20 ++++++++++ .../kt2631_MultipleDeclaration.kt | 25 ++++++++++++ .../checkers/JetDiagnosticsTestGenerated.java | 10 +++++ 6 files changed, 103 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/MultiDeclarationErrors.kt create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/kt2631_MultipleDeclaration.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 7b57957f861..fcbe9c2506e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -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 MANY_FUNCTION_LITERAL_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR); SimpleDiagnosticFactory PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, NAMED_ELEMENT); + SimpleDiagnosticFactory INITIALIZER_REQUIRED_FOR_MULTIDECLARATION = SimpleDiagnosticFactory.create(ERROR, DEFAULT); + DiagnosticFactory1 COMPONENT_FUNCTION_MISSING = DiagnosticFactory1.create(ERROR, DEFAULT); + DiagnosticFactory2>> COMPONENT_FUNCTION_AMBIGUITY = DiagnosticFactory2.create(ERROR, DEFAULT); SimpleDiagnosticFactory ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER); SimpleDiagnosticFactory ABSTRACT_PROPERTY_NOT_IN_CLASS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index 91e1a70d363..939b3ae9c38 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -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"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index 6157121457e..1ba3fefe1e0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -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 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); diff --git a/compiler/testData/diagnostics/tests/declarationChecks/MultiDeclarationErrors.kt b/compiler/testData/diagnostics/tests/declarationChecks/MultiDeclarationErrors.kt new file mode 100644 index 00000000000..adfa81bf277 --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/MultiDeclarationErrors.kt @@ -0,0 +1,20 @@ +package a + +class MyClass { + fun component0(i: Int) {} +} + +class MyClass2 {} + +fun MyClass2.component0() = 1.2 +fun MyClass2.component0() = 1.3 + +fun test(mc1: MyClass, mc2: MyClass2) { + val (a, b) = mc1 + val (c) = mc2 + + //a,b,c are error types + a : Boolean + b : Boolean + c : Boolean +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/kt2631_MultipleDeclaration.kt b/compiler/testData/diagnostics/tests/declarationChecks/kt2631_MultipleDeclaration.kt new file mode 100644 index 00000000000..f554e097298 --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/kt2631_MultipleDeclaration.kt @@ -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(mc1: MyClass, mc2: MyClass2) { + val (a, b) = mc1 + a : Int + b : String + + val (c) = mc2 + c : Double + + //check no error types + a : Boolean + b : Boolean + c : Boolean +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index e280fc018f4..893a825ff51 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -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")