diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt
index 9c2f3afa34b..080f22696b3 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWi
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.hasThisOrNoDispatchReceiver
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
+import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.KotlinType
@@ -64,15 +65,26 @@ class ControlFlowInformationProvider private constructor(
private val subroutine: KtElement,
private val trace: BindingTrace,
private val pseudocode: Pseudocode,
- private val languageVersionSettings: LanguageVersionSettings
+ private val languageVersionSettings: LanguageVersionSettings,
+ private val diagnosticSuppressor: PlatformDiagnosticSuppressor
) {
private val pseudocodeVariablesData by lazy {
PseudocodeVariablesData(pseudocode, trace.bindingContext)
}
- constructor(declaration: KtElement, trace: BindingTrace, languageVersionSettings: LanguageVersionSettings)
- : this(declaration, trace, ControlFlowProcessor(trace).generatePseudocode(declaration), languageVersionSettings)
+ constructor(
+ declaration: KtElement,
+ trace: BindingTrace,
+ languageVersionSettings: LanguageVersionSettings,
+ diagnosticSuppressor: PlatformDiagnosticSuppressor
+ ) : this(
+ declaration,
+ trace,
+ ControlFlowProcessor(trace).generatePseudocode(declaration),
+ languageVersionSettings,
+ diagnosticSuppressor
+ )
fun checkForLocalClassOrObjectMode() {
// Local classes and objects are analyzed twice: when TopDownAnalyzer processes it and as a part of its container.
@@ -178,7 +190,8 @@ class ControlFlowInformationProvider private constructor(
val expectedType = functionDescriptor?.returnType
val providerForLocalDeclaration = ControlFlowInformationProvider(
- element, trace, localDeclarationInstruction.body, languageVersionSettings)
+ element, trace, localDeclarationInstruction.body, languageVersionSettings, diagnosticSuppressor
+ )
providerForLocalDeclaration.checkFunction(expectedType)
}
@@ -656,8 +669,10 @@ class ControlFlowInformationProvider private constructor(
is KtPrimaryConstructor -> if (!element.hasValOrVar()) {
val containingClass = owner.getContainingClassOrObject()
val containingClassDescriptor = trace.get(DECLARATION_TO_DESCRIPTOR, containingClass) as? ClassDescriptor
- if (!DescriptorUtils.isAnnotationClass(containingClassDescriptor) && containingClassDescriptor?.isExpect == false &&
- !containingClassDescriptor.isEffectivelyExternal()
+ if (!DescriptorUtils.isAnnotationClass(containingClassDescriptor) &&
+ containingClassDescriptor?.isExpect == false &&
+ !containingClassDescriptor.isEffectivelyExternal() &&
+ diagnosticSuppressor.shouldReportUnusedParameter(variableDescriptor)
) {
report(UNUSED_PARAMETER.on(element, variableDescriptor), ctxt)
}
@@ -680,7 +695,8 @@ class ControlFlowInformationProvider private constructor(
|| functionDescriptor.isEffectivelyExternal()
|| OperatorNameConventions.GET_VALUE == functionName
|| OperatorNameConventions.SET_VALUE == functionName
- || OperatorNameConventions.PROVIDE_DELEGATE == functionName) {
+ || OperatorNameConventions.PROVIDE_DELEGATE == functionName
+ || !diagnosticSuppressor.shouldReportUnusedParameter(variableDescriptor)) {
return
}
if (anonymous) {
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java
index 5d15fd7a1ca..a396915894e 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ControlFlowAnalyzer.java
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.kotlin.psi.*;
+import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.Map;
@@ -32,16 +33,21 @@ import java.util.Map;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class ControlFlowAnalyzer {
- @NotNull private final BindingTrace trace;
- @NotNull private final KotlinBuiltIns builtIns;
- @NotNull private final LanguageVersionSettings languageVersionSettings;
+ private final BindingTrace trace;
+ private final KotlinBuiltIns builtIns;
+ private final LanguageVersionSettings languageVersionSettings;
+ private final PlatformDiagnosticSuppressor diagnosticSuppressor;
public ControlFlowAnalyzer(
- @NotNull BindingTrace trace, @NotNull KotlinBuiltIns builtIns, @NotNull LanguageVersionSettings languageVersionSettings
+ @NotNull BindingTrace trace,
+ @NotNull KotlinBuiltIns builtIns,
+ @NotNull LanguageVersionSettings languageVersionSettings,
+ @NotNull PlatformDiagnosticSuppressor diagnosticSuppressor
) {
this.trace = trace;
this.builtIns = builtIns;
this.languageVersionSettings = languageVersionSettings;
+ this.diagnosticSuppressor = diagnosticSuppressor;
}
public void process(@NotNull BodiesResolveContext c) {
@@ -74,7 +80,7 @@ public class ControlFlowAnalyzer {
private void checkSecondaryConstructor(@NotNull KtSecondaryConstructor constructor) {
ControlFlowInformationProvider controlFlowInformationProvider =
- new ControlFlowInformationProvider(constructor, trace, languageVersionSettings);
+ new ControlFlowInformationProvider(constructor, trace, languageVersionSettings, diagnosticSuppressor);
controlFlowInformationProvider.checkDeclaration();
controlFlowInformationProvider.checkFunction(builtIns.getUnitType());
}
@@ -82,8 +88,9 @@ public class ControlFlowAnalyzer {
private void checkDeclarationContainer(@NotNull BodiesResolveContext c, KtDeclarationContainer declarationContainer) {
// A pseudocode of class/object initialization corresponds to a class/object
// or initialization of properties corresponds to a package declared in a file
- ControlFlowInformationProvider controlFlowInformationProvider =
- new ControlFlowInformationProvider((KtElement) declarationContainer, trace, languageVersionSettings);
+ ControlFlowInformationProvider controlFlowInformationProvider = new ControlFlowInformationProvider(
+ (KtElement) declarationContainer, trace, languageVersionSettings, diagnosticSuppressor
+ );
if (c.getTopDownAnalysisMode().isLocalDeclarations()) {
controlFlowInformationProvider.checkForLocalClassOrObjectMode();
return;
@@ -102,9 +109,11 @@ public class ControlFlowAnalyzer {
}
}
- private void checkFunction(@NotNull BodiesResolveContext c, @NotNull KtDeclarationWithBody function, @Nullable KotlinType expectedReturnType) {
+ private void checkFunction(
+ @NotNull BodiesResolveContext c, @NotNull KtDeclarationWithBody function, @Nullable KotlinType expectedReturnType
+ ) {
ControlFlowInformationProvider controlFlowInformationProvider =
- new ControlFlowInformationProvider(function, trace, languageVersionSettings);
+ new ControlFlowInformationProvider(function, trace, languageVersionSettings, diagnosticSuppressor);
if (c.getTopDownAnalysisMode().isLocalDeclarations()) {
controlFlowInformationProvider.checkForLocalClassOrObjectMode();
return;
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PlatformDiagnosticSuppressor.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PlatformDiagnosticSuppressor.kt
new file mode 100644
index 00000000000..d8fe33fa43f
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/PlatformDiagnosticSuppressor.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.checkers
+
+import org.jetbrains.kotlin.container.DefaultImplementation
+import org.jetbrains.kotlin.descriptors.VariableDescriptor
+
+@DefaultImplementation(PlatformDiagnosticSuppressor.Default::class)
+interface PlatformDiagnosticSuppressor {
+ fun shouldReportUnusedParameter(parameter: VariableDescriptor): Boolean
+
+ object Default : PlatformDiagnosticSuppressor {
+ override fun shouldReportUnusedParameter(parameter: VariableDescriptor): Boolean = true
+ }
+}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java
index b7bc93ae383..6b1e74b0cac 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/ResolveSession.java
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
+import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor;
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension;
import org.jetbrains.kotlin.resolve.lazy.data.KtClassOrObjectInfo;
import org.jetbrains.kotlin.resolve.lazy.data.KtScriptInfo;
@@ -82,6 +83,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private LanguageVersionSettings languageVersionSettings;
private DelegationFilter delegationFilter;
private WrappedTypeFactory wrappedTypeFactory;
+ private PlatformDiagnosticSuppressor platformDiagnosticSuppressor;
private final SyntheticResolveExtension syntheticResolveExtension;
@@ -135,17 +137,21 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
this.languageVersionSettings = languageVersionSettings;
}
-
@Inject
public void setDelegationFilter(@NotNull DelegationFilter delegationFilter) {
this.delegationFilter = delegationFilter;
}
@Inject
- public void setWrappedTypeFactory(WrappedTypeFactory wrappedTypeFactory) {
+ public void setWrappedTypeFactory(@NotNull WrappedTypeFactory wrappedTypeFactory) {
this.wrappedTypeFactory = wrappedTypeFactory;
}
+ @Inject
+ public void setPlatformDiagnosticSuppressor(@NotNull PlatformDiagnosticSuppressor platformDiagnosticSuppressor) {
+ this.platformDiagnosticSuppressor = platformDiagnosticSuppressor;
+ }
+
// Only calls from injectors expected
@Deprecated
public ResolveSession(
@@ -462,6 +468,11 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
return wrappedTypeFactory;
}
+ @NotNull
+ public PlatformDiagnosticSuppressor getPlatformDiagnosticSuppressor() {
+ return platformDiagnosticSuppressor;
+ }
+
@Override
public void assertValid() {
module.assertValid();
diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt
index 5e9d603cafd..f9261f489fa 100644
--- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt
+++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt
@@ -349,7 +349,9 @@ class ResolveElementCache(
}
val controlFlowTrace = DelegatingBindingTrace(trace.bindingContext, "Element control flow resolve", resolveElement, allowSliceRewrite = true)
- ControlFlowInformationProvider(resolveElement, controlFlowTrace, resolveElement.languageVersionSettings).checkDeclaration()
+ ControlFlowInformationProvider(
+ resolveElement, controlFlowTrace, resolveElement.languageVersionSettings, resolveSession.platformDiagnosticSuppressor
+ ).checkDeclaration()
controlFlowTrace.addOwnDataTo(trace, null, false)
return Pair(trace.bindingContext, statementFilterUsed)
@@ -485,7 +487,9 @@ class ResolveElementCache(
forceResolveAnnotationsInside(property)
for (accessor in property.accessors) {
- ControlFlowInformationProvider(accessor, trace, accessor.languageVersionSettings).checkDeclaration()
+ ControlFlowInformationProvider(
+ accessor, trace, accessor.languageVersionSettings, resolveSession.platformDiagnosticSuppressor
+ ).checkDeclaration()
}
return trace
diff --git a/idea/src/META-INF/extensions/kotlin2js.xml b/idea/src/META-INF/extensions/kotlin2js.xml
index 738a855207a..19f25d6afea 100644
--- a/idea/src/META-INF/extensions/kotlin2js.xml
+++ b/idea/src/META-INF/extensions/kotlin2js.xml
@@ -2,7 +2,6 @@
org.jetbrains.kotlin
-
diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/suppressWarnings.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/suppressWarnings.kt
index fb35b0bfd07..46495cf64ee 100644
--- a/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/suppressWarnings.kt
+++ b/js/js.frontend/src/org/jetbrains/kotlin/js/analyze/suppressWarnings.kt
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.js.analyze
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticWithParameters1
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.js.PredefinedAnnotation.*
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
+import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor
import org.jetbrains.kotlin.resolve.diagnostics.FUNCTION_NO_BODY_ERRORS
import org.jetbrains.kotlin.resolve.diagnostics.PROPERTY_NOT_INITIALIZED_ERRORS
@@ -30,7 +32,17 @@ import org.jetbrains.kotlin.resolve.diagnostics.SuppressDiagnosticsByAnnotations
private val NATIVE_ANNOTATIONS = arrayOf(NATIVE.fqName, NATIVE_INVOKE.fqName, NATIVE_GETTER.fqName, NATIVE_SETTER.fqName)
-class SuppressUnusedParameterForJsNative : SuppressDiagnosticsByAnnotations(listOf(Errors.UNUSED_PARAMETER), *NATIVE_ANNOTATIONS)
+object JsNativeDiagnosticSuppressor : PlatformDiagnosticSuppressor {
+ override fun shouldReportUnusedParameter(parameter: VariableDescriptor): Boolean {
+ var descriptor: DeclarationDescriptor = parameter
+ while (true) {
+ val annotations = descriptor.annotations
+ if (!annotations.isEmpty() && NATIVE_ANNOTATIONS.any(annotations::hasAnnotation)) return false
+ descriptor = descriptor.containingDeclaration ?: break
+ }
+ return true
+ }
+}
class SuppressNoBodyErrorsForNativeDeclarations : SuppressDiagnosticsByAnnotations(FUNCTION_NO_BODY_ERRORS + PROPERTY_NOT_INITIALIZED_ERRORS, *NATIVE_ANNOTATIONS)
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 127d73b780a..8c2044451ab 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
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.resolve
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance
+import org.jetbrains.kotlin.js.analyze.JsNativeDiagnosticSuppressor
import org.jetbrains.kotlin.js.naming.NameSuggestion
import org.jetbrains.kotlin.js.resolve.diagnostics.*
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap
@@ -72,5 +73,6 @@ object JsPlatformConfigurator : PlatformConfigurator(
container.useImpl()
container.useInstance(ExtensionFunctionToExternalIsInlinable)
container.useInstance(JsQualifierChecker)
+ container.useInstance(JsNativeDiagnosticSuppressor)
}
}