Additional correctness check for noinline & crossinline #KT-9567 Fixed

This commit is contained in:
Mikhail Glukhikh
2015-10-13 19:59:02 +03:00
parent 96b567254d
commit c210ca5b4d
7 changed files with 78 additions and 0 deletions
@@ -125,6 +125,7 @@ public interface Errors {
DiagnosticFactory2<PsiElement, JetModifierKeywordToken, String> REDUNDANT_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<PsiElement, JetModifierKeywordToken, String> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<PsiElement, JetModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
DiagnosticFactory1<PsiElement, JetModifierKeywordToken> ILLEGAL_INLINE_PARAMETER_MODIFIER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<JetAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<JetAnnotationEntry> REPEATED_ANNOTATION = DiagnosticFactory0.create(ERROR);
@@ -132,6 +132,7 @@ public class DefaultErrorMessages {
MAP.put(REDUNDANT_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is redundant for ''{1}''", TO_STRING, TO_STRING);
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
MAP.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier ''{0}'' is allowed only for function parameters of an inline function", TO_STRING);
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
MAP.put(REPEATED_ANNOTATION, "This annotation is not repeatable");
@@ -0,0 +1,53 @@
/*
* 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.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.JetDeclaration
import org.jetbrains.kotlin.psi.JetFunction
import org.jetbrains.kotlin.psi.JetParameter
object InlineParameterChecker : DeclarationChecker {
override fun check(declaration: JetDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
if (declaration is JetFunction) {
val inline = declaration.hasModifier(JetTokens.INLINE_KEYWORD)
for (parameter in declaration.valueParameters) {
val parameterDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, parameter)
if (!inline || (parameterDescriptor != null && !KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameterDescriptor.type))) {
parameter.reportIncorrectInline(JetTokens.NOINLINE_KEYWORD, diagnosticHolder)
parameter.reportIncorrectInline(JetTokens.CROSSINLINE_KEYWORD, diagnosticHolder)
}
}
}
}
private fun JetParameter.reportIncorrectInline(modifierToken: JetModifierKeywordToken, diagnosticHolder: DiagnosticSink) {
val modifier = modifierList?.getModifier(modifierToken)
modifier?.let {
diagnosticHolder.report(Errors.ILLEGAL_INLINE_PARAMETER_MODIFIER.on(modifier, modifierToken))
}
}
}
@@ -51,6 +51,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
DataClassAnnotationChecker(),
ConstModifierChecker,
UnderscoreChecker,
InlineParameterChecker,
OperatorModifierChecker(),
InfixModifierChecker())
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
<!NOTHING_TO_INLINE!>inline<!> fun foo(<!ILLEGAL_INLINE_PARAMETER_MODIFIER!>noinline<!> x: Int) {}
<!NOTHING_TO_INLINE!>inline<!> fun bar(y: Int, <!ILLEGAL_INLINE_PARAMETER_MODIFIER!>crossinline<!> x: String) {}
fun gav(<!ILLEGAL_INLINE_PARAMETER_MODIFIER!>noinline<!> x: (Int) -> Unit, <!ILLEGAL_INLINE_PARAMETER_MODIFIER!>crossinline<!> y: (String) -> Int) {}
inline fun correct(noinline x: (Int) -> Unit, crossinline y: (String) -> Int) {}
@@ -0,0 +1,6 @@
package
@kotlin.inline() public fun bar(/*0*/ y: kotlin.Int, /*1*/ @kotlin.crossinline() x: kotlin.String): kotlin.Unit
@kotlin.inline() public fun correct(/*0*/ @kotlin.noinline() x: (kotlin.Int) -> kotlin.Unit, /*1*/ @kotlin.crossinline() y: (kotlin.String) -> kotlin.Int): kotlin.Unit
@kotlin.inline() public fun foo(/*0*/ @kotlin.noinline() x: kotlin.Int): kotlin.Unit
public fun gav(/*0*/ @kotlin.noinline() x: (kotlin.Int) -> kotlin.Unit, /*1*/ @kotlin.crossinline() y: (kotlin.String) -> kotlin.Int): kotlin.Unit
@@ -9430,6 +9430,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("inlineParameters.kt")
public void testInlineParameters() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/inlineParameters.kt");
doTest(fileName);
}
@TestMetadata("internalInInterface.kt")
public void testInternalInInterface() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/modifiers/internalInInterface.kt");