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