From bc0550d7b7ad7da1799e418d9a012a8c4e7b4cc1 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 20 Jan 2017 16:08:08 +0300 Subject: [PATCH] JS: don't report about inline modifier on inline extension fun to external class --- .../kotlin/resolve/AnalyzerExtensions.java | 13 ++++--- .../resolve/inline/InlineAnalyzerExtension.kt | 4 ++- .../resolve/inline/ReasonableInlineRule.kt | 25 +++++++++++++ .../inlineExtensionToNative.dynamic.txt | 3 ++ .../native/inlineExtensionToNative.kt | 9 +++++ .../native/inlineExtensionToNative.txt | 19 ++++++++++ .../DiagnosticsTestWithJsStdLibGenerated.java | 6 ++++ .../ExtensionFunctionToExternalIsInlinable.kt | 36 +++++++++++++++++++ .../js/resolve/JsPlatformConfigurator.kt | 1 + 9 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/ReasonableInlineRule.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.dynamic.txt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.txt create mode 100644 js/js.frontend/src/org/jetbrains/kotlin/js/resolve/ExtensionFunctionToExternalIsInlinable.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnalyzerExtensions.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnalyzerExtensions.java index c0c65ac07ab..25bfd7aeaaa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnalyzerExtensions.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/AnalyzerExtensions.java @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtNamedFunction; import org.jetbrains.kotlin.psi.KtProperty; import org.jetbrains.kotlin.resolve.inline.InlineAnalyzerExtension; import org.jetbrains.kotlin.resolve.inline.InlineUtil; +import org.jetbrains.kotlin.resolve.inline.ReasonableInlineRule; import java.util.Collections; import java.util.List; @@ -35,9 +36,11 @@ public class AnalyzerExtensions { } @NotNull private final BindingTrace trace; + @NotNull private final Iterable reasonableInlineRules; - public AnalyzerExtensions(@NotNull BindingTrace trace) { + public AnalyzerExtensions(@NotNull BindingTrace trace, @NotNull Iterable reasonableInlineRules) { this.trace = trace; + this.reasonableInlineRules = reasonableInlineRules; } public void process(@NotNull BodiesResolveContext bodiesResolveContext) { @@ -61,17 +64,17 @@ public class AnalyzerExtensions { } @NotNull - private static List getFunctionExtensions(@NotNull FunctionDescriptor functionDescriptor) { + private List getFunctionExtensions(@NotNull FunctionDescriptor functionDescriptor) { if (InlineUtil.isInline(functionDescriptor)) { - return Collections.singletonList(InlineAnalyzerExtension.INSTANCE); + return Collections.singletonList(new InlineAnalyzerExtension(reasonableInlineRules)); } return Collections.emptyList(); } @NotNull - private static List getPropertyExtensions(@NotNull PropertyDescriptor propertyDescriptor) { + private List getPropertyExtensions(@NotNull PropertyDescriptor propertyDescriptor) { if (InlineUtil.hasInlineAccessors(propertyDescriptor)) { - return Collections.singletonList(InlineAnalyzerExtension.INSTANCE); + return Collections.singletonList(new InlineAnalyzerExtension(reasonableInlineRules)); } return Collections.emptyList(); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt index e3a89da0820..f76616e259d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/InlineAnalyzerExtension.kt @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue -object InlineAnalyzerExtension : AnalyzerExtensions.AnalyzerExtension { +class InlineAnalyzerExtension(private val reasonableInlineRules: Iterable) : AnalyzerExtensions.AnalyzerExtension { override fun process(descriptor: CallableMemberDescriptor, functionOrProperty: KtCallableDeclaration, trace: BindingTrace) { checkModalityAndOverrides(descriptor, functionOrProperty, trace) @@ -143,6 +143,8 @@ object InlineAnalyzerExtension : AnalyzerExtensions.AnalyzerExtension { functionDescriptor.isInlineOnlyOrReifiable() || functionDescriptor.isHeader) return + if (reasonableInlineRules.any { it.isInlineReasonable(functionDescriptor, function, trace.bindingContext) }) return + val reportOn = function.modifierList?.getModifier(KtTokens.INLINE_KEYWORD) ?: function trace.report(Errors.NOTHING_TO_INLINE.on(reportOn, functionDescriptor)) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/ReasonableInlineRule.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/ReasonableInlineRule.kt new file mode 100644 index 00000000000..1caf18db1a7 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/ReasonableInlineRule.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2017 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.inline + +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.resolve.BindingContext + +interface ReasonableInlineRule { + fun isInlineReasonable(descriptor: CallableMemberDescriptor, declaration: KtCallableDeclaration, context: BindingContext): Boolean +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.dynamic.txt b/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.dynamic.txt new file mode 100644 index 00000000000..5ebbf59c470 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.dynamic.txt @@ -0,0 +1,3 @@ +public final fun foo(/*0*/ p0: dynamic): dynamic +public final fun get(/*0*/ p0: dynamic): dynamic +public final fun get(/*0*/ p0: dynamic): dynamic diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.kt b/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.kt new file mode 100644 index 00000000000..2a8be53e70f --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.kt @@ -0,0 +1,9 @@ +external class A { + class B +} + +inline fun A.foo(x: Int): String = asDynamic().foo(x) + +inline operator fun A.get(x: Int): String = asDynamic()[x] + +inline operator fun A.B.get(x: Int): String = asDynamic()[x] \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.txt b/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.txt new file mode 100644 index 00000000000..b2420390ae8 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.txt @@ -0,0 +1,19 @@ +package + +public inline fun A.foo(/*0*/ x: kotlin.Int): kotlin.String +public operator inline fun A.get(/*0*/ x: kotlin.Int): kotlin.String +public operator inline fun A.B.get(/*0*/ x: kotlin.Int): kotlin.String + +public external 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 class B { + public constructor 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 + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java index 5116c5aa7cf..e1c5a5b4adc 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestWithJsStdLibGenerated.java @@ -653,6 +653,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes doTest(fileName); } + @TestMetadata("inlineExtensionToNative.kt") + public void testInlineExtensionToNative() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/inlineExtensionToNative.kt"); + doTest(fileName); + } + @TestMetadata("innerClass.kt") public void testInnerClass() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/innerClass.kt"); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/ExtensionFunctionToExternalIsInlinable.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/ExtensionFunctionToExternalIsInlinable.kt new file mode 100644 index 00000000000..c03913da765 --- /dev/null +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/ExtensionFunctionToExternalIsInlinable.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2017 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.js.resolve + +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.inline.ReasonableInlineRule + +object ExtensionFunctionToExternalIsInlinable : ReasonableInlineRule { + override fun isInlineReasonable( + descriptor: CallableMemberDescriptor, + declaration: KtCallableDeclaration, + context: BindingContext + ): Boolean { + val receiverParameter = descriptor.extensionReceiverParameter ?: return false + val receiverClass = receiverParameter.value.type.constructor.declarationDescriptor as? ClassDescriptor ?: return false + return DescriptorUtils.isEffectivelyExternal(receiverClass) + } +} \ No newline at end of file diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt index b7dca3ead2e..dc3e1e07c45 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/resolve/JsPlatformConfigurator.kt @@ -67,5 +67,6 @@ object JsPlatformConfigurator : PlatformConfigurator( container.useImpl() container.useImpl() container.useImpl() + container.useInstance(ExtensionFunctionToExternalIsInlinable) } }