diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspectionBase.java index 5ab01c3ce6f6..55ddb1fdd1c8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/sillyAssignment/SillyAssignmentInspectionBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -124,13 +125,20 @@ public class SillyAssignmentInspectionBase extends BaseJavaBatchLocalInspectionT private static PsiExpression deparenthesizeRExpr(PsiExpression rExpression, PsiVariable variable) { rExpression = PsiUtil.skipParenthesizedExprDown(rExpression); if (rExpression instanceof PsiTypeCastExpression) { - final PsiTypeElement castTypeElement = ((PsiTypeCastExpression)rExpression).getCastType(); - if (castTypeElement != null && - castTypeElement.getType() instanceof PsiPrimitiveType && - variable.getType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { - return rExpression; + final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)rExpression; + final PsiExpression operand = typeCastExpression.getOperand(); + final PsiTypeElement castTypeElement = typeCastExpression.getCastType(); + if (castTypeElement == null || operand == null) return null; + final PsiType castType = castTypeElement.getType(); + if (castType instanceof PsiPrimitiveType) { + if (variable.getType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { + return rExpression; + } + else if (TypeUtils.isNarrowingConversion(operand.getType(), castType)) { + return null; + } } - return PsiUtil.deparenthesizeExpression(rExpression); + return deparenthesizeRExpr(operand, variable); } return rExpression; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java index 44cd9f7dc587..ed5e8bdfe101 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ConvertSwitchToIfIntention.java @@ -24,6 +24,7 @@ import com.intellij.psi.controlFlow.*; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.psiutils.ParenthesesUtils; import org.jetbrains.annotations.NonNls; @@ -80,7 +81,7 @@ public class ConvertSwitchToIfIntention implements IntentionAction { if (switchExpression == null) { return; } - final PsiType switchExpressionType = switchExpression.getType(); + final PsiType switchExpressionType = RefactoringUtil.getTypeByExpressionWithExpectedType(switchExpression); if (switchExpressionType == null) { return; } @@ -110,10 +111,7 @@ public class ConvertSwitchToIfIntention implements IntentionAction { "i", switchExpression, true); } expressionText = variableName; - declarationString = - switchExpressionType.getPresentableText() + ' ' + - variableName + " = " + - switchExpression.getText() + ';'; + declarationString = switchExpressionType.getCanonicalText() + ' ' + variableName + " = " + switchExpression.getText() + ';'; } else { hadSideEffects = false; @@ -334,7 +332,7 @@ public class ConvertSwitchToIfIntention implements IntentionAction { for (PsiLocalVariable variable : variables) { if (ReferencesSearch.search(variable, new LocalSearchScope(bodyStatements.toArray(new PsiElement[bodyStatements.size()]))).findFirst() != null) { final PsiType varType = variable.getType(); - ifStatementString.append(varType.getPresentableText()); + ifStatementString.append(varType.getCanonicalText()); ifStatementString.append(' '); ifStatementString.append(variable.getName()); ifStatementString.append(';'); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SillyAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SillyAssignment.java index feb81d8e0499..512efd3e1b0b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SillyAssignment.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SillyAssignment.java @@ -37,4 +37,9 @@ class a { void cf2(a aa) { aa.f = f; } + + void m() { + double m = 1.5; + m = (double) (int) m; + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertSwitchToIf/after5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertSwitchToIf/after5.java new file mode 100644 index 000000000000..d6a0fb4d8e88 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertSwitchToIf/after5.java @@ -0,0 +1,9 @@ +// "Replace 'switch' with 'if'" "true" +class Test { + void foo(Object e) { + Class i = e.getClass(); + if (i.equals(RuntimeException.class)) { + } else if (i.equals(IOException.class)) { + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertSwitchToIf/before5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertSwitchToIf/before5.java new file mode 100644 index 000000000000..669464e71dbd --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/convertSwitchToIf/before5.java @@ -0,0 +1,11 @@ +// "Replace 'switch' with 'if'" "true" +class Test { + void foo(Object e) { + switch(e.getClass()) { + case RuntimeException.class: + break; + case IOException.class: + break; + } + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java index 69c5183b5271..69ee66e83a12 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java @@ -370,7 +370,8 @@ public final class NavigationUtil { //noinspection ConstantConditions return ((GotoRelatedItem)value).getCustomName(); } - final PsiElement element = (PsiElement)value; + PsiElement element = (PsiElement)value; + if (!element.isValid()) return "INVALID"; return renderer.getElementText(element) + " " + renderer.getContainerText(element, null); } diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java index 0d2fe9a19642..6a35377e6d52 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -101,6 +101,9 @@ public class ProjectUtil { if (virtualFile == null) return null; virtualFile.refresh(false, false); + Project existing = findAndFocusExistingProjectForPath(path); + if (existing != null) return existing; + ProjectOpenProcessor strong = ProjectOpenProcessor.getStrongImportProvider(virtualFile); if (strong != null) { return strong.doOpenProject(virtualFile, projectToClose, forceOpenInNewFrame); @@ -158,14 +161,10 @@ public class ProjectUtil { return null; } - Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); - for (Project project : openProjects) { - if (!project.isDefault() && isSameProject(path, project)) { - focusProjectWindow(project, false); - return project; - } - } + Project existing = findAndFocusExistingProjectForPath(path); + if (existing != null) return existing; + Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (!forceOpenInNewFrame && openProjects.length > 0) { int exitCode = confirmOpenNewProject(false); if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) { @@ -199,6 +198,18 @@ public class ProjectUtil { return project; } + @Nullable + private static Project findAndFocusExistingProjectForPath(String path) { + Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); + for (Project project : openProjects) { + if (!project.isDefault() && isSameProject(path, project)) { + focusProjectWindow(project, false); + return project; + } + } + return null; + } + /** * @return {@link com.intellij.ide.GeneralSettings#OPEN_PROJECT_SAME_WINDOW} * {@link com.intellij.ide.GeneralSettings#OPEN_PROJECT_NEW_WINDOW} @@ -233,7 +244,7 @@ public class ProjectUtil { return confirmOpenNewProject; } - private static boolean isSameProject(String path, @NotNull Project project) { + public static boolean isSameProject(String path, @NotNull Project project) { IProjectStore projectStore = (IProjectStore)ServiceKt.getStateStore(project); String toOpen = FileUtil.toSystemIndependentName(path); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java index 99f7a8542130..eb890242af2e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java @@ -31,6 +31,7 @@ import com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer; import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; import com.intellij.util.ConcurrencyUtil; +import com.intellij.util.FileContentUtilCore; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.URLUtil; @@ -431,7 +432,8 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp } else if (event instanceof VFilePropertyChangeEvent) { final VFilePropertyChangeEvent change = (VFilePropertyChangeEvent)event; - if (VirtualFile.PROP_NAME.equals(change.getPropertyName())) { + if (VirtualFile.PROP_NAME.equals(change.getPropertyName()) + && event.getRequestor() != FileContentUtilCore.FORCE_RELOAD_REQUESTOR) { VirtualFile eventFile = change.getFile(); VirtualFile parent = eventFile.getParent(); // e.g. for LightVirtualFiles addPointersUnder(parent, true, change.getNewValue().toString(), toFireEvents); diff --git a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java index 2926b4e2c683..ffd38062e8c8 100644 --- a/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java +++ b/platform/platform-impl/src/org/jetbrains/io/NettyUtil.java @@ -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) { diff --git a/platform/platform-resources/src/idea/FindViewColorsScheme.xml b/platform/platform-resources/src/idea/FindViewColorsScheme.xml index b10adf490071..bd2a0a59d860 100644 --- a/platform/platform-resources/src/idea/FindViewColorsScheme.xml +++ b/platform/platform-resources/src/idea/FindViewColorsScheme.xml @@ -1,5 +1,5 @@ - + diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMap.kt b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMap.kt index e8a128739057..80128eda7eb7 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMap.kt +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMap.kt @@ -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, val sourceResolver: SourceResolver, val hasNameMappings: Boolean) { val sources: Array - get() = sourceResolver.canonicalizedSources + get() = sourceResolver.canonicalizedUrls fun getSourceLineByRawLocation(rawLine: Int, rawColumn: Int) = mappings.get(rawLine, rawColumn)?.sourceLine ?: -1 fun findMappingList(sourceUrls: List, sourceFile: VirtualFile?, resolver: NullableLazyValue?): 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 } diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceResolver.kt b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceResolver.kt index 925c9ca00332..2edeccd99557 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceResolver.kt +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceResolver.kt @@ -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, trimFileScheme: Boolean, baseFileUrl: Url?, private val sourceContents: List?, baseUrlIsFile: Boolean = true) { - private val canonicalizedSourcesMap: ObjectIntHashMap = if (SystemInfo.isFileSystemCaseSensitive) ObjectIntHashMap(rawSources.size) else ObjectIntHashMap(rawSources.size, Urls.getCaseInsensitiveUrlHashingStrategy()) +inline fun SourceResolver(rawSources: List, sourceContents: List?, 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, + trimFileScheme: Boolean, + baseFileUrl: Url?, sourceContents: List?, + baseUrlIsFile: Boolean = true): SourceResolver { + return SourceResolver(rawSources, sourceContents) { canonicalizeUrl(it, baseFileUrl, trimFileScheme, baseUrlIsFile) } +} + +class SourceResolver(private val rawSources: List, internal val canonicalizedUrls: Array, private val sourceContents: List?) { + private val canonicalizedUrlToSourceIndex: ObjectIntHashMap = 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? = null - // absoluteLocalPathToSourceIndex contains canonical paths too, but this map contains only used (specified in the source map) path - private var sourceIndexToAbsoluteLocalPath: Array? = 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(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): 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, 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): 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, 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, 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(initialCapacity) else ObjectIntHashMap(initialCapacity, CaseInsensitiveStringHashingStrategy.INSTANCE) \ No newline at end of file +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) + } +} \ No newline at end of file diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/RemoteVmConnection.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/RemoteVmConnection.kt index 40489768ec36..81a5efbd03f2 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/RemoteVmConnection.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/RemoteVmConnection.kt @@ -35,50 +35,48 @@ import java.net.InetSocketAddress import java.util.concurrent.atomic.AtomicReference abstract class RemoteVmConnection : VmConnection() { - private val connectCancelHandler = AtomicReference() + private val connectCancelHandler = AtomicReference<() -> Unit>() abstract fun createBootstrap(address: InetSocketAddress, vmResult: org.jetbrains.concurrency.AsyncPromise): Bootstrap @JvmOverloads fun open(address: InetSocketAddress, stopCondition: Condition? = 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() - connectCancelHandler.set(Runnable { result.setError("Closed explicitly") }) - - val connectionPromise = AsyncPromise() - 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() + connectCancelHandler.set({ result.setError("Closed explicitly") }) + + val connectionPromise = AsyncPromise() + 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() { } } -fun chooseDebuggee(targets: Collection, selectedIndex: Int, itemToString: (T) -> String): org.jetbrains.concurrency.Promise { +fun chooseDebuggee(targets: Collection, selectedIndex: Int, itemToString: (T) -> String): Promise { if (targets.size == 1) { return resolvedPromise(targets.first()) } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index cc50652cbb13..7d54dd519e53 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1227,7 +1227,7 @@ implicit.numeric.conversion.ignore.widening.conversion.option=Ignore widening co implicit.numeric.conversion.ignore.char.conversion.option=Ignore conversions from and to char implicit.numeric.conversion.ignore.constant.conversion.option=Ignore conversions from constants and literals implicit.numeric.conversion.problem.descriptor=Implicit numeric conversion of #ref from ''{0}'' to ''{1}'' #loc -implicit.numeric.conversion.convert.quickfix=Convert to ''{0}'' literal +implicit.numeric.conversion.convert.quickfix=Convert to ''{0}'' implicit.numeric.conversion.make.explicit.quickfix=Make conversion explicit long.literals.ending.with.lowercase.l.replace.quickfix=Replace 'l' with 'L' non.reproducible.math.call.replace.quickfix=Replace with 'StrictMath' call diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java index cec661a0ba79..132746e2bb03 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import com.siyeh.ig.PsiReplacementUtil; import com.siyeh.ig.psiutils.ClassUtils; import com.siyeh.ig.psiutils.ExpectedTypeUtils; import com.siyeh.ig.psiutils.ParenthesesUtils; -import gnu.trove.TObjectIntHashMap; +import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,21 +39,6 @@ import javax.swing.*; public class ImplicitNumericConversionInspection extends BaseInspection { - /** - * @noinspection StaticCollection - */ - private static final gnu.trove.TObjectIntHashMap typePrecisions = new TObjectIntHashMap(7); - - static { - typePrecisions.put(PsiType.BYTE, 1); - typePrecisions.put(PsiType.CHAR, 2); - typePrecisions.put(PsiType.SHORT, 2); - typePrecisions.put(PsiType.INT, 3); - typePrecisions.put(PsiType.LONG, 4); - typePrecisions.put(PsiType.FLOAT, 5); - typePrecisions.put(PsiType.DOUBLE, 6); - } - @SuppressWarnings({"PublicField"}) public boolean ignoreWideningConversions = false; @@ -105,8 +90,9 @@ public class ImplicitNumericConversionInspection extends BaseInspection { private final String m_name; ImplicitNumericConversionFix(PsiExpression expression, PsiType expectedType) { - if (isConvertible(expression, expectedType)) { - m_name = InspectionGadgetsBundle.message("implicit.numeric.conversion.convert.quickfix", expectedType.getCanonicalText()); + final String convertedExpression = convertExpression(expression, expectedType); + if (convertedExpression != null) { + m_name = InspectionGadgetsBundle.message("implicit.numeric.conversion.convert.quickfix", convertedExpression); } else { m_name = InspectionGadgetsBundle.message("implicit.numeric.conversion.make.explicit.quickfix"); @@ -132,28 +118,28 @@ public class ImplicitNumericConversionInspection extends BaseInspection { if (expectedType == null) { return; } - if (isConvertible(expression, expectedType)) { - final String newExpression = convertExpression(expression, expectedType); - if (newExpression == null) { - return; - } - PsiReplacementUtil.replaceExpression(expression, newExpression); + final String convertedExpression = convertExpression(expression, expectedType); + if (convertedExpression != null) { + PsiReplacementUtil.replaceExpression(expression, convertedExpression); } else { - final String newExpression; + final String castExpression; if (ParenthesesUtils.getPrecedence(expression) <= ParenthesesUtils.TYPE_CAST_PRECEDENCE) { - newExpression = '(' + expectedType.getCanonicalText() + ')' + expression.getText(); + castExpression = '(' + expectedType.getCanonicalText() + ')' + expression.getText(); } else { - newExpression = '(' + expectedType.getCanonicalText() + ")(" + expression.getText() + ')'; + castExpression = '(' + expectedType.getCanonicalText() + ")(" + expression.getText() + ')'; } - PsiReplacementUtil.replaceExpression(expression, newExpression); + PsiReplacementUtil.replaceExpression(expression, castExpression); } } @Nullable @NonNls private static String convertExpression(PsiExpression expression, PsiType expectedType) { + if (!(expression instanceof PsiLiteralExpression) && !isNegatedLiteral(expression)) { + return null; + } final PsiType expressionType = expression.getType(); if (expressionType == null) { return null; @@ -192,27 +178,7 @@ public class ImplicitNumericConversionInspection extends BaseInspection { final int length = text.length(); return text.substring(0, length - 1); } - return null; //can't happen - } - - private static boolean isConvertible(PsiExpression expression, PsiType expectedType) { - if (!(expression instanceof PsiLiteralExpression) && !isNegatedLiteral(expression)) { - return false; - } - final PsiType expressionType = expression.getType(); - if (expressionType == null) { - return false; - } - if (hasLowerPrecision(expectedType, expressionType)) { - return false; - } - if (isIntegral(expressionType) && isIntegral(expectedType)) { - return true; - } - if (isIntegral(expressionType) && isFloatingPoint(expectedType)) { - return true; - } - return isFloatingPoint(expressionType) && isFloatingPoint(expectedType); + return null; } private static boolean isNegatedLiteral(PsiExpression expression) { @@ -328,7 +294,7 @@ public class ImplicitNumericConversionInspection extends BaseInspection { if (expressionType.equals(expectedType)) { return; } - if (ignoreWideningConversions && hasLowerPrecision(expressionType, expectedType)) { + if (ignoreWideningConversions && TypeUtils.isNarrowingConversion(expressionType, expectedType)) { return; } if (ignoreCharConversions && PsiType.CHAR.equals(expectedType)) { @@ -363,10 +329,4 @@ public class ImplicitNumericConversionInspection extends BaseInspection { return CommonClassNames.JAVA_LANG_STRING.equals(className); } } - - static boolean hasLowerPrecision(PsiType expressionType, PsiType expectedType) { - final int operandPrecision = typePrecisions.get(expressionType); - final int castPrecision = typePrecisions.get(expectedType); - return operandPrecision <= castPrecision; - } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java index 4cf028de2c7b..3cc581a6eaa6 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java @@ -66,10 +66,13 @@ public class TypeUtils { return getType(CommonClassNames.JAVA_LANG_STRING, context); } - public static boolean isNarrowingConversion(@NotNull PsiType operandType, @NotNull PsiType castType) { - final Integer operandPrecision = typePrecisions.get(operandType); - final Integer castPrecision = typePrecisions.get(castType); - return operandPrecision != null && castPrecision != null && operandPrecision.intValue() > castPrecision.intValue(); + /** + * JLS 5.1.3. Narrowing Primitive Conversion + */ + public static boolean isNarrowingConversion(@Nullable PsiType sourceType, @Nullable PsiType targetType) { + final Integer sourcePrecision = typePrecisions.get(sourceType); + final Integer targetPrecision = typePrecisions.get(targetType); + return sourcePrecision != null && targetPrecision != null && targetPrecision.intValue() < sourcePrecision.intValue(); } public static boolean isJavaLangObject(@Nullable PsiType targetType) { diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/CastThatLosesPrecision.html b/plugins/InspectionGadgets/src/inspectionDescriptions/CastThatLosesPrecision.html index fdb55f31fc83..3d8d0b791b5d 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/CastThatLosesPrecision.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/CastThatLosesPrecision.html @@ -1,6 +1,6 @@ -Reports any cast operations between built-in numeric types which may +Reports any cast operations between primitive numeric types which may result in loss of precision. Such casts are not necessarily a problem, but may result in difficult to trace bugs if the loss of precision is unexpected. @@ -9,7 +9,7 @@ Use the checkbox below to indicate that this inspection should ignore casts from int to char. This type of cast is often used when implementing I/O operations, because the read() method of the class -java.io.Reader returns an intl +java.io.Reader returns an int.

diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index 032e117597de..6c3b58f824e6 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -556,14 +556,17 @@ class PyDB: self._lock_running_thread_ids.acquire() try: for t in all_threads: - thread_id = GetThreadId(t) - if getattr(t, 'is_pydev_daemon_thread', False): pass # I.e.: skip the DummyThreads created from pydev daemon threads elif isinstance(t, PyDBDaemonThread): pydev_log.error_once('Error in debugger: Found PyDBDaemonThread not marked with is_pydev_daemon_thread=True.\n') elif isThreadAlive(t): + if not self._running_thread_ids: + thread_id = GetThreadId(t, True) + curr_thread_id = GetThreadId(threadingCurrentThread()) + else: + thread_id = GetThreadId(t) program_threads_alive[thread_id] = t if not DictContains(self._running_thread_ids, thread_id): diff --git a/python/helpers/pydev/pydevd_constants.py b/python/helpers/pydev/pydevd_constants.py index f3281071b0f1..b7960c13d836 100644 --- a/python/helpers/pydev/pydevd_constants.py +++ b/python/helpers/pydev/pydevd_constants.py @@ -195,29 +195,38 @@ class NextId: _nextThreadId = NextId() + +#======================================================================================================================= +# GetPid +#======================================================================================================================= +def GetPid(): + try: + return os.getpid() + except AttributeError: + try: + #Jython does not have it! + import java.lang.management.ManagementFactory #@UnresolvedImport -- just for jython + pid = java.lang.management.ManagementFactory.getRuntimeMXBean().getName() + return pid.replace('@', '_') + except: + #ok, no pid available (will be unable to debug multiple processes) + return '000001' + + #======================================================================================================================= # GetThreadId #======================================================================================================================= -def GetThreadId(thread): +def GetThreadId(thread, update_pydevd_id=False): try: + if update_pydevd_id: + del thread.__pydevd_id__ return thread.__pydevd_id__ except AttributeError: _nextThreadIdLock.acquire() try: #We do a new check with the lock in place just to be sure that nothing changed if not hasattr(thread, '__pydevd_id__'): - try: - pid = os.getpid() - except AttributeError: - try: - #Jython does not have it! - import java.lang.management.ManagementFactory #@UnresolvedImport -- just for jython - pid = java.lang.management.ManagementFactory.getRuntimeMXBean().getName() - pid = pid.replace('@', '_') - except: - #ok, no pid available (will be unable to debug multiple processes) - pid = '000001' - + pid = GetPid() thread.__pydevd_id__ = 'pid%s_seq%s' % (pid, _nextThreadId()) finally: _nextThreadIdLock.release()