diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt index c1f731f53e4..f3ed20ab7da 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt @@ -105,6 +105,8 @@ var JsNameRef.coroutineController by MetadataProperty(default = false) var JsFunction.continuationInterfaceRef: JsExpression? by MetadataProperty(default = null) +var JsName.imported by MetadataProperty(default = false) + enum class TypeCheck { TYPEOF, INSTANCEOF, diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedImports.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedImports.kt new file mode 100644 index 00000000000..313612cf965 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedImports.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2016 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.inline.clean + +import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.metadata.imported + +fun removeUnusedImports(root: JsNode) { + val collector = UsedImportsCollector() + root.accept(collector) + NodeRemover(JsVars::class.java) { statement -> + if (statement.vars.size == 1) { + val name = statement.vars[0].name + name.imported && name !in collector.usedImports + } + else { + false + } + }.accept(root) +} + +private class UsedImportsCollector : RecursiveJsVisitor() { + val usedImports = mutableSetOf() + + override fun visitNameRef(nameRef: JsNameRef) { + val name = nameRef.name + if (name != null && name.imported) { + usedImports += name + } + super.visitNameRef(nameRef) + } +} diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 83c3e8307d9..da592c2d163 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -4562,6 +4562,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/inlineSizeReduction"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("inlineImportCleanup.kt") + public void testInlineImportCleanup() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineSizeReduction/inlineImportCleanup.kt"); + doTest(fileName); + } + @TestMetadata("inlineLambdaCleanup.kt") public void testInlineLambdaCleanup() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineSizeReduction/inlineLambdaCleanup.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java index 80759cd3e1b..769dd9c5e14 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.config.JsConfig; import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer; import org.jetbrains.kotlin.js.facade.exceptions.TranslationException; import org.jetbrains.kotlin.js.inline.JsInliner; +import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.general.Translation; import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus; @@ -88,6 +89,7 @@ public final class K2JSTranslator { CoroutineTransformer coroutineTransformer = new CoroutineTransformer(program); coroutineTransformer.accept(program); + RemoveUnusedImportsKt.removeUnusedImports(program); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java index cf8cf3f6cb0..88f2e2c3f93 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/StaticContext.java @@ -48,7 +48,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import java.util.*; import static org.jetbrains.kotlin.js.config.LibrarySourcesConfig.UNKNOWN_EXTERNAL_MODULE_NAME; -import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject; import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isLibraryObject; import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject; import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn; @@ -403,6 +402,7 @@ public final class StaticContext { // TODO: remove prefix when problem with scopes is solved JsName result = rootFunction.getScope().declareFreshName("imported$" + suggestedName); + MetadataProperties.setImported(result, true); importStatements.add(JsAstUtils.newVar(result, declaration)); return result; } diff --git a/js/js.translator/testData/box/inlineSizeReduction/inlineImportCleanup.kt b/js/js.translator/testData/box/inlineSizeReduction/inlineImportCleanup.kt new file mode 100644 index 00000000000..09b9e5af4eb --- /dev/null +++ b/js/js.translator/testData/box/inlineSizeReduction/inlineImportCleanup.kt @@ -0,0 +1,10 @@ +// MODULE: lib +// FILE: lib.kt +package lib + +inline fun foo(f: () -> String) = f() + +// MODULE: main(lib) +// FILE: main.kt +// PROPERTY_NOT_READ_FROM: foo_6r51u9$ +fun box() = lib.foo { "OK" } \ No newline at end of file