Simple diagnostic on 'operator' keyword
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.resolve
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.JetDeclaration
|
||||||
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions.*
|
||||||
|
|
||||||
|
public class OperatorModifierChecker : DeclarationChecker {
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val GET = Name.identifier("get")
|
||||||
|
private val SET = Name.identifier("set")
|
||||||
|
|
||||||
|
private val COMPONENT_REGEX = "component\\d+".toRegex()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun check(
|
||||||
|
declaration: JetDeclaration,
|
||||||
|
descriptor: DeclarationDescriptor,
|
||||||
|
diagnosticHolder: DiagnosticSink,
|
||||||
|
bindingContext: BindingContext
|
||||||
|
) {
|
||||||
|
val functionDescriptor = descriptor as? FunctionDescriptor ?: return
|
||||||
|
if (!functionDescriptor.isOperator) return
|
||||||
|
val modifier = declaration.modifierList?.getModifier(JetTokens.OPERATOR_KEYWORD) ?: return
|
||||||
|
|
||||||
|
val name = functionDescriptor.name
|
||||||
|
|
||||||
|
when {
|
||||||
|
GET == name -> {}
|
||||||
|
SET == name -> {}
|
||||||
|
INVOKE == name -> {}
|
||||||
|
CONTAINS == name -> {}
|
||||||
|
ITERATOR == name -> {}
|
||||||
|
EQUALS == name -> {}
|
||||||
|
COMPARE_TO == name -> {}
|
||||||
|
UNARY_OPERATION_NAMES.any { it.value == name } && functionDescriptor.valueParameters.isEmpty() -> {}
|
||||||
|
BINARY_OPERATION_NAMES.any { it.value == name } && functionDescriptor.valueParameters.size() == 1 -> {}
|
||||||
|
ASSIGNMENT_OPERATIONS.any { it.value == name } -> {}
|
||||||
|
name.asString().matches(COMPONENT_REGEX) -> {}
|
||||||
|
else -> diagnosticHolder.report(Errors.INAPPLICABLE_OPERATOR_MODIFIER.on(modifier))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ public abstract class TargetPlatform(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DEFAULT_DECLARATION_CHECKERS = listOf(DataClassAnnotationChecker(), ConstModifierChecker, UnderscoreChecker)
|
private val DEFAULT_DECLARATION_CHECKERS = listOf(DataClassAnnotationChecker(), ConstModifierChecker, UnderscoreChecker, OperatorModifierChecker())
|
||||||
private val DEFAULT_CALL_CHECKERS = listOf(CapturingInClosureChecker(), InlineCheckerWrapper(), ReifiedTypeParameterSubstitutionChecker())
|
private val DEFAULT_CALL_CHECKERS = listOf(CapturingInClosureChecker(), InlineCheckerWrapper(), ReifiedTypeParameterSubstitutionChecker())
|
||||||
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
private val DEFAULT_TYPE_CHECKERS = emptyList<AdditionalTypeChecker>()
|
||||||
private val DEFAULT_VALIDATORS = listOf(DeprecatedSymbolValidator(), AccessToPrivateTopLevelSymbolValidator(), OperatorValidator())
|
private val DEFAULT_VALIDATORS = listOf(DeprecatedSymbolValidator(), AccessToPrivateTopLevelSymbolValidator(), OperatorValidator())
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class OperatorConventions {
|
|||||||
public static final Name COMPARE_TO = Name.identifier("compareTo");
|
public static final Name COMPARE_TO = Name.identifier("compareTo");
|
||||||
public static final Name CONTAINS = Name.identifier("contains");
|
public static final Name CONTAINS = Name.identifier("contains");
|
||||||
public static final Name INVOKE = Name.identifier("invoke");
|
public static final Name INVOKE = Name.identifier("invoke");
|
||||||
|
public static final Name ITERATOR = Name.identifier("iterator");
|
||||||
|
|
||||||
private OperatorConventions() {}
|
private OperatorConventions() {}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
class A {
|
||||||
|
operator fun A.minus(o: A) = o
|
||||||
|
|
||||||
|
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun A.add(o: A) = o
|
||||||
|
operator fun A.get(o: A) = o
|
||||||
|
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun A.invokee() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun A.plus(o: A) = o
|
||||||
|
operator fun A.component1() = 1
|
||||||
|
<!INAPPLICABLE_OPERATOR_MODIFIER!>operator<!> fun A.componentN() = 1
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public operator fun A.component1(): kotlin.Int
|
||||||
|
public operator fun A.componentN(): kotlin.Int
|
||||||
|
public operator fun A.plus(/*0*/ o: A): A
|
||||||
|
|
||||||
|
public final class A {
|
||||||
|
public constructor A()
|
||||||
|
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
|
||||||
|
public final operator fun A.add(/*0*/ o: A): A
|
||||||
|
public final operator fun A.get(/*0*/ o: A): A
|
||||||
|
public final operator fun A.invokee(): kotlin.Unit
|
||||||
|
public final operator fun A.minus(/*0*/ o: A): A
|
||||||
|
}
|
||||||
@@ -343,6 +343,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("OperatorsWithWrongNames.kt")
|
||||||
|
public void testOperatorsWithWrongNames() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/OperatorsWithWrongNames.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("OverrideFunctionWithParamDefaultValue.kt")
|
@TestMetadata("OverrideFunctionWithParamDefaultValue.kt")
|
||||||
public void testOverrideFunctionWithParamDefaultValue() throws Exception {
|
public void testOverrideFunctionWithParamDefaultValue() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/OverrideFunctionWithParamDefaultValue.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/OverrideFunctionWithParamDefaultValue.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user