JS inline: common reference utilities for cleaning up after inline
This commit is contained in:
committed by
Zalim Bashorov
parent
ddb3157a58
commit
7f98ceb427
@@ -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<T : JsNode>(removable: Collection<T> = listOf()) : NodeRemovingVisitor<T>(removable) {
|
||||||
|
|
||||||
|
override fun <T : JsNode?> doTraverse(node: T?, ctx: JsContext?) {
|
||||||
|
if (node == null) return
|
||||||
|
|
||||||
|
if (shouldRemove(node)) {
|
||||||
|
ctx?.removeMe()
|
||||||
|
} else {
|
||||||
|
super.doTraverse(node, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<T : JsNode>(removable: Collection<T>) : JsVisitorWithContextImpl() {
|
||||||
|
private val removeSet: Set<T> = removable.toIdentitySet()
|
||||||
|
|
||||||
|
protected fun <R : JsNode?> shouldRemove(node: R): Boolean {
|
||||||
|
return removeSet.contains(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Reference, RemoveCandidate : JsNode> {
|
||||||
|
private val reachable = IdentityHashMap<Reference, Boolean>()
|
||||||
|
private val removableCandidates = IdentityHashMap<Reference, RemoveCandidate>()
|
||||||
|
private val refereceFromTo = IdentityHashMap<Reference, MutableList<Reference>>()
|
||||||
|
private val visited = IdentitySet<Reference>()
|
||||||
|
|
||||||
|
public val removable: List<RemoveCandidate>
|
||||||
|
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<Reference> {
|
||||||
|
return refereceFromTo.getOrPut(referer, { ArrayList<Reference>() })
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isKnown(ref: Reference): Boolean {
|
||||||
|
return removableCandidates.containsKey(ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isReachable(ref: Reference): Boolean {
|
||||||
|
return reachable[ref] ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<JsName> {
|
||||||
|
return with(ReferenceNameCollector()) {
|
||||||
|
accept(scope)
|
||||||
|
references.filter { it.getStaticRef() is JsFunction }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collectReferencesInside(scope: JsNode): List<JsName> {
|
||||||
|
return with(ReferenceNameCollector()) {
|
||||||
|
accept(scope)
|
||||||
|
references
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ReferenceNameCollector : JsVisitorWithContextImpl() {
|
||||||
|
private val referenceSet = IdentitySet<JsName>()
|
||||||
|
|
||||||
|
public val references: List<JsName>
|
||||||
|
get() = referenceSet.toList()
|
||||||
|
|
||||||
|
override fun endVisit(x: JsNameRef?, ctx: JsContext?) {
|
||||||
|
val name = x?.getName()
|
||||||
|
if (name != null) {
|
||||||
|
referenceSet.add(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user