Create from usage: Fixed case for multi-declaration in a for-loop.

This commit is contained in:
Jack Zhou
2013-05-02 13:35:43 -04:00
parent e0a7e85e4a
commit 5bd144313d
9 changed files with 117 additions and 17 deletions
@@ -358,7 +358,7 @@ public interface Errors {
// Multi-declarations
DiagnosticFactory0<JetMultiDeclaration> INITIALIZER_REQUIRED_FOR_MULTIDECLARATION = DiagnosticFactory0.create(ERROR, DEFAULT);
DiagnosticFactory1<JetExpression, Name> COMPONENT_FUNCTION_MISSING = DiagnosticFactory1.create(ERROR, DEFAULT);
DiagnosticFactory2<JetExpression, Name, JetType> COMPONENT_FUNCTION_MISSING = DiagnosticFactory2.create(ERROR, DEFAULT);
DiagnosticFactory2<JetExpression, Name, Collection<? extends ResolvedCall<? extends CallableDescriptor>>> COMPONENT_FUNCTION_AMBIGUITY = DiagnosticFactory2.create(ERROR, DEFAULT);
DiagnosticFactory3<JetExpression, Name, JetType, JetType> COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH = DiagnosticFactory3.create(ERROR, DEFAULT);
@@ -113,7 +113,7 @@ public class DefaultErrorMessages {
MAP.put(VARIABLE_WITH_NO_TYPE_NO_INITIALIZER, "This variable 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_MISSING, "Multi-declaration initializer of type {1} must have a ''{0}()'' function", TO_STRING, RENDER_TYPE);
MAP.put(COMPONENT_FUNCTION_AMBIGUITY, "Function ''{0}()'' is ambiguous for this expression: {1}", TO_STRING, AMBIGUOUS_CALLS);
MAP.put(COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, "''{0}()'' function returns ''{1}'', but ''{2}'' is expected",
TO_STRING, RENDER_TYPE, RENDER_TYPE);
@@ -417,7 +417,7 @@ public class ExpressionTypingUtils {
context.trace.report(COMPONENT_FUNCTION_AMBIGUITY.on(reportErrorsOn, componentName, results.getResultingCalls()));
}
else {
context.trace.report(COMPONENT_FUNCTION_MISSING.on(reportErrorsOn, componentName));
context.trace.report(COMPONENT_FUNCTION_MISSING.on(reportErrorsOn, componentName, receiver.getType()));
}
if (componentType == null) {
componentType = ErrorUtils.createErrorType(componentName + "() return type");
@@ -51,9 +51,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.diagnostics.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
@@ -1313,7 +1311,10 @@ public class CreateFunctionFromUsageFix extends CreateFromUsageFixBase {
JetForExpression forExpr = QuickFixUtil.getParentElementOfType(diagnostic, JetForExpression.class);
if (forExpr == null) return null;
JetExpression variableExpr = forExpr.getLoopParameter();
if (variableExpr == null) return null;
if (variableExpr == null) {
variableExpr = forExpr.getMultiParameter();
if (variableExpr == null) return null;
}
TypeOrExpressionThereof returnType = new TypeOrExpressionThereof(variableExpr, Variance.OUT_VARIANCE);
return new CreateFunctionFromUsageFix(forExpr, ownerType, "next", returnType, new ArrayList<Parameter>());
}
@@ -1335,7 +1336,10 @@ public class CreateFunctionFromUsageFix extends CreateFromUsageFixBase {
JetExpression iterableExpr = forExpr.getLoopRange();
if (iterableExpr == null) return null;
JetExpression variableExpr = forExpr.getLoopParameter();
if (variableExpr == null) return null;
if (variableExpr == null) {
variableExpr = forExpr.getMultiParameter();
if (variableExpr == null) return null;
}
TypeOrExpressionThereof iterableType = new TypeOrExpressionThereof(iterableExpr, Variance.IN_VARIANCE);
JetType returnJetType = KotlinBuiltIns.getInstance().getIterator().getDefaultType();
@@ -1359,25 +1363,33 @@ public class CreateFunctionFromUsageFix extends CreateFromUsageFixBase {
@Nullable
@Override
public IntentionAction createAction(Diagnostic diagnostic) {
JetMultiDeclaration multiDeclaration = QuickFixUtil.getParentElementOfType(diagnostic, JetMultiDeclaration.class);
if (multiDeclaration == null) return null;
List<JetMultiDeclarationEntry> entries = multiDeclaration.getEntries();
assert diagnostic.getFactory() == Errors.COMPONENT_FUNCTION_MISSING;
@SuppressWarnings("unchecked")
DiagnosticWithParameters1<JetExpression, Name> diagnosticWithParameters =
(DiagnosticWithParameters1<JetExpression, Name>) diagnostic;
DiagnosticWithParameters2<JetExpression, Name, JetType> diagnosticWithParameters =
(DiagnosticWithParameters2<JetExpression, Name, JetType>) diagnostic;
Name name = diagnosticWithParameters.getA();
Matcher componentNumberMatcher = COMPONENT_FUNCTION_PATTERN.matcher(name.getIdentifier());
if (!componentNumberMatcher.matches()) return null;
String componentNumberString = componentNumberMatcher.group(1);
int componentNumber = Integer.decode(componentNumberString) - 1;
JetMultiDeclaration multiDeclaration = QuickFixUtil.getParentElementOfType(diagnostic, JetMultiDeclaration.class);
TypeOrExpressionThereof ownerType;
if (multiDeclaration == null) { // if it's not a multi-declaration, must be a multi parameter in a for-loop
JetForExpression forExpr = QuickFixUtil.getParentElementOfType(diagnostic, JetForExpression.class);
if (forExpr == null) return null;
multiDeclaration = forExpr.getMultiParameter();
if (multiDeclaration == null) return null;
ownerType = new TypeOrExpressionThereof(diagnosticWithParameters.getB(), Variance.IN_VARIANCE);
} else {
JetExpression rhs = multiDeclaration.getInitializer();
if (rhs == null) return null;
ownerType = new TypeOrExpressionThereof(rhs, Variance.IN_VARIANCE);
}
List<JetMultiDeclarationEntry> entries = multiDeclaration.getEntries();
JetMultiDeclarationEntry entry = entries.get(componentNumber);
TypeOrExpressionThereof returnType = new TypeOrExpressionThereof(entry, Variance.OUT_VARIANCE);
JetExpression rhs = multiDeclaration.getInitializer();
if (rhs == null) return null;
TypeOrExpressionThereof ownerType = new TypeOrExpressionThereof(rhs, Variance.IN_VARIANCE);
return new CreateFunctionFromUsageFix(multiDeclaration, ownerType, name.getIdentifier(), returnType, new ArrayList<Parameter>());
}
@@ -0,0 +1,21 @@
// "Create function 'component2' from usage" "true"
class FooIterator<T> {
fun hasNext(): Boolean { return false }
fun next(): Any {
throw UnsupportedOperationException("not implemented")
}
}
class Foo<T> {
fun iterator(): FooIterator<String> {
throw UnsupportedOperationException("not implemented")
}
}
fun Any.component1(): Int {
return 0
}
fun foo() {
for ((i: Int, j: Int) in Foo<Int>()) { }
}
fun Any.component2(): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -0,0 +1,18 @@
// "Create function 'component2' from usage" "true"
class FooIterator<T> {
fun hasNext(): Boolean { return false }
fun next(): Any {
throw UnsupportedOperationException("not implemented")
}
}
class Foo<T> {
fun iterator(): FooIterator<String> {
throw UnsupportedOperationException("not implemented")
}
}
fun Any.component1(): Int {
return 0
}
fun foo() {
for ((i: Int, j: Int) in Foo<caret><Int>()) { }
}
@@ -0,0 +1,21 @@
// "Create function 'next' from usage" "true"
class FooIterator<T> {
fun hasNext(): Boolean { return false }
fun next(): Any {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
class Foo<T> {
fun iterator(): FooIterator<String> {
throw UnsupportedOperationException("not implemented")
}
}
fun Any.component1(): Int {
return 0
}
fun Any.component2(): Int {
return 0
}
fun foo() {
for ((i: Int, j: Int) in Foo<Int>()) { }
}
@@ -0,0 +1,18 @@
// "Create function 'next' from usage" "true"
class FooIterator<T> {
fun hasNext(): Boolean { return false }
}
class Foo<T> {
fun iterator(): FooIterator<String> {
throw UnsupportedOperationException("not implemented")
}
}
fun Any.component1(): Int {
return 0
}
fun Any.component2(): Int {
return 0
}
fun foo() {
for ((i: Int, j: Int) in Foo<caret><Int>()) { }
}
@@ -452,6 +452,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest("idea/testData/quickfix/createFromUsage/component/beforeCreateComponentFromUsage2.kt");
}
@TestMetadata("beforeCreateComponentFromUsage3.kt")
public void testCreateComponentFromUsage3() throws Exception {
doTest("idea/testData/quickfix/createFromUsage/component/beforeCreateComponentFromUsage3.kt");
}
}
@TestMetadata("idea/testData/quickfix/createFromUsage/get")
@@ -561,6 +566,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest("idea/testData/quickfix/createFromUsage/iterator/beforeCreateIteratorFromUsage2.kt");
}
@TestMetadata("beforeCreateIteratorFromUsage3.kt")
public void testCreateIteratorFromUsage3() throws Exception {
doTest("idea/testData/quickfix/createFromUsage/iterator/beforeCreateIteratorFromUsage3.kt");
}
}
@TestMetadata("idea/testData/quickfix/createFromUsage/next")