diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 7114358b97f..81b6ef06602 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -85,7 +85,7 @@ public interface Errors { DiagnosticFactory0 REDUNDANT_NULLABLE = DiagnosticFactory0.create(WARNING, NULLABLE_TYPE); DiagnosticFactory1 BASE_WITH_NULLABLE_UPPER_BOUND = DiagnosticFactory1.create(WARNING, NULLABLE_TYPE); DiagnosticFactory1 WRONG_NUMBER_OF_TYPE_ARGUMENTS = DiagnosticFactory1.create(ERROR); - DiagnosticFactory2 NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION = DiagnosticFactory2.create(ERROR); + DiagnosticFactory2 NO_TYPE_ARGUMENTS_ON_RHS = DiagnosticFactory2.create(ERROR); DiagnosticFactory1 CONFLICTING_PROJECTION = DiagnosticFactory1.create(ERROR, VARIANCE_IN_PROJECTION); DiagnosticFactory1 REDUNDANT_PROJECTION = DiagnosticFactory1.create(WARNING, VARIANCE_IN_PROJECTION); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index 4f49d7c5414..d7f248d3b49 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -434,7 +434,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: found: {1} required: {0}", RENDER_TYPE, RENDER_TYPE); MAP.put(WRONG_NUMBER_OF_TYPE_ARGUMENTS, "{0,choice,0#No type arguments|1#Type argument|1<{0,number,integer} type arguments} expected", null); - MAP.put(NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION, "{0,choice,0#No type arguments|1#Type argument|1<{0,number,integer} type arguments} expected. " + + MAP.put(NO_TYPE_ARGUMENTS_ON_RHS, "{0,choice,0#No type arguments|1#Type argument|1<{0,number,integer} type arguments} expected. " + "Use ''{1}'' if you don''t want to pass type arguments", null, TO_STRING); MAP.put(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/PossiblyBareType.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/PossiblyBareType.java index 2b6d7b9bea1..655c67f57d7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/PossiblyBareType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/PossiblyBareType.java @@ -79,17 +79,19 @@ public class PossiblyBareType { } @NotNull - public JetType reconstruct(@NotNull JetType subjectType) { - if (!isBare()) return getActualType(); + public TypeReconstructionResult reconstruct(@NotNull JetType subjectType) { + if (!isBare()) return new TypeReconstructionResult(getActualType(), true); - JetType type = CastDiagnosticsUtil.findStaticallyKnownSubtype( + TypeReconstructionResult reconstructionResult = CastDiagnosticsUtil.findStaticallyKnownSubtype( TypeUtils.makeNotNullable(subjectType), getBareTypeConstructor() ); + JetType type = reconstructionResult.getResultingType(); // No need to make an absent type nullable - if (type == null) return type; + if (type == null) return reconstructionResult; - return TypeUtils.makeNullableAsSpecified(type, isBareTypeNullable()); + JetType resultingType = TypeUtils.makeNullableAsSpecified(type, isBareTypeNullable()); + return new TypeReconstructionResult(resultingType, reconstructionResult.isAllArgumentsInferred()); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java index 889a6b96717..0d33e5d1a5f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java @@ -112,7 +112,7 @@ public class CastDiagnosticsUtil { // NOTE: this does not account for 'as Array>' if (allParametersReified(subtype)) return false; - JetType staticallyKnownSubtype = findStaticallyKnownSubtype(supertype, subtype.getConstructor()); + JetType staticallyKnownSubtype = findStaticallyKnownSubtype(supertype, subtype.getConstructor()).getResultingType(); // If the substitution failed, it means that the result is an impossible type, e.g. something like Out // In this case, we can't guarantee anything, so the cast is considered to be erased @@ -132,14 +132,14 @@ public class CastDiagnosticsUtil { * Example 1: * supertype = Collection * subtype = List<...> - * result = List + * result = List, all arguments are inferred * * Example 2: * supertype = Any * subtype = List<...> - * result = List<*> + * result = List<*>, some arguments were not inferred, replaced with '*' */ - public static JetType findStaticallyKnownSubtype(@NotNull JetType supertype, @NotNull TypeConstructor subtypeConstructor) { + public static TypeReconstructionResult findStaticallyKnownSubtype(@NotNull JetType supertype, @NotNull TypeConstructor subtypeConstructor) { assert !supertype.isNullable() : "This method only makes sense for non-nullable types"; // Assume we are casting an expression of type Collection to List @@ -176,6 +176,7 @@ public class CastDiagnosticsUtil { // If some of the parameters are not determined by unification, it means that these parameters are lost, // let's put stars instead, so that we can only cast to something like List<*>, e.g. (a: Any) as List<*> + boolean allArgumentsInferred = true; for (TypeParameterDescriptor variable : variables) { TypeProjection value = substitution.get(variable.getTypeConstructor()); if (value == null) { @@ -183,12 +184,15 @@ public class CastDiagnosticsUtil { variable.getTypeConstructor(), SubstitutionUtils.makeStarProjection(variable) ); + allArgumentsInferred = false; } } // At this point we have values for all type parameters of List // Let's make a type by substituting them: List -> List - return TypeSubstitutor.create(substitution).substitute(subtypeWithVariables, Variance.INVARIANT); + JetType substituted = TypeSubstitutor.create(substitution).substitute(subtypeWithVariables, Variance.INVARIANT); + + return new TypeReconstructionResult(substituted, allArgumentsInferred); } private static boolean allParametersReified(JetType subtype) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeReconstructionResult.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeReconstructionResult.java new file mode 100644 index 00000000000..e448835e1c9 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeReconstructionResult.java @@ -0,0 +1,38 @@ +/* + * 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.lang.types; + +import org.jetbrains.annotations.Nullable; + +public class TypeReconstructionResult { + private final JetType resultingType; + private final boolean allArgumentsInferred; + + public TypeReconstructionResult(@Nullable JetType resultingType, boolean allArgumentsInferred) { + this.resultingType = resultingType; + this.allArgumentsInferred = allArgumentsInferred; + } + + @Nullable + public JetType getResultingType() { + return resultingType; + } + + public boolean isAllArgumentsInferred() { + return allArgumentsInferred; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index f7692084d69..a1ff2368054 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -62,7 +62,9 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.utils.ThrowingList; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; import static org.jetbrains.jet.lang.diagnostics.Errors.*; @@ -77,12 +79,14 @@ import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType; import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.createCallForSpecialConstruction; import static org.jetbrains.jet.lang.types.expressions.ControlStructureTypingUtils.resolveSpecialConstructionAsCall; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*; -import static org.jetbrains.jet.lexer.JetTokens.*; +import static org.jetbrains.jet.lang.types.expressions.TypeReconstructionUtil.reconstructBareType; +import static org.jetbrains.jet.lexer.JetTokens.AS_KEYWORD; +import static org.jetbrains.jet.lexer.JetTokens.AS_SAFE; @SuppressWarnings("SuspiciousMethodCalls") public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { - private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE, IS_KEYWORD, NOT_IS); + private static final TokenSet BARE_TYPES_ALLOWED = TokenSet.create(AS_KEYWORD, AS_SAFE); private final PlatformToKotlinClassMap platformToKotlinClassMap; @@ -192,10 +196,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { DataFlowInfo dataFlowInfo = context.dataFlowInfo; JetType subjectType = typeInfo.getType(); - JetType targetType; - if (subjectType != null) { - targetType = possiblyBareTarget.reconstruct(subjectType); + JetType targetType = reconstructBareType(right, possiblyBareTarget, subjectType, context.trace); + if (subjectType != null) { checkBinaryWithTypeRHS(expression, contextWithNoExpectedType, targetType, subjectType); dataFlowInfo = typeInfo.getDataFlowInfo(); if (operationType == AS_KEYWORD) { @@ -204,10 +207,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType); } } - else { - // Recovery: let's reconstruct as if we were casting from Any, to get some type there - targetType = possiblyBareTarget.reconstruct(KotlinBuiltIns.getInstance().getAnyType()); - } + JetType result = operationType == AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType; return DataFlowUtils.checkType(result, expression, context, dataFlowInfo); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java index fa6c1d01e53..f5ce19361d2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java @@ -283,10 +283,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { } TypeResolutionContext typeResolutionContext = new TypeResolutionContext(context.scope, context.trace, true, /*allowBareTypes=*/ true); PossiblyBareType possiblyBareTarget = context.expressionTypingServices.getTypeResolver().resolvePossiblyBareType(typeResolutionContext, typeReferenceAfterIs); - JetType type = possiblyBareTarget.reconstruct(subjectType); - if (possiblyBareTarget.isBare()) { - context.trace.record(BindingContext.TYPE, typeReferenceAfterIs, type); - } + JetType type = TypeReconstructionUtil.reconstructBareType(typeReferenceAfterIs, possiblyBareTarget, subjectType, context.trace); if (!subjectType.isNullable() && type.isNullable()) { JetTypeElement element = typeReferenceAfterIs.getTypeElement(); assert element instanceof JetNullableType : "element must be instance of " + JetNullableType.class.getName(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/TypeReconstructionUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/TypeReconstructionUtil.java new file mode 100644 index 00000000000..5f4467b7501 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/TypeReconstructionUtil.java @@ -0,0 +1,72 @@ +/* + * 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.lang.types.expressions; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.psi.JetTypeReference; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.PossiblyBareType; +import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; + +import static org.jetbrains.jet.lang.diagnostics.Errors.NO_TYPE_ARGUMENTS_ON_RHS; + +public class TypeReconstructionUtil { + @NotNull + public static JetType reconstructBareType( + @NotNull JetTypeReference right, + @NotNull PossiblyBareType possiblyBareTarget, + @Nullable JetType subjectType, + @NotNull BindingTrace trace + ) { + if (subjectType == null) { + // Recovery: let's reconstruct as if we were casting from Any, to get some type there + subjectType = KotlinBuiltIns.getInstance().getAnyType(); + } + TypeReconstructionResult reconstructionResult = possiblyBareTarget.reconstruct(subjectType); + if (!reconstructionResult.isAllArgumentsInferred()) { + TypeConstructor typeConstructor = possiblyBareTarget.getBareTypeConstructor(); + trace.report(NO_TYPE_ARGUMENTS_ON_RHS.on(right, + typeConstructor.getParameters().size(), + allStarProjectionsString(typeConstructor))); + } + + JetType targetType = reconstructionResult.getResultingType(); + if (targetType != null) { + if (possiblyBareTarget.isBare()) { + trace.record(BindingContext.TYPE, right, targetType); + } + return targetType; + } + + return ErrorUtils.createErrorType("Failed to reconstruct type: " + right.getText()); + } + + @NotNull + private static String allStarProjectionsString(@NotNull TypeConstructor constructor) { + int size = constructor.getParameters().size(); + assert size != 0 : "No projections possible for a nilary type constructor" + constructor; + ClassifierDescriptor declarationDescriptor = constructor.getDeclarationDescriptor(); + assert declarationDescriptor != null : "No declaration descriptor for type constructor " + constructor; + String name = declarationDescriptor.getName().asString(); + + return TypeUtils.getTypeNameAndStarProjectionsString(name, size); + } +} diff --git a/compiler/testData/diagnostics/tests/cast/bare/AsNullableNotEnough.kt b/compiler/testData/diagnostics/tests/cast/bare/AsNullableNotEnough.kt new file mode 100644 index 00000000000..b64e30082ff --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/bare/AsNullableNotEnough.kt @@ -0,0 +1,8 @@ +trait Tr +trait G + +fun test(tr: Tr) { + val v = tr as G? + // If v is not nullable, there will be a warning on this line: + v!!: G<*> +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/bare/FromErrorType.kt b/compiler/testData/diagnostics/tests/cast/bare/FromErrorType.kt new file mode 100644 index 00000000000..31fb179653e --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/bare/FromErrorType.kt @@ -0,0 +1,6 @@ +class G + +fun foo(p: P) { + val v = p as G? + v!!: G<*> +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/bare/NullableAsNotEnough.kt b/compiler/testData/diagnostics/tests/cast/bare/NullableAsNotEnough.kt new file mode 100644 index 00000000000..a9ef3a458bf --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/bare/NullableAsNotEnough.kt @@ -0,0 +1,7 @@ +trait Tr +trait G + +fun test(tr: Tr?) { + val v = tr as G + v: G<*> +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/bare/NullableAsNullable.kt b/compiler/testData/diagnostics/tests/cast/bare/NullableAsNullable.kt new file mode 100644 index 00000000000..e48f070ccb5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/bare/NullableAsNullable.kt @@ -0,0 +1,8 @@ +trait Tr +trait G : Tr + +fun test(tr: Tr?) { + val v = tr as G? + // If v is not nullable, there will be a warning on this line: + v!!: G +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/bare/NullableAsNullableNotEnough.kt b/compiler/testData/diagnostics/tests/cast/bare/NullableAsNullableNotEnough.kt new file mode 100644 index 00000000000..a27bcbbef21 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cast/bare/NullableAsNullableNotEnough.kt @@ -0,0 +1,7 @@ +trait Tr +trait G + +fun test(tr: Tr?) { + val v = tr as G? + v!!: G<*> +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/bare/UnrelatedAs.kt b/compiler/testData/diagnostics/tests/cast/bare/UnrelatedAs.kt index f3731d6a5b0..159aaca6d21 100644 --- a/compiler/testData/diagnostics/tests/cast/bare/UnrelatedAs.kt +++ b/compiler/testData/diagnostics/tests/cast/bare/UnrelatedAs.kt @@ -2,6 +2,6 @@ trait Tr trait G fun test(tr: Tr) { - val v = tr as G + val v = tr as G v: G<*> -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/cast/bare/UnrelatedIs.kt b/compiler/testData/diagnostics/tests/cast/bare/UnrelatedIs.kt index 20ceb0b1998..bf51d82c30c 100644 --- a/compiler/testData/diagnostics/tests/cast/bare/UnrelatedIs.kt +++ b/compiler/testData/diagnostics/tests/cast/bare/UnrelatedIs.kt @@ -1,4 +1,4 @@ trait Tr trait G -fun test(tr: Tr) = tr is G +fun test(tr: Tr) = tr is G \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt b/compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt index a404383ccb2..8c68d4a62f6 100644 --- a/compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt +++ b/compiler/testData/diagnostics/tests/generics/RawTypeInIsExpression.kt @@ -2,15 +2,13 @@ package p public fun foo(a: Any) { a is Map - a is Map + a is Map a is Map a is Map<*, *> a is Map<> a is List<Map> - a is List + a is List a is Int - (a as Map) is Int -} - - + (a as Map) is Int +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/generics/RawTypeInIsPattern.kt b/compiler/testData/diagnostics/tests/generics/RawTypeInIsPattern.kt index b1f7a4564c0..6decc0f4180 100644 --- a/compiler/testData/diagnostics/tests/generics/RawTypeInIsPattern.kt +++ b/compiler/testData/diagnostics/tests/generics/RawTypeInIsPattern.kt @@ -1,12 +1,12 @@ public fun foo(a: Any, b: Map) { when (a) { is Map -> {} - is Map -> {} + is Map -> {} is Map -> {} is Map<*, *> -> {} is Map<> -> {} is List<Map> -> {} - is List -> {} + is List -> {} is Int -> {} else -> {} } diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 12e9726a0a2..8acbcaa80ac 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -1201,6 +1201,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/cast/bare/AsNullable.kt"); } + @TestMetadata("AsNullableNotEnough.kt") + public void testAsNullableNotEnough() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/bare/AsNullableNotEnough.kt"); + } + @TestMetadata("EitherAs.kt") public void testEitherAs() throws Exception { doTest("compiler/testData/diagnostics/tests/cast/bare/EitherAs.kt"); @@ -1231,11 +1236,31 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/cast/bare/ErrorsInSubstitution.kt"); } + @TestMetadata("FromErrorType.kt") + public void testFromErrorType() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/bare/FromErrorType.kt"); + } + @TestMetadata("NullableAs.kt") public void testNullableAs() throws Exception { doTest("compiler/testData/diagnostics/tests/cast/bare/NullableAs.kt"); } + @TestMetadata("NullableAsNotEnough.kt") + public void testNullableAsNotEnough() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/bare/NullableAsNotEnough.kt"); + } + + @TestMetadata("NullableAsNullable.kt") + public void testNullableAsNullable() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/bare/NullableAsNullable.kt"); + } + + @TestMetadata("NullableAsNullableNotEnough.kt") + public void testNullableAsNullableNotEnough() throws Exception { + doTest("compiler/testData/diagnostics/tests/cast/bare/NullableAsNullableNotEnough.kt"); + } + @TestMetadata("RedundantNullable.kt") public void testRedundantNullable() throws Exception { doTest("compiler/testData/diagnostics/tests/cast/bare/RedundantNullable.kt"); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddStarProjectionsFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddStarProjectionsFix.java index ecce5c271ba..961840f5199 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddStarProjectionsFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddStarProjectionsFix.java @@ -72,14 +72,17 @@ public abstract class AddStarProjectionsFix extends JetIntentionAction diagnosticWithParameters = - (DiagnosticWithParameters2) diagnostic; - JetUserType userType = QuickFixUtil.getParentElementOfType(diagnostic, JetUserType.class); - if (userType == null) return null; + DiagnosticWithParameters2 diagnosticWithParameters = + (DiagnosticWithParameters2) diagnostic; + JetTypeElement typeElement = diagnosticWithParameters.getPsiElement().getTypeElement(); + while (typeElement instanceof JetNullableType) { + typeElement = ((JetNullableType) typeElement).getInnerType(); + } + if (!(typeElement instanceof JetUserType)) return null; Integer size = diagnosticWithParameters.getA(); - return new AddStarProjectionsFix(userType, size) {}; + return new AddStarProjectionsFix((JetUserType) typeElement, size) {}; } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index e188881ed5b..21b034f15a4 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -182,7 +182,7 @@ public class QuickFixes { factories.put(ELSE_MISPLACED_IN_WHEN, MoveWhenElseBranchFix.createFactory()); factories.put(NO_ELSE_IN_WHEN, AddWhenElseBranchFix.createFactory()); - factories.put(NO_TYPE_ARGUMENTS_ON_RHS_OF_IS_EXPRESSION, AddStarProjectionsFix.createFactoryForIsExpression()); + factories.put(NO_TYPE_ARGUMENTS_ON_RHS, AddStarProjectionsFix.createFactoryForIsExpression()); factories.put(WRONG_NUMBER_OF_TYPE_ARGUMENTS, AddStarProjectionsFix.createFactoryForJavaClass()); factories.put(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER, RemovePsiElementSimpleFix.createRemoveTypeArgumentsFactory());