diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index beb160d421b..2894a507a60 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -333,6 +333,8 @@ public interface Errors { DiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 FUNCTION_DECLARATION_WITH_NO_NAME = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); + DiagnosticFactory0 VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NO_TAIL_CALLS_FOUND = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index e785e3487be..a1154f712ae 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -32,7 +32,9 @@ public object PositioningStrategies { private open class DeclarationHeader : PositioningStrategy() { override fun isValid(element: T): Boolean { if (element is JetNamedDeclaration && - (element !is JetObjectDeclaration && element !is JetSecondaryConstructor) + element !is JetObjectDeclaration && + element !is JetSecondaryConstructor && + element !is JetNamedFunction ) { if (element.getNameIdentifier() == null) { return false @@ -103,6 +105,9 @@ public object PositioningStrategies { } return markElement(nameIdentifier) } + if (element is JetNamedFunction) { + return DECLARATION_SIGNATURE.mark(element) + } return DEFAULT.mark(element) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 8ccb0fa8b9e..7aa8cba5515 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -224,6 +224,7 @@ public class DefaultErrorMessages { MAP.put(FINAL_FUNCTION_WITH_NO_BODY, "Function ''{0}'' without body cannot be final", NAME); MAP.put(NON_MEMBER_FUNCTION_NO_BODY, "Function ''{0}'' must have a body", NAME); + MAP.put(FUNCTION_DECLARATION_WITH_NO_NAME, "Function declaration must have a name"); MAP.put(NON_FINAL_MEMBER_IN_FINAL_CLASS, "\"open\" has no effect in a final class"); MAP.put(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, "Public or protected member should have specified type"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 12d059e75b3..60fd7aba81f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -237,7 +237,19 @@ public class DescriptorResolver { @NotNull DataFlowInfo dataFlowInfo ) { return resolveFunctionDescriptor(containingDescriptor, scope, function, trace, dataFlowInfo, - annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace)); + annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace), false); + } + + @NotNull + public SimpleFunctionDescriptor resolveAnonymousFunctionDescriptor( + @NotNull DeclarationDescriptor containingDescriptor, + @NotNull JetScope scope, + @NotNull JetNamedFunction function, + @NotNull BindingTrace trace, + @NotNull DataFlowInfo dataFlowInfo + ) { + return resolveFunctionDescriptor(containingDescriptor, scope, function, trace, dataFlowInfo, + annotationResolver.resolveAnnotationsWithArguments(scope, function.getModifierList(), trace), true); } @NotNull @@ -249,7 +261,7 @@ public class DescriptorResolver { @NotNull DataFlowInfo dataFlowInfo ) { return resolveFunctionDescriptor(containingDescriptor, scope, function, trace, dataFlowInfo, - annotationResolver.resolveAnnotationsWithoutArguments(scope, function.getModifierList(), trace)); + annotationResolver.resolveAnnotationsWithoutArguments(scope, function.getModifierList(), trace), false); } @NotNull @@ -259,12 +271,17 @@ public class DescriptorResolver { @NotNull final JetNamedFunction function, @NotNull final BindingTrace trace, @NotNull final DataFlowInfo dataFlowInfo, - @NotNull Annotations annotations + @NotNull Annotations annotations, + boolean nameCanBeOmitted ) { + if (!nameCanBeOmitted && function.getName() == null) { + trace.report(FUNCTION_DECLARATION_WITH_NO_NAME.on(function)); + } + final SimpleFunctionDescriptorImpl functionDescriptor = SimpleFunctionDescriptorImpl.create( containingDescriptor, annotations, - JetPsiUtil.safeName(function.getName()), + function.getNameAsSafeName(), CallableMemberDescriptor.Kind.DECLARATION, toSourceElement(function) ); diff --git a/compiler/testData/diagnostics/tests/declarationChecks/FunctionWithMissingNames.kt b/compiler/testData/diagnostics/tests/declarationChecks/FunctionWithMissingNames.kt new file mode 100644 index 00000000000..cb041888d74 --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/FunctionWithMissingNames.kt @@ -0,0 +1,25 @@ +annotation class a +trait A +trait B + +fun () {} +fun A.() {} + +a fun () {} +fun [a] A.() {} + +class Outer { + fun () {} + fun B.() {} + + a fun () {} + fun [a] A.() {} +} + +fun outerFun() { + fun () {} + fun B.() {} + + [a] fun () {} + fun [a] A.() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/FunctionWithMissingNames.txt b/compiler/testData/diagnostics/tests/declarationChecks/FunctionWithMissingNames.txt new file mode 100644 index 00000000000..fbe124fd600 --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/FunctionWithMissingNames.txt @@ -0,0 +1,37 @@ +package + +a() internal fun (): kotlin.Unit +internal fun (): kotlin.Unit +internal fun outerFun(): kotlin.Unit +internal fun A.(): kotlin.Unit +internal fun A.(): kotlin.Unit + +internal trait 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 +} + +internal trait B { + 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 +} + +internal final class Outer { + public constructor Outer() + a() internal final fun (): kotlin.Unit + internal final fun (): kotlin.Unit + 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 + internal final fun A.(): kotlin.Unit + internal final fun B.(): kotlin.Unit +} + +internal final annotation class a : kotlin.Annotation { + 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 +} diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.kt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.kt index 5de524609ad..1ecc779baaa 100644 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.kt +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.kt @@ -1,4 +1,8 @@ -fun () { +fun () { + +} + +fun Outer.() { } @@ -25,7 +29,7 @@ annotation class { } class Outer { - fun () { + fun () { } @@ -50,4 +54,14 @@ class Outer { annotation class { } -} \ No newline at end of file +} + +fun outerFun() { + fun () { + + } + fun () { + + } +} + diff --git a/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.txt b/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.txt index 809283f542e..616013759f3 100644 --- a/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.txt +++ b/compiler/testData/diagnostics/tests/duplicateJvmSignature/missingNames.txt @@ -2,6 +2,8 @@ package internal val : kotlin.Int = 1 internal fun (): kotlin.Unit +internal fun outerFun(): kotlin.Unit +internal fun Outer.(): kotlin.Unit internal final class { internal constructor () diff --git a/compiler/testData/diagnostics/tests/recovery/namelessInJava.kt b/compiler/testData/diagnostics/tests/recovery/namelessInJava.kt index 3110d8d69e7..b6fc44dbeb4 100644 --- a/compiler/testData/diagnostics/tests/recovery/namelessInJava.kt +++ b/compiler/testData/diagnostics/tests/recovery/namelessInJava.kt @@ -12,6 +12,6 @@ public class Nameless { import p.* class K : Nameless() { - fun () {} + fun () {} val : Int = 1 -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/recovery/namelessMembers.kt b/compiler/testData/diagnostics/tests/recovery/namelessMembers.kt index b5bc8e6e55c..4b7f5dd3d55 100644 --- a/compiler/testData/diagnostics/tests/recovery/namelessMembers.kt +++ b/compiler/testData/diagnostics/tests/recovery/namelessMembers.kt @@ -1,7 +1,7 @@ // !DIAGNOSTICS: -REDECLARATION class C { - fun () { + fun () { } diff --git a/compiler/testData/diagnostics/tests/recovery/namelessToplevelDeclarations.kt b/compiler/testData/diagnostics/tests/recovery/namelessToplevelDeclarations.kt index 2c380e965ee..067f80d0a19 100644 --- a/compiler/testData/diagnostics/tests/recovery/namelessToplevelDeclarations.kt +++ b/compiler/testData/diagnostics/tests/recovery/namelessToplevelDeclarations.kt @@ -2,7 +2,7 @@ package -fun () { +fun () { } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 90d02fe1376..73c44d338ac 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -2965,6 +2965,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("FunctionWithMissingNames.kt") + public void testFunctionWithMissingNames() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/FunctionWithMissingNames.kt"); + doTest(fileName); + } + @TestMetadata("illegalModifiersOnClass.kt") public void testIllegalModifiersOnClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/illegalModifiersOnClass.kt"); diff --git a/idea/testData/checker/recovery/namelessMembers.kt b/idea/testData/checker/recovery/namelessMembers.kt index 14c6e2d520a..f9114d59c45 100644 --- a/idea/testData/checker/recovery/namelessMembers.kt +++ b/idea/testData/checker/recovery/namelessMembers.kt @@ -1,5 +1,5 @@ class C { - fun () { + fun () { } diff --git a/idea/testData/checker/recovery/namelessToplevelDeclarations.kt b/idea/testData/checker/recovery/namelessToplevelDeclarations.kt index a77cb125fc9..daf846bf54a 100644 --- a/idea/testData/checker/recovery/namelessToplevelDeclarations.kt +++ b/idea/testData/checker/recovery/namelessToplevelDeclarations.kt @@ -1,6 +1,6 @@ package -fun () { +fun () { } diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt b/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt index d6ae0749fe8..4c5478d63e8 100644 --- a/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt +++ b/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt @@ -1,3 +1,4 @@ +// ERROR: Function declaration must have a name class Owner { fun () {} } \ No newline at end of file diff --git a/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt.after b/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt.after index 59e92e72377..a223121db61 100644 --- a/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt.after +++ b/idea/testData/intentions/declarations/convertMemberToExtension/funcitonNoName.kt.after @@ -1,3 +1,4 @@ +// ERROR: Function declaration must have a name class Owner { } diff --git a/idea/testData/quickfix/autoImports/beforeNamelessFunction.kt b/idea/testData/quickfix/autoImports/beforeNamelessFunction.kt index 05d0de5fb0b..92d51beb481 100644 --- a/idea/testData/quickfix/autoImports/beforeNamelessFunction.kt +++ b/idea/testData/quickfix/autoImports/beforeNamelessFunction.kt @@ -1,5 +1,6 @@ // "class com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFixBase" "false" // ERROR: Unresolved reference: TTTTT +// ERROR: Function declaration must have a name fun () { val tttt : TTTTT = null diff --git a/idea/testData/quickfix/typeMismatch/afterChangeReturnTypeWhenFunctionNameIsMissing.kt b/idea/testData/quickfix/typeMismatch/afterChangeReturnTypeWhenFunctionNameIsMissing.kt index 824275c22e9..ca584ac90f3 100644 --- a/idea/testData/quickfix/typeMismatch/afterChangeReturnTypeWhenFunctionNameIsMissing.kt +++ b/idea/testData/quickfix/typeMismatch/afterChangeReturnTypeWhenFunctionNameIsMissing.kt @@ -1,4 +1,5 @@ // "Remove explicitly specified function return type" "true" +// ERROR: Function declaration must have a name fun () { return } \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforeChangeReturnTypeWhenFunctionNameIsMissing.kt b/idea/testData/quickfix/typeMismatch/beforeChangeReturnTypeWhenFunctionNameIsMissing.kt index 5a7e745cead..ecc9eb38684 100644 --- a/idea/testData/quickfix/typeMismatch/beforeChangeReturnTypeWhenFunctionNameIsMissing.kt +++ b/idea/testData/quickfix/typeMismatch/beforeChangeReturnTypeWhenFunctionNameIsMissing.kt @@ -1,4 +1,5 @@ // "Remove explicitly specified function return type" "true" +// ERROR: Function declaration must have a name fun (): Int { return } \ No newline at end of file