getExtraRangesToFormat(@NotNull FormattingRangesInfo info) {
+ int startOffset = getTextRange().getStartOffset();
+ if (info.isOnInsertedLine(startOffset) && myNode.getTextLength() == 1 && myNode.textContains('}')) {
+ ASTNode parent = myNode.getTreeParent();
+ return new NodeIndentRangesCalculator(parent).calculateExtraRanges();
+ }
+ return null;
+ }
+
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java b/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java
index 82f99be64274..c86d0792906b 100644
--- a/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java
+++ b/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java
@@ -24,10 +24,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.psi.PsiElement;
import org.intellij.lang.regexp.DefaultRegExpPropertiesProvider;
import org.intellij.lang.regexp.RegExpLanguageHost;
-import org.intellij.lang.regexp.psi.RegExpChar;
-import org.intellij.lang.regexp.psi.RegExpGroup;
-import org.intellij.lang.regexp.psi.RegExpNamedGroupRef;
-import org.intellij.lang.regexp.psi.RegExpSimpleClass;
+import org.intellij.lang.regexp.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -94,6 +91,24 @@ public class JavaRegExpHost implements RegExpLanguageHost {
return hasAtLeastJdkVersion(regExpChar, JavaSdkVersion.JDK_1_7);
}
+ @Override
+ public boolean supportsBoundary(RegExpBoundary boundary) {
+ switch (boundary.getType()) {
+ case UNICODE_EXTENDED_GRAPHEME:
+ return hasAtLeastJdkVersion(boundary, JavaSdkVersion.JDK_1_9);
+ case LINE_START:
+ case LINE_END:
+ case WORD:
+ case NON_WORD:
+ case BEGIN:
+ case END:
+ case END_NO_LINE_TERM:
+ case PREVIOUS_MATCH:
+ default:
+ return true;
+ }
+ }
+
@Override
public boolean supportsSimpleClass(RegExpSimpleClass simpleClass) {
switch(simpleClass.getKind()) {
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/FormatWithContextTest.kt b/java/java-tests/testSrc/com/intellij/psi/formatter/java/FormatWithContextTest.kt
index 9eae257769a9..ea46a45738cd 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/FormatWithContextTest.kt
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/FormatWithContextTest.kt
@@ -114,7 +114,7 @@ class X {
}
- fun `ignore test inserted closing brace`() {
+ fun `test inserted closing brace`() {
myLineRange = TextRange(6, 6)
check(
"""
diff --git a/lib/jna-platform.jar b/lib/jna-platform.jar
index c01edecd6717..f3a9fd2b2294 100644
Binary files a/lib/jna-platform.jar and b/lib/jna-platform.jar differ
diff --git a/lib/jna.jar b/lib/jna.jar
index da2ffe17b67d..a943670981d8 100644
Binary files a/lib/jna.jar and b/lib/jna.jar differ
diff --git a/lib/src/jna-platform.zip b/lib/src/jna-platform.zip
index 21ebc8e1acca..9fc9f0ca4b73 100644
Binary files a/lib/src/jna-platform.zip and b/lib/src/jna-platform.zip differ
diff --git a/lib/src/jna.zip b/lib/src/jna.zip
index df0617bf9cf1..b09a18be654e 100644
Binary files a/lib/src/jna.zip and b/lib/src/jna.zip differ
diff --git a/platform/annotations/common/src/org/jetbrains/annotations/Contract.java b/platform/annotations/common/src/org/jetbrains/annotations/Contract.java
index 003d541746a2..361a95ba130d 100644
--- a/platform/annotations/common/src/org/jetbrains/annotations/Contract.java
+++ b/platform/annotations/common/src/org/jetbrains/annotations/Contract.java
@@ -26,7 +26,7 @@ import java.lang.annotation.*;
* clause ::= args '->' effect
* args ::= ((arg ',')* arg )?
* arg ::= value-constraint
- * value-constraint ::= 'any' | 'null' | '!null' | 'false' | 'true'
+ * value-constraint ::= '_' | 'null' | '!null' | 'false' | 'true'
* effect ::= value-constraint | 'fail'
*
* The constraints denote the following:
diff --git a/platform/core-api/core-api.iml b/platform/core-api/core-api.iml
index 0877129ba99f..b56ccffb06aa 100644
--- a/platform/core-api/core-api.iml
+++ b/platform/core-api/core-api.iml
@@ -14,15 +14,7 @@
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/platform/core-api/src/com/intellij/lexer/FlexAdapter.java b/platform/core-api/src/com/intellij/lexer/FlexAdapter.java
index c8b5b90688ea..e57d2b3f188b 100644
--- a/platform/core-api/src/com/intellij/lexer/FlexAdapter.java
+++ b/platform/core-api/src/com/intellij/lexer/FlexAdapter.java
@@ -18,6 +18,7 @@ package com.intellij.lexer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
+import com.intellij.util.SystemProperties;
import org.jetbrains.annotations.NotNull;
/**
@@ -26,6 +27,7 @@ import org.jetbrains.annotations.NotNull;
public class FlexAdapter extends LexerBase {
private static final Logger LOG = Logger.getInstance(FlexAdapter.class);
+ private static final boolean logLexerErrors = SystemProperties.getBooleanProperty("log.flex.adapter.errors", true); // Used by Upsource
private final FlexLexer myFlex;
@@ -105,13 +107,17 @@ public class FlexAdapter extends LexerBase {
myTokenType = myFlex.advance();
myTokenEnd = myFlex.getTokenEnd();
}
- catch (Exception e) {
- LOG.error(myFlex.getClass().getName(), e);
+ catch (Exception e) {
+ if (logLexerErrors) {
+ LOG.error(myFlex.getClass().getName(), e);
+ }
myTokenType = TokenType.WHITE_SPACE;
myTokenEnd = myBufferEnd;
}
catch (Error e) {
- LOG.error(myFlex.getClass().getName(), e);
+ if (logLexerErrors) {
+ LOG.error(myFlex.getClass().getName(), e);
+ }
myTokenType = TokenType.WHITE_SPACE;
myTokenEnd = myBufferEnd;
}
diff --git a/platform/credential-store/src/FileCredentialStore.kt b/platform/credential-store/src/FileCredentialStore.kt
index 31549209f850..4ce3dac4440a 100644
--- a/platform/credential-store/src/FileCredentialStore.kt
+++ b/platform/credential-store/src/FileCredentialStore.kt
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe
+package com.intellij.credentialStore
+import com.intellij.ide.passwordSafe.PasswordStorage
import com.intellij.ide.passwordSafe.impl.providers.masterKey.windows.WindowsCryptUtils
import com.intellij.openapi.application.PathManager
-import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream
import com.intellij.openapi.util.io.setOwnerPermissions
@@ -29,15 +29,19 @@ import java.nio.file.NoSuchFileException
import java.nio.file.Path
import java.nio.file.Paths
import java.security.Key
-import java.security.MessageDigest
-import java.security.SecureRandom
import java.util.Base64
import java.util.concurrent.atomic.AtomicBoolean
import javax.crypto.spec.SecretKeySpec
-internal val LOG = Logger.getInstance(FileCredentialStore::class.java)
+class FileCredentialStore(keyToValue: Map? = null, baseDirectory: Path = Paths.get(PathManager.getConfigPath()), var memoryOnly: Boolean = false) : PasswordStorage, CredentialStore {
+ override fun get(key: String) = getPassword(null, key)
+
+ override fun set(key: String, password: ByteArray?) {
+ val string = password?.toString(Charsets.UTF_8)
+ password?.fill(0)
+ setPassword(key, string)
+ }
-class FileCredentialStore(keyToValue: Map? = null, baseDirectory: Path = Paths.get(PathManager.getConfigPath()), var memoryOnly: Boolean = false) : PasswordStorage {
private val db = ContainerUtil.newConcurrentMap()
private val dbFile = baseDirectory.resolve("pdb")
@@ -132,10 +136,10 @@ class FileCredentialStore(keyToValue: Map? = null, baseDirectory
override fun getPassword(requestor: Class<*>?, key: String): String? {
val rawKey = getRawKey(key, requestor)
- // try old key - as hash
var value = db.get(rawKey)
- if (value == null) {
- value = db.remove(toOldKey(MessageDigest.getInstance("SHA-256").digest(rawKey.toByteArray())))
+ if (value == null && (requestor != null || key.contains('/'))) {
+ // try old key - as hash
+ value = db.remove(toOldKey(rawKey))
if (value != null) {
db.put(rawKey, value)
needToSave.set(true)
@@ -163,16 +167,6 @@ class FileCredentialStore(keyToValue: Map? = null, baseDirectory
}
}
-internal fun getRawKey(key: String, requestor: Class<*>?) = if (requestor == null) key else "${requestor.name}/$key"
-
-internal fun toOldKey(hash: ByteArray) = "old-hashed-key|" + Base64.getEncoder().encodeToString(hash)
-
-internal fun generate(): ByteArray {
- val bytes = ByteArray(16)
- SecureRandom().nextBytes(bytes)
- return bytes
-}
-
interface MasterKeyStorage {
fun get(): ByteArray?
diff --git a/platform/credential-store/src/MacOsCredentialStore.kt b/platform/credential-store/src/MacOsCredentialStore.kt
deleted file mode 100644
index 6eb22ed36c93..000000000000
--- a/platform/credential-store/src/MacOsCredentialStore.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2000-2016 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 com.intellij.ide.passwordSafe
-
-import com.intellij.ide.passwordSafe.macOs.deleteGenericPassword
-import com.intellij.ide.passwordSafe.macOs.findGenericPassword
-import com.intellij.ide.passwordSafe.macOs.isMacOsCredentialStoreSupported
-import com.intellij.ide.passwordSafe.macOs.saveGenericPassword
-import com.intellij.openapi.diagnostic.catchAndLog
-import com.intellij.util.SystemProperties
-import java.security.MessageDigest
-
-private class MacOsCredentialStore(serviceName: String) : PasswordStorage {
- private val serviceName = serviceName.toByteArray()
-
- override fun getPassword(requestor: Class<*>?, key: String): String? {
- val rawKey = getRawKey(key, requestor)
- // try old key - as hash
- @Suppress("CanBeVal")
- var value: String?
- try {
- value = findGenericPassword(serviceName, rawKey)
- }
- catch (e: Throwable) {
- LOG.error(e)
- return null
- }
-
- if (value == null) {
- LOG.catchAndLog {
- val oldKey = toOldKey(MessageDigest.getInstance("SHA-256").digest(rawKey.toByteArray()))
- value = findGenericPassword(serviceName, oldKey)
- if (value != null) {
- LOG.catchAndLog { deleteGenericPassword(serviceName, oldKey) }
- saveGenericPassword(serviceName, key, value!!)
- }
- }
- }
- return value
- }
-
- override fun setPassword(requestor: Class<*>?, key: String, value: String?) {
- LOG.catchAndLog {
- val rawKey = getRawKey(key, requestor)
- if (value == null) {
- deleteGenericPassword(serviceName, rawKey)
- }
- else {
- saveGenericPassword(serviceName, rawKey, value)
- }
- }
- }
-}
-
-private class MacOsCredentialStoreFactory : CredentialStoreFactory {
- override fun create(): PasswordStorage? {
- if (isMacOsCredentialStoreSupported && SystemProperties.getBooleanProperty("use.mac.keychain", true)) {
- return MacOsCredentialStore("IntelliJ Platform")
- }
- return null
- }
-}
\ No newline at end of file
diff --git a/platform/credential-store/src/PasswordSafeConfigurable.kt b/platform/credential-store/src/PasswordSafeConfigurable.kt
index c75ad7197708..6fcf8afb4dfd 100644
--- a/platform/credential-store/src/PasswordSafeConfigurable.kt
+++ b/platform/credential-store/src/PasswordSafeConfigurable.kt
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe.config
+package com.intellij.credentialStore
+import com.intellij.credentialStore.PasswordSafeSettings.ProviderType
import com.intellij.ide.passwordSafe.PasswordSafe
-import com.intellij.ide.passwordSafe.config.PasswordSafeSettings.ProviderType
import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl
import com.intellij.layout.*
import com.intellij.layout.CCFlags.*
diff --git a/platform/credential-store/src/PasswordSafeImpl.kt b/platform/credential-store/src/PasswordSafeImpl.kt
index 977164bd5fe8..a40a4ec7d91d 100644
--- a/platform/credential-store/src/PasswordSafeImpl.kt
+++ b/platform/credential-store/src/PasswordSafeImpl.kt
@@ -15,10 +15,13 @@
*/
package com.intellij.ide.passwordSafe.impl
-import com.intellij.ide.passwordSafe.*
-import com.intellij.ide.passwordSafe.config.PasswordSafeSettings
-import com.intellij.ide.passwordSafe.config.PasswordSafeSettings.ProviderType
-import com.intellij.ide.passwordSafe.config.PasswordSafeSettingsListener
+import com.intellij.credentialStore.FileCredentialStore
+import com.intellij.credentialStore.LOG
+import com.intellij.credentialStore.PasswordSafeSettings
+import com.intellij.credentialStore.PasswordSafeSettings.ProviderType
+import com.intellij.credentialStore.PasswordSafeSettingsListener
+import com.intellij.ide.passwordSafe.PasswordSafe
+import com.intellij.ide.passwordSafe.PasswordStorage
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ex.ApplicationInfoEx
import com.intellij.openapi.components.SettingsSavingComponent
@@ -126,7 +129,7 @@ class PasswordSafeImpl(/* public - backward compatibility */val settings: Passwo
private fun createPersistentCredentialStore(existing: FileCredentialStore? = null, convertFileStore: Boolean = false): PasswordStorage {
LOG.catchAndLog {
- for (factory in CredentialStoreFactory.CREDENTIAL_STORE_FACTORY.extensions) {
+ for (factory in com.intellij.credentialStore.CredentialStoreFactory.CREDENTIAL_STORE_FACTORY.extensions) {
val store = factory.create() ?: continue
if (convertFileStore) {
LOG.catchAndLog {
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/CredentialStoreFactory.java b/platform/credential-store/src/com/intellij/credentialStore/CredentialStoreFactory.java
similarity index 90%
rename from platform/platform-impl/src/com/intellij/ide/passwordSafe/CredentialStoreFactory.java
rename to platform/credential-store/src/com/intellij/credentialStore/CredentialStoreFactory.java
index 58a76ab90949..b9cc5a0e85a2 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/CredentialStoreFactory.java
+++ b/platform/credential-store/src/com/intellij/credentialStore/CredentialStoreFactory.java
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe;
+package com.intellij.credentialStore;
+import com.intellij.ide.passwordSafe.PasswordStorage;
import com.intellij.openapi.extensions.ExtensionPointName;
import org.jetbrains.annotations.Nullable;
diff --git a/platform/credential-store/src/com/intellij/ide/passwordSafe/config/PasswordSafeSettings.java b/platform/credential-store/src/com/intellij/credentialStore/PasswordSafeSettings.java
similarity index 98%
rename from platform/credential-store/src/com/intellij/ide/passwordSafe/config/PasswordSafeSettings.java
rename to platform/credential-store/src/com/intellij/credentialStore/PasswordSafeSettings.java
index 946ccb3388a9..080f8429ff57 100644
--- a/platform/credential-store/src/com/intellij/ide/passwordSafe/config/PasswordSafeSettings.java
+++ b/platform/credential-store/src/com/intellij/credentialStore/PasswordSafeSettings.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe.config;
+package com.intellij.credentialStore;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
diff --git a/platform/credential-store/src/credentialStore.kt b/platform/credential-store/src/credentialStore.kt
new file mode 100644
index 000000000000..470d4b54724d
--- /dev/null
+++ b/platform/credential-store/src/credentialStore.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.credentialStore
+
+import com.intellij.openapi.diagnostic.Logger
+import java.security.MessageDigest
+import java.util.*
+
+internal val LOG = Logger.getInstance(CredentialStore::class.java)
+
+internal interface CredentialStore {
+ fun get(key: String): String?
+
+ // passed byte array will be cleared
+ fun set(key: String, password: ByteArray?)
+}
+
+internal fun getRawKey(key: String, requestor: Class<*>?) = if (requestor == null) key else "${requestor.name}/$key"
+
+internal fun toOldKey(hash: ByteArray) = "old-hashed-key|" + Base64.getEncoder().encodeToString(hash)
+
+internal fun toOldKey(newKey: String) = toOldKey(MessageDigest.getInstance("SHA-256").digest(newKey.toByteArray()))
\ No newline at end of file
diff --git a/platform/credential-store/src/dbV1Convertor.kt b/platform/credential-store/src/dbV1Convertor.kt
index 6503ffecd35b..fc7ee0d33f10 100644
--- a/platform/credential-store/src/dbV1Convertor.kt
+++ b/platform/credential-store/src/dbV1Convertor.kt
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe
+package com.intellij.credentialStore
import com.intellij.ide.ApplicationLoadListener
-import com.intellij.ide.passwordSafe.config.PasswordSafeSettings
import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper
import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil
import com.intellij.ide.passwordSafe.impl.providers.masterKey.EnterPasswordComponent
diff --git a/platform/credential-store/src/libraries/linuxSecretLibrary.kt b/platform/credential-store/src/libraries/linuxSecretLibrary.kt
new file mode 100644
index 000000000000..e1cb25a67186
--- /dev/null
+++ b/platform/credential-store/src/libraries/linuxSecretLibrary.kt
@@ -0,0 +1,91 @@
+package com.intellij.credentialStore.linux
+
+import com.intellij.credentialStore.CredentialStore
+import com.intellij.credentialStore.LOG
+import com.intellij.jna.DisposableMemory
+import com.sun.jna.Library
+import com.sun.jna.Native
+import com.sun.jna.Pointer
+
+private val LIBRARY by lazy { Native.loadLibrary("secret-1", SecretLibrary::class.java) as SecretLibrary }
+
+private const val SECRET_SCHEMA_NONE = 0
+private const val SECRET_SCHEMA_ATTRIBUTE_STRING = 0
+
+// explicitly create pointer to be explicitly dispose it to avoid sensitive data in the memory
+internal fun stringPointer(data: ByteArray): DisposableMemory {
+ val pointer = DisposableMemory(data.size + 1L)
+ pointer.write(0, data, 0, data.size)
+ pointer.setByte(data.size.toLong(), 0.toByte())
+ return pointer
+}
+
+// we use default collection, it seems no way to use custom
+internal class SecretCredentialStore(schemeName: String) : CredentialStore {
+ private val keyAttributeNamePointer by lazy { stringPointer("key".toByteArray()) }
+ private val scheme by lazy { LIBRARY.secret_schema_new(schemeName, SECRET_SCHEMA_NONE, keyAttributeNamePointer, SECRET_SCHEMA_ATTRIBUTE_STRING, null) }
+
+ override fun get(key: String): String? {
+ val keyPointer = stringPointer(key.toByteArray())
+ return checkError("secret_password_lookup_sync") { errorRef ->
+ LIBRARY.secret_password_lookup_sync(scheme, null, errorRef, keyAttributeNamePointer, keyPointer, null)
+ }
+ }
+
+ override fun set(key: String, password: ByteArray?) {
+ val keyPointer = stringPointer(key.toByteArray())
+
+ if (password == null) {
+ checkError("secret_password_store_sync") { errorRef ->
+ LIBRARY.secret_password_clear_sync(scheme, null, errorRef, keyAttributeNamePointer, keyPointer, null)
+ }
+ return
+ }
+
+ val passwordPointer = stringPointer(password)
+ password.fill(0)
+
+ checkError("secret_password_store_sync") { errorRef ->
+ try {
+ LIBRARY.secret_password_store_sync(scheme, null, keyPointer, passwordPointer, null, errorRef, keyAttributeNamePointer, keyPointer, null)
+ }
+ finally {
+ passwordPointer.dispose()
+ keyPointer.dispose()
+ }
+ }
+ }
+}
+
+private inline fun checkError(method: String, task: (errorRef: Array) -> T): T {
+ val errorRef = arrayOf(null)
+ val result = task(errorRef)
+ val error = errorRef.get(0)
+ if (error != null && error.code !== 0) {
+ LOG.error("$method error code ${error.code}, error message ${error.message}")
+ }
+ return result
+}
+
+// we use sync API to simplify - client will use postponed write
+private interface SecretLibrary : Library {
+ fun secret_schema_new(name: String, flags: Int, vararg attributes: Any?): Pointer
+
+ fun secret_password_store_sync(scheme: Pointer, collection: Pointer?, label: Pointer, password: Pointer, cancellable: Pointer?, error: Array, vararg attributes: Pointer?)
+
+ fun secret_password_lookup_sync(scheme: Pointer, cancellable: Pointer?, error: Array, vararg attributes: Pointer?): String
+
+ fun secret_password_clear_sync(scheme: Pointer, cancellable: Pointer?, error: Array, vararg attributes: Pointer?)
+}
+
+@Suppress("unused")
+class GErrorStruct : com.sun.jna.Structure() {
+ @JvmField
+ var domain = 0
+ @JvmField
+ var code = 0
+ @JvmField
+ var message: String? = null
+
+ override fun getFieldOrder() = listOf("domain", "code", "message")
+}
\ No newline at end of file
diff --git a/platform/credential-store/src/macOsKeychainLibrary.kt b/platform/credential-store/src/libraries/macOsKeychainLibrary.kt
similarity index 66%
rename from platform/credential-store/src/macOsKeychainLibrary.kt
rename to platform/credential-store/src/libraries/macOsKeychainLibrary.kt
index c6d7a7047a91..11df303e0df3 100644
--- a/platform/credential-store/src/macOsKeychainLibrary.kt
+++ b/platform/credential-store/src/libraries/macOsKeychainLibrary.kt
@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe.macOs
+package com.intellij.credentialStore.macOs
-import com.intellij.ide.passwordSafe.LOG
+import com.intellij.credentialStore.CredentialStore
+import com.intellij.credentialStore.LOG
import com.intellij.openapi.util.SystemInfo
+import com.sun.jna.Library
import com.sun.jna.Native
import com.sun.jna.Pointer
@@ -27,12 +29,25 @@ private val LIBRARY by lazy {
Native.loadLibrary("Security", MacOsKeychainLibrary::class.java) as MacOsKeychainLibrary
}
-fun saveGenericPassword(serviceName: ByteArray, accountName: String, password: String) {
- saveGenericPassword(serviceName, accountName, password.toByteArray())
-}
+private const val errSecItemNotFound = -25300
+private const val errSecInvalidRecord = -67701
-private fun saveGenericPassword(serviceName: ByteArray, accountName: String, passwordData: ByteArray) {
- saveGenericPassword(serviceName, accountName, passwordData, passwordData.size)
+internal class KeyChainCredentialStore(serviceName: String) : CredentialStore {
+ private val serviceName = serviceName.toByteArray()
+
+ override fun get(key: String): String? {
+ return findGenericPassword(serviceName, key)
+ }
+
+ override fun set(key: String, password: ByteArray?) {
+ if (password == null) {
+ deleteGenericPassword(serviceName, key)
+ return
+ }
+
+ saveGenericPassword(serviceName, key, password, password.size)
+ password.fill(0)
+ }
}
fun findGenericPassword(serviceName: ByteArray, accountName: String): String? {
@@ -50,17 +65,22 @@ fun findGenericPassword(serviceName: ByteArray, accountName: String): String? {
fun deleteGenericPassword(serviceName: ByteArray, accountName: String) {
val itemRef = arrayOf(null)
val accountNameBytes = accountName.toByteArray()
- checkForError("find (for delete)", LIBRARY.SecKeychainFindGenericPassword(null, serviceName.size, serviceName, accountNameBytes.size, accountNameBytes, null, null, itemRef))
- val pointer = itemRef[0]
+ val code = LIBRARY.SecKeychainFindGenericPassword(null, serviceName.size, serviceName, accountNameBytes.size, accountNameBytes, null, null, itemRef)
+ if (code == errSecItemNotFound || code == errSecInvalidRecord) {
+ return
+ }
+
+ checkForError("find (for delete)", code)
+ val pointer = itemRef.get(0)
if (pointer != null) {
checkForError("delete", LIBRARY.SecKeychainItemDelete(pointer))
LIBRARY.CFRelease(pointer)
}
}
-// http://developer.apple.com/mac/library/DOCUMENTATION/Security/Reference/keychainservices/Reference/reference.html
+// https://developer.apple.com/library/mac/documentation/Security/Reference/keychainservices/index.html
// It is very, very important to use CFRelease/SecKeychainItemFreeContent You must do it, otherwise you can get "An invalid record was encountered."
-interface MacOsKeychainLibrary : com.sun.jna.Library {
+private interface MacOsKeychainLibrary : Library {
fun SecKeychainAddGenericPassword(keychain: Pointer?, serviceNameLength: Int, serviceName: ByteArray, accountNameLength: Int, accountName: ByteArray, passwordLength: Int, passwordData: ByteArray, itemRef: Pointer? = null): Int
fun SecKeychainItemModifyContent(/*SecKeychainItemRef*/ itemRef: Pointer, /*SecKeychainAttributeList**/ attrList: Pointer?, length: Int, data: ByteArray): Int
@@ -89,35 +109,38 @@ interface MacOsKeychainLibrary : com.sun.jna.Library {
fun SecKeychainItemFreeContent(/*SecKeychainAttributeList*/attrList: Pointer?, data: Pointer?)
}
-private fun saveGenericPassword(serviceName: ByteArray, accountName: String, password: ByteArray, passwordSize: Int) {
+fun saveGenericPassword(serviceName: ByteArray, accountName: String, password: ByteArray, passwordSize: Int = password.size) {
val accountNameBytes = accountName.toByteArray()
val itemRef = arrayOf(null)
- checkForError("find (for save)", LIBRARY.SecKeychainFindGenericPassword(null, serviceName.size, serviceName, accountNameBytes.size, accountNameBytes, null, null, itemRef))
+ val library = LIBRARY
+ checkForError("find (for save)", library.SecKeychainFindGenericPassword(null, serviceName.size, serviceName, accountNameBytes.size, accountNameBytes, null, null, itemRef))
val pointer = itemRef[0]
if (pointer == null) {
- checkForError("save (new)", LIBRARY.SecKeychainAddGenericPassword(null, serviceName.size, serviceName, accountNameBytes.size, accountNameBytes, passwordSize, password))
+ checkForError("save (new)", library.SecKeychainAddGenericPassword(null, serviceName.size, serviceName, accountNameBytes.size, accountNameBytes, passwordSize, password))
}
else {
- checkForError("save (update)", LIBRARY.SecKeychainItemModifyContent(pointer, null, passwordSize, password))
- LIBRARY.CFRelease(pointer)
+ checkForError("save (update)", library.SecKeychainItemModifyContent(pointer, null, passwordSize, password))
+ library.CFRelease(pointer)
}
}
private fun checkForError(message: String, code: Int) {
- if (code != 0 && code != /* errSecItemNotFound, always returned from find it seems */-25300) {
- val translated = LIBRARY.SecCopyErrorMessageString(code, null)
- val builder = StringBuilder(message).append(": ")
- if (translated == null) {
- builder.append(code)
- }
- else {
- val buf = CharArray(LIBRARY.CFStringGetLength(translated).toInt())
- for (i in 0..buf.size - 1) {
- buf[i] = LIBRARY.CFStringGetCharacterAtIndex(translated, i.toLong())
- }
- LIBRARY.CFRelease(translated)
- builder.append(buf).append(" (").append(code).append(')')
- }
- LOG.error(builder.toString())
+ if (code == 0 || code == errSecItemNotFound) {
+ return
}
+
+ val translated = LIBRARY.SecCopyErrorMessageString(code, null)
+ val builder = StringBuilder(message).append(": ")
+ if (translated == null) {
+ builder.append(code)
+ }
+ else {
+ val buf = CharArray(LIBRARY.CFStringGetLength(translated).toInt())
+ for (i in 0..buf.size - 1) {
+ buf[i] = LIBRARY.CFStringGetCharacterAtIndex(translated, i.toLong())
+ }
+ LIBRARY.CFRelease(translated)
+ builder.append(buf).append(" (").append(code).append(')')
+ }
+ LOG.error(builder.toString())
}
\ No newline at end of file
diff --git a/platform/credential-store/src/nativeCredentialStore.kt b/platform/credential-store/src/nativeCredentialStore.kt
new file mode 100644
index 000000000000..ef0255be4885
--- /dev/null
+++ b/platform/credential-store/src/nativeCredentialStore.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.credentialStore
+
+import com.intellij.credentialStore.linux.SecretCredentialStore
+import com.intellij.credentialStore.macOs.KeyChainCredentialStore
+import com.intellij.credentialStore.macOs.isMacOsCredentialStoreSupported
+import com.intellij.ide.passwordSafe.PasswordStorage
+import com.intellij.openapi.diagnostic.catchAndLog
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.util.SystemProperties
+import com.intellij.util.concurrency.QueueProcessor
+import com.intellij.util.containers.ContainerUtil
+
+private const val nullPassword = "\u0000"
+
+private class CredentialStoreWrapper(private val store: CredentialStore) : PasswordStorage {
+ private val fallbackStore = lazy { FileCredentialStore(memoryOnly = true) }
+
+ private val queueProcessor = QueueProcessor<() -> Unit>({
+ it()
+ })
+
+ private val postponedCredentials = ContainerUtil.newConcurrentMap()
+
+ override fun getPassword(requestor: Class<*>?, key: String): String? {
+ val rawKey = getRawKey(key, requestor)
+
+ postponedCredentials.get(rawKey)?.let {
+ return if (it == nullPassword) null else it
+ }
+
+ var store = if (fallbackStore.isInitialized()) fallbackStore.value else store
+
+ // try old key - as hash
+ @Suppress("CanBeVal")
+ var value: String?
+ try {
+ value = store.get(rawKey)
+ }
+ catch (e: UnsatisfiedLinkError) {
+ store = fallbackStore.value
+ LOG.error(e)
+ value = store.get(rawKey)
+ }
+ catch (e: Throwable) {
+ LOG.error(e)
+ return null
+ }
+
+ if (value == null) {
+ LOG.catchAndLog {
+ val oldKey = toOldKey(rawKey)
+ value = store.get(oldKey)
+ if (value != null) {
+ LOG.catchAndLog { store.set(oldKey, null) }
+ store.set(key, value!!.toByteArray())
+ }
+ }
+ }
+ return value
+ }
+
+ override fun setPassword(requestor: Class<*>?, key: String, value: String?) {
+ LOG.catchAndLog {
+ val store = if (fallbackStore.isInitialized()) fallbackStore.value else store
+ val rawKey = getRawKey(key, requestor)
+ val passwordData = value?.toByteArray()
+ if (fallbackStore.isInitialized()) {
+ store.set(rawKey, passwordData)
+ }
+ else {
+ postponedCredentials.put(rawKey, value ?: nullPassword)
+ queueProcessor.add {
+ if (!fallbackStore.isInitialized()) {
+ LOG.catchAndLog {
+ store.set(rawKey, passwordData)
+ postponedCredentials.remove(rawKey)
+ return@add
+ }
+ }
+ fallbackStore.value.set(rawKey, passwordData)
+ postponedCredentials.remove(rawKey)
+ }
+ }
+ }
+ }
+}
+
+private class MacOsCredentialStoreFactory : CredentialStoreFactory {
+ override fun create(): PasswordStorage? {
+ if (isMacOsCredentialStoreSupported && SystemProperties.getBooleanProperty("use.mac.keychain", true)) {
+ return CredentialStoreWrapper(KeyChainCredentialStore("IntelliJ Platform"))
+ }
+ return null
+ }
+}
+
+private class LinuxSecretCredentialStoreFactory : CredentialStoreFactory {
+ override fun create(): PasswordStorage? {
+ if (SystemInfo.isLinux && SystemProperties.getBooleanProperty("use.linux.keychain", true)) {
+ return CredentialStoreWrapper(SecretCredentialStore("com.intellij.credentialStore.Credential"))
+ }
+ return null
+ }
+}
\ No newline at end of file
diff --git a/platform/credential-store/test/FileCredentialStoreTest.kt b/platform/credential-store/test/FileCredentialStoreTest.kt
index eb24fc26b816..d04364800102 100644
--- a/platform/credential-store/test/FileCredentialStoreTest.kt
+++ b/platform/credential-store/test/FileCredentialStoreTest.kt
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe
+package com.intellij.credentialStore
import com.intellij.testFramework.RuleChain
import com.intellij.testFramework.TemporaryDirectory
diff --git a/platform/credential-store/test/LinuxSecretTest.kt b/platform/credential-store/test/LinuxSecretTest.kt
new file mode 100644
index 000000000000..5abe45740229
--- /dev/null
+++ b/platform/credential-store/test/LinuxSecretTest.kt
@@ -0,0 +1,32 @@
+package com.intellij.credentialStore.linux
+
+import com.intellij.openapi.util.SystemInfo
+import com.intellij.testFramework.UsefulTestCase
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Test
+import java.math.BigInteger
+import java.util.*
+
+class LinuxSecretTest {
+ @Test
+ fun test() {
+ if (!SystemInfo.isLinux || UsefulTestCase.IS_UNDER_TEAMCITY) {
+ return
+ }
+
+ val store = SecretCredentialStore("com.intellij.test")
+ val pass = BigInteger(128, Random()).toString(32)
+ store.set("test", pass.toByteArray())
+ assertThat(store.get("test")).isEqualTo(pass)
+
+ store.set("test", null)
+ assertThat(store.get("test")).isNull()
+
+ val unicodePassword = "Gr\u00FCnwald"
+ store.set("test", unicodePassword.toByteArray())
+ assertThat(store.get("test")).isEqualTo(unicodePassword)
+
+ store.set(unicodePassword, pass.toByteArray())
+ assertThat(store.get(unicodePassword)).isEqualTo(pass)
+ }
+}
\ No newline at end of file
diff --git a/platform/credential-store/test/MasterPasswordMigrationTest.kt b/platform/credential-store/test/MasterPasswordMigrationTest.kt
index 0a966f3b144a..36360051ec06 100644
--- a/platform/credential-store/test/MasterPasswordMigrationTest.kt
+++ b/platform/credential-store/test/MasterPasswordMigrationTest.kt
@@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.ide.passwordSafe
+package com.intellij.credentialStore
import com.intellij.ide.passwordSafe.impl.providers.masterKey.PasswordDatabase
import com.intellij.openapi.util.JDOMUtil
import com.intellij.testFramework.ApplicationRule
import com.intellij.testFramework.runInEdtAndWait
import com.intellij.util.xmlb.XmlSerializer
-
import org.assertj.core.api.Assertions.assertThat
import org.junit.ClassRule
import org.junit.Test
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java
index 4f9b181adc52..35f2ca182bb8 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProvider.java
@@ -74,7 +74,7 @@ public abstract class InspectionRVContentProvider {
@NotNull
public RefElementNode createNode(@NotNull InspectionToolPresentation presentation) {
- return ReadAction.compute(() -> new RefElementNode(myEntity, presentation));
+ return ReadAction.compute(() -> presentation.createRefNode(myEntity));
}
@Nullable
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java
index f3ef73f63605..1efc1db12d9c 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java
@@ -271,7 +271,7 @@ public class QuickFixAction extends AnAction implements CustomComponentAction {
}
}
- private static void refreshViews(@NotNull Project project, @NotNull RefEntity[] refElements, @NotNull InspectionToolWrapper toolWrapper) {
+ protected static void refreshViews(@NotNull Project project, @NotNull RefEntity[] refElements, @NotNull InspectionToolWrapper toolWrapper) {
final Set ignoredElements = new HashSet<>();
for (RefEntity element : refElements) {
final PsiElement psiElement = element instanceof RefElement ? ((RefElement)element).getElement() : null;
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java
index 4c5244ac361c..32712db58793 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionToolPresentation.java
@@ -48,6 +48,12 @@ public interface InspectionToolPresentation extends ProblemDescriptionsProcessor
@NotNull InspectionTreeNode parentNode,
final boolean showStructure,
final boolean groupBySeverity);
+
+ @NotNull
+ default RefElementNode createRefNode(@NotNull RefEntity entity) {
+ return new RefElementNode(entity, this);
+ }
+
void updateContent();
boolean hasReportedProblems();
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeCellRenderer.java
index 907a726033d1..040f413da079 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeCellRenderer.java
@@ -69,7 +69,7 @@ class InspectionTreeCellRenderer extends ColoredTreeCellRenderer {
if (node.isExcluded(myView.getExcludedManager())) {
return attributes.derive(attributes.getStyle() | SimpleTextAttributes.STYLE_STRIKEOUT, null, null, null);
}
- if (node instanceof ProblemDescriptionNode && ((ProblemDescriptionNode)node).isQuickFixAppliedFromView()) {
+ if (node instanceof SuppressableInspectionTreeNode && ((SuppressableInspectionTreeNode)node).isQuickFixAppliedFromView()) {
return attributes.derive(-1, SimpleTextAttributes.GRAYED_ATTRIBUTES.getFgColor(), null, null);
}
if (!node.isValid()) {
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java
index a4d7bb6bdb14..f431cd7c79a4 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/ProblemDescriptionNode.java
@@ -169,6 +169,7 @@ public class ProblemDescriptionNode extends SuppressableInspectionTreeNode {
return XmlStringUtil.stripHtml(ProblemDescriptorUtil.renderDescriptionMessage(descriptor, element, TRIM_AT_TREE_END));
}
+ @Override
public boolean isQuickFixAppliedFromView() {
return (myDescriptor != null && myPresentation.isProblemResolved(getElement(), myDescriptor)) && !isAlreadySuppressedFromView();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java
index 68a0d15c9479..a92de6a639e9 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java
@@ -134,6 +134,11 @@ public class RefElementNode extends SuppressableInspectionTreeNode {
super.visitProblemSeverities(counter);
}
+ @Override
+ public boolean isQuickFixAppliedFromView() {
+ return false;
+ }
+
@Nullable
@Override
public String getCustomizedTailText() {
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/SuppressableInspectionTreeNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/SuppressableInspectionTreeNode.java
index c8e6928a6691..1c0110b9745d 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/SuppressableInspectionTreeNode.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/SuppressableInspectionTreeNode.java
@@ -60,6 +60,8 @@ public abstract class SuppressableInspectionTreeNode extends CachedInspectionTre
return usrObj != null && myView.getSuppressedNodes(myPresentation.getToolWrapper().getShortName()).contains(usrObj);
}
+ public abstract boolean isQuickFixAppliedFromView();
+
@Nullable
@Override
public String getCustomizedTailText() {
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
index 2010b73d2968..4252c2d346e2 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
@@ -43,6 +43,7 @@ import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.Consumer;
import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.containers.ContainerUtil;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -190,22 +191,13 @@ extends BeforeRunTaskProvider targets = ApplicationManager.getApplication().runReadAction(new Computable>() {
- @Override
- public List compute() {
- return ExecutionTargetManager.getTargetsFor(env.getProject(), settings);
- }
- });
-
- if (targets.isEmpty()) {
+ ExecutionTarget compatibleTarget = getCompatibleTarget(env, settings);
+ if (compatibleTarget == null) {
return false;
}
- final ExecutionEnvironment environment = builder.target(targets.get(0)).build();
+ final ExecutionEnvironment environment = builder.target(compatibleTarget).build();
environment.setExecutionId(env.getExecutionId());
- if (!ExecutionTargetManager.canRun(settings, environment.getExecutionTarget())) {
- return false;
- }
if (!environment.getRunner().canRun(executorId, environment.getRunProfile())) {
return false;
@@ -216,6 +208,22 @@ extends BeforeRunTaskProvider targets = ApplicationManager.getApplication().runReadAction(new Computable>() {
+ @Override
+ public List compute() {
+ return ExecutionTargetManager.getTargetsFor(env.getProject(), settings);
+ }
+ });
+
+ return ContainerUtil.getFirstItem(targets);
+ }
+
public static boolean doRunTask(final String executorId, final ExecutionEnvironment environment, ProgramRunner> runner) {
final Semaphore targetDone = new Semaphore();
final Ref result = new Ref<>(false);
diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
index 75cb5c7c25ce..33e36b1fa833 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
@@ -407,11 +407,6 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
public UsageNode valueOf(UsageNode node) {
return node;
}
-
- @Override
- public boolean isCellEditable(UsageNode node) {
- return usageView.isOriginUsage(node.getUsage());
- }
};
List> list = Collections.nCopies(cols, o);
return list.toArray(new ColumnInfo[list.size()]);
@@ -652,7 +647,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
new DumbAwareAction() {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
- cancel(popup);
+ cancel(popup[0]);
showDialogAndFindUsages(handler, popupPosition, editor, maxUsages);
}
}.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table);
@@ -662,13 +657,13 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
new DumbAwareAction() {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
- cancel(popup);
+ cancel(popup[0]);
searchEverywhere(options, handler, editor, popupPosition, maxUsages);
}
}.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table);
}
- InplaceButton settingsButton = createSettingsButton(handler, popupPosition, editor, maxUsages, () -> cancel(popup));
+ InplaceButton settingsButton = createSettingsButton(handler, popupPosition, editor, maxUsages, () -> cancel(popup[0]));
ActiveComponent spinningProgress = new ActiveComponent.Adapter() {
@Override
@@ -726,7 +721,7 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
hideHints();
- cancel(popup);
+ cancel(popup[0]);
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(usageView.getProject())).getFindUsagesManager();
findUsagesManager.findUsages(handler.getPrimaryElements(), handler.getSecondaryElements(), handler, options,
FindSettings.getInstance().isSkipResultsWithOneUsage());
@@ -747,9 +742,9 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
};
}
- private static void cancel(@Nullable JBPopup... popup) {
- if (popup != null && popup.length>0 && popup[0] != null) {
- popup[0].cancel();
+ private static void cancel(@Nullable JBPopup popup) {
+ if (popup != null) {
+ popup.cancel();
}
}
@@ -957,6 +952,13 @@ public class ShowUsagesAction extends AnAction implements PopupAction {
newSelection = table.getSelectedRow();
}
else {
+ // do not pre-select the usage under caret by default
+ if (newSelection == 0 && table.getModel().getRowCount() > 1) {
+ Object valueInTopRow = table.getModel().getValueAt(0, 0);
+ if (valueInTopRow instanceof UsageNode && usageView.isOriginUsage(((UsageNode)valueInTopRow).getUsage())) {
+ newSelection++;
+ }
+ }
table.getSelectionModel().setSelectionInterval(newSelection, newSelection);
}
ScrollingUtil.ensureIndexIsVisible(table, newSelection, 0);
diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.java
index d30d9d2535b1..4e3d744f5735 100644
--- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.java
+++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.java
@@ -307,7 +307,7 @@ public abstract class AbstractNavBarUI implements NavBarUI {
@Override
public void doPaintNavBarPanel(Graphics2D g, Rectangle r, boolean mainToolbarVisible, boolean undocked) {
g.setColor(getBackgroundColor());
- if (!UIUtil.isUnderAquaLookAndFeel() && mainToolbarVisible) {
+ if (mainToolbarVisible) {
g.fillRect(0, 0, r.width, r.height);
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
index 66fff05abaf9..b70a8eafa159 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
@@ -53,7 +53,10 @@ import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.*;
-import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
@@ -88,7 +91,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.ListSelectionEvent;
@@ -389,9 +391,6 @@ public abstract class ChooseByNameBase {
if (myModel.getPromptText() != null) {
JLabel label = new JLabel(myModel.getPromptText());
- if (UIUtil.isUnderAquaLookAndFeel()) {
- label.setBorder(new CompoundBorder(new EmptyBorder(0, 9, 0, 0), label.getBorder()));
- }
label.setFont(UIUtil.getLabelFont().deriveFont(Font.BOLD));
caption2Tools.add(label, BorderLayout.WEST);
}
diff --git a/platform/platform-api/platform-api.iml b/platform/platform-api/platform-api.iml
index fa8a000b28c8..2e3cac31a1e1 100644
--- a/platform/platform-api/platform-api.iml
+++ b/platform/platform-api/platform-api.iml
@@ -16,17 +16,9 @@
+
-
-
-
-
-
-
-
-
-
diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java
index c51fef0c4b22..65d8582e2d28 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java
@@ -87,7 +87,7 @@ public class FileChooser {
@Nullable final Project project,
@Nullable final VirtualFile toSelect,
@NotNull final Consumer> callback) {
- chooseFiles(descriptor, project, KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(), toSelect, callback);
+ chooseFiles(descriptor, project, KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(), toSelect, callback);
}
/**
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java
index b320b9f85a7b..59eeaae20025 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java
@@ -17,7 +17,6 @@ package com.intellij.openapi.ui;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.components.JBList;
@@ -27,7 +26,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.table.TableCellEditor;
import java.awt.*;
@@ -242,14 +240,7 @@ public class ComboBox extends ComboBoxWithWidePopup implements AWTEventLis
}
public final void setEditor(final ComboBoxEditor editor) {
- ComboBoxEditor _editor = editor;
- if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel()) {
- if (editor instanceof UIResource) {
- _editor = new FixedComboBoxEditor();
- }
- }
-
- super.setEditor(new MyEditor(this, _editor));
+ super.setEditor(new MyEditor(this, editor));
}
public final Dimension getMinimumSize() {
@@ -266,23 +257,6 @@ public class ComboBox extends ComboBoxWithWidePopup implements AWTEventLis
return new Dimension(width, UIUtil.fixComboBoxHeight(preferredSize.height));
}
- @Override
- public Insets getInsets() {
- Insets insets = super.getInsets();
- if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel() && isEditable) {
- insets.right += 2;
- }
- return insets;
- }
-
- @Override
- public boolean hasFocus() {
- if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel() && myPaintingNow && isEditable) {
- return false;
- }
- return super.hasFocus();
- }
-
protected Dimension getOriginalPreferredSize() {
return super.getPreferredSize();
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/BalloonBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/BalloonBuilder.java
index 41db010dbfe6..bad5404519b7 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/popup/BalloonBuilder.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/BalloonBuilder.java
@@ -98,6 +98,8 @@ public interface BalloonBuilder {
@NotNull
BalloonBuilder setRequestFocus(boolean requestFocus);
+ BalloonBuilder setHideOnCloseClick(boolean hideOnCloseClick);
+
/**
* Links target balloon life cycle to the given object. I.e. current balloon will be auto-hide and collected as soon
* as given anchor is disposed.
diff --git a/platform/platform-api/src/com/intellij/util/io/CompressedBytesReadAwareGZIPInputStream.java b/platform/platform-api/src/com/intellij/util/io/CountingGZIPInputStream.java
similarity index 61%
rename from platform/platform-api/src/com/intellij/util/io/CompressedBytesReadAwareGZIPInputStream.java
rename to platform/platform-api/src/com/intellij/util/io/CountingGZIPInputStream.java
index 6c1a487e1ee1..287d0a5b3354 100644
--- a/platform/platform-api/src/com/intellij/util/io/CompressedBytesReadAwareGZIPInputStream.java
+++ b/platform/platform-api/src/com/intellij/util/io/CountingGZIPInputStream.java
@@ -19,61 +19,62 @@ import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
-import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.GZIPInputStream;
-public class CompressedBytesReadAwareGZIPInputStream extends GZIPInputStream {
- private final BytesReadAwareInputStream myInputStream;
+/**
+ * A stream for reading compressed data in the GZIP file format.
+ * Total amount of compressed read bytes can be accessed via {@link #getCompressedBytesRead()}.
+ *
+ * Note that this implementation is not thread safe.
+ */
+public class CountingGZIPInputStream extends GZIPInputStream {
+ private final CountingInputStream myInputStream;
- private CompressedBytesReadAwareGZIPInputStream(@NotNull BytesReadAwareInputStream inputStream) throws IOException {
+ private CountingGZIPInputStream(@NotNull CountingInputStream inputStream) throws IOException {
super(inputStream);
myInputStream = inputStream;
}
public long getCompressedBytesRead() {
- return myInputStream.myBytesRead.get();
+ return myInputStream.myBytesRead;
}
@NotNull
- public static CompressedBytesReadAwareGZIPInputStream create(@NotNull InputStream inputStream) throws IOException {
- return new CompressedBytesReadAwareGZIPInputStream(new BytesReadAwareInputStream(inputStream));
+ public static CountingGZIPInputStream create(@NotNull InputStream inputStream) throws IOException {
+ return new CountingGZIPInputStream(new CountingInputStream(inputStream));
}
- private static class BytesReadAwareInputStream extends InputStream {
+ private static class CountingInputStream extends InputStream {
private final InputStream myInputStream;
- private final AtomicLong myBytesRead = new AtomicLong(0);
+ private long myBytesRead = 0;
- public BytesReadAwareInputStream(@NotNull InputStream inputStream) {
+ public CountingInputStream(@NotNull InputStream inputStream) {
myInputStream = inputStream;
}
public int read() throws IOException {
- long bytesReadBefore = myBytesRead.get();
int data = myInputStream.read();
- myBytesRead.compareAndSet(bytesReadBefore, bytesReadBefore + 1);
+ myBytesRead++;
return data;
}
@Override
public int read(@NotNull byte[] b) throws IOException {
- long bytesReadBefore = myBytesRead.get();
int bytesRead = myInputStream.read(b);
- myBytesRead.compareAndSet(bytesReadBefore, bytesReadBefore + bytesRead);
+ myBytesRead += bytesRead;
return bytesRead;
}
@Override
public int read(@NotNull byte[] b, int off, int len) throws IOException {
- long bytesReadBefore = myBytesRead.get();
int bytesRead = myInputStream.read(b, off, len);
- myBytesRead.compareAndSet(bytesReadBefore, bytesReadBefore + bytesRead);
+ myBytesRead += bytesRead;
return bytesRead;
}
public long skip(long n) throws IOException {
- long bytesReadBefore = myBytesRead.get();
long bytesSkipped = myInputStream.skip(n);
- myBytesRead.compareAndSet(bytesReadBefore, bytesReadBefore + bytesSkipped);
+ myBytesRead += bytesSkipped;
return bytesSkipped;
}
diff --git a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java
index 3db597dcec5d..98952a16bb33 100644
--- a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java
+++ b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java
@@ -278,8 +278,7 @@ public final class HttpRequests {
if (myInputStream == null) {
myInputStream = getConnection().getInputStream();
if (myBuilder.myGzip && "gzip".equalsIgnoreCase(getConnection().getContentEncoding())) {
- //noinspection IOResourceOpenedButNotSafelyClosed
- myInputStream = CompressedBytesReadAwareGZIPInputStream.create(myInputStream);
+ myInputStream = CountingGZIPInputStream.create(myInputStream);
}
}
return myInputStream;
diff --git a/platform/platform-api/src/com/intellij/util/net/NetUtils.java b/platform/platform-api/src/com/intellij/util/net/NetUtils.java
index 1c02684465ac..e8e9405c42b8 100644
--- a/platform/platform-api/src/com/intellij/util/net/NetUtils.java
+++ b/platform/platform-api/src/com/intellij/util/net/NetUtils.java
@@ -21,7 +21,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SystemProperties;
-import com.intellij.util.io.CompressedBytesReadAwareGZIPInputStream;
+import com.intellij.util.io.CountingGZIPInputStream;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -188,7 +188,7 @@ public class NetUtils {
indicator.setIndeterminate(true);
}
}
- CompressedBytesReadAwareGZIPInputStream gzipStream = ObjectUtils.tryCast(inputStream, CompressedBytesReadAwareGZIPInputStream.class);
+ CountingGZIPInputStream gzipStream = ObjectUtils.tryCast(inputStream, CountingGZIPInputStream.class);
final byte[] buffer = new byte[8 * 1024];
int count;
int bytesWritten = 0;
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizationUtil.java b/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizationUtil.java
index 4d9e745381fe..4e19b7758d2d 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizationUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizationUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -137,11 +137,13 @@ public class CustomizationUtil {
@Override
public boolean accept(Object node) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
- if (treeNode.isLeaf()) {
+ Object userObject = treeNode.getUserObject();
+ if (treeNode.isLeaf() && !(userObject instanceof Group)) {
return true;
}
- final ActionUrl url = getActionUrl(new TreePath(treeNode.getPath()), 0);
- url.getGroupPath().add(((Group)treeNode.getUserObject()).getName());
+ ActionUrl url = getActionUrl(new TreePath(treeNode.getPath()), 0);
+ String groupName = ((Group)userObject).getName();
+ url.getGroupPath().add(groupName);
final TreePath treePath = getTreePath(defaultTree, url);
if (treePath != null) {
final DefaultMutableTreeNode visited = (DefaultMutableTreeNode)treePath.getLastPathComponent();
@@ -152,7 +154,7 @@ public class CustomizationUtil {
//customizations at the new place
url.getGroupPath().remove(url.getParentGroup());
if (actions.contains(url)){
- url.getGroupPath().add(((Group)treeNode.getUserObject()).getName());
+ url.getGroupPath().add(groupName);
actions.addAll(schema.getChildActions(url));
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
index 9dd912540ece..e15b6351e343 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
@@ -54,6 +54,7 @@ import com.intellij.ui.mac.foundation.MacUtil;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.JBInsets;
+import com.intellij.util.ui.OwnerOptional;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -175,18 +176,16 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
*/
protected DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper, @NotNull Component parent, boolean canBeParent) {
myWrapper = wrapper;
- if (!parent.isShowing()) {
- throw new IllegalArgumentException("parent must be showing: " + parent);
- }
+
myWindowManager = null;
Application application = ApplicationManager.getApplication();
if (application != null && application.hasComponent(WindowManager.class)) {
myWindowManager = (WindowManagerEx)WindowManager.getInstance();
}
- Window owner = parent instanceof Window ? (Window)parent : (Window)SwingUtilities.getAncestorOfClass(Window.class, parent);
- if (!(owner instanceof Dialog) && !(owner instanceof Frame)) {
- owner = JOptionPane.getRootFrame();
+ Window owner = OwnerOptional.fromComponent(parent).get();
+ if (!owner.isShowing()) {
+ throw new IllegalArgumentException("owner must be showing: " + owner);
}
createDialog(owner, canBeParent);
}
@@ -219,7 +218,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
@Deprecated
public DialogWrapperPeerImpl(@NotNull DialogWrapper wrapper,final Window owner, final boolean canBeParent, final boolean applicationModalIfPossible) {
- this(wrapper, owner, canBeParent, applicationModalIfPossible ? DialogWrapper.IdeModalityType.IDE : DialogWrapper.IdeModalityType.PROJECT);
+ this(wrapper, owner, canBeParent, applicationModalIfPossible ? DialogWrapper.IdeModalityType.IDE : DialogWrapper.IdeModalityType.PROJECT);
}
@Override
@@ -496,7 +495,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
if (StackingPopupDispatcher.getInstance().isPopupFocused()) return;
JTree tree = UIUtil.getParentOfType(JTree.class, focusOwner);
JTable table = UIUtil.getParentOfType(JTable.class, focusOwner);
-
+
if (tree != null || table != null) {
if (hasNoEditingTreesOrTablesUpward(focusOwner)) {
e.getPresentation().setEnabled(true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java
index 8572df500c3a..c33b3833f172 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -184,8 +184,14 @@ public final class StripeButton extends AnchoredButton implements ActionListener
myDragPane = findLayeredPane(e);
if (myDragPane == null) return;
- final BufferedImage image = UIUtil.createImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
- paint(image.getGraphics());
+ int width = getWidth() - 1; // -1 because StripeButtonUI.paint will not paint 1 pixel in case (anchor == ToolWindowAnchor.LEFT)
+ int height = getHeight() - 1; // -1 because StripeButtonUI.paint will not paint 1 pixel in case (anchor.isHorizontal())
+ BufferedImage image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_RGB);
+ Graphics graphics = image.getGraphics();
+ graphics.setColor(UIUtil.getBgFillColor(getParent()));
+ graphics.fillRect(0, 0, width, height);
+ paint(graphics);
+ graphics.dispose();
myDragButtonImage = new JLabel(new JBImageIcon(image)) {
public String toString() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeBalloonLayoutImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeBalloonLayoutImpl.java
index 61bdca9a5b22..b36fa6982a78 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeBalloonLayoutImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/WelcomeBalloonLayoutImpl.java
@@ -105,8 +105,8 @@ public class WelcomeBalloonLayoutImpl extends BalloonLayoutImpl {
});
myPopupBalloon =
- new BalloonImpl(pane, BORDER_COLOR, new Insets(0, 0, 0, 0), FILL_COLOR, true, false, false, false, true, 0, false, false, null,
- false, 0, 0, 0, 0, false, null, null, false, false, false, null, false);
+ new BalloonImpl(pane, BORDER_COLOR, new Insets(0, 0, 0, 0), FILL_COLOR, true, false, false, true, false, true, 0, false, false,
+ null, false, 0, 0, 0, 0, false, null, null, false, false, false, null, false);
myPopupBalloon.setAnimationEnabled(false);
myPopupBalloon.setShadowBorderProvider(
new NotificationBalloonShadowBorderProvider(FILL_COLOR, BORDER_COLOR));
diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
index 674277664414..3c080a48cde8 100644
--- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
@@ -157,7 +157,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
}
}
- if (UIUtil.isCloseClick(me)) {
+ if (myHideOnCloseClick && UIUtil.isCloseClick(me)) {
if (isInsideBalloon(me)) {
hide();
me.consume();
@@ -291,6 +291,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
private Runnable myHideListener;
private final boolean myHideOnKey;
private final boolean myHideOnAction;
+ private final boolean myHideOnCloseClick;
private final boolean myRequestFocus;
private Component myOriginalFocusOwner;
private final boolean myEnableButtons;
@@ -302,6 +303,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
boolean hideOnMouse,
boolean hideOnKey,
boolean hideOnAction,
+ boolean hideOnCloseClick,
boolean showPointer,
boolean enableButtons,
long fadeoutTime,
@@ -328,6 +330,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
myHideOnMouse = hideOnMouse;
myHideOnKey = hideOnKey;
myHideOnAction = hideOnAction;
+ myHideOnCloseClick = hideOnCloseClick;
myShowPointer = showPointer;
myEnableButtons = enableButtons;
myHideOnFrameResize = hideOnFrameResize;
diff --git a/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java b/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java
index 413c09e1d5bd..4621570a73de 100644
--- a/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java
+++ b/platform/platform-impl/src/com/intellij/ui/Win7TaskBar.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -15,6 +15,7 @@
*/
package com.intellij.ui;
+import com.intellij.jna.DisposableMemory;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.wm.IdeFrame;
@@ -70,17 +71,6 @@ class Win7TaskBar {
boolean FlashWindow(WinDef.HWND hwnd, boolean bInvert);
}
- private static class MyMemory extends Memory {
- private MyMemory(long size) {
- super(size);
- }
-
- @Override
- public synchronized void dispose() {
- super.dispose();
- }
- }
-
private static boolean ourInitialized = true;
static {
@@ -162,7 +152,7 @@ class Win7TaskBar {
return new Object();
}
- MyMemory memory = new MyMemory(ico.length);
+ DisposableMemory memory = new DisposableMemory(ico.length);
try {
memory.write(0, ico, 0, ico.length);
diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java b/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java
index 843caae83081..37f85924d2e8 100644
--- a/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java
+++ b/platform/platform-impl/src/com/intellij/ui/mac/MacPathChooserDialog.java
@@ -26,18 +26,15 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.PathChooserDialog;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.popup.StackingPopupDispatcher;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.ui.UIBundle;
-import com.intellij.ui.popup.AbstractPopup;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.OwnerOptional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,23 +51,25 @@ import java.util.stream.Stream;
public class MacPathChooserDialog implements PathChooserDialog {
- private final FileDialog myFileDialog;
+ private FileDialog myFileDialog;
private final FileChooserDescriptor myFileChooserDescriptor;
private final Component myParent;
private final String myTitle;
public MacPathChooserDialog(FileChooserDescriptor descriptor, Component parent, Project project) {
- //StackingPopupDispatcher.getInstance().hidePersistentPopups();
- //myDisposeActions.add(() -> StackingPopupDispatcher.getInstance().restorePersistentPopups());
-
- myFileDialog = parent != null
- ? createFileDialogWithOwner(findOwnerByComponent(parent), descriptor.getTitle(), FileDialog.LOAD)
- : createFileDialogWithoutOwner(descriptor.getTitle(), FileDialog.LOAD);
-
myFileChooserDescriptor = descriptor;
myParent = parent;
myTitle = getChooserTitle(descriptor);
+
+ Consumer