KT-2631 Check multiple assignment - in progress
check multiple declaration without specified type annotation
This commit is contained in:
committed by
Andrey Breslav
parent
68ebdabf8f
commit
a0da232ed3
@@ -24,7 +24,9 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
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.calls.inference.InferenceErrorData;
|
||||||
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lexer.JetKeywordToken;
|
import org.jetbrains.jet.lexer.JetKeywordToken;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
@@ -97,6 +99,9 @@ public interface Errors {
|
|||||||
|
|
||||||
SimpleDiagnosticFactory<JetExpression> MANY_FUNCTION_LITERAL_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR);
|
SimpleDiagnosticFactory<JetExpression> MANY_FUNCTION_LITERAL_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR);
|
||||||
SimpleDiagnosticFactory<JetProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, NAMED_ELEMENT);
|
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<JetModifierListOwner> ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER);
|
||||||
SimpleDiagnosticFactory<JetProperty> ABSTRACT_PROPERTY_NOT_IN_CLASS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER);
|
SimpleDiagnosticFactory<JetProperty> ABSTRACT_PROPERTY_NOT_IN_CLASS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER);
|
||||||
|
|||||||
+3
@@ -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(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(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_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");
|
MAP.put(ABSTRACT_PROPERTY_NOT_IN_CLASS, "A property may be abstract only when defined in a class or trait");
|
||||||
|
|||||||
+40
@@ -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.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
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.JetTypeInfo;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -127,6 +128,45 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
return DataFlowUtils.checkStatementType(property, context, context.dataFlowInfo);
|
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
|
@Override
|
||||||
public JetTypeInfo visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
|
public JetTypeInfo visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
|
||||||
SimpleFunctionDescriptor functionDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function, context.trace);
|
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");
|
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")
|
@TestMetadata("kt559.kt")
|
||||||
public void testKt559() throws Exception {
|
public void testKt559() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/declarationChecks/kt559.kt");
|
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")
|
@TestMetadata("compiler/testData/diagnostics/tests/extensions")
|
||||||
|
|||||||
Reference in New Issue
Block a user