WEB-16337 unprefixed package debug

This commit is contained in:
Vladimir Krivosheev
2015-12-01 16:50:09 +01:00
parent 4c8fc53821
commit c227fffbe6
4 changed files with 119 additions and 148 deletions
@@ -140,7 +140,7 @@ public final class NettyUtil {
break;
}
catch (IOException e) {
if (stopCondition.value(null) || (promise != null && promise.getState() == Promise.State.REJECTED)) {
if (stopCondition.value(null) || (promise != null && promise.getState() != Promise.State.PENDING)) {
return null;
}
else if (maxAttemptCount == -1) {
@@ -22,17 +22,14 @@ import com.intellij.util.Url
// sources - is not originally specified, but canonicalized/normalized
class SourceMap(val outFile: String?, val mappings: MappingList, internal val sourceIndexToMappings: Array<MappingList?>, val sourceResolver: SourceResolver, val hasNameMappings: Boolean) {
val sources: Array<Url>
get() = sourceResolver.canonicalizedSources
get() = sourceResolver.canonicalizedUrls
fun getSourceLineByRawLocation(rawLine: Int, rawColumn: Int) = mappings.get(rawLine, rawColumn)?.sourceLine ?: -1
fun findMappingList(sourceUrls: List<Url>, sourceFile: VirtualFile?, resolver: NullableLazyValue<SourceResolver.Resolver>?): MappingList? {
var mappings = sourceResolver.findMappings(sourceUrls, this, sourceFile)
if (mappings == null && resolver != null) {
val resolverValue = resolver.value
if (resolverValue != null) {
mappings = sourceResolver.findMappings(sourceFile, this, resolverValue)
}
mappings = resolver.value?.let { sourceResolver.findMappings(sourceFile, this, it) }
}
return mappings
}
@@ -27,62 +27,35 @@ import com.intellij.util.Urls
import com.intellij.util.containers.ObjectIntHashMap
import com.intellij.util.containers.isNullOrEmpty
import com.intellij.util.io.URLUtil
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy
import gnu.trove.TObjectIntHashMap
import org.jetbrains.io.LocalFileFinder
import java.io.File
open class SourceResolver(private val rawSources: List<String>, trimFileScheme: Boolean, baseFileUrl: Url?, private val sourceContents: List<String>?, baseUrlIsFile: Boolean = true) {
private val canonicalizedSourcesMap: ObjectIntHashMap<Url> = if (SystemInfo.isFileSystemCaseSensitive) ObjectIntHashMap(rawSources.size) else ObjectIntHashMap(rawSources.size, Urls.getCaseInsensitiveUrlHashingStrategy())
inline fun SourceResolver(rawSources: List<String>, sourceContents: List<String>?, urlCanonicalizer: (String) -> Url): SourceResolver {
return SourceResolver(rawSources, Array(rawSources.size) { urlCanonicalizer(rawSources[it]) }, sourceContents)
}
internal val canonicalizedSources = Array(rawSources.size) { i ->
val rawSource = rawSources[i]
val url = canonicalizeUrl(rawSource, baseFileUrl, trimFileScheme, i, baseUrlIsFile)
canonicalizedSourcesMap.put(url, i)
url
fun SourceResolver(rawSources: List<String>,
trimFileScheme: Boolean,
baseFileUrl: Url?, sourceContents: List<String>?,
baseUrlIsFile: Boolean = true): SourceResolver {
return SourceResolver(rawSources, sourceContents) { canonicalizeUrl(it, baseFileUrl, trimFileScheme, baseUrlIsFile) }
}
class SourceResolver(private val rawSources: List<String>, internal val canonicalizedUrls: Array<Url>, private val sourceContents: List<String>?) {
private val canonicalizedUrlToSourceIndex: ObjectIntHashMap<Url> = if (SystemInfo.isFileSystemCaseSensitive) ObjectIntHashMap(rawSources.size) else ObjectIntHashMap(rawSources.size, Urls.getCaseInsensitiveUrlHashingStrategy())
init {
for (i in rawSources.indices) {
canonicalizedUrlToSourceIndex.put(canonicalizedUrls[i], i)
}
}
private var absoluteLocalPathToSourceIndex: TObjectIntHashMap<String>? = null
// absoluteLocalPathToSourceIndex contains canonical paths too, but this map contains only used (specified in the source map) path
private var sourceIndexToAbsoluteLocalPath: Array<String?>? = null
// see canonicalizeUri kotlin impl and https://trac.webkit.org/browser/trunk/Source/WebCore/inspector/front-end/ParsedURL.js completeURL
protected open fun canonicalizeUrl(url: String, baseUrl: Url?, trimFileScheme: Boolean, sourceIndex: Int, baseUrlIsFile: Boolean): Url {
if (trimFileScheme && url.startsWith(StandardFileSystems.FILE_PROTOCOL_PREFIX)) {
return Urls.newLocalFileUrl(FileUtil.toCanonicalPath(VfsUtilCore.toIdeaUrl(url, true).substring(StandardFileSystems.FILE_PROTOCOL_PREFIX.length), '/'))
}
else if (baseUrl == null || url.contains(URLUtil.SCHEME_SEPARATOR) || url.startsWith("data:") || url.startsWith("blob:") || url.startsWith("javascript:")) {
return Urls.parseEncoded(url) ?: UrlImpl(url)
}
val path = canonicalizePath(url, baseUrl, baseUrlIsFile)
if (baseUrl.scheme == null && baseUrl.isInLocalFileSystem) {
return Urls.newLocalFileUrl(path)
}
// browserify produces absolute path in the local filesystem
if (isAbsolute(path)) {
val file = LocalFileFinder.findFile(path)
if (file != null) {
if (absoluteLocalPathToSourceIndex == null) {
// must be linked, on iterate original path must be first
absoluteLocalPathToSourceIndex = createStringIntMap(rawSources.size)
sourceIndexToAbsoluteLocalPath = arrayOfNulls<String>(rawSources.size)
}
absoluteLocalPathToSourceIndex!!.put(path, sourceIndex)
sourceIndexToAbsoluteLocalPath!![sourceIndex] = path
val canonicalPath = file.canonicalPath
if (canonicalPath != null && canonicalPath != path) {
absoluteLocalPathToSourceIndex!!.put(canonicalPath, sourceIndex)
}
return Urls.newLocalFileUrl(path)
}
}
return UrlImpl(baseUrl.scheme, baseUrl.authority, path, null)
interface Resolver {
fun resolve(sourceFile: VirtualFile?, map: ObjectIntHashMap<Url>): Int
}
fun getSource(entry: MappingEntry): Url? {
val index = entry.source
return if (index < 0) null else canonicalizedSources[index]
return if (index < 0) null else canonicalizedUrls[index]
}
fun getSourceContent(entry: MappingEntry): String? {
@@ -101,30 +74,21 @@ open class SourceResolver(private val rawSources: List<String>, trimFileScheme:
return if (sourceIndex < 0 || sourceIndex >= sourceContents!!.size) null else sourceContents[sourceIndex]
}
fun getSourceIndex(url: Url) = ArrayUtil.indexOf(canonicalizedSources, url)
fun getSourceIndex(url: Url) = ArrayUtil.indexOf(canonicalizedUrls, url)
fun getRawSource(entry: MappingEntry): String? {
val index = entry.source
return if (index < 0) null else rawSources[index]
}
fun getLocalFilePath(entry: MappingEntry): String? {
val index = entry.source
return if (index < 0 || sourceIndexToAbsoluteLocalPath == null) null else sourceIndexToAbsoluteLocalPath!![index]
}
interface Resolver {
fun resolve(sourceFile: VirtualFile?, map: ObjectIntHashMap<Url>): Int
}
fun findMappings(sourceFile: VirtualFile?, sourceMap: SourceMap, resolver: Resolver): MappingList? {
val index = resolver.resolve(sourceFile, canonicalizedSourcesMap)
val index = resolver.resolve(sourceFile, canonicalizedUrlToSourceIndex)
return if (index < 0) null else sourceMap.sourceIndexToMappings[index]
}
fun findMappings(sourceUrls: List<Url>, sourceMap: SourceMap, sourceFile: VirtualFile?): MappingList? {
for (sourceUrl in sourceUrls) {
val index = canonicalizedSourcesMap.get(sourceUrl)
val index = canonicalizedUrlToSourceIndex.get(sourceUrl)
if (index != -1) {
return sourceMap.sourceIndexToMappings[index]
}
@@ -139,69 +103,81 @@ open class SourceResolver(private val rawSources: List<String>, trimFileScheme:
return null
}
private fun findByFile(sourceMap: SourceMap, sourceFile: VirtualFile): MappingList? {
var mappings: MappingList? = null
if (absoluteLocalPathToSourceIndex != null && sourceFile.isInLocalFileSystem) {
mappings = getMappingsBySource(sourceMap, absoluteLocalPathToSourceIndex!!.get(sourceFile.path))
if (mappings == null) {
val sourceFileCanonicalPath = sourceFile.canonicalPath
if (sourceFileCanonicalPath != null) {
mappings = getMappingsBySource(sourceMap, absoluteLocalPathToSourceIndex!!.get(sourceFileCanonicalPath))
}
}
fun findByFile(sourceMap: SourceMap, sourceFile: VirtualFile): MappingList? {
var index = canonicalizedUrlToSourceIndex.get(Urls.newFromVirtualFile(sourceFile).trimParameters())
if (index != -1) {
return sourceMap.sourceIndexToMappings[index]
}
if (mappings == null) {
val index = canonicalizedSourcesMap.get(Urls.newFromVirtualFile(sourceFile).trimParameters())
if (sourceFile.isInLocalFileSystem) {
// local file url - without "file" scheme, just path
index = canonicalizedUrlToSourceIndex.get(Urls.newLocalFileUrl(sourceFile))
if (index != -1) {
return sourceMap.sourceIndexToMappings[index]
}
}
for (i in canonicalizedSources.indices) {
val url = canonicalizedSources[i]
if (Urls.equalsIgnoreParameters(url, sourceFile)) {
return sourceMap.sourceIndexToMappings[i]
}
val canonicalFile = sourceFile.canonicalFile
if (canonicalFile != null && canonicalFile != sourceFile && Urls.equalsIgnoreParameters(url, canonicalFile)) {
// ok, search by canonical path
val canonicalFile = sourceFile.canonicalFile
if (canonicalFile != null && canonicalFile != sourceFile) {
for (i in canonicalizedUrls.indices) {
val url = canonicalizedUrls[i]
if (Urls.equalsIgnoreParameters(url, canonicalFile)) {
return sourceMap.sourceIndexToMappings[i]
}
}
}
return mappings
return null
}
fun getLocalFilePath(entry: MappingEntry) = canonicalizedUrls.getOrNull(entry.source)?.let { if (it.isInLocalFileSystem) it.path else null }
companion object {
fun isAbsolute(path: String): Boolean {
return !path.isEmpty() && (path[0] == '/' || (SystemInfo.isWindows && (path.length > 2 && path[1] == ':')))
}
fun canonicalizePath(url: String, baseUrl: Url, baseUrlIsFile: Boolean): String {
var path = url
if (url[0] != '/') {
val basePath = baseUrl.path
if (baseUrlIsFile) {
val lastSlashIndex = basePath.lastIndexOf('/')
val pathBuilder = StringBuilder()
if (lastSlashIndex == -1) {
pathBuilder.append('/')
}
else {
pathBuilder.append(basePath, 0, lastSlashIndex + 1)
}
path = pathBuilder.append(url).toString()
}
else {
path = "$basePath/$url"
}
}
path = FileUtil.toCanonicalPath(path, '/')
return path
}
private fun getMappingsBySource(sourceMap: SourceMap, index: Int) = if (index == -1) null else sourceMap.sourceIndexToMappings[index]
fun isAbsolute(path: String) = path.firstOrNull() == '/' || (SystemInfo.isWindows && (path.length > 2 && path[1] == ':'))
}
}
private fun createStringIntMap(initialCapacity: Int) = if (SystemInfo.isFileSystemCaseSensitive) ObjectIntHashMap<String>(initialCapacity) else ObjectIntHashMap(initialCapacity, CaseInsensitiveStringHashingStrategy.INSTANCE)
fun canonicalizePath(url: String, baseUrl: Url, baseUrlIsFile: Boolean): String {
var path = url
if (url[0] != '/') {
val basePath = baseUrl.path
if (baseUrlIsFile) {
val lastSlashIndex = basePath.lastIndexOf('/')
val pathBuilder = StringBuilder()
if (lastSlashIndex == -1) {
pathBuilder.append('/')
}
else {
pathBuilder.append(basePath, 0, lastSlashIndex + 1)
}
path = pathBuilder.append(url).toString()
}
else {
path = "$basePath/$url"
}
}
return FileUtil.toCanonicalPath(path, '/')
}
// see canonicalizeUri kotlin impl and https://trac.webkit.org/browser/trunk/Source/WebCore/inspector/front-end/ParsedURL.js completeURL
fun canonicalizeUrl(url: String, baseUrl: Url?, trimFileScheme: Boolean, baseUrlIsFile: Boolean = true): Url {
if (trimFileScheme && url.startsWith(StandardFileSystems.FILE_PROTOCOL_PREFIX)) {
return Urls.newLocalFileUrl(FileUtil.toCanonicalPath(VfsUtilCore.toIdeaUrl(url, true).substring(StandardFileSystems.FILE_PROTOCOL_PREFIX.length), '/'))
}
else if (baseUrl == null || url.contains(URLUtil.SCHEME_SEPARATOR) || url.startsWith("data:") || url.startsWith("blob:") || url.startsWith("javascript:")) {
return Urls.parseEncoded(url) ?: UrlImpl(url)
}
else {
return doCanonicalize(url, baseUrl, baseUrlIsFile, true)
}
}
fun doCanonicalize(url: String, baseUrl: Url, baseUrlIsFile: Boolean, asLocalFileIfAbsoluteAndExists: Boolean): Url {
val path = canonicalizePath(url, baseUrl, baseUrlIsFile)
if ((baseUrl.scheme == null && baseUrl.isInLocalFileSystem) || (asLocalFileIfAbsoluteAndExists && SourceResolver.isAbsolute(path) && File(path).exists())) {
return Urls.newLocalFileUrl(path)
}
else {
return UrlImpl(baseUrl.scheme, baseUrl.authority, path, null)
}
}
@@ -35,50 +35,48 @@ import java.net.InetSocketAddress
import java.util.concurrent.atomic.AtomicReference
abstract class RemoteVmConnection : VmConnection<Vm>() {
private val connectCancelHandler = AtomicReference<Runnable>()
private val connectCancelHandler = AtomicReference<() -> Unit>()
abstract fun createBootstrap(address: InetSocketAddress, vmResult: org.jetbrains.concurrency.AsyncPromise<Vm>): Bootstrap
@JvmOverloads
fun open(address: InetSocketAddress, stopCondition: Condition<Void>? = null) {
setState(ConnectionStatus.WAITING_FOR_CONNECTION, "Connecting to ${address.hostName}:${address.port}")
val future = ApplicationManager.getApplication().executeOnPooledThread(object : Runnable {
override fun run() {
if (Thread.interrupted()) {
return
}
val result = org.jetbrains.concurrency.AsyncPromise<Vm>()
connectCancelHandler.set(Runnable { result.setError("Closed explicitly") })
val connectionPromise = AsyncPromise<Any?>()
connectionPromise.rejected { result.setError(it) }
result
.done {
vm = it
setState(ConnectionStatus.CONNECTED, "Connected to ${connectedAddressToPresentation(address, it)}")
startProcessing()
}
.rejected {
if (it !is ConnectException) {
Promise.logError(LOG, it)
}
setState(ConnectionStatus.CONNECTION_FAILED, it.message)
}
.processed { connectCancelHandler.set(null) }
createBootstrap(address, result).connect(address, connectionPromise, maxAttemptCount = if (stopCondition == null) NettyUtil.DEFAULT_CONNECT_ATTEMPT_COUNT else -1, stopCondition = stopCondition)
val future = ApplicationManager.getApplication().executeOnPooledThread(Runnable {
if (Thread.interrupted()) {
return@Runnable
}
val result = org.jetbrains.concurrency.AsyncPromise<Vm>()
connectCancelHandler.set({ result.setError("Closed explicitly") })
val connectionPromise = AsyncPromise<Any?>()
connectionPromise.rejected { result.setError(it) }
result
.done {
vm = it
setState(ConnectionStatus.CONNECTED, "Connected to ${connectedAddressToPresentation(address, it)}")
startProcessing()
}
.rejected {
if (it !is ConnectException) {
Promise.logError(LOG, it)
}
setState(ConnectionStatus.CONNECTION_FAILED, it.message)
}
.processed { connectCancelHandler.set(null) }
createBootstrap(address, result).connect(address, connectionPromise, maxAttemptCount = if (stopCondition == null) NettyUtil.DEFAULT_CONNECT_ATTEMPT_COUNT else -1, stopCondition = stopCondition)
})
connectCancelHandler.set(Runnable { future.cancel(true) })
connectCancelHandler.set({ future.cancel(true) })
}
protected open fun connectedAddressToPresentation(address: InetSocketAddress, vm: Vm): String = address.hostName + ":" + address.port
protected open fun connectedAddressToPresentation(address: InetSocketAddress, vm: Vm): String = "${address.hostName}:${address.port}"
override fun detachAndClose(): Promise<*> {
try {
connectCancelHandler.getAndSet(null)?.run()
connectCancelHandler.getAndSet(null)?.invoke()
}
finally {
return super.detachAndClose()
@@ -86,7 +84,7 @@ abstract class RemoteVmConnection : VmConnection<Vm>() {
}
}
fun <T> chooseDebuggee(targets: Collection<T>, selectedIndex: Int, itemToString: (T) -> String): org.jetbrains.concurrency.Promise<T> {
fun <T> chooseDebuggee(targets: Collection<T>, selectedIndex: Int, itemToString: (T) -> String): Promise<T> {
if (targets.size == 1) {
return resolvedPromise(targets.first())
}