diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index bc165fbcd305..6185c30ddacf 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -16,5 +16,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Trove4j.xml b/.idea/libraries/Trove4j.xml
index db72e5172478..42d326c8c761 100644
--- a/.idea/libraries/Trove4j.xml
+++ b/.idea/libraries/Trove4j.xml
@@ -1,15 +1,15 @@
-
+
+
-
+
-
-
+
\ No newline at end of file
diff --git a/.idea/libraries/swingx.xml b/.idea/libraries/swingx.xml
index 9da1c0f6130a..223866db78d1 100644
--- a/.idea/libraries/swingx.xml
+++ b/.idea/libraries/swingx.xml
@@ -1,11 +1,12 @@
-
+
+
-
+
-
+
\ No newline at end of file
diff --git a/build/conf/nsis/customInstallActions.nsi b/build/conf/nsis/customInstallActions.nsi
index 56277ba6e209..213a2c824d45 100644
--- a/build/conf/nsis/customInstallActions.nsi
+++ b/build/conf/nsis/customInstallActions.nsi
@@ -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
diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi
index 082c0ad63ed7..79826dd8082d 100644
--- a/build/conf/nsis/idea.nsi
+++ b/build/conf/nsis/idea.nsi
@@ -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"
diff --git a/build/conf/nsis/registry.nsi b/build/conf/nsis/registry.nsi
index 99a47ce2715d..baff6702852a 100644
--- a/build/conf/nsis/registry.nsi
+++ b/build/conf/nsis/registry.nsi
@@ -81,8 +81,6 @@ Function ${un}OMReadRegStr
hkcr:
ReadRegStr $3 HKCR $1 $2
done:
- IfErrors 0 +2
- DetailPrint "ERROR: $0, $1, $2"
FunctionEnd
; -----------------------------------------------------------------------------
diff --git a/build/dependencies/build.gradle b/build/dependencies/build.gradle
index a211c438e729..39bc92fc2624 100644
--- a/build/dependencies/build.gradle
+++ b/build/dependencies/build.gradle
@@ -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'
}
\ No newline at end of file
diff --git a/build/dependencies/gradle/wrapper/gradle-wrapper.jar b/build/dependencies/gradle/wrapper/gradle-wrapper.jar
index 0bcc53af302f..6b6ea3ab4ff4 100644
Binary files a/build/dependencies/gradle/wrapper/gradle-wrapper.jar and b/build/dependencies/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/build/dependencies/gradle/wrapper/gradle-wrapper.properties b/build/dependencies/gradle/wrapper/gradle-wrapper.properties
index 8129803d391d..0e680f3759f5 100644
--- a/build/dependencies/gradle/wrapper/gradle-wrapper.properties
+++ b/build/dependencies/gradle/wrapper/gradle-wrapper.properties
@@ -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
diff --git a/build/dependencies/gradlew b/build/dependencies/gradlew
index 4453ccea33d9..cccdd3d517fc 100755
--- a/build/dependencies/gradlew
+++ b/build/dependencies/gradlew
@@ -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 " "
}
diff --git a/build/dependencies/setupBuildScriptsDeps.gradle b/build/dependencies/setupBuildScriptsDeps.gradle
index 8a026c587238..5b5625237cf3 100644
--- a/build/dependencies/setupBuildScriptsDeps.gradle
+++ b/build/dependencies/setupBuildScriptsDeps.gradle
@@ -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")
}
/**
diff --git a/build/gant.xml b/build/gant.xml
index e1e2e210a39b..1d7c76146e27 100644
--- a/build/gant.xml
+++ b/build/gant.xml
@@ -39,7 +39,6 @@
-
diff --git a/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy b/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy
index 2d971629a5aa..2331c06a89bc 100644
--- a/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy
+++ b/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy
@@ -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"])
diff --git a/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy b/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy
index 9d2c89fb24dd..b1476a06f39a 100644
--- a/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy
+++ b/build/groovy/org/jetbrains/intellij/build/IdeaCommunityProperties.groovy
@@ -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"]
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index 74f6e59fc8ea..bbb1cbb98088 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -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
}
diff --git a/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java b/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java
index ab9e210fbcb7..6815601f1964 100644
--- a/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java
+++ b/java/compiler/impl/src/com/intellij/build/AbstractViewManager.java
@@ -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);
diff --git a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java
index c4b4ae47b91d..76037cfb55ab 100644
--- a/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java
+++ b/java/compiler/impl/src/com/intellij/build/BuildTreeConsoleView.java
@@ -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()));
}
}
});
diff --git a/java/compiler/impl/src/com/intellij/build/ExecutionNode.java b/java/compiler/impl/src/com/intellij/build/ExecutionNode.java
index 09cb70d662c0..1bbaa137fee5 100644
--- a/java/compiler/impl/src/com/intellij/build/ExecutionNode.java
+++ b/java/compiler/impl/src/com/intellij/build/ExecutionNode.java
@@ -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 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;
}
diff --git a/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java b/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java
index 7390bd13e274..11c0119cf5ad 100644
--- a/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java
+++ b/java/compiler/impl/src/com/intellij/build/MultipleBuildsView.java
@@ -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;
diff --git a/java/compiler/impl/src/com/intellij/build/events/Failure.java b/java/compiler/impl/src/com/intellij/build/events/Failure.java
index 54d62d1a5eb0..93ed811db219 100644
--- a/java/compiler/impl/src/com/intellij/build/events/Failure.java
+++ b/java/compiler/impl/src/com/intellij/build/events/Failure.java
@@ -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;}
}
diff --git a/java/compiler/impl/src/com/intellij/build/events/NotificationData.java b/java/compiler/impl/src/com/intellij/build/events/NotificationData.java
deleted file mode 100644
index 2e1c3fe79805..000000000000
--- a/java/compiler/impl/src/com/intellij/build/events/NotificationData.java
+++ /dev/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();
-}
diff --git a/java/compiler/impl/src/com/intellij/build/events/impl/FailureImpl.java b/java/compiler/impl/src/com/intellij/build/events/impl/FailureImpl.java
index d7b3321aa9e9..6da9d065d189 100644
--- a/java/compiler/impl/src/com/intellij/build/events/impl/FailureImpl.java
+++ b/java/compiler/impl/src/com/intellij/build/events/impl/FailureImpl.java
@@ -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;
}
}
diff --git a/java/compiler/impl/src/com/intellij/build/events/impl/NotificationDataImpl.java b/java/compiler/impl/src/com/intellij/build/events/impl/NotificationDataImpl.java
deleted file mode 100644
index 736dbd5a74a5..000000000000
--- a/java/compiler/impl/src/com/intellij/build/events/impl/NotificationDataImpl.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java
index 86b6bd982fbc..69118990a54a 100644
--- a/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java
+++ b/java/compiler/impl/src/com/intellij/compiler/CompilerMessageImpl.java
@@ -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 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 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;
diff --git a/java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt b/java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt
index 14f7feab2f0c..c7e85cefed90 100644
--- a/java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt
+++ b/java/compiler/impl/src/com/intellij/compiler/ExternalCompilerConfigurationStorage.kt
@@ -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, ProjectModelElement {
var loadedState: Map? = null
private set
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java b/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java
index 66fc6e1cdefa..a387fa8fad80 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/MessagesContainer.java
@@ -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> 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)() -> {
+ 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 messages = myMessages.computeIfAbsent(msg.getCategory(), k -> new LinkedHashSet<>());
return messages.add(msg);
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java
index 770695874a49..29fefbdf4557 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java
@@ -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() {
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/ViewsGeneralSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/ViewsGeneralSettings.java
index d8d4c1c668f9..106bd9236ee9 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/ViewsGeneralSettings.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/ViewsGeneralSettings.java
@@ -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 {
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";
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ExistingLibraryEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ExistingLibraryEditor.java
index a45bcaedcdd3..50e6f64985fa 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ExistingLibraryEditor.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/ExistingLibraryEditor.java
@@ -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
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/BatchSuppressManager.java b/java/java-analysis-api/src/com/intellij/codeInspection/BatchSuppressManager.java
index 467b392b9dba..9dc592884eeb 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/BatchSuppressManager.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/BatchSuppressManager.java
@@ -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 getInspectionIdsSuppressedInAnnotation(@NotNull PsiModifierListOwner owner);
-
@Nullable
String getSuppressedInspectionIdsIn(@NotNull PsiElement element);
diff --git a/java/java-analysis-impl/java-analysis-impl.iml b/java/java-analysis-impl/java-analysis-impl.iml
index ebcda34a7da5..ac27777d1517 100644
--- a/java/java-analysis-impl/java-analysis-impl.iml
+++ b/java/java-analysis-impl/java-analysis-impl.iml
@@ -21,5 +21,6 @@
+
\ No newline at end of file
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
index f50a027907c0..39a9f68a26ac 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
@@ -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
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/ExpressionTypeMemoryState.java b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/ExpressionTypeMemoryState.java
index 5689b2153f02..562ea478b6e3 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/ExpressionTypeMemoryState.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/ExpressionTypeMemoryState.java
@@ -50,7 +50,7 @@ public class ExpressionTypeMemoryState extends DfaMemoryStateImpl {
return false;
}
};
- private final MultiMap myStates = MultiMap.create(EXPRESSION_HASHING_STRATEGY);
+ private final MultiMap 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
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java
index 49b003049f4a..0aa01f983a13 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java
@@ -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 getAllTypeCasts(PsiExpression forPlace) {
- assert forPlace.isValid();
- final int start = forPlace.getTextRange().getStartOffset();
- final Map 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 getControlFlowExpressionTypeConjuncts(@NotNull PsiExpression expr) {
- final Map 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 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 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 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 map) {
if (myResult == null) {
- myResult = MultiMap.create(ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY);
+ myResult = MultiMap.createSet(ExpressionTypeMemoryState.EXPRESSION_HASHING_STRATEGY);
myResult.putAllValues(map);
} else {
final Iterator iterator = myResult.keySet().iterator();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/BatchSuppressManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/BatchSuppressManagerImpl.java
index 5b6585fab2f8..b12a71f0abe3 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/BatchSuppressManagerImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/BatchSuppressManagerImpl.java
@@ -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 getInspectionIdsSuppressedInAnnotation(@NotNull final PsiModifierListOwner owner) {
- return JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation(owner);
- }
-
@Override
@Nullable
public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
index b27c4dfced35..3cf304bb107a 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/SuppressManagerImpl.java
@@ -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 getInspectionIdsSuppressedInAnnotation(@NotNull final PsiModifierListOwner owner) {
- return JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation(owner);
- }
-
@Override
@Nullable
public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/FieldAccessNotGuardedInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/FieldAccessNotGuardedInspection.java
index 3886bf9ae28e..248aac974dc9 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/FieldAccessNotGuardedInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/FieldAccessNotGuardedInspection.java
@@ -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;
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CommonDataflow.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CommonDataflow.java
index 297c1045f2c3..d5cb1051c809 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CommonDataflow.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CommonDataflow.java
@@ -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;
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
index 9c54f35c914b..b82857cd0a08 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
@@ -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 nestedClosures = dfaRunner.getNestedClosures();
- for (PsiElement closure : nestedClosures.keySet()) {
- List 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 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;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
index 13efd844170e..3d6bf0e6e61c 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
@@ -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 createInitialStates(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
+ private Collection 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 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 initialStates = createInitialStates(psiBlock, visitor);
+ Collection 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 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 initialStateAdjuster) {
@@ -243,6 +277,28 @@ public class DataFlowRunner {
}
}
+ public RunnerResult analyzeMethodRecursively(PsiElement block, StandardInstructionVisitor visitor) {
+ Collection 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 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 getNestedClosures() {
- return new MultiMap<>(myNestedClosures);
+ public void forNestedClosures(BiConsumer> consumer) {
+ // Copy to avoid concurrent modifications
+ MultiMap closures = new MultiMap<>(myNestedClosures);
+ for (PsiElement closure : closures.keySet()) {
+ List 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 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
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
index 2b0db143e9d8..f6c5098f6f07 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
@@ -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 vars = new HashSet<>(copy.getVariableStates().keySet());
+ Set 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 equivalentVariables(DfaVariableValue var) {
DfaVariableValue qualifier = var.getQualifier();
@@ -1206,9 +1221,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return state;
}
- @NotNull
- Map getVariableStates() {
- return myVariableStates;
+ void forVariableStates(BiConsumer 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;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
index d44424c06bad..a722dee05e7a 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
@@ -324,10 +324,8 @@ public class DfaUtil {
PsiExpression place = instruction.getPlace();
if (place != null) {
PlaceResult result = myResults.computeIfAbsent(place, __ -> new PlaceResult());
- final Map map = ((ValuableDataFlowRunner.MyDfaMemoryState)memState).getVariableStates();
- for (Map.Entry 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 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();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java
index 99ab239dccb3..abe573db90a2 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java
@@ -265,8 +265,7 @@ class StateMerger {
Map> ranges = new LinkedHashMap<>();
for (DfaMemoryStateImpl state : states) {
ProgressManager.checkCanceled();
- Map 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 getFacts(@NotNull DfaMemoryStateImpl state) {
- Set result = myFacts.get(state);
- if (result != null) {
- return result;
- }
-
- result = ContainerUtil.newLinkedHashSet();
+ return myFacts.computeIfAbsent(state, StateMerger::doGetFacts);
+ }
+
+ @NotNull
+ private static Set doGetFacts(DfaMemoryStateImpl state) {
+ Set result = ContainerUtil.newLinkedHashSet();
IdentityHashMap classInfo = new IdentityHashMap<>();
@@ -426,10 +425,7 @@ class StateMerger {
}
}
- Map states = state.getVariableStates();
- for (Map.Entry 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);
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java
index da71149fec59..52143b02e20c 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/TypeConstraint.java
@@ -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 leftTypes = new HashSet<>(this.myInstanceofValues);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaInstanceofValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaInstanceofValue.java
index 833f5037f265..66204892e0cf 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaInstanceofValue.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaInstanceofValue.java
@@ -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);
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java
index 730ca2067a21..f47aa2c2afb0 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java
@@ -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",
"" + name + "",
"" + StringUtil.unquoteString(value) + ""),
- createFix(name, value),
+ usedForWriting ? null : createFix(name, value),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
index 1cbd6aef81c5..91a77961c3c1 100644
--- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
+++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
@@ -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 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 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) {
diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractableExpressionPart.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractableExpressionPart.java
index e9e09e4600c1..4024972bfbd8 100644
--- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractableExpressionPart.java
+++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractableExpressionPart.java
@@ -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 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();
diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractedParameter.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractedParameter.java
index 4eb924cfde1a..b85bce090e52 100644
--- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractedParameter.java
+++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/ExtractedParameter.java
@@ -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 myFields;
private boolean myModified;
diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml
index 61fdeb0c48e1..c1689b990467 100644
--- a/java/java-impl/src/META-INF/JavaPlugin.xml
+++ b/java/java-impl/src/META-INF/JavaPlugin.xml
@@ -213,8 +213,8 @@
-
+
@@ -236,8 +236,8 @@
-
+
bold = LookupElementDecorator.withRenderer(item, new LookupElementRenderer>() {
@Override
public void renderElement(LookupElementDecorator 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;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateCastExpressionFromInstanceofAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateCastExpressionFromInstanceofAction.java
index 5441d24143c7..48652bb17d8f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateCastExpressionFromInstanceofAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateCastExpressionFromInstanceofAction.java
@@ -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());
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
index 0643e66efe0a..2bcd9bc6b007 100644
--- a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
@@ -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 conflicts = new MultiMap<>();
JavaSafeDeleteProcessor.collectMethodConflicts(conflicts, method, parameter);
+ final Collection 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 refsToInline = ReferencesSearch.search(parameter).findAll();
-
ApplicationManager.getApplication().runWriteAction(() -> {
try {
PsiExpression[] exprs = new PsiExpression[refsToInline.size()];
diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java
index 5ffd44d5d901..2d55c4d63817 100644
--- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java
+++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/BaseConvertToLocalQuickFix.java
@@ -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 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 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,
diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
index ce527ab84af5..d49df52c8512 100644
--- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
@@ -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;
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ShiftIndentInsideHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ShiftIndentInsideHelper.java
index 158e8b60cd2d..edda602d6259 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ShiftIndentInsideHelper.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ShiftIndentInsideHelper.java
@@ -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();
}
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/JavaPushDownDelegate.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/JavaPushDownDelegate.java
index 7f22ae6234bc..4df908f30b42 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/JavaPushDownDelegate.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/JavaPushDownDelegate.java
@@ -204,11 +204,14 @@ public class JavaPushDownDelegate extends PushDownDelegate 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;
diff --git a/java/java-psi-api/src/com/intellij/lang/jvm/JvmPackage.java b/java/java-psi-api/src/com/intellij/lang/jvm/JvmPackage.java
new file mode 100644
index 000000000000..94d856550a35
--- /dev/null
+++ b/java/java-psi-api/src/com/intellij/lang/jvm/JvmPackage.java
@@ -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();
+}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiPackage.java b/java/java-psi-api/src/com/intellij/psi/PsiPackage.java
index 76982b89fbe4..b445c524aaa3 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiPackage.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiPackage.java
@@ -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();
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java
index adacb5bbfe42..984e97ef132b 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java
@@ -29,6 +29,7 @@ public class PsiMethodUtil {
public static final Condition 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);
};
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java
index 55a74af8f004..6eb60aa328e2 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java
@@ -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 imp
}
}
+ @NotNull
+ @Override
+ public SearchScope getUseScope() {
+ return ProjectScope.getProjectScope(getProject());
+ }
+
@Override
public String toString() {
return "PsiJavaModule:" + getName();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java
index 2cb70cb14536..b354144d2c3d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleReference.java
@@ -66,7 +66,8 @@ public class PsiJavaModuleReference extends PsiReferenceBase.Poly modules = findModules(file, moduleName, incompleteCode);
+ boolean global = incompleteCode || refElement.getParent() instanceof PsiPackageAccessibilityStatement;
+ Collection 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 findModules(PsiFile file, String moduleName, boolean incompleteCode) {
+ private static Collection 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);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
index 8113cf28f45b..5d23a7da2d63 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java
@@ -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;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java
index 0eee9facbd53..a30005d54044 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java
@@ -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.*;
diff --git a/java/java-tests/testData/codeInsight/completion/normal/AssignmentPreciseTypeDfa.java b/java/java-tests/testData/codeInsight/completion/normal/AssignmentPreciseTypeDfa.java
new file mode 100644
index 000000000000..729fa4c6ac3d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/AssignmentPreciseTypeDfa.java
@@ -0,0 +1,7 @@
+class Foo {
+ void test(String s) {
+ Object x;
+ x = s;
+ System.out.println(x.subst);
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/AssignmentPreciseTypeDfa_after.java b/java/java-tests/testData/codeInsight/completion/normal/AssignmentPreciseTypeDfa_after.java
new file mode 100644
index 000000000000..45d7a408e5da
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/AssignmentPreciseTypeDfa_after.java
@@ -0,0 +1,7 @@
+class Foo {
+ void test(String s) {
+ Object x;
+ x = s;
+ System.out.println(((String) x).substring());
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/CastWhenMethodComesFromDfaSuperType.java b/java/java-tests/testData/codeInsight/completion/normal/CastWhenMethodComesFromDfaSuperType.java
new file mode 100644
index 000000000000..a91dd5c1cd7a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/CastWhenMethodComesFromDfaSuperType.java
@@ -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)
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normal/CastWhenMethodComesFromDfaSuperType_after.java b/java/java-tests/testData/codeInsight/completion/normal/CastWhenMethodComesFromDfaSuperType_after.java
new file mode 100644
index 000000000000..972621df4da8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/CastWhenMethodComesFromDfaSuperType_after.java
@@ -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())
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normal/DeclarationPreciseTypeDfa.java b/java/java-tests/testData/codeInsight/completion/normal/DeclarationPreciseTypeDfa.java
new file mode 100644
index 000000000000..d27bc3d84ba3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/DeclarationPreciseTypeDfa.java
@@ -0,0 +1,6 @@
+class Foo {
+ void test(String s) {
+ Object x = s;
+ System.out.println(x.subst);
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/DeclarationPreciseTypeDfa_after.java b/java/java-tests/testData/codeInsight/completion/normal/DeclarationPreciseTypeDfa_after.java
new file mode 100644
index 000000000000..941af7c18e1d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/DeclarationPreciseTypeDfa_after.java
@@ -0,0 +1,6 @@
+class Foo {
+ void test(String s) {
+ Object x = s;
+ System.out.println(((String) x).substring());
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/InstanceOfAssignmentDfa.java b/java/java-tests/testData/codeInsight/completion/normal/InstanceOfAssignmentDfa.java
new file mode 100644
index 000000000000..0770c40d72a9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/InstanceOfAssignmentDfa.java
@@ -0,0 +1,8 @@
+class Foo {
+ void test(Object obj) {
+ if(!(obj instanceof String)) {
+ obj = "foo";
+ }
+ obj.subst
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/InstanceOfAssignmentDfa_after.java b/java/java-tests/testData/codeInsight/completion/normal/InstanceOfAssignmentDfa_after.java
new file mode 100644
index 000000000000..d75378ee0e63
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/InstanceOfAssignmentDfa_after.java
@@ -0,0 +1,8 @@
+class Foo {
+ void test(Object obj) {
+ if(!(obj instanceof String)) {
+ obj = "foo";
+ }
+ ((String) obj).substring()
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/OptionalDfa.java b/java/java-tests/testData/codeInsight/completion/normal/OptionalDfa.java
new file mode 100644
index 000000000000..85ff2cb08ed5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/OptionalDfa.java
@@ -0,0 +1,8 @@
+import java.util.*;
+
+class Foo {
+ void test(Optional