diff --git a/.idea/artifacts/instrumentation_jar.xml b/.idea/artifacts/instrumentation_jar.xml index 5e0f98bc70e..be868324bfb 100644 --- a/.idea/artifacts/instrumentation_jar.xml +++ b/.idea/artifacts/instrumentation_jar.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/build.xml b/build.xml index 182b6655096..90421ff0b54 100644 --- a/build.xml +++ b/build.xml @@ -539,12 +539,15 @@ + + + diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java index abe2a333b0d..941175e951c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java @@ -17,9 +17,11 @@ package org.jetbrains.jet.lang.resolve.java.kotlinSignature; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; -import com.intellij.psi.HierarchicalMethodSignature; -import com.intellij.psi.PsiMethod; +import com.intellij.psi.*; +import com.intellij.psi.impl.PsiSubstitutorImpl; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,7 +40,11 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.renderer.DescriptorRenderer; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Map; + +import static com.intellij.psi.util.TypeConversionUtil.erasure; // This class contains heuristics for processing corner cases in propagation class PropagationHeuristics { @@ -122,8 +128,7 @@ class PropagationHeuristics { @NotNull static List getSuperMethods(@NotNull PsiMethod method) { List superMethods = Lists.newArrayList(); - for (HierarchicalMethodSignature superSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) { - PsiMethod superMethod = superSignature.getMethod(); + for (PsiMethod superMethod : new SuperMethodCollector(method).collect()) { CallableMemberDescriptor.Kind kindFromFlags = DescriptorKindUtils.flagsToKind(new PsiMethodWrapper(superMethod).getJetMethodAnnotation().kind()); if (kindFromFlags == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { @@ -141,4 +146,110 @@ class PropagationHeuristics { private PropagationHeuristics() { } + + private static class SuperMethodCollector { + private final PsiMethod initialMethod; + private final String initialMethodName; + private final List initialParametersErasure; + + private final List visitedSuperclasses = Lists.newArrayList(); + private final List collectedMethods = Lists.newArrayList(); + + private SuperMethodCollector(@NotNull PsiMethod initialMethod) { + this.initialMethod = initialMethod; + initialMethodName = initialMethod.getName(); + + PsiParameterList parameterList = initialMethod.getParameterList(); + initialParametersErasure = Lists.newArrayListWithExpectedSize(parameterList.getParametersCount()); + for (PsiParameter parameter : parameterList.getParameters()) { + initialParametersErasure.add(erasureNoEllipsis(parameter.getType())); + } + } + + public List collect() { + if (!canHaveSuperMethod(initialMethod)) { + return Collections.emptyList(); + } + + PsiClass containingClass = initialMethod.getContainingClass(); + assert containingClass != null : " containing class is null for " + initialMethod; + + for (PsiClassType superType : containingClass.getSuperTypes()) { + collectFromSupertype(superType); + } + + return collectedMethods; + } + + private void collectFromSupertype(PsiClassType type) { + PsiClass klass = type.resolve(); + if (klass == null) { + return; + } + if (!visitedSuperclasses.add(klass)) { + return; + } + + PsiSubstitutor supertypeSubstitutor = getErasedSubstitutor(type); + for (PsiMethod methodFromSuper : klass.getMethods()) { + if (isSubMethodOf(methodFromSuper, supertypeSubstitutor)) { + collectedMethods.add(methodFromSuper); + return; + } + } + + for (PsiType superType : type.getSuperTypes()) { + assert superType instanceof PsiClassType : "supertype is not a PsiClassType for " + type + ": " + superType; + collectFromSupertype((PsiClassType) superType); + } + } + + private boolean isSubMethodOf(@NotNull PsiMethod methodFromSuper, @NotNull PsiSubstitutor supertypeSubstitutor) { + if (!methodFromSuper.getName().equals(initialMethodName)) { + return false; + } + + PsiParameterList fromSuperParameterList = methodFromSuper.getParameterList(); + + if (fromSuperParameterList.getParametersCount() != initialParametersErasure.size()) { + return false; + } + + for (int i = 0; i < initialParametersErasure.size(); i++) { + PsiType originalType = initialParametersErasure.get(i); + PsiType typeFromSuper = fromSuperParameterList.getParameters()[i].getType(); + PsiType typeFromSuperErased = erasureNoEllipsis(supertypeSubstitutor.substitute(typeFromSuper)); + + if (!Comparing.equal(originalType, typeFromSuperErased)) { + return false; + } + } + + return true; + } + + private static PsiType erasureNoEllipsis(PsiType type) { + if (type instanceof PsiEllipsisType) { + return erasureNoEllipsis(((PsiEllipsisType) type).toArrayType()); + } + return erasure(type); + } + + private static PsiSubstitutor getErasedSubstitutor(PsiClassType type) { + Map unerasedMap = type.resolveGenerics().getSubstitutor().getSubstitutionMap(); + Map erasedMap = Maps.newHashMapWithExpectedSize(unerasedMap.size()); + for (Map.Entry entry : unerasedMap.entrySet()) { + erasedMap.put(entry.getKey(), erasure(entry.getValue())); + } + return PsiSubstitutorImpl.createSubstitutor(erasedMap); + } + + private static boolean canHaveSuperMethod(PsiMethod method) { + if (method.isConstructor()) return false; + if (method.hasModifierProperty(PsiModifier.STATIC)) return false; + if (method.hasModifierProperty(PsiModifier.PRIVATE)) return false; + PsiClass containingClass = method.getContainingClass(); + return containingClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName()); + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java index b1edec00e93..5399c1a0af1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowValueFactory.java @@ -18,17 +18,20 @@ package org.jetbrains.jet.lang.resolve.calls.autocasts; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.JetModuleUtil; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.scopes.receivers.*; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; +import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL; public class DataFlowValueFactory { public static final DataFlowValueFactory INSTANCE = new DataFlowValueFactory(); @@ -42,8 +45,8 @@ public class DataFlowValueFactory { if (constantExpression.getNode().getElementType() == JetNodeTypes.NULL) return DataFlowValue.NULL; } if (TypeUtils.equalTypes(type, KotlinBuiltIns.getInstance().getNullableNothingType())) return DataFlowValue.NULL; // 'null' is the only inhabitant of 'Nothing?' - Pair result = getIdForStableIdentifier(expression, bindingContext, false); - return new DataFlowValue(result.first == null ? expression : result.first, type, result.second, getImmanentNullability(type)); + IdentifierInfo result = getIdForStableIdentifier(expression, bindingContext); + return new DataFlowValue(result.id == null ? expression : result.id, type, result.isStable, getImmanentNullability(type)); } @NotNull @@ -104,55 +107,154 @@ public class DataFlowValueFactory { return type.isNullable() || TypeUtils.hasNullableSuperType(type) ? Nullability.UNKNOWN : Nullability.NOT_NULL; } + private static class IdentifierInfo { + public final Object id; + public final boolean isStable; + public final boolean isNamespace; + + private IdentifierInfo(Object id, boolean isStable, boolean isNamespace) { + this.id = id; + this.isStable = isStable; + this.isNamespace = isNamespace; + } + } + + private static final IdentifierInfo ERROR_IDENTIFIER_INFO = new IdentifierInfo(null, false, false); + @NotNull - private static Pair getIdForStableIdentifier(@NotNull JetExpression expression, @NotNull BindingContext bindingContext, boolean allowNamespaces) { + private static IdentifierInfo createInfo(Object id, boolean isStable) { + return new IdentifierInfo(id, isStable, false); + } + + @NotNull + private static IdentifierInfo createNamespaceInfo(Object id) { + return new IdentifierInfo(id, true, true); + } + + @NotNull + private static IdentifierInfo combineInfo(@Nullable IdentifierInfo receiverInfo, @NotNull IdentifierInfo selectorInfo) { + if (receiverInfo == null || receiverInfo == ERROR_IDENTIFIER_INFO || receiverInfo.isNamespace) { + return selectorInfo; + } + return createInfo(Pair.create(receiverInfo.id, selectorInfo.id), receiverInfo.isStable && selectorInfo.isStable); + } + + @NotNull + private static IdentifierInfo getIdForStableIdentifier( + @Nullable JetExpression expression, + @NotNull BindingContext bindingContext + ) { if (expression instanceof JetParenthesizedExpression) { JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression) expression; JetExpression innerExpression = parenthesizedExpression.getExpression(); - if (innerExpression == null) { - return Pair.create(null, false); - } - return getIdForStableIdentifier(innerExpression, bindingContext, allowNamespaces); + + return getIdForStableIdentifier(innerExpression, bindingContext); } else if (expression instanceof JetQualifiedExpression) { JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) expression; + JetExpression receiverExpression = qualifiedExpression.getReceiverExpression(); JetExpression selectorExpression = qualifiedExpression.getSelectorExpression(); - if (selectorExpression == null) { - return Pair.create(null, false); - } - Pair receiverId = getIdForStableIdentifier(qualifiedExpression.getReceiverExpression(), bindingContext, true); - Pair selectorId = getIdForStableIdentifier(selectorExpression, bindingContext, allowNamespaces); - return receiverId.second ? selectorId : Pair.create(receiverId.first, false); + IdentifierInfo receiverId = getIdForStableIdentifier(receiverExpression, bindingContext); + IdentifierInfo selectorId = getIdForStableIdentifier(selectorExpression, bindingContext); + + return combineInfo(receiverId, selectorId); } if (expression instanceof JetSimpleNameExpression) { - JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression; - DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, simpleNameExpression); - if (declarationDescriptor instanceof VariableDescriptor) { - return Pair.create((Object) declarationDescriptor, isStableVariable((VariableDescriptor) declarationDescriptor)); - } - if (declarationDescriptor instanceof NamespaceDescriptor) { - return Pair.create((Object) declarationDescriptor, allowNamespaces); - } - if (declarationDescriptor instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; - return Pair.create((Object) classDescriptor, classDescriptor.isClassObjectAValue()); - } + return getIdForSimpleNameExpression((JetSimpleNameExpression) expression, bindingContext); } else if (expression instanceof JetThisExpression) { JetThisExpression thisExpression = (JetThisExpression) expression; DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, thisExpression.getInstanceReference()); - if (declarationDescriptor instanceof CallableDescriptor) { - return Pair.create((Object) ((CallableDescriptor) declarationDescriptor).getReceiverParameter().getValue(), true); - } - if (declarationDescriptor instanceof ClassDescriptor) { - return Pair.create((Object) ((ClassDescriptor) declarationDescriptor).getThisAsReceiverParameter().getValue(), true); - } - return Pair.create(null, true); + + return getIdForThisReceiver(declarationDescriptor); } else if (expression instanceof JetRootNamespaceExpression) { - return Pair.create((Object) JetModuleUtil.getRootNamespaceType(expression), allowNamespaces); + return createNamespaceInfo(JetModuleUtil.getRootNamespaceType(expression)); } - return Pair.create(null, false); + return ERROR_IDENTIFIER_INFO; + } + + @NotNull + private static IdentifierInfo getIdForSimpleNameExpression( + @NotNull JetSimpleNameExpression simpleNameExpression, + @NotNull BindingContext bindingContext + ) { + DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, simpleNameExpression); + if (declarationDescriptor instanceof VariableDescriptor) { + ResolvedCall resolvedCall = bindingContext.get(RESOLVED_CALL, simpleNameExpression); + // todo return assert + // for now it fails for resolving 'invoke' convention, return it after 'invoke' algorithm changes + // assert resolvedCall != null : "Cannot create right identifier info if the resolved call is not known yet for " + declarationDescriptor; + + IdentifierInfo receiverInfo = resolvedCall != null ? getIdForImplicitReceiver(resolvedCall.getThisObject(), simpleNameExpression) : null; + + VariableDescriptor variableDescriptor = (VariableDescriptor) declarationDescriptor; + return combineInfo(receiverInfo, createInfo(variableDescriptor, isStableVariable(variableDescriptor))); + } + if (declarationDescriptor instanceof NamespaceDescriptor) { + return createNamespaceInfo(declarationDescriptor); + } + if (declarationDescriptor instanceof ClassDescriptor) { + ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; + return createInfo(classDescriptor, classDescriptor.isClassObjectAValue()); + } + return ERROR_IDENTIFIER_INFO; + } + + @Nullable + private static IdentifierInfo getIdForImplicitReceiver(@NotNull ReceiverValue receiverValue, @Nullable final JetExpression expression) { + return receiverValue.accept(new ReceiverValueVisitor() { + + @Override + public IdentifierInfo visitNoReceiver(ReceiverValue noReceiver, Void data) { + return null; + } + + @Override + public IdentifierInfo visitTransientReceiver(TransientReceiver receiver, Void data) { + assert false: "Transient receiver is implicit for an explicit expression: " + expression + ". Receiver: " + receiver; + return null; + } + + @Override + public IdentifierInfo visitExtensionReceiver(ExtensionReceiver receiver, Void data) { + return getIdForThisReceiver(receiver); + } + + @Override + public IdentifierInfo visitExpressionReceiver(ExpressionReceiver receiver, Void data) { + // there is an explicit "this" expression and it was analyzed earlier + return null; + } + + @Override + public IdentifierInfo visitClassReceiver(ClassReceiver receiver, Void data) { + return getIdForThisReceiver(receiver); + } + + @Override + public IdentifierInfo visitScriptReceiver(ScriptReceiver receiver, Void data) { + return getIdForThisReceiver(receiver); + } + }, null); + } + + @NotNull + private static IdentifierInfo getIdForThisReceiver(@NotNull ThisReceiver thisReceiver) { + return getIdForThisReceiver(thisReceiver.getDeclarationDescriptor()); + } + + @NotNull + private static IdentifierInfo getIdForThisReceiver(@Nullable DeclarationDescriptor descriptorOfThisReceiver) { + if (descriptorOfThisReceiver instanceof CallableDescriptor) { + ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) descriptorOfThisReceiver).getReceiverParameter(); + assert receiverParameter != null : "'This' refers to the callable member without a receiver parameter: " + descriptorOfThisReceiver; + return createInfo(receiverParameter.getValue(), true); + } + if (descriptorOfThisReceiver instanceof ClassDescriptor) { + return createInfo(((ClassDescriptor) descriptorOfThisReceiver).getThisAsReceiverParameter().getValue(), true); + } + return ERROR_IDENTIFIER_INFO; } public static boolean isStableVariable(@NotNull VariableDescriptor variableDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverValueVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverValueVisitor.java index 44281585f7c..110189c2330 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverValueVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverValueVisitor.java @@ -16,28 +16,16 @@ package org.jetbrains.jet.lang.resolve.scopes.receivers; -public class ReceiverValueVisitor { - public R visitNoReceiver(ReceiverValue noReceiver, D data) { - return null; - } +public interface ReceiverValueVisitor { + R visitNoReceiver(ReceiverValue noReceiver, D data); - public R visitTransientReceiver(TransientReceiver receiver, D data) { - return null; - } + R visitTransientReceiver(TransientReceiver receiver, D data); - public R visitExtensionReceiver(ExtensionReceiver receiver, D data) { - return null; - } + R visitExtensionReceiver(ExtensionReceiver receiver, D data); - public R visitExpressionReceiver(ExpressionReceiver receiver, D data) { - return null; - } + R visitExpressionReceiver(ExpressionReceiver receiver, D data); - public R visitClassReceiver(ClassReceiver receiver, D data) { - return null; - } + R visitClassReceiver(ClassReceiver receiver, D data); - public R visitScriptReceiver(ScriptReceiver receiver, D data) { - return null; - } + R visitScriptReceiver(ScriptReceiver receiver, D data); } diff --git a/compiler/preloader/instrumentation/ReadMe.md b/compiler/preloader/instrumentation/ReadMe.md index dfdb9eac23c..22506fd0086 100644 --- a/compiler/preloader/instrumentation/ReadMe.md +++ b/compiler/preloader/instrumentation/ReadMe.md @@ -27,7 +27,7 @@ This is determined by the ```src/META-INF/services/org.jetbrains.jet.preloading. Preloader loads the **first** instrumenter service found on the class path. Services are provided through the [standard JDK mechanism](http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html). -Every preloaded class is run through the instrumenter. Before exiting the program instrumenter's dupm() method is called. +Every preloaded class is run through the instrumenter. Before exiting the program instrumenter's dump() method is called. **Note** JDK classes and everything in the Preloader's own class path are not preloaded, thus not instrumented. The ```instrumentation``` module provides a convenient way to define useful instrumenters: diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt2422.kt b/compiler/testData/diagnostics/tests/smartCasts/kt2422.kt new file mode 100644 index 00000000000..ea3ac5e68fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/kt2422.kt @@ -0,0 +1,23 @@ +package bar + +class Test { + val foo: Int? = null + fun foo(o: Test) = foo == null && o.foo == null // ERROR warning: o.test == null is always true + + fun bar(a: Test, b: Test) { + if (a.foo != null) { + useInt(b.foo) + } + if (a.foo != null) { + useInt(foo) + } + if (this.foo != null) { + useInt(foo) + } + if (foo != null) { + useInt(this.foo) + } + } + + fun useInt(i: Int) = i +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/noErrorCheckForPackageLevelVal.kt b/compiler/testData/diagnostics/tests/smartCasts/noErrorCheckForPackageLevelVal.kt new file mode 100644 index 00000000000..c993a144277 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/noErrorCheckForPackageLevelVal.kt @@ -0,0 +1,25 @@ +//FILE: bar.kt +package bar + +val i: Int? = 2 + +//FILE: foo.kt +package foo + +val i: Int? = 1 + +class A(val i: Int?) { + fun testUseFromClass() { + if (foo.i != null) { + useInt(i) + } + } +} + +fun testUseFromOtherPackage() { + if (bar.i != null) { + useInt(i) + } +} + +fun useInt(i: Int) = i \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt b/compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt new file mode 100644 index 00000000000..618f5b66a69 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt @@ -0,0 +1,36 @@ +package foo + +class A(val i: Int?) { + fun test1() { + if (this@A.i != null) { + useInt(this.i) + useInt(i) + } + } + + inner class B { + fun test2() { + if (i != null) { + useInt(this@A.i) + } + } + } +} + +fun A.foo() { + if (this@foo.i != null) { + useInt(this.i) + useInt(i) + } +} + +fun test3() { + useFunction { + if(i != null) { + useInt(this.i) + } + } +} + +fun useInt(i: Int) = i +fun useFunction(f: A.() -> Unit) = f \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/smartCasts/thisWithLabelAsReceiverPart.kt b/compiler/testData/diagnostics/tests/smartCasts/thisWithLabelAsReceiverPart.kt new file mode 100644 index 00000000000..bdbc0aa44f7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/thisWithLabelAsReceiverPart.kt @@ -0,0 +1,39 @@ +package foo + +class C(val i: Int?) {} + +class A(val c: C) { + fun test1() { + if (this@A.c.i != null) { + useInt(this.c.i) + useInt(c.i) + } + } + + inner class B { + fun test2() { + if (c.i != null) { + useInt(this@A.c.i) + } + } + } +} + +fun A.foo() { + if (this@foo.c.i != null) { + useInt(this.c.i) + useInt(c.i) + } +} + +fun test3() { + useFunction { + if(c.i != null) { + useInt(this.c.i) + } + } +} + +fun useInt(i: Int) = i +fun useFunction(f: A.() -> Unit) = f + diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 115e37c96fa..3ccf049c0d8 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -4722,6 +4722,26 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/smartCasts/kt1461.kt"); } + @TestMetadata("kt2422.kt") + public void testKt2422() throws Exception { + doTest("compiler/testData/diagnostics/tests/smartCasts/kt2422.kt"); + } + + @TestMetadata("noErrorCheckForPackageLevelVal.kt") + public void testNoErrorCheckForPackageLevelVal() throws Exception { + doTest("compiler/testData/diagnostics/tests/smartCasts/noErrorCheckForPackageLevelVal.kt"); + } + + @TestMetadata("thisWithLabel.kt") + public void testThisWithLabel() throws Exception { + doTest("compiler/testData/diagnostics/tests/smartCasts/thisWithLabel.kt"); + } + + @TestMetadata("thisWithLabelAsReceiverPart.kt") + public void testThisWithLabelAsReceiverPart() throws Exception { + doTest("compiler/testData/diagnostics/tests/smartCasts/thisWithLabelAsReceiverPart.kt"); + } + } @TestMetadata("compiler/testData/diagnostics/tests/substitutions") diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index c640470d94b..a68d3edbb91 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -59,9 +59,12 @@ add.semicolon.after.invocation=Add semicolon after invocation of ''{0}'' add.semicolon.family=Add Semicolon change.function.return.type=Change ''{0}'' function return type to ''{1}'' change.no.name.function.return.type=Change function return type to ''{0}'' +change.function.literal.return.type=Change function literal return type to ''{0}'' remove.function.return.type=Remove explicitly specified return type in ''{0}'' function remove.no.name.function.return.type=Remove explicitly specified function return type change.element.type=Change ''{0}'' type to ''{1}'' +change.function.parameter.type=Change parameter ''{0}'' type of function ''{1}'' to ''{2}'' +change.primary.constructor.parameter.type=Change parameter ''{0}'' type of primary constructor of class ''{1}'' to ''{2}'' change.type=Change type from ''{0}'' to ''{1}'' change.type.family=Change Type add.parameters.to.function=Add parameter{0} to function ''{1}'' diff --git a/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertedCode.java b/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertedCode.java index 89827815faa..e9af4d9cebc 100644 --- a/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertedCode.java +++ b/idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertedCode.java @@ -43,12 +43,12 @@ class ConvertedCode implements TextBlockTransferableData { @Override public int getOffsets(int[] offsets, int index) { - return 0; + return index; } @Override public int setOffsets(int[] offsets, int index) { - return 0; + return index; } public String getData() { diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java index 21d32d41fa7..21b4a2a6729 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/JetPsiChecker.java @@ -43,9 +43,8 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; -import org.jetbrains.jet.plugin.quickfix.JetIntentionActionFactory; +import org.jetbrains.jet.plugin.quickfix.JetIntentionActionsFactory; import org.jetbrains.jet.plugin.quickfix.QuickFixes; -import org.jetbrains.jet.utils.ExceptionUtils; import java.util.Collection; import java.util.List; @@ -217,14 +216,12 @@ public class JetPsiChecker implements Annotator { return null; } - Collection intentionActionFactories = QuickFixes.getActionFactories(diagnostic.getFactory()); - for (JetIntentionActionFactory intentionActionFactory : intentionActionFactories) { - IntentionAction action = null; - if (intentionActionFactory != null) { - action = intentionActionFactory.createAction(diagnostic); - } - if (action != null) { - annotation.registerFix(action); + Collection intentionActionsFactories = QuickFixes.getActionsFactories(diagnostic.getFactory()); + for (JetIntentionActionsFactory intentionActionsFactory : intentionActionsFactories) { + if (intentionActionsFactory != null) { + for (IntentionAction action: intentionActionsFactory.createActions(diagnostic)) { + annotation.registerFix(action); + } } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java index 2654f228e78..b0819791d25 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java @@ -67,8 +67,8 @@ public class AddFunctionBodyFix extends JetIntentionAction { element.replace(newElement); } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java index 05844b5f937..f565679cb6d 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionToSupertypeFix.java @@ -158,8 +158,8 @@ public class AddFunctionToSupertypeFix extends JetHintAction { return new JetAddFunctionToClassifierAction(project, editor, bindingContext, functionsToAdd); } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionsFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java index 162dc6b7aa3..d3bdd9b985e 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java @@ -164,8 +164,8 @@ public class AddModifierFix extends JetIntentionAction { return true; } - public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier, final Class modifierOwnerClass) { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory(final JetKeywordToken modifier, final Class modifierOwnerClass) { + return new JetSingleIntentionActionFactory() { @Override public IntentionAction createAction(Diagnostic diagnostic) { JetModifierListOwner modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, modifierOwnerClass); @@ -175,7 +175,7 @@ public class AddModifierFix extends JetIntentionAction { }; } - public static JetIntentionActionFactory createFactory(JetKeywordToken modifier) { + public static JetSingleIntentionActionFactory createFactory(JetKeywordToken modifier) { return createFactory(modifier, JetModifierListOwner.class); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java index cc53c6ad0e3..93c03343de2 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddNameToArgumentFix.java @@ -183,8 +183,8 @@ public class AddNameToArgumentFix extends JetIntentionAction { return JetBundle.message("add.name.to.argument.family"); } @NotNull - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionsFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddOpenModifierToClassDeclarationFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddOpenModifierToClassDeclarationFix.java index 8fa3b39a8c6..13509245a17 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddOpenModifierToClassDeclarationFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddOpenModifierToClassDeclarationFix.java @@ -81,8 +81,8 @@ public class AddOpenModifierToClassDeclarationFix extends JetIntentionAction editor.getCaretModel().moveToOffset(textRange.getStartOffset() + indexOfOpenBrace + 1); } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java index c4cdd8d9533..68b66bfa623 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AutoImportFix.java @@ -289,8 +289,8 @@ public class AutoImportFix extends JetHintAction implem } @Nullable - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(@NotNull Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java index 1b4cc20a134..d58f92e6ebd 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/CastExpressionFix.java @@ -20,7 +20,6 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,19 +32,22 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.renderer.DescriptorRenderer; public class CastExpressionFix extends JetIntentionAction { private final JetType type; + private final String renderedType; public CastExpressionFix(@NotNull JetExpression element, @NotNull JetType type) { super(element); this.type = type; + renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); } @NotNull @Override public String getText() { - return JetBundle.message("cast.expression.to.type", element.getText(), type.toString()); + return JetBundle.message("cast.expression.to.type", element.getText(), renderedType); } @NotNull @@ -64,9 +66,9 @@ public class CastExpressionFix extends JetIntentionAction { @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { JetBinaryExpressionWithTypeRHS castedExpression = - (JetBinaryExpressionWithTypeRHS) JetPsiFactory.createExpression(project, "(" + element.getText() + ") as " + type.toString()); + (JetBinaryExpressionWithTypeRHS) JetPsiFactory.createExpression(project, "(" + element.getText() + ") as " + renderedType); if (JetPsiUtil.areParenthesesUseless((JetParenthesizedExpression) castedExpression.getLeft())) { - castedExpression = (JetBinaryExpressionWithTypeRHS) JetPsiFactory.createExpression(project, element.getText() + " as " + type.toString()); + castedExpression = (JetBinaryExpressionWithTypeRHS) JetPsiFactory.createExpression(project, element.getText() + " as " + renderedType); } JetParenthesizedExpression castedExpressionInParentheses = @@ -78,8 +80,8 @@ public class CastExpressionFix extends JetIntentionAction { } @NotNull - public static JetIntentionActionFactory createFactoryForAutoCastImpossible() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactoryForAutoCastImpossible() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { @@ -91,32 +93,4 @@ public class CastExpressionFix extends JetIntentionAction { } }; } - - @NotNull - public static JetIntentionActionFactory createFactoryForTypeMismatch() { - return new JetIntentionActionFactory() { - @Nullable - @Override - public IntentionAction createAction(Diagnostic diagnostic) { - assert diagnostic.getFactory() == Errors.TYPE_MISMATCH; - @SuppressWarnings("unchecked") - DiagnosticWithParameters2 diagnosticWithParameters = - (DiagnosticWithParameters2) diagnostic; - JetExpression expression = diagnosticWithParameters.getPsiElement(); - - // we don't want to cast a cast: - if (expression instanceof JetBinaryExpressionWithTypeRHS) { - return null; - } - - // 'x: Int' - TYPE_MISMATCH might be reported on 'x', and we don't want this quickfix to be available: - JetBinaryExpressionWithTypeRHS parentExpressionWithTypeRHS = - PsiTreeUtil.getParentOfType(expression, JetBinaryExpressionWithTypeRHS.class, true); - if (parentExpressionWithTypeRHS != null && parentExpressionWithTypeRHS.getLeft() == expression) { - return null; - } - return new CastExpressionFix(expression, diagnosticWithParameters.getA()); - } - }; - } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java index 102874d7f83..59dee5775e8 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java @@ -23,38 +23,38 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.renderer.DescriptorRenderer; public class ChangeAccessorTypeFix extends JetIntentionAction { + private String renderedType; + public ChangeAccessorTypeFix(@NotNull JetPropertyAccessor element) { super(element); } - @Nullable - private JetType getPropertyType() { - JetProperty property = PsiTreeUtil.getParentOfType(element, JetProperty.class); - if (property == null) return null; - return QuickFixUtil.getDeclarationReturnType(property); - } - @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - JetType type = getPropertyType(); - return super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type); + JetProperty property = PsiTreeUtil.getParentOfType(element, JetProperty.class); + if (property == null) return false; + JetType type = QuickFixUtil.getDeclarationReturnType(property); + if (super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type)) { + renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); + return true; + } + return false; } @NotNull @Override public String getText() { - JetType type = getPropertyType(); return element.isGetter() - ? JetBundle.message("change.getter.type", type) - : JetBundle.message("change.setter.type", type); + ? JetBundle.message("change.getter.type", renderedType) + : JetBundle.message("change.setter.type", renderedType); } @NotNull @@ -65,10 +65,8 @@ public class ChangeAccessorTypeFix extends JetIntentionAction createAction(Diagnostic diagnostic) { JetPropertyAccessor accessor = QuickFixUtil.getParentElementOfType(diagnostic, JetPropertyAccessor.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionLiteralReturnTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionLiteralReturnTypeFix.java new file mode 100644 index 00000000000..3027cba79c4 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionLiteralReturnTypeFix.java @@ -0,0 +1,140 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeProjection; +import org.jetbrains.jet.lang.types.TypeUtils; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.plugin.JetBundle; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.renderer.DescriptorRenderer; + +import java.util.LinkedList; +import java.util.List; + +public class ChangeFunctionLiteralReturnTypeFix extends JetIntentionAction { + private final String renderedType; + private final JetTypeReference functionLiteralReturnTypeRef; + private IntentionAction appropriateQuickFix = null; + + public ChangeFunctionLiteralReturnTypeFix(@NotNull JetFunctionLiteralExpression element, @NotNull JetType type) { + super(element); + renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); + functionLiteralReturnTypeRef = element.getFunctionLiteral().getReturnTypeRef(); + + BindingContext context = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) element.getContainingFile()).getBindingContext(); + JetType functionLiteralType = context.get(BindingContext.EXPRESSION_TYPE, element); + assert functionLiteralType != null : "Type of function literal not available in binding context"; + + ClassDescriptor functionClass = KotlinBuiltIns.getInstance().getFunction(functionLiteralType.getArguments().size() - 1); + List functionClassTypeParameters = new LinkedList(); + for (TypeProjection typeProjection: functionLiteralType.getArguments()) { + functionClassTypeParameters.add(typeProjection.getType()); + } + // Replacing return type: + functionClassTypeParameters.remove(functionClassTypeParameters.size() - 1); + functionClassTypeParameters.add(type); + JetType eventualFunctionLiteralType = TypeUtils.substituteParameters(functionClass, functionClassTypeParameters); + + JetProperty correspondingProperty = PsiTreeUtil.getParentOfType(element, JetProperty.class); + if (correspondingProperty != null && QuickFixUtil.canEvaluateTo(correspondingProperty.getInitializer(), element)) { + JetTypeReference correspondingPropertyTypeRef = correspondingProperty.getTypeRef(); + JetType propertyType = context.get(BindingContext.TYPE, correspondingPropertyTypeRef); + if (propertyType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(eventualFunctionLiteralType, propertyType)) { + appropriateQuickFix = new ChangeVariableTypeFix(correspondingProperty, eventualFunctionLiteralType); + } + return; + } + + JetParameter correspondingParameter = QuickFixUtil.getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList(element); + if (correspondingParameter != null) { + JetTypeReference correspondingParameterTypeRef = correspondingParameter.getTypeReference(); + JetType parameterType = context.get(BindingContext.TYPE, correspondingParameterTypeRef); + if (parameterType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(eventualFunctionLiteralType, parameterType)) { + appropriateQuickFix = new ChangeParameterTypeFix(correspondingParameter, eventualFunctionLiteralType); + } + return; + } + + JetFunction parentFunction = PsiTreeUtil.getParentOfType(element, JetFunction.class, true); + if (parentFunction != null && QuickFixUtil.canFunctionOrGetterReturnExpression(parentFunction, element)) { + JetTypeReference parentFunctionReturnTypeRef = parentFunction.getReturnTypeRef(); + JetType parentFunctionReturnType = context.get(BindingContext.TYPE, parentFunctionReturnTypeRef); + if (parentFunctionReturnType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(eventualFunctionLiteralType, parentFunctionReturnType)) { + appropriateQuickFix = new ChangeFunctionReturnTypeFix(parentFunction, eventualFunctionLiteralType); + } + } + } + + @NotNull + @Override + public String getText() { + if (appropriateQuickFix != null) { + return appropriateQuickFix.getText(); + } + return JetBundle.message("change.function.literal.return.type", renderedType); + } + + @NotNull + @Override + public String getFamilyName() { + return JetBundle.message("change.type.family"); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return super.isAvailable(project, editor, file) && + (functionLiteralReturnTypeRef != null || (appropriateQuickFix != null && appropriateQuickFix.isAvailable(project, editor, file))); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, JetFile file) throws IncorrectOperationException { + if (functionLiteralReturnTypeRef != null) { + functionLiteralReturnTypeRef.replace(JetPsiFactory.createType(project, renderedType)); + } + if (appropriateQuickFix != null && appropriateQuickFix.isAvailable(project, editor, file)) { + appropriateQuickFix.invoke(project, editor, file); + } + } + + @NotNull + public static JetSingleIntentionActionFactory createFactoryForExpectedOrAssignmentTypeMismatch() { + return new JetSingleIntentionActionFactory() { + @Nullable + @Override + public IntentionAction createAction(Diagnostic diagnostic) { + JetFunctionLiteralExpression functionLiteralExpression = QuickFixUtil.getParentElementOfType(diagnostic, JetFunctionLiteralExpression.class); + assert functionLiteralExpression != null : "ASSIGNMENT/EXPECTED_TYPE_MISMATCH reported outside any function literal"; + return new ChangeFunctionLiteralReturnTypeFix(functionLiteralExpression, KotlinBuiltIns.getInstance().getUnitType()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java index e8368c9a771..cf22d69bf9c 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java @@ -23,11 +23,13 @@ import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters3; import org.jetbrains.jet.lang.psi.*; @@ -37,24 +39,45 @@ import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; import org.jetbrains.jet.plugin.intentions.SpecifyTypeExplicitlyAction; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.renderer.DescriptorRenderer; -public class ChangeFunctionReturnTypeFix extends JetIntentionAction { +import java.util.LinkedList; +import java.util.List; + +public class ChangeFunctionReturnTypeFix extends JetIntentionAction { private final JetType type; + private final String renderedType; + private final ChangeFunctionLiteralReturnTypeFix changeFunctionLiteralReturnTypeFix; - public ChangeFunctionReturnTypeFix(@NotNull JetNamedFunction element, @NotNull JetType type) { + public ChangeFunctionReturnTypeFix(@NotNull JetFunction element, @NotNull JetType type) { super(element); this.type = type; + renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); + if (element instanceof JetFunctionLiteral) { + JetFunctionLiteralExpression functionLiteralExpression = PsiTreeUtil.getParentOfType(element, JetFunctionLiteralExpression.class); + assert functionLiteralExpression != null : "FunctionLiteral outside any FunctionLiteralExpression"; + changeFunctionLiteralReturnTypeFix = new ChangeFunctionLiteralReturnTypeFix(functionLiteralExpression, type); + } + else { + changeFunctionLiteralReturnTypeFix = null; + } } @NotNull @Override public String getText() { + if (changeFunctionLiteralReturnTypeFix != null) { + return changeFunctionLiteralReturnTypeFix.getText(); + } + String functionName = element.getName(); FqName fqName = JetPsiUtil.getFQName(element); if (fqName != null) functionName = fqName.asString(); @@ -65,8 +88,8 @@ public class ChangeFunctionReturnTypeFix extends JetIntentionAction) diagnostic).getA().asString(); int componentIndex = Integer.valueOf(componentName.substring(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX.length())); JetMultiDeclaration multiDeclaration = QuickFixUtil.getParentElementOfType(diagnostic, JetMultiDeclaration.class); @@ -105,8 +139,8 @@ public class ChangeFunctionReturnTypeFix extends JetIntentionAction resolvedCall = context.get(BindingContext.COMPONENT_RESOLVED_CALL, entry); if (resolvedCall == null) return null; - JetNamedFunction componentFunction = (JetNamedFunction) BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getCandidateDescriptor()); + JetFunction componentFunction = (JetFunction) BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getCandidateDescriptor()); JetType expectedType = context.get(BindingContext.TYPE, entry.getTypeRef()); if (componentFunction != null && expectedType != null) { return new ChangeFunctionReturnTypeFix(componentFunction, expectedType); @@ -125,8 +159,8 @@ public class ChangeFunctionReturnTypeFix extends JetIntentionAction resolvedCall = context.get(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, expression); if (resolvedCall == null) return null; - JetNamedFunction hasNextFunction = (JetNamedFunction) BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getCandidateDescriptor()); + JetFunction hasNextFunction = (JetFunction) BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getCandidateDescriptor()); if (hasNextFunction != null) { return new ChangeFunctionReturnTypeFix(hasNextFunction, KotlinBuiltIns.getInstance().getBooleanType()); } @@ -145,67 +179,75 @@ public class ChangeFunctionReturnTypeFix extends JetIntentionAction resolvedCall = context.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); + ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, + expression.getOperationReference()); if (resolvedCall == null) return null; PsiElement compareTo = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getCandidateDescriptor()); - if (!(compareTo instanceof JetNamedFunction)) return null; - return new ChangeFunctionReturnTypeFix((JetNamedFunction) compareTo, KotlinBuiltIns.getInstance().getIntType()); + if (!(compareTo instanceof JetFunction)) return null; + return new ChangeFunctionReturnTypeFix((JetFunction) compareTo, KotlinBuiltIns.getInstance().getIntType()); } }; } @NotNull - public static JetIntentionActionFactory createFactoryForReturnTypeMismatchOnOverride() { - return new JetIntentionActionFactory() { - @Nullable + public static JetIntentionActionsFactory createFactoryForReturnTypeMismatchOnOverride() { + return new JetIntentionActionsFactory() { + @NotNull @Override - public IntentionAction createAction(Diagnostic diagnostic) { - JetNamedFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction.class); - if (function == null) return null; - BindingContext context = KotlinCacheManagerUtil.getDeclarationsBindingContext(function); - JetType matchingReturnType = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(context, function); - return matchingReturnType == null ? null : new ChangeFunctionReturnTypeFix(function, matchingReturnType); + public List createActions(Diagnostic diagnostic) { + List actions = new LinkedList(); + + JetFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetFunction.class); + if (function != null) { + BindingContext context = KotlinCacheManagerUtil.getDeclarationsBindingContext(function); + JetType matchingReturnType = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(context, function); + if (matchingReturnType != null) { + actions.add(new ChangeFunctionReturnTypeFix(function, matchingReturnType)); + } + + SimpleFunctionDescriptor descriptor = context.get(BindingContext.FUNCTION, function); + if (descriptor == null) return actions; + JetType functionType = descriptor.getReturnType(); + if (functionType == null) return actions; + + List overriddenMismatchingFunctions = new LinkedList(); + for (FunctionDescriptor overriddenFunction: descriptor.getOverriddenDescriptors()) { + JetType overriddenFunctionType = overriddenFunction.getReturnType(); + if (overriddenFunctionType == null) continue; + if (!JetTypeChecker.INSTANCE.isSubtypeOf(functionType, overriddenFunctionType)) { + overriddenMismatchingFunctions.add(overriddenFunction); + } + } + + if (overriddenMismatchingFunctions.size() == 1) { + PsiElement overriddenFunction = BindingContextUtils.descriptorToDeclaration(context, overriddenMismatchingFunctions.get(0)); + if (overriddenFunction instanceof JetFunction) { + actions.add(new ChangeFunctionReturnTypeFix((JetFunction) overriddenFunction, functionType)); + } + } + } + return actions; } }; } @NotNull - public static JetIntentionActionFactory createFactoryForChangingReturnTypeToUnit() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactoryForChangingReturnTypeToUnit() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { - JetNamedFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction.class); + JetFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetFunction.class); return function == null ? null : new ChangeFunctionReturnTypeFix(function, KotlinBuiltIns.getInstance().getUnitType()); } }; } - - @NotNull - public static JetIntentionActionFactory createFactoryForTypeMismatch() { - return new JetIntentionActionFactory() { - @Nullable - @Override - public IntentionAction createAction(Diagnostic diagnostic) { - JetExpression expression = (JetExpression) diagnostic.getPsiElement(); - JetNamedFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction.class); - - if (function != null && (function.getInitializer() == expression || expression.getParent() instanceof JetReturnExpression)) { - BindingContext context = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) diagnostic.getPsiFile()).getBindingContext(); - JetType type = context.get(BindingContext.EXPRESSION_TYPE, expression); - assert type != null : "Expression type mismatch, but expression has no type"; - return new ChangeFunctionReturnTypeFix(function, type); - } - return null; - } - }; - } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java index 62449021494..0412b7191e4 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionSignatureFix.java @@ -124,8 +124,8 @@ public abstract class ChangeFunctionSignatureFix extends JetIntentionAction { + private final String renderedType; + private final String containingDeclarationName; + private final boolean isPrimaryConstructorParameter; + + public ChangeParameterTypeFix(@NotNull JetParameter element, @NotNull JetType type) { + super(element); + renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); + JetNamedDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetNamedDeclaration.class); + isPrimaryConstructorParameter = declaration instanceof JetClass; + FqName declarationFQName = declaration == null ? null : JetPsiUtil.getFQName(declaration); + containingDeclarationName = declarationFQName == null ? null : declarationFQName.asString(); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return super.isAvailable(project, editor, file) && containingDeclarationName != null; + } + + @NotNull + @Override + public String getText() { + return isPrimaryConstructorParameter ? + JetBundle.message("change.primary.constructor.parameter.type", element.getName(), containingDeclarationName, renderedType) : + JetBundle.message("change.function.parameter.type", element.getName(), containingDeclarationName, renderedType); + } + + @NotNull + @Override + public String getFamilyName() { + return JetBundle.message("change.type.family"); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, JetFile file) throws IncorrectOperationException { + JetTypeReference typeReference = element.getTypeReference(); + assert typeReference != null : "Parameter without type annotation cannot cause type mismatch"; + typeReference.replace(JetPsiFactory.createType(project, renderedType)); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java index 4f524d4d9a0..52b672da595 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java @@ -49,8 +49,8 @@ public class ChangeToBackingFieldFix extends JetIntentionAction createAction(Diagnostic diagnostic) { JetSimpleNameExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetSimpleNameExpression.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToConstructorInvocationFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToConstructorInvocationFix.java index 7890d0a49da..3cb0532bf48 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToConstructorInvocationFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToConstructorInvocationFix.java @@ -84,8 +84,8 @@ public class ChangeToConstructorInvocationFix extends JetIntentionAction createAction(Diagnostic diagnostic) { if (diagnostic.getPsiElement() instanceof JetDelegatorToSuperClass) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToFunctionInvocationFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToFunctionInvocationFix.java index acbdc338f17..b96a01b3155 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToFunctionInvocationFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToFunctionInvocationFix.java @@ -50,8 +50,8 @@ public class ChangeToFunctionInvocationFix extends JetIntentionAction createAction(Diagnostic diagnostic) { if (diagnostic.getPsiElement() instanceof JetExpression) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToPropertyNameFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToPropertyNameFix.java index 96ecda49d7e..9d832492d35 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToPropertyNameFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToPropertyNameFix.java @@ -58,8 +58,8 @@ public class ChangeToPropertyNameFix extends JetIntentionAction createAction(Diagnostic diagnostic) { JetSimpleNameExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetSimpleNameExpression.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToStarProjectionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToStarProjectionFix.java index 18c050c42d3..ac083e375bd 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToStarProjectionFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToStarProjectionFix.java @@ -54,8 +54,8 @@ public class ChangeToStarProjectionFix extends JetIntentionAction { - private final JetType type; + private final String renderedType; public ChangeTypeFix(@NotNull JetTypeReference element, JetType type) { super(element); - this.type = type; + renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); } @NotNull @Override public String getText() { - return JetBundle.message("change.type", element.getText(), type); + return JetBundle.message("change.type", element.getText(), renderedType); } @NotNull @@ -53,13 +54,13 @@ public class ChangeTypeFix extends JetIntentionAction { } @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - element.replace(JetPsiFactory.createType(project, type.toString())); + public void invoke(@NotNull Project project, Editor editor, JetFile file) throws IncorrectOperationException { + element.replace(JetPsiFactory.createType(project, renderedType)); } @NotNull - public static JetIntentionActionFactory createFactoryForExpectedParameterTypeMismatch() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactoryForExpectedParameterTypeMismatch() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { @@ -74,8 +75,8 @@ public class ChangeTypeFix extends JetIntentionAction { } @NotNull - public static JetIntentionActionFactory createFactoryForExpectedReturnTypeMismatch() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactoryForExpectedReturnTypeMismatch() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java index c3423fa6b28..bcb408900ba 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java @@ -26,29 +26,43 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheManagerUtil; import org.jetbrains.jet.plugin.intentions.SpecifyTypeExplicitlyAction; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; +import org.jetbrains.jet.renderer.DescriptorRenderer; + +import java.util.LinkedList; +import java.util.List; public class ChangeVariableTypeFix extends JetIntentionAction { + private final String renderedType; private final JetType type; public ChangeVariableTypeFix(@NotNull JetVariableDeclaration element, @NotNull JetType type) { super(element); + renderedType = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(type); this.type = type; } @NotNull @Override public String getText() { - return JetBundle.message("change.element.type", element.getName(), type); + String propertyName = element.getName(); + FqName fqName = JetPsiUtil.getFQName(element); + if (fqName != null) propertyName = fqName.asString(); + + return JetBundle.message("change.element.type", propertyName, renderedType); } @NotNull @@ -58,17 +72,37 @@ public class ChangeVariableTypeFix extends JetIntentionAction typeWhiteSpaceAndColon = JetPsiFactory.createTypeWhiteSpaceAndColon(project, type.toString()); + Pair typeWhiteSpaceAndColon = JetPsiFactory.createTypeWhiteSpaceAndColon(project, renderedType); element.addRangeAfter(typeWhiteSpaceAndColon.first, typeWhiteSpaceAndColon.second, nameIdentifier); + + if (element instanceof JetProperty) { + JetPropertyAccessor getter = ((JetProperty) element).getGetter(); + JetTypeReference getterReturnTypeRef = getter == null ? null : getter.getReturnTypeReference(); + if (getterReturnTypeRef != null) { + getterReturnTypeRef.replace(JetPsiFactory.createType(project, renderedType)); + } + + JetPropertyAccessor setter = ((JetProperty) element).getSetter(); + JetParameter setterParameter = setter == null ? null : setter.getParameter(); + JetTypeReference setterParameterTypeRef = setterParameter == null ? null : setterParameter.getTypeReference(); + if (setterParameterTypeRef != null) { + setterParameterTypeRef.replace(JetPsiFactory.createType(project, renderedType)); + } + } } @NotNull - public static JetIntentionActionFactory createFactoryForComponentFunctionReturnTypeMismatch() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactoryForComponentFunctionReturnTypeMismatch() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { @@ -85,16 +119,53 @@ public class ChangeVariableTypeFix extends JetIntentionAction createActions(Diagnostic diagnostic) { + List actions = new LinkedList(); + JetProperty property = QuickFixUtil.getParentElementOfType(diagnostic, JetProperty.class); - if (property == null) return null; - BindingContext context = KotlinCacheManagerUtil.getDeclarationsBindingContext(property); - JetType type = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(context, property); - return type == null ? null : new ChangeVariableTypeFix(property, type); + if (property != null) { + BindingContext context = KotlinCacheManagerUtil.getDeclarationsBindingContext(property); + JetType lowerBoundOfOverriddenPropertiesTypes = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(context, property); + + PropertyDescriptor descriptor = (PropertyDescriptor) context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property); + assert descriptor != null : "Descriptor of property not available in binding context"; + JetType propertyType = descriptor.getReturnType(); + assert propertyType != null : "Property type cannot be null if it mismatch something"; + + List overriddenMismatchingProperties = new LinkedList(); + boolean canChangeOverriddenPropertyType = true; + for (PropertyDescriptor overriddenProperty: descriptor.getOverriddenDescriptors()) { + JetType overriddenPropertyType = overriddenProperty.getReturnType(); + if (overriddenPropertyType != null) { + if (!JetTypeChecker.INSTANCE.isSubtypeOf(propertyType, overriddenPropertyType)) { + overriddenMismatchingProperties.add(overriddenProperty); + } + else if (overriddenProperty.isVar() && !JetTypeChecker.INSTANCE.equalTypes(overriddenPropertyType, propertyType)) { + canChangeOverriddenPropertyType = false; + } + if (overriddenProperty.isVar() && lowerBoundOfOverriddenPropertiesTypes != null && + !JetTypeChecker.INSTANCE.equalTypes(lowerBoundOfOverriddenPropertiesTypes, overriddenPropertyType)) { + lowerBoundOfOverriddenPropertiesTypes = null; + } + } + } + + if (lowerBoundOfOverriddenPropertiesTypes != null) { + actions.add(new ChangeVariableTypeFix(property, lowerBoundOfOverriddenPropertiesTypes)); + } + + if (overriddenMismatchingProperties.size() == 1 && canChangeOverriddenPropertyType) { + PsiElement overriddenProperty = BindingContextUtils.descriptorToDeclaration(context, overriddenMismatchingProperties.get(0)); + if (overriddenProperty instanceof JetProperty) { + actions.add(new ChangeVariableTypeFix((JetProperty) overriddenProperty, propertyType)); + } + } + } + return actions; } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVisibilityModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVisibilityModifierFix.java index 0bcc32fbdd9..b3adc058a84 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVisibilityModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVisibilityModifierFix.java @@ -103,8 +103,8 @@ public class ChangeVisibilityModifierFix extends JetIntentionAction createAction(Diagnostic diagnostic) { PsiElement element = diagnostic.getPsiElement(); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionFactory.java b/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionsFactory.java similarity index 80% rename from idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionFactory.java rename to idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionsFactory.java index 3301507e6ac..953acf3469b 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionsFactory.java @@ -17,12 +17,13 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.codeInsight.intention.IntentionAction; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.diagnostics.Diagnostic; -public interface JetIntentionActionFactory { +import java.util.List; - @Nullable - IntentionAction createAction(Diagnostic diagnostic); +public interface JetIntentionActionsFactory { + @NotNull + List createActions(Diagnostic diagnostic); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/JetSingleIntentionActionFactory.java b/idea/src/org/jetbrains/jet/plugin/quickfix/JetSingleIntentionActionFactory.java new file mode 100644 index 00000000000..1ecbd890a63 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/JetSingleIntentionActionFactory.java @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.intention.IntentionAction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; + +import java.util.LinkedList; +import java.util.List; + +public abstract class JetSingleIntentionActionFactory implements JetIntentionActionsFactory { + + @Nullable + public abstract IntentionAction createAction(Diagnostic diagnostic); + + @NotNull + @Override + public final List createActions(Diagnostic diagnostic) { + List intentionActionList = new LinkedList(); + IntentionAction intentionAction = createAction(diagnostic); + if (intentionAction != null) { + intentionActionList.add(intentionAction); + } + return intentionActionList; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java index 4f5191179a3..6f2712cc75d 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/MakeClassAnAnnotationClassFix.java @@ -90,8 +90,8 @@ public class MakeClassAnAnnotationClassFix extends JetIntentionAction { } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/MoveWhenElseBranchFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/MoveWhenElseBranchFix.java index 132d8989c9d..95e503a6eab 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/MoveWhenElseBranchFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/MoveWhenElseBranchFix.java @@ -78,8 +78,8 @@ public class MoveWhenElseBranchFix extends JetIntentionAction editor.getCaretModel().moveToOffset(insertedWhenEntry.getTextOffset() + cursorOffset); } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java new file mode 100644 index 00000000000..9eb2dd5314b --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java @@ -0,0 +1,135 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters2; +import org.jetbrains.jet.lang.diagnostics.Errors; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; + +import java.util.LinkedList; +import java.util.List; + +public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsFactory { + @NotNull + @Override + public List createActions(Diagnostic diagnostic) { + List actions = new LinkedList(); + + assert diagnostic.getFactory() == Errors.TYPE_MISMATCH; + @SuppressWarnings("unchecked") + DiagnosticWithParameters2 diagnosticWithParameters = + (DiagnosticWithParameters2) diagnostic; + JetExpression expression = diagnosticWithParameters.getPsiElement(); + JetType expectedType = diagnosticWithParameters.getA(); + JetType expressionType = diagnosticWithParameters.getB(); + BindingContext context = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) diagnostic.getPsiFile()).getBindingContext(); + + // We don't want to cast a cast or type-asserted expression: + if (!(expression instanceof JetBinaryExpressionWithTypeRHS) && !(expression.getParent() instanceof JetBinaryExpressionWithTypeRHS)) { + actions.add(new CastExpressionFix(expression, expectedType)); + } + + // Property initializer type mismatch property type: + JetProperty property = PsiTreeUtil.getParentOfType(expression, JetProperty.class); + if (property != null) { + JetPropertyAccessor getter = property.getGetter(); + if (QuickFixUtil.canEvaluateTo(property.getInitializer(), expression) || + (getter != null && QuickFixUtil.canFunctionOrGetterReturnExpression(property.getGetter(), expression))) { + actions.add(new ChangeVariableTypeFix(property, expressionType)); + } + } + + // Mismatch in returned expression: + JetFunction function = PsiTreeUtil.getParentOfType(expression, JetFunction.class, true); + if (function != null && QuickFixUtil.canFunctionOrGetterReturnExpression(function, expression)) { + actions.add(new ChangeFunctionReturnTypeFix(function, expressionType)); + } + + // Fixing overloaded operators: + if (expression instanceof JetOperationExpression) { + ResolvedCall resolvedCall = + context.get(BindingContext.RESOLVED_CALL, ((JetOperationExpression) expression).getOperationReference()); + if (resolvedCall != null) { + PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); + if (declaration instanceof JetFunction) { + actions.add(new ChangeFunctionReturnTypeFix((JetFunction) declaration, expectedType)); + } + } + } + if (expression.getParent() instanceof JetBinaryExpression) { + JetBinaryExpression parentBinary = (JetBinaryExpression) expression.getParent(); + if (parentBinary.getRight() == expression) { + ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, parentBinary.getOperationReference()); + if (resolvedCall != null) { + PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); + if (declaration instanceof JetFunction) { + JetParameter binaryOperatorParameter = ((JetFunction) declaration).getValueParameterList().getParameters().get(0); + actions.add(new ChangeParameterTypeFix(binaryOperatorParameter, expressionType)); + } + } + } + } + + // Change function return type when TYPE_MISMATCH is reported on call expression: + if (expression instanceof JetCallExpression) { + ResolvedCall resolvedCall = + context.get(BindingContext.RESOLVED_CALL, ((JetCallExpression) expression).getCalleeExpression()); + if (resolvedCall != null) { + PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); + if (declaration instanceof JetFunction) { + actions.add(new ChangeFunctionReturnTypeFix((JetFunction) declaration, expectedType)); + } + } + } + + // Change type of a function parameter in case TYPE_MISMATCH is reported on expression passed as value argument of call. + // 1) When an argument is a dangling function literal: + JetFunctionLiteralExpression functionLiteralExpression = + QuickFixUtil.getParentElementOfType(diagnostic, JetFunctionLiteralExpression.class); + if (functionLiteralExpression != null && functionLiteralExpression.getBodyExpression() == expression) { + JetParameter correspondingParameter = + QuickFixUtil.getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList(functionLiteralExpression); + JetType functionLiteralExpressionType = context.get(BindingContext.EXPRESSION_TYPE, functionLiteralExpression); + if (correspondingParameter != null && functionLiteralExpressionType != null) { + actions.add(new ChangeParameterTypeFix(correspondingParameter, functionLiteralExpressionType)); + } + } + // 2) When an argument is passed inside value argument list: + else { + JetValueArgument valueArgument = QuickFixUtil.getParentElementOfType(diagnostic, JetValueArgument.class); + if (valueArgument != null && QuickFixUtil.canEvaluateTo(valueArgument.getArgumentExpression(), expression)) { + JetParameter correspondingParameter = QuickFixUtil.getParameterCorrespondingToValueArgumentPassedInCall(valueArgument); + JetType valueArgumentType = context.get(BindingContext.EXPRESSION_TYPE, valueArgument.getArgumentExpression()); + if (correspondingParameter != null && valueArgumentType != null) { + actions.add(new ChangeParameterTypeFix(correspondingParameter, valueArgumentType)); + } + } + } + return actions; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java index a1d9aa40425..11380a56cc4 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java @@ -26,10 +26,10 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; -import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.psi.JetNamedDeclaration; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.types.DeferredType; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; @@ -93,4 +93,103 @@ public class QuickFixUtil { public static boolean canModifyElement(@NotNull PsiElement element) { return element.isWritable() && !BuiltInsReferenceResolver.isFromBuiltIns(element); } + + @Nullable + public static JetParameterList getParameterListOfCallee(@NotNull JetCallExpression callExpression) { + BindingContext context = AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) callExpression.getContainingFile()).getBindingContext(); + ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, callExpression.getCalleeExpression()); + if (resolvedCall == null) return null; + PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getCandidateDescriptor()); + if (declaration instanceof JetFunction) { + return ((JetFunction) declaration).getValueParameterList(); + } + if (declaration instanceof JetClass) { + return ((JetClass) declaration).getPrimaryConstructorParameterList(); + } + return null; + } + + @Nullable + public static JetParameter getParameterCorrespondingToFunctionLiteralPassedOutsideArgumentList(@NotNull JetFunctionLiteralExpression functionLiteralExpression) { + if (!(functionLiteralExpression.getParent() instanceof JetCallExpression)) { + return null; + } + JetCallExpression callExpression = (JetCallExpression) functionLiteralExpression.getParent(); + JetParameterList parameterList = getParameterListOfCallee(callExpression); + if (parameterList == null) return null; + return parameterList.getParameters().get(parameterList.getParameters().size() - 1); + } + + @Nullable + public static JetParameter getParameterCorrespondingToValueArgumentPassedInCall(@NotNull JetValueArgument valueArgument) { + if (!(valueArgument.getParent() instanceof JetValueArgumentList)) { + return null; + } + JetValueArgumentList valueArgumentList = (JetValueArgumentList) valueArgument.getParent(); + if (!(valueArgumentList.getParent() instanceof JetCallExpression)) { + return null; + } + JetCallExpression callExpression = (JetCallExpression) valueArgumentList.getParent(); + JetParameterList parameterList = getParameterListOfCallee(callExpression); + if (parameterList == null) return null; + int position = valueArgumentList.getArguments().indexOf(valueArgument); + if (position == -1) return null; + + if (valueArgument.isNamed()) { + JetValueArgumentName valueArgumentName = valueArgument.getArgumentName(); + JetSimpleNameExpression referenceExpression = valueArgumentName == null ? null : valueArgumentName.getReferenceExpression(); + String valueArgumentNameAsString = referenceExpression == null ? null : referenceExpression.getReferencedName(); + if (valueArgumentNameAsString == null) return null; + + for (JetParameter parameter: parameterList.getParameters()) { + if (valueArgumentNameAsString.equals(parameter.getName())) { + return parameter; + } + } + return null; + } + else { + return parameterList.getParameters().get(position); + } + } + + private static boolean equalOrLastInThenOrElse(JetExpression thenOrElse, JetExpression expression) { + if (thenOrElse == expression) return true; + return thenOrElse instanceof JetBlockExpression && expression.getParent() == thenOrElse && + PsiTreeUtil.getNextSiblingOfType(expression, JetExpression.class) == null; + } + + public static boolean canEvaluateTo(JetExpression parent, JetExpression child) { + if (parent == null || child == null) { + return false; + } + while (parent != child) { + if (child.getParent() instanceof JetParenthesizedExpression) { + child = (JetExpression) child.getParent(); + continue; + } + JetIfExpression jetIfExpression = PsiTreeUtil.getParentOfType(child, JetIfExpression.class, true); + if (jetIfExpression == null) return false; + if (!equalOrLastInThenOrElse(jetIfExpression.getThen(), child) && !equalOrLastInThenOrElse(jetIfExpression.getElse(), child)) { + return false; + } + child = jetIfExpression; + } + return true; + } + + public static boolean canFunctionOrGetterReturnExpression(@NotNull JetDeclaration functionOrGetter, @NotNull JetExpression expression) { + if (functionOrGetter instanceof JetFunctionLiteral) { + JetBlockExpression functionLiteralBody = ((JetFunctionLiteral) functionOrGetter).getBodyExpression(); + PsiElement returnedElement = functionLiteralBody == null ? null : functionLiteralBody.getLastChild(); + return returnedElement instanceof JetExpression && canEvaluateTo((JetExpression) returnedElement, expression); + } + else { + if (functionOrGetter instanceof JetWithExpressionInitializer && canEvaluateTo(((JetWithExpressionInitializer) functionOrGetter).getInitializer(), expression)) { + return true; + } + JetReturnExpression returnExpression = PsiTreeUtil.getParentOfType(expression, JetReturnExpression.class); + return returnExpression != null && canEvaluateTo(returnExpression.getReturnedExpression(), expression); + } + } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index be8f7fb5b30..63f87c80c17 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -30,10 +30,10 @@ import static org.jetbrains.jet.lexer.JetTokens.*; public class QuickFixes { - private static final Multimap factories = HashMultimap.create(); + private static final Multimap factories = HashMultimap.create(); private static final Multimap actions = HashMultimap.create(); - public static Collection getActionFactories(AbstractDiagnosticFactory diagnosticFactory) { + public static Collection getActionsFactories(AbstractDiagnosticFactory diagnosticFactory) { return factories.get(diagnosticFactory); } @@ -44,12 +44,12 @@ public class QuickFixes { private QuickFixes() {} static { - JetIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD); - JetIntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(ABSTRACT_KEYWORD); + JetSingleIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD); + JetSingleIntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(ABSTRACT_KEYWORD); factories.put(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory); - JetIntentionActionFactory removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory(); + JetSingleIntentionActionFactory removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory(); factories.put(ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory); factories.put(ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory); @@ -63,13 +63,13 @@ public class QuickFixes { factories.put(MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory); - JetIntentionActionFactory removeFinalModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(FINAL_KEYWORD); + JetSingleIntentionActionFactory removeFinalModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(FINAL_KEYWORD); - JetIntentionActionFactory addAbstractToClassFactory = AddModifierFix.createFactory(ABSTRACT_KEYWORD, JetClass.class); + JetSingleIntentionActionFactory addAbstractToClassFactory = AddModifierFix.createFactory(ABSTRACT_KEYWORD, JetClass.class); factories.put(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); factories.put(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); - JetIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory(); + JetSingleIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory(); factories.put(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); factories.put(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); @@ -79,7 +79,7 @@ public class QuickFixes { factories.put(FINAL_PROPERTY_IN_TRAIT, removeFinalModifierFactory); factories.put(FINAL_FUNCTION_WITH_NO_BODY, removeFinalModifierFactory); - JetIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory(); + JetSingleIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory(); factories.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory); factories.put(NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory); @@ -97,13 +97,13 @@ public class QuickFixes { factories.put(USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory()); factories.put(USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory()); - JetIntentionActionFactory changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory(); + JetSingleIntentionActionFactory changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory(); factories.put(WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory); factories.put(WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory); factories.put(USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory()); - JetIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true); + JetSingleIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true); factories.put(REDUNDANT_MODIFIER, removeRedundantModifierFactory); factories.put(ABSTRACT_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(ABSTRACT_KEYWORD, true)); factories.put(OPEN_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD, true)); @@ -112,28 +112,28 @@ public class QuickFixes { factories.put(INCOMPATIBLE_MODIFIERS, RemoveModifierFix.createRemoveModifierFactory(false)); factories.put(VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY, RemoveModifierFix.createRemoveVarianceFactory()); - JetIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD); + JetSingleIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD); factories.put(NON_FINAL_MEMBER_IN_FINAL_CLASS, AddModifierFix.createFactory(OPEN_KEYWORD, JetClass.class)); factories.put(NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory); - JetIntentionActionFactory removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory(); + JetSingleIntentionActionFactory removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory(); factories.put(GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory); factories.put(REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory); factories.put(ILLEGAL_MODIFIER, removeModifierFactory); - JetIntentionActionFactory changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory(); + JetSingleIntentionActionFactory changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory(); factories.put(INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory); factories.put(INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory); - JetIntentionActionFactory changeToPropertyNameFactory = ChangeToPropertyNameFix.createFactory(); + JetSingleIntentionActionFactory changeToPropertyNameFactory = ChangeToPropertyNameFix.createFactory(); factories.put(NO_BACKING_FIELD_ABSTRACT_PROPERTY, changeToPropertyNameFactory); factories.put(NO_BACKING_FIELD_CUSTOM_ACCESSORS, changeToPropertyNameFactory); factories.put(INACCESSIBLE_BACKING_FIELD, changeToPropertyNameFactory); - JetIntentionActionFactory unresolvedReferenceFactory = AutoImportFix.createFactory(); + JetSingleIntentionActionFactory unresolvedReferenceFactory = AutoImportFix.createFactory(); factories.put(UNRESOLVED_REFERENCE, unresolvedReferenceFactory); - JetIntentionActionFactory removeImportFixFactory = RemovePsiElementSimpleFix.createRemoveImportFactory(); + JetSingleIntentionActionFactory removeImportFixFactory = RemovePsiElementSimpleFix.createRemoveImportFactory(); factories.put(USELESS_SIMPLE_IMPORT, removeImportFixFactory); factories.put(USELESS_HIDDEN_IMPORT, removeImportFixFactory); @@ -173,7 +173,7 @@ public class QuickFixes { actions.put(UNNECESSARY_NOT_NULL_ASSERTION, ExclExclCallFix.removeExclExclCall()); factories.put(UNSAFE_INFIX_CALL, ReplaceInfixCallFix.createFactory()); - JetIntentionActionFactory removeProtectedModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(PROTECTED_KEYWORD); + JetSingleIntentionActionFactory removeProtectedModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(PROTECTED_KEYWORD); factories.put(PACKAGE_MEMBER_CANNOT_BE_PROTECTED, removeProtectedModifierFactory); actions.put(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, new SpecifyTypeExplicitlyFix()); @@ -187,13 +187,13 @@ public class QuickFixes { factories.put(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER, RemovePsiElementSimpleFix.createRemoveTypeArgumentsFactory()); - JetIntentionActionFactory changeToStarProjectionFactory = ChangeToStarProjectionFix.createFactory(); + JetSingleIntentionActionFactory changeToStarProjectionFactory = ChangeToStarProjectionFix.createFactory(); factories.put(UNCHECKED_CAST, changeToStarProjectionFactory); factories.put(CANNOT_CHECK_FOR_ERASED, changeToStarProjectionFactory); factories.put(INACCESSIBLE_OUTER_CLASS_EXPRESSION, AddModifierFix.createFactory(INNER_KEYWORD, JetClass.class)); - JetIntentionActionFactory addOpenModifierToClassDeclarationFix = AddOpenModifierToClassDeclarationFix.createFactory(); + JetSingleIntentionActionFactory addOpenModifierToClassDeclarationFix = AddOpenModifierToClassDeclarationFix.createFactory(); factories.put(FINAL_SUPERTYPE, addOpenModifierToClassDeclarationFix); factories.put(FINAL_UPPER_BOUND, addOpenModifierToClassDeclarationFix); @@ -214,19 +214,18 @@ public class QuickFixes { factories.put(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED, AddSemicolonAfterFunctionCallFix.createFactory()); - JetIntentionActionFactory changeVariableTypeFix = ChangeVariableTypeFix.createFactoryForPropertyOrReturnTypeMismatchOnOverride(); + JetIntentionActionsFactory changeVariableTypeFix = ChangeVariableTypeFix.createFactoryForPropertyOrReturnTypeMismatchOnOverride(); factories.put(RETURN_TYPE_MISMATCH_ON_OVERRIDE, changeVariableTypeFix); factories.put(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE, changeVariableTypeFix); factories.put(COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, ChangeVariableTypeFix.createFactoryForComponentFunctionReturnTypeMismatch()); - JetIntentionActionFactory changeFunctionReturnTypeFix = ChangeFunctionReturnTypeFix.createFactoryForChangingReturnTypeToUnit(); + JetSingleIntentionActionFactory changeFunctionReturnTypeFix = ChangeFunctionReturnTypeFix.createFactoryForChangingReturnTypeToUnit(); factories.put(RETURN_TYPE_MISMATCH, changeFunctionReturnTypeFix); factories.put(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY, changeFunctionReturnTypeFix); factories.put(RETURN_TYPE_MISMATCH_ON_OVERRIDE, ChangeFunctionReturnTypeFix.createFactoryForReturnTypeMismatchOnOverride()); factories.put(COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, ChangeFunctionReturnTypeFix.createFactoryForComponentFunctionReturnTypeMismatch()); factories.put(HAS_NEXT_FUNCTION_TYPE_MISMATCH, ChangeFunctionReturnTypeFix.createFactoryForHasNextFunctionTypeMismatch()); factories.put(COMPARE_TO_TYPE_MISMATCH, ChangeFunctionReturnTypeFix.createFactoryForCompareToTypeMismatch()); - factories.put(TYPE_MISMATCH, ChangeFunctionReturnTypeFix.createFactoryForTypeMismatch()); factories.put(TOO_MANY_ARGUMENTS, ChangeFunctionSignatureFix.createFactory()); factories.put(NO_VALUE_FOR_PARAMETER, ChangeFunctionSignatureFix.createFactory()); @@ -235,9 +234,14 @@ public class QuickFixes { factories.put(EXPECTED_PARAMETER_TYPE_MISMATCH, ChangeTypeFix.createFactoryForExpectedParameterTypeMismatch()); factories.put(EXPECTED_RETURN_TYPE_MISMATCH, ChangeTypeFix.createFactoryForExpectedReturnTypeMismatch()); - + + JetSingleIntentionActionFactory changeFunctionLiteralReturnTypeFix = ChangeFunctionLiteralReturnTypeFix.createFactoryForExpectedOrAssignmentTypeMismatch(); + factories.put(EXPECTED_TYPE_MISMATCH, changeFunctionLiteralReturnTypeFix); + factories.put(ASSIGNMENT_TYPE_MISMATCH, changeFunctionLiteralReturnTypeFix); + + factories.put(TYPE_MISMATCH, new QuickFixFactoryForTypeMismatchError()); + factories.put(AUTOCAST_IMPOSSIBLE, CastExpressionFix.createFactoryForAutoCastImpossible()); - factories.put(TYPE_MISMATCH, CastExpressionFix.createFactoryForTypeMismatch()); factories.put(PLATFORM_CLASS_MAPPED_TO_KOTLIN, MapPlatformClassToKotlinFix.createFactory()); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java index f93954651f4..19e77848cd5 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java @@ -87,8 +87,8 @@ public class RemoveFunctionBodyFix extends JetIntentionAction { return false; } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { JetFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetFunction.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java index 6dfe9a14c17..03d61b2998a 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java @@ -103,12 +103,12 @@ public class RemoveModifierFix extends JetIntentionAction } - public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(JetKeywordToken modifier) { + public static JetSingleIntentionActionFactory createRemoveModifierFromListOwnerFactory(JetKeywordToken modifier) { return createRemoveModifierFromListOwnerFactory(modifier, false); } - public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { @@ -119,12 +119,12 @@ public class RemoveModifierFix extends JetIntentionAction }; } - public static JetIntentionActionFactory createRemoveModifierFactory() { + public static JetSingleIntentionActionFactory createRemoveModifierFactory() { return createRemoveModifierFactory(false); } - public static JetIntentionActionFactory createRemoveModifierFactory(final boolean isRedundant) { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveModifierFactory(final boolean isRedundant) { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { @@ -139,8 +139,8 @@ public class RemoveModifierFix extends JetIntentionAction }; } - public static JetIntentionActionFactory createRemoveProjectionFactory(final boolean isRedundant) { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveProjectionFactory(final boolean isRedundant) { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { @@ -156,8 +156,8 @@ public class RemoveModifierFix extends JetIntentionAction }; } - public static JetIntentionActionFactory createRemoveVarianceFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveVarianceFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public JetIntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveNullableFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveNullableFix.java index fdabcc18e73..a1f0e08fd8b 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveNullableFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveNullableFix.java @@ -62,8 +62,8 @@ public class RemoveNullableFix extends JetIntentionAction { super.element.replace(type); } - public static JetIntentionActionFactory createFactory(final NullableKind typeOfError) { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory(final NullableKind typeOfError) { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { JetNullableType nullType = QuickFixUtil.getParentElementOfType(diagnostic, JetNullableType.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java index 6854ba50f3c..6778eec9646 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java @@ -121,8 +121,8 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction } } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { PsiElement element = diagnostic.getPsiElement(); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePsiElementSimpleFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePsiElementSimpleFix.java index 43388a24bb5..40f46346cf6 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePsiElementSimpleFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePsiElementSimpleFix.java @@ -60,8 +60,8 @@ public class RemovePsiElementSimpleFix extends JetIntentionAction { element.delete(); } - public static JetIntentionActionFactory createRemoveImportFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveImportFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { JetImportDirective directive = QuickFixUtil.getParentElementOfType(diagnostic, JetImportDirective.class); @@ -79,8 +79,8 @@ public class RemovePsiElementSimpleFix extends JetIntentionAction { }; } - public static JetIntentionActionFactory createRemoveSpreadFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveSpreadFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { PsiElement element = diagnostic.getPsiElement(); @@ -92,8 +92,8 @@ public class RemovePsiElementSimpleFix extends JetIntentionAction { }; } - public static JetIntentionActionFactory createRemoveTypeArgumentsFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveTypeArgumentsFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { JetTypeArgumentList element = QuickFixUtil.getParentElementOfType(diagnostic, JetTypeArgumentList.class); @@ -104,8 +104,8 @@ public class RemovePsiElementSimpleFix extends JetIntentionAction { }; } - public static JetIntentionActionFactory createRemoveVariableFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveVariableFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { final JetProperty expression = QuickFixUtil.getParentElementOfType(diagnostic, JetProperty.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java index 3ad449a3bc4..a2918726a83 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java @@ -57,8 +57,8 @@ public class RemoveRightPartOfBinaryExpressionFix exten } } - public static JetIntentionActionFactory createRemoveCastFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveCastFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { JetBinaryExpressionWithTypeRHS expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpressionWithTypeRHS.class); @@ -68,8 +68,8 @@ public class RemoveRightPartOfBinaryExpressionFix exten }; } - public static JetIntentionActionFactory createRemoveElvisOperatorFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createRemoveElvisOperatorFactory() { + return new JetSingleIntentionActionFactory() { @Override public JetIntentionAction createAction(Diagnostic diagnostic) { JetBinaryExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpression.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveSupertypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveSupertypeFix.java index e6374d65aa4..fd7983caa1e 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveSupertypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveSupertypeFix.java @@ -63,8 +63,8 @@ public class RemoveSupertypeFix extends JetIntentionAction createAction(Diagnostic diagnostic) { JetDelegationSpecifier superClass = QuickFixUtil.getParentElementOfType(diagnostic, JetDelegationSpecifier.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RenameParameterToMatchOverriddenMethodFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RenameParameterToMatchOverriddenMethodFix.java index 59c7b6fa088..2c41571125c 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RenameParameterToMatchOverriddenMethodFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RenameParameterToMatchOverriddenMethodFix.java @@ -82,8 +82,8 @@ public class RenameParameterToMatchOverriddenMethodFix extends JetIntentionActio } @NotNull - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Nullable @Override public IntentionAction createAction(Diagnostic diagnostic) { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java index b4c93eb5b5c..7f31feeac9e 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java @@ -59,8 +59,8 @@ public class ReplaceInfixCallFix extends JetIntentionAction return true; } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetSingleIntentionActionFactory createFactory() { + return new JetSingleIntentionActionFactory() { @Override public IntentionAction createAction(Diagnostic diagnostic) { JetBinaryExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpression.class); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java index 317a2c3cd9d..2bb7c65bfdb 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java @@ -18,7 +18,6 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -55,8 +54,8 @@ public abstract class ReplaceOperationInBinaryExpressionFix createAction(Diagnostic diagnostic) { JetBinaryExpressionWithTypeRHS expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpressionWithTypeRHS.class); diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverriddenPropertyType1.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverriddenPropertyType1.kt new file mode 100644 index 00000000000..6a3586ed492 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverriddenPropertyType1.kt @@ -0,0 +1,12 @@ +// "Change 'B.x' type to '(Int) -> Int'" "true" +trait A { + val x: (Int) -> Int +} + +trait B { + val x: (Int) -> Int +} + +trait C : A, B { + override val x: (Int) -> Int +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverriddenPropertyType2.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverriddenPropertyType2.kt new file mode 100644 index 00000000000..fd1e09a06ce --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverriddenPropertyType2.kt @@ -0,0 +1,12 @@ +// "Change 'A.x' type to 'String'" "true" +trait A { + var x: String +} + +trait B { + var x: String +} + +trait C : A, B { + override var x: String +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverridingPropertyTypeToFunctionType.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverridingPropertyTypeToFunctionType.kt new file mode 100644 index 00000000000..8bd2d6f38b3 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeOverridingPropertyTypeToFunctionType.kt @@ -0,0 +1,7 @@ +// "Change 'B.x' type to '(String) -> Int'" "true" +trait A { + var x: (String) -> Int +} +trait B : A { + override var x: (String) -> Int +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeReturnTypeOfOverriddenFunction.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeReturnTypeOfOverriddenFunction.kt new file mode 100644 index 00000000000..0efefb16139 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/afterChangeReturnTypeOfOverriddenFunction.kt @@ -0,0 +1,12 @@ +// "Change 'A.foo' function return type to 'Long'" "true" +trait A { + fun foo(): Long +} + +trait B { + fun foo(): Number +} + +trait C : A, B { + override fun foo(): Long +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyReturnTypeMismatchOnOverride.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyReturnTypeMismatchOnOverride.kt index 9dbb3cbe563..0f79cd40f9d 100644 --- a/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyReturnTypeMismatchOnOverride.kt +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyReturnTypeMismatchOnOverride.kt @@ -1,4 +1,4 @@ -// "Change 'x' type to 'Int'" "true" +// "Change 'A.x' type to 'Int'" "true" trait X { val x: Int } diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntLong.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntLong.kt index e810c22a1ee..80d3b2e6a05 100644 --- a/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntLong.kt +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntLong.kt @@ -1,4 +1,4 @@ -// "Change 'x' type to 'Int'" "true" +// "Change 'B.x' type to 'Int'" "true" abstract class A { abstract var x : Int } diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntUnit.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntUnit.kt index 8296b837504..f37ab4f9ff0 100644 --- a/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntUnit.kt +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/afterPropertyTypeMismatchOnOverrideIntUnit.kt @@ -1,4 +1,4 @@ -// "Change 'x' type to 'Int'" "true" +// "Change 'B.x' type to 'Int'" "true" abstract class A { abstract var x : Int } diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeMultipleOverriddenPropertiesTypes.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeMultipleOverriddenPropertiesTypes.kt new file mode 100644 index 00000000000..9fe0b5a6264 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeMultipleOverriddenPropertiesTypes.kt @@ -0,0 +1,14 @@ +// "Change 'A.x' type to '(Int) -> Int'" "false" +// ACTION: Change 'C.x' type to '(String) -> Int' +// ERROR: Return type is '(jet.Int) → jet.Int', which is not a subtype of overridden
internal abstract val x: (jet.String) → jet.Int defined in A +trait A { + val x: (String) -> Int +} + +trait B { + val x: (String) -> Any +} + +trait C : A, B { + override val x: (Int) -> Int +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeOverriddenPropertyTypeToMatchOverridingProperty.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeOverriddenPropertyTypeToMatchOverridingProperty.kt new file mode 100644 index 00000000000..1a7149f1ca8 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeOverriddenPropertyTypeToMatchOverridingProperty.kt @@ -0,0 +1,13 @@ +// "Change 'A.x' type to 'String'" "false" +// ERROR: Var-property type is 'jet.String', which is not a type of overridden
internal abstract var x: jet.Int defined in A +trait A { + var x: Int +} + +trait B { + var x: Any +} + +trait C : A, B { + override var x: String +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangePropertyTypeToMatchOverridenProperties.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangePropertyTypeToMatchOverridenProperties.kt new file mode 100644 index 00000000000..c47babf6e69 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangePropertyTypeToMatchOverridenProperties.kt @@ -0,0 +1,13 @@ +// "Change 'C.x' type to 'String'" "false" +// ERROR: Var-property type is 'jet.Int', which is not a type of overridden
internal abstract var x: jet.String defined in A +trait A { + var x: String +} + +trait B { + var x: Any +} + +trait C : A, B { + override var x: Int +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeReturnTypeOfOverriddenFunction.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeReturnTypeOfOverriddenFunction.kt new file mode 100644 index 00000000000..302ed8d5be4 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeReturnTypeOfOverriddenFunction.kt @@ -0,0 +1,13 @@ +// "Change 'A.foo' function return type to 'Long'" "false" +// ERROR: Return type is 'jet.Long', which is not a subtype of overridden
internal abstract fun foo(): jet.Int defined in A +trait A { + fun foo(): Int +} + +trait B { + fun foo(): String +} + +trait C : A, B { + override fun foo(): Long +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType1.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType1.kt new file mode 100644 index 00000000000..9216f429193 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType1.kt @@ -0,0 +1,12 @@ +// "Change 'B.x' type to '(Int) -> Int'" "true" +trait A { + val x: (Int) -> Int +} + +trait B { + val x: (String) -> Any +} + +trait C : A, B { + override val x: (Int) -> Int +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType2.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType2.kt new file mode 100644 index 00000000000..df144be7ce6 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType2.kt @@ -0,0 +1,12 @@ +// "Change 'A.x' type to 'String'" "true" +trait A { + var x: Int +} + +trait B { + var x: String +} + +trait C : A, B { + override var x: String +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverridingPropertyTypeToFunctionType.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverridingPropertyTypeToFunctionType.kt new file mode 100644 index 00000000000..6a6b1155d01 --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverridingPropertyTypeToFunctionType.kt @@ -0,0 +1,7 @@ +// "Change 'B.x' type to '(String) -> Int'" "true" +trait A { + var x: (String) -> Int +} +trait B : A { + override var x: (Int) -> String +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeReturnTypeOfOverriddenFunction.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeReturnTypeOfOverriddenFunction.kt new file mode 100644 index 00000000000..a8ccbc2551c --- /dev/null +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeReturnTypeOfOverriddenFunction.kt @@ -0,0 +1,12 @@ +// "Change 'A.foo' function return type to 'Long'" "true" +trait A { + fun foo(): Int +} + +trait B { + fun foo(): Number +} + +trait C : A, B { + override fun foo(): Long +} \ No newline at end of file diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyReturnTypeMismatchOnOverride.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyReturnTypeMismatchOnOverride.kt index afd321e5cfa..4378d809f4a 100644 --- a/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyReturnTypeMismatchOnOverride.kt +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyReturnTypeMismatchOnOverride.kt @@ -1,4 +1,4 @@ -// "Change 'x' type to 'Int'" "true" +// "Change 'A.x' type to 'Int'" "true" trait X { val x: Int } diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntLong.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntLong.kt index db0eabb5856..a70d8d74a05 100644 --- a/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntLong.kt +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntLong.kt @@ -1,4 +1,4 @@ -// "Change 'x' type to 'Int'" "true" +// "Change 'B.x' type to 'Int'" "true" abstract class A { abstract var x : Int } diff --git a/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntUnit.kt b/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntUnit.kt index 39289180da2..469a62099b0 100644 --- a/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntUnit.kt +++ b/idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyTypeMismatchOnOverrideIntUnit.kt @@ -1,4 +1,4 @@ -// "Change 'x' type to 'Int'" "true" +// "Change 'B.x' type to 'Int'" "true" abstract class A { abstract var x : Int } diff --git a/idea/testData/quickfix/typeAddition/afterChangeAccessorTypeToFunctionType.kt b/idea/testData/quickfix/typeAddition/afterChangeAccessorTypeToFunctionType.kt new file mode 100644 index 00000000000..642223733a3 --- /dev/null +++ b/idea/testData/quickfix/typeAddition/afterChangeAccessorTypeToFunctionType.kt @@ -0,0 +1,5 @@ +// "Change getter type to (String) -> Int" "true" +class A { + val x: (String) -> Int + get(): (String) -> Int = {42} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeAddition/beforeChangeAccessorTypeToFunctionType.kt b/idea/testData/quickfix/typeAddition/beforeChangeAccessorTypeToFunctionType.kt new file mode 100644 index 00000000000..2a070579945 --- /dev/null +++ b/idea/testData/quickfix/typeAddition/beforeChangeAccessorTypeToFunctionType.kt @@ -0,0 +1,5 @@ +// "Change getter type to (String) -> Int" "true" +class A { + val x: (String) -> Int + get(): Int = {42} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/afterChangeFunctionLiteralParameterTypeToFunctionType.kt b/idea/testData/quickfix/typeMismatch/afterChangeFunctionLiteralParameterTypeToFunctionType.kt new file mode 100644 index 00000000000..89a07f91281 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/afterChangeFunctionLiteralParameterTypeToFunctionType.kt @@ -0,0 +1,6 @@ +// "Change type from 'String' to '(Int) -> String'" "true" +fun foo(f: ((Int) -> String) -> String) { + foo { + (f: (Int) -> String) -> f(42) + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/afterChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt b/idea/testData/quickfix/typeMismatch/afterChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt new file mode 100644 index 00000000000..e043c28dd7b --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/afterChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt @@ -0,0 +1,3 @@ +// "Change 'bar' function return type to 'String'" "true" +fun bar(): String = "" +fun foo(): String = bar() \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/afterPropertyTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/afterPropertyTypeMismatch.kt new file mode 100644 index 00000000000..4302b75770c --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/afterPropertyTypeMismatch.kt @@ -0,0 +1,4 @@ +// "Change 'f' type to '(Long) -> Unit'" "true" +fun foo() { + var f: (Long) -> Unit = if (true) { (x: Long) -> } else { (x: Long) -> } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforeChangeFunctionLiteralParameterTypeToFunctionType.kt b/idea/testData/quickfix/typeMismatch/beforeChangeFunctionLiteralParameterTypeToFunctionType.kt new file mode 100644 index 00000000000..c8897d3a65e --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/beforeChangeFunctionLiteralParameterTypeToFunctionType.kt @@ -0,0 +1,6 @@ +// "Change type from 'String' to '(Int) -> String'" "true" +fun foo(f: ((Int) -> String) -> String) { + foo { + (f: String) -> f(42) + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt b/idea/testData/quickfix/typeMismatch/beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt new file mode 100644 index 00000000000..dcd7a090c5b --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt @@ -0,0 +1,3 @@ +// "Change 'bar' function return type to 'String'" "true" +fun bar(): Any = "" +fun foo(): String = bar() \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforeDontChangeOverriddenPropertyTypeToErrorType.kt b/idea/testData/quickfix/typeMismatch/beforeDontChangeOverriddenPropertyTypeToErrorType.kt new file mode 100644 index 00000000000..b291b9499cf --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/beforeDontChangeOverriddenPropertyTypeToErrorType.kt @@ -0,0 +1,10 @@ +// "Change 'B.x' type to '(String) -> [ERROR : Ay]'" "false" +// ACTION: Change 'A.x' type to '(Int) -> Int' +// ERROR: Return type is '(jet.Int) → jet.Int', which is not a subtype of overridden
internal abstract val x: (jet.String) → [ERROR : Ay] defined in A +// ERROR: Unresolved reference: Ay +trait A { + val x: (String) -> Ay +} +trait B : A { + override val x: (Int) -> Int +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforePropertyTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/beforePropertyTypeMismatch.kt new file mode 100644 index 00000000000..a1ffc07759c --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/beforePropertyTypeMismatch.kt @@ -0,0 +1,4 @@ +// "Change 'f' type to '(Long) -> Unit'" "true" +fun foo() { + var f: Int = if (true) { (x: Long) -> } else { (x: Long) -> } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/casts/afterCastToFunctionType.kt b/idea/testData/quickfix/typeMismatch/casts/afterCastToFunctionType.kt new file mode 100644 index 00000000000..989e55304cf --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/casts/afterCastToFunctionType.kt @@ -0,0 +1,4 @@ +// "Cast expression 'x' to '() -> Int'" "true" +fun foo(x: Any): () -> Int { + return x as () -> Int +} diff --git a/idea/testData/quickfix/typeMismatch/casts/beforeCastToFunctionType.kt b/idea/testData/quickfix/typeMismatch/casts/beforeCastToFunctionType.kt new file mode 100644 index 00000000000..eb0f35b50c3 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/casts/beforeCastToFunctionType.kt @@ -0,0 +1,4 @@ +// "Cast expression 'x' to '() -> Int'" "true" +fun foo(x: Any): () -> Int { + return x +} diff --git a/idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch1.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch1.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch1.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch1.kt diff --git a/idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch2.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch2.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch2.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch2.kt diff --git a/idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch3.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch3.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch3.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch3.kt diff --git a/idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch4.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch4.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch4.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch4.kt diff --git a/idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch5.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch5.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/afterComponentFunctionReturnTypeMismatch5.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/afterComponentFunctionReturnTypeMismatch5.kt diff --git a/idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch1.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch1.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch1.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch1.kt diff --git a/idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch2.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch2.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch2.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch2.kt diff --git a/idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch3.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch3.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch3.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch3.kt diff --git a/idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch4.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch4.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch4.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch4.kt diff --git a/idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch5.kt b/idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch5.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch5.kt rename to idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch5.kt diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeNotFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeNotFunctionReturnType.kt new file mode 100644 index 00000000000..2e02e549264 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeNotFunctionReturnType.kt @@ -0,0 +1,7 @@ +// "Change 'A.not' function return type to 'A'" "true" +trait A { + fun not(): A + fun times(a: A): A +} + +fun foo(a: A): A = a * !(if (true) a else a) \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangePlusFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangePlusFunctionReturnType.kt new file mode 100644 index 00000000000..5f841fe38b4 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangePlusFunctionReturnType.kt @@ -0,0 +1,8 @@ +// "Change 'A.plus' function return type to '() -> Int'" "true" +trait A { + fun plus(a: A): () -> Int +} + +fun foo(a: A): () -> Int { + return a + a +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeTimesFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeTimesFunctionParameterType.kt new file mode 100644 index 00000000000..a0178c297d5 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeTimesFunctionParameterType.kt @@ -0,0 +1,6 @@ +// "Change parameter 'a' type of function 'A.times' to 'String'" "true" +trait A { + fun times(a: String): A +} + +fun foo(a: A): A = a * "" \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt new file mode 100644 index 00000000000..3fcbddff06c --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt @@ -0,0 +1,7 @@ +// "Change 'A.not' function return type to 'A'" "true" +trait A { + fun not(): String + fun times(a: A): A +} + +fun foo(a: A): A = a * !(if (true) a else a) \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt new file mode 100644 index 00000000000..c83d83f0c41 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt @@ -0,0 +1,8 @@ +// "Change 'A.plus' function return type to '() -> Int'" "true" +trait A { + fun plus(a: A): String +} + +fun foo(a: A): () -> Int { + return a + a +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt new file mode 100644 index 00000000000..837fc7af446 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt @@ -0,0 +1,6 @@ +// "Change parameter 'a' type of function 'A.times' to 'String'" "true" +trait A { + fun times(a: A): A +} + +fun foo(a: A): A = a * "" \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType1.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType1.kt new file mode 100644 index 00000000000..b253e8b1782 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType1.kt @@ -0,0 +1,5 @@ +// "Change parameter 'x' type of function 'bar.foo' to '(String) -> Int'" "true" +package bar +fun foo(w: Int = 0, x: (String) -> Int, y: Int = 0, z: (Int) -> Int = {42}) { + foo(1, {(a: String) -> 42}, 1) +} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType2.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType2.kt new file mode 100644 index 00000000000..c1b3343642c --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType2.kt @@ -0,0 +1,4 @@ +// "Change parameter 'y' type of function 'foo' to 'String'" "true" +fun foo(v: Int, w: Int = 0, x: Int = 0, y: String, z: (Int) -> Int = {42}) { + foo(0, 1, y = "") +} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType3.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType3.kt new file mode 100644 index 00000000000..30b490ba5ed --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangeFunctionParameterType3.kt @@ -0,0 +1,4 @@ +// "Change parameter 'z' type of function 'foo' to '(Int) -> Unit'" "true" +fun foo(w: Int = 0, x: Int, y: Int = 0, z: (Int) -> Unit) { + foo(0, 1) {} +} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangePrimaryConstructorParameterType.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangePrimaryConstructorParameterType.kt new file mode 100644 index 00000000000..9acd1ad0389 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/afterChangePrimaryConstructorParameterType.kt @@ -0,0 +1,5 @@ +// "Change parameter 'a' type of primary constructor of class 'B' to 'String'" "true" +class B(val a: String) +fun foo() { + B(if (true) "" else "") +} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType1.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType1.kt new file mode 100644 index 00000000000..deb5313f041 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType1.kt @@ -0,0 +1,5 @@ +// "Change parameter 'x' type of function 'bar.foo' to '(String) -> Int'" "true" +package bar +fun foo(w: Int = 0, x: Int, y: Int = 0, z: (Int) -> Int = {42}) { + foo(1, {(a: String) -> 42}, 1) +} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType2.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType2.kt new file mode 100644 index 00000000000..c5e45b514be --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType2.kt @@ -0,0 +1,4 @@ +// "Change parameter 'y' type of function 'foo' to 'String'" "true" +fun foo(v: Int, w: Int = 0, x: Int = 0, y: Int, z: (Int) -> Int = {42}) { + foo(0, 1, y = "") +} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType3.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType3.kt new file mode 100644 index 00000000000..9d5f48d961d --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType3.kt @@ -0,0 +1,4 @@ +// "Change parameter 'z' type of function 'foo' to '(Int) -> Unit'" "true" +fun foo(w: Int = 0, x: Int, y: Int = 0, z: (Int) -> String) { + foo(0, 1) {} +} diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType4.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType4.kt new file mode 100644 index 00000000000..a4c9f02baaf --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType4.kt @@ -0,0 +1,8 @@ +// "Change parameter 'z' type of function 'foo' to '(Int) -> String'" "false" +// ERROR: Type mismatch.
Required:jet.Int
Found:jet.String
+fun foo(y: Int = 0, z: (Int) -> String = {""}) { + foo { + "": Int + "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType5.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType5.kt new file mode 100644 index 00000000000..80f37c15a85 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType5.kt @@ -0,0 +1,5 @@ +// "Change parameter 'y' type of function 'foo' to 'Int'" "false" +// ERROR: Type mismatch.
Required:jet.Int
Found:jet.String
+fun foo(y: Int = 0, z: (Int) -> String = {""}) { + foo("": Int) +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangePrimaryConstructorParameterType.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangePrimaryConstructorParameterType.kt new file mode 100644 index 00000000000..7e39c54a4a1 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangePrimaryConstructorParameterType.kt @@ -0,0 +1,5 @@ +// "Change parameter 'a' type of primary constructor of class 'B' to 'String'" "true" +class B(val a: Int) +fun foo() { + B(if (true) "" else "") +} diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterAssignmentTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterAssignmentTypeMismatch.kt new file mode 100644 index 00000000000..ac73a6453e9 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterAssignmentTypeMismatch.kt @@ -0,0 +1,7 @@ +// "Change 'f' type to '() -> Unit'" "true" +fun foo() { + val f: () -> Unit = { + var x = 1 + x += 21 + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt new file mode 100644 index 00000000000..b2b6552068c --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt @@ -0,0 +1,7 @@ +// "Change function literal return type to 'String'" "true" +fun foo(f: (String) -> Any) { + foo { + (s: String): String -> + s + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionLiteralTypeWithoutChangingPropertyType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionLiteralTypeWithoutChangingPropertyType.kt new file mode 100644 index 00000000000..35be90c1bea --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionLiteralTypeWithoutChangingPropertyType.kt @@ -0,0 +1,7 @@ +// "Change function literal return type to 'String'" "true" +fun foo() { + val f: (String) -> String = { + (s: Any): String -> + "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionReturnTypeToFunctionType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionReturnTypeToFunctionType.kt new file mode 100644 index 00000000000..4d6e718b946 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionReturnTypeToFunctionType.kt @@ -0,0 +1,4 @@ +// "Change 'foo' function return type to '(Long) -> Int'" "true" +fun foo(x: Any): (Long) -> Int { + return {(x: Long) -> 42} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt new file mode 100644 index 00000000000..5c7182093c5 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt @@ -0,0 +1,4 @@ +// "Change 'foo' function return type to '() -> Any'" "true" +fun foo(x: Any): () -> Any { + return {x} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterExpectedTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterExpectedTypeMismatch.kt new file mode 100644 index 00000000000..d51e2648772 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterExpectedTypeMismatch.kt @@ -0,0 +1,7 @@ +// "Change 'bar' type to '(() -> Long) -> Unit'" "true" +fun foo() { + val bar: (() -> Long) -> Unit = { + (f: () -> Long): Unit -> + var x = 5 + } +} diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterPropertyGetterInitializerTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterPropertyGetterInitializerTypeMismatch.kt new file mode 100644 index 00000000000..e22fc7027ef --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterPropertyGetterInitializerTypeMismatch.kt @@ -0,0 +1,6 @@ +// "Change 'A.x' type to '() -> Int'" "true" +class A { + var x: () -> Int + get(): () -> Int = if (true) { {42} } else { {24} } + set(i: () -> Int) {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterReturnedExpressionTypeMismatchFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterReturnedExpressionTypeMismatchFunctionParameterType.kt new file mode 100644 index 00000000000..16a4b270648 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterReturnedExpressionTypeMismatchFunctionParameterType.kt @@ -0,0 +1,6 @@ +// "Change parameter 'f' type of function 'foo' to '() -> String'" "true" +fun foo(f: () -> String) { + foo { + "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInIfStatementReturnedByFunction.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInIfStatementReturnedByFunction.kt new file mode 100644 index 00000000000..031dded208b --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInIfStatementReturnedByFunction.kt @@ -0,0 +1,7 @@ +// "Change 'boo' function return type to 'String'" "true" +fun boo(): String { + return ((if (true) { + val a = "" + a + } else "")) +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInIfStatementReturnedByLiteral.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInIfStatementReturnedByLiteral.kt new file mode 100644 index 00000000000..19f21d70c71 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInIfStatementReturnedByLiteral.kt @@ -0,0 +1,12 @@ +// "Change 'f' type to '(Int, Int) -> (String) -> Int'" "true" +fun foo() { + val f: (Int, Int) -> (String) -> Int = { + (a: Int, b: Int): (String) -> Int -> + val x = {(s: String) -> 42} + if (true) x + else if (true) x else { + var y = 42 + if (true) x else x + } + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/afterTypeMismatchInInitializer.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInInitializer.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/afterTypeMismatchInInitializer.kt rename to idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInInitializer.kt diff --git a/idea/testData/quickfix/typeMismatch/afterTypeMismatchInReturnStatement.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInReturnStatement.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/afterTypeMismatchInReturnStatement.kt rename to idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/afterTypeMismatchInReturnStatement.kt diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeAssignmentTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeAssignmentTypeMismatch.kt new file mode 100644 index 00000000000..ad45d53e8c7 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeAssignmentTypeMismatch.kt @@ -0,0 +1,7 @@ +// "Change 'f' type to '() -> Unit'" "true" +fun foo() { + val f: () -> Int = { + var x = 1 + x += 21 + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt new file mode 100644 index 00000000000..0a04b9f473b --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt @@ -0,0 +1,7 @@ +// "Change function literal return type to 'String'" "true" +fun foo(f: (String) -> Any) { + foo { + (s: String): Int -> + s + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingPropertyType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingPropertyType.kt new file mode 100644 index 00000000000..dbec7994ac1 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingPropertyType.kt @@ -0,0 +1,7 @@ +// "Change function literal return type to 'String'" "true" +fun foo() { + val f: (String) -> String = { + (s: Any): Int -> + "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToFunctionType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToFunctionType.kt new file mode 100644 index 00000000000..2f90f8ee5e5 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToFunctionType.kt @@ -0,0 +1,4 @@ +// "Change 'foo' function return type to '(Long) -> Int'" "true" +fun foo(x: Any): Int { + return {(x: Long) -> 42} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt new file mode 100644 index 00000000000..44c4c565685 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt @@ -0,0 +1,4 @@ +// "Change 'foo' function return type to '() -> Any'" "true" +fun foo(x: Any): () -> Int { + return {x} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeDontChangeFunctionReturnTypeToErrorType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeDontChangeFunctionReturnTypeToErrorType.kt new file mode 100644 index 00000000000..ff1d6c75cf7 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeDontChangeFunctionReturnTypeToErrorType.kt @@ -0,0 +1,6 @@ +// "Change 'foo' function return type to '([ERROR : NoSuchType]) -> Int'" "false" +// ERROR: Type mismatch.
Required:jet.Int
Found:([ERROR : NoSuchType]) → jet.Int
+// ERROR: Unresolved reference: NoSuchType +fun foo(): Int { + return { (x: NoSuchType) -> 42 } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeExpectedTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeExpectedTypeMismatch.kt new file mode 100644 index 00000000000..379a397ab85 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeExpectedTypeMismatch.kt @@ -0,0 +1,7 @@ +// "Change 'bar' type to '(() -> Long) -> Unit'" "true" +fun foo() { + val bar: () -> Double = { + (f: () -> Long): String -> + var x = 5 + } +} diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforePropertyGetterInitializerTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforePropertyGetterInitializerTypeMismatch.kt new file mode 100644 index 00000000000..c9196877276 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforePropertyGetterInitializerTypeMismatch.kt @@ -0,0 +1,6 @@ +// "Change 'A.x' type to '() -> Int'" "true" +class A { + var x: Int + get(): Int = if (true) { {42} } else { {24} } + set(i: Int) {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpresionCantEvaluateToExpresionThatTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpresionCantEvaluateToExpresionThatTypeMismatch.kt new file mode 100644 index 00000000000..8161c29c287 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpresionCantEvaluateToExpresionThatTypeMismatch.kt @@ -0,0 +1,6 @@ +// "Change function 'foo' return type to 'String'" "false" +// ERROR: Type mismatch.
Required:jet.Int
Found:jet.String
+// ACTION: Disable 'Replace 'if' with 'when'' +// ACTION: Edit intention settings +// ACTION: Replace 'if' with 'when' +fun foo(): Int = if (true) "": Int else 4 \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpressionTypeMismatchFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpressionTypeMismatchFunctionParameterType.kt new file mode 100644 index 00000000000..cb39787a072 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpressionTypeMismatchFunctionParameterType.kt @@ -0,0 +1,6 @@ +// "Change parameter 'f' type of function 'foo' to '() -> String'" "true" +fun foo(f: () -> Int) { + foo { + "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByFunction.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByFunction.kt new file mode 100644 index 00000000000..8a4869a7439 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByFunction.kt @@ -0,0 +1,7 @@ +// "Change 'boo' function return type to 'String'" "true" +fun boo(): Int { + return ((if (true) { + val a = "" + a + } else "")) +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByLiteral.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByLiteral.kt new file mode 100644 index 00000000000..ae1c5c6a142 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByLiteral.kt @@ -0,0 +1,12 @@ +// "Change 'f' type to '(Int, Int) -> (String) -> Int'" "true" +fun foo() { + val f: () -> Long = { + (a: Int, b: Int): Long -> + val x = {(s: String) -> 42} + if (true) x + else if (true) x else { + var y = 42 + if (true) x else x + } + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforeTypeMismatchInInitializer.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInInitializer.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/beforeTypeMismatchInInitializer.kt rename to idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInInitializer.kt diff --git a/idea/testData/quickfix/typeMismatch/beforeTypeMismatchInReturnStatement.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInReturnStatement.kt similarity index 100% rename from idea/testData/quickfix/typeMismatch/beforeTypeMismatchInReturnStatement.kt rename to idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInReturnStatement.kt diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java index 350eaa4bd87..f4226698736 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -1018,6 +1018,46 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/override/typeMismatchOnOverride"), Pattern.compile("^before(\\w+)\\.kt$"), true); } + @TestMetadata("beforeCantChangeMultipleOverriddenPropertiesTypes.kt") + public void testCantChangeMultipleOverriddenPropertiesTypes() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeMultipleOverriddenPropertiesTypes.kt"); + } + + @TestMetadata("beforeCantChangeOverriddenPropertyTypeToMatchOverridingProperty.kt") + public void testCantChangeOverriddenPropertyTypeToMatchOverridingProperty() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeOverriddenPropertyTypeToMatchOverridingProperty.kt"); + } + + @TestMetadata("beforeCantChangePropertyTypeToMatchOverridenProperties.kt") + public void testCantChangePropertyTypeToMatchOverridenProperties() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangePropertyTypeToMatchOverridenProperties.kt"); + } + + @TestMetadata("beforeCantChangeReturnTypeOfOverriddenFunction.kt") + public void testCantChangeReturnTypeOfOverriddenFunction() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeCantChangeReturnTypeOfOverriddenFunction.kt"); + } + + @TestMetadata("beforeChangeOverriddenPropertyType1.kt") + public void testChangeOverriddenPropertyType1() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType1.kt"); + } + + @TestMetadata("beforeChangeOverriddenPropertyType2.kt") + public void testChangeOverriddenPropertyType2() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverriddenPropertyType2.kt"); + } + + @TestMetadata("beforeChangeOverridingPropertyTypeToFunctionType.kt") + public void testChangeOverridingPropertyTypeToFunctionType() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeOverridingPropertyTypeToFunctionType.kt"); + } + + @TestMetadata("beforeChangeReturnTypeOfOverriddenFunction.kt") + public void testChangeReturnTypeOfOverriddenFunction() throws Exception { + doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforeChangeReturnTypeOfOverriddenFunction.kt"); + } + @TestMetadata("beforePropertyReturnTypeMismatchOnOverride.kt") public void testPropertyReturnTypeMismatchOnOverride() throws Exception { doTest("idea/testData/quickfix/override/typeMismatchOnOverride/beforePropertyReturnTypeMismatchOnOverride.kt"); @@ -1149,6 +1189,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeAddition/beforeAmbiguousPropertyReturnType.kt"); } + @TestMetadata("beforeChangeAccessorTypeToFunctionType.kt") + public void testChangeAccessorTypeToFunctionType() throws Exception { + doTest("idea/testData/quickfix/typeAddition/beforeChangeAccessorTypeToFunctionType.kt"); + } + @TestMetadata("beforeNoAddErrorType.kt") public void testNoAddErrorType() throws Exception { doTest("idea/testData/quickfix/typeAddition/beforeNoAddErrorType.kt"); @@ -1230,12 +1275,22 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } @TestMetadata("idea/testData/quickfix/typeMismatch") - @InnerTestClasses({TypeMismatch.Casts.class}) + @InnerTestClasses({TypeMismatch.Casts.class, TypeMismatch.ComponentFunctionReturnTypeMismatch.class, TypeMismatch.FixOverloadedOperator.class, TypeMismatch.ParameterTypeMismatch.class, TypeMismatch.TypeMismatchOnReturnedExpression.class}) public static class TypeMismatch extends AbstractQuickFixTest { public void testAllFilesPresentInTypeMismatch() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/typeMismatch"), Pattern.compile("^before(\\w+)\\.kt$"), true); } + @TestMetadata("beforeChangeFunctionLiteralParameterTypeToFunctionType.kt") + public void testChangeFunctionLiteralParameterTypeToFunctionType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/beforeChangeFunctionLiteralParameterTypeToFunctionType.kt"); + } + + @TestMetadata("beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt") + public void testChangeFunctionReturnTypeToMatchExpectedTypeOfCall() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/beforeChangeFunctionReturnTypeToMatchExpectedTypeOfCall.kt"); + } + @TestMetadata("beforeChangeReturnTypeWhenFunctionNameIsMissing.kt") public void testChangeReturnTypeWhenFunctionNameIsMissing() throws Exception { doTest("idea/testData/quickfix/typeMismatch/beforeChangeReturnTypeWhenFunctionNameIsMissing.kt"); @@ -1251,29 +1306,9 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeMismatch/beforeCompareToTypeMismatch.kt"); } - @TestMetadata("beforeComponentFunctionReturnTypeMismatch1.kt") - public void testComponentFunctionReturnTypeMismatch1() throws Exception { - doTest("idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch1.kt"); - } - - @TestMetadata("beforeComponentFunctionReturnTypeMismatch2.kt") - public void testComponentFunctionReturnTypeMismatch2() throws Exception { - doTest("idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch2.kt"); - } - - @TestMetadata("beforeComponentFunctionReturnTypeMismatch3.kt") - public void testComponentFunctionReturnTypeMismatch3() throws Exception { - doTest("idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch3.kt"); - } - - @TestMetadata("beforeComponentFunctionReturnTypeMismatch4.kt") - public void testComponentFunctionReturnTypeMismatch4() throws Exception { - doTest("idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch4.kt"); - } - - @TestMetadata("beforeComponentFunctionReturnTypeMismatch5.kt") - public void testComponentFunctionReturnTypeMismatch5() throws Exception { - doTest("idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch5.kt"); + @TestMetadata("beforeDontChangeOverriddenPropertyTypeToErrorType.kt") + public void testDontChangeOverriddenPropertyTypeToErrorType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/beforeDontChangeOverriddenPropertyTypeToErrorType.kt"); } @TestMetadata("beforeExpectedParameterTypeMismatch.kt") @@ -1296,21 +1331,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeMismatch/beforeNoReturnInFunctionWithBlockBody.kt"); } + @TestMetadata("beforePropertyTypeMismatch.kt") + public void testPropertyTypeMismatch() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/beforePropertyTypeMismatch.kt"); + } + @TestMetadata("beforeReturnTypeMismatch.kt") public void testReturnTypeMismatch() throws Exception { doTest("idea/testData/quickfix/typeMismatch/beforeReturnTypeMismatch.kt"); } - @TestMetadata("beforeTypeMismatchInInitializer.kt") - public void testTypeMismatchInInitializer() throws Exception { - doTest("idea/testData/quickfix/typeMismatch/beforeTypeMismatchInInitializer.kt"); - } - - @TestMetadata("beforeTypeMismatchInReturnStatement.kt") - public void testTypeMismatchInReturnStatement() throws Exception { - doTest("idea/testData/quickfix/typeMismatch/beforeTypeMismatchInReturnStatement.kt"); - } - @TestMetadata("idea/testData/quickfix/typeMismatch/casts") public static class Casts extends AbstractQuickFixTest { public void testAllFilesPresentInCasts() throws Exception { @@ -1332,6 +1362,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeMismatch/casts/beforeAutocastImpossible3.kt"); } + @TestMetadata("beforeCastToFunctionType.kt") + public void testCastToFunctionType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/casts/beforeCastToFunctionType.kt"); + } + @TestMetadata("beforeTypeMismatch1.kt") public void testTypeMismatch1() throws Exception { doTest("idea/testData/quickfix/typeMismatch/casts/beforeTypeMismatch1.kt"); @@ -1359,10 +1394,186 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } + @TestMetadata("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch") + public static class ComponentFunctionReturnTypeMismatch extends AbstractQuickFixTest { + public void testAllFilesPresentInComponentFunctionReturnTypeMismatch() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch"), Pattern.compile("^before(\\w+)\\.kt$"), true); + } + + @TestMetadata("beforeComponentFunctionReturnTypeMismatch1.kt") + public void testComponentFunctionReturnTypeMismatch1() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch1.kt"); + } + + @TestMetadata("beforeComponentFunctionReturnTypeMismatch2.kt") + public void testComponentFunctionReturnTypeMismatch2() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch2.kt"); + } + + @TestMetadata("beforeComponentFunctionReturnTypeMismatch3.kt") + public void testComponentFunctionReturnTypeMismatch3() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch3.kt"); + } + + @TestMetadata("beforeComponentFunctionReturnTypeMismatch4.kt") + public void testComponentFunctionReturnTypeMismatch4() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch4.kt"); + } + + @TestMetadata("beforeComponentFunctionReturnTypeMismatch5.kt") + public void testComponentFunctionReturnTypeMismatch5() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/componentFunctionReturnTypeMismatch/beforeComponentFunctionReturnTypeMismatch5.kt"); + } + + } + + @TestMetadata("idea/testData/quickfix/typeMismatch/fixOverloadedOperator") + public static class FixOverloadedOperator extends AbstractQuickFixTest { + public void testAllFilesPresentInFixOverloadedOperator() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/typeMismatch/fixOverloadedOperator"), Pattern.compile("^before(\\w+)\\.kt$"), true); + } + + @TestMetadata("beforeChangeNotFunctionReturnType.kt") + public void testChangeNotFunctionReturnType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt"); + } + + @TestMetadata("beforeChangePlusFunctionReturnType.kt") + public void testChangePlusFunctionReturnType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt"); + } + + @TestMetadata("beforeChangeTimesFunctionParameterType.kt") + public void testChangeTimesFunctionParameterType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt"); + } + + } + + @TestMetadata("idea/testData/quickfix/typeMismatch/parameterTypeMismatch") + public static class ParameterTypeMismatch extends AbstractQuickFixTest { + public void testAllFilesPresentInParameterTypeMismatch() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/typeMismatch/parameterTypeMismatch"), Pattern.compile("^before(\\w+)\\.kt$"), true); + } + + @TestMetadata("beforeChangeFunctionParameterType1.kt") + public void testChangeFunctionParameterType1() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType1.kt"); + } + + @TestMetadata("beforeChangeFunctionParameterType2.kt") + public void testChangeFunctionParameterType2() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType2.kt"); + } + + @TestMetadata("beforeChangeFunctionParameterType3.kt") + public void testChangeFunctionParameterType3() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType3.kt"); + } + + @TestMetadata("beforeChangeFunctionParameterType4.kt") + public void testChangeFunctionParameterType4() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType4.kt"); + } + + @TestMetadata("beforeChangeFunctionParameterType5.kt") + public void testChangeFunctionParameterType5() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangeFunctionParameterType5.kt"); + } + + @TestMetadata("beforeChangePrimaryConstructorParameterType.kt") + public void testChangePrimaryConstructorParameterType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/beforeChangePrimaryConstructorParameterType.kt"); + } + + } + + @TestMetadata("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression") + public static class TypeMismatchOnReturnedExpression extends AbstractQuickFixTest { + public void testAllFilesPresentInTypeMismatchOnReturnedExpression() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression"), Pattern.compile("^before(\\w+)\\.kt$"), true); + } + + @TestMetadata("beforeAssignmentTypeMismatch.kt") + public void testAssignmentTypeMismatch() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeAssignmentTypeMismatch.kt"); + } + + @TestMetadata("beforeChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt") + public void testChangeFunctionLiteralTypeWithoutChangingFunctionParameterType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingFunctionParameterType.kt"); + } + + @TestMetadata("beforeChangeFunctionLiteralTypeWithoutChangingPropertyType.kt") + public void testChangeFunctionLiteralTypeWithoutChangingPropertyType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionLiteralTypeWithoutChangingPropertyType.kt"); + } + + @TestMetadata("beforeChangeFunctionReturnTypeToFunctionType.kt") + public void testChangeFunctionReturnTypeToFunctionType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToFunctionType.kt"); + } + + @TestMetadata("beforeChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt") + public void testChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeChangeFunctionReturnTypeToMatchReturnTypeOfReturnedLiteral.kt"); + } + + @TestMetadata("beforeDontChangeFunctionReturnTypeToErrorType.kt") + public void testDontChangeFunctionReturnTypeToErrorType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeDontChangeFunctionReturnTypeToErrorType.kt"); + } + + @TestMetadata("beforeExpectedTypeMismatch.kt") + public void testExpectedTypeMismatch() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeExpectedTypeMismatch.kt"); + } + + @TestMetadata("beforePropertyGetterInitializerTypeMismatch.kt") + public void testPropertyGetterInitializerTypeMismatch() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforePropertyGetterInitializerTypeMismatch.kt"); + } + + @TestMetadata("beforeReturnedExpresionCantEvaluateToExpresionThatTypeMismatch.kt") + public void testReturnedExpresionCantEvaluateToExpresionThatTypeMismatch() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpresionCantEvaluateToExpresionThatTypeMismatch.kt"); + } + + @TestMetadata("beforeReturnedExpressionTypeMismatchFunctionParameterType.kt") + public void testReturnedExpressionTypeMismatchFunctionParameterType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeReturnedExpressionTypeMismatchFunctionParameterType.kt"); + } + + @TestMetadata("beforeTypeMismatchInIfStatementReturnedByFunction.kt") + public void testTypeMismatchInIfStatementReturnedByFunction() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByFunction.kt"); + } + + @TestMetadata("beforeTypeMismatchInIfStatementReturnedByLiteral.kt") + public void testTypeMismatchInIfStatementReturnedByLiteral() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInIfStatementReturnedByLiteral.kt"); + } + + @TestMetadata("beforeTypeMismatchInInitializer.kt") + public void testTypeMismatchInInitializer() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInInitializer.kt"); + } + + @TestMetadata("beforeTypeMismatchInReturnStatement.kt") + public void testTypeMismatchInReturnStatement() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeTypeMismatchInReturnStatement.kt"); + } + + } + public static Test innerSuite() { TestSuite suite = new TestSuite("TypeMismatch"); suite.addTestSuite(TypeMismatch.class); suite.addTestSuite(Casts.class); + suite.addTestSuite(ComponentFunctionReturnTypeMismatch.class); + suite.addTestSuite(FixOverloadedOperator.class); + suite.addTestSuite(ParameterTypeMismatch.class); + suite.addTestSuite(TypeMismatchOnReturnedExpression.class); return suite; } } diff --git a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java index ce53354d6ad..593cf2407c6 100644 --- a/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java +++ b/jps-plugin/src/org/jetbrains/jet/jps/build/KotlinBuilderModuleScriptGenerator.java @@ -130,6 +130,16 @@ public class KotlinBuilderModuleScriptGenerator { } } + // JDK is stored locally on user's machine, so its configuration, including external annotation paths + // is not available on TeamCity. When running on TeamCity, one has to provide extra path to JDK annotations + String extraAnnotationsPaths = System.getProperty("jps.kotlin.extra.annotation.paths"); + if (extraAnnotationsPaths != null) { + String[] paths = extraAnnotationsPaths.split(File.pathSeparator); + for (String path : paths) { + annotationRootFiles.add(new File(path)); + } + } + return annotationRootFiles; } diff --git a/libraries/pom.xml b/libraries/pom.xml index b3e31788884..48652d81263 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -57,6 +57,7 @@ tools/kotlin-jdk-annotations tools/runtime tools/kotlin-gradle-plugin + tools/kotlin-gradle-plugin-core tools/kotlin-maven-plugin tools/kotlin-js-library tools/kotlin-js-tests diff --git a/libraries/stdlib/src/kotlin/properties/Delegation.kt b/libraries/stdlib/src/kotlin/properties/Delegation.kt new file mode 100644 index 00000000000..a56b98b2a78 --- /dev/null +++ b/libraries/stdlib/src/kotlin/properties/Delegation.kt @@ -0,0 +1,175 @@ +package kotlin.properties + +public trait ReadOnlyProperty { + public fun get(thisRef: R, desc: PropertyMetadata): T +} + +public trait ReadWriteProperty { + public fun get(thisRef: R, desc: PropertyMetadata): T + public fun set(thisRef: R, desc: PropertyMetadata, value: T) +} + +public object Delegates { + public fun notNull(): ReadWriteProperty = NotNullVar() + + public fun lazy(initializer: () -> T): ReadOnlyProperty = LazyVal(initializer) + public fun blockingLazy(lock: Any? = null, initializer: () -> T): ReadOnlyProperty = BlockingLazyVal(lock, initializer) + + public fun observable(initial: T, onChange: (desc: PropertyMetadata, oldValue: T, newValue: T) -> Unit): ReadWriteProperty { + return ObservableProperty(initial) { (desc, old, new) -> + onChange(desc, old, new) + true + } + } + + public fun vetoable(initial: T, onChange: (desc: PropertyMetadata, oldValue: T, newValue: T) -> Boolean): ReadWriteProperty { + return ObservableProperty(initial, onChange) + } + + public fun mapVar(map: MutableMap, + default: (thisRef: Any?, desc: String) -> T = defaultValueProvider): ReadWriteProperty { + return FixedMapVar(map, defaultKeyProvider, default) + } + + public fun mapVal(map: Map, + default: (thisRef: Any?, desc: String) -> T = defaultValueProvider): ReadOnlyProperty { + return FixedMapVal(map, defaultKeyProvider, default) + } +} + + +private class NotNullVar() : ReadWriteProperty { + private var value: T? = null + + public override fun get(thisRef: Any?, desc: PropertyMetadata): T { + return value ?: throw IllegalStateException("Property ${desc.name} should be initialized before get") + } + + public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) { + this.value = value + } +} + +class ObservableProperty(initialValue: T, val onChange: (name: jet.PropertyMetadata, oldValue: T, newValue: T) -> Boolean): ReadWriteProperty { + private var value = initialValue + + public override fun get(thisRef: Any?, desc: PropertyMetadata): T { + return value + } + + public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) { + if (onChange(desc, this.value, value)) { + this.value = value + } + } +} + +private val NULL_VALUE: Any = Any() + +private fun escape(value: Any?): Any { + return value ?: NULL_VALUE +} + +private fun unescape(value: Any?): Any? { + return if (value == NULL_VALUE) null else value +} + +private class LazyVal(private val initializer: () -> T) : ReadOnlyProperty { + private var value: Any? = null + + public override fun get(thisRef: Any?, desc: PropertyMetadata): T { + if (value == null) { + value = escape(initializer()) + } + return unescape(value) as T + } +} + +private class BlockingLazyVal(lock: Any?, private val initializer: () -> T) : ReadOnlyProperty { + private val lock = lock ?: this + private volatile var value: Any? = null + + public override fun get(thisRef: Any?, desc: PropertyMetadata): T { + val _v1 = value + if (_v1 != null) { + return unescape(_v1) as T + } + + return synchronized(lock) { + val _v2 = value + if (_v2 != null) { + unescape(_v2) as T + } + else { + val typedValue = initializer() + value = escape(typedValue) + typedValue + } + } + } +} + +public class KeyMissingException(message: String): RuntimeException(message) + +public abstract class MapVal() : ReadOnlyProperty { + protected abstract fun map(ref: T): Map + protected abstract fun key(desc: PropertyMetadata): K + + protected open fun default(ref: T, desc: PropertyMetadata): V { + throw KeyMissingException("Key $desc is missing in $ref") + } + + public override fun get(thisRef: T, desc: PropertyMetadata) : V { + val map = map(thisRef) + val key = key(desc) + if (!map.containsKey(key)) { + return default(thisRef, desc) + } + + return map[key] as V + } +} + +public abstract class MapVar() : MapVal(), ReadWriteProperty { + protected abstract override fun map(ref: T): MutableMap + + public override fun set(thisRef: T, desc: PropertyMetadata, value: V) { + val map = map(thisRef) + map.put(key(desc), value) + } +} + +private val defaultKeyProvider:(PropertyMetadata) -> String = {it.name} +private val defaultValueProvider:(Any?, Any?) -> Nothing = {(thisRef, key) -> throw KeyMissingException("$key is missing from $thisRef")} + +public open class FixedMapVal(private val map: Map, + private val key: (PropertyMetadata) -> K, + private val default: (ref: T, key: K) -> V = defaultValueProvider) : MapVal() { + protected override fun map(ref: T): Map { + return map + } + + protected override fun key(desc: PropertyMetadata): K { + return (key)(desc) + } + + protected override fun default(ref: T, desc: PropertyMetadata): V { + return (default)(ref, key(desc)) + } +} + +public open class FixedMapVar(private val map: MutableMap, + private val key: (PropertyMetadata) -> K, + private val default: (ref: T, key: K) -> V = defaultValueProvider) : MapVar() { + protected override fun map(ref: T): MutableMap { + return map + } + + protected override fun key(desc: PropertyMetadata): K { + return (key)(desc) + } + + protected override fun default(ref: T, desc: PropertyMetadata): V { + return (default)(ref, key(desc)) + } +} diff --git a/libraries/stdlib/src/kotlin/properties/Properties.kt b/libraries/stdlib/src/kotlin/properties/Properties.kt index e045c5993c6..78dc550e692 100644 --- a/libraries/stdlib/src/kotlin/properties/Properties.kt +++ b/libraries/stdlib/src/kotlin/properties/Properties.kt @@ -2,7 +2,6 @@ package kotlin.properties import java.util.HashMap import java.util.ArrayList -import kotlin.properties.delegation.ObservableProperty public class ChangeEvent(val source: Any, val name: String, val oldValue: Any?, val newValue: Any?) { var propogationId: Any? = null @@ -65,8 +64,8 @@ public abstract class ChangeSupport { } } - protected fun property(init: T): ObservableProperty { - return ObservableProperty(init) { name, oldValue, newValue -> changeProperty(name, oldValue, newValue) } + protected fun property(init: T): ReadWriteProperty { + return Delegates.observable(init) { desc, oldValue, newValue -> changeProperty(desc.name, oldValue, newValue) } } public fun onPropertyChange(fn: (ChangeEvent) -> Unit) { diff --git a/libraries/stdlib/test/properties/delegation/DelegationTest.kt b/libraries/stdlib/test/properties/delegation/DelegationTest.kt index cceeeaf6af1..4098956d993 100644 --- a/libraries/stdlib/test/properties/delegation/DelegationTest.kt +++ b/libraries/stdlib/test/properties/delegation/DelegationTest.kt @@ -3,8 +3,6 @@ package test.properties.delegation import junit.framework.TestCase import kotlin.test.* import kotlin.properties.* -import kotlin.properties.delegation.* -import kotlin.properties.delegation.lazy.* trait WithBox { fun box(): String @@ -27,8 +25,8 @@ class DelegationTest(): DelegationTestBase() { } public class TestNotNullVar(val a1: String, val b1: T): WithBox { - var a: String by NotNullVar() - var b by NotNullVar() + var a: String by Delegates.notNull() + var b by Delegates.notNull() override fun box(): String { a = a1 @@ -61,4 +59,4 @@ class TestObservableProperty: WithBox, ChangeSupport() { if (!result) return "fail: result should be true" return "OK" } -} \ No newline at end of file +} diff --git a/libraries/stdlib/test/properties/delegation/MapDelegationTest.kt b/libraries/stdlib/test/properties/delegation/MapDelegationTest.kt index 9bc21c81c20..b6df3fc21fb 100644 --- a/libraries/stdlib/test/properties/delegation/MapDelegationTest.kt +++ b/libraries/stdlib/test/properties/delegation/MapDelegationTest.kt @@ -1,7 +1,7 @@ package test.properties.delegation import java.util.HashMap -import kotlin.properties.delegation.* +import kotlin.properties.* class MapDelegationTest(): DelegationTestBase() { @@ -48,10 +48,10 @@ class MapDelegationTest(): DelegationTestBase() { class TestMapValWithDifferentTypes(): WithBox { val map = hashMapOf("a" to "a", "b" to 1, "c" to A(1), "d" to null) - val a by map.readOnlyProperty() - val b by map.readOnlyProperty() - val c by map.readOnlyProperty() - val d by map.readOnlyProperty() + val a by Delegates.mapVal(map) + val b by Delegates.mapVal(map) + val c by Delegates.mapVal(map) + val d by Delegates.mapVal(map) override fun box(): String { if (a != "a") return "fail at 'a'" @@ -66,10 +66,10 @@ class TestMapValWithDifferentTypes(): WithBox { class TestMapVarWithDifferentTypes(): WithBox { val map: HashMap = hashMapOf("a" to "a", "b" to 1, "c" to A(1), "d" to "d") - var a by map.property() - var b by map.property() - var c by map.property() - var d by map.property() + var a by Delegates.mapVar(map) + var b by Delegates.mapVar(map) + var c by Delegates.mapVar(map) + var d by Delegates.mapVar(map) override fun box(): String { a = "aa" @@ -87,8 +87,8 @@ class TestMapVarWithDifferentTypes(): WithBox { } class TestNullableKey: WithBox { - val map = hashMapOf(null to "null") - var a by map.property { desc -> null } + val map = hashMapOf(null:Any? to "null": Any?) + var a by FixedMapVar(map, key = { desc -> null }, default = {ref, desc -> null}) override fun box(): String { if (a != "null") return "fail at 'a'" @@ -99,10 +99,10 @@ class TestNullableKey: WithBox { } class TestMapPropertyString(): WithBox { - val map = hashMapOf("a" to "a", "b" to "b", "c" to "c") - val a by map.readOnlyProperty() - var b by map.property() - val c by map.property() + val map = hashMapOf("a" to "a", "b" to "b", "c" to "c":Any?) + val a by Delegates.mapVal(map) + var b by Delegates.mapVar(map) + val c by Delegates.mapVal(map) override fun box(): String { b = "newB" @@ -115,9 +115,9 @@ class TestMapPropertyString(): WithBox { class TestMapValWithDefault(): WithBox { val map = hashMapOf() - val a by map.readOnlyProperty(default = { "aDefault" }) - val b by map.readOnlyProperty(default = { "bDefault" }, key = "b") - val c by map.readOnlyProperty(default = { "cDefault" }, key = { desc -> desc.name }) + val a by Delegates.mapVal(map, default = { ref, desc -> "aDefault" }) + val b by FixedMapVal(map, default = { ref, desc -> "bDefault" }, key = {"b"}) + val c by FixedMapVal(map, default = { ref, desc -> "cDefault" }, key = { desc -> desc.name }) override fun box(): String { if (a != "aDefault") return "fail at 'a'" @@ -128,10 +128,10 @@ class TestMapValWithDefault(): WithBox { } class TestMapVarWithDefault(): WithBox { - val map = hashMapOf() - var a by map.property(default = { "aDefault" }) - var b by map.property(default = { "bDefault" }, key = "b") - var c by map.property(default = { "cDefault" }, key = { desc -> desc.name }) + val map = hashMapOf() + var a: String by Delegates.mapVar(map, default = {ref, desc -> "aDefault" }) + var b: String by FixedMapVar(map, default = {ref, desc -> "bDefault" }, key = {"b"}) + var c: String by FixedMapVar(map, default = {ref, desc -> "cDefault" }, key = { desc -> desc.name }) override fun box(): String { if (a != "aDefault") return "fail at 'a'" @@ -148,9 +148,9 @@ class TestMapVarWithDefault(): WithBox { } class TestMapPropertyKey(): WithBox { - val map = hashMapOf("a" to "a", "b" to "b") - val a by map.readOnlyProperty(key = "a") - var b by map.property(key = "b") + val map = hashMapOf("a" to "a", "b" to "b" : Any?) + val a by FixedMapVal(map, key = {"a"}) + var b by FixedMapVar(map, key = {"b"}) override fun box(): String { b = "c" @@ -161,9 +161,9 @@ class TestMapPropertyKey(): WithBox { } class TestMapPropertyFunction(): WithBox { - val map = hashMapOf("aDesc" to "a", "bDesc" to "b") - val a by map.readOnlyProperty { desc -> "${desc.name}Desc" } - var b by map.property { desc -> "${desc.name}Desc" } + val map = hashMapOf("aDesc" to "a", "bDesc" to "b": Any?) + val a by FixedMapVal(map, { desc -> "${desc.name}Desc" }) + var b by FixedMapVar(map, { desc -> "${desc.name}Desc" }) override fun box(): String { b = "c" @@ -173,17 +173,18 @@ class TestMapPropertyFunction(): WithBox { } } -val mapVal = object : MapVal() { - override fun getMap(thisRef: TestMapPropertyCustom) = thisRef.map - override fun getKey(desc: PropertyMetadata) = "${desc.name}Desc" +val mapVal = object: MapVal() { + override fun map(ref: TestMapPropertyCustom) = ref.map + override fun key(desc: PropertyMetadata) = "${desc.name}Desc" } -val mapVar = object : MapVar() { - override fun getMap(thisRef: TestMapPropertyCustom) = thisRef.map - override fun getKey(desc: PropertyMetadata) = "${desc.name}Desc" + +val mapVar = object : MapVar() { + override fun map(ref: TestMapPropertyCustom) = ref.map + override fun key(desc: PropertyMetadata) = "${desc.name}Desc" } class TestMapPropertyCustom(): WithBox { - val map = hashMapOf("aDesc" to "a", "bDesc" to "b") + val map = hashMapOf("aDesc" to "a", "bDesc" to "b":Any?) val a by mapVal var b by mapVar @@ -195,22 +196,22 @@ class TestMapPropertyCustom(): WithBox { } } -val mapValWithDefault = object : MapVal() { - override fun getMap(thisRef: TestMapPropertyCustomWithDefault) = thisRef.map - override fun getKey(desc: PropertyMetadata) = desc.name +val mapValWithDefault = object : MapVal() { + override fun map(ref: TestMapPropertyCustomWithDefault) = ref.map + override fun key(desc: PropertyMetadata) = desc.name - override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = "default" + override fun default(ref: TestMapPropertyCustomWithDefault, key: PropertyMetadata) = "default" } -val mapVarWithDefault = object : MapVar() { - override fun getMap(thisRef: TestMapPropertyCustomWithDefault) = thisRef.map - override fun getKey(desc: PropertyMetadata) = desc.name +val mapVarWithDefault = object : MapVar() { + override fun map(ref: TestMapPropertyCustomWithDefault) = ref.map + override fun key(desc: PropertyMetadata) = desc.name - override fun getDefaultValue(desc: PropertyMetadata, key: Any?) = "default" + override fun default(ref: TestMapPropertyCustomWithDefault, key: PropertyMetadata) = "default" } class TestMapPropertyCustomWithDefault(): WithBox { - val map = hashMapOf() + val map = hashMapOf() val a by mapValWithDefault var b by mapVarWithDefault @@ -221,4 +222,4 @@ class TestMapPropertyCustomWithDefault(): WithBox { if (b != "c") return "fail at 'b' after set" return "OK" } -} \ No newline at end of file +} diff --git a/libraries/stdlib/test/properties/delegation/lazy/LazyValuesTest.kt b/libraries/stdlib/test/properties/delegation/lazy/LazyValuesTest.kt index 6a3a4cac847..31fe609bf2d 100644 --- a/libraries/stdlib/test/properties/delegation/lazy/LazyValuesTest.kt +++ b/libraries/stdlib/test/properties/delegation/lazy/LazyValuesTest.kt @@ -1,8 +1,8 @@ package test.properties.delegation.lazy -import kotlin.properties.delegation.lazy.* import test.properties.delegation.WithBox import test.properties.delegation.DelegationTestBase +import kotlin.properties.* class LazyValuesTest(): DelegationTestBase() { @@ -33,7 +33,7 @@ class LazyValuesTest(): DelegationTestBase() { class TestLazyVal: WithBox { var result = 0 - val a by LazyVal { + val a by Delegates.lazy { ++result } @@ -48,8 +48,8 @@ class TestNullableLazyVal: WithBox { var resultA = 0 var resultB = 0 - val a: Int? by NullableLazyVal { resultA++; null} - val b by NullableLazyVal { foo() } + val a: Int? by Delegates.lazy { resultA++; null} + val b by Delegates.lazy { foo() } override fun box(): String { a @@ -70,7 +70,7 @@ class TestNullableLazyVal: WithBox { class TestAtomicLazyVal: WithBox { var result = 0 - val a by AtomicLazyVal { + val a by Delegates.blockingLazy { ++result } @@ -85,8 +85,8 @@ class TestVolatileNullableLazyVal: WithBox { var resultA = 0 var resultB = 0 - val a: Int? by VolatileNullableLazyVal { resultA++; null} - val b by VolatileNullableLazyVal { foo() } + val a: Int? by Delegates.blockingLazy { resultA++; null} + val b by Delegates.blockingLazy { foo() } override fun box(): String { a @@ -107,7 +107,7 @@ class TestVolatileNullableLazyVal: WithBox { class TestVolatileLazyVal: WithBox { var result = 0 - val a by VolatileLazyVal { + val a by Delegates.blockingLazy { ++result } @@ -122,8 +122,8 @@ class TestAtomicNullableLazyVal: WithBox { var resultA = 0 var resultB = 0 - val a: Int? by AtomicNullableLazyVal { resultA++; null} - val b by AtomicNullableLazyVal { foo() } + val a: Int? by Delegates.blockingLazy { resultA++; null} + val b by Delegates.blockingLazy { foo() } override fun box(): String { a diff --git a/libraries/tools/kotlin-gradle-plugin-core/.gitignore b/libraries/tools/kotlin-gradle-plugin-core/.gitignore new file mode 100644 index 00000000000..b97b22398a9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/.gitignore @@ -0,0 +1 @@ +local-repo diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/.gitignore b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/.gitignore similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/.gitignore rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/.gitignore diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/README.txt b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/README.txt similarity index 96% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/README.txt rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/README.txt index c9045e657f0..df08dc77e0d 100644 --- a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/README.txt +++ b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/README.txt @@ -1,7 +1,7 @@ -Deploying gradle api to maven - - * gradlew build - -> build/libs/gradle-api-1.4.jar - - * mvn deploy - build/libs/gradle-api-1.4.jar -> http://repository.jetbrains.com/utils +Deploying gradle api to maven + + * gradlew build + -> build/libs/gradle-api-1.4.jar + + * mvn deploy + build/libs/gradle-api-1.4.jar -> http://repository.jetbrains.com/utils diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/build.gradle b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build.gradle similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/build.gradle rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build.gradle diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradle/wrapper/gradle-wrapper.jar b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradle/wrapper/gradle-wrapper.jar rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradle/wrapper/gradle-wrapper.jar diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradle/wrapper/gradle-wrapper.properties b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradle/wrapper/gradle-wrapper.properties rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradle/wrapper/gradle-wrapper.properties diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradlew b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradlew similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradlew rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradlew diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradlew.bat b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradlew.bat similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/gradlew.bat rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/gradlew.bat diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/pom.xml b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/pom.xml similarity index 97% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/pom.xml rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/pom.xml index b5e367c2c68..ab208885125 100644 --- a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/pom.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/pom.xml @@ -1,51 +1,51 @@ - - - - 4.0.0 - - 1.4.1 - 3.0.4 - - - org.jetbrains.kotlin - gradle-api - pom - 1.4 - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.7 - - - attach-artifacts - compile - - attach-artifact - - - - - build/libs/gradle-api-1.4.jar - jar - - - - - - - - - - - - utils - http://repository.jetbrains.com/utils - - - - + + + + 4.0.0 + + 1.4.1 + 3.0.4 + + + org.jetbrains.kotlin + gradle-api + pom + 1.4 + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.7 + + + attach-artifacts + compile + + attach-artifact + + + + + build/libs/gradle-api-1.4.jar + jar + + + + + + + + + + + + utils + http://repository.jetbrains.com/utils + + + + diff --git a/libraries/tools/kotlin-gradle-plugin/gradle_api_jar/settings.gradle b/libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/settings.gradle similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/gradle_api_jar/settings.gradle rename to libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/settings.gradle diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/google/common/base/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/google/common/base/annotations.xml new file mode 100644 index 00000000000..69ed1be5713 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/google/common/base/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/google/common/io/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/google/common/io/annotations.xml new file mode 100644 index 00000000000..64ac65dcca1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/com/google/common/io/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/apache/commons/io/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/apache/commons/io/annotations.xml similarity index 97% rename from libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/apache/commons/io/annotations.xml rename to libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/apache/commons/io/annotations.xml index 86f130b880e..0aee42a6e6a 100644 --- a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/apache/commons/io/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/apache/commons/io/annotations.xml @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml new file mode 100644 index 00000000000..dc5cd1bbcbe --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/annotations.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/file/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/file/annotations.xml new file mode 100644 index 00000000000..dea5cec6774 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/file/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/initialization/dsl/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/initialization/dsl/annotations.xml new file mode 100644 index 00000000000..a33a584b9ed --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/initialization/dsl/annotations.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml new file mode 100644 index 00000000000..c14ebed20ae --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/annotations.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/project/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/project/annotations.xml new file mode 100644 index 00000000000..6595499a4a1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/internal/project/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/logging/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/logging/annotations.xml new file mode 100644 index 00000000000..87c8bc5da18 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/logging/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml new file mode 100644 index 00000000000..5859b33807e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/plugins/annotations.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/tasks/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/tasks/annotations.xml new file mode 100644 index 00000000000..67bc433ea20 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/tasks/annotations.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/tasks/compile/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/tasks/compile/annotations.xml new file mode 100644 index 00000000000..812dfa500fa --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/kotlinAnnotation/org/gradle/api/tasks/compile/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/pom.xml b/libraries/tools/kotlin-gradle-plugin-core/pom.xml new file mode 100644 index 00000000000..2c558ae18e8 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/pom.xml @@ -0,0 +1,154 @@ + + + + + 4.0.0 + + 3.0.4 + + + + org.jetbrains.kotlin + kotlin-project + 0.1-SNAPSHOT + ../../pom.xml + + + kotlin-gradle-plugin-core + jar + + + + junit + junit + 4.11 + test + + + commons-lang + commons-lang + 2.3 + + + com.google.guava + guava + 12.0 + + + org.apache.directory.studio + org.apache.commons.io + 2.4 + + + org.jetbrains.kotlin + gradle-api + 1.4 + provided + + + org.jetbrains.kotlin + kotlin-compiler + ${project.version} + + + org.jetbrains.kotlin + kotlin-jdk-annotations + ${project.version} + + + org.jetbrains.kotlin + kdoc + ${project.version} + + + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} + + + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + + + ${kotlin-sdk}/lib + kotlin-jdk-annotations.jar + false + + + ${project.basedir}/src/main/resources + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${project.version} + + + ${basedir}/kotlinAnnotation + + + + + + compile + compile + compile + + + + test-compile + test-compile + test-compile + + + + + + maven-invoker-plugin + 1.8 + + ${project.build.directory}/it + local-repo + verify + + + + create_local + pre-integration-test + + install + + + + + + maven-failsafe-plugin + 2.6 + + + + integration-test + verify + + + + + + + + + + jetbrains-utils + http://repository.jetbrains.com/utils + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSet.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSet.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSet.kt rename to libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KotlinSourceSet.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt rename to libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt rename to libraries/tools/kotlin-gradle-plugin-core/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-core/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt new file mode 100644 index 00000000000..7fc7be8cb97 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -0,0 +1,125 @@ +package org.jetbrains.kotlin.gradle + +import com.google.common.io.Files +import com.intellij.openapi.util.SystemInfo +import java.io.File +import java.util.Arrays +import java.util.Scanner +import org.junit.Before +import org.junit.After +import org.junit.Test +import kotlin.test.assertTrue +import kotlin.test.assertEquals +import kotlin.test.fail + +class BasicKotlinGradleIT { + + var workingDir: File = File(".") + + Before fun setUp() { + workingDir = Files.createTempDir() + workingDir.mkdirs() + copyRecursively(File("src/test/resources/testProject/alfa"), workingDir) + } + + + After fun tearDown() { + deleteRecursively(workingDir) + } + + Test fun testSimpleCompile() { + val projectDir = File(workingDir, "alfa") + + val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("local-repo").getAbsolutePath() + val cmd = if (SystemInfo.isWindows) + listOf("cmd", "/C", "gradlew.bat", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + else + listOf("/bin/bash", "./gradlew", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + + val builder = ProcessBuilder(cmd) + builder.directory(projectDir) + builder.redirectErrorStream(true) + val process = builder.start() + + val s = Scanner(process.getInputStream()!!) + val text = StringBuilder() + while (s.hasNextLine()) { + text append s.nextLine() + text append "\n" + } + s.close() + + val result = process.waitFor() + val buildOutput = text.toString() + + println(buildOutput) + + assertEquals(result, 0) + assertTrue(buildOutput.contains(":compileKotlin"), "Should contain ':compileKotlin'") + assertTrue(buildOutput.contains(":compileTestKotlin"), "Should contain ':compileTestKotlin'") + assertTrue(buildOutput.contains(":compileDeployKotlin"), "Should contain ':compileDeployKotlin'") + assertTrue(File(projectDir, "build/reports/tests/demo.TestSource.html").exists(), "Test report does not exist. Were tests executed?") + + // Run the build second time, assert everything is up-to-date + + val up2dateBuilder = ProcessBuilder(cmd) + up2dateBuilder.directory(projectDir) + up2dateBuilder.redirectErrorStream(true) + val up2dateProcess = up2dateBuilder.start() + + val up2dateProcessScanner = Scanner(up2dateProcess.getInputStream()!!) + val up2dateText = StringBuilder() + while (up2dateProcessScanner.hasNextLine()) { + up2dateText append up2dateProcessScanner.nextLine() + up2dateText append "\n" + } + up2dateProcessScanner.close() + + val up2dateResult = up2dateProcess.waitFor() + val up2dateBuildOutput = up2dateText.toString() + + println(up2dateBuildOutput) + + assertEquals(up2dateResult, 0) + assertTrue(up2dateBuildOutput.contains(":compileKotlin UP-TO-DATE"), "Should contain ':compileKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileTestKotlin UP-TO-DATE"), "Should contain ':compileTestKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileDeployKotlin UP-TO-DATE"), "Should contain ':compileDeployKotlin UP-TO-DATE'") + assertTrue(up2dateBuildOutput.contains(":compileJava UP-TO-DATE"), "Should contain ':compileJava UP-TO-DATE'") + } + + + fun copyRecursively(source: File, target: File) { + assertTrue(target.isDirectory()) + val targetFile = File(target, source.getName()) + if (source.isDirectory()) { + targetFile.mkdir() + val array = source.listFiles() + if (array != null) { + for (child in array) { + copyRecursively(child, targetFile) + } + } + } else { + Files.copy(source, targetFile) + } + } + + + fun deleteRecursively(f: File): Unit { + if (f.isDirectory()) { + val children = f.listFiles() + if (children != null) { + for (child in children) { + deleteRecursively(child) + } + } + val shouldBeEmpty = f.listFiles() + if (shouldBeEmpty != null) { + assertTrue(shouldBeEmpty.isEmpty()) + } else { + fail("Error listing directory content") + } + } + f.delete() + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/build.gradle b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/build.gradle new file mode 100644 index 00000000000..14bf8d494aa --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/build.gradle @@ -0,0 +1,49 @@ +buildscript { + repositories { + mavenCentral() + maven { + url 'file://' + pathToKotlinPlugin + } + } + dependencies { + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin-core:0.1-SNAPSHOT' + } +} + +apply plugin: org.jetbrains.kotlin.gradle.plugin.KotlinPlugin + +sourceSets { + deploy +} + +repositories { + maven { + url 'file://' + pathToKotlinPlugin + } + mavenCentral() +} + +dependencies { + compile 'com.google.guava:guava:12.0' + deployCompile 'com.google.guava:guava:12.0' + testCompile 'org.testng:testng:6.8' + testRuntime 'org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT' +} + +test { + useTestNG() +} + +task show << { + buildscript.configurations.classpath.each { println it } +} + + +compileKotlin { + kotlinOptions.annotations = "externalAnnotations" +} + + +task wrapper(type: Wrapper) { + gradleVersion="1.4" +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/externalAnnotations/com/google/common/base/annotations.xml b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/externalAnnotations/com/google/common/base/annotations.xml new file mode 100644 index 00000000000..be8ddab04a3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/externalAnnotations/com/google/common/base/annotations.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradle/wrapper/gradle-wrapper.jar b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000000..42d9b0e9c58 Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradle/wrapper/gradle-wrapper.jar differ diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradle/wrapper/gradle-wrapper.properties b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..90e63547fc6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Feb 28 14:00:49 MSK 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.4-bin.zip diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradlew b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradlew new file mode 100644 index 00000000000..91a7e269e19 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradlew.bat b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradlew.bat new file mode 100644 index 00000000000..8a0b282aa68 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/deploy/kotlin/kotlinSrc.kt b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/deploy/kotlin/kotlinSrc.kt new file mode 100644 index 00000000000..eec86b34406 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/deploy/kotlin/kotlinSrc.kt @@ -0,0 +1,12 @@ +package demo + +import com.google.common.primitives.Ints +import com.google.common.base.Joiner + +class ExampleSource(param : Int) { + val property = param + fun f() : String? { + return "Hello World" + } +} + diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/java/demo/Greeter.java b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/java/demo/Greeter.java new file mode 100644 index 00000000000..ec2831d8d21 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/java/demo/Greeter.java @@ -0,0 +1,17 @@ +package demo; + +/** + * Created by Nikita.Skvortsov + * Date: 3/1/13, 10:53 AM + */ +public class Greeter { + private final String myGreeting; + + public Greeter(String greeting) { + myGreeting = greeting; + } + + public String getGreeting() { + return myGreeting; + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/java/demo/HelloWorld.java b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/java/demo/HelloWorld.java new file mode 100644 index 00000000000..2bc6463319b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/java/demo/HelloWorld.java @@ -0,0 +1,18 @@ +package demo; + +/** + * Created by Nikita.Skvortsov + * Date: 3/1/13, 10:50 AM + */ +public class HelloWorld { + public static void main(String[] args) { + final KotlinGreetingJoiner example = new KotlinGreetingJoiner(new Greeter("Hi")); + + example.addName("Harry"); + example.addName("Ron"); + example.addName(null); + example.addName("Hermione"); + + System.out.println(example.getJoinedGreeting()); + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/kotlin/helloWorld.kt b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/kotlin/helloWorld.kt new file mode 100644 index 00000000000..b3e99bbdd59 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/main/kotlin/helloWorld.kt @@ -0,0 +1,20 @@ +package demo + +import com.google.common.primitives.Ints +import com.google.common.base.Joiner +import java.util.ArrayList + +class KotlinGreetingJoiner(val greeter : Greeter) { + + val names = ArrayList() + + fun addName(name : String?): Unit{ + names.add(name) + } + + fun getJoinedGreeting() : String? { + val joiner = Joiner.on(" and ").skipNulls(); + return "${greeter.getGreeting()} ${joiner.join(names)}" + } +} + diff --git a/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/test/kotlin/tests.kt b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/test/kotlin/tests.kt new file mode 100644 index 00000000000..e631927f0ff --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-core/src/test/resources/testProject/alfa/src/test/kotlin/tests.kt @@ -0,0 +1,21 @@ +package demo + +import com.google.common.primitives.Ints +import com.google.common.base.Joiner +import org.testng.Assert.* +import org.testng.annotations.AfterMethod +import org.testng.annotations.BeforeMethod +import org.testng.annotations.Test as test + +class TestSource() { + test fun f() { + val example : KotlinGreetingJoiner = KotlinGreetingJoiner(Greeter("Hi")) + example.addName("Harry") + example.addName("Ron") + example.addName(null) + example.addName("Hermione") + + assertEquals(example.getJoinedGreeting(), "Hi Harry and Ron and Hermione") + } +} + diff --git a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/com/google/common/io/annotations.xml b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/com/google/common/io/annotations.xml index b7f0b110ddc..64ac65dcca1 100644 --- a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/com/google/common/io/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/com/google/common/io/annotations.xml @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/artifacts/annotations.xml b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/artifacts/annotations.xml new file mode 100644 index 00000000000..885acfdd4ab --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/artifacts/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/artifacts/dsl/annotations.xml b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/artifacts/dsl/annotations.xml new file mode 100644 index 00000000000..0402ed182e0 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/artifacts/dsl/annotations.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/initialization/dsl/annotations.xml b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/initialization/dsl/annotations.xml index a33a584b9ed..4005fe3c2c3 100644 --- a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/initialization/dsl/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/initialization/dsl/annotations.xml @@ -4,4 +4,9 @@ + + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/logging/annotations.xml b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/logging/annotations.xml index 7ee1ff08665..87c8bc5da18 100644 --- a/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/logging/annotations.xml +++ b/libraries/tools/kotlin-gradle-plugin/kotlinAnnotation/org/gradle/api/logging/annotations.xml @@ -1,5 +1,5 @@ - - - - + + + + \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/pom.xml b/libraries/tools/kotlin-gradle-plugin/pom.xml index f3602e2ce62..717f6ce83d6 100644 --- a/libraries/tools/kotlin-gradle-plugin/pom.xml +++ b/libraries/tools/kotlin-gradle-plugin/pom.xml @@ -21,51 +21,26 @@ - junit - junit - 4.11 - test + org.jetbrains.kotlin + kotlin-stdlib + ${project.version} - commons-lang - commons-lang - 2.3 + org.jetbrains.kotlin + kotlin-jdk-annotations + ${project.version} - com.google.guava - guava - 12.0 + org.jetbrains.kotlin + gradle-api + 1.4 + provided - org.apache.directory.studio - org.apache.commons.io - 2.4 - - - org.jetbrains.kotlin - gradle-api - 1.4 - provided - - - org.jetbrains.kotlin - kotlin-compiler - ${project.version} - - - org.jetbrains.kotlin - kotlin-jdk-annotations - ${project.version} - - - org.jetbrains.kotlin - kdoc - ${project.version} - - - org.jetbrains.kotlin - kotlin-stdlib - ${project.version} + org.jetbrains.kotlin + kotlin-gradle-plugin-core + ${project.version} + provided @@ -75,14 +50,9 @@ ${project.basedir}/src/test/kotlin - - - ${kotlin-sdk}/lib - kotlin-jdk-annotations.jar - false - ${project.basedir}/src/main/resources + true diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt new file mode 100644 index 00000000000..f2891244fc9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -0,0 +1,64 @@ +package org.jetbrains.kotlin.gradle.plugin + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.api.artifacts.ConfigurationContainer +import org.gradle.api.artifacts.Dependency +import org.gradle.api.specs.Spec +import java.io.File +import java.net.URL +import org.gradle.api.logging.Logging +import java.util.Properties +import java.io.FileNotFoundException + +open class KotlinPluginWrapper: Plugin { + + val log = Logging.getLogger(getClass())!! + + public override fun apply(project: Project) { + val dependencyHandler : DependencyHandler = project.getBuildscript().getDependencies() + val configurationsContainer : ConfigurationContainer = project.getBuildscript().getConfigurations() + + log.debug("Loading version information") + val props = Properties() + val propFileName = "project.properties" + val inputStream = getClass().getClassLoader()!!.getResourceAsStream(propFileName) + + if (inputStream == null) { + throw FileNotFoundException("property file '" + propFileName + "' not found in the classpath") + } + + props.load(inputStream); + + val projectVersion = props.get("project.version") + log.debug("Found project version [" + projectVersion + "]") + + log.debug("Creating configuration and dependency") + val kotlinPluginCoreCoordinates = "org.jetbrains.kotlin:kotlin-gradle-plugin-core:" + projectVersion + val dependency = dependencyHandler.create(kotlinPluginCoreCoordinates) + val configuration = configurationsContainer.detachedConfiguration(dependency)!! + + log.debug("Resolving [" + kotlinPluginCoreCoordinates + "]") + val kotlinPluginDependencies : List = configuration.getResolvedConfiguration().getFiles(KSpec({ dep -> true }))!!.map({(f: File):URL -> f.toURI().toURL() }) + log.debug("Resolved files: [" + kotlinPluginDependencies.toString() + "]") + log.debug("Load plugin in parent-last URL classloader") + val kotlinPluginClassloader = ParentLastURLClassLoader(kotlinPluginDependencies, getClass().getClassLoader()) + log.debug("Class loader created") + val cls = Class.forName("org.jetbrains.kotlin.gradle.plugin.KotlinPlugin", true, kotlinPluginClassloader) + log.debug("Plugin class loaded") + val pluginInstance = cls.newInstance() + log.debug("Plugin class instantiated") + + val applyMethod = cls.getMethod("apply", javaClass()) + log.debug("'apply' method found, invoking...") + applyMethod.invoke(pluginInstance, project); + log.debug("'apply' method invoked successfully") + } +} + +open class KSpec(val predicate: (T) -> Boolean): Spec { + public override fun isSatisfiedBy(p0: T?): Boolean { + return p0 != null && predicate(p0) + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/ParentLastURLClassLoader.java b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/ParentLastURLClassLoader.java new file mode 100644 index 00000000000..dec931c3baa --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/ParentLastURLClassLoader.java @@ -0,0 +1,74 @@ +package org.jetbrains.kotlin.gradle.plugin; + + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.List; + +/** + * A parent-last classloader that will try the child classloader first and then the parent. + * This takes a fair bit of doing because java really prefers parent-first. + *

+ * For those not familiar with class loading trickery, be wary + */ +public class ParentLastURLClassLoader extends ClassLoader { + private ChildURLClassLoader childClassLoader; + + public ParentLastURLClassLoader(List classpath, ClassLoader parent) { + super(Thread.currentThread().getContextClassLoader()); + + URL[] urls = classpath.toArray(new URL[classpath.size()]); + + childClassLoader = new ChildURLClassLoader(urls, new FindClassClassLoader(parent)); + } + + @Override + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + try { + // first we try to find a class inside the child classloader + return childClassLoader.findClass(name); + } catch (ClassNotFoundException e) { + // didn't find it, try the parent + return super.loadClass(name, resolve); + } + } + + /** + * This class allows me to call findClass on a classloader + */ + private static class FindClassClassLoader extends ClassLoader { + public FindClassClassLoader(ClassLoader parent) { + super(parent); + } + + @Override + public Class findClass(String name) throws ClassNotFoundException { + return super.findClass(name); + } + } + + /** + * This class delegates (child then parent) for the findClass method for a URLClassLoader. + * We need this because findClass is protected in URLClassLoader + */ + private static class ChildURLClassLoader extends URLClassLoader { + private FindClassClassLoader realParent; + + public ChildURLClassLoader(URL[] urls, FindClassClassLoader realParent) { + super(urls, null); + + this.realParent = realParent; + } + + @Override + public Class findClass(String name) throws ClassNotFoundException { + try { + // first try to use the URLClassLoader findClass + return super.findClass(name); + } catch (ClassNotFoundException e) { + // if that fails, we ask our real parent classloader to load the class (we give up) + return realParent.loadClass(name); + } + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin.properties b/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin.properties index 4f8cd030af6..3a22596804f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin.properties +++ b/libraries/tools/kotlin-gradle-plugin/src/main/resources/META-INF/gradle-plugins/kotlin.properties @@ -1 +1 @@ -implementation-class=org.jetbrains.kotlin.gradle.plugin.KotlinPlugin \ No newline at end of file +implementation-class=org.jetbrains.kotlin.gradle.plugin.KotlinPluginWrapper \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/resources/project.properties b/libraries/tools/kotlin-gradle-plugin/src/main/resources/project.properties new file mode 100644 index 00000000000..e362614406a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/resources/project.properties @@ -0,0 +1 @@ +project.version=${project.version} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt index 7fc7be8cb97..68f085a6eae 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginIT.kt @@ -30,11 +30,12 @@ class BasicKotlinGradleIT { Test fun testSimpleCompile() { val projectDir = File(workingDir, "alfa") - val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("local-repo").getAbsolutePath() + val pathToKotlinPluginWrapper = "-PpathToKotlinPluginWrapper=" + File("local-repo").getAbsolutePath() + val pathToKotlinPlugin = "-PpathToKotlinPlugin=" + File("../kotlin-gradle-plugin-core/local-repo").getAbsolutePath() val cmd = if (SystemInfo.isWindows) - listOf("cmd", "/C", "gradlew.bat", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + listOf("cmd", "/C", "gradlew.bat", "compileDeployKotlin", "build", pathToKotlinPluginWrapper, pathToKotlinPlugin, "--no-daemon", "--debug") else - listOf("/bin/bash", "./gradlew", "compileDeployKotlin", "build", pathToKotlinPlugin, "--no-daemon", "--debug") + listOf("/bin/bash", "./gradlew", "compileDeployKotlin", "build", pathToKotlinPluginWrapper, pathToKotlinPlugin, "--no-daemon", "--debug") val builder = ProcessBuilder(cmd) builder.directory(projectDir) diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle index dbee1e21015..451ac3de6c0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin/src/test/resources/testProject/alfa/build.gradle @@ -4,6 +4,9 @@ buildscript { maven { url 'file://' + pathToKotlinPlugin } + maven { + url 'file://' + pathToKotlinPluginWrapper + } } dependencies { classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.1-SNAPSHOT' diff --git a/update_dependencies.xml b/update_dependencies.xml index 7ec9ad1fb71..234d504126e 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -126,17 +126,9 @@ - - - - - - - - - - - + + +