diff --git a/compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.kt b/compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.kt new file mode 100644 index 00000000000..d11be9bd86c --- /dev/null +++ b/compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.kt @@ -0,0 +1,46 @@ +class A { + fun foo(): Unit + { + } + + fun bar(): Unit + { + return Unit + } + + fun baz(): Unit = bar() + + fun f1(): Int = 1 + + fun f2(): Unit + { + throw UnsupportedOperationException("") + } + + fun f3(): Unit = throw UnsupportedOperationException("") +} + +class B { + fun run(f: () -> T) = f() + + fun foo(): Unit = run { + bar() + } + + fun bar() = 1 + + fun call(f: () -> Unit) = f() + + fun boo(): Unit = call { + baz() + } + + fun baz() {} + + fun T.let(f: (T) -> R) = f(this) + + fun goo(): Unit = 1.let { + bar() + } +} + diff --git a/compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.txt b/compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.txt new file mode 100644 index 00000000000..884456a2152 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.txt @@ -0,0 +1,76 @@ +FILE: RedundantReturnUnitTypeChecker.kt + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + } + + public final fun bar(): R|kotlin/Unit| { + ^bar Q|kotlin/Unit| + } + + public final fun baz(): R|kotlin/Unit| { + ^baz this@R|/A|.R|/A.bar|() + } + + public final fun f1(): R|kotlin/Int| { + ^f1 Int(1) + } + + public final fun f2(): R|kotlin/Unit| { + throw R|java/lang/UnsupportedOperationException.UnsupportedOperationException|(String()) + } + + public final fun f3(): R|kotlin/Unit| { + ^f3 throw R|java/lang/UnsupportedOperationException.UnsupportedOperationException|(String()) + } + + } + public final class B : R|kotlin/Any| { + public constructor(): R|B| { + super() + } + + public final fun run(f: R|() -> T|): R|T| { + ^run R|/f|.R|FakeOverride|() + } + + public final fun foo(): R|kotlin/Unit| { + ^foo this@R|/B|.R|/B.run|( = run@fun (): R|kotlin/Int| { + ^ this@R|/B|.R|/B.bar|() + } + ) + } + + public final fun bar(): R|kotlin/Int| { + ^bar Int(1) + } + + public final fun call(f: R|() -> kotlin/Unit|): R|kotlin/Unit| { + ^call R|/f|.R|FakeOverride|() + } + + public final fun boo(): R|kotlin/Unit| { + ^boo this@R|/B|.R|/B.call|( = call@fun (): R|kotlin/Unit| { + this@R|/B|.R|/B.baz|() + } + ) + } + + public final fun baz(): R|kotlin/Unit| { + } + + public final fun R|T|.let(f: R|(T) -> R|): R|R| { + ^let R|/f|.R|FakeOverride|(this@R|/B.let|) + } + + public final fun goo(): R|kotlin/Unit| { + ^goo (this@R|/B|, Int(1)).R|/B.let|( = let@fun (it: R|kotlin/Int|): R|kotlin/Int| { + ^ this@R|/B|.R|/B.bar|() + } + ) + } + + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/ExtendedFirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/ExtendedFirDiagnosticsTestGenerated.java index aaf414b872b..7a19623cb0c 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/ExtendedFirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/ExtendedFirDiagnosticsTestGenerated.java @@ -28,6 +28,11 @@ public class ExtendedFirDiagnosticsTestGenerated extends AbstractExtendedFirDiag KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/extendedCheckers"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("RedundantReturnUnitTypeChecker.kt") + public void testRedundantReturnUnitTypeChecker() throws Exception { + runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantReturnUnitTypeChecker.kt"); + } + @TestMetadata("RedundantVisibilityModifierChecker.kt") public void testRedundantVisibilityModifierChecker() throws Exception { runTest("compiler/fir/analysis-tests/testData/extendedCheckers/RedundantVisibilityModifierChecker.kt"); diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt index f2e43683602..12dd507aa34 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DefaultDeclarationCheckers.kt @@ -5,13 +5,15 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration +import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantReturnUnitType import org.jetbrains.kotlin.fir.analysis.checkers.extended.RedundantVisibilityModifierChecker object CommonDeclarationCheckers : DeclarationCheckers() { override val declarationCheckers: List = listOf( FirAnnotationClassDeclarationChecker, FirModifierChecker, - RedundantVisibilityModifierChecker + RedundantVisibilityModifierChecker, + RedundantReturnUnitType ) override val memberDeclarationCheckers: List = listOf( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantReturnUnitTypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantReturnUnitTypeChecker.kt new file mode 100644 index 00000000000..c5a4a41fa9a --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantReturnUnitTypeChecker.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.checkers.extended + +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock +import org.jetbrains.kotlin.fir.types.isUnit + +object RedundantReturnUnitType : FirBasicDeclarationChecker() { + override val isExtended = true + + override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { + if (declaration !is FirSimpleFunction) return + if (declaration.body is FirSingleExpressionBlock) return + if (declaration.returnTypeRef.source == null) return + + if (declaration.returnTypeRef.isUnit) { + reporter.report(declaration.returnTypeRef.source, FirErrors.REDUNDANT_RETURN_UNIT_TYPE) + } + } + +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 6e0b8bfcf92..2440c50a664 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import com.intellij.psi.PsiElement +import com.intellij.psi.PsiTypeElement import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.fir.FirEffectiveVisibility import org.jetbrains.kotlin.fir.FirSourceElement @@ -83,6 +84,7 @@ object FirErrors { // Extended checkers group val REDUNDANT_VISIBILITY_MODIFIER by warning0() + val REDUNDANT_RETURN_UNIT_TYPE by warning0() }