Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Batkovich
2017-11-20 09:18:20 +03:00
159 changed files with 2204 additions and 1750 deletions
@@ -115,11 +115,11 @@ public class ArtifactRepositoryManager {
// setup session here
session.setLocalRepositoryManager(ourSystem.newLocalRepositoryManager(session, new LocalRepository(localRepositoryPath)));
session.setProxySelector(new org.jetbrains.idea.maven.aether.JreProxySelector());
session.setReadOnly();
mySession = session;
}
public void addRemoteRepository(final String id, final String url) {
myRemoteRepositories.add(createRemoteRepository(id, url));
}
@@ -0,0 +1,127 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.maven.aether;
import org.eclipse.aether.repository.*;
import org.eclipse.aether.repository.Proxy;
import org.eclipse.aether.repository.ProxySelector;
import java.net.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* This is a modified copy of the corresponding Aether class that adds support for https proxy types
*/
final class JreProxySelector implements ProxySelector {
JreProxySelector() {
}
public Proxy getProxy(RemoteRepository repository) {
try {
final java.net.ProxySelector systemSelector = java.net.ProxySelector.getDefault();
if (systemSelector == null) {
return null;
}
final URI uri = new URI(repository.getUrl()).parseServerAuthority();
final List<java.net.Proxy> selected = systemSelector.select(uri);
if (selected == null || selected.isEmpty()) {
return null;
}
for (java.net.Proxy proxy : selected) {
if (proxy.type() == java.net.Proxy.Type.HTTP && isValid(proxy.address())) {
final String proxyType = chooseProxyType(uri.getScheme());
if (proxyType != null) {
final InetSocketAddress addr = (InetSocketAddress)proxy.address();
return new Proxy(proxyType, addr.getHostName(), addr.getPort(), JreProxyAuthentication.INSTANCE);
}
}
}
}
catch (Throwable e) {
// URL invalid or not accepted by selector or no selector at all, simply use no proxy
}
return null;
}
private static String chooseProxyType(final String protocol) {
if (Proxy.TYPE_HTTP.equals(protocol)) {
return Proxy.TYPE_HTTP;
}
if (Proxy.TYPE_HTTPS.equals(protocol)) {
return Proxy.TYPE_HTTPS;
}
return null;
}
private static boolean isValid(SocketAddress address) {
if (address instanceof InetSocketAddress) {
/*
* NOTE: On some platforms with java.net.useSystemProxies=true, unconfigured proxies show up as proxy
* objects with empty host and port 0.
*/
final InetSocketAddress addr = (InetSocketAddress)address;
return addr.getPort() > 0 && addr.getHostName() != null && !addr.getHostName().isEmpty();
}
return false;
}
private static final class JreProxyAuthentication implements Authentication {
public static final Authentication INSTANCE = new JreProxyAuthentication();
public void fill(AuthenticationContext context, String key, Map<String, String> data) {
Proxy proxy = context.getProxy();
if (proxy == null) {
return;
}
if (!AuthenticationContext.USERNAME.equals(key) && !AuthenticationContext.PASSWORD.equals(key)) {
return;
}
try {
URL url;
String protocol = "http";
try {
url = new URL(context.getRepository().getUrl());
protocol = url.getProtocol();
}
catch (Exception e) {
url = null;
}
PasswordAuthentication auth = Authenticator.requestPasswordAuthentication(
proxy.getHost(), null, proxy.getPort(), protocol, "Credentials for proxy " + proxy, null, url, Authenticator.RequestorType.PROXY
);
if (auth != null) {
context.put(AuthenticationContext.USERNAME, auth.getUserName());
context.put(AuthenticationContext.PASSWORD, auth.getPassword());
}
else {
context.put(AuthenticationContext.USERNAME, System.getProperty(protocol + ".proxyUser"));
context.put(AuthenticationContext.PASSWORD, System.getProperty(protocol + ".proxyPassword"));
}
}
catch (SecurityException e) {
// oh well, let's hope the proxy can do without auth
}
}
public void digest(AuthenticationDigest digest) {
// we don't know anything about the JRE's current authenticator, assume the worst (i.e. interactive)
digest.update(UUID.randomUUID().toString());
}
@Override
public boolean equals(Object obj) {
return this == obj || (obj != null && getClass().equals(obj.getClass()));
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}
}
+5
View File
@@ -1,9 +1,14 @@
!define INSTALL_OPTION_ELEMENTS 5
!define CUSTOM_SILENT_CONFIG 0
Function customPreInstallActions
DetailPrint "There are no custom pre-install actions."
FunctionEnd
Function customSilentConfigReader
DetailPrint "There are no custom silent install actions."
FunctionEnd
Function customInstallActions
DetailPrint "There are no custom install actions."
FunctionEnd
+347 -218
View File
@@ -25,11 +25,26 @@ SetCompressor lzma
; http://nsis.sourceforge.net/Shortcuts_removal_fails_on_Windows_Vista
RequestExecutionLevel user
;------------------------------------------------------------------------------
; Variables
;------------------------------------------------------------------------------
Var STARTMENU_FOLDER
Var config_path
Var system_path
Var productLauncher
Var baseRegKey
Var downloadJreX86
Var productDir
Var control_fields
Var max_fields
Var silentMode
;------------------------------------------------------------------------------
; include "Modern User Interface"
;------------------------------------------------------------------------------
!include "MUI2.nsh"
!include "FileFunc.nsh"
!include "TextFunc.nsh"
!include UAC.nsh
!include "InstallOptions.nsh"
!include StrFunc.nsh
@@ -53,19 +68,6 @@ ReserveFile "DeleteSettings.ini"
!define MUI_HEADERIMAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_HEADER_FILE}"
!define MUI_WELCOMEFINISHPAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_LOGO_FILE}"
;------------------------------------------------------------------------------
; Variables
;------------------------------------------------------------------------------
Var STARTMENU_FOLDER
Var config_path
Var system_path
Var productLauncher
Var baseRegKey
Var downloadJreX86
Var productDir
Var control_fields
Var max_fields
;------------------------------------------------------------------------------
; on GUI initialization installer checks whether IDEA is already installed
;------------------------------------------------------------------------------
@@ -117,92 +119,95 @@ ReserveFile "DeleteSettings.ini"
complete:
FunctionEnd
Function ${un}SplitStr
Exch $0 ; str
Push $1 ; inQ
Push $3 ; idx
Push $4 ; tmp
StrCpy $1 0
StrCpy $3 0
Exch $0 ; str
Push $1 ; inQ
Push $3 ; idx
Push $4 ; tmp
StrCpy $1 0
StrCpy $3 0
loop:
StrCpy $4 $0 1 $3
${If} $4 == '"'
${If} $1 <> 0
StrCpy $0 $0 "" 1
IntOp $3 $3 - 1
${EndIf}
IntOp $1 $1 !
StrCpy $4 $0 1 $3
${If} $4 == '"'
${If} $1 <> 0
StrCpy $0 $0 "" 1
IntOp $3 $3 - 1
${EndIf}
${If} $4 == '' ; The end?
StrCpy $1 0
StrCpy $4 ','
${EndIf}
${If} $4 == ','
IntOp $1 $1 !
${EndIf}
${If} $4 == '' ; The end?
StrCpy $1 0
StrCpy $4 ','
${EndIf}
${If} $4 == ','
${AndIf} $1 = 0
StrCpy $4 $0 $3
StrCpy $1 $4 "" -1
${IfThen} $1 == '"' ${|} StrCpy $4 $4 -1 ${|}
killspace:
IntOp $3 $3 + 1
StrCpy $0 $0 "" $3
StrCpy $1 $0 1
StrCpy $3 0
StrCmp $1 ',' killspace
Push $0 ; Remaining
Exch 4
Pop $0
StrCmp $4 "" 0 moreleft
Pop $4
Pop $3
Pop $1
Return
moreleft:
Exch $4
Exch 2
Pop $1
StrCpy $4 $0 $3
StrCpy $1 $4 "" -1
${IfThen} $1 == '"' ${|} StrCpy $4 $4 -1 ${|}
killspace:
IntOp $3 $3 + 1
StrCpy $0 $0 "" $3
StrCpy $1 $0 1
StrCpy $3 0
StrCmp $1 ',' killspace
Push $0 ; Remaining
Exch 4
Pop $0
StrCmp $4 "" 0 moreleft
Pop $4
Pop $3
Pop $1
Return
${EndIf}
IntOp $3 $3 + 1
Goto loop
moreleft:
Exch $4
Exch 2
Pop $1
Pop $3
Return
${EndIf}
IntOp $3 $3 + 1
Goto loop
FunctionEnd
!macroend
!insertmacro INST_UNINST_SWITCH ""
!insertmacro INST_UNINST_SWITCH "un."
Function InstDirState
!define InstDirState `!insertmacro InstDirStateCall`
!define InstDirState `!insertmacro InstDirStateCall`
!macro InstDirStateCall _PATH _RESULT
Push `${_PATH}`
Call InstDirState
Pop ${_RESULT}
!macroend
!macro InstDirStateCall _PATH _RESULT
Push `${_PATH}`
Call InstDirState
Pop ${_RESULT}
!macroend
Exch $0
Push $1
ClearErrors
Exch $0
Push $1
ClearErrors
FindFirst $1 $0 '$0\*.*'
IfErrors 0 +3
StrCpy $0 -1
goto end
StrCmp $0 '.' 0 +4
FindNext $1 $0
StrCmp $0 '..' 0 +2
FindNext $1 $0
FindClose $1
IfErrors 0 +3
StrCpy $0 0
goto end
StrCpy $0 1
end:
Pop $1
Exch $0
FindFirst $1 $0 '$0\*.*'
IfErrors 0 +3
StrCpy $0 -1
goto end
StrCmp $0 '.' 0 +4
FindNext $1 $0
StrCmp $0 '..' 0 +2
FindNext $1 $0
FindClose $1
IfErrors 0 +3
StrCpy $0 0
goto end
StrCpy $0 1
end:
Pop $1
Exch $0
FunctionEnd
Function SplitFirstStrPart
Exch $R0
Exch
@@ -212,24 +217,24 @@ Function SplitFirstStrPart
StrCpy $R3 $R1
StrLen $R1 $R0
IntOp $R1 $R1 + 1
loop:
IntOp $R1 $R1 - 1
StrCpy $R2 $R0 1 -$R1
StrCmp $R1 0 exit0
StrCmp $R2 $R3 exit1 loop
exit0:
loop:
IntOp $R1 $R1 - 1
StrCpy $R2 $R0 1 -$R1
StrCmp $R1 0 exit0
StrCmp $R2 $R3 exit1 loop
exit0:
StrCpy $R1 ""
Goto exit2
exit1:
IntOp $R1 $R1 - 1
StrCmp $R1 0 0 +3
exit1:
IntOp $R1 $R1 - 1
StrCmp $R1 0 0 +3
StrCpy $R2 ""
Goto +2
StrCpy $R2 $R0 "" -$R1
IntOp $R1 $R1 + 1
StrCpy $R0 $R0 -$R1
StrCpy $R1 $R2
exit2:
StrCpy $R2 $R0 "" -$R1
IntOp $R1 $R1 + 1
StrCpy $R0 $R0 -$R1
StrCpy $R1 $R2
exit2:
Pop $R3
Pop $R2
Exch $R1 ;rest
@@ -237,29 +242,31 @@ Function SplitFirstStrPart
Exch $R0 ;first
FunctionEnd
Function VersionSplit
!define VersionSplit `!insertmacro VersionSplitCall`
!define VersionSplit `!insertmacro VersionSplitCall`
!macro VersionSplitCall _FULL _PRODUCT _BRANCH _BUILD
Push `${_FULL}`
Call VersionSplit
Pop ${_PRODUCT}
Pop ${_BRANCH}
Pop ${_BUILD}
!macroend
!macro VersionSplitCall _FULL _PRODUCT _BRANCH _BUILD
Push `${_FULL}`
Call VersionSplit
Pop ${_PRODUCT}
Pop ${_BRANCH}
Pop ${_BUILD}
!macroend
Pop $R0
Push "-"
Push $R0
Call SplitFirstStrPart
Pop $R0
Pop $R1
Push "."
Push $R1
Call SplitFirstStrPart
Push $R0
Pop $R0
Push "-"
Push $R0
Call SplitFirstStrPart
Pop $R0
Pop $R1
Push "."
Push $R1
Call SplitFirstStrPart
Push $R0
FunctionEnd
Function OnDirectoryPageLeave
;check
; - if there are no files into $INSTDIR (recursively)
@@ -281,18 +288,18 @@ Function instDirEmpty
ClearErrors
FindFirst $1 $2 "$9\*.*"
IfErrors done 0
nextElemement:
next_elemement:
;is the element a folder?
StrCmp $2 "." getNextElement
StrCmp $2 ".." getNextElement
IfFileExists "$9\$2\*.*" 0 nextFile
StrCmp $2 "." get_next_element
StrCmp $2 ".." get_next_element
IfFileExists "$9\$2\*.*" 0 next_file
Push $9
StrCpy "$9" "$9\$2"
Call instDirEmpty
StrCmp $9 "not empty" done 0
Pop $9
Goto getNextElement
nextFile:
Goto get_next_element
next_file:
;is it the file property?
${If} $2 != "idea.properties"
${AndIf} $2 != "${PRODUCT_EXE_FILE}.vmoptions"
@@ -301,9 +308,9 @@ nextFile:
StrCpy $9 "not empty"
Goto done
${EndIf}
getNextElement:
get_next_element:
FindNext $1 $2
IfErrors 0 nextElemement
IfErrors 0 next_elemement
done:
FindClose $1
Pop $2
@@ -311,19 +318,6 @@ done:
Pop $0
FunctionEnd
Function searchJava64
StrCpy $0 "HKLM"
StrCpy $1 "Software\JavaSoft\Java Development Kit\${JAVA_REQUIREMENT}"
StrCpy $2 "JavaHome"
SetRegView 64
call OMReadRegStr
SetRegView 32
StrCpy $3 "$3\bin\java.exe"
IfFileExists $3 done no_java_64
no_java_64:
StrCpy $3 ""
done:
FunctionEnd
Function ConfirmDesktopShortcut
!insertmacro MUI_HEADER_TEXT "$(installation_options)" "$(installation_options_prompt)"
@@ -344,7 +338,7 @@ Function ConfirmDesktopShortcut
${EndIf}
; if jre x86 for the build is available then add checkbox to Installation Options dialog
StrCmp "${LINK_TO_JRE}" "null" customPreActions 0
StrCmp "${LINK_TO_JRE}" "null" custom_pre_actions 0
inetc::head /SILENT /TOSTACK ${LINK_TO_JRE} "" /END
Pop $0
${If} $0 == "OK"
@@ -358,7 +352,7 @@ Function ConfirmDesktopShortcut
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "State" $downloadJreX86
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Text" "Download and install JRE x86 by JetBrains"
${EndIf}
customPreActions:
custom_pre_actions:
Call customPreInstallActions
SetRegView 32
StrCmp "${ASSOCIATION}" "NoAssociation" skip_association
@@ -378,6 +372,7 @@ done:
!insertmacro INSTALLOPTIONS_DISPLAY "Desktop.ini"
FunctionEnd
Function downloadJre
!insertmacro INSTALLOPTIONS_READ $R0 "Desktop.ini" "Field 4" "State"
${If} $R0 == 1
@@ -385,10 +380,10 @@ Function downloadJre
Pop $0
${If} $0 == "OK"
untgz::extract "-d" "$INSTDIR\jre32" "$TEMP\jre.tar.gz"
StrCmp $R0 "success" removeTempJre
StrCmp $R0 "success" remove_temp_jre
DetailPrint "Failed to extract jre.tar.gz"
MessageBox MB_OK|MB_ICONEXCLAMATION|MB_DEFBUTTON1 "Failed to extract $TEMP\jre.tar.gz"
removeTempJre:
remove_temp_jre:
IfFileExists "$TEMP\jre.tar.gz" 0 done
Delete "$TEMP\jre.tar.gz"
${Else}
@@ -398,13 +393,11 @@ removeTempJre:
done:
FunctionEnd
;------------------------------------------------------------------------------
; configuration
;------------------------------------------------------------------------------
!insertmacro MUI_PAGE_WELCOME
Page custom uninstallOldVersionDialog
!ifdef LICENSE_FILE
@@ -458,51 +451,112 @@ LicenseLangString myLicenseData ${LANG_ENGLISH} "${LICENSE_FILE}.txt"
LicenseLangString myLicenseData ${LANG_JAPANESE} "${LICENSE_FILE}.txt"
!endif
Function .onInit
SetRegView 32
!insertmacro INSTALLOPTIONS_EXTRACT "Desktop.ini"
IfSilent silent_mode uac_elevate
silent_mode:
IntCmp ${CUSTOM_SILENT_CONFIG} 0 silent_config silent_config custom_silent_config
silent_config:
Call silentConfigReader
Goto set_reg_key
custom_silent_config:
Call customSilentConfigReader
set_reg_key:
StrCpy $baseRegKey "HKCU"
IfSilent UAC_Done
UAC_Elevate:
!insertmacro UAC_RunElevated
StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user? - continue install under user
StrCmp 0 $0 0 UAC_Err ; Error?
StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper?
Quit
UAC_Err:
Abort
UAC_ElevationAborted:
StrCpy $INSTDIR "$APPDATA\${MANUFACTURER}\${PRODUCT_WITH_VER}"
goto UAC_Done
UAC_Success:
StrCmp 1 $3 UAC_Admin ;Admin?
StrCmp 3 $1 0 UAC_ElevationAborted ;Try again?
goto UAC_Elevate
UAC_Admin:
${If} ${RunningX64}
StrCpy $INSTDIR "$PROGRAMFILES64\${MANUFACTURER}\${PRODUCT_WITH_VER}"
${Else}
StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}"
${EndIf}
SetShellVarContext all
StrCpy $baseRegKey "HKLM"
UAC_Done:
StrCmp $silentMode "admin" uac_elevate done
uac_elevate:
!insertmacro UAC_RunElevated
StrCmp 1223 $0 uac_elevation_aborted ; UAC dialog aborted by user? - continue install under user
StrCmp 0 $0 0 uac_err ; Error?
StrCmp 1 $1 0 uac_success ;Are we the real deal or just the wrapper?
Quit
uac_err:
Abort
uac_elevation_aborted:
IfSilent done set_install_dir
set_install_dir:
StrCpy $INSTDIR "$APPDATA\${MANUFACTURER}\${PRODUCT_WITH_VER}"
goto done
uac_success:
StrCmp 1 $3 uac_admin ;Admin?
StrCmp 3 $1 0 uac_elevation_aborted ;Try again?
goto uac_elevate
uac_admin:
IfSilent uac_all_users set_install_dir_admin_mode
set_install_dir_admin_mode:
${If} ${RunningX64}
StrCpy $INSTDIR "$PROGRAMFILES64\${MANUFACTURER}\${PRODUCT_WITH_VER}"
${Else}
StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}"
${EndIf}
uac_all_users:
SetShellVarContext all
StrCpy $baseRegKey "HKLM"
done:
; !insertmacro MUI_LANGDLL_DISPLAY
FunctionEnd
Function silentConfigReader
${GetParameters} $R0
ClearErrors
${GetOptions} $R0 /CONFIG= $R1
IfErrors no_silent_config
${ConfigRead} "$R1" "mode=" $R0
StrCpy $silentMode "user"
IfErrors launcher_32
StrCpy $silentMode $R0
launcher_32:
ClearErrors
${ConfigRead} "$R1" "launcher32=" $R3
IfErrors launcher_64
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "State" $R3
launcher_64:
ClearErrors
${ConfigRead} "$R1" "launcher64=" $R3
IfErrors download_jre32
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 3" "Type" "checkbox"
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 3" "State" $R3
download_jre32:
ClearErrors
${ConfigRead} "$R1" "jre32=" $R3
IfErrors associations
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "Type" "checkbox"
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 4" "State" $R3
associations:
ClearErrors
StrCmp "${ASSOCIATION}" "NoAssociation" done
!insertmacro INSTALLOPTIONS_READ $R0 "Desktop.ini" "Settings" "NumFields"
push "${ASSOCIATION}"
loop:
call SplitStr
Pop $0
StrCmp $0 "" update_settings
ClearErrors
${ConfigRead} "$R1" "$0=" $R3
IfErrors update_settings
IntOp $R0 $R0 + 1
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "State" $R3
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0"
goto loop
update_settings:
!insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0"
no_silent_config:
done:
FunctionEnd
Function checkVersion
StrCpy $2 ""
StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
; ${If} $0 == "HKLM"
; StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
; Push $0
; call winVersion
; ${If} $0 == "1"
; StrCpy $1 "Software\Wow6432Node\${MANUFACTURER}\${PRODUCT_REG_VER}"
; ${Else}
; StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
; ${EndIf}
; Pop $0
; ${EndIf}
Call OMReadRegStr
IfFileExists $3\bin\${PRODUCT_EXE_FILE} check_version
Goto Done
@@ -533,7 +587,7 @@ FunctionEnd
Function uninstallOldVersion
; uninstallation mode
;uninstallation mode
!insertmacro INSTALLOPTIONS_READ $9 "UninstallOldVersions.ini" "Field 2" "State"
${If} $9 == "1"
ExecWait '"$3\bin\Uninstall.exe" /S'
@@ -544,7 +598,7 @@ Function uninstallOldVersion
goto complete
uninstall:
;previous installation has been removed
;customer decided to keep properties?
;customer has decided to keep properties?
IfFileExists $3\bin\idea.properties saveProperties fullRemove
saveProperties:
Delete "$3\bin\Uninstall.exe"
@@ -563,12 +617,12 @@ StrCpy $6 ""
loop:
IntOp $7 $7 + 1
${If} $8 >= $7
!insertmacro INSTALLOPTIONS_READ $6 "UninstallOldVersions.ini" "Field $7" "Text"
${If} $6 == $3
;found the same value in list of installations
StrCpy $6 "duplicated"
Goto finish
${EndIf}
!insertmacro INSTALLOPTIONS_READ $6 "UninstallOldVersions.ini" "Field $7" "Text"
${If} $6 == $3
;found the same value in list of installations
StrCpy $6 "duplicated"
Goto finish
${EndIf}
Goto loop
${EndIf}
finish:
@@ -609,6 +663,7 @@ ${If} $0 == "HKLM"
StrCpy $4 0
Goto get_installation_info
${EndIf}
complete:
!insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Settings" "NumFields" "$8"
${If} $8 > $control_fields
@@ -710,7 +765,6 @@ continue_enum_versions_hkcu:
Goto enum_versions_hkcu
end_enum_versions_hkcu:
StrCpy $0 "0" # registry key index
enum_versions_hklm:
@@ -725,15 +779,14 @@ continue_enum_versions_hklm:
Goto enum_versions_hklm
end_enum_versions_hklm:
StrCmp $INSTDIR "" 0 skip_default_instdir
${If} ${RunningX64}
StrCpy $INSTDIR "$PROGRAMFILES64\${MANUFACTURER}\${MUI_PRODUCT} ${MUI_VERSION_MAJOR}.${MUI_VERSION_MINOR}"
${Else}
StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${MUI_PRODUCT} ${MUI_VERSION_MAJOR}.${MUI_VERSION_MINOR}"
${EndIf}
skip_default_instdir:
skip_default_instdir:
Pop $5
Pop $4
Pop $3
@@ -763,22 +816,60 @@ createRegistration:
FunctionEnd
Function ProductAssociation
push $0
push $1
push $2
push $3
StrCpy $2 ""
StrCmp $baseRegKey "HKLM" admin user
admin:
StrCpy $0 HKCR
StrCpy $R5 ${PRODUCT_PATHS_SELECTOR}
goto back_up
user:
StrCpy $0 HKCU
StrCpy $R4 "Software\Classes\$R4"
StrCpy $R5 "Software\Classes\${PRODUCT_PATHS_SELECTOR}"
back_up:
; back up old value of an association
ReadRegStr $1 HKCR $R4 ""
StrCmp $1 "" skip_backup
StrCmp $1 ${PRODUCT_PATHS_SELECTOR} skip_backup
WriteRegStr HKCR $R4 "backup_val" $1
StrCpy $1 $R4
call OMReadRegStr
StrCmp $3 "" skip_backup
StrCmp $3 ${PRODUCT_PATHS_SELECTOR} skip_backup
StrCpy $2 "backup_val"
Call OMWriteRegStr
skip_backup:
WriteRegStr HKCR $R4 "" "${PRODUCT_PATHS_SELECTOR}"
ReadRegStr $0 HKCR ${PRODUCT_PATHS_SELECTOR} ""
StrCmp $0 "" 0 command_exists
WriteRegStr HKCR ${PRODUCT_PATHS_SELECTOR} "" "${PRODUCT_FULL_NAME}"
WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\shell" "" "open"
WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\DefaultIcon" "" "$productLauncher,0"
StrCpy $2 ""
StrCpy $3 ${PRODUCT_PATHS_SELECTOR}
Call OMWriteRegStr
StrCpy $1 ${PRODUCT_PATHS_SELECTOR}
StrCpy $2 ""
Call OMReadRegStr
StrCmp $3 "" 0 command_exists
StrCpy $2 ""
StrCpy $3 "${PRODUCT_FULL_NAME}"
Call OMWriteRegStr
StrCpy $1 "$R5\shell"
StrCpy $2 ""
StrCpy $3 "open"
Call OMWriteRegStr
StrCpy $1 "$R5\DefaultIcon"
StrCpy $2 ""
StrCpy $3 "$productLauncher,0"
Call OMWriteRegStr
command_exists:
WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\DefaultIcon" "" " $productLauncher,0"
WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\shell\open\command" "" \
'"$productLauncher" "%1"'
StrCpy $1 "$R5\DefaultIcon"
StrCpy $2 ""
StrCpy $3 " $productLauncher,0"
Call OMWriteRegStr
StrCpy $1 "$R5\shell\open\command"
StrCpy $2 ""
StrCpy $3 '"$productLauncher" "%1"'
Call OMWriteRegStr
pop $3
pop $2
pop $1
pop $0
FunctionEnd
;------------------------------------------------------------------------------
@@ -786,20 +877,22 @@ FunctionEnd
;------------------------------------------------------------------------------
Section "IDEA Files" CopyIdeaFiles
CreateDirectory $INSTDIR
Call customInstallActions
SetRegView 32
; set up a launcher for associations
;define launcher in accordingly to OS version
${If} ${RunningX64}
StrCpy $productLauncher "$INSTDIR\bin\${PRODUCT_EXE_FILE_64}"
${Else}
StrCpy $productLauncher "$INSTDIR\bin\${PRODUCT_EXE_FILE}"
${EndIf}
DetailPrint "productLauncher: $productLauncher"
StrCmp "${LINK_TO_JRE}" "null" shortcuts 0
; download and install JRE x86
;download and install JRE x86
Call downloadJre
shortcuts:
; create shortcuts
!insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 2" "State"
StrCmp $R2 1 "" exe_64
CreateShortCut "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \
@@ -823,11 +916,7 @@ get_user_choice:
next_association:
IntOp $R2 $R2 + 1
IntCmp $R1 $R2 get_user_choice done get_user_choice
done:
Call customInstallActions
SetRegView 32
; registration application to be presented in Open With list
call ProductRegistration
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
@@ -867,10 +956,9 @@ done:
!undef Index
skip_ipr:
; readonly section
SectionIn RO
!include "idea_win.nsh"
!include "idea_win.nsh"
SetOutPath $INSTDIR\bin
File "${PRODUCT_PROPERTIES_FILE}"
@@ -1012,16 +1100,44 @@ UAC_Done:
FunctionEnd
Function un.ReturnBackupRegValue
Function un.RestoreBackupRegValue
;replace Default str with the backup value (if there is the one) and then delete backup
; $1 - key (for example ".java")
; $2 - name (for example "backup_val")
Push $0
ReadRegStr $0 HKCR $1 $2
StrCmp $0 "" "noBackup"
WriteRegStr HKCR $1 "" $0
DeleteRegValue HKCR $1 $2
noBackup:
Push $3
StrCmp $baseRegKey "HKLM" admin user
admin:
StrCpy $0 HKCR
goto read_backup_value
user:
StrCpy $0 HKCU
StrCpy $1 "Software\Classes\$1"
read_backup_value:
call un.OMReadRegStr
StrCmp $3 "" no_backup restore_backup
no_backup:
;clean default value if it contains current product info
StrCpy $2 ""
call un.OMReadRegStr
StrCmp $4 $3 0 done
call un.OMDeleteRegValue
goto done
restore_backup:
StrCmp $3 $4 remove_backup 0
push $2
StrCpy $2 ""
call un.OMWriteRegStr
pop $2
remove_backup:
call un.OMDeleteRegValue
done:
Pop $3
Pop $0
FunctionEnd
@@ -1225,7 +1341,7 @@ skip_delete_settings:
StrCmp $R9 "" registry
StrCpy $5 "Software\${MANUFACTURER}"
shortcuts:
;the user has the admin rights
;user has the admin rights
IfFileExists "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" keep_current_user
SetShellVarContext all
keep_current_user:
@@ -1244,13 +1360,17 @@ registry:
StrCmp "${ASSOCIATION}" "NoAssociation" finish_uninstall
push "${ASSOCIATION}"
loop:
StrCpy $2 "backup_val"
StrCpy $4 "${PRODUCT_PATHS_SELECTOR}"
call un.SplitStr
Pop $0
StrCmp $0 "" finish_uninstall
;restore backup association(s)
StrCpy $1 $0
StrCpy $2 "backup_val"
Call un.ReturnBackupRegValue
Call un.RestoreBackupRegValue
goto loop
finish_uninstall:
StrCpy $0 $baseRegKey
StrCpy $1 "$5\${PRODUCT_REG_VER}"
@@ -1275,8 +1395,16 @@ finish:
StrCpy $0 "HKCR"
StrCpy $1 "Applications\${PRODUCT_EXE_FILE}"
Call un.OMDeleteRegKey
StrCmp $baseRegKey "HKLM" admin user
admin:
StrCpy $0 "HKCR"
StrCpy $1 "${PRODUCT_PATHS_SELECTOR}"
goto delete_association
user:
StrCpy $0 "HKCU"
StrCpy $1 "Software\Classes\${PRODUCT_PATHS_SELECTOR}"
delete_association:
; remove product information which was used for association(s)
Call un.OMDeleteRegKey
StrCpy $0 "${MUI_LANGDLL_REGISTRY_ROOT}"
@@ -1287,6 +1415,7 @@ finish:
StrCpy $1 "IntelliJIdeaProjectFile\DefaultIcon"
StrCpy $2 ""
call un.OMReadRegStr
StrCmp $3 "$productDir\${PRODUCT_EXE_FILE},0" remove_IntelliJIdeaProjectFile done
remove_IntelliJIdeaProjectFile:
StrCpy $1 "IntelliJIdeaProjectFile"
-2
View File
@@ -81,8 +81,6 @@ Function ${un}OMReadRegStr
hkcr:
ReadRegStr $3 HKCR $1 $2
done:
IfErrors 0 +2
DetailPrint "ERROR: $0, $1, $2"
FunctionEnd
; -----------------------------------------------------------------------------
@@ -36,6 +36,7 @@ import com.intellij.openapi.project.VetoableProjectManagerListener;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindow;
@@ -75,6 +76,8 @@ public class BuildContentManagerImpl implements BuildContentManager {
public static final String Run = "Run";
public static final String Debug = "Debug";
private static final String[] ourPresetOrder = {Build, Sync, Run, Debug};
private static final Key<Map<Object, CloseListener>> CONTENT_CLOSE_LISTENERS = Key.create("CONTENT_CLOSE_LISTENERS");
private Project myProject;
private ToolWindow myToolWindow;
private final List<Runnable> myPostponedRunnables = new ArrayList<>();
@@ -263,9 +266,16 @@ public class BuildContentManagerImpl implements BuildContentManager {
return content;
}
public void startBuildNotified(@NotNull Content content, @Nullable BuildProcessHandler processHandler) {
public void startBuildNotified(@NotNull BuildDescriptor buildDescriptor,
@NotNull Content content,
@Nullable BuildProcessHandler processHandler) {
if (processHandler != null) {
new CloseListener(content, processHandler);
Map<Object, CloseListener> closeListenerMap = content.getUserData(CONTENT_CLOSE_LISTENERS);
if (closeListenerMap == null) {
closeListenerMap = ContainerUtil.newHashMap();
content.putUserData(CONTENT_CLOSE_LISTENERS, closeListenerMap);
}
closeListenerMap.put(buildDescriptor.getId(), new CloseListener(content, processHandler));
}
runWhenInitialized(() -> {
Pair<Icon, AtomicInteger> pair = liveContentsMap.computeIfAbsent(content, c -> Pair.pair(c.getIcon(), new AtomicInteger(0)));
@@ -280,7 +290,17 @@ public class BuildContentManagerImpl implements BuildContentManager {
});
}
public void finishBuildNotified(@NotNull Content content) {
public void finishBuildNotified(@NotNull BuildDescriptor buildDescriptor, @NotNull Content content) {
Map<Object, CloseListener> closeListenerMap = content.getUserData(CONTENT_CLOSE_LISTENERS);
if (closeListenerMap != null) {
CloseListener closeListener = closeListenerMap.remove(buildDescriptor.getId());
if (closeListener != null) {
Disposer.dispose(closeListener);
if (closeListenerMap.isEmpty()) {
content.putUserData(CONTENT_CLOSE_LISTENERS, null);
}
}
}
runWhenInitialized(() -> {
Pair<Icon, AtomicInteger> pair = liveContentsMap.get(content);
if (pair != null && pair.second.decrementAndGet() == 0) {
@@ -308,8 +328,10 @@ public class BuildContentManagerImpl implements BuildContentManager {
}
private class CloseListener extends ContentManagerAdapter implements VetoableProjectManagerListener, Disposable {
@Nullable
private Content myContent;
private final BuildProcessHandler myProcessHandler;
@Nullable
private BuildProcessHandler myProcessHandler;
private CloseListener(@NotNull final Content content, @NotNull BuildProcessHandler processHandler) {
myContent = content;
@@ -339,8 +361,11 @@ public class BuildContentManagerImpl implements BuildContentManager {
contentManager.removeContentManagerListener(this);
}
ProjectManager.getInstance().removeProjectManagerListener(myProject, this);
content.release();
myContent = null;
if (myProcessHandler instanceof Disposable) {
Disposer.dispose((Disposable)myProcessHandler);
}
myProcessHandler = null;
}
@Override
@@ -201,7 +201,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable {
boolean focusContent = contentDescriptor.isAutoFocusContent();
myBuildContentManager.setSelectedContent(
myContent, focusContent, focusContent, activateToolWindow, contentDescriptor.getActivationCallback());
Disposer.register(this, contentDescriptor);
Disposer.register(view, contentDescriptor);
}
else {
myBuildContentManager.setSelectedContent(myContent, true, true, true, null);
@@ -233,7 +233,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable {
}
myViewManager.onBuildStart(buildInfo);
myProgressWatcher.addBuild(buildInfo);
((BuildContentManagerImpl)myBuildContentManager).startBuildNotified(buildInfo.content, startBuildEvent.getProcessHandler());
((BuildContentManagerImpl)myBuildContentManager).startBuildNotified(buildInfo, buildInfo.content, startBuildEvent.getProcessHandler());
}
else {
if (event instanceof FinishBuildEvent) {
@@ -241,7 +241,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable {
buildInfo.message = event.getMessage();
buildInfo.result = ((FinishBuildEvent)event).getResult();
myProgressWatcher.stopBuild(buildInfo);
((BuildContentManagerImpl)myBuildContentManager).finishBuildNotified(buildInfo.content);
((BuildContentManagerImpl)myBuildContentManager).finishBuildNotified(buildInfo, buildInfo.content);
myViewManager.onBuildFinish(buildInfo);
}
else {
@@ -26,6 +26,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.impl.ExternalModuleListStorage;
import com.intellij.openapi.project.ModuleListener;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -60,6 +61,8 @@ import org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfig
import java.io.File;
import java.util.*;
import static com.intellij.compiler.ExternalCompilerConfigurationStorageKt.*;
import static com.intellij.util.JdomKt.element;
import static org.jetbrains.jps.model.java.impl.compiler.ResourcePatterns.normalizeWildcards;
import static org.jetbrains.jps.model.java.impl.compiler.ResourcePatterns.optimize;
import static org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfigurationSerializer.DEFAULT_WILDCARD_PATTERNS;
@@ -153,7 +156,6 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
@Override
public Element getState() {
Element state = new Element("state");
XmlSerializer.serializeInto(myState, state, new SkipDefaultValuesSerializationFilters() {
@Override
@@ -207,30 +209,17 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
state.addContent(annotationProcessingSettings);
}
if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !myModuleBytecodeTarget.isEmpty()) {
final Element bytecodeTarget = addChild(state, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
List<String> moduleNames = getFilteredModuleNameList(myProject, myModuleBytecodeTarget, false);
if (!StringUtil.isEmpty(myBytecodeTargetLevel) || !moduleNames.isEmpty()) {
final Element bytecodeTarget = element(state, JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
if (!StringUtil.isEmpty(myBytecodeTargetLevel)) {
bytecodeTarget.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, myBytecodeTargetLevel);
}
if (!myModuleBytecodeTarget.isEmpty()) {
final List<String> moduleNames = new ArrayList<>(myModuleBytecodeTarget.keySet());
Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER);
for (String name : moduleNames) {
final Element moduleElement = addChild(bytecodeTarget, JpsJavaCompilerConfigurationSerializer.MODULE);
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name);
final String value = myModuleBytecodeTarget.get(name);
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, value != null ? value : "");
}
}
writeBytecodeTarget(moduleNames, myModuleBytecodeTarget, bytecodeTarget);
}
return state;
}
@Override
public void loadState(Element state) {
readExternal(state);
}
@Override
public int getBuildProcessHeapSize(final int javacPreferredHeapSize) {
final int heapSize = myState.BUILD_PROCESS_HEAP_SIZE;
@@ -702,8 +691,8 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
return true;
}
public void readExternal(@NotNull Element parentNode) {
@Override
public void loadState(@NotNull Element parentNode) {
myState = XmlSerializer.deserialize(parentNode, State.class);
if (!myProject.isDefault()) {
for (Element option : parentNode.getChildren("option")) {
@@ -785,20 +774,16 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
myBytecodeTargetLevel = null;
myModuleBytecodeTarget.clear();
final Element bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
Element bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL);
if (bytecodeTargetElement != null) {
myBytecodeTargetLevel = bytecodeTargetElement.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE);
for (Element elem : bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) {
final String name = elem.getAttributeValue(JpsJavaCompilerConfigurationSerializer.NAME);
if (name == null) {
continue;
}
final String target = elem.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE);
if (target == null) {
continue;
}
myModuleBytecodeTarget.put(name, target);
}
readByteTargetLevel(parentNode);
}
Map<String, String> externalState = myProject.getComponent(ExternalCompilerConfigurationStorage.class).getLoadedState();
if (externalState != null) {
myModuleBytecodeTarget.putAll(externalState);
}
}
@@ -0,0 +1,85 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.compiler
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.module.impl.ModuleManagerImpl
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.isExternalStorageEnabled
import com.intellij.openapi.roots.ExternalProjectSystemRegistry
import com.intellij.openapi.roots.ProjectModelElement
import com.intellij.openapi.roots.ProjectModelExternalSource
import com.intellij.util.element
import gnu.trove.THashMap
import org.jdom.Element
import org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfigurationSerializer
import java.util.*
@State(name = "ExternalCompilerConfigurationStorage", storages = arrayOf(Storage("compiler.xml")), externalStorageOnly = true)
internal class ExternalCompilerConfigurationStorage(private val project: Project) : PersistentStateComponent<Element>, ProjectModelElement {
var loadedState: Map<String, String>? = null
private set
override fun getState(): Element {
val e = Element("state")
if (!project.isExternalStorageEnabled) {
return e
}
val map = (CompilerConfigurationImpl.getInstance(project) as CompilerConfigurationImpl).modulesBytecodeTargetMap
val moduleNames = getFilteredModuleNameList(project, map, true)
if (moduleNames.isNotEmpty()) {
writeBytecodeTarget(moduleNames, map, e.element(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL))
}
return e
}
override fun loadState(state: Element) {
loadedState = readByteTargetLevel(state)
}
override fun getExternalSource(): ProjectModelExternalSource? {
val externalProjectSystemRegistry = ExternalProjectSystemRegistry.getInstance()
for (module in ModuleManagerImpl.getInstanceImpl(project).modules) {
externalProjectSystemRegistry.getExternalSource(module)?.let {
return it
}
}
return null
}
}
internal fun getFilteredModuleNameList(project: Project, map: Map<String, String>, isExternal: Boolean): List<String> {
if (!project.isExternalStorageEnabled) {
return map.keys.toList()
}
val moduleManager = ModuleManagerImpl.getInstanceImpl(project)
val externalProjectSystemRegistry = ExternalProjectSystemRegistry.getInstance()
return map.keys.filter {
// if no module and !isExternal - return true because CompilerConfigurationImpl saves module name as is without module existence check and this logic is preserved
val module = moduleManager.findModuleByName(it) ?: return@filter !isExternal
(externalProjectSystemRegistry.getExternalSource(module) != null) == isExternal
}
}
internal fun writeBytecodeTarget(moduleNames: List<String>, map: Map<String, String>, element: Element) {
Collections.sort(moduleNames, String.CASE_INSENSITIVE_ORDER)
for (name in moduleNames) {
val moduleElement = element.element(JpsJavaCompilerConfigurationSerializer.MODULE)
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.NAME, name)
moduleElement.setAttribute(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE, map.get(name) ?: "")
}
}
internal fun readByteTargetLevel(parentNode: Element): Map<String, String> {
val result = THashMap<String, String>()
val bytecodeTargetElement = parentNode.getChild(JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL) ?: return result
for (element in bytecodeTargetElement.getChildren(JpsJavaCompilerConfigurationSerializer.MODULE)) {
val name = element.getAttributeValue(JpsJavaCompilerConfigurationSerializer.NAME) ?: continue
val target = element.getAttributeValue(JpsJavaCompilerConfigurationSerializer.TARGET_ATTRIBUTE) ?: continue
result.put(name, target)
}
return result
}
@@ -37,19 +37,21 @@ public class CorruptedBuildCachesTest extends BaseCompilerTestCase {
}
public void testSrcOutMapping() {
final String moduleName = "m";
final String moduleDirName = moduleName + "_" + Integer.toHexString(moduleName.hashCode());
VirtualFile a = createFile("src/A.java", "class A{}");
Module m = addModule("m", a.getParent());
Module m = addModule(moduleName, a.getParent());
make(m);
assertOutput(m, fs().file("A.class"));
File systemDirectory = BuildManager.getInstance().getProjectSystemDirectory(myProject);
assertTrue(FileUtil.delete(new File(systemDirectory, "targets/java-production/m/src-out")));
assertTrue(FileUtil.delete(new File(systemDirectory, "targets/java-production/"+moduleDirName+"/src-out")));
changeFile(a, "class A{int b;}");
make(m).assertGenerated("A.class");
make(m).assertUpToDate();
changeFile(a, "class A{int c;}");
corruptCaches(new File(systemDirectory, "targets/java-production/m/src-out/data"));
corruptCaches(new File(systemDirectory, "targets/java-production/"+moduleDirName+"/src-out/data"));
make(m).assertGenerated("A.class");
assertOutput(m, fs().file("A.class"));
@@ -558,7 +558,7 @@ public class DebugProcessEvents extends DebugProcessImpl {
if (event != null && myNotificationsCoolDown.compareAndSet(false, true)) {
AppExecutorUtil.getAppScheduledExecutorService().schedule(() -> myNotificationsCoolDown.set(false), 1, TimeUnit.SECONDS);
XDebuggerManagerImpl.NOTIFICATION_GROUP
.createNotification(DebuggerBundle.message("message.breakpoint.skipped", event.location()), MessageType.INFO)
.createNotification(DebuggerBundle.message("message.breakpoint.skipped", event.location()), MessageType.WARNING)
.notify(getProject());
}
}
@@ -474,17 +474,21 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
if (timeoutArg != null) {
timeoutArg.setValue("0"); // wait forever
}
String listeningAddress = connector.startListening(myArguments);
String port = StringUtil.substringAfter(listeningAddress, ":");
if (port != null) {
listeningAddress = port;
}
myConnection.setAddress(listeningAddress);
myDebugProcessDispatcher.getMulticaster().connectorIsReady();
try {
String listeningAddress = connector.startListening(myArguments);
String port = StringUtil.substringAfter(listeningAddress, ":");
if (port != null) {
listeningAddress = port;
}
myConnection.setAddress(listeningAddress);
myDebugProcessDispatcher.getMulticaster().connectorIsReady();
return connector.accept(myArguments);
}
catch (IllegalArgumentException e) {
throw new CantRunException(e.getLocalizedMessage());
}
finally {
if(myArguments != null) {
try {
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.engine;
import com.intellij.debugger.DebuggerBundle;
@@ -51,7 +37,7 @@ public abstract class JavaValueModifier extends XValueModifier {
@Override
public void calculateInitialValueEditorText(final XInitialValueCallback callback) {
final Value value = myJavaValue.getDescriptor().getValue();
if (value instanceof PrimitiveValue) {
if (value == null || value instanceof PrimitiveValue) {
String valueString = myJavaValue.getValueString();
int pos = valueString.lastIndexOf('('); //skip hex presentation if any
if (pos > 1) {
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.DebuggerBundle;
@@ -128,6 +114,11 @@ public abstract class EvaluationDescriptor extends ValueDescriptorImpl {
}
}
@Override
protected boolean isPrintExceptionToConsole() {
return false;
}
@Nullable
public Modifier getModifier() {
return myModifier;
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.DebuggerBundle;
@@ -31,7 +17,9 @@ import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.ui.tree.FieldDescriptor;
import com.intellij.debugger.ui.tree.NodeDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiExpression;
@@ -95,13 +83,32 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException {
DebuggerManagerThreadImpl.assertIsManagerThread();
try {
return (myObject != null) ? myObject.getValue(myField) : myField.declaringType().getValue(myField);
if (myObject != null) {
populateExceptionStackTraceIfNeeded(evaluationContext);
return myObject.getValue(myField);
}
else {
return myField.declaringType().getValue(myField);
}
}
catch (ObjectCollectedException ignored) {
throw EvaluateExceptionUtil.OBJECT_WAS_COLLECTED;
}
}
private void populateExceptionStackTraceIfNeeded(EvaluationContextImpl evaluationContext) {
if ("stackTrace".equals(getName()) &&
Registry.is("debugger.populate.exception.stack") &&
DebuggerUtils.instanceOf(myObject.type(), CommonClassNames.JAVA_LANG_THROWABLE)) {
try {
invokeExceptionGetStackTrace(myObject, evaluationContext);
}
catch (Throwable e) {
LOG.info(e); // catch all exceptions to ensure the method returns gracefully
}
}
}
public boolean isStatic() {
return myIsStatic;
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.ui.impl.watch;
import com.intellij.Patches;
@@ -221,7 +207,8 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
catch (EvaluateException e) {
myValueException = e;
setFailed(e);
myValue = getTargetExceptionWithStackTraceFilled(evaluationContext, e);
myValue = getTargetExceptionWithStackTraceFilled(evaluationContext, e,
isPrintExceptionToConsole() || ApplicationManager.getApplication().isUnitTestMode());
myIsExpandable = false;
}
finally {
@@ -231,24 +218,36 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
myIsNew = false;
}
protected boolean isPrintExceptionToConsole() {
return true;
}
@Nullable
private static ObjectReference getTargetExceptionWithStackTraceFilled(final EvaluationContextImpl evaluationContext, EvaluateException ex){
protected static Value invokeExceptionGetStackTrace(ObjectReference exceptionObj, EvaluationContextImpl evaluationContext)
throws EvaluateException {
Method method = ((ClassType)exceptionObj.referenceType()).concreteMethodByName("getStackTrace", "()[Ljava/lang/StackTraceElement;");
if (method != null) {
return evaluationContext.getDebugProcess().invokeMethod(evaluationContext, exceptionObj, method, Collections.emptyList());
}
return null;
}
@Nullable
private static ObjectReference getTargetExceptionWithStackTraceFilled(@Nullable EvaluationContextImpl evaluationContext,
EvaluateException ex,
boolean printToConsole) {
final ObjectReference exceptionObj = ex.getExceptionFromTargetVM();
if (exceptionObj != null && evaluationContext != null) {
try {
ClassType refType = (ClassType)exceptionObj.referenceType();
Method method = refType.concreteMethodByName("getStackTrace", "()[Ljava/lang/StackTraceElement;");
if (method != null) {
final DebugProcessImpl process = evaluationContext.getDebugProcess();
Value trace = process.invokeMethod(evaluationContext, exceptionObj, method, Collections.emptyList());
Value trace = invokeExceptionGetStackTrace(exceptionObj, evaluationContext);
// print to console as well
if (trace instanceof ArrayReference) {
ArrayReference traceArray = (ArrayReference)trace;
process.printToConsole(DebuggerUtils.getValueAsString(evaluationContext, exceptionObj) + "\n");
for (Value stackElement : traceArray.getValues()) {
process.printToConsole("\tat " + DebuggerUtils.getValueAsString(evaluationContext, stackElement) + "\n");
}
// print to console as well
if (printToConsole && trace instanceof ArrayReference) {
DebugProcessImpl process = evaluationContext.getDebugProcess();
ArrayReference traceArray = (ArrayReference)trace;
process.printToConsole(DebuggerUtils.getValueAsString(evaluationContext, exceptionObj) + "\n");
for (Value stackElement : traceArray.getValues()) {
process.printToConsole("\tat " + DebuggerUtils.getValueAsString(evaluationContext, stackElement) + "\n");
}
}
}
@@ -51,7 +51,7 @@
<text resource-bundle="messages/ExecutionBundle" key="remote.configuration.port.label"/>
</properties>
</component>
<component id="11a97" class="javax.swing.JTextField" binding="myPortField">
<component id="11a97" class="com.intellij.ui.components.fields.IntegerField" binding="myPortField" custom-create="true">
<constraints>
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
/*
* Class RemoteConfigurable
@@ -31,6 +17,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.components.fields.IntegerField;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -47,7 +34,7 @@ public class RemoteConfigurable extends SettingsEditor<RemoteConfiguration> {
private JRadioButton myRbAttach;
private JTextField myAddressField;
private JTextField myHostField;
private JTextField myPortField;
private IntegerField myPortField;
private JPanel myShmemPanel;
private JPanel mySocketPanel;
private ConfigurationArgumentsHelpArea myHelpArea;
@@ -147,6 +134,9 @@ public class RemoteConfigurable extends SettingsEditor<RemoteConfiguration> {
configuration.SHMEM_ADDRESS = null;
}
configuration.USE_SOCKET_TRANSPORT = myRbSocket.isSelected();
if (configuration.USE_SOCKET_TRANSPORT) {
myPortField.validateContent();
}
configuration.SERVER_MODE = myRbListen.isSelected();
myModuleSelector.applyTo(configuration);
}
@@ -199,5 +189,7 @@ public class RemoteConfigurable extends SettingsEditor<RemoteConfiguration> {
myJDK13HelpArea.updateText("-Xnoagent -Djava.compiler=NONE " + cmdLine);
}
private void createUIComponents() {
myPortField = new IntegerField("Port", 0, 0xFFFF);
}
}
@@ -473,7 +473,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
ContainerUtil.addIfNotNull(modifiableRootModels, modifiableRootModel);
}
ModuleDeleteProvider.removeModule(moduleToRemove, null, modifiableRootModels, myModuleModel);
ModuleDeleteProvider.removeModule(moduleToRemove, modifiableRootModels, myModuleModel);
Disposer.dispose(editor);
}
processModuleCountChanged();
@@ -171,47 +171,21 @@ public class ModuleHighlightUtil {
@NotNull
static List<HighlightInfo> checkDuplicateStatements(@NotNull PsiJavaModule module) {
List<HighlightInfo> results = ContainerUtil.newSmartList();
checkDuplicateRefs(
module.getRequires(),
st -> Optional.ofNullable(st.getReferenceElement()).map(PsiJavaModuleReferenceElement::getReferenceText),
"module.duplicate.requires",
results);
checkDuplicateRefs(
module.getExports(),
st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText),
"module.duplicate.exports",
results);
checkDuplicateRefs(
module.getOpens(),
st -> Optional.ofNullable(st.getPackageReference()).map(ModuleHighlightUtil::refText),
"module.duplicate.opens",
results);
checkDuplicateRefs(
module.getUses(),
st -> Optional.ofNullable(st.getClassReference()).map(ModuleHighlightUtil::qName),
"module.duplicate.uses",
results);
checkDuplicateRefs(
module.getProvides(),
st -> Optional.ofNullable(st.getInterfaceReference()).map(ModuleHighlightUtil::qName),
"module.duplicate.provides",
results);
checkDuplicateRefs(module.getRequires(), st -> st.getModuleName(), "module.duplicate.requires", results);
checkDuplicateRefs(module.getExports(), st -> st.getPackageName(), "module.duplicate.exports", results);
checkDuplicateRefs(module.getOpens(), st -> st.getPackageName(), "module.duplicate.opens", results);
checkDuplicateRefs(module.getUses(), st -> qName(st.getClassReference()), "module.duplicate.uses", results);
checkDuplicateRefs(module.getProvides(), st -> qName(st.getInterfaceReference()), "module.duplicate.provides", results);
return results;
}
private static <T extends PsiElement> void checkDuplicateRefs(Iterable<T> statements,
Function<T, Optional<String>> ref,
@PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String key,
List<HighlightInfo> results) {
private static <T extends PsiStatement> void checkDuplicateRefs(Iterable<T> statements,
Function<T, String> ref,
@PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String key,
List<HighlightInfo> results) {
Set<String> filter = ContainerUtil.newTroveSet();
for (T statement : statements) {
String refText = ref.apply(statement).orElse(null);
String refText = ref.apply(statement);
if (refText != null && !filter.add(refText)) {
String message = JavaErrorMessages.message(key, refText);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
@@ -226,20 +200,25 @@ public class ModuleHighlightUtil {
static List<HighlightInfo> checkUnusedServices(@NotNull PsiJavaModule module, @NotNull PsiFile file) {
List<HighlightInfo> results = ContainerUtil.newSmartList();
Set<String> exports = JBIterable.from(module.getExports()).map(st -> refText(st.getPackageReference())).filter(Objects::nonNull).toSet();
Set<String> uses = JBIterable.from(module.getUses()).map(st -> qName(st.getClassReference())).filter(Objects::nonNull).toSet();
Module host = findModuleForFile(file);
if (host != null) {
for (PsiProvidesStatement statement : module.getProvides()) {
PsiJavaCodeReferenceElement ref = statement.getInterfaceReference();
if (ref != null) {
PsiElement target = ref.resolve();
if (target instanceof PsiClass && findModuleForFile(target.getContainingFile()) == host) {
String className = qName(ref), packageName = StringUtil.getPackageName(className);
if (!exports.contains(packageName) && !uses.contains(className)) {
String message = JavaErrorMessages.message("module.service.unused");
results.add(HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(range(ref)).descriptionAndTooltip(message).create());
List<PsiProvidesStatement> provides = JBIterable.from(module.getProvides()).toList();
if (!provides.isEmpty()) {
Set<String> exports = JBIterable.from(module.getExports()).map(PsiPackageAccessibilityStatement::getPackageName).filter(Objects::nonNull).toSet();
Set<String> uses = JBIterable.from(module.getUses()).map(st -> qName(st.getClassReference())).filter(Objects::nonNull).toSet();
for (PsiProvidesStatement statement : provides) {
PsiJavaCodeReferenceElement ref = statement.getInterfaceReference();
if (ref != null) {
PsiElement target = ref.resolve();
if (target instanceof PsiClass && findModuleForFile(target.getContainingFile()) == host) {
String className = qName(ref), packageName = StringUtil.getPackageName(className);
if (!exports.contains(packageName) && !uses.contains(className)) {
String message = JavaErrorMessages.message("module.service.unused");
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(range(ref)).descriptionAndTooltip(message).create();
QuickFixAction.registerQuickFixAction(info, new AddExportsDirectiveFix(module, packageName, ""));
QuickFixAction.registerQuickFixAction(info, new AddUsesDirectiveFix(module, className));
results.add(info);
}
}
}
}
@@ -249,10 +228,6 @@ public class ModuleHighlightUtil {
return results;
}
private static String refText(PsiJavaCodeReferenceElement ref) {
return ref != null ? PsiNameHelper.getQualifiedClassName(ref.getText(), true) : null;
}
private static String qName(PsiJavaCodeReferenceElement ref) {
return ref != null ? ref.getQualifiedName() : null;
}
@@ -324,13 +299,13 @@ public class ModuleHighlightUtil {
if (module != null) {
PsiElement target = refElement.resolve();
PsiDirectory[] directories = target instanceof PsiPackage ? ((PsiPackage)target).getDirectories(module.getModuleScope(false)) : null;
String packageName = refText(refElement);
String packageName = statement.getPackageName();
HighlightInfoType type = statement.getRole() == Role.OPENS ? HighlightInfoType.WARNING : HighlightInfoType.ERROR;
if (directories == null || directories.length == 0) {
String message = JavaErrorMessages.message("package.not.found", packageName);
return HighlightInfo.newHighlightInfo(type).range(refElement).descriptionAndTooltip(message).create();
}
if (PsiUtil.isPackageEmpty(directories, packageName)) {
if (packageName != null && PsiUtil.isPackageEmpty(directories, packageName)) {
String message = JavaErrorMessages.message("package.is.empty", packageName);
return HighlightInfo.newHighlightInfo(type).range(refElement).descriptionAndTooltip(message).create();
}
@@ -40,11 +40,21 @@ class AddExportsDirectiveFix(module: PsiJavaModule,
if (existing == null) {
PsiUtil.addModuleStatement(module, PsiKeyword.EXPORTS + ' ' + packageName)
}
else {
else if (!targetName.isEmpty()) {
val targets = existing.moduleReferences.map { it.referenceText }
if (!targets.isEmpty() && targetName !in targets) {
existing.add(PsiElementFactory.SERVICE.getInstance(project).createModuleReferenceFromText(targetName))
}
}
}
}
class AddUsesDirectiveFix(module: PsiJavaModule, private val svcName: String) : AddModuleDirectiveFix(module) {
override fun getText() = QuickFixBundle.message("module.info.add.uses.name", svcName)
override fun invoke(project: Project, file: PsiFile, editor: Editor?, module: PsiJavaModule) {
if (module.uses.find { svcName == it.classReference?.qualifiedName } == null) {
PsiUtil.addModuleStatement(module, PsiKeyword.USES + ' ' + svcName)
}
}
}
@@ -564,7 +564,7 @@ public class DuplicatesFinder {
PsiElement child2 = children2[i];
if (!matchPattern(child1, child2, candidates, match)) {
matchedExtractablePart = matchExtractableExpression(child1, child2, candidates, match, true);
return matchedExtractablePart != null && matchedExtractablePart;
if (matchedExtractablePart == null || !matchedExtractablePart) return false;
}
}
@@ -308,6 +308,7 @@ extract.side.effects.family.name=Delete statement extracting side effects
module.info.add.directive.family.name=Add a directive to module-info.java
module.info.add.requires.name=Add ''requires {0}'' directive to module-info.java
module.info.add.exports.name=Add ''exports {0}'' directive to module-info.java
module.info.add.uses.name=Add ''uses {0}'' directive to module-info.java
collection.to.array.text=Apply conversion ''.toArray({0})''
collection.to.array.family.name=Apply conversion '.toArray()'
@@ -1,30 +1,17 @@
/*
* 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.
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.execution.configuration;
import com.intellij.openapi.application.PathMacroFilter;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class JavaRunConfigurationPathMacroFilter extends PathMacroFilter {
@Override
public boolean skipPathMacros(Attribute attribute) {
public boolean skipPathMacros(@NotNull Attribute attribute) {
final Element parent = attribute.getParent();
if (parent.getName().equals("option")) {
@@ -811,7 +811,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
*
* @param child variable declaration child node which alignment is to be defined
* @return alignment to use for the given node
* @see CodeStyleSettings#ALIGN_GROUP_FIELD_DECLARATIONS
* @see CommonCodeStyleSettings#ALIGN_GROUP_FIELD_DECLARATIONS
*/
private boolean shouldAlignFieldInColumns(@NotNull ASTNode child) {
// The whole idea of variable declarations alignment is that complete declaration blocks which children are to be aligned hold
@@ -521,7 +521,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
/**
* Initializes {@link #myResult} property with {@link Spacing} which {@code 'min line feeds'} property is defined
* from {@link CodeStyleSettings#BLANK_LINES_AROUND_CLASS} value.
* from {@link CommonCodeStyleSettings#BLANK_LINES_AROUND_CLASS} value.
*/
private void setAroundClassSpacing() {
myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, mySettings.BLANK_LINES_AROUND_CLASS + 1,
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi;
import org.jetbrains.annotations.Nullable;
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.compiled;
import com.intellij.openapi.util.text.StringUtil;
@@ -1,25 +1,8 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiUsesStatement;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiUsesStatementStub;
import com.intellij.psi.util.PsiTreeUtil;
@@ -0,0 +1,17 @@
class WriteDifferentFieldsDuplicate {
Runnable x;
Runnable y;
private void foo() {
<selection>
if (x != null) {
x.run();
x = null;
}</selection>
if (y != null) {
y.run();
y = null;
}
}
}
@@ -0,0 +1,21 @@
class WriteDifferentFieldsDuplicate {
Runnable x;
Runnable y;
private void foo() {
newMethod();
if (y != null) {
y.run();
y = null;
}
}
private void newMethod() {
if (x != null) {
x.run();
x = null;
}
}
}
@@ -21,8 +21,6 @@ import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.testFramework.LightCodeInsightTestCase;
@@ -43,81 +41,81 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
public void testLiteralSCR4989() { doTest(); }
public void testSCR3493() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
}
}
public void testSCR3493a() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
}
}
public void testSCR3493b() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
}
}
public void testSCR3493c() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
}
}
public void testSCR3493d() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
}
}
public void testSCR3493e() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
}
}
public void testSCR5959() {
@@ -138,49 +136,54 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
public void testDeclarationWithInitializer() {doTest(); }
public void testUnwrapCodeBlock1() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
int old = settings.IF_BRACE_FORCE;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_IF_MULTILINE;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = old;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
settings.IF_BRACE_FORCE = old;
}
}
public void testUnwrapCodeBlock2() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
boolean use_tab_character = settings.useTabCharacter(null);
boolean smart_tabs = settings.isSmartTabs(null);
CommonCodeStyleSettings settings = getJavaSettings();
boolean use_tab_character = settings.getIndentOptions().USE_TAB_CHARACTER;
boolean smart_tabs = settings.getIndentOptions().SMART_TABS;
int old = settings.IF_BRACE_FORCE;
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS;
doTest();
} finally {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = smart_tabs;
settings.getCommonSettings(JavaLanguage.INSTANCE).IF_BRACE_FORCE = old;
settings.getIndentOptions().USE_TAB_CHARACTER = use_tab_character;
settings.getIndentOptions().SMART_TABS = smart_tabs;
settings.IF_BRACE_FORCE = old;
}
}
@NotNull
protected CommonCodeStyleSettings getJavaSettings() {
return CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE);
}
public void testAssignmentExpression() {
doTest();
}
public void testReformatInsertsNewlines() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
CommonCodeStyleSettings settings = getJavaSettings();
final Element root = new Element("fake");
settings.writeExternal(root);
try {
settings.getIndentOptions(StdFileTypes.JAVA).USE_TAB_CHARACTER = true;
settings.getIndentOptions(StdFileTypes.JAVA).SMART_TABS = true;
settings.getIndentOptions().USE_TAB_CHARACTER = true;
settings.getIndentOptions().SMART_TABS = true;
settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS;
settings.METHOD_BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
doTest();
@@ -190,7 +193,7 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
}
public void testForceBrace() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
CommonCodeStyleSettings settings = getJavaSettings();
int old = settings.IF_BRACE_FORCE;
try {
settings.IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS;
@@ -201,8 +204,8 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
}
public void testWrongWrapping() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.setDefaultRightMargin(80);
CommonCodeStyleSettings settings = getJavaSettings();
settings.RIGHT_MARGIN = 80;
settings.CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
doTest();
@@ -210,9 +213,9 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
public void testSubsequentJoiningAndUnexpectedTextRemoval() {
// Inspired by IDEA-65342
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.setDefaultRightMargin(50);
settings.getCommonSettings(JavaLanguage.INSTANCE).CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
CommonCodeStyleSettings settings = getJavaSettings();
settings.RIGHT_MARGIN = 50;
settings.CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doTest(2);
}
@@ -223,7 +226,7 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
}
public void testJoiningMethodCallWhenItDoesntFit() {
CommonCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE);
CommonCodeStyleSettings settings = getJavaSettings();
settings.METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
settings.RIGHT_MARGIN = 20;
doTest();
@@ -232,7 +235,7 @@ public class JoinLinesTest extends LightCodeInsightTestCase {
public void testMultipleBlockComments() { doTest(); }
public void testPreserveSpaceIfOnNewLineOptionEnabled() {
CommonCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE);
CommonCodeStyleSettings settings = getJavaSettings();
settings.CATCH_ON_NEW_LINE = true;
doTest();
}
@@ -221,6 +221,9 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() {
addFile("module-info.java", "module M2 { }", M2)
fixes("module M { requires M2; uses <caret>pkg.m2.C2; }", arrayOf("AddExportsDirectiveFix"))
fixes("pkg/main/C.java", "package pkg.main;\nimport <caret>pkg.m2.C2;", arrayOf("AddExportsDirectiveFix"))
addFile("pkg/main/S.java", "package pkg.main;\npublic class S { }")
fixes("module M { provides pkg.main.<caret>S with pkg.main.S; }", arrayOf("AddExportsDirectiveFix", "AddUsesDirectiveFix"))
}
fun testPackageAccessibility() = doTestPackageAccessibility(moduleFileInTests = false, checkFileInTests = false)
@@ -3,6 +3,7 @@ package com.intellij.java.codeInsight.daemon.quickFix
import com.intellij.codeInsight.daemon.impl.quickfix.AddExportsDirectiveFix
import com.intellij.codeInsight.daemon.impl.quickfix.AddRequiresDirectiveFix
import com.intellij.codeInsight.daemon.impl.quickfix.AddUsesDirectiveFix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.java.testFramework.fixtures.LightJava9ModulesCodeInsightFixtureTestCase
import com.intellij.openapi.command.WriteCommandAction
@@ -57,6 +58,11 @@ class AddModuleDirectiveTest : LightJava9ModulesCodeInsightFixtureTestCase() {
"module M { exports pkg.m to M1, M2; }",
"module M { exports pkg.m to M1, M2; }")
fun testNoExportsToUnnamed() = doExportsTest(
"module M { exports pkg.m to M1; }",
"module M { exports pkg.m to M1; }",
target = "")
fun testExportsExtendsOther() = doExportsTest(
"module M {\n" +
" exports pkg.m to M1;\n" +
@@ -73,8 +79,28 @@ class AddModuleDirectiveTest : LightJava9ModulesCodeInsightFixtureTestCase() {
" exports pkg.m to M1, M2\n" +
"}")
fun testNewUses() = doUsesTest(
"module M { }",
"module M {\n" +
" uses pkg.m.C;\n" +
"}")
fun testUsesAfterOther() = doUsesTest(
"module M {\n" +
" uses pkg.m.B;\n" +
"}",
"module M {\n" +
" uses pkg.m.B;\n" +
" uses pkg.m.C;\n" +
"}")
fun testNoDuplicateUses() = doUsesTest(
"module M { uses pkg.m.C; }",
"module M { uses pkg.m.C; }")
private fun doRequiresTest(text: String, expected: String) = doTest(text, { AddRequiresDirectiveFix(it, "M2") }, expected)
private fun doExportsTest(text: String, expected: String) = doTest(text, { AddExportsDirectiveFix(it, "pkg.m", "M2") }, expected)
private fun doExportsTest(text: String, expected: String, target: String = "M2") = doTest(text, { AddExportsDirectiveFix(it, "pkg.m", target) }, expected)
private fun doUsesTest(text: String, expected: String) = doTest(text, { AddUsesDirectiveFix(it, "pkg.m.C") }, expected)
private fun doTest(text: String, fix: (PsiJavaModule) -> IntentionAction, expected: String) {
val file = myFixture.configureByText("module-info.java", text) as PsiJavaFile
@@ -83,7 +83,7 @@ public class DetectIndentAndTypeTest extends LightPlatformCodeInsightFixtureTest
public void testContinuationTab_AsTabSize() {
CommonCodeStyleSettings common = mySettings.getCommonSettings(JavaLanguage.INSTANCE);
mySettings.ALIGN_MULTILINE_BINARY_OPERATION = false;
common.ALIGN_MULTILINE_BINARY_OPERATION = false;
CommonCodeStyleSettings.IndentOptions indentOptions = common.getIndentOptions();
assert indentOptions != null;
@@ -106,7 +106,7 @@ public class DetectIndentAndTypeTest extends LightPlatformCodeInsightFixtureTest
public void testContinuationTabs_AsDoubleTabSize() {
CommonCodeStyleSettings common = mySettings.getCommonSettings(JavaLanguage.INSTANCE);
mySettings.ALIGN_MULTILINE_BINARY_OPERATION = false;
common.ALIGN_MULTILINE_BINARY_OPERATION = false;
CommonCodeStyleSettings.IndentOptions indentOptions = common.getIndentOptions();
assert indentOptions != null;
@@ -106,7 +106,7 @@ public class IndentTest extends LightIdeaTestCase {
public void testParenthesizedContinuation() throws Exception {
defaultSettings();
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
CommonCodeStyleSettings settings = getJavaSettings();
settings.ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION = true;
doTest("ParenthesizedContinuation.java", "ParenthesizedContinuation_after.java");
@@ -115,7 +115,7 @@ public class IndentTest extends LightIdeaTestCase {
public void testParenthesizedContinuation2() throws Exception {
defaultSettings();
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
CommonCodeStyleSettings settings = getJavaSettings();
settings.ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION = true;
doTest("ParenthesizedContinuation2.java", "ParenthesizedContinuation2_after.java");
@@ -159,7 +159,7 @@ public class IndentTest extends LightIdeaTestCase {
}
private void defaultSettings() {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
CommonCodeStyleSettings settings = getJavaSettings();
settings.ALIGN_MULTILINE_PARAMETERS = true;
settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = false;
@@ -1953,16 +1953,17 @@ class JavaFormatterTest : AbstractJavaFormatterTest() {
}
fun testWrapParamsOnEveryItem() {
val codeStyleSettings = CodeStyleSettingsManager.getSettings(LightPlatformTestCase.getProject())
val codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject())
val oldMargin = codeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE).RIGHT_MARGIN
val oldKeep = codeStyleSettings.KEEP_LINE_BREAKS
val oldWrap = codeStyleSettings.METHOD_PARAMETERS_WRAP
val javaSettings = codeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE)
val oldMargin = javaSettings.RIGHT_MARGIN
val oldKeep = javaSettings.KEEP_LINE_BREAKS
val oldWrap = javaSettings.METHOD_PARAMETERS_WRAP
try {
codeStyleSettings.setRightMargin(JavaLanguage.INSTANCE, 80)
codeStyleSettings.KEEP_LINE_BREAKS = false
codeStyleSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM
javaSettings.KEEP_LINE_BREAKS = false
javaSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM
doClassTest(
"public void foo(String p1,\n" +
@@ -1986,8 +1987,8 @@ class JavaFormatterTest : AbstractJavaFormatterTest() {
}
finally {
codeStyleSettings.setRightMargin(JavaLanguage.INSTANCE, oldMargin)
codeStyleSettings.KEEP_LINE_BREAKS = oldKeep
codeStyleSettings.METHOD_PARAMETERS_WRAP = oldWrap
javaSettings.KEEP_LINE_BREAKS = oldKeep
javaSettings.METHOD_PARAMETERS_WRAP = oldWrap
}
}
@@ -1,26 +1,10 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.psi.formatter.java;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
public class JavaWrapOnTypingTest extends LightCodeInsightFixtureTestCase {
public void testWrapInsideTags() {
myFixture.configureByText(JavaFileType.INSTANCE,
"public class Hw {\n" +
@@ -51,4 +35,32 @@ public class JavaWrapOnTypingTest extends LightCodeInsightFixtureTestCase {
" }\n" +
"}\n");
}
public void testWrapAtLineWithParameterHints() {
myFixture.configureByText(JavaFileType.INSTANCE,
"public class C {\n" +
" void m(int a, int b) {}\n" +
" void other() { m(1, 2<caret>); }\n" +
"}");
myFixture.doHighlighting();
myFixture.checkResultWithInlays("public class C {\n" +
" void m(int a, int b) {}\n" +
" void other() { m(<hint text=\"a:\"/>1, <hint text=\"b:\"/>2<caret>); }\n" +
"}");
myFixture.getEditor().getSettings().setWrapWhenTypingReachesRightMargin(true);
myFixture.getEditor().getSettings().setRightMargin(30);
myFixture.type(" ");
myFixture.checkResultWithInlays("public class C {\n" +
" void m(int a, int b) {}\n" +
" void other() { m(<hint text=\"a:\"/>1, <hint text=\"b:\"/>2 <caret>); }\n" +
"}");
myFixture.type(" ");
myFixture.checkResultWithInlays("public class C {\n" +
" void m(int a, int b) {}\n" +
" void other() { m(<hint text=\"a:\"/>1, <hint text=\"b:\"/>2 <caret>\n" +
" ); }\n" +
"}");
}
}
@@ -1177,6 +1177,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doTest();
}
public void testWriteDifferentFieldsDuplicate() throws Exception {
doDuplicatesTest();
}
private void doTestDisabledParam() throws PrepareFailedException {
final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.ELSE_ON_NEW_LINE = true;
@@ -0,0 +1,129 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.roots.ui.configuration.actions;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.UnloadedModuleDescription;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TestDialog;
import com.intellij.testFramework.MapDataContext;
import com.intellij.testFramework.PlatformTestCase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author nik
*/
public class ModuleDeleteProviderTest extends PlatformTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
Messages.setTestDialog(TestDialog.OK);
}
public void testSimple() {
createModule("a");
assertNotNull(getModuleManager().findModuleByName("a"));
deleteModules("a");
assertNull(getModuleManager().findModuleByName("a"));
}
public void testDeleteDependency() {
Module a = createModule("a");
Module b = createModule("b");
ModuleRootModificationUtil.addDependency(a, b);
assertSameElements(ModuleRootManager.getInstance(a).getDependencyModuleNames(), "b");
deleteModules("b");
assertEmpty(ModuleRootManager.getInstance(a).getDependencyModuleNames());
}
public void testDeleteTwoModules() {
Module a = createModule("a");
Module b = createModule("b");
ModuleRootModificationUtil.addDependency(a, b);
ModuleRootModificationUtil.addDependency(myModule, a);
ModuleRootModificationUtil.addDependency(myModule, b);
assertSameElements(ModuleRootManager.getInstance(myModule).getDependencyModuleNames(), "a", "b");
deleteModules("a", "b");
assertNull(getModuleManager().findModuleByName("a"));
assertNull(getModuleManager().findModuleByName("b"));
assertEmpty(ModuleRootManager.getInstance(myModule).getDependencyModuleNames());
}
public void testUnloaded() {
createModule("a");
getModuleManager().setUnloadedModules(Arrays.asList("a"));
assertNotNull(getModuleManager().getUnloadedModuleDescription("a"));
deleteModules("a");
assertNull(getModuleManager().getUnloadedModuleDescription("a"));
}
public void testDeleteDependencyOnUnloadedModule() {
Module a = createModule("a");
Module b = createModule("b");
ModuleRootModificationUtil.addDependency(a, b);
getModuleManager().setUnloadedModules(Arrays.asList("b"));
assertSameElements(ModuleRootManager.getInstance(a).getDependencyModuleNames(), "b");
deleteModules("b");
assertEmpty(ModuleRootManager.getInstance(a).getDependencyModuleNames());
}
public void testLoadedAndUnloadedModule() {
Module a = createModule("a");
Module b = createModule("b");
ModuleRootModificationUtil.addDependency(a, b);
ModuleRootModificationUtil.addDependency(myModule, a);
ModuleRootModificationUtil.addDependency(myModule, b);
getModuleManager().setUnloadedModules(Arrays.asList("a"));
assertSameElements(ModuleRootManager.getInstance(myModule).getDependencyModuleNames(), "a", "b");
deleteModules("a", "b");
assertNull(getModuleManager().findModuleByName("a"));
assertNull(getModuleManager().findModuleByName("b"));
assertEmpty(getModuleManager().getUnloadedModuleDescriptions());
assertEmpty(ModuleRootManager.getInstance(myModule).getDependencyModuleNames());
}
private ModuleManager getModuleManager() {
return ModuleManager.getInstance(myProject);
}
private void deleteModules(String... names) {
ModuleDeleteProvider provider = new ModuleDeleteProvider();
MapDataContext dataContext = new MapDataContext();
dataContext.put(CommonDataKeys.PROJECT, myProject);
List<Module> modules = new ArrayList<>();
List<UnloadedModuleDescription> unloaded = new ArrayList<>();
for (String name : names) {
UnloadedModuleDescription description = getModuleManager().getUnloadedModuleDescription(name);
if (description != null) {
unloaded.add(description);
}
else {
Module module = getModuleManager().findModuleByName(name);
assertNotNull("Module " + name + " not found", module);
modules.add(module);
}
}
if (!modules.isEmpty()) {
dataContext.put(LangDataKeys.MODULE_CONTEXT_ARRAY, modules.toArray(Module.EMPTY_ARRAY));
}
if (!unloaded.isEmpty()) {
dataContext.put(ProjectView.UNLOADED_MODULES_CONTEXT_KEY, unloaded);
}
assertTrue(provider.canDeleteElement(dataContext));
provider.deleteElement(dataContext);
}
@Override
public void tearDown() throws Exception {
Messages.setTestDialog(TestDialog.DEFAULT);
super.tearDown();
}
}
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.application;
import org.jdom.Attribute;
@@ -34,7 +20,7 @@ public abstract class PathMacroFilter {
return false;
}
public boolean skipPathMacros(Attribute attribute) {
public boolean skipPathMacros(@NotNull Attribute attribute) {
return false;
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.jps.model.serialization;
import com.intellij.openapi.diagnostic.Logger;
@@ -57,7 +43,7 @@ public abstract class JpsLoaderBase {
String fileName = serializer.getConfigFileName();
Path configFile = fileName == null ? defaultConfigFile : dir.resolve(fileName);
Runnable timingLog = TimingLog.startActivity("loading: " + configFile.getFileName() + ":" + serializer.getComponentName());
Element componentTag = JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName());
Element componentTag = loadComponentData(serializer, configFile);
if (componentTag != null) {
serializer.loadExtension(element, componentTag);
}
@@ -67,6 +53,11 @@ public abstract class JpsLoaderBase {
timingLog.run();
}
@Nullable
private <E extends JpsElement> Element loadComponentData(@NotNull JpsElementExtensionSerializerBase<E> serializer, Path configFile) {
return JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName());
}
/**
* Returns null if file doesn't exist
*/
@@ -110,6 +110,12 @@ public class JpsProjectLoader extends JpsLoaderBase {
return dir.getParent().getFileName().toString();
}
@Nullable
@Override
protected Element loadRootElement(@NotNull Path file) {
return super.loadRootElement(file);
}
private void loadFromDirectory(@NotNull Path dir) {
myProject.setName(getDirectoryBaseProjectName(dir));
Path defaultConfigFile = dir.resolve("misc.xml");
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.search;
import com.intellij.openapi.actionSystem.DataContext;
@@ -0,0 +1,16 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.search;
import com.intellij.openapi.extensions.ExtensionPointName;
import java.util.List;
public interface SearchScopeProvider {
ExtensionPointName<SearchScopeProvider> EP = ExtensionPointName.create("com.intellij.searchScopesProvider");
/**
* General project scopes are added after 'Project', 'Everything' but before 'Production', 'Tests', etc.
* @see PredefinedSearchScopeProvider
*/
List<SearchScope> getGeneralProjectScopes();
}
@@ -222,10 +222,6 @@ class LinuxDistributionBuilder extends OsSpecificDistributionBuilder {
}
}
buildContext.ant.concat(destfile: "${unixDistPath}/bin/idea.properties", append: true) {
filelist(dir: "${buildContext.paths.communityHome}/platform/build-scripts/resources/linux/snap", files: "idea-snap.properties")
}
buildContext.ant.delete(quiet: true) {
fileset(dir: "${unixDistPath}/bin") {
include(name: "fsnotifier")
@@ -16,8 +16,9 @@
package org.jetbrains.intellij.build.images
import com.intellij.openapi.util.text.StringUtil
import java.awt.*
import java.awt.Dimension
import java.io.File
import javax.imageio.ImageIO
internal val File.children: List<File> get() = if (isDirectory) listFiles().toList() else emptyList()
@@ -35,27 +36,12 @@ internal fun isIcon(file: File): Boolean {
private fun isImage(name: String) = name.endsWith(".png") || name.endsWith(".gif")
internal fun imageSize(file: File): Dimension? {
val image = loadImage(file) ?: return null
val image = ImageIO.read(file) ?: return null
val width = image.getWidth(null)
val height = image.getHeight(null)
return Dimension(width, height)
}
private fun loadImage(file: File): Image? {
val image = Toolkit.getDefaultToolkit().createImage(file.absolutePath)
if (!waitForImage(image)) return null
return image
}
private fun waitForImage(image: Image?): Boolean {
if (image == null) return false
if (image.getWidth(null) > 0) return true
val mediaTracker = MediaTracker(object : Component() {})
mediaTracker.addImage(image, 1)
mediaTracker.waitForID(1, 5000)
return !mediaTracker.isErrorID(1)
}
internal enum class ImageType(private val suffix: String) {
BASIC(""), RETINA("@2x"), DARCULA("_dark"), RETINA_DARCULA("@2x_dark");
@@ -1,6 +0,0 @@
#-----------------------------------------------------------------------
# Snap-specific properties
#-----------------------------------------------------------------------
idea.skip.desktop.entry.step=true
ide.no.platform.update=Snap
@@ -36,7 +36,7 @@ private open class ModuleStoreImpl(module: Module, private val pathMacroManager:
override fun <T> getStorageSpecs(component: PersistentStateComponent<T>, stateSpec: State, operation: StateStorageOperation): List<Storage> {
val result = super.getStorageSpecs(component, stateSpec, operation)
return StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny {
LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager.componentManager!!, result, operation) }
LOG.runAndLogException { it.customizeStorageSpecs(component, storageManager.componentManager!!, stateSpec, result, operation) }
} ?: result
}
}
@@ -201,7 +201,7 @@ abstract class ProjectStoreBase(override final val project: ProjectImpl) : Compo
else {
result!!.sortWith(deprecatedComparator)
StreamProviderFactory.EP_NAME.getExtensions(project).computeIfAny {
LOG.runAndLogException { it.customizeStorageSpecs(component, project, result!!, operation) }
LOG.runAndLogException { it.customizeStorageSpecs(component, project, stateSpec, result!!, operation) }
}?.let {
// yes, DEPRECATED_PROJECT_FILE_STORAGE_ANNOTATION is not added in this case
return it
@@ -130,16 +130,7 @@ class StateMap private constructor(private val names: Array<String>, private val
fun hasState(key: String) = get(key) is Element
fun hasStates(): Boolean {
if (isEmpty()) {
return false
}
for (i in names.indices) {
if (states.get(i) is Element) {
return true
}
}
return false
return !isEmpty() && names.indices.any { states.get(it) is Element }
}
fun compare(key: String, newStates: StateMap, diffs: MutableSet<String>) {
@@ -241,16 +232,5 @@ private fun arrayEquals(a: ByteArray, a2: ByteArray, size: Int = a.size): Boolea
if (a === a2) {
return true
}
if (a2.size != size) {
return false
}
for (i in 0 until size) {
if (a[i] != a2[i]) {
return false
}
}
return true
return a2.size == size && (0 until size).none { a[it] != a2[it] }
}
@@ -174,7 +174,14 @@ open class StateStorageManagerImpl(private val rootTagName: String,
key = normalizedCollapsedPath
}
else {
key = storageClass.name!!
val storageClassName = storageClass.name!!
// we cannot change this ancient logic for now, so, detect this case manually
if (storageClassName === "com.intellij.openapi.externalSystem.configurationStore.ExternalProjectStorage") {
key = "$normalizedCollapsedPath@ExternalProjectStorage"
}
else {
key = storageClassName
}
}
val storage = storageLock.read { storages.get(key) } ?: return storageLock.write {
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2011 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.graph;
import com.intellij.openapi.components.ServiceManager;
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.core;
import com.intellij.codeInsight.folding.CodeFoldingSettings;
@@ -66,6 +52,8 @@ import com.intellij.psi.stubs.CoreStubTreeLoader;
import com.intellij.psi.stubs.StubTreeLoader;
import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import com.intellij.util.graph.GraphAlgorithms;
import com.intellij.util.graph.impl.GraphAlgorithmsImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.picocontainer.MutablePicoContainer;
@@ -126,12 +114,12 @@ public class CoreApplicationEnvironment {
registerApplicationService(StubTreeLoader.class, new CoreStubTreeLoader());
registerApplicationService(PsiReferenceService.class, new PsiReferenceServiceImpl());
registerApplicationService(MetaDataRegistrar.class, new MetaRegistry());
registerApplicationService(ProgressManager.class, createProgressIndicatorProvider());
registerApplicationService(JobLauncher.class, createJobLauncher());
registerApplicationService(CodeFoldingSettings.class, new CodeFoldingSettings());
registerApplicationService(CommandProcessor.class, new CoreCommandProcessor());
registerApplicationService(GraphAlgorithms.class, new GraphAlgorithmsImpl());
myApplication.registerService(ApplicationInfo.class, ApplicationInfoImpl.class);
}
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.graph.impl;
import com.intellij.util.containers.ContainerUtil;
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.graph.impl;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2011 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.graph.impl;
import org.jetbrains.annotations.NotNull;
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2011 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.graph.impl;
import com.intellij.openapi.diagnostic.Logger;
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2011 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.graph.impl;
import com.intellij.util.graph.Graph;
@@ -139,7 +139,9 @@ public class DocumentContentImpl extends DiffContentBase implements DocumentCont
public void navigate(boolean requestFocus) {
Document targetDocument = FileDocumentManager.getInstance().getDocument(myTargetFile);
LineCol targetPosition = translatePosition(myDocument, targetDocument, myPosition);
OpenFileDescriptor descriptor = new OpenFileDescriptor(myProject, myTargetFile, targetPosition.line, targetPosition.column);
OpenFileDescriptor descriptor = targetDocument != null
? new OpenFileDescriptor(myProject, myTargetFile, targetPosition.toOffset(targetDocument))
: new OpenFileDescriptor(myProject, myTargetFile, targetPosition.line, targetPosition.column);
if (descriptor.canNavigate()) descriptor.navigate(true);
}
@@ -33,12 +33,7 @@ internal open class ExternalProjectStorage(fileSpec: String, project: Project, s
override fun createSaveSession(states: StateMap) = object : XmlElementStorageSaveSession<ExternalProjectStorage>(states, this) {
override fun saveLocally(element: Element?) {
if (element == null) {
manager.fileStorage.remove(fileSpec)
}
else {
manager.fileStorage.write(fileSpec, element)
}
manager.fileStorage.write(fileSpec, element)
}
}
}
@@ -63,7 +63,7 @@ internal class ExternalSystemStreamProviderFactory(private val project: Project)
})
}
override fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, storages: List<Storage>, operation: StateStorageOperation): List<Storage>? {
override fun customizeStorageSpecs(component: PersistentStateComponent<*>, componentManager: ComponentManager, stateSpec: State, storages: List<Storage>, operation: StateStorageOperation): List<Storage>? {
val project = componentManager as? Project ?: (componentManager as Module).project
// we store isExternalStorageEnabled option in the project workspace file, so, for such components external storage is always disabled and not applicable
if ((storages.size == 1 && storages.first().value == StoragePathMacros.WORKSPACE_FILE) || !project.isExternalStorageEnabled) {
@@ -94,14 +94,21 @@ internal class ExternalSystemStreamProviderFactory(private val project: Project)
// so, we just add our storage as first and default storages in the end as fallback
// on write default storages also returned, because default FileBasedStorage will remove data if component has external source
val result = ArrayList<Storage>(storages.size + 1)
val annotation: FileStorageAnnotation
if (componentManager is Project) {
result.add(FileStorageAnnotation(storages.get(0).value, false, ExternalProjectStorage::class.java))
val fileSpec = storages.get(0).value
annotation = FileStorageAnnotation(fileSpec, false, ExternalProjectStorage::class.java)
}
else {
result.add(EXTERNAL_MODULE_STORAGE_ANNOTATION)
annotation = EXTERNAL_MODULE_STORAGE_ANNOTATION
}
if (stateSpec.externalStorageOnly) {
return listOf(annotation)
}
val result = ArrayList<Storage>(storages.size + 1)
result.add(annotation)
result.addAll(storages)
return result
}
@@ -105,6 +105,9 @@ public class ExternalSystemProcessHandler extends BuildProcessHandler implements
}
protected void closeInput() {
if (myTask instanceof UserDataHolder) {
((UserDataHolder)myTask).putUserData(ExternalSystemRunConfiguration.RUN_INPUT_KEY, null);
}
StreamUtil.closeStream(myProcessInput);
myProcessInput = null;
}
@@ -118,11 +118,6 @@ public class ExternalSystemResolveProjectTask extends AbstractExternalSystemTask
return resolver.cancelTask(getId());
}
@Nullable
public DataNode<ProjectData> getExternalProject() {
return myExternalProject.get();
}
@Override
@NotNull
protected String wrapProgressText(@NotNull String text) {
@@ -134,7 +129,7 @@ public class ExternalSystemResolveProjectTask extends AbstractExternalSystemTask
super.setState(state);
if (state.isStopped()) {
InternalExternalProjectInfo projectInfo =
new InternalExternalProjectInfo(getExternalSystemId(), getExternalProjectPath(), getExternalProject());
new InternalExternalProjectInfo(getExternalSystemId(), getExternalProjectPath(), myExternalProject.getAndSet(null));
final long currentTimeMillis = System.currentTimeMillis();
projectInfo.setLastImportTimestamp(currentTimeMillis);
projectInfo.setLastSuccessfulImportTimestamp(state == ExternalSystemTaskState.FAILED ? -1 : currentTimeMillis);
@@ -221,8 +221,13 @@ public class ExternalSystemKeymapExtension implements KeymapExtension {
public static void clearActions(Project project, Collection<DataNode<TaskData>> taskData) {
ActionManager actionManager = ActionManager.getInstance();
if (actionManager != null) {
for (DataNode<TaskData> each : taskData) {
for (String eachAction : actionManager.getActionIds(getActionPrefix(project, each.getData().getLinkedExternalProjectPath()))) {
Set<String> externalProjectPaths = ContainerUtil.newHashSet();
for (DataNode<TaskData> node : taskData) {
externalProjectPaths.add(node.getData().getLinkedExternalProjectPath());
}
for (String externalProjectPath : externalProjectPaths) {
for (String eachAction : actionManager.getActionIds(getActionPrefix(project, externalProjectPath))) {
AnAction action = actionManager.getAction(eachAction);
if (!(action instanceof ExternalSystemRunConfigurationAction)) {
actionManager.unregisterAction(eachAction);
@@ -23,7 +23,6 @@ import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.RootPolicy;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -145,7 +144,6 @@ public class LibraryDataService extends AbstractProjectDataService<LibraryData,
/**
* Remove orphan project libraries during postprocess phase (after execution of LibraryDependencyDataService#import)
* in order to use LibraryDataService.isOrphanProjectLibrary method properly
*/
@Override
public void postProcess(@NotNull Collection<DataNode<LibraryData>> toImport,
@@ -157,15 +155,45 @@ public class LibraryDataService extends AbstractProjectDataService<LibraryData,
// do not cleanup orphan project libraries if import runs from Project Structure Dialog
// since libraries order entries cannot be imported for modules in that case
// and hence #isOrphanProjectLibrary() method will work incorrectly
// and hence orphans will be detected incorrectly
if (modelsProvider instanceof IdeUIModifiableModelsProvider) return;
final List<Library> orphanIdeLibraries = ContainerUtil.newSmartList();
final LibraryTable.ModifiableModel librariesModel = modelsProvider.getModifiableProjectLibrariesModel();
final Map<String, Library> namesToLibs = ContainerUtil.newHashMap();
final Set<Library> potentialOrphans = ContainerUtil.newHashSet();
RootPolicy<Void> excludeUsedLibraries = new RootPolicy<Void>() {
@Override
public Void visitLibraryOrderEntry(@NotNull LibraryOrderEntry ideDependency, Void value) {
if (ideDependency.isModuleLevel()) {
return null;
}
Library lib = ideDependency.getLibrary();
if (lib == null) {
lib = namesToLibs.get(ideDependency.getLibraryName());
}
if (lib != null) {
potentialOrphans.remove(lib);
}
return null;
}
};
for (Library library : librariesModel.getLibraries()) {
if (!ExternalSystemApiUtil.isExternalSystemLibrary(library, projectData.getOwner())) continue;
if (isOrphanProjectLibrary(library, modelsProvider) && !modelsProvider.isSubstituted(library.getName())) {
orphanIdeLibraries.add(library);
namesToLibs.put(library.getName(), library);
potentialOrphans.add(library);
}
for (Module module : modelsProvider.getModules()) {
for (OrderEntry entry : modelsProvider.getOrderEntries(module)) {
entry.accept(excludeUsedLibraries, null);
}
}
for (Library lib : potentialOrphans) {
if (!modelsProvider.isSubstituted(lib.getName())) {
orphanIdeLibraries.add(lib);
}
}
@@ -220,22 +248,4 @@ public class LibraryDataService extends AbstractProjectDataService<LibraryData,
registerPaths(externalLibrary.isUnresolved(), roots, libraryModel, externalLibrary.getInternalName());
}
}
private static boolean isOrphanProjectLibrary(@NotNull final Library library,
@NotNull final IdeModifiableModelsProvider modelsProvider) {
RootPolicy<Boolean> visitor = new RootPolicy<Boolean>() {
@Override
public Boolean visitLibraryOrderEntry(@NotNull LibraryOrderEntry ideDependency, Boolean value) {
return !ideDependency.isModuleLevel() &&
(library == ideDependency.getLibrary() ||
(ideDependency.getLibrary() == null && StringUtil.equals(library.getName(), ideDependency.getLibraryName())));
}
};
for (Module module : modelsProvider.getModules()) {
for (OrderEntry entry : modelsProvider.getOrderEntries(module)) {
if (entry.accept(visitor, false)) return false;
}
}
return true;
}
}
@@ -275,7 +275,7 @@ public class ExternalSystemUtil {
final ExternalProjectRefreshCallback callback;
if (spec.getCallback() == null) {
callback = new MyMultiExternalProjectRefreshCallback(spec.getProject(), projectDataManager, spec.getExternalSystemId());
callback = new MyMultiExternalProjectRefreshCallback(spec.getProject(), projectDataManager);
}
else {
callback = spec.getCallback();
@@ -390,9 +390,10 @@ public class ExternalSystemUtil {
else {
projectName = projectFile.getName();
}
final ExternalSystemResolveProjectTask myTask =
new ExternalSystemResolveProjectTask(externalSystemId, project, externalProjectPath, vmOptions, arguments, isPreviewMode);
final TaskUnderProgress refreshProjectStructureTask = new TaskUnderProgress() {
private final ExternalSystemResolveProjectTask myTask
= new ExternalSystemResolveProjectTask(externalSystemId, project, externalProjectPath, vmOptions, arguments, isPreviewMode);
@SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "IOResourceOpenedButNotSafelyClosed"})
@Override
@@ -404,7 +405,7 @@ public class ExternalSystemUtil {
@Override
public void cancel() {
super.cancel();
cancellImport();
cancelImport();
}
});
}
@@ -430,7 +431,7 @@ public class ExternalSystemUtil {
final ExternalSystemProcessHandler processHandler = new ExternalSystemProcessHandler(myTask, projectName + " import") {
@Override
protected void destroyProcessImpl() {
cancellImport();
cancelImport();
closeInput();
}
};
@@ -442,7 +443,6 @@ public class ExternalSystemUtil {
consoleManager.attachExecutionConsole(project, myTask, null, processHandler);
if (consoleView != null) {
Disposer.register(project, consoleView);
Disposer.register(consoleView, processHandler);
} else {
Disposer.register(project, processHandler);
}
@@ -529,11 +529,15 @@ public class ExternalSystemUtil {
final Throwable error = myTask.getError();
if (error == null) {
if (callback != null) {
DataNode<ProjectData> externalProject = myTask.getExternalProject();
if (externalProject != null && importSpec.shouldCreateDirectoriesForEmptyContentRoots()) {
externalProject.putUserData(ContentRootDataService.CREATE_EMPTY_DIRECTORIES, Boolean.TRUE);
final ExternalProjectInfo externalProjectData = ProjectDataManagerImpl.getInstance()
.getExternalProjectData(project, externalSystemId, externalProjectPath);
if (externalProjectData != null) {
DataNode<ProjectData> externalProject = externalProjectData.getExternalProjectStructure();
if (externalProject != null && importSpec.shouldCreateDirectoriesForEmptyContentRoots()) {
externalProject.putUserData(ContentRootDataService.CREATE_EMPTY_DIRECTORIES, Boolean.TRUE);
}
callback.onSuccess(externalProject);
}
callback.onSuccess(externalProject);
}
if (!isPreviewMode) {
externalSystemTaskActivator.runTasks(externalProjectPath, ExternalSystemTaskActivator.Phase.AFTER_SYNC);
@@ -556,7 +560,7 @@ public class ExternalSystemUtil {
}
}
public void cancellImport() {
private void cancelImport() {
myTask.cancel(ExternalSystemTaskNotificationListener.EP_NAME.getExtensions());
}
};
@@ -1064,14 +1068,10 @@ public class ExternalSystemUtil {
private final Set<String> myExternalModulePaths;
private final Project myProject;
private final ProjectDataManager myProjectDataManager;
private final ProjectSystemId myExternalSystemId;
public MyMultiExternalProjectRefreshCallback(Project project,
ProjectDataManager projectDataManager,
ProjectSystemId externalSystemId) {
public MyMultiExternalProjectRefreshCallback(Project project, ProjectDataManager projectDataManager) {
myProject = project;
myProjectDataManager = projectDataManager;
myExternalSystemId = externalSystemId;
myExternalModulePaths = ContainerUtilRt.newHashSet();
}
@@ -57,6 +57,8 @@ public interface RunDashboardManager {
void createToolWindowContent(@NotNull ToolWindow toolWindow);
void updateDashboard(boolean withSStructure);
List<Pair<RunnerAndConfigurationSettings, RunContentDescriptor>> getRunConfigurations();
boolean isShowConfigurations();
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2011 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.template.TemplateManager;
@@ -118,8 +104,8 @@ public class AutoHardWrapHandler {
return;
}
VisualPosition visEndLinePosition = editor.offsetToVisualPosition(endOffset);
if (margin >= visEndLinePosition.column) {
LogicalPosition logEndLinePosition = editor.offsetToLogicalPosition(endOffset);
if (margin >= logEndLinePosition.column) {
if (change != null) {
change.modificationStamp = document.getModificationStamp();
}
@@ -159,9 +145,9 @@ public class AutoHardWrapHandler {
change.update(editor);
// Is assumed to be max possible number of characters inserted on the visual line with caret.
int maxPreferredOffset = editor.logicalPositionToOffset(editor.visualToLogicalPosition(
new VisualPosition(caretModel.getVisualPosition().line, margin - FormatConstants.getReservedLineWrapWidthInColumns(editor))
));
int maxPreferredOffset = editor.logicalPositionToOffset(
new LogicalPosition(caretModel.getLogicalPosition().line, margin - FormatConstants.getReservedLineWrapWidthInColumns(editor))
);
int wrapOffset = strategy.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset, true, false);
if (wrapOffset < 0) {
@@ -1045,7 +1045,14 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
for (AbstractDocumentationTooltipAction action : ourTooltipActions) {
Icon icon = action.getTemplatePresentation().getIcon();
Dimension minSize = new Dimension(icon.getIconWidth(), icon.getIconHeight());
myButtons.add(new ActionButton(action, presentationFactory.getPresentation(action), IdeTooltipManager.IDE_TOOLTIP_PLACE, minSize));
ActionButton actionButton =
new ActionButton(action, presentationFactory.getPresentation(action), IdeTooltipManager.IDE_TOOLTIP_PLACE, minSize) {
@Override
protected boolean checkSkipPressForEvent(@NotNull MouseEvent e) {
return e.getButton() != MouseEvent.BUTTON1;
}
};
myButtons.add(actionButton);
action.setDocInfo(documentationAnchor, elementUnderMouse);
}
Collections.reverse(myButtons);
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.execution.configuration;
import com.intellij.openapi.application.PathMacroFilter;
@@ -26,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
class RunConfigurationPathMacroFilter extends PathMacroFilter {
@Override
public boolean skipPathMacros(@NotNull Attribute attribute) {
return attribute.getParent().getName().equals("configuration") && attribute.getName().equals("name");
return attribute.getName().equals("name") && attribute.getParent().getName().equals("configuration");
}
@Override
@@ -140,21 +140,7 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab
myContentManagerListener = new ContentManagerAdapter() {
@Override
public void contentAdded(ContentManagerEvent event) {
Content content = event.getContent();
RunContentDescriptor descriptor = RunContentManagerImpl.getRunContentDescriptorByContent(content);
if (descriptor == null) {
return;
}
RunnerLayoutUi layoutUi = descriptor.getRunnerLayoutUi();
if (!(layoutUi instanceof RunnerLayoutUiImpl)) {
return;
}
RunnerLayoutUiImpl layoutUiImpl = (RunnerLayoutUiImpl)layoutUi;
layoutUiImpl.setLeftToolbarVisible(false);
layoutUiImpl.setContentToolbarBefore(false);
List<AnAction> leftToolbarActions = layoutUiImpl.getActions();
myContentActions.put(content, leftToolbarActions);
updateContentToolbar(content);
onContentAdded(event.getContent());
}
@Override
@@ -172,17 +158,9 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab
if (ContentManagerEvent.ContentOperation.add != event.getOperation()) {
return;
}
contentAdded(event);
myBuilder.queueUpdate().doWhenDone(() -> myBuilder.accept(RunDashboardNode.class, new TreeVisitor<RunDashboardNode>() {
@Override
public boolean visit(@NotNull RunDashboardNode node) {
if (node.getContent() == event.getContent()) {
myBuilder.select(node);
}
return false;
}
}));
showContentPanel();
Content content = event.getContent();
onContentAdded(content);
onContentSelectionChanged(content);
}
};
myContentManager.addContentManagerListener(myContentManagerListener);
@@ -261,6 +239,16 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab
new TreeSpeedSearch(myTree, TreeSpeedSearch.NODE_DESCRIPTOR_TOSTRING, true);
setTreeVisible(dashboardManager.isShowConfigurations());
// RunDashboardContent may be initialized when some contents have been already added to content manager.
// Process already added content.
for (Content content : myContentManager.getContents()) {
onContentAdded(content);
}
Content selectedContent = myContentManager.getSelectedContent();
if (selectedContent != null) {
onContentSelectionChanged(selectedContent);
}
}
private void setTreeVisible(boolean visible) {
@@ -331,6 +319,36 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab
showMessagePanel(ExecutionBundle.message("run.dashboard.empty.selection.message"));
}
private void onContentAdded(Content content) {
RunContentDescriptor descriptor = RunContentManagerImpl.getRunContentDescriptorByContent(content);
if (descriptor == null) {
return;
}
RunnerLayoutUi layoutUi = descriptor.getRunnerLayoutUi();
if (!(layoutUi instanceof RunnerLayoutUiImpl)) {
return;
}
RunnerLayoutUiImpl layoutUiImpl = (RunnerLayoutUiImpl)layoutUi;
layoutUiImpl.setLeftToolbarVisible(false);
layoutUiImpl.setContentToolbarBefore(false);
List<AnAction> leftToolbarActions = layoutUiImpl.getActions();
myContentActions.put(content, leftToolbarActions);
updateContentToolbar(content);
}
private void onContentSelectionChanged(Content content) {
myBuilder.queueUpdate().doWhenDone(() -> myBuilder.accept(RunDashboardNode.class, new TreeVisitor<RunDashboardNode>() {
@Override
public boolean visit(@NotNull RunDashboardNode node) {
if (node.getContent() == content) {
myBuilder.select(node);
}
return false;
}
}));
showContentPanel();
}
private void showMessagePanel(String text) {
Content selectedContent = myContentManager.getSelectedContent();
if (selectedContent != null) {
@@ -53,6 +53,7 @@ import javax.swing.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
@@ -71,6 +72,7 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
@NotNull private final Set<String> myTypes = ContainerUtil.newHashSet();
@NotNull private final List<RunDashboardGrouper> myGroupers;
@NotNull private final Condition<Content> myReuseCondition;
@NotNull private final AtomicBoolean myListenersInitialized = new AtomicBoolean();
private boolean myShowConfigurations = true;
private float myContentProportion = DEFAULT_CONTENT_PROPORTION;
@@ -94,18 +96,17 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
.sorted(RunDashboardGroupingRule.PRIORITY_COMPARATOR)
.map(RunDashboardGrouper::new)
.collect(Collectors.toList());
if (isDashboardEnabled()) {
addRunConfigurationListener();
}
}
private static boolean isDashboardEnabled() {
return Registry.is("ide.run.dashboard");
}
private void addRunConfigurationListener() {
myProject.getMessageBus().connect(myProject).subscribe(RunManagerListener.TOPIC, new RunManagerListener() {
private void initToolWindowContentListeners() {
if (!myListenersInitialized.compareAndSet(false, true)) return;
MessageBusConnection connection = myProject.getMessageBus().connect(myProject);
connection.subscribe(RunManagerListener.TOPIC, new RunManagerListener() {
private volatile boolean myUpdateStarted;
@Override
@@ -140,10 +141,6 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
updateDashboard(true);
}
});
}
private void initToolWindowContentListeners() {
MessageBusConnection connection = myProject.getMessageBus().connect(myProject);
connection.subscribe(ExecutionManager.EXECUTION_TOPIC, new ExecutionListener() {
@Override
public void processStarted(@NotNull String executorId, @NotNull ExecutionEnvironment env, final @NotNull ProcessHandler handler) {
@@ -225,8 +222,6 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
myToolWindowContentManager.addContent(myToolWindowContent);
myToolWindowContentManagerListener = new ToolWindowContentManagerListener();
initToolWindowContentListeners();
}
@Override
@@ -317,6 +312,9 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
public void setTypes(@NotNull Set<String> types) {
myTypes.clear();
myTypes.addAll(types);
if (!myTypes.isEmpty()) {
initToolWindowContentListeners();
}
updateDashboard(true);
}
@@ -363,7 +361,8 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
});
}
private void updateDashboard(final boolean withStructure) {
@Override
public void updateDashboard(final boolean withStructure) {
final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
if (toolWindowManager == null) return;
@@ -376,8 +375,11 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
boolean available = hasContent();
ToolWindow toolWindow = toolWindowManager.getToolWindow(getToolWindowId());
if (toolWindow == null) {
if (!myTypes.isEmpty() || available) {
toolWindow = createToolWindow(toolWindowManager, available);
}
if (available) {
createToolWindow(toolWindowManager).show(null);
toolWindow.show(null);
}
return;
}
@@ -395,10 +397,11 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
});
}
private ToolWindow createToolWindow(ToolWindowManager toolWindowManager) {
private ToolWindow createToolWindow(ToolWindowManager toolWindowManager, boolean available) {
ToolWindow toolWindow = toolWindowManager.registerToolWindow(getToolWindowId(), true, ToolWindowAnchor.BOTTOM,
myProject, true);
toolWindow.setIcon(getToolWindowIcon());
toolWindow.setAvailable(available, null);
createToolWindowContent(toolWindow);
return toolWindow;
}
@@ -495,6 +498,9 @@ public class RunDashboardManagerImpl implements RunDashboardManager, PersistentS
public void loadState(State state) {
myTypes.clear();
myTypes.addAll(state.configurationTypes);
if (!myTypes.isEmpty()) {
initToolWindowContentListeners();
}
state.ruleStates.forEach(ruleState -> {
for (RunDashboardGrouper grouper : myGroupers) {
if (grouper.getRule().getName().equals(ruleState.name) && !grouper.getRule().isAlwaysEnabled()) {
@@ -28,6 +28,11 @@ import org.jetbrains.annotations.NotNull;
public class RunDashboardToolWindowFactory implements ToolWindowFactory, Condition<Project>, DumbAware {
@Override
public boolean value(Project project) {
return !RunDashboardManager.getInstance(project).getTypes().isEmpty();
}
@Override
public boolean shouldBeAvailable(@NotNull Project project) {
return RunDashboardManager.getInstance(project).isToolWindowAvailable();
}
@@ -162,7 +162,15 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
return doExecuteTask(env, settings.first, settings.second);
}
public static boolean doExecuteTask(@NotNull final ExecutionEnvironment env,
/**
* @deprecated use {@link #doExecuteTask(ExecutionEnvironment, RunnerAndConfigurationSettings, ExecutionTarget)} instead
*/
public static boolean doExecuteTask(@NotNull final ExecutionEnvironment env,
@NotNull final RunnerAndConfigurationSettings settings) {
return doExecuteTask(env, settings, null);
}
public static boolean doExecuteTask(@NotNull final ExecutionEnvironment env,
@NotNull final RunnerAndConfigurationSettings settings,
@Nullable final ExecutionTarget target) {
final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
@@ -89,6 +89,7 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
RunDashboardManager dashboardManager = RunDashboardManager.getInstance(myProject);
dashboardManager.updateDashboard(true);
initToolWindow(null, dashboardManager.getToolWindowId(), dashboardManager.getToolWindowIcon(),
dashboardManager.getDashboardContentManager());
@@ -425,14 +425,11 @@ public class FindPopupPanel extends JBPanel implements FindUI {
myReplaceAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (myResultsPreviewTable.getRowCount() < 2 || MessageDialogBuilder.yesNo(FindBundle.message(
"find.replace.all.confirmation.title"), FindBundle.message(
"find.replace.all.confirmation",
if (myResultsPreviewTable.getRowCount() < 2 || ReplaceInProjectManager.getInstance(myProject).showReplaceAllConfirmDialog(
myMessageState[0],
getStringToFind(),
myMessageState[1],
getStringToReplace()))
.yesText(Messages.OK_BUTTON).noText(Messages.CANCEL_BUTTON).show() == Messages.YES) {
getStringToReplace())) {
doOK(false);
}
}
@@ -36,6 +36,7 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageDialogBuilder;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Factory;
@@ -357,6 +358,14 @@ public class ReplaceInProjectManager {
return true;
}
public boolean showReplaceAllConfirmDialog(String usagesCount, String stringToFind, String filesCount, String stringToReplace) {
return Messages.YES == MessageDialogBuilder.yesNo(
FindBundle.message("find.replace.all.confirmation.title"),
FindBundle.message("find.replace.all.confirmation", usagesCount, StringUtil.escapeXml(stringToFind), filesCount, StringUtil.escapeXml(stringToReplace)))
.yesText(Messages.OK_BUTTON)
.noText(Messages.CANCEL_BUTTON).show();
}
private void addReplaceActions(final ReplaceContext replaceContext) {
final AbstractAction replaceAction = new AbstractAction(FindBundle.message("find.replace.all.action")) {
@Override
@@ -369,15 +378,11 @@ public class ReplaceInProjectManager {
files.add(((UsageInfo2UsageAdapter)usage).getFile());
}
}
if (files.size() < 2 ||
JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog(replaceContext.getUsageView().getComponent(),
FindBundle.message("find.replace.all.confirmation",
usages.size(),
replaceContext.getFindModel().getStringToFind(),
files.size(),
replaceContext.getFindModel().getStringToReplace()),
FindBundle.message("find.replace.all.confirmation.title"),
JOptionPane.OK_CANCEL_OPTION)) {
if (files.size() < 2 || showReplaceAllConfirmDialog(
"" + usages.size(),
replaceContext.getFindModel().getStringToFind(),
"" + files.size(),
replaceContext.getFindModel().getStringToReplace())) {
replaceUsagesUnderCommand(replaceContext, usages);
}
}
@@ -0,0 +1,38 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.impl;
import com.intellij.ide.projectView.impl.AbstractProjectViewPane;
import com.intellij.openapi.project.PossiblyDumbAware;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
public class ProjectViewSelectInPaneTarget extends ProjectViewSelectInTarget implements PossiblyDumbAware {
private final AbstractProjectViewPane myPane;
private final boolean myDumbAware;
public ProjectViewSelectInPaneTarget(@NotNull Project project, @NotNull AbstractProjectViewPane pane, boolean dumbAware) {
super(project);
myPane = pane;
myDumbAware = dumbAware;
}
@Override
public String toString() {
return myPane.getTitle();
}
@Override
public String getMinorViewId() {
return myPane.getId();
}
@Override
public float getWeight() {
return myPane.getWeight();
}
@Override
public boolean isDumbAware() {
return myDumbAware;
}
}
@@ -18,7 +18,9 @@ package com.intellij.ide.projectView;
import com.intellij.ide.SelectInTarget;
import com.intellij.ide.projectView.impl.AbstractProjectViewPane;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.UnloadedModuleDescription;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.vfs.VirtualFile;
@@ -27,8 +29,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
public abstract class ProjectView {
/**
* Use this key to get unloaded modules which content roots are selected in Project View
*/
public static final DataKey<List<UnloadedModuleDescription>> UNLOADED_MODULES_CONTEXT_KEY = DataKey.create("context.unloaded.modules.list");
public static ProjectView getInstance(Project project) {
return ServiceManager.getService(project, ProjectView.class);
}
@@ -28,6 +28,8 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.tree.DefaultMutableTreeNode;
import static com.intellij.util.ObjectUtils.notNull;
public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdapter {
private final PsiModificationTracker myModificationTracker;
private long myOutOfCodeBlockModificationCount;
@@ -105,7 +107,7 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap
break;
}
if (addSubtreeToUpdateByElement(parent)) {
if (addSubtreeToUpdateByElementFile(parent)) {
break;
}
@@ -122,8 +124,8 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap
addSubtreeToUpdateByRoot();
}
else if (propertyName.equals(PsiTreeChangeEvent.PROP_WRITABLE)){
if (!addSubtreeToUpdateByElement(element) && element instanceof PsiFile) {
addSubtreeToUpdateByElement(((PsiFile)element).getContainingDirectory());
if (!addSubtreeToUpdateByElementFile(element) && element instanceof PsiFile) {
addSubtreeToUpdateByElementFile(((PsiFile)element).getContainingDirectory());
}
}
else if (propertyName.equals(PsiTreeChangeEvent.PROP_FILE_NAME) || propertyName.equals(PsiTreeChangeEvent.PROP_DIRECTORY_NAME)){
@@ -132,11 +134,11 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap
return;
}
final PsiElement parent = element.getParent();
if (parent == null || !addSubtreeToUpdateByElement(parent)) {
addSubtreeToUpdateByElement(element);
if (parent == null || !addSubtreeToUpdateByElementFile(parent)) {
addSubtreeToUpdateByElementFile(element);
}
}
else if (propertyName.equals(PsiTreeChangeEvent.PROP_FILE_TYPES)){
else if (propertyName.equals(PsiTreeChangeEvent.PROP_FILE_TYPES) || propertyName.equals(PsiTreeChangeEvent.PROP_UNLOADED_PSI)) {
addSubtreeToUpdateByRoot();
}
}
@@ -151,4 +153,8 @@ public abstract class ProjectViewPsiTreeChangeListener extends PsiTreeChangeAdap
AbstractTreeUpdater updater = getUpdater();
return updater != null && updater.addSubtreeToUpdateByElement(element);
}
private boolean addSubtreeToUpdateByElementFile(PsiElement element) {
return element != null && addSubtreeToUpdateByElement(notNull(element.getContainingFile(), element));
}
}
@@ -1,22 +1,9 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.projectView.impl;
import com.intellij.ide.DataManager;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.PsiCopyPasteManager;
import com.intellij.ide.SelectInTarget;
import com.intellij.ide.dnd.*;
@@ -72,11 +59,8 @@ import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.*;
import java.util.List;
import java.util.Map;
public abstract class AbstractProjectViewPane implements DataProvider, Disposable, BusyObject {
public static final ExtensionPointName<AbstractProjectViewPane> EP_NAME = ExtensionPointName.create("com.intellij.projectViewPane");
@@ -159,6 +143,10 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
public boolean supportsManualOrder() {
return false;
}
protected String getManualOrderOptionText() {
return IdeBundle.message("action.manual.order");
}
/**
* @return all supported sub views IDs.
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.projectView.impl;
@@ -51,7 +37,9 @@ import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.module.UnloadedModuleDescription;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
@@ -87,6 +75,7 @@ import com.intellij.ui.tree.TreeVisitor;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.PlatformIcons;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.JBIterable;
import com.intellij.util.messages.MessageBusConnection;
@@ -1104,7 +1093,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) {
final Module[] modules = getSelectedModules();
if (modules != null) {
if (modules != null || !getSelectedUnloadedModules().isEmpty()) {
return myDeleteModuleProvider;
}
final LibraryOrderEntry orderEntry = getSelectedLibrary();
@@ -1152,6 +1141,9 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
if (LangDataKeys.MODULE_CONTEXT_ARRAY.is(dataId)) {
return getSelectedModules();
}
if (UNLOADED_MODULES_CONTEXT_KEY.is(dataId)) {
return Collections.unmodifiableList(getSelectedUnloadedModules());
}
if (ModuleGroup.ARRAY_DATA_KEY.is(dataId)) {
final List<ModuleGroup> selectedElements = getSelectedElements(ModuleGroup.class);
return selectedElements.isEmpty() ? null : selectedElements.toArray(new ModuleGroup[selectedElements.size()]);
@@ -1165,6 +1157,11 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return selectedElements.isEmpty() ? null : selectedElements.toArray(new NamedLibraryElement[selectedElements.size()]);
}
if (PlatformDataKeys.SELECTED_ITEMS.is(dataId)) {
final AbstractProjectViewPane viewPane = getCurrentProjectViewPane();
return viewPane == null ? null : viewPane.getSelectedElements();
}
if (QuickActionProvider.KEY.is(dataId)) {
return ProjectViewImpl.this;
}
@@ -1260,6 +1257,21 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return result.toArray(new Module[result.size()]);
}
}
private List<UnloadedModuleDescription> getSelectedUnloadedModules() {
final AbstractProjectViewPane viewPane = getCurrentProjectViewPane();
if (viewPane == null) return Collections.emptyList();
List<UnloadedModuleDescription> result = new SmartList<>();
for (Object element : viewPane.getSelectedElements()) {
if (element instanceof PsiDirectory) {
ContainerUtil.addIfNotNull(result, getUnloadedModuleByContentRoot(((PsiDirectory)element).getVirtualFile()));
}
else if (element instanceof VirtualFile) {
ContainerUtil.addIfNotNull(result, getUnloadedModuleByContentRoot((VirtualFile)element));
}
}
return result;
}
}
/** Project view has the same node for module and its single content root
@@ -1280,6 +1292,15 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return null;
}
@Nullable
private UnloadedModuleDescription getUnloadedModuleByContentRoot(@NotNull VirtualFile file) {
String moduleName = ProjectRootsUtil.findUnloadedModuleByContentRoot(file, myProject);
if (moduleName != null) {
return ModuleManager.getInstance(myProject).getUnloadedModuleDescription(moduleName);
}
return null;
}
@NotNull
private <T> List<T> getSelectedElements(@NotNull Class<T> klass) {
List<T> result = new ArrayList<>();
@@ -1922,10 +1943,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
pane.installComparator();
}
protected String getManualOrderOptionText() {
return IdeBundle.message("action.manual.order");
}
@Override
public boolean isSortByType(String paneId) {
return getPaneOptionValue(mySortByType, paneId, ourSortByTypeDefaults);
@@ -1940,7 +1957,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private class ManualOrderAction extends ToggleAction implements DumbAware {
private ManualOrderAction() {
super(getManualOrderOptionText(), getManualOrderOptionText(), AllIcons.ObjectBrowser.Sorted);
super(IdeBundle.message("action.manual.order"), null, AllIcons.ObjectBrowser.Sorted);
}
@Override
@@ -1958,7 +1975,13 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
super.update(e);
final Presentation presentation = e.getPresentation();
AbstractProjectViewPane pane = getCurrentProjectViewPane();
presentation.setEnabledAndVisible(pane != null && pane.supportsManualOrder());
if (pane == null) {
presentation.setEnabledAndVisible(false);
}
else {
presentation.setEnabledAndVisible(pane.supportsManualOrder());
presentation.setText(pane.getManualOrderOptionText());
}
}
}
@@ -1,22 +1,9 @@
/*
* 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.
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.application;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
/**
* Filter remote path in {@link com.intellij.util.PathMappingSettings.PathMapping}
@@ -25,7 +12,7 @@ import org.jdom.Element;
*/
public class PathMappingsMacroFilter extends PathMacroFilter {
@Override
public boolean skipPathMacros(Attribute attribute) {
public boolean skipPathMacros(@NotNull Attribute attribute) {
final Element parent = attribute.getParent();
if ("mapping".equals(parent.getName()) && "remote-root".equals(attribute.getName())) {
return true;
@@ -1,21 +1,8 @@
/*
* Copyright 2000-2012 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.application;
import org.jdom.Attribute;
import org.jetbrains.annotations.NotNull;
/**
* Since SSR inspections can be stored in inspection profiles and loaded by users who don't have the SSR plugin installed, unfortunately
@@ -25,7 +12,7 @@ import org.jdom.Attribute;
*/
public class StructuralSearchPathMacroFilter extends PathMacroFilter {
@Override
public boolean skipPathMacros(Attribute attribute) {
public boolean skipPathMacros(@NotNull Attribute attribute) {
final String parentName = attribute.getParent().getName();
if ("replaceConfiguration".equals(parentName) || "searchConfiguration".equals(parentName)) {
return true;
@@ -18,14 +18,14 @@ package com.intellij.openapi.roots.ui.configuration.actions;
import com.intellij.ide.DeleteProvider;
import com.intellij.ide.TitledHandler;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.*;
import com.intellij.openapi.module.impl.LoadedModuleDescriptionImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ModifiableRootModel;
@@ -37,22 +37,20 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.project.ProjectKt;
import com.intellij.projectImport.ProjectAttachProcessor;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.PathUtilRt;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
public class ModuleDeleteProvider implements DeleteProvider, TitledHandler {
@Override
public boolean canDeleteElement(@NotNull DataContext dataContext) {
final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext);
return modules != null && !containsPrimaryModule(modules);
List<UnloadedModuleDescription> unloadedModules = ProjectView.UNLOADED_MODULES_CONTEXT_KEY.getData(dataContext);
return modules != null && !containsPrimaryModule(modules) || unloadedModules != null && !unloadedModules.isEmpty();
}
private static boolean containsPrimaryModule(Module[] modules) {
@@ -77,12 +75,21 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler {
@Override
public void deleteElement(@NotNull DataContext dataContext) {
final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext);
assert modules != null;
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
assert project != null;
String names = StringUtil.join(Arrays.asList(modules), module -> "\'" + module.getName() + "\'", ", ");
int ret = Messages.showOkCancelDialog(getConfirmationText(modules, names), getActionTitle(), Messages.getQuestionIcon());
List<ModuleDescription> moduleDescriptions = new ArrayList<>();
final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(dataContext);
if (modules != null) {
moduleDescriptions.addAll(ContainerUtil.map(modules, LoadedModuleDescriptionImpl::new));
}
List<UnloadedModuleDescription> unloadedModules = ProjectView.UNLOADED_MODULES_CONTEXT_KEY.getData(dataContext);
if (unloadedModules != null) {
moduleDescriptions.addAll(unloadedModules);
}
String names = StringUtil.join(moduleDescriptions, description -> "\'" + description.getName() + "\'", ", ");
int ret = Messages.showOkCancelDialog(getConfirmationText(names, moduleDescriptions.size()), getActionTitle(), Messages.getQuestionIcon());
if (ret != Messages.OK) return;
CommandProcessor.getInstance().executeCommand(project, () -> {
final Runnable action = () -> {
@@ -90,28 +97,33 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler {
final Module[] currentModules = moduleManager.getModules();
final ModifiableModuleModel modifiableModuleModel = moduleManager.getModifiableModel();
final Map<Module, ModifiableRootModel> otherModuleRootModels = new HashMap<>();
for (final Module module : modules) {
final ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(module).getModifiableModel();
for (final Module otherModule : currentModules) {
if (otherModule == module || ArrayUtilRt.find(modules, otherModule) != -1) continue;
if (!otherModuleRootModels.containsKey(otherModule)) {
otherModuleRootModels.put(otherModule, ModuleRootManager.getInstance(otherModule).getModifiableModel());
}
Set<String> moduleNamesToDelete = moduleDescriptions.stream().map(ModuleDescription::getName).collect(Collectors.toSet());
for (final Module otherModule : currentModules) {
if (!moduleNamesToDelete.contains(otherModule.getName())) {
otherModuleRootModels.put(otherModule, ModuleRootManager.getInstance(otherModule).getModifiableModel());
}
}
removeDependenciesOnModules(moduleNamesToDelete, otherModuleRootModels.values());
if (modules != null) {
for (final Module module : modules) {
modifiableModuleModel.disposeModule(module);
}
removeModule(module, modifiableModel, otherModuleRootModels.values(), modifiableModuleModel);
}
final ModifiableRootModel[] modifiableRootModels = otherModuleRootModels.values().toArray(new ModifiableRootModel[otherModuleRootModels.size()]);
ModifiableModelCommitter.multiCommit(modifiableRootModels, modifiableModuleModel);
if (unloadedModules != null) {
moduleManager.removeUnloadedModules(unloadedModules);
}
};
ApplicationManager.getApplication().runWriteAction(action);
}, ProjectBundle.message("module.remove.command"), null);
}
private static String getConfirmationText(Module[] modules, String names) {
private static String getConfirmationText(String names, int numberOfModules) {
if (ProjectAttachProcessor.canAttachToProject()) {
return ProjectBundle.message("project.remove.confirmation.prompt", names, modules.length);
return ProjectBundle.message("project.remove.confirmation.prompt", names, numberOfModules);
}
return ProjectBundle.message("module.remove.confirmation.prompt", names, modules.length);
return ProjectBundle.message("module.remove.confirmation.prompt", names, numberOfModules);
}
@Override
@@ -120,26 +132,21 @@ public class ModuleDeleteProvider implements DeleteProvider, TitledHandler {
}
public static void removeModule(@NotNull final Module moduleToRemove,
@Nullable ModifiableRootModel modifiableRootModelToRemove,
@NotNull Collection<ModifiableRootModel> otherModuleRootModels,
@NotNull final ModifiableModuleModel moduleModel) {
// remove all dependencies on the module that is about to be removed
@NotNull Collection<ModifiableRootModel> otherModuleRootModels,
@NotNull final ModifiableModuleModel moduleModel) {
removeDependenciesOnModules(Collections.singleton(moduleToRemove.getName()), otherModuleRootModels);
moduleModel.disposeModule(moduleToRemove);
}
private static void removeDependenciesOnModules(@NotNull Set<String> moduleNamesToRemove,
@NotNull Collection<ModifiableRootModel> otherModuleRootModels) {
for (final ModifiableRootModel modifiableRootModel : otherModuleRootModels) {
final OrderEntry[] orderEntries = modifiableRootModel.getOrderEntries();
for (final OrderEntry orderEntry : orderEntries) {
if (orderEntry instanceof ModuleOrderEntry && orderEntry.isValid()) {
final Module orderEntryModule = ((ModuleOrderEntry)orderEntry).getModule();
if (orderEntryModule != null && orderEntryModule.equals(moduleToRemove)) {
modifiableRootModel.removeOrderEntry(orderEntry);
}
if (orderEntry instanceof ModuleOrderEntry && moduleNamesToRemove.contains(((ModuleOrderEntry)orderEntry).getModuleName())) {
modifiableRootModel.removeOrderEntry(orderEntry);
}
}
}
// destroyProcess editor
if (modifiableRootModelToRemove != null) {
modifiableRootModelToRemove.dispose();
}
// destroyProcess module
moduleModel.disposeModule(moduleToRemove);
}
}
@@ -1,18 +1,4 @@
/*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.search;
import com.intellij.ide.IdeBundle;
@@ -27,6 +13,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.*;
import com.intellij.openapi.project.Project;
@@ -76,6 +63,10 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv
result.add(GlobalSearchScope.allScope(project));
}
for (SearchScopeProvider each : Extensions.getExtensions(SearchScopeProvider.EP, project)) {
result.addAll(each.getGeneralProjectScopes());
}
if (ModuleUtil.isSupportedRootType(project, JavaSourceRootType.TEST_SOURCE)) {
result.add(GlobalSearchScopesCore.projectProductionScope(project));
result.add(GlobalSearchScopesCore.projectTestScope(project));
@@ -80,6 +80,11 @@ public class ToolEditorDialog extends DialogWrapper {
private JBCheckBox myShowConsoleOnStdErrCheckbox;
private RawCommandLineEditor myOutputFilterField;
@Nullable
public Project getProject() {
return myProject;
}
@Override
@NotNull
protected JPanel createCenterPanel() {
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui.tabs;
@@ -29,7 +15,6 @@ import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.psi.search.scope.packageSet.PackageSet;
import com.intellij.psi.search.scope.packageSet.PackageSetBase;
import com.intellij.ui.ColorUtil;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jdom.Element;
@@ -49,65 +34,61 @@ import java.util.Map;
public class FileColorsModel implements Cloneable {
public static final String FILE_COLOR = "fileColor";
private final List<FileColorConfiguration> myApplicationLevelConfigurations;
private final List<FileColorConfiguration> myProjectLevelConfigurations;
private static final Map<String, String> predefinedScopeNameToPropertyKey;
private static final Map<String, String> predefinedScopeNameToColor;
static {
predefinedScopeNameToPropertyKey = new THashMap<>();
predefinedScopeNameToPropertyKey.put(NonProjectFilesScope.NAME, "file.colors.enable.non.project");
// These IDEs have TestScope registered (via PackagesScopesProvider or TestScopeProvider)
if (PlatformUtils.isIntelliJ() || PlatformUtils.isRubyMine() || PlatformUtils.isPhpStorm() || PlatformUtils.isWebStorm() || PlatformUtils.isGoIde()) {
predefinedScopeNameToPropertyKey.put(TestsScope.NAME, "file.colors.enable.tests");
}
predefinedScopeNameToColor = new THashMap<>();
}
private final List<FileColorConfiguration> myApplicationLevelConfigurations = new ArrayList<>();
private final List<FileColorConfiguration> myProjectLevelConfigurations = new ArrayList<>();
private final Map<String, String> myPredefinedScopeNameToPropertyKey = new THashMap<>();
private final Map<String, String> myPredefinedScopeNameToColor = new THashMap<>();
@NotNull
private final Project myProject;
FileColorsModel(@NotNull final Project project) {
myProject = project;
myApplicationLevelConfigurations = new ArrayList<>();
myProjectLevelConfigurations = new ArrayList<>();
if (predefinedScopeNameToColor.size() < predefinedScopeNameToPropertyKey.size()) {
DefaultScopesProvider defaultScopesProvider = DefaultScopesProvider.getInstance(project);
for (String scopeName : predefinedScopeNameToPropertyKey.keySet()) {
final NamedScope scope = defaultScopesProvider.findCustomScope(scopeName);
assert scope != null : "There is no custom scope with name " + scopeName;
final Color color = ColorUtil.getColor(scope.getClass());
assert color != null : scope.getClass().getName() + " is not annotated with @Colored";
final String colorName = FileColorManagerImpl.getColorName(color);
predefinedScopeNameToColor.put(scopeName, colorName == null ? ColorUtil.toHex(color) : colorName);
}
}
initGlobalScopes();
initPredefinedAndGlobalScopes();
}
private FileColorsModel(@NotNull Project project,
@NotNull List<FileColorConfiguration> applicationLevel,
@NotNull List<FileColorConfiguration> projectLevel) {
myProject = project;
myApplicationLevelConfigurations = new ArrayList<>();
myProjectLevelConfigurations = new ArrayList<>();
myApplicationLevelConfigurations.addAll(applicationLevel);
myProjectLevelConfigurations.addAll(projectLevel);
initGlobalScopes();
initPredefinedAndGlobalScopes();
}
private void initGlobalScopes() {
private void initPredefinedAndGlobalScopes() {
for (NamedScope scope : DefaultScopesProvider.getInstance(myProject).getAllCustomScopes()) {
String scopeName = scope.getName();
final Color color = ColorUtil.getColor(scope.getClass());
if (color == null) continue;
String colorName = FileColorManagerImpl.getColorName(color);
myPredefinedScopeNameToColor.put(scopeName, colorName == null ? ColorUtil.toHex(color) : colorName);
String propertyKey;
if (NonProjectFilesScope.NAME.equals(scopeName)) {
propertyKey = "file.colors.enable.non.project";
}
else if (TestsScope.NAME.equals(scopeName)) {
propertyKey = "file.colors.enable.tests";
}
else {
propertyKey = "file.colors.enable.custom." + scopeName;
}
myPredefinedScopeNameToPropertyKey.put(scopeName, propertyKey);
}
PropertiesComponent propertyComponent = PropertiesComponent.getInstance();
for (String scopeName : predefinedScopeNameToPropertyKey.keySet()) {
for (String scopeName : myPredefinedScopeNameToPropertyKey.keySet()) {
if (findConfiguration(scopeName, false) == null) {
String color = propertyComponent.getValue(predefinedScopeNameToPropertyKey.get(scopeName));
String color = propertyComponent.getValue(myPredefinedScopeNameToPropertyKey.get(scopeName));
if (color == null) {
// backward compatibility, previously it was saved incorrectly as scope name instead of specified property key
color = propertyComponent.getValue(scopeName);
if (color == null) {
color = predefinedScopeNameToColor.get(scopeName);
color = myPredefinedScopeNameToColor.get(scopeName);
}
}
@@ -124,13 +105,13 @@ public class FileColorsModel implements Cloneable {
List<FileColorConfiguration> configurations = isProjectLevel ? myProjectLevelConfigurations : myApplicationLevelConfigurations;
for (FileColorConfiguration configuration : configurations) {
String scopeName = configuration.getScopeName();
String propertyKey = isProjectLevel ? null : predefinedScopeNameToPropertyKey.get(scopeName);
String propertyKey = isProjectLevel ? null : myPredefinedScopeNameToPropertyKey.get(scopeName);
if (propertyKey == null) {
configuration.save(e);
}
else {
PropertiesComponent propertyComponent = PropertiesComponent.getInstance();
propertyComponent.setValue(propertyKey, configuration.getColorName(), predefinedScopeNameToColor.get(scopeName));
propertyComponent.setValue(propertyKey, configuration.getColorName(), myPredefinedScopeNameToColor.get(scopeName));
// previously it was saved incorrectly as scope name instead of specified property key
PropertiesComponent.getInstance().setValue(scopeName, null);
}
@@ -142,7 +123,7 @@ public class FileColorsModel implements Cloneable {
configurations.clear();
Map<String, String> predefinedScopeNameToPropertyKey = new THashMap<>(FileColorsModel.predefinedScopeNameToPropertyKey);
Map<String, String> predefinedScopeNameToPropertyKey = new THashMap<>(myPredefinedScopeNameToPropertyKey);
for (Element child : e.getChildren(FILE_COLOR)) {
FileColorConfiguration configuration = FileColorConfiguration.load(child);
if (configuration != null) {
@@ -163,7 +144,7 @@ public class FileColorsModel implements Cloneable {
// so, default value
if (colorName == null) {
colorName = predefinedScopeNameToColor.get(scopeName);
colorName = myPredefinedScopeNameToColor.get(scopeName);
}
}
// empty means that value deleted
@@ -282,7 +263,7 @@ public class FileColorsModel implements Cloneable {
}
else {
myApplicationLevelConfigurations.clear();
Map<String, String> predefinedScopeNameToPropertyKey = new THashMap<>(FileColorsModel.predefinedScopeNameToPropertyKey);
Map<String, String> predefinedScopeNameToPropertyKey = new THashMap<>(myPredefinedScopeNameToPropertyKey);
PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
for (FileColorConfiguration configuration : configurations) {
myApplicationLevelConfigurations.add(configuration);
@@ -1,20 +1,19 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 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.execution.util;
import com.intellij.execution.CommandLineUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.CapturingProcessHandler;
@@ -93,7 +92,7 @@ public class ExecUtil {
@NotNull
public static String getWindowsShellName() {
return SystemInfo.isWin2kOrNewer ? "cmd.exe" : "command.com";
return CommandLineUtil.getWinShellName();
}
@NotNull
@@ -1790,7 +1790,7 @@ public class AbstractTreeUi {
@Override
public void perform() {
if (!pass.isExpired()) {
queueUpdate(node);
queueUpdate(getElementFor(node));
}
}
});
@@ -49,10 +49,14 @@ import java.beans.PropertyChangeListener;
public abstract class ComboBoxAction extends AnAction implements CustomComponentAction {
private static Icon myIcon = null;
private static Icon myDisabledIcon = null;
private static Icon myWin10ComboDropTriagleIcon = null;
public static Icon getArrowIcon(boolean enabled) {
if (UIUtil.isUnderWin10LookAndFeel()) {
return IconLoader.getIcon("/com/intellij/ide/ui/laf/icons/win10/comboDropTriangle.png");
if (myWin10ComboDropTriagleIcon == null) {
myWin10ComboDropTriagleIcon = IconLoader.getIcon("/com/intellij/ide/ui/laf/icons/win10/comboDropTriangle.png");
}
return myWin10ComboDropTriagleIcon;
}
Icon icon = UIUtil.isUnderDarcula() ? AllIcons.General.ComboArrow : AllIcons.General.ComboBoxButtonArrow;
if (myIcon != icon) {
@@ -76,7 +76,7 @@ public class CreateDesktopEntryAction extends DumbAwareAction {
};
public static boolean isAvailable() {
return SystemInfo.isUnix && SystemInfo.hasXdgOpen();
return SystemInfo.isUnix && !SystemInfo.isSnap() && SystemInfo.hasXdgOpen();
}
@Override
@@ -51,7 +51,7 @@ public class CreateLauncherScriptAction extends DumbAwareAction {
private static final String CONTENTS = "/Contents";
public static boolean isAvailable() {
return SystemInfo.isUnix;
return SystemInfo.isUnix && !SystemInfo.isSnap();
}
@Override
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.actions;
import com.intellij.execution.ExecutionException;
@@ -283,9 +269,9 @@ public class ShowFilePathAction extends AnAction {
String toSelect = _toSelect != null ? FileUtil.toSystemDependentName(FileUtil.toCanonicalPath(_toSelect.getPath())) : null;
if (SystemInfo.isWindows) {
String cmd = toSelect != null ? "explorer /select," + toSelect : "explorer /root," + dir;
String cmd = toSelect != null ? "explorer /select,\"" + toSelect + '"' : "explorer /root,\"" + dir + '"';
LOG.debug(cmd);
Process process = Runtime.getRuntime().exec(cmd); // no quoting/escaping is needed
Process process = Runtime.getRuntime().exec(cmd); // no advanced quoting/escaping is needed
new CapturingProcessHandler(process, null, cmd).runProcess().checkSuccess(LOG);
}
else if (SystemInfo.isMac) {
@@ -20,6 +20,7 @@ import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
@@ -30,8 +30,8 @@ import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ui.*;
import com.intellij.util.ui.accessibility.ScreenReader;
import com.intellij.util.ui.accessibility.AccessibleContextUtil;
import com.intellij.util.ui.accessibility.ScreenReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -337,7 +337,7 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A
protected void processMouseEvent(MouseEvent e) {
super.processMouseEvent(e);
if (e.isConsumed()) return;
boolean skipPress = e.isMetaDown() || e.getButton() != MouseEvent.BUTTON1;
boolean skipPress = checkSkipPressForEvent(e);
switch (e.getID()) {
case MouseEvent.MOUSE_PRESSED:
if (skipPress || !isButtonEnabled()) return;
@@ -372,6 +372,10 @@ public class ActionButton extends JComponent implements ActionButtonComponent, A
}
}
protected boolean checkSkipPressForEvent(@NotNull MouseEvent e) {
return e.isMetaDown() || e.getButton() != MouseEvent.BUTTON1;
}
private int getPopState(boolean isPushed) {
if (isPushed || myRollover && myMouseDown && isButtonEnabled()) {
return PUSHED;
@@ -18,6 +18,7 @@ package com.intellij.openapi.updateSettings.impl;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.components.*;
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
@@ -65,7 +66,7 @@ public class UpdateSettings implements PersistentStateComponent<UpdateSettings.S
private State myState = new State();
public boolean isPlatformUpdateEnabled() {
return myPackageManager == null;
return myPackageManager == null && !SystemInfo.isSnap();
}
@NotNull
@@ -573,9 +573,12 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
for (int id : myData.myChildrenIds) {
existingNames.add(VfsData.getNameByFileId(id));
}
FSRecords.NameId[] persistentIds = FSRecords.listAll(getId());
for (FSRecords.NameId nameId : persistentIds) {
existingNames.add(nameId.name);
int id = getId();
if (id >= 0) {
FSRecords.NameId[] persistentIds = FSRecords.listAll(id);
for (FSRecords.NameId nameId : persistentIds) {
existingNames.add(nameId.name);
}
}
validateAgainst(childrenToCreate, existingNames);
@@ -205,11 +205,12 @@ public class StructureTreeModel extends AbstractTreeModel implements Disposable,
Object element = structure.getRootElement();
if (!isValid(element)) return null;
Node node = root.get();
boolean leaf = structure.isAlwaysLeaf(element);
if (node == null || leaf == node.getAllowsChildren() || !element.equals(node.getElement())) node = new Node(leaf);
node.update(structure.createDescriptor(element, null));
return node;
Node newNode = new Node(structure, element, null); // an exception may be thrown while getting a root
Node oldNode = root.get();
if (oldNode != null && oldNode.canReuse(newNode, element)) {
return oldNode; // reuse old node with possible children
}
return newNode;
}
private List<Node> getValidChildren(@NotNull Node node) {
@@ -225,32 +226,37 @@ public class StructureTreeModel extends AbstractTreeModel implements Disposable,
Object[] elements = structure.getChildElements(parent);
if (elements == null || elements.length == 0) return null;
List<Node> list = new ArrayList<>(elements.length);
for (Object element : elements) {
if (isValid(element)) {
list.add(new Node(structure, element, descriptor)); // an exception may be thrown while getting children
}
}
Comparator<Node> comparator = this.comparator;
if (comparator != null) list.sort(comparator); // an exception may be thrown while sorting children
HashMap<Object, Node> map = new HashMap<>();
node.getChildren().forEach(child -> {
Object element = child.getElement();
if (element != null) map.put(element, child);
});
List<Node> list = new ArrayList<>(elements.length);
for (Object element : elements) {
if (isValid(element)) {
Node child = map.get(element);
boolean leaf = structure.isAlwaysLeaf(element);
if (child == null || leaf == child.getAllowsChildren()) child = new Node(leaf);
child.update(structure.createDescriptor(element, descriptor));
list.add(child);
for (int i = 0; i < list.size(); i++) {
Node newNode = list.get(i);
Node oldNode = map.get(newNode.getElement());
if (oldNode != null && oldNode.canReuse(newNode, null)) {
list.set(i, oldNode); // reuse old node with possible children
}
}
Comparator<Node> comparator = this.comparator;
if (comparator != null) list.sort(comparator);
return list;
}
private static final class Node extends DefaultMutableTreeNode {
private final Reference<List<Node>> children = new Reference<>();
private Node(boolean leaf) {
super(null, !leaf);
if (leaf) children.set(null);
private Node(@NotNull AbstractTreeStructure structure, Object element, NodeDescriptor parent) {
super(structure.createDescriptor(element, parent), !structure.isAlwaysLeaf(element));
if (!getAllowsChildren()) children.set(null); // validate children for leaf node
update(); // an exception may be thrown while updating
}
private void dispose() {
@@ -259,9 +265,11 @@ public class StructureTreeModel extends AbstractTreeModel implements Disposable,
if (list != null) list.forEach(Node::dispose);
}
private void update(@NotNull NodeDescriptor descriptor) {
descriptor.update();
super.userObject = descriptor;
private boolean canReuse(@NotNull Node node, Object element) {
if (super.allowsChildren != node.allowsChildren) return false;
if (element != null && !element.equals(getElement())) return false;
super.userObject = node.userObject; // replace old descriptor
return true;
}
private boolean update() {

Some files were not shown because too many files have changed in this diff Show More