Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2017-11-21 18:47:48 +01:00
373 changed files with 5675 additions and 3261 deletions
+5
View File
@@ -16,5 +16,10 @@
<option name="name" value="IntelliJ Dependencies on Bintray" />
<option name="url" value="https://jetbrains.bintray.com/intellij-third-party-dependencies" />
</remote-repository>
<remote-repository>
<option name="id" value="jcenter"/>
<option name="name" value="JCenter on Bintray"/>
<option name="url" value="https://jcenter.bintray.com"/>
</remote-repository>
</component>
</project>
+4 -4
View File
@@ -1,15 +1,15 @@
<component name="libraryTable">
<library name="Trove4j">
<library name="Trove4j" type="repository">
<properties maven-id="org.jetbrains.intellij.deps:trove4j:1.0.20160824" />
<ANNOTATIONS>
<root url="file://$PROJECT_DIR$/lib/annotations/trove4j" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/trove4j.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/intellij/deps/trove4j/1.0.20160824/trove4j-1.0.20160824.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/trove4j_src.jar!/generated/src" />
<root url="jar://$PROJECT_DIR$/lib/src/trove4j_src.jar!/core/src" />
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/intellij/deps/trove4j/1.0.20160824/trove4j-1.0.20160824-sources.jar!/" />
</SOURCES>
</library>
</component>
+4 -3
View File
@@ -1,11 +1,12 @@
<component name="libraryTable">
<library name="swingx">
<library name="swingx" type="repository">
<properties maven-id="org.swinglabs:swingx-core:1.6.2-2" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/swingx-core-1.6.2.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/swinglabs/swingx-core/1.6.2-2/swingx-core-1.6.2-2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/src/swingx-1.6.2-src.zip!/java"/>
<root url="jar://$MAVEN_REPOSITORY$/org/swinglabs/swingx-core/1.6.2-2/swingx-core-1.6.2-2-sources.jar!/" />
</SOURCES>
</library>
</component>
+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 $R5
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
; -----------------------------------------------------------------------------
+1 -2
View File
@@ -116,6 +116,5 @@ task dependenciesFile() {
}
task wrapper(type: Wrapper) {
// 2.14 is the latest version supports Java 6 (which is still present on TeamCity build agents)
gradleVersion = '2.14'
gradleVersion = '4.3.1'
}
Binary file not shown.
@@ -1,6 +1,5 @@
#Fri Feb 17 14:30:05 MSK 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
+3 -3
View File
@@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
warn () {
echo "$*"
}
die ( ) {
die () {
echo
echo "$*"
echo
@@ -155,7 +155,7 @@ if $cygwin ; then
fi
# Escape application args
save ( ) {
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
@@ -15,6 +15,8 @@
*/
repositories {
mavenCentral()
maven { url "http://repo.labs.intellij.net/intellij-third-party-dependencies/" }
maven { url "https://jetbrains.bintray.com/intellij-third-party-dependencies" }
}
configurations {
@@ -28,6 +30,7 @@ dependencies {
buildScriptsDeps loadLibraryMavenId("OroMatcher")
buildScriptsDeps loadLibraryMavenId("commons-codec")
buildScriptsDeps loadLibraryMavenId("commons-logging")
buildScriptsDeps loadLibraryMavenId("Trove4j")
}
/**
-1
View File
@@ -39,7 +39,6 @@
<fileset dir="${idea.lib}">
<include name="jdom.jar"/>
<include name="log4j.jar"/>
<include name="trove4j.jar"/>
<include name="netty*.jar"/>
<include name="asm-all.jar"/>
<include name="jgoodies-forms.jar"/>
@@ -55,7 +55,6 @@ abstract class BaseIdeaProperties extends ProductProperties {
productLayout.additionalPlatformJars.put("jps-builders-6.jar", "jps-builders-6")
productLayout.additionalPlatformJars.put("aether-dependency-resolver.jar", "aether-dependency-resolver")
productLayout.additionalPlatformJars.put("jshell-protocol.jar", "jshell-protocol")
productLayout.additionalPlatformJars.putAll("jps-model.jar", ["jps-model-impl", "jps-model-serialization"])
productLayout.additionalPlatformJars.putAll("resources.jar", ["resources", "resources-en"])
productLayout.additionalPlatformJars.
putAll("javac2.jar", ["javac2", "forms-compiler", "forms_rt", "instrumentation-util", "instrumentation-util-8", "javac-ref-scanner-8"])
@@ -33,8 +33,7 @@ class IdeaCommunityProperties extends BaseIdeaProperties {
buildCrossPlatformDistribution = true
productLayout.platformApiJarModules = CommunityRepositoryModules.PLATFORM_API_MODULES
//jps modules are packed into a separate JAR to include into build process's classpath so we need to exclude them from the main platform JAR
productLayout.platformImplJarModules = CommunityRepositoryModules.PLATFORM_IMPLEMENTATION_MODULES - ["jps-model-impl", "jps-model-serialization"]
productLayout.platformImplJarModules = CommunityRepositoryModules.PLATFORM_IMPLEMENTATION_MODULES
productLayout.productApiModules = JAVA_API_MODULES
productLayout.productImplementationModules = JAVA_IMPLEMENTATION_MODULES +
["duplicates-analysis", "structuralsearch", "structuralsearch-java", "typeMigration", "platform-main"]
+15 -9
View File
@@ -154,17 +154,23 @@ private boolean ensureKotlinCompilerAddedToClassPath() {
return true
}
def kotlinPluginLibPath = "$home/build/dependencies/build/kotlin/Kotlin/lib"
if (!new File(kotlinPluginLibPath).exists()) {
kotlinPluginLibPath = "$home/community/build/dependencies/build/kotlin/Kotlin/lib"
def kotlinHomePath = "$home/build/dependencies/build/kotlin/Kotlin"
if (!new File(kotlinHomePath).exists()) {
kotlinHomePath = "$home/community/build/dependencies/build/kotlin/Kotlin"
}
if (!new File(kotlinPluginLibPath, "kotlin-runtime.jar").exists()) {
projectBuilder.error("Could not find Kotlin JARs at $kotlinPluginLibPath: run `./gradlew setupKotlinPlugin` in dependencies module " +
"to download Kotlin JARs")
return false
def kotlinPluginLibPath = "$kotlinHomePath/lib"
def kotlincLibPath = "$kotlinHomePath/kotlinc/lib"
if (new File(kotlinPluginLibPath).exists() && new File(kotlincLibPath).exists()) {
["jps/kotlin-jps-plugin.jar", "kotlin-plugin.jar", "kotlin-reflect.jar"].each {
BuildUtils.addToJpsClassPath("$kotlinPluginLibPath/$it", ant)
}
["kotlin-runtime.jar"].each {
BuildUtils.addToJpsClassPath("$kotlincLibPath/$it", ant)
}
}
["jps/kotlin-jps-plugin.jar", "kotlin-plugin.jar", "kotlin-runtime.jar", "kotlin-reflect.jar"].each {
BuildUtils.addToJpsClassPath("$kotlinPluginLibPath/$it", ant)
else {
projectBuilder.error(
"Could not find Kotlin JARs at $kotlinPluginLibPath and $kotlincLibPath: run `./gradlew setupKotlinPlugin` in dependencies module to download Kotlin JARs")
}
return true
}
@@ -16,10 +16,10 @@
package com.intellij.build;
import com.intellij.build.events.*;
import com.intellij.build.events.impl.FailureImpl;
import com.intellij.execution.ExecutionBundle;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.notification.Notification;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
@@ -134,16 +134,15 @@ public abstract class AbstractViewManager implements ViewManager, BuildProgressL
if (buildInfo.result instanceof FailureResult) {
boolean activate = buildInfo.activateToolWindowWhenFailed;
myBuildContentManager.setSelectedContent(buildInfo.content, activate, activate, activate, null);
List<? extends Failure> failures = ((FailureResult)buildInfo.result).getFailures();
List<? extends Failure>
failures = ((FailureResult)buildInfo.result).getFailures();
if (failures.isEmpty()) return;
Failure failure = failures.get(0);
if (failure instanceof FailureImpl) {
NotificationData notificationData = ((FailureImpl)failure).getNotificationData();
if (notificationData != null) {
final String title = notificationData.getNotification().getTitle();
final String content = notificationData.getNotification().getContent();
SystemNotifications.getInstance().notify(ToolWindowId.BUILD, title, content);
}
Notification notification = failure.getNotification();
if (notification != null) {
final String title = notification.getTitle();
final String content = notification.getContent();
SystemNotifications.getInstance().notify(ToolWindowId.BUILD, title, content);
}
}
}
@@ -196,7 +195,7 @@ public abstract class AbstractViewManager implements ViewManager, BuildProgressL
String tabName = getPinnedTabName(buildsView);
UIUtil.invokeLaterIfNeeded(() -> {
content.setPinnable(false);
if(content.getIcon() == null) {
if (content.getIcon() == null) {
content.setIcon(EmptyIcon.ICON_8);
}
content.putUserData(ToolWindow.SHOW_CONTENT_ICON, Boolean.TRUE);
@@ -16,7 +16,6 @@
package com.intellij.build;
import com.intellij.build.events.*;
import com.intellij.build.events.impl.FailureImpl;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
@@ -24,6 +23,7 @@ import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.icons.AllIcons;
import com.intellij.notification.Notification;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsManager;
@@ -61,8 +61,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
@@ -644,12 +642,13 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
.createActionToolbar("BuildResults", new DefaultActionGroup(consoleActions), false);
myPanel.add(toolbar.getComponent(), BorderLayout.EAST);
myPanel.setVisible(false);
tree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
TreePath path = tree.getSelectionPath();
setNode(path != null ? (DefaultMutableTreeNode)path.getLastPathComponent() : null);
tree.addTreeSelectionListener(e -> {
TreePath path = e.getPath();
if (path == null || !e.isAddedPath()) {
return;
}
TreePath selectionPath = tree.getSelectionPath();
setNode(selectionPath != null ? (DefaultMutableTreeNode)selectionPath.getLastPathComponent() : null);
});
Disposer.register(threeComponentsSplitter, myConsole);
@@ -670,7 +669,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
text = failure.getError().getMessage();
}
if (text == null) continue;
printDetails((FailureImpl)failure, text);
printDetails(failure, text);
hasChanged = true;
if (iterator.hasNext()) {
myConsole.print("\n\n", ConsoleViewContentType.NORMAL_OUTPUT);
@@ -690,7 +689,7 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
return true;
}
public void printDetails(FailureImpl failure, String text) {
public void printDetails(Failure failure, String text) {
String content = StringUtil.convertLineSeparators(text);
while (true) {
Matcher tagMatcher = TAG_PATTERN.matcher(content);
@@ -709,11 +708,10 @@ public class BuildTreeConsoleView implements ConsoleView, DataProvider, BuildCon
myConsole.printHyperlink(linkText, new HyperlinkInfo() {
@Override
public void navigate(Project project) {
NotificationData notificationData = failure.getNotificationData();
if (notificationData != null) {
notificationData.getListener().hyperlinkUpdate(
notificationData.getNotification(),
IJSwingUtilities.createHyperlinkEvent(href, myConsole.getComponent()));
Notification notification = failure.getNotification();
if (notification != null && notification.getListener() != null) {
notification.getListener().hyperlinkUpdate(
notification, IJSwingUtilities.createHyperlinkEvent(href, myConsole.getComponent()));
}
}
});
@@ -16,7 +16,6 @@
package com.intellij.build;
import com.intellij.build.events.*;
import com.intellij.build.events.impl.FailureImpl;
import com.intellij.icons.AllIcons;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.openapi.project.Project;
@@ -148,7 +147,7 @@ public class ExecutionNode extends CachingSimpleNode {
final long duration = startTime == 0 ? 0 : System.currentTimeMillis() - startTime;
String durationText = StringUtil.formatDuration(duration);
int index = durationText.indexOf("s ");
if(index != -1) {
if (index != -1) {
durationText = durationText.substring(0, index + 1);
}
return "Running for " + durationText;
@@ -218,10 +217,7 @@ public class ExecutionNode extends CachingSimpleNode {
if (myResult instanceof FailureResult) {
List<Navigatable> result = new SmartList<>();
for (Failure failure : ((FailureResult)myResult).getFailures()) {
NotificationData notificationData = ((FailureImpl)failure).getNotificationData();
if (notificationData != null) {
ContainerUtil.addIfNotNull(result, notificationData.getNavigatable());
}
ContainerUtil.addIfNotNull(result, failure.getNavigatable());
}
return result;
}
@@ -204,7 +204,7 @@ public class MultipleBuildsView implements BuildProgressListener, Disposable {
Disposer.register(view, contentDescriptor);
}
else {
myBuildContentManager.setSelectedContent(myContent, true, true, true, null);
myBuildContentManager.setSelectedContent(myContent, true, true, false, null);
}
buildInfo.content = myContent;
@@ -15,6 +15,8 @@
*/
package com.intellij.build.events;
import com.intellij.notification.Notification;
import com.intellij.pom.Navigatable;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
@@ -32,7 +34,13 @@ public interface Failure {
String getDescription();
@Nullable
Throwable getError();
default Throwable getError() {return null;}
List<? extends Failure> getCauses();
@Nullable
default Notification getNotification() {return null;}
@Nullable
default Navigatable getNavigatable() {return null;}
}
@@ -1,39 +0,0 @@
/*
* 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.build.events;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.pom.Navigatable;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Vladislav.Soroka
*/
@ApiStatus.Experimental
public interface NotificationData {
@NotNull
Notification getNotification();
@NotNull
NotificationListener getListener();
@Nullable
Navigatable getNavigatable();
}
@@ -16,7 +16,8 @@
package com.intellij.build.events.impl;
import com.intellij.build.events.Failure;
import com.intellij.build.events.NotificationData;
import com.intellij.notification.Notification;
import com.intellij.pom.Navigatable;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
@@ -32,34 +33,38 @@ public class FailureImpl implements Failure {
private final List<? extends Failure> myCauses;
private final Throwable myError;
@Nullable
private final NotificationData myNotificationData;
private final Notification myNotification;
@Nullable
private final Navigatable myNavigatable;
public FailureImpl(String message, Throwable error) {
this(message, null, Collections.emptyList(), error, null);
this(message, null, Collections.emptyList(), error, null, null);
}
public FailureImpl(String message, Throwable error, @Nullable NotificationData notificationData) {
this(message, null, Collections.emptyList(), error, notificationData);
public FailureImpl(String message, Throwable error, @Nullable Notification notification, @Nullable Navigatable navigatable) {
this(message, null, Collections.emptyList(), error, notification, navigatable);
}
public FailureImpl(String message, String description) {
this(message, description, Collections.emptyList(), null, null);
this(message, description, Collections.emptyList(), null, null, null);
}
public FailureImpl(String message, String description, List<? extends Failure> causes) {
this(message, description, causes, null, null);
this(message, description, causes, null, null, null);
}
private FailureImpl(String message,
String description,
List<? extends Failure> causes,
Throwable error,
@Nullable NotificationData notificationData) {
@Nullable Notification notification,
@Nullable Navigatable navigatable) {
myMessage = message;
myDescription = description;
myCauses = causes;
myError = error;
myNotificationData = notificationData;
myNotification = notification;
myNavigatable = navigatable;
}
@Nullable
@@ -86,7 +91,14 @@ public class FailureImpl implements Failure {
}
@Nullable
public NotificationData getNotificationData() {
return myNotificationData;
@Override
public Notification getNotification() {
return myNotification;
}
@Nullable
@Override
public Navigatable getNavigatable() {
return myNavigatable;
}
}
@@ -1,58 +0,0 @@
/*
* 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.build.events.impl;
import com.intellij.build.events.NotificationData;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.pom.Navigatable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Vladislav.Soroka
*/
public class NotificationDataImpl implements NotificationData {
@NotNull private final Notification notification;
@NotNull private final NotificationListener myListener;
@Nullable private final Navigatable navigatable;
public NotificationDataImpl(@NotNull Notification notification,
@NotNull NotificationListener listener,
@Nullable Navigatable navigatable) {
this.notification = notification;
myListener = listener;
this.navigatable = navigatable;
}
@NotNull
@Override
public Notification getNotification() {
return notification;
}
@NotNull
@Override
public NotificationListener getListener() {
return myListener;
}
@Nullable
@Override
public Navigatable getNavigatable() {
return navigatable;
}
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.util.TripleFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,6 +35,8 @@ public final class CompilerMessageImpl implements CompilerMessage {
private final VirtualFile myFile;
private final int myRow;
private final int myColumn;
@NotNull
private TripleFunction<CompilerMessage, Integer, Integer, Integer> myColumnAdjuster = (msg, line, col) -> col;
public CompilerMessageImpl(Project project, CompilerMessageCategory category, String message) {
this(project, category, message, null, -1, -1, null);
@@ -55,6 +58,10 @@ public final class CompilerMessageImpl implements CompilerMessage {
myFile = file;
}
public void setColumnAdjuster(@NotNull TripleFunction<CompilerMessage, Integer, Integer, Integer> columnAdjuster) {
myColumnAdjuster = columnAdjuster;
}
@NotNull
@Override
public CompilerMessageCategory getCategory() {
@@ -75,7 +82,7 @@ public final class CompilerMessageImpl implements CompilerMessage {
if (virtualFile != null && virtualFile.isValid()) {
final int line = getLine() - 1; // editor lines are zero-based
if (line >= 0) {
return myNavigatable = new OpenFileDescriptor(myProject, virtualFile, line, Math.max(0, getColumn()-1));
return myNavigatable = new OpenFileDescriptor(myProject, virtualFile, line, myColumnAdjuster.fun(this, line, Math.max(0, getColumn()-1))) ;
}
}
return null;
@@ -16,7 +16,7 @@ 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)
@State(name = "ExternalCompilerConfiguration", 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
@@ -15,10 +15,16 @@
*/
package com.intellij.compiler.impl;
import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.compiler.CompilerMessageImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerMessage;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.pom.Navigatable;
@@ -32,11 +38,15 @@ import java.util.*;
* Date: 27-Jan-16
*/
public class MessagesContainer {
private static final int JAVAC_TAB_SIZE = 8;
private final Project myProject;
private final Map<CompilerMessageCategory, Collection<CompilerMessage>> myMessages = new EnumMap<>(CompilerMessageCategory.class);
private final int myTabSize;
public MessagesContainer(Project project) {
myProject = project;
myTabSize = CodeStyleFacade.getInstance().getTabSize(StdFileTypes.JAVA);
}
@NotNull
@@ -52,11 +62,49 @@ public class MessagesContainer {
public CompilerMessage addMessage(CompilerMessageCategory category, String message, String url, int lineNum, int columnNum, Navigatable navigatable) {
CompilerMessageImpl msg = new CompilerMessageImpl(myProject, category, message, findFileByUrl(url), lineNum, columnNum, navigatable);
if (addMessage(msg)) {
msg.setColumnAdjuster((m, line, col) -> adjustColumn(m, line, col));
return msg;
}
return null;
}
private int adjustColumn(final CompilerMessage m, final int line, final int col) {
if (myTabSize != JAVAC_TAB_SIZE && line >= 1) {
// javac uses hard-coded tab size 8 chars. So recalculate only if project's codestyle is different
final VirtualFile file = m.getVirtualFile();
if (file != null && file.isValid()) {
final int tabCount = ApplicationManager.getApplication().runReadAction((Computable<Integer>)() -> {
final Document doc = FileDocumentManager.getInstance().getDocument(file);
if (doc == null) {
return 0;
}
int tcount = 0;
final CharSequence seq = doc.getCharsSequence();
final int start = doc.getLineStartOffset(line);
final int end = doc.getLineEndOffset(line);
int charsExpanded = 0;
for (int i = start; i< end; i++) {
if (seq.charAt(i) == '\t') {
charsExpanded += JAVAC_TAB_SIZE;
tcount++;
}
else {
charsExpanded += 1;
}
if (charsExpanded >= col) {
break; // consider only those tabs that are located before the given column number
}
}
return tcount;
});
if (tabCount > 0) {
return Math.max(0, col + tabCount * (myTabSize - JAVAC_TAB_SIZE));
}
}
}
return col;
}
public boolean addMessage(CompilerMessage msg) {
Collection<CompilerMessage> messages = myMessages.computeIfAbsent(msg.getCategory(), k -> new LinkedHashSet<>());
return messages.add(msg);
@@ -40,6 +40,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
private JCheckBox myCbShowObjectId;
private JCheckBox myCbShowStringsType;
private JCheckBox myCbHexValue;
private JCheckBox myCbPopulateThrowableStack;
private StateRestoringCheckBox myCbShowStaticFinalFields;
//private final ArrayRendererConfigurable myArrayRendererConfigurable;
@@ -110,6 +111,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
myCbShowObjectId = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.object.id"));
myCbHexValue = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.hex.value"));
myCbShowStringsType = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.show.strings.type"));
myCbPopulateThrowableStack = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.populate.throwable.stack"));
myCbEnableToString = new JCheckBox(DebuggerBundle.message("label.base.renderer.configurable.enable.toString"));
myRbAllThatOverride = new JRadioButton(DebuggerBundle.message("label.base.renderer.configurable.all.overriding"));
@@ -160,6 +162,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
panel.add(myCbShowStringsType, new GridBagConstraints(0, RELATIVE, 3, 1, 1.0, 0.0, NORTH, HORIZONTAL, JBUI.emptyInsets(), 0, 0));
panel.add(myCbHexValue, new GridBagConstraints(0, RELATIVE, 3, 1, 1.0, 0.0, NORTH, HORIZONTAL, JBUI.insetsTop(4), 0, 0));
panel.add(myCbHideNullArrayElements, new GridBagConstraints(0, RELATIVE, 3, 1, 1.0, 0.0, NORTH, HORIZONTAL, JBUI.insetsTop(4), 0, 0));
panel.add(myCbPopulateThrowableStack, new GridBagConstraints(0, RELATIVE, 3, 1, 1.0, 0.0, NORTH, HORIZONTAL, JBUI.insetsTop(4), 0, 0));
panel.add(myCbEnableAlternateViews, new GridBagConstraints(0, RELATIVE, 1, 1, 0.0, 0.0, WEST, NONE, JBUI.insets(4, 0, 0, 10), 0, 0));
// starting 4-th row
@@ -180,6 +183,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
generalSettings.AUTOSCROLL_TO_NEW_LOCALS = myCbAutoscroll.isSelected();
rendererSettings.setAlternateCollectionViewsEnabled(myCbEnableAlternateViews.isSelected());
generalSettings.HIDE_NULL_ARRAY_ELEMENTS = myCbHideNullArrayElements.isSelected();
generalSettings.POPULATE_THROWABLE_STACKTRACE = myCbPopulateThrowableStack.isSelected();
final ClassRenderer classRenderer = rendererSettings.getClassRenderer();
classRenderer.SHOW_STATIC = myCbShowStatic.isSelected();
@@ -210,6 +214,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
myCbAutoscroll.setSelected(generalSettings.AUTOSCROLL_TO_NEW_LOCALS);
myCbHideNullArrayElements.setSelected(generalSettings.HIDE_NULL_ARRAY_ELEMENTS);
myCbEnableAlternateViews.setSelected(rendererSettings.areAlternateCollectionViewsEnabled());
myCbPopulateThrowableStack.setSelected(generalSettings.POPULATE_THROWABLE_STACKTRACE);
ClassRenderer classRenderer = rendererSettings.getClassRenderer();
@@ -251,7 +256,8 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable {
private boolean areGeneralSettingsModified() {
ViewsGeneralSettings generalSettings = ViewsGeneralSettings.getInstance();
return generalSettings.AUTOSCROLL_TO_NEW_LOCALS != myCbAutoscroll.isSelected() ||
generalSettings.HIDE_NULL_ARRAY_ELEMENTS != myCbHideNullArrayElements.isSelected();
generalSettings.HIDE_NULL_ARRAY_ELEMENTS != myCbHideNullArrayElements.isSelected() ||
generalSettings.POPULATE_THROWABLE_STACKTRACE != myCbPopulateThrowableStack.isSelected();
}
private boolean areDefaultRenderersModified() {
@@ -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.settings;
import com.intellij.openapi.components.PersistentStateComponent;
@@ -29,6 +15,7 @@ public class ViewsGeneralSettings implements PersistentStateComponent<ViewsGener
public boolean SHOW_OBJECTID = true;
public boolean HIDE_NULL_ARRAY_ELEMENTS = true;
public boolean AUTOSCROLL_TO_NEW_LOCALS = true;
public boolean POPULATE_THROWABLE_STACKTRACE = true;
public static ViewsGeneralSettings getInstance() {
return ServiceManager.getService(ViewsGeneralSettings.class);
@@ -49,6 +36,7 @@ public class ViewsGeneralSettings implements PersistentStateComponent<ViewsGener
ViewsGeneralSettings generalSettings = ((ViewsGeneralSettings)object);
return SHOW_OBJECTID == generalSettings.SHOW_OBJECTID &&
HIDE_NULL_ARRAY_ELEMENTS == generalSettings.HIDE_NULL_ARRAY_ELEMENTS &&
AUTOSCROLL_TO_NEW_LOCALS == generalSettings.AUTOSCROLL_TO_NEW_LOCALS;
AUTOSCROLL_TO_NEW_LOCALS == generalSettings.AUTOSCROLL_TO_NEW_LOCALS &&
POPULATE_THROWABLE_STACKTRACE == generalSettings.POPULATE_THROWABLE_STACKTRACE;
}
}
@@ -14,10 +14,10 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.PositionUtil;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.settings.ViewsGeneralSettings;
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;
@@ -84,8 +84,12 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
DebuggerManagerThreadImpl.assertIsManagerThread();
try {
if (myObject != null) {
populateExceptionStackTraceIfNeeded(evaluationContext);
return myObject.getValue(myField);
Value fieldValue = myObject.getValue(myField);
if (populateExceptionStackTraceIfNeeded(fieldValue, evaluationContext)) {
// re-read stacktrace value
fieldValue = myObject.getValue(myField);
}
return fieldValue;
}
else {
return myField.declaringType().getValue(myField);
@@ -96,17 +100,21 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
}
}
private void populateExceptionStackTraceIfNeeded(EvaluationContextImpl evaluationContext) {
private boolean populateExceptionStackTraceIfNeeded(Value value, EvaluationContextImpl evaluationContext) {
if ("stackTrace".equals(getName()) &&
Registry.is("debugger.populate.exception.stack") &&
ViewsGeneralSettings.getInstance().POPULATE_THROWABLE_STACKTRACE &&
value instanceof ArrayReference &&
((ArrayReference)value).length() == 0 &&
DebuggerUtils.instanceOf(myObject.type(), CommonClassNames.JAVA_LANG_THROWABLE)) {
try {
invokeExceptionGetStackTrace(myObject, evaluationContext);
return true;
}
catch (Throwable e) {
LOG.info(e); // catch all exceptions to ensure the method returns gracefully
}
}
return false;
}
public boolean isStatic() {
@@ -19,6 +19,7 @@ import com.intellij.execution.configuration.RunConfigurationExtensionsManager;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
public class JavaRunConfigurationExtensionManager extends RunConfigurationExtensionsManager<RunConfigurationBase, RunConfigurationExtension> {
private static final Logger LOG = Logger.getInstance(RunConfigurationExtension.class);
@@ -40,11 +41,13 @@ public class JavaRunConfigurationExtensionManager extends RunConfigurationExtens
}
}
@NotNull
@Override
protected String getIdAttrName() {
return "name";
}
@NotNull
@Override
protected String getExtensionRootAttr() {
return "extension";
@@ -189,11 +189,7 @@ public class ExistingLibraryEditor extends LibraryEditorBase implements Disposab
@Override
public void removeRoot(@NotNull String url, @NotNull OrderRootType rootType) {
boolean removed;
do {
removed = getModel().removeRoot(url, rootType);
}
while (removed);
getModel().removeRoot(url, rootType);
}
@Override
@@ -1,30 +1,13 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 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.codeInspection;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.psi.PsiDocCommentOwner;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifierListOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public interface BatchSuppressManager {
String SUPPRESS_INSPECTIONS_ANNOTATION_NAME = "java.lang.SuppressWarnings";
@@ -38,17 +21,6 @@ public interface BatchSuppressManager {
boolean isSuppressedFor(@NotNull PsiElement element, @NotNull String toolId);
PsiElement getElementMemberSuppressedIn(@NotNull PsiDocCommentOwner owner, @NotNull String inspectionToolID);
@Nullable
PsiElement getAnnotationMemberSuppressedIn(@NotNull PsiModifierListOwner owner, @NotNull String inspectionToolID);
@Nullable
PsiElement getDocCommentToolSuppressedIn(@NotNull PsiDocCommentOwner owner, @NotNull String inspectionToolID);
@NotNull
Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull PsiModifierListOwner owner);
@Nullable
String getSuppressedInspectionIdsIn(@NotNull PsiElement element);
@@ -21,5 +21,6 @@
<orderEntry type="library" exported="" name="ASM" level="project" />
<orderEntry type="library" name="StreamEx" level="project" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="module" module-name="openapi" />
</component>
</module>
@@ -785,9 +785,15 @@ public class AnnotationsHighlightUtil {
return getText();
}
@Nullable
@Override
public PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) {
return myAnnotation;
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
return myAnnotation.isValid();
}
@Override
@@ -50,7 +50,7 @@ public class ExpressionTypeMemoryState extends DfaMemoryStateImpl {
return false;
}
};
private final MultiMap<PsiExpression, PsiType> myStates = MultiMap.create(EXPRESSION_HASHING_STRATEGY);
private final MultiMap<PsiExpression, PsiType> myStates = MultiMap.createSet(EXPRESSION_HASHING_STRATEGY);
public ExpressionTypeMemoryState(final DfaValueFactory factory) {
super(factory);
@@ -75,6 +75,7 @@ public class ExpressionTypeMemoryState extends DfaMemoryStateImpl {
if (!value.isNegated()) {
setExpressionType(value.getExpression(), value.getCastType());
}
return super.applyCondition(((DfaInstanceofValue)dfaCond).getRelation());
}
return super.applyCondition(dfaCond);
@@ -91,10 +92,7 @@ public class ExpressionTypeMemoryState extends DfaMemoryStateImpl {
if (!super.equals(o)) return false;
ExpressionTypeMemoryState that = (ExpressionTypeMemoryState)o;
if (!myStates.equals(that.myStates)) return false;
return true;
return myStates.equals(that.myStates);
}
@Override
@@ -17,11 +17,10 @@ package com.intellij.codeInsight.guess.impl;
import com.intellij.codeInsight.guess.GuessManager;
import com.intellij.codeInspection.dataFlow.*;
import com.intellij.codeInspection.dataFlow.instructions.InstanceofInstruction;
import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction;
import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
import com.intellij.codeInspection.dataFlow.instructions.TypeCastInstruction;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.DfaInstanceofValue;
import com.intellij.codeInspection.dataFlow.value.DfaRelationValue;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
@@ -36,7 +35,7 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.util.BitUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashMap;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -156,33 +155,60 @@ public class GuessManagerImpl extends GuessManager {
};
final ExpressionTypeInstructionVisitor visitor = new ExpressionTypeInstructionVisitor(forPlace);
if (runner.analyzeMethod(scope, visitor) == RunnerResult.OK) {
if (runner.analyzeMethodWithInlining(scope, visitor) == RunnerResult.OK) {
return visitor.getResult();
}
return null;
}
private static Map<PsiExpression, PsiType> getAllTypeCasts(PsiExpression forPlace) {
assert forPlace.isValid();
final int start = forPlace.getTextRange().getStartOffset();
final Map<PsiExpression, PsiType> allCasts = new THashMap<>(ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY);
getTopmostBlock(forPlace).accept(new JavaRecursiveElementWalkingVisitor() {
private static boolean mayHaveMorePreciseType(PsiExpression expr) {
PsiExpression place = PsiUtil.skipParenthesizedExprDown(expr);
if (place instanceof PsiReferenceExpression) {
PsiElement target = ((PsiReferenceExpression)place).resolve();
if (target instanceof PsiParameter) {
PsiElement parent = target.getParent();
if (parent instanceof PsiParameterList && parent.getParent() instanceof PsiLambdaExpression) {
return true;
}
}
}
if (place == null) return false;
final int start = place.getTextRange().getStartOffset();
class Visitor extends JavaRecursiveElementWalkingVisitor {
public boolean hasInteresting;
@Override
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
if (ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY.equals(expression.getLExpression(), place)) {
hasInteresting = true;
stopWalking();
}
super.visitAssignmentExpression(expression);
}
@Override
public void visitLocalVariable(PsiLocalVariable variable) {
if (variable.getInitializer() != null && ExpressionUtils.isReferenceTo(place, variable)) {
hasInteresting = true;
stopWalking();
}
super.visitLocalVariable(variable);
}
@Override
public void visitTypeCastExpression(PsiTypeCastExpression expression) {
final PsiType castType = expression.getType();
final PsiExpression operand = expression.getOperand();
if (operand != null && castType != null) {
allCasts.put(operand, castType);
if (ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY.equals(expression.getOperand(), place)) {
hasInteresting = true;
stopWalking();
}
super.visitTypeCastExpression(expression);
}
@Override
public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
final PsiTypeElement castType = expression.getCheckType();
final PsiExpression operand = expression.getOperand();
if (castType != null) {
allCasts.put(operand, castType.getType());
if (ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY.equals(expression.getOperand(), place)) {
hasInteresting = true;
stopWalking();
}
super.visitInstanceOfExpression(expression);
}
@@ -190,13 +216,14 @@ public class GuessManagerImpl extends GuessManager {
@Override
public void visitElement(PsiElement element) {
if (element.getTextRange().getStartOffset() > start) {
return;
stopWalking();
}
super.visitElement(element);
}
});
return allCasts;
}
Visitor visitor = new Visitor();
getTopmostBlock(place).accept(visitor);
return visitor.hasInteresting;
}
private static PsiElement getTopmostBlock(PsiElement scope) {
@@ -375,8 +402,7 @@ public class GuessManagerImpl extends GuessManager {
@NotNull
@Override
public List<PsiType> getControlFlowExpressionTypeConjuncts(@NotNull PsiExpression expr) {
final Map<PsiExpression, PsiType> allCasts = getAllTypeCasts(expr);
if (!allCasts.containsKey(expr)) {
if (!mayHaveMorePreciseType(expr)) {
return Collections.emptyList(); //optimization
}
@@ -391,9 +417,10 @@ public class GuessManagerImpl extends GuessManager {
return Collections.emptyList();
}
private static class ExpressionTypeInstructionVisitor extends InstructionVisitor {
private static class ExpressionTypeInstructionVisitor extends StandardInstructionVisitor {
private MultiMap<PsiExpression, PsiType> myResult;
private final PsiElement myForPlace;
private TypeConstraint myConstraint = null;
private ExpressionTypeInstructionVisitor(@NotNull PsiElement forPlace) {
PsiElement parent = PsiUtil.skipParenthesizedExprUp(forPlace.getParent());
@@ -405,14 +432,24 @@ public class GuessManagerImpl extends GuessManager {
}
MultiMap<PsiExpression, PsiType> getResult() {
if (myConstraint != null && myForPlace instanceof PsiExpression) {
PsiType type = myConstraint.getPsiType();
if (type instanceof PsiIntersectionType) {
myResult.putValues((PsiExpression)myForPlace, Arrays.asList(((PsiIntersectionType)type).getConjuncts()));
}
else {
myResult.putValue((PsiExpression)myForPlace, type);
}
}
return myResult;
}
@Override
public DfaInstructionState[] visitInstanceof(InstanceofInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
memState.pop();
memState.pop();
memState.push(new DfaInstanceofValue(runner.getFactory(), instruction.getLeft(), instruction.getCastType()));
DfaValue type = memState.pop();
DfaValue operand = memState.pop();
DfaValue relation = runner.getFactory().createCondition(operand, DfaRelationValue.RelationType.IS, type);
memState.push(new DfaInstanceofValue(runner.getFactory(), instruction.getLeft(), instruction.getCastType(), relation, false));
return new DfaInstructionState[]{new DfaInstructionState(runner.getInstruction(instruction.getIndex() + 1), memState)};
}
@@ -422,12 +459,27 @@ public class GuessManagerImpl extends GuessManager {
return super.visitTypeCast(instruction, runner, memState);
}
@Override
public DfaInstructionState[] visitAssign(AssignInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
PsiExpression left = instruction.getLExpression();
PsiExpression right = instruction.getRExpression();
if (left != null && right != null) {
MultiMap<PsiExpression, PsiType> states = ((ExpressionTypeMemoryState)memState).getStates();
states.remove(left);
}
return super.visitAssign(instruction, runner, memState);
}
@Override
public DfaInstructionState[] visitMethodCall(MethodCallInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
if (myForPlace == instruction.getCallExpression()) {
addToResult(((ExpressionTypeMemoryState)memState).getStates());
}
return super.visitMethodCall(instruction, runner, memState);
DfaInstructionState[] states = super.visitMethodCall(instruction, runner, memState);
if (myForPlace == instruction.getCallExpression()) {
addConstraints(states);
}
return states;
}
@Override
@@ -435,12 +487,31 @@ public class GuessManagerImpl extends GuessManager {
if (myForPlace == instruction.getPlace()) {
addToResult(((ExpressionTypeMemoryState)memState).getStates());
}
return super.visitPush(instruction, runner, memState);
DfaInstructionState[] states = super.visitPush(instruction, runner, memState);
if (myForPlace == instruction.getPlace()) {
addConstraints(states);
}
return states;
}
private void addConstraints(DfaInstructionState[] states) {
for (DfaInstructionState state : states) {
DfaMemoryState memoryState = state.getMemoryState();
if (myConstraint == TypeConstraint.EMPTY) return;
TypeConstraint constraint = memoryState.getValueFact(memoryState.peek(), DfaFactType.TYPE_CONSTRAINT);
if (constraint != null) {
myConstraint = myConstraint == null ? constraint : myConstraint.union(constraint);
if (myConstraint == null) {
myConstraint = TypeConstraint.EMPTY;
return;
}
}
}
}
private void addToResult(MultiMap<PsiExpression, PsiType> map) {
if (myResult == null) {
myResult = MultiMap.create(ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY);
myResult = MultiMap.createSet(ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY);
myResult.putAllValues(map);
} else {
final Iterator<PsiExpression> iterator = myResult.keySet().iterator();
@@ -1,30 +1,13 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 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.codeInspection;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.actions.*;
import com.intellij.psi.PsiDocCommentOwner;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifierListOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public class BatchSuppressManagerImpl implements BatchSuppressManager {
@NotNull
@Override
@@ -45,30 +28,6 @@ public class BatchSuppressManagerImpl implements BatchSuppressManager {
return JavaSuppressionUtil.getElementToolSuppressedIn(element, toolId) != null;
}
@Override
@Nullable
public PsiElement getElementMemberSuppressedIn(@NotNull final PsiDocCommentOwner owner, @NotNull final String inspectionToolID) {
return JavaSuppressionUtil.getElementMemberSuppressedIn(owner, inspectionToolID);
}
@Override
@Nullable
public PsiElement getAnnotationMemberSuppressedIn(@NotNull final PsiModifierListOwner owner, @NotNull final String inspectionToolID) {
return JavaSuppressionUtil.getAnnotationMemberSuppressedIn(owner, inspectionToolID);
}
@Override
@Nullable
public PsiElement getDocCommentToolSuppressedIn(@NotNull final PsiDocCommentOwner owner, @NotNull final String inspectionToolID) {
return JavaSuppressionUtil.getDocCommentToolSuppressedIn(owner, inspectionToolID);
}
@Override
@NotNull
public Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull final PsiModifierListOwner owner) {
return JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation(owner);
}
@Override
@Nullable
public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
@@ -1,18 +1,4 @@
/*
* 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.codeInspection;
@@ -20,12 +6,9 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiDocCommentOwner;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifierListOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public class SuppressManagerImpl extends SuppressManager {
private static final Logger LOG = Logger.getInstance(SuppressManager.class);
@@ -49,30 +32,6 @@ public class SuppressManagerImpl extends SuppressManager {
return JavaSuppressionUtil.getElementToolSuppressedIn(element, toolId) != null;
}
@Override
@Nullable
public PsiElement getElementMemberSuppressedIn(@NotNull final PsiDocCommentOwner owner, @NotNull final String inspectionToolID) {
return JavaSuppressionUtil.getElementMemberSuppressedIn(owner, inspectionToolID);
}
@Override
@Nullable
public PsiElement getAnnotationMemberSuppressedIn(@NotNull final PsiModifierListOwner owner, @NotNull final String inspectionToolID) {
return JavaSuppressionUtil.getAnnotationMemberSuppressedIn(owner, inspectionToolID);
}
@Override
@Nullable
public PsiElement getDocCommentToolSuppressedIn(@NotNull final PsiDocCommentOwner owner, @NotNull final String inspectionToolID) {
return JavaSuppressionUtil.getDocCommentToolSuppressedIn(owner, inspectionToolID);
}
@Override
@NotNull
public Collection<String> getInspectionIdsSuppressedInAnnotation(@NotNull final PsiModifierListOwner owner) {
return JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation(owner);
}
@Override
@Nullable
public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
@@ -81,7 +82,7 @@ public class FieldAccessNotGuardedInspection extends AbstractBaseJavaLocalInspec
if (guardExpression instanceof PsiThisExpression) {
final PsiThisExpression thisExpression = (PsiThisExpression)guardExpression;
final PsiClass aClass = getClassFromThisExpression(thisExpression, field);
if (aClass == null || aClass.equals(containingMethod.getContainingClass())) {
if (aClass == null || InheritanceUtil.isInheritorOrSelf(containingMethod.getContainingClass(), aClass, true)) {
return;
}
}
@@ -82,7 +82,7 @@ public class CommonDataflow {
return states;
}
};
RunnerResult result = runner.analyzeMethod(block, visitor);
RunnerResult result = runner.analyzeMethodRecursively(block, visitor);
return result == RunnerResult.OK ? dfr : null;
}
@@ -18,7 +18,6 @@ import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.DfaConstValue;
import com.intellij.codeInspection.dataFlow.value.DfaUnknownValue;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.codeInspection.nullable.NullableStuffInspectionBase;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -31,7 +30,6 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.siyeh.ig.psiutils.*;
import one.util.streamex.StreamEx;
import org.jdom.Element;
@@ -184,24 +182,7 @@ public class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool
final RunnerResult rc = dfaRunner.analyzeMethod(scope, visitor, IGNORE_ASSERT_STATEMENTS, initialStates);
if (rc == RunnerResult.OK) {
createDescription(dfaRunner, holder, visitor, scope);
MultiMap<PsiElement,DfaMemoryState> nestedClosures = dfaRunner.getNestedClosures();
for (PsiElement closure : nestedClosures.keySet()) {
List<DfaVariableValue> unusedVars = StreamEx.of(dfaRunner.getFactory().getValues())
.select(DfaVariableValue.class)
.filter(var -> var.getQualifier() == null)
.filter(var -> var.getPsiVariable() instanceof PsiVariable &&
!VariableAccessUtils.variableIsUsed((PsiVariable)var.getPsiVariable(), closure))
.toList();
Collection<? extends DfaMemoryState> states = nestedClosures.get(closure);
if (!unusedVars.isEmpty()) {
List<DfaMemoryStateImpl> stateList = StreamEx.of(states)
.peek(state -> unusedVars.forEach(state::flushVariable))
.map(state -> (DfaMemoryStateImpl)state).distinct().toList();
states = StateQueue.mergeGroup(stateList);
}
analyzeDfaWithNestedClosures(closure, holder, dfaRunner, states);
}
dfaRunner.forNestedClosures((closure, states) -> analyzeDfaWithNestedClosures(closure, holder, dfaRunner, states));
}
else if (rc == RunnerResult.TOO_COMPLEX) {
PsiIdentifier name = null;
@@ -23,6 +23,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -30,12 +31,14 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import gnu.trove.THashSet;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class DataFlowRunner {
@@ -73,14 +76,16 @@ public class DataFlowRunner {
}
@Nullable
private Collection<DfaMemoryState> createInitialStates(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
private Collection<DfaMemoryState> createInitialStates(@NotNull PsiElement psiBlock,
@NotNull InstructionVisitor visitor,
boolean allowInlining) {
PsiElement container = PsiTreeUtil.getParentOfType(psiBlock, PsiClass.class, PsiLambdaExpression.class);
if (container != null && (!(container instanceof PsiClass) || PsiUtil.isLocalOrAnonymousClass((PsiClass)container))) {
PsiElement block = DfaPsiUtil.getTopmostBlockInSameClass(container.getParent());
if (block != null) {
final RunnerResult result;
try {
myInlining = false;
myInlining = allowInlining;
result = analyzeMethod(block, visitor);
}
finally {
@@ -88,7 +93,7 @@ public class DataFlowRunner {
}
if (result == RunnerResult.OK) {
final Collection<DfaMemoryState> closureStates = myNestedClosures.get(DfaPsiUtil.getTopmostBlockInSameClass(psiBlock));
if (!closureStates.isEmpty()) {
if (allowInlining || !closureStates.isEmpty()) {
return closureStates;
}
}
@@ -99,12 +104,41 @@ public class DataFlowRunner {
return Collections.singletonList(createMemoryState());
}
/**
* Analyze this particular method (lambda, class initializer) without inlining this method into parent one.
* E.g. if supplied method is a lambda within Stream API call chain, it still will be analyzed as separate method.
* On the other hand, inlining will normally work inside the supplied method.
*
* @param psiBlock method/lambda/class initializer body
* @param visitor a visitor to use
* @return result status
*/
@NotNull
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor);
Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor, false);
return initialStates == null ? RunnerResult.NOT_APPLICABLE : analyzeMethod(psiBlock, visitor, false, initialStates);
}
/**
* Analyze this particular method (lambda, class initializer) trying to inline it into outer scope if possible.
* Usually inlining works, e.g. for lambdas inside stream API calls.
*
* @param psiBlock method/lambda/class initializer body
* @param visitor a visitor to use
* @return result status
*/
@NotNull
public final RunnerResult analyzeMethodWithInlining(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor, true);
if (initialStates == null) {
return RunnerResult.NOT_APPLICABLE;
}
if (initialStates.isEmpty()) {
return RunnerResult.OK;
}
return analyzeMethod(psiBlock, visitor, false, initialStates);
}
public final RunnerResult analyzeCodeBlock(@NotNull PsiCodeBlock block,
@NotNull InstructionVisitor visitor,
Consumer<DfaMemoryState> initialStateAdjuster) {
@@ -243,6 +277,28 @@ public class DataFlowRunner {
}
}
public RunnerResult analyzeMethodRecursively(PsiElement block, StandardInstructionVisitor visitor) {
Collection<DfaMemoryState> states = createInitialStates(block, visitor, false);
if (states == null) return RunnerResult.NOT_APPLICABLE;
return analyzeBlockRecursively(block, states, visitor);
}
private RunnerResult analyzeBlockRecursively(PsiElement block,
Collection<? extends DfaMemoryState> states,
StandardInstructionVisitor visitor) {
RunnerResult result = analyzeMethod(block, visitor, false, states);
if (result != RunnerResult.OK) return result;
Ref<RunnerResult> ref = Ref.create(RunnerResult.OK);
forNestedClosures((closure, nestedStates) -> {
RunnerResult res = analyzeBlockRecursively(closure, nestedStates, visitor);
if (res != RunnerResult.OK) {
ref.set(res);
}
});
return ref.get();
}
@Nullable
private static DfaValue makeInitialValue(DfaVariableValue var, PsiElement block) {
if(var.getQualifier() != null) return null;
@@ -372,9 +428,25 @@ public class DataFlowRunner {
return myInstructions[index];
}
@NotNull
MultiMap<PsiElement, DfaMemoryState> getNestedClosures() {
return new MultiMap<>(myNestedClosures);
public void forNestedClosures(BiConsumer<PsiElement, Collection<? extends DfaMemoryState>> consumer) {
// Copy to avoid concurrent modifications
MultiMap<PsiElement, DfaMemoryState> closures = new MultiMap<>(myNestedClosures);
for (PsiElement closure : closures.keySet()) {
List<DfaVariableValue> unusedVars = StreamEx.of(getFactory().getValues())
.select(DfaVariableValue.class)
.filter(var -> var.getQualifier() == null)
.filter(var -> var.getPsiVariable() instanceof PsiVariable &&
!VariableAccessUtils.variableIsUsed((PsiVariable)var.getPsiVariable(), closure))
.toList();
Collection<? extends DfaMemoryState> states = closures.get(closure);
if (!unusedVars.isEmpty()) {
List<DfaMemoryStateImpl> stateList = StreamEx.of(states)
.peek(state -> unusedVars.forEach(state::flushVariable))
.map(state -> (DfaMemoryStateImpl)state).distinct().toList();
states = StateQueue.mergeGroup(stateList);
}
consumer.accept(closure, states);
}
}
@NotNull
@@ -24,10 +24,7 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UnorderedPair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.PsiPrimitiveType;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.*;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
@@ -39,6 +36,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BiConsumer;
public class DfaMemoryStateImpl implements DfaMemoryState {
@@ -106,7 +104,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
public DfaMemoryStateImpl createClosureState() {
DfaMemoryStateImpl copy = createCopy();
copy.flushFields();
Set<DfaVariableValue> vars = new HashSet<>(copy.getVariableStates().keySet());
Set<DfaVariableValue> vars = new HashSet<>(copy.myVariableStates.keySet());
for (DfaVariableValue value : vars) {
copy.flushDependencies(value);
}
@@ -275,10 +273,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
}
if (getVariableState(var).isNotNull()) {
DfaConstValue dfaNull = myFactory.getConstFactory().getNull();
applyRelation(var, dfaNull, true);
}
updateEqClassesByState(var);
}
private DfaValue handleFlush(DfaVariableValue flushed, DfaValue value) {
@@ -733,6 +728,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return false;
}
setVariableState((DfaVariableValue)value, newState);
updateEquivalentVariables((DfaVariableValue)value, newState);
return updateEqClassesByState((DfaVariableValue)value);
}
return true;
@@ -757,6 +753,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
DfaVariableState newState = state.intersectFact(factType, factValue);
if (newState == null) return false;
setVariableState(var, newState);
updateEquivalentVariables(var, newState);
return updateEqClassesByState(var);
}
}
@@ -897,19 +894,26 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
private void updateVarStateOnComparison(@NotNull DfaVariableValue dfaVar, DfaValue value) {
if (!isUnknownState(dfaVar)) {
if (!isUnknownState(dfaVar) && !(dfaVar.getVariableType() instanceof PsiPrimitiveType)) {
if (value instanceof DfaConstValue) {
Object constValue = ((DfaConstValue)value).getValue();
if (constValue == null) {
setVariableState(dfaVar, getVariableState(dfaVar).withFact(DfaFactType.CAN_BE_NULL, true));
return;
}
PsiType psiType;
if (constValue instanceof PsiVariable) {
DfaPsiType dfaType = myFactory.createDfaType(((PsiVariable)constValue).getType());
DfaVariableState state = getVariableState(dfaVar).withInstanceofValue(dfaType);
if (state != null) {
setVariableState(dfaVar, state);
}
psiType = ((PsiVariable)constValue).getType();
}
else {
PsiModifierListOwner context = dfaVar.getPsiVariable();
psiType = JavaPsiFacade.getElementFactory(context.getProject())
.createTypeByFQClassName(constValue.getClass().getName(), context.getResolveScope());
}
DfaPsiType dfaType = myFactory.createDfaType(psiType);
DfaVariableState state = getVariableState(dfaVar).withInstanceofValue(dfaType);
if (state != null) {
setVariableState(dfaVar, state);
}
}
if (isNotNull(value) && !isNotNull(dfaVar)) {
@@ -926,12 +930,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
final boolean containsCalls = dfaLeft instanceof DfaVariableValue && ((DfaVariableValue)dfaLeft).containsCalls();
// track "x" property state only inside "if (getX() != null) ..."
if (containsCalls && !isNotNull(dfaLeft) && isNull(dfaRight) && !isNegated) {
return true;
}
if (dfaLeft == dfaRight) {
return containsCalls || !isNegated;
}
@@ -1162,6 +1166,17 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
myCachedHash = null;
}
protected void updateEquivalentVariables(DfaVariableValue dfaVar, DfaVariableState state) {
int index = getEqClassIndex(dfaVar);
if (index != -1) {
for (DfaValue value : myEqClasses.get(index).getMemberValues()) {
if (value != dfaVar && value instanceof DfaVariableValue) {
setVariableState((DfaVariableValue)value, state);
}
}
}
}
@NotNull
private StreamEx<DfaVariableValue> equivalentVariables(DfaVariableValue var) {
DfaVariableValue qualifier = var.getQualifier();
@@ -1206,9 +1221,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return state;
}
@NotNull
Map<DfaVariableValue, DfaVariableState> getVariableStates() {
return myVariableStates;
void forVariableStates(BiConsumer<DfaVariableValue, DfaVariableState> consumer) {
myVariableStates.forEach(consumer);
}
@NotNull
@@ -1282,12 +1296,26 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
void doFlush(@NotNull DfaVariableValue varPlain, boolean markUnknown) {
DfaVariableValue varNegated = varPlain.getNegatedValue();
removeEquivalenceRelations(varPlain);
myVariableStates.remove(varPlain);
if (varNegated != null) {
myVariableStates.remove(varNegated);
}
if (markUnknown) {
myUnknownVariables.add(varPlain);
}
myCachedHash = null;
}
void removeEquivalenceRelations(@NotNull DfaVariableValue varPlain) {
DfaVariableValue varNegated = varPlain.getNegatedValue();
final int idPlain = varPlain.getID();
final int idNegated = varNegated == null ? -1 : varNegated.getID();
int[] classes = myIdToEqClassesIndices.get(idPlain);
int[] negatedClasses = myIdToEqClassesIndices.get(idNegated);
int[] result = ArrayUtil.mergeArrays(ObjectUtils.notNull(classes, ArrayUtil.EMPTY_INT_ARRAY), ObjectUtils.notNull(negatedClasses, ArrayUtil.EMPTY_INT_ARRAY));
int[] result = ArrayUtil
.mergeArrays(ObjectUtils.notNull(classes, ArrayUtil.EMPTY_INT_ARRAY), ObjectUtils.notNull(negatedClasses, ArrayUtil.EMPTY_INT_ARRAY));
int interruptCount = 0;
@@ -1332,13 +1360,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
removeAllFromMap(idPlain);
removeAllFromMap(idNegated);
checkInvariants();
myVariableStates.remove(varPlain);
if (varNegated != null) {
myVariableStates.remove(varNegated);
}
if (markUnknown) {
myUnknownVariables.add(varPlain);
}
myCachedNonTrivialEqClasses = null;
myCachedDistinctClassPairs = null;
myCachedHash = null;
@@ -324,10 +324,8 @@ public class DfaUtil {
PsiExpression place = instruction.getPlace();
if (place != null) {
PlaceResult result = myResults.computeIfAbsent(place, __ -> new PlaceResult());
final Map<DfaVariableValue,DfaVariableState> map = ((ValuableDataFlowRunner.MyDfaMemoryState)memState).getVariableStates();
for (Map.Entry<DfaVariableValue, DfaVariableState> entry : map.entrySet()) {
ValuableDataFlowRunner.ValuableDfaVariableState state = (ValuableDataFlowRunner.ValuableDfaVariableState)entry.getValue();
DfaVariableValue variableValue = entry.getKey();
((ValuableDataFlowRunner.MyDfaMemoryState)memState).forVariableStates((variableValue, value) -> {
ValuableDataFlowRunner.ValuableDfaVariableState state = (ValuableDataFlowRunner.ValuableDfaVariableState)value;
final FList<PsiExpression> concatenation = state.myConcatenation;
if (!concatenation.isEmpty() && variableValue.getQualifier() == null) {
PsiModifierListOwner element = variableValue.getPsiVariable();
@@ -335,7 +333,7 @@ public class DfaUtil {
result.myValues.put((PsiVariable)element, concatenation);
}
}
}
});
DfaValue value = instruction.getValue();
if (value instanceof DfaVariableValue && ((DfaVariableValue)value).getQualifier() == null) {
PsiModifierListOwner element = ((DfaVariableValue)value).getPsiVariable();
@@ -265,8 +265,7 @@ class StateMerger {
Map<DfaVariableValue, Map<LongRangeSet, LongRangeSet>> ranges = new LinkedHashMap<>();
for (DfaMemoryStateImpl state : states) {
ProgressManager.checkCanceled();
Map<DfaVariableValue, DfaVariableState> variableStates = state.getVariableStates();
variableStates.forEach((varValue, varState) -> {
state.forVariableStates((varValue, varState) -> {
LongRangeSet range = varState.getFact(RANGE);
if (range != null) {
ranges.computeIfAbsent(varValue, k -> new HashMap<>()).put(range, range);
@@ -378,12 +377,12 @@ class StateMerger {
@NotNull
private Set<Fact> getFacts(@NotNull DfaMemoryStateImpl state) {
Set<Fact> result = myFacts.get(state);
if (result != null) {
return result;
}
result = ContainerUtil.newLinkedHashSet();
return myFacts.computeIfAbsent(state, StateMerger::doGetFacts);
}
@NotNull
private static Set<Fact> doGetFacts(DfaMemoryStateImpl state) {
Set<Fact> result = ContainerUtil.newLinkedHashSet();
IdentityHashMap<EqClass, EqClassInfo> classInfo = new IdentityHashMap<>();
@@ -426,10 +425,7 @@ class StateMerger {
}
}
Map<DfaVariableValue, DfaVariableState> states = state.getVariableStates();
for (Map.Entry<DfaVariableValue, DfaVariableState> entry : states.entrySet()) {
DfaVariableValue var = entry.getKey();
DfaVariableState variableState = entry.getValue();
state.forVariableStates((var, variableState) -> {
TypeConstraint typeConstraint = variableState.getTypeConstraint();
for (DfaPsiType type : typeConstraint.getInstanceofValues()) {
result.add(new InstanceofFact(var, true, type));
@@ -437,9 +433,7 @@ class StateMerger {
for (DfaPsiType type : typeConstraint.getNotInstanceofValues()) {
result.add(new InstanceofFact(var, false, type));
}
}
myFacts.put(state, result);
});
return result;
}
@@ -519,9 +513,7 @@ class StateMerger {
@Override
void removeFromState(@NotNull DfaMemoryStateImpl state) {
DfaVariableState varState = state.getVariableState(myVar);
state.flushVariable(myVar);
state.setVariableState(myVar, varState);
state.removeEquivalenceRelations(myVar);
}
}
@@ -162,7 +162,7 @@ public final class TypeConstraint {
}
@Nullable
TypeConstraint union(@NotNull TypeConstraint other) {
public TypeConstraint union(@NotNull TypeConstraint other) {
if(isSuperStateOf(other)) return this;
if(other.isSuperStateOf(this)) return other;
Set<DfaPsiType> leftTypes = new HashSet<>(this.myInstanceofValues);
@@ -18,28 +18,34 @@ package com.intellij.codeInspection.dataFlow.value;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class DfaInstanceofValue extends DfaValue {
private final PsiExpression myExpression;
private final PsiType myCastType;
private final @NotNull PsiExpression myExpression;
private final @NotNull PsiType myCastType;
private final boolean myNegated;
private final @NotNull DfaValue myRelation;
public DfaInstanceofValue(DfaValueFactory factory, PsiExpression expression, PsiType castType) {
this(factory, expression, castType, false);
}
public DfaInstanceofValue(DfaValueFactory factory, PsiExpression expression, PsiType castType, boolean negated) {
public DfaInstanceofValue(DfaValueFactory factory,
@NotNull PsiExpression expression,
@NotNull PsiType castType,
@NotNull DfaValue relation,
boolean negated) {
super(factory);
myExpression = expression;
myCastType = castType;
myRelation = relation;
myNegated = negated;
}
@Nullable
@NotNull
public DfaValue getRelation() {
return myRelation;
}
@NotNull
public PsiExpression getExpression() {
return myExpression;
}
@@ -55,6 +61,6 @@ public class DfaInstanceofValue extends DfaValue {
@Override
public DfaValue createNegated() {
return new DfaInstanceofValue(myFactory, myExpression, myCastType, !myNegated);
return new DfaInstanceofValue(myFactory, myExpression, myCastType, myRelation.createNegated(), !myNegated);
}
}
@@ -49,7 +49,7 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
if (value != null) {
if (!globalContext.shouldCheck(refParameter, this)) continue;
if (problems == null) problems = new ArrayList<>(1);
problems.add(registerProblem(manager, refParameter.getElement(), value));
problems.add(registerProblem(manager, refParameter.getElement(), value, refParameter.isUsedForWriting()));
}
}
}
@@ -228,7 +228,7 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
for (int i = 0, length = paramValues.length; i < length; i++) {
String value = paramValues[i];
if (value != null && value != NOT_CONST) {
holder.registerProblem(registerProblem(holder.getManager(), parameters[i], value));
holder.registerProblem(registerProblem(holder.getManager(), parameters[i], value, false));
}
}
}
@@ -243,13 +243,14 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
private ProblemDescriptor registerProblem(@NotNull InspectionManager manager,
PsiParameter parameter,
String value) {
String value,
boolean usedForWriting) {
final String name = parameter.getName();
return manager.createProblemDescriptor(ObjectUtils.notNull(parameter.getNameIdentifier(), parameter),
InspectionsBundle.message("inspection.same.parameter.problem.descriptor",
"<code>" + name + "</code>",
"<code>" + StringUtil.unquoteString(value) + "</code>"),
createFix(name, value),
usedForWriting ? null : createFix(name, value),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
}
}
@@ -343,9 +343,6 @@ public class DuplicatesFinder {
}
}
Boolean matchedExtractablePart = matchExtractableExpression(pattern, candidate, candidates, match, false);
if (matchedExtractablePart != null) return matchedExtractablePart;
if (!canBeEquivalent(pattern, candidate)) return false; // Q : is it correct to check implementation classes?
if (pattern instanceof PsiExpressionList && candidate instanceof PsiExpressionList) { //check varargs
@@ -562,9 +559,9 @@ public class DuplicatesFinder {
for (int i = 0; i < children1.length; i++) {
PsiElement child1 = children1[i];
PsiElement child2 = children2[i];
if (!matchPattern(child1, child2, candidates, match)) {
matchedExtractablePart = matchExtractableExpression(child1, child2, candidates, match, true);
if (matchedExtractablePart == null || !matchedExtractablePart) return false;
if (!matchPattern(child1, child2, candidates, match) &&
!matchExtractableExpression(child1, child2, candidates, match)) {
return false;
}
}
@@ -578,49 +575,35 @@ public class DuplicatesFinder {
return true;
}
@Nullable
private Boolean matchExtractableExpression(PsiElement pattern, PsiElement candidate,
List<PsiElement> candidates, Match match,
boolean withFolding) {
if (!(pattern instanceof PsiExpression) || !(candidate instanceof PsiExpression) || withFolding && !myWithExtractedParameters) {
return null;
}
if (myPattern.length == 1 && myPattern[0] == pattern || candidates.size() == 1 && candidates.get(0) == candidate) {
return null;
private boolean matchExtractableExpression(PsiElement pattern, PsiElement candidate,
List<PsiElement> candidates, Match match) {
if (!myWithExtractedParameters || !(pattern instanceof PsiExpression) || !(candidate instanceof PsiExpression)) {
return false;
}
ComplexityHolder patternComplexity = null;
if (withFolding) {
if (myPatternComplexityHolder == null) {
myPatternComplexityHolder = new ComplexityHolder(myPatternAsList);
}
patternComplexity = myPatternComplexityHolder;
if (myPatternComplexityHolder == null) {
myPatternComplexityHolder = new ComplexityHolder(myPatternAsList);
}
ExtractableExpressionPart patternPart = ExtractableExpressionPart.match((PsiExpression)pattern, myPatternAsList, patternComplexity);
ExtractableExpressionPart patternPart = ExtractableExpressionPart.match((PsiExpression)pattern, myPatternAsList, myPatternComplexityHolder);
if (patternPart == null) {
return null;
return false;
}
ComplexityHolder candidatesComplexity = null;
if (withFolding) {
if (myCandidateComplexityHolder == null || myCandidateComplexityHolder.getScope() != candidates) {
myCandidateComplexityHolder = new ComplexityHolder(candidates);
}
candidatesComplexity = myCandidateComplexityHolder;
if (myCandidateComplexityHolder == null || myCandidateComplexityHolder.getScope() != candidates) {
myCandidateComplexityHolder = new ComplexityHolder(candidates);
}
ExtractableExpressionPart candidatePart = ExtractableExpressionPart.match((PsiExpression)candidate, candidates, candidatesComplexity);
ExtractableExpressionPart candidatePart = ExtractableExpressionPart.match((PsiExpression)candidate, candidates, myCandidateComplexityHolder);
if (candidatePart == null) {
return null;
return false;
}
if (patternPart.myValue != null && patternPart.myValue.equals(candidatePart.myValue)) {
return true;
}
if (patternPart.myVariable == null || candidatePart.myVariable == null) {
return myWithExtractedParameters &&
match.putExtractedParameter(patternPart, candidatePart);
return match.putExtractedParameter(patternPart, candidatePart);
}
return null;
return false;
}
private boolean matchExtractableVariable(PsiElement pattern, PsiElement candidate, Match match) {
@@ -17,6 +17,7 @@ package com.intellij.refactoring.util.duplicates;
import com.intellij.codeInsight.JavaPsiEquivalenceUtil;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
@@ -94,6 +95,11 @@ public class ExtractableExpressionPart {
return matchConstant(expression);
}
}
PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent());
if (parent instanceof PsiExpressionStatement ||
parent instanceof PsiExpressionList && parent.getParent() instanceof PsiExpressionListStatement) {
return null;
}
if (complexityHolder != null && (isConstant || complexityHolder.isAcceptableExpression(expression))) {
return matchExpression(expression);
}
@@ -116,6 +122,9 @@ public class ExtractableExpressionPart {
@Nullable
static ExtractableExpressionPart matchVariable(@NotNull PsiReferenceExpression expression, @Nullable List<PsiElement> scope) {
PsiElement resolved = expression.resolve();
if (resolved instanceof PsiField && isUnqualifiedModification(expression)) {
return null;
}
if (resolved instanceof PsiVariable && (scope == null || !DuplicatesFinder.isUnder(resolved, scope))) {
PsiVariable variable = (PsiVariable)resolved;
return new ExtractableExpressionPart(expression, variable, null, variable.getType());
@@ -123,6 +132,28 @@ public class ExtractableExpressionPart {
return null;
}
private static boolean isUnqualifiedModification(@NotNull PsiReferenceExpression expression) {
PsiExpression qualifier = expression.getQualifierExpression();
if (qualifier == null || qualifier instanceof PsiQualifiedExpression) { // 'this.' and 'super.' with fields are just like unqualified
PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent());
if (parent instanceof PsiAssignmentExpression) {
PsiAssignmentExpression assignment = (PsiAssignmentExpression)parent;
if (PsiTreeUtil.isAncestor(assignment.getLExpression(), expression, false)) {
return true;
}
}
else if (parent instanceof PsiUnaryExpression) {
PsiUnaryExpression unary = (PsiUnaryExpression)parent;
IElementType tokenType = unary.getOperationTokenType();
if ((tokenType.equals(JavaTokenType.PLUSPLUS) || tokenType.equals(JavaTokenType.MINUSMINUS)) &&
PsiTreeUtil.isAncestor(unary.getOperand(), expression, false)) {
return true;
}
}
}
return false;
}
@Nullable
private static ExtractableExpressionPart matchExpression(@NotNull PsiExpression expression) {
PsiType type = expression.getType();
@@ -50,12 +50,6 @@ public class ExtractedParameter {
if (type == null) {
return false;
}
if (patternPart.myVariable != null && !isStaticOrLocal(patternPart.myVariable)) {
return false;
}
if (candidatePart.myVariable != null && !isStaticOrLocal(candidatePart.myVariable)) {
return false;
}
for (ExtractedParameter parameter : parameters) {
boolean samePattern = parameter.samePattern(patternPart);
boolean sameCandidate = parameter.sameCandidate(candidatePart);
@@ -141,13 +135,6 @@ public class ExtractedParameter {
return false;
}
static boolean isStaticOrLocal(@NotNull PsiVariable variable) {
if (variable instanceof PsiField && variable.hasModifierProperty(PsiModifier.STATIC)) {
return true;
}
return variable instanceof PsiLocalVariable || variable instanceof PsiParameter;
}
private static class FieldModificationVisitor extends JavaRecursiveElementWalkingVisitor {
private final Set<PsiField> myFields;
private boolean myModified;
+2 -2
View File
@@ -213,8 +213,8 @@
<usageContextPanelProvider implementation="com.intellij.usageView.UsageContextDataflowFromPanel$Provider"/>
<usageContextPanelProvider implementation="com.intellij.usageView.UsageContextDataflowToPanel$Provider"/>
<usageTypeProvider implementation="com.intellij.usages.impl.rules.JavaUsageTypeProvider"/>
<fileStructureGroupRuleProvider implementation="com.intellij.usages.impl.rules.JavaMethodGroupRuleProvider"/>
<fileStructureGroupRuleProvider implementation="com.intellij.usages.impl.rules.JavaClassGroupRuleProvider"/>
<fileStructureGroupRuleProvider implementation="com.intellij.usages.impl.rules.JavaMethodGroupRuleProvider"/>
<fileStructureGroupRuleProvider implementation="com.intellij.usages.impl.rules.NonJavaFileGroupRuleProvider"/>
<qualifiedNameProvider implementation="com.intellij.ide.actions.JavaQualifiedNameProvider"/>
<referenceImporter implementation="com.intellij.codeInsight.daemon.impl.JavaReferenceImporter"/>
@@ -236,8 +236,8 @@
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenameJavaClassProcessor"/>
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenameJavaMethodProcessor" id="javamethod"/>
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenameJavaVariableProcessor" id="javaVariable"/>
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenameAliasingPomTargetProcessor"/>
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenameJavaModuleProcessor"/>
<renamePsiElementProcessor implementation="com.intellij.refactoring.rename.RenameAliasingPomTargetProcessor"/>
<referenceProviderType key="Class Reference Provider"
implementationClass="com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider"/>
<findUsagesHandlerFactory implementation="com.intellij.find.findUsages.JavaFindUsagesHandlerFactory" id="java"
@@ -404,7 +404,7 @@ public class JavaCompletionUtil {
}
}
return containsMember(castType, o) && !containsMember(plainQualifier, o);
return containsMember(castType, o, true) && !containsMember(plainQualifier, o, true);
}
return false;
}
@@ -469,7 +469,7 @@ public class JavaCompletionUtil {
}
}), -1);
}
if (containsMember(qualifierType, object) && !qualifierType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
if (containsMember(qualifierType, object, false) && !qualifierType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
LookupElementDecorator<LookupElement> bold = LookupElementDecorator.withRenderer(item, new LookupElementRenderer<LookupElementDecorator<LookupElement>>() {
@Override
public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) {
@@ -495,9 +495,11 @@ public class JavaCompletionUtil {
return false;
}
@Contract("null, _ -> false")
public static boolean containsMember(@Nullable PsiType qualifierType, @NotNull Object object) {
if (qualifierType instanceof PsiArrayType && object instanceof PsiMember) { //length and clone()
@Contract("null, _, _ -> false")
private static boolean containsMember(@Nullable PsiType qualifierType, @NotNull Object object, boolean checkBases) {
if (!(object instanceof PsiMember)) return false;
if (qualifierType instanceof PsiArrayType) { //length and clone()
PsiFile file = ((PsiMember)object).getContainingFile();
if (file == null || file.getVirtualFile() == null) { //yes, they're a bit dummy
return true;
@@ -506,12 +508,11 @@ public class JavaCompletionUtil {
else if (qualifierType instanceof PsiClassType) {
PsiClass qualifierClass = ((PsiClassType)qualifierType).resolve();
if (qualifierClass == null) return false;
if (object instanceof PsiMethod && qualifierClass.findMethodBySignature((PsiMethod)object, false) != null) {
if (object instanceof PsiMethod && qualifierClass.findMethodBySignature((PsiMethod)object, checkBases) != null) {
return true;
}
if (object instanceof PsiMember) {
return qualifierClass.equals(((PsiMember)object).getContainingClass());
}
PsiClass memberClass = ((PsiMember)object).getContainingClass();
return checkBases ? InheritanceUtil.isInheritorOrSelf(qualifierClass, memberClass, true) : qualifierClass.equals(memberClass);
}
return false;
}
@@ -49,7 +49,9 @@ public class CreateCastExpressionFromInstanceofAction extends CreateLocalVarFrom
assert instanceOfExpression.getContainingFile() == file : instanceOfExpression.getContainingFile() + "; file="+file;
PsiElement decl = createAndInsertCast(instanceOfExpression, editor, file);
if (decl == null) return;
decl = CodeStyleManager.getInstance(project).reformat(CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(decl));
decl = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(decl);
if (decl == null) return;
decl = CodeStyleManager.getInstance(project).reformat(decl);
editor.getCaretModel().moveToOffset(decl.getTextRange().getEndOffset());
}
@@ -28,6 +28,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
@@ -135,6 +136,14 @@ public class SameParameterValueInspection extends SameParameterValueInspectionBa
public static void inlineSameParameterValue(final PsiMethod method, final PsiParameter parameter, final PsiExpression defToInline) {
final MultiMap<PsiElement, String> conflicts = new MultiMap<>();
JavaSafeDeleteProcessor.collectMethodConflicts(conflicts, method, parameter);
final Collection<PsiReference> refsToInline = ReferencesSearch.search(parameter).findAll();
for (PsiReference reference : refsToInline) {
PsiElement referenceElement = reference.getElement();
if (referenceElement instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression)referenceElement)) {
conflicts.putValue(referenceElement, "Parameter has write usages. Inline is not supported");
break;
}
}
if (!conflicts.isEmpty()) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
if (!BaseRefactoringProcessor.ConflictsInTestsException.isTestIgnore()) {
@@ -146,8 +155,6 @@ public class SameParameterValueInspection extends SameParameterValueInspectionBa
}
}
final Collection<PsiReference> refsToInline = ReferencesSearch.search(parameter).findAll();
ApplicationManager.getApplication().runWriteAction(() -> {
try {
PsiExpression[] exprs = new PsiExpression[refsToInline.size()];
@@ -33,6 +33,7 @@ import com.intellij.util.IJSwingUtilities;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.NotNullFunction;
import com.intellij.util.containers.HashSet;
import com.siyeh.ig.psiutils.CommentTracker;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -132,7 +133,14 @@ public abstract class BaseConvertToLocalQuickFix<V extends PsiVariable> implemen
variable,
references,
delete,
declaration -> anchorBlock.addBefore(declaration, anchor)
declaration -> {
PsiElement parent = anchorBlock.getParent();
if (parent instanceof PsiSwitchStatement) {
PsiElement switchContainer = parent.getParent();
return switchContainer.addBefore(declaration, parent);
}
return anchorBlock.addBefore(declaration, anchor);
}
);
}
@@ -147,14 +155,20 @@ public abstract class BaseConvertToLocalQuickFix<V extends PsiVariable> implemen
return WriteAction.compute(() -> {
final PsiElement newDeclaration = moveDeclaration(elementFactory, localName, variable, initializer, action, references);
if (delete) {
beforeDelete(project, variable, newDeclaration);
variable.normalizeDeclaration();
variable.delete();
deleteSourceVariable(project, variable, newDeclaration);
}
return newDeclaration;
});
}
protected void deleteSourceVariable(@NotNull Project project, @NotNull V variable, PsiElement newDeclaration) {
CommentTracker tracker = new CommentTracker();
beforeDelete(project, variable, newDeclaration);
variable.normalizeDeclaration();
tracker.delete(variable);
tracker.insertCommentsBefore(newDeclaration);
}
protected PsiElement moveDeclaration(PsiElementFactory elementFactory,
String localName,
V variable,
@@ -70,12 +70,7 @@ public class FieldCanBeLocalInspection extends FieldCanBeLocalInspectionBase {
}
if (element != null) {
final PsiElement finalElement = element;
Runnable runnable = () -> {
beforeDelete(project, variable, finalElement);
variable.normalizeDeclaration();
variable.delete();
};
ApplicationManager.getApplication().runWriteAction(runnable);
ApplicationManager.getApplication().runWriteAction(() -> deleteSourceVariable(project, variable, finalElement));
}
return element;
}
@@ -19,12 +19,13 @@ import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.Factory;
import com.intellij.psi.impl.source.tree.LeafElement;
@@ -39,14 +40,14 @@ import com.intellij.util.CharTable;
public class ShiftIndentInsideHelper {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.codeStyle.Helper");
private final CodeStyleSettings mySettings;
private final CommonCodeStyleSettings mySettings;
private final FileType myFileType;
private final IndentHelper myIndentIndentHelper;
private final Project myProject;
public ShiftIndentInsideHelper(FileType fileType, Project project) {
myProject = project;
mySettings = CodeStyleSettingsManager.getSettings(project);
mySettings = CodeStyleSettingsManager.getSettings(project).getCommonSettings(JavaLanguage.INSTANCE);
myFileType = fileType;
myIndentIndentHelper = IndentHelper.getInstance();
}
@@ -204,11 +204,14 @@ public class JavaPushDownDelegate extends PushDownDelegate<MemberInfo, PsiMember
refsToRebind.add(reference);
}
}
if (member instanceof PsiField) {
((PsiField)member).normalizeDeclaration();
}
member = (PsiMember)member.copy();
RefactoringUtil.replaceMovedMemberTypeParameters(member, PsiUtil.typeParametersIterable(sourceClass), substitutor, factory);
PsiMember newMember = null;
if (member instanceof PsiField) {
((PsiField)member).normalizeDeclaration();
if (sourceClass.isInterface() && !targetClass.isInterface()) {
PsiUtil.setModifierProperty(member, PsiModifier.PUBLIC, true);
PsiUtil.setModifierProperty(member, PsiModifier.STATIC, true);
@@ -367,7 +367,7 @@ public class RefactoringUtil {
}
ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, false);
if (expectedTypes.length == 1 || (isFunctionalType || !isDenotable)&& expectedTypes.length > 0 ) {
if (typeByExpression != null && Arrays.stream(expectedTypes).anyMatch(typeInfo -> typeInfo.getType().equals(typeByExpression))) {
if (typeByExpression != null && Arrays.stream(expectedTypes).anyMatch(typeInfo -> typeByExpression.isAssignableFrom(typeInfo.getType()))) {
return type;
}
type = expectedTypes[0].getType();
@@ -889,16 +889,13 @@ public class RefactoringUtil {
final PsiElement invalidBody = lambdaExpression.getBody();
if (invalidBody == null) return declaration;
final PsiLambdaExpression expressionFromText = (PsiLambdaExpression)elementFactory
.createExpressionFromText(lambdaExpression.getParameterList().getText() + " -> {}", lambdaExpression.getParent());
String lambdaParamListWithArrowAndComments = lambdaExpression.getText()
.substring(0, (declaration.isPhysical() ? declaration : invalidBody).getStartOffsetInParent());
final PsiLambdaExpression expressionFromText = (PsiLambdaExpression)elementFactory.createExpressionFromText(lambdaParamListWithArrowAndComments + "{}", lambdaExpression.getParent());
PsiCodeBlock newBody = (PsiCodeBlock)expressionFromText.getBody();
LOG.assertTrue(newBody != null);
newBody.add(declaration);
lambdaExpression =
(PsiLambdaExpression)lambdaExpression.replace(elementFactory.createExpressionFromText(
lambdaExpression.getParameterList().getText() + " -> " + invalidBody.getText(), lambdaExpression));
final PsiElement lambdaExpressionBody = lambdaExpression.getBody();
LOG.assertTrue(lambdaExpressionBody != null);
final PsiStatement lastBodyStatement;
@@ -0,0 +1,32 @@
// 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.lang.jvm;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents a package.
*
* @see Package
*/
public interface JvmPackage extends JvmAnnotatedElement, JvmNamedElement {
/**
* @return the name, or {@code null} for the default package
*/
@Nullable("default package")
@Override
String getName();
/**
* @return the fully qualified name, or an empty string for the default package
*/
@NotNull
String getQualifiedName();
/**
* @return the parent package, or {@code null} for the default package
*/
@Nullable
JvmPackage getParentPackage();
}
@@ -1,20 +1,7 @@
/*
* 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;
import com.intellij.lang.jvm.JvmPackage;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
@@ -24,7 +11,9 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents a Java package.
*/
public interface PsiPackage extends PsiCheckedRenameElement, NavigationItem, PsiModifierListOwner, PsiDirectoryContainer, PsiQualifiedNamedElement {
public interface PsiPackage extends PsiCheckedRenameElement, NavigationItem, PsiModifierListOwner,
PsiDirectoryContainer, PsiQualifiedNamedElement, JvmPackage {
String PACKAGE_INFO_CLASS = "package-info";
String PACKAGE_INFO_FILE = PACKAGE_INFO_CLASS + ".java";
String PACKAGE_INFO_CLS_FILE = PACKAGE_INFO_CLASS + ".class";
@@ -45,6 +34,7 @@ public interface PsiPackage extends PsiCheckedRenameElement, NavigationItem, Psi
*
* @return the parent package, or null for the default package.
*/
@Override
@Nullable
PsiPackage getParentPackage();
@@ -29,6 +29,7 @@ public class PsiMethodUtil {
public static final Condition<PsiClass> MAIN_CLASS = psiClass -> {
if (psiClass instanceof PsiAnonymousClass) return false;
if (psiClass.isAnnotationType()) return false;
if (psiClass.isInterface() && !PsiUtil.isLanguageLevel8OrHigher(psiClass)) return false;
return psiClass.getContainingClass() == null || psiClass.hasModifierProperty(PsiModifier.STATIC);
};
@@ -10,6 +10,8 @@ import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
@@ -159,6 +161,12 @@ public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> imp
}
}
@NotNull
@Override
public SearchScope getUseScope() {
return ProjectScope.getProjectScope(getProject());
}
@Override
public String toString() {
return "PsiJavaModule:" + getName();
@@ -66,7 +66,8 @@ public class PsiJavaModuleReference extends PsiReferenceBase.Poly<PsiJavaModuleR
@NotNull
@Override
public ResolveResult[] resolve(@NotNull PsiJavaModuleReference reference, boolean incompleteCode) {
PsiFile file = reference.getElement().getContainingFile();
PsiJavaModuleReferenceElement refElement = reference.getElement();
PsiFile file = refElement.getContainingFile();
String moduleName = reference.getCanonicalText();
if (file instanceof PsiJavaFile) {
@@ -76,7 +77,8 @@ public class PsiJavaModuleReference extends PsiReferenceBase.Poly<PsiJavaModuleR
}
}
Collection<PsiJavaModule> modules = findModules(file, moduleName, incompleteCode);
boolean global = incompleteCode || refElement.getParent() instanceof PsiPackageAccessibilityStatement;
Collection<PsiJavaModule> modules = findModules(file, moduleName, global);
if (!modules.isEmpty()) {
ResolveResult[] result = new ResolveResult[modules.size()];
int i = 0;
@@ -88,9 +90,9 @@ public class PsiJavaModuleReference extends PsiReferenceBase.Poly<PsiJavaModuleR
}
}
private static Collection<PsiJavaModule> findModules(PsiFile file, String moduleName, boolean incompleteCode) {
private static Collection<PsiJavaModule> findModules(PsiFile file, String moduleName, boolean global) {
Project project = file.getProject();
GlobalSearchScope scope = incompleteCode ? GlobalSearchScope.allScope(project) : file.getResolveScope();
GlobalSearchScope scope = global ? GlobalSearchScope.allScope(project) : file.getResolveScope();
return JavaFileManager.getInstance(project).findModules(moduleName, scope);
}
}
@@ -153,7 +153,7 @@ public class JavaResolveUtil {
PsiClass topAccessClass = getTopLevelClass(accessObjectClass, memberClass);
if (!manager.areElementsEquivalent(topMemberClass, topAccessClass)) return false;
if (accessObjectClass instanceof PsiAnonymousClass && accessObjectClass.isInheritor(memberClass, true)) {
if (place instanceof PsiMethodCallExpression) {
if (!(place instanceof PsiAnonymousClass)) {
return false;
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.impl.source.resolve;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -0,0 +1,7 @@
class Foo {
void test(String s) {
Object x;
x = s;
System.out.println(x.subst<caret>);
}
}
@@ -0,0 +1,7 @@
class Foo {
void test(String s) {
Object x;
x = s;
System.out.println(((String) x).substring());
}
}
@@ -0,0 +1,13 @@
interface E { }
interface Named {
String getName();
}
interface MyNamed extends Named {}
class X {
void foo(E e) {
if (e instanceof MyNamed && e.getn<caret>)
}
}
@@ -0,0 +1,13 @@
interface E { }
interface Named {
String getName();
}
interface MyNamed extends Named {}
class X {
void foo(E e) {
if (e instanceof MyNamed && ((MyNamed) e).getName()<caret>)
}
}
@@ -0,0 +1,6 @@
class Foo {
void test(String s) {
Object x = s;
System.out.println(x.subst<caret>);
}
}
@@ -0,0 +1,6 @@
class Foo {
void test(String s) {
Object x = s;
System.out.println(((String) x).substring());
}
}
@@ -0,0 +1,8 @@
class Foo {
void test(Object obj) {
if(!(obj instanceof String)) {
obj = "foo";
}
obj.subst<caret>
}
}
@@ -0,0 +1,8 @@
class Foo {
void test(Object obj) {
if(!(obj instanceof String)) {
obj = "foo";
}
((String) obj).substring()
}
}
@@ -0,0 +1,8 @@
import java.util.*;
class Foo {
void test(Optional<Object> opt) {
opt.filter(x -> x instanceof String)
.map(s -> s.subst<caret>)
}
}
@@ -0,0 +1,8 @@
import java.util.*;
class Foo {
void test(Optional<Object> opt) {
opt.filter(x -> x instanceof String)
.map(s -> ((String) s).substring())
}
}
@@ -0,0 +1,9 @@
import java.util.*;
class Foo {
void test(List<?> obj) {
obj.stream()
.filter(x -> x instanceof String)
.forEach(e -> e.subst<caret>);
}
}
@@ -0,0 +1,9 @@
import java.util.*;
class Foo {
void test(List<?> obj) {
obj.stream()
.filter(x -> x instanceof String)
.forEach(e -> ((String) e).substring());
}
}
@@ -3,12 +3,14 @@ enum EnumPrivateMethodTest {
@Override
public void execute() {
this.<error descr="'firstMethod()' has private access in 'EnumPrivateMethodTest'">firstMethod</error>();
String s = this.<error descr="'myDescription' has private access in 'EnumPrivateMethodTest'">myDescription</error>;
}
};
public abstract void execute();
private void firstMethod() {}
private final String myDescription = "description";
}
abstract class EnumPrivateMethodTest1 {
@@ -5,6 +5,7 @@ class ITest {
public IntelliJBugConvertToLocal(int x, int z) {
//my comment to keep in code
ArrayList<String> mayBeLocal = new ArrayList<String>();
if (x == 5) {
mayBeLocal.add("jjj");
@@ -0,0 +1,18 @@
// "Convert to local" "true"
class TestFieldConversion
{
public void someMethod(int s) {
int someInt = 0;
switch (s) {
case 1:
System.out.println(someInt);
break;
case 3:
System.out.println(someInt);
break;
default:
break;
}
}
}
@@ -3,7 +3,7 @@ import java.util.ArrayList;
class ITest {
private ArrayList<String> may<caret>BeLocal = new ArrayList<String>();
private ArrayList<String> may<caret>BeLocal = new ArrayList<String>(); //my comment to keep in code
public IntelliJBugConvertToLocal(int x, int z) {
@@ -0,0 +1,18 @@
// "Convert to local" "true"
class TestFieldConversion
{
private int som<caret>eInt = 0;
public void someMethod(int s) {
switch (s) {
case 1:
System.out.println(someInt);
break;
case 3:
System.out.println(someInt);
break;
default:
break;
}
}
}
@@ -0,0 +1,10 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
class NullableReturn {
@NotNull Object test(Object o, Object o2, Object o3) {
Object x = o == null ? o3 : o2;
// no nullable return from notnull method here
return x == null ? o3 : x;
}
}
@@ -46,10 +46,17 @@ public class StreamInlining {
void test2(int[] array) {
IntStream.of(array).filter(x -> x < 5)
.filter(x -> x > 7) // TODO: find variable state for non-qualified value
.filter(x -> <warning descr="Condition 'x > 7' is always 'false'">x > 7</warning>)
.forEach(value -> System.out.println(value));
}
void testInstanceof(List<?> objects) {
objects.stream()
.filter(x -> x instanceof String)
.filter(x -> <warning descr="Condition 'x instanceof Number' is always 'false'">x instanceof Number</warning>)
.forEach(System.out::println);
}
// IDEA-152871
static class A {
@@ -104,3 +104,14 @@ class Example3
private long total = 0;
}
}
class Example4 {
@GuardedBy("this")
protected Object field;
static class Example4Derived extends Example4 {
synchronized void foo() {
Object o = field;
}
}
}
@@ -0,0 +1,8 @@
// "f 1" "true"
public class Test {
void foo(boolean <caret>f){
f++;
}
void bar(){foo(1);}
void bar1(){foo(1);}
}
@@ -0,0 +1,24 @@
import java.util.List;
class C {
List<String> x;
List<String> y;
private void foo() {
<selection>
if (x.isEmpty()) return;
x.remove(0);
y.add(str());
baz();</selection>
}
private void bar() {
if (y.isEmpty()) return;
y.remove(0);
x.add(str());
baz();
}
private void baz() { }
private String str() { return null; }
}
@@ -0,0 +1,25 @@
import java.util.List;
class C {
List<String> x;
List<String> y;
private void foo() {
newMethod(x, y);
}
private void newMethod(List<String> x, List<String> y) {
if (x.isEmpty()) return;
x.remove(0);
y.add(str());
baz();
}
private void bar() {
newMethod(y, x);
}
private void baz() { }
private String str() { return null; }
}
@@ -0,0 +1,19 @@
import java.util.List;
class ArgumentFoldingWholeStatement {
List<String> x;
List<String> y;
private void foo() {
<selection>x.add(str());
baz();</selection>
}
private void bar() {
y.add(str());
baz();
}
private String str() { return null; }
private void baz() { }
}
@@ -0,0 +1,22 @@
import java.util.List;
class ArgumentFoldingWholeStatement {
List<String> x;
List<String> y;
private void foo() {
<selection>
for (int i = 0; ++i < 5; x.indexOf(str())) {
baz();
}</selection>
}
private void bar() {
for (int i = 0; ++i < 5; y.indexOf(str())) {
baz();
}
}
private String str() { return null; }
private void baz() { }
}
@@ -0,0 +1,22 @@
import java.util.List;
class ArgumentFoldingWholeStatement {
List<String> x;
List<String> y;
private void foo() {
<selection>
for (int i = 0; i < 5; i++, x.indexOf(str())) {
baz();
}</selection>
}
private void bar() {
for (int i = 0; i < 5; i++, y.indexOf(str())) {
baz();
}
}
private String str() { return null; }
private void baz() { }
}
@@ -0,0 +1,24 @@
import java.util.List;
class ArgumentFoldingWholeStatement {
List<String> x;
List<String> y;
private void foo() {
newMethod(x);
}
private void newMethod(List<String> x) {
for (int i = 0; i < 5; i++, x.indexOf(str())) {
baz();
}
}
private void bar() {
newMethod(y);
}
private String str() { return null; }
private void baz() { }
}
@@ -0,0 +1,24 @@
import java.util.List;
class ArgumentFoldingWholeStatement {
List<String> x;
List<String> y;
private void foo() {
newMethod(x);
}
private void newMethod(List<String> x) {
for (int i = 0; ++i < 5; x.indexOf(str())) {
baz();
}
}
private void bar() {
newMethod(y);
}
private String str() { return null; }
private void baz() { }
}
@@ -0,0 +1,22 @@
import java.util.List;
class ArgumentFoldingWholeStatement {
List<String> x;
List<String> y;
private void foo() {
newMethod(x);
}
private void newMethod(List<String> x) {
x.add(str());
baz();
}
private void bar() {
newMethod(y);
}
private String str() { return null; }
private void baz() { }
}
@@ -0,0 +1,19 @@
class DecrementDifferentFieldsDuplicate {
int x;
int y;
private void foo() {
<selection>
if (x > 0) {
bar(x);
x--;
}</selection>
if (y > 0) {
bar(y);
y--;
}
}
private void bar(int i) { }
}
@@ -0,0 +1,23 @@
class DecrementDifferentFieldsDuplicate {
int x;
int y;
private void foo() {
newMethod();
if (y > 0) {
bar(y);
y--;
}
}
private void newMethod() {
if (x > 0) {
bar(x);
x--;
}
}
private void bar(int i) { }
}
@@ -1,14 +1,15 @@
public class Test {
int method() {
try {
return newMethod("Text", 0);
System.out.println("Text");
return 0;
} finally {
return newMethod("!!!", 1);
return newMethod();
}
}
private int newMethod(String s, int i) {
System.out.println(s);
return i;
private int newMethod() {
System.out.println("!!!");
return 1;
}
}
@@ -3,18 +3,18 @@ class C {
void foo(int x) {
newMethod(x, 1, "A" + "B" + "C" + "D" + "E" + 1);
newMethod(x, 1);
newMethod(x, 2, "A" + "B" + "C" + "D" + "E" + 2);
newMethod(x, 2);
if (x <= A + B + C + D + E + 2)
bar("A" + "B" + "C" + "D" + "E" + 2);
}
private void newMethod(int x, int i, String s) {
private void newMethod(int x, int i) {
if (x >= A + B + C + D + E + i)
bar(s);
bar("A" + "B" + "C" + "D" + "E" + i);
}
void bar(String s) {}

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