diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/clean/GenericRemover.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/GenericRemover.kt new file mode 100644 index 00000000000..214e375b32e --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/GenericRemover.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2014 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.k2js.inline.clean + +import com.google.dart.compiler.backend.js.ast.* + +private class GenericRemover(removable: Collection = listOf()) : NodeRemovingVisitor(removable) { + + override fun doTraverse(node: T?, ctx: JsContext?) { + if (node == null) return + + if (shouldRemove(node)) { + ctx?.removeMe() + } else { + super.doTraverse(node, ctx) + } + } +} diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/clean/NodeRemovingVisitor.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/NodeRemovingVisitor.kt new file mode 100644 index 00000000000..3290a8d2c74 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/NodeRemovingVisitor.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2014 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.k2js.inline.clean + +import com.google.dart.compiler.backend.js.ast.* +import org.jetbrains.k2js.inline.util.IdentitySet + +import java.util.IdentityHashMap +import org.jetbrains.k2js.inline.util.toIdentitySet + +private abstract class NodeRemovingVisitor(removable: Collection) : JsVisitorWithContextImpl() { + private val removeSet: Set = removable.toIdentitySet() + + protected fun shouldRemove(node: R): Boolean { + return removeSet.contains(node) + } +} diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/clean/ReferenceTracker.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/ReferenceTracker.kt new file mode 100644 index 00000000000..e0fdb59a1b0 --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/ReferenceTracker.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2014 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.k2js.inline.clean + +import com.google.dart.compiler.backend.js.ast.* +import org.jetbrains.k2js.inline.util.IdentitySet + +import java.util.IdentityHashMap +import java.util.ArrayList + +private class ReferenceTracker { + private val reachable = IdentityHashMap() + private val removableCandidates = IdentityHashMap() + private val refereceFromTo = IdentityHashMap>() + private val visited = IdentitySet() + + public val removable: List + get() { + return reachable + .filter { !it.value } + .map { removableCandidates.get(it.key)!! } + } + + public fun addCandidateForRemoval(reference: Reference, candidate: RemoveCandidate) { + assert(!isKnown(reference)) { "Candidate for removal cannot be reassigned: $candidate" } + + removableCandidates.put(reference, candidate) + reachable.put(reference, false) + } + + public fun addRemovableReference(referer: Reference, referenced: Reference) { + if (!isKnown(referenced)) return + + getReferencedBy(referer).add(referenced) + + if (isReachable(referer)) { + markReachable(referenced) + } + } + + public fun markReachable(reference: Reference) { + if (!isKnown(reference)) return + + visited.add(reference) + getReferencedBy(reference) + .filterNot { it in visited } + .filter { isKnown(it) && !isReachable(it) } + .forEach { markReachable(it) } + + visited.remove(reference) + reachable[reference] = true + } + + private fun getReferencedBy(referer: Reference): MutableList { + return refereceFromTo.getOrPut(referer, { ArrayList() }) + } + + private fun isKnown(ref: Reference): Boolean { + return removableCandidates.containsKey(ref) + } + + private fun isReachable(ref: Reference): Boolean { + return reachable[ref] ?: false + } +} diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/clean/referenceCollectionUtils.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/referenceCollectionUtils.kt new file mode 100644 index 00000000000..4646aa42a3e --- /dev/null +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/clean/referenceCollectionUtils.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2014 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.k2js.inline.clean + +import com.google.dart.compiler.backend.js.ast.* +import org.jetbrains.k2js.inline.util.IdentitySet + +import java.util.ArrayList + +private fun collectFunctionReferencesInside(scope: JsNode): List { + return with(ReferenceNameCollector()) { + accept(scope) + references.filter { it.getStaticRef() is JsFunction } + } +} + +private fun collectReferencesInside(scope: JsNode): List { + return with(ReferenceNameCollector()) { + accept(scope) + references + } +} + +private class ReferenceNameCollector : JsVisitorWithContextImpl() { + private val referenceSet = IdentitySet() + + public val references: List + get() = referenceSet.toList() + + override fun endVisit(x: JsNameRef?, ctx: JsContext?) { + val name = x?.getName() + if (name != null) { + referenceSet.add(name) + } + } +} \ No newline at end of file