val / var are now forbidden on a loop multi declaration parameter #KT-6274 Fixed
VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER error added KtValVarKeywordOwner interface added for PSIs that have getValOrVarKeyword method
This commit is contained in:
committed by
Mikhail Glukhikh
parent
54cb575819
commit
141ffa27dc
@@ -667,6 +667,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory3<KtExpression, DeclarationDescriptor, Visibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
|
DiagnosticFactory3<KtExpression, DeclarationDescriptor, Visibility, DeclarationDescriptor> INVISIBLE_SETTER = DiagnosticFactory3.create(ERROR);
|
||||||
|
|
||||||
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_LOOP_PARAMETER = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_LOOP_PARAMETER = DiagnosticFactory1.create(ERROR);
|
||||||
|
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_FUN_PARAMETER = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_FUN_PARAMETER = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_CATCH_PARAMETER = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_CATCH_PARAMETER = DiagnosticFactory1.create(ERROR);
|
||||||
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<PsiElement, KtKeywordToken> VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER = DiagnosticFactory1.create(ERROR);
|
||||||
|
|||||||
+1
@@ -264,6 +264,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(VARIABLE_EXPECTED, "Variable expected");
|
MAP.put(VARIABLE_EXPECTED, "Variable expected");
|
||||||
|
|
||||||
MAP.put(VAL_OR_VAR_ON_LOOP_PARAMETER, "''{0}'' on loop parameter is not allowed", TO_STRING);
|
MAP.put(VAL_OR_VAR_ON_LOOP_PARAMETER, "''{0}'' on loop parameter is not allowed", TO_STRING);
|
||||||
|
MAP.put(VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER, "''{0}'' on loop multi parameter is not allowed", TO_STRING);
|
||||||
MAP.put(VAL_OR_VAR_ON_FUN_PARAMETER, "''{0}'' on function parameter is not allowed", TO_STRING);
|
MAP.put(VAL_OR_VAR_ON_FUN_PARAMETER, "''{0}'' on function parameter is not allowed", TO_STRING);
|
||||||
MAP.put(VAL_OR_VAR_ON_CATCH_PARAMETER, "''{0}'' on catch parameter is not allowed", TO_STRING);
|
MAP.put(VAL_OR_VAR_ON_CATCH_PARAMETER, "''{0}'' on catch parameter is not allowed", TO_STRING);
|
||||||
MAP.put(VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER, "''{0}'' on secondary constructor parameter is not allowed", TO_STRING);
|
MAP.put(VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER, "''{0}'' on secondary constructor parameter is not allowed", TO_STRING);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.jetbrains.kotlin.lexer.KtTokens.*;
|
import static org.jetbrains.kotlin.lexer.KtTokens.*;
|
||||||
|
|
||||||
public class KtMultiDeclaration extends KtDeclarationImpl {
|
public class KtMultiDeclaration extends KtDeclarationImpl implements KtValVarKeywordOwner {
|
||||||
public KtMultiDeclaration(@NotNull ASTNode node) {
|
public KtMultiDeclaration(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersKt;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class KtParameter extends KtNamedDeclarationStub<KotlinParameterStub> implements KtCallableDeclaration {
|
public class KtParameter extends KtNamedDeclarationStub<KotlinParameterStub> implements KtCallableDeclaration, KtValVarKeywordOwner {
|
||||||
|
|
||||||
public KtParameter(@NotNull ASTNode node) {
|
public KtParameter(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 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.kotlin.psi;
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public interface KtValVarKeywordOwner extends PsiElement {
|
||||||
|
@Nullable
|
||||||
|
PsiElement getValOrVarKeyword();
|
||||||
|
}
|
||||||
@@ -16,12 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi;
|
package org.jetbrains.kotlin.psi;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
public interface KtVariableDeclaration extends KtCallableDeclaration, KtWithExpressionInitializer, KtValVarKeywordOwner {
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public interface KtVariableDeclaration extends KtCallableDeclaration, KtWithExpressionInitializer {
|
|
||||||
boolean isVar();
|
boolean isVar();
|
||||||
|
|
||||||
@Nullable
|
|
||||||
PsiElement getValOrVarKeyword();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public class ModifiersChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void checkParameterHasNoValOrVar(
|
public void checkParameterHasNoValOrVar(
|
||||||
@NotNull KtParameter parameter,
|
@NotNull KtValVarKeywordOwner parameter,
|
||||||
@NotNull DiagnosticFactory1<PsiElement, KtKeywordToken> diagnosticFactory
|
@NotNull DiagnosticFactory1<PsiElement, KtKeywordToken> diagnosticFactory
|
||||||
) {
|
) {
|
||||||
PsiElement valOrVar = parameter.getValOrVarKeyword();
|
PsiElement valOrVar = parameter.getValOrVarKeyword();
|
||||||
|
|||||||
+1
@@ -407,6 +407,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context
|
loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context
|
||||||
);
|
);
|
||||||
components.modifiersChecker.withTrace(context.trace).checkModifiersForMultiDeclaration(multiParameter);
|
components.modifiersChecker.withTrace(context.trace).checkModifiersForMultiDeclaration(multiParameter);
|
||||||
|
components.modifiersChecker.withTrace(context.trace).checkParameterHasNoValOrVar(multiParameter, VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER);
|
||||||
components.identifierChecker.checkDeclaration(multiParameter, context.trace);
|
components.identifierChecker.checkDeclaration(multiParameter, context.trace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
class Pair {
|
||||||
|
operator fun component1(): Int = null!!
|
||||||
|
operator fun component2(): Int = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
class Coll {
|
||||||
|
operator fun iterator(): It = It()
|
||||||
|
}
|
||||||
|
|
||||||
|
class It {
|
||||||
|
operator fun next() = Pair()
|
||||||
|
operator fun hasNext() = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun f() {
|
fun f() {
|
||||||
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>val<!> i in 1..4) {
|
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>val<!> i in 1..4) {
|
||||||
|
|
||||||
@@ -6,4 +21,12 @@ fun f() {
|
|||||||
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>var<!> i in 1..4) {
|
for (<!VAL_OR_VAR_ON_LOOP_PARAMETER!>var<!> i in 1..4) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (<!VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER!>val<!> (i,j) in Coll()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (<!VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER!>var<!> (i,j) in Coll()) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
@@ -1,3 +1,29 @@
|
|||||||
package
|
package
|
||||||
|
|
||||||
public fun f(): kotlin.Unit
|
public fun f(): kotlin.Unit
|
||||||
|
|
||||||
|
public final class Coll {
|
||||||
|
public constructor Coll()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final operator fun iterator(): It
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class It {
|
||||||
|
public constructor It()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final operator fun hasNext(): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public final operator fun next(): Pair
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Pair {
|
||||||
|
public constructor Pair()
|
||||||
|
public final operator fun component1(): kotlin.Int
|
||||||
|
public final operator fun component2(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ class A {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun foo(list: List<A>) {
|
fun foo(list: List<A>) {
|
||||||
for (var (c1, c2, c3) in list) {
|
for (<!VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER!>var<!> (c1, c2, c3) in list) {
|
||||||
<!UNUSED_VALUE!>c1 =<!> 1
|
<!UNUSED_VALUE!>c1 =<!> 1
|
||||||
c3 + 1
|
c3 + 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ public class QuickFixRegistrar : QuickFixContributor {
|
|||||||
val removeValVarFromParameterFixFactory = RemoveValVarFromParameterFix.createFactory()
|
val removeValVarFromParameterFixFactory = RemoveValVarFromParameterFix.createFactory()
|
||||||
VAL_OR_VAR_ON_FUN_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
VAL_OR_VAR_ON_FUN_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
||||||
VAL_OR_VAR_ON_LOOP_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
VAL_OR_VAR_ON_LOOP_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
||||||
|
VAL_OR_VAR_ON_LOOP_MULTI_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
||||||
VAL_OR_VAR_ON_CATCH_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
VAL_OR_VAR_ON_CATCH_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
||||||
VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER.registerFactory(removeValVarFromParameterFixFactory)
|
||||||
|
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle;
|
import org.jetbrains.kotlin.idea.KotlinBundle;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.psi.KtParameter;
|
import org.jetbrains.kotlin.psi.KtValVarKeywordOwner;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||||
|
|
||||||
public class RemoveValVarFromParameterFix extends KotlinQuickFixAction<KtParameter> {
|
public class RemoveValVarFromParameterFix extends KotlinQuickFixAction<KtValVarKeywordOwner> {
|
||||||
private final String varOrVal;
|
private final String varOrVal;
|
||||||
|
|
||||||
public RemoveValVarFromParameterFix(@NotNull KtParameter element) {
|
public RemoveValVarFromParameterFix(@NotNull KtValVarKeywordOwner element) {
|
||||||
super(element);
|
super(element);
|
||||||
PsiElement valOrVarNode = element.getValOrVarKeyword();
|
PsiElement valOrVarNode = element.getValOrVarKeyword();
|
||||||
assert valOrVarNode != null : "Val or var node not found for " + PsiUtilsKt.getElementTextWithContext(element);
|
assert valOrVarNode != null : "Val or var node not found for " + PsiUtilsKt.getElementTextWithContext(element);
|
||||||
@@ -64,7 +64,7 @@ public class RemoveValVarFromParameterFix extends KotlinQuickFixAction<KtParamet
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public IntentionAction createAction(@NotNull Diagnostic diagnostic) {
|
public IntentionAction createAction(@NotNull Diagnostic diagnostic) {
|
||||||
return new RemoveValVarFromParameterFix((KtParameter) diagnostic.getPsiElement().getParent());
|
return new RemoveValVarFromParameterFix((KtValVarKeywordOwner) diagnostic.getPsiElement().getParent());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtParameter
|
|
||||||
import org.jetbrains.kotlin.psi.KtVariableDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.KtClass
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
@@ -59,7 +56,7 @@ public class AutomaticVariableRenamer(
|
|||||||
usageElement,
|
usageElement,
|
||||||
javaClass<KtVariableDeclaration>(),
|
javaClass<KtVariableDeclaration>(),
|
||||||
javaClass<KtParameter>()
|
javaClass<KtParameter>()
|
||||||
) ?: continue
|
) as KtCallableDeclaration? ?: continue
|
||||||
|
|
||||||
if (parameterOrVariable.getTypeReference()?.isAncestor(usageElement) != true) continue
|
if (parameterOrVariable.getTypeReference()?.isAncestor(usageElement) != true) continue
|
||||||
|
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// "Remove 'val' from parameter" "true"
|
||||||
|
class Pair<A, B>
|
||||||
|
{
|
||||||
|
operator fun component1(): A = null!!
|
||||||
|
operator fun component2(): B = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f(list: List<Pair<String, String>>) {
|
||||||
|
for (val<caret> (x,y) in list) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
// "Remove 'val' from parameter" "true"
|
||||||
|
class Pair<A, B>
|
||||||
|
{
|
||||||
|
operator fun component1(): A = null!!
|
||||||
|
operator fun component2(): B = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun f(list: List<Pair<String, String>>) {
|
||||||
|
for ((x,y) in list) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6851,6 +6851,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("loopMultiParameter.kt")
|
||||||
|
public void testLoopMultiParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/variables/removeValVarFromParameter/loopMultiParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("loopParameter.kt")
|
@TestMetadata("loopParameter.kt")
|
||||||
public void testLoopParameter() throws Exception {
|
public void testLoopParameter() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/variables/removeValVarFromParameter/loopParameter.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/variables/removeValVarFromParameter/loopParameter.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user